TowardsDataScience-博客中文翻译-2020-三十八-
TowardsDataScience 博客中文翻译 2020(三十八)
第 145 天的#NLP365: NLP 论文摘要 SUPERT:迈向多文档摘要的无监督评估度量的新前沿

阅读和理解研究论文就像拼凑一个未解之谜。汉斯-彼得·高斯特在 Unsplash 上拍摄的照片。
内线艾 NLP365
NLP 论文摘要是我总结 NLP 研究论文要点的系列文章
项目#NLP365 (+1)是我在 2020 年每天记录我的 NLP 学习旅程的地方。在这里,你可以随意查看我在过去的 280 天里学到了什么。在这篇文章的最后,你可以找到以前按自然语言处理领域分类的论文摘要,你也可以订阅# NLP 365 @http://eepurl.com/gW7bBP😃
今天的 NLP 论文是 SUPERT:迈向多文档摘要的无监督评估度量的新前沿 。以下是研究论文的要点。
目标和贡献
提出了 SUPERT,一种通过测量摘要和伪引用摘要之间的语义相似性来评估多文档摘要的无监督评估度量。伪引用摘要是通过使用上下文嵌入和软标记对齐从源文档中选择显著句子来生成的。SUPERT 能够实现与人类评估 18–39%的更好的相关性。我们使用 SUPERT 和一个强化学习摘要器,与 SOTA 无监督摘要器相比,它产生了很好的性能。这展示了 SUPERT 的有效性,也意味着我们可以从无限数量的文档中创建许多参考摘要,以增加数据集的大小。
数据集和评估指标
我们使用了两个多文档汇总数据集:TAC'08 和 TAC'09。两个 TAC 数据集包含大约 45+个主题,每个主题有 10 篇新闻文章、4 个参考摘要和 55+个机器生成的摘要。我们的评估标准是三个不同的相关系数:皮尔森的,斯皮尔曼的和肯德尔的。
模型比较
- TFIDF
- JS 发散。测量源和摘要中单词分布之间的 JS 差异
- 死神
- 余弦-埃尔莫。语境化词语嵌入
- 波姆 19
- ROUGE-1 和 ROUGE-2 以及 MoverScore 。性能测量上限
使用伪引用和 bERT (SUPERT)的汇总评估
SUPERT 测量多文档摘要的相关性,它测量来自源文档的摘要中包含多少重要信息。我们用两个步骤来衡量相关性:
- 从源文档中找出突出的句子
- 测量伪引用(步骤 1)和生成的摘要之间的语义重叠

SUPERT 的工作流程[1]
下面的结果表展示了所有基准方法在显著低于性能上限时的表现。令人惊讶的是,基于嵌入的方法比基于词典的方法表现更差。这告诉我们,现有的单文档评估度量在评估多文档摘要时是无效的。

不同评估指标和人员评级之间的汇总级相关性[1]
用情境化嵌入度量相似性
我们通过探索不同的文本编码器,如 BERT、ROBERTa、ALBERT 和 s BERT,扩展了余弦 ELMo。结果显示如下。如图所示,SBERT 作为具有余弦相似性的文本编码器产生了最高相关性的生成摘要。然而,与基于词典的方法相比,这仍然表现不佳。我们探索的另一个扩展是使用单词移动距离(WMDs)来度量两个文档之间的语义相似性,而不是使用余弦相似性。先前的工作已经证明 WMDs 产生了更强的性能,并且我们下面的结果支持了带 SBERT 的 as WMD(M _ SBERT)明显优于它的余弦相似性对应物和所有基于词典的方法。这让我们想到了计算文档间语义相似度的终极方法,那就是使用 SBERT 和 WMD。

上下文嵌入度量的性能[1]
构建伪引用
前面表格中的结果显示了无监督评估和基于参考的评估之间的巨大性能差异。这表明我们仍然需要参考文献摘要,因此我们探索了建立伪参考文献的不同方法。
首先,我们探索了两种建立基线结果的简单策略:选择 N 个随机句子或前 N 个句子。结果显示如下。结果显示了随机选择的句子的较差性能,我们应该选择前 10-15 个句子作为伪引用,因为它优于基于词汇的方法和我们的 M_SBERT 方法。这也说明了新闻文章中的立场偏差。

通过随机选择句子建立伪引用[1]
其次,我们探索了两种基于图的方法来构建伪引用:位置不可知图和位置感知图。对于位置不可知的图,我们使用 SBERT (SLR)扩展了 LexRank 来度量余弦相似性。我们还探索了相似传播聚类算法,该算法对句子进行聚类,并选择每个聚类的中心来建立伪引用。这种聚类算法不需要我们预设聚类数。对于单反和 SC,我们有两种变体:个体图和全局图。个体图为每个源文档构建一个图,并选择前 K 个句子。全局图使用来自同一主题的所有源文档的所有句子构建一个图,并选择前 M 个句子。
对于位置感知图,我们使用 SBERT (SPS)扩展了 PacSum 来度量句子相似性,并且类似地,考虑了个体和全局图版本。PacSum 选择语义中心的句子,这意味着它与后面的句子具有高*均相似度,而与前面的句子具有低*均相似度。此外,我们还提出了 Top + Clique (TC ),它选择前 N 个句子和语义中心句来构建伪引用。TC 是这样工作的:
- 将每个文档中的前 N 个句子标记为显著
- 构建一个连接高度相似的非前 N 名句子的图表
- 从图中识别集团,并从每个集团中选择语义中心句作为潜在的显著句
- 对于每个潜在的显著句子,将其与前 N 个句子进行比较,如果它与前 N 个句子不高度相似,则将其标记为显著
下表展示了位置不可知图和位置感知图的结果。所有方法(除了 SC_G)都优于上表 1 中的基准模型。我们的位置不可知图表现不如位置感知图。此外,我们的位置感知图表现不如表 3 中选择前 N 个句子的简单句子提取方法。这向我们表明,新闻中的位置偏向是非常强烈的,它仍然是选择正面信息的最有效的方法。

使用位置不可知和位置感知构建伪引用[1]
引导强化学习
我们使用我们的新的无监督评估度量来指导基于 RL 的多文档摘要器神经时间差异(NTD)的训练。我们考虑了三个无监督的奖励函数:JS,REAPER 和 SUPERT (SP)。SUPERT 从每个源文档中选择前 10-15 个句子作为伪引用,并使用 SBERT 来测量摘要和伪引用之间的语义相似性。结果如下所示,使用 SUPERT 的 NTD 产生了最强的结果。

NTD 2008 年和 2009 年 TAC 的 ROUGE 结果[1]
来源:
[1]高,杨,赵,魏和埃格,s,2020 .SUPERT:迈向多文档摘要的无监督评估度量的新前沿。arXiv 预印本 arXiv:2005.03724 。
原载于 2020 年 5 月 24 日 https://ryanong.co.uk。
特征提取/基于特征的情感分析
- https://towards data science . com/day-102-of-NLP 365-NLP-papers-summary-implicit-and-explicit-aspect-extraction-in-financial-BDF 00 a 66 db 41
- https://towards data science . com/day-103-NLP-research-papers-utilizing-Bert-for-aspect-based-sense-analysis-via-construction-38ab 3e 1630 a3
- https://towards data science . com/day-104-of-NLP 365-NLP-papers-summary-senthious-targeted-aspect-based-sensitive-analysis-f 24 a2 EC 1 ca 32
- https://towards data science . com/day-105-of-NLP 365-NLP-papers-summary-aspect-level-sensation-class ification-with-3a 3539 be 6 AE 8
- https://towards data science . com/day-106-of-NLP 365-NLP-papers-summary-an-unsupervised-neural-attention-model-for-aspect-b 874d 007 b 6d 0
- https://towardsdatascience . com/day-110-of-NLP 365-NLP-papers-summary-double-embedding-and-CNN-based-sequence-labeling-for-b8a 958 F3 bddd
- https://towards data science . com/day-112-of-NLP 365-NLP-papers-summary-a-challenge-dataset-and-effective-models-for-aspect-based-35b 7 a5 e 245 b5
- https://towards data science . com/day-123-of-NLP 365-NLP-papers-summary-context-aware-embedding-for-targeted-aspect-based-be9f 998d 1131
总结
- https://towards data science . com/day-107-of-NLP 365-NLP-papers-summary-make-lead-bias-in-your-favor-a-simple-effective-4c 52 B1 a 569 b 8
- https://towards data science . com/day-109-of-NLP 365-NLP-papers-summary-studing-summary-evaluation-metrics-in-the-619 F5 acb1 b 27
- https://towards data science . com/day-113-of-NLP 365-NLP-papers-summary-on-extractive-and-abstract-neural-document-87168 b 7 e 90 BC
- https://towards data science . com/day-116-of-NLP 365-NLP-papers-summary-data-driven-summary-of-scientific-articles-3 FBA 016 c 733 b
- https://towards data science . com/day-117-of-NLP 365-NLP-papers-summary-abstract-text-summary-a-low-resource-challenge-61a E6 CDF 32 f
- https://towards data science . com/day-118-of-NLP 365-NLP-papers-summary-extractive-summary-of-long-documents-by-combining-AEA 118 a5 eb3f
- https://towards data science . com/day-120-of-NLP 365-NLP-papers-summary-a-simple-theory-model-of-importance-for-summary-843 ddbcb 9b
- https://towards data science . com/day-121-of-NLP 365-NLP-papers-summary-concept-pointer-network-for-abstract-summary-cd55e 577 F6 de
- https://towards data science . com/day-124-NLP-papers-summary-tldr-extreme-summary-of-scientific-documents-106 CD 915 F9 a 3
- https://towards data science . com/day-143-of-NLP 365-NLP-papers-summary-unsupervised-pseudo-labeling-for-extract-summary-3b 94920 e04c 6
- https://towards data science . com/day-144-of-NLP 365-NLP-papers-summary-attend-to-medical-ontology-content-selection-for-ff 7 cded 5d 95 b
其他人
- https://towards data science . com/day-108-of-NLP 365-NLP-papers-summary-simple-Bert-models-for-relation-extraction-and-semantic-98f 7698184 D7
- https://towards data science . com/day-111-of-NLP 365-NLP-papers-summary-the-risk-of-race-of-bias-in-hate-speech-detection-BFF 7 F5 f 20 ce 5
- https://towards data science . com/day-115-of-NLP 365-NLP-papers-summary-scibert-a-pre trained-language-model-for-scientific-text-185785598 e33
- https://towards data science . com/day-119-NLP-papers-summary-an-argument-annoted-corpus-of-scientific-publications-d 7 b 9 e 2e ea 1097
- https://towards data science . com/day-122-of-NLP 365-NLP-papers-summary-applying-Bert-to-document-retrieval-with-birch-766 EAC 17 ab
- https://towards data science . com/day-125-of-NLP 365-NLP-papers-summary-a2n-attending-to-neighbors-for-knowledge-graph-inference-87305 C3 aebe 2
- https://towards data science . com/day-126-of-NLP 365-NLP-papers-summary-neural-news-recommendation-with-topic-aware-news-4eb 9604330 bb
- https://towards data science . com/day-140-of-NLP 365-NLP-papers-summary-multimodal-machine-learning-for-automated-ICD-coding-b32e 02997 ea 2
- https://towards data science . com/day-141-of-NLP 365-NLP-papers-summary-text attack-a-framework-for-adversarial-attack-in-aac2a 282d 72 c
- https://towards data science . com/day-142-of-NLP 365-NLP-papers-summary-measuring-emotions-in-the-the-新冠肺炎-现实世界-忧虑-d565098a0937
#NLP365 的第 146 天:NLP 论文摘要——探索小说章节摘要的内容选择

阅读和理解研究论文就像拼凑一个未解之谜。汉斯-彼得·高斯特在 Unsplash 上拍摄的照片。
内线艾 NLP365
NLP 论文摘要是我总结 NLP 研究论文要点的系列文章
项目#NLP365 (+1)是我在 2020 年每天记录我的 NLP 学习旅程的地方。在这里,你可以随意查看我在过去的 280 天里学到了什么。在这篇文章的最后,你可以找到以前按自然语言处理领域分类的论文摘要,你也可以订阅# NLP 365 @http://eepurl.com/gW7bBP😃
今天的 NLP 论文是 探讨小说章节 摘要中的内容选择。以下是研究论文的要点。
目标和贡献
提出了一个新的总结任务,从在线学习指南中总结小说章节。由于源文件的长度和更高层次的转述,这比新闻摘要更具挑战性。本文的贡献如下:
- 提出了一个新的概括小说章节的概括任务
- 提出了一种新的度量标准,用于将参考摘要中的句子与章节中的句子对齐,以创建高质量的“基础事实”摘要来训练我们的摘要模型。通过 ROUGE 分数和金字塔分析,这已被证明比以前的方法有所改进
资料组
我们从五个不同的学习指南中收集章节/摘要对:
- 巴伦书笔记(BB)
- 书狼
- 克利夫斯 Notes(中国)
- 坡度保护器(GS)
- 小说指南(NG)
我们进行了两轮过滤来处理数据。首先,我们删除任何超过 700 个句子的参考文本,因为它们太大了。其次,我们删除过于冗长的摘要(压缩比小于 2)。我们的最终章节/摘要对总数是 8088 (6288 / 938 / 862)。培训数据统计如下所示。章节正文*均比新闻文章长 7 倍,章节摘要比新闻摘要长 8 倍。此外,对于小说,摘要和章节之间的*均单词重叠率为 33.7%,而对于 CNN/DailyMail news,则为 68.7%,显示了章节摘要中的高水*转述。下面的示例参考摘要中显示了这种大量的解释。

数据集的描述性统计[1]

摘要示例[1]
对齐实验
相似性度量

参考摘要 vs R-L 贪婪稳定的例子[1]

ROUGE-L 和众包 F1 的内容得分重叠[1]
由于基本事实摘要是抽象的,我们需要创建黄金提取摘要来训练我们的提取摘要模型。这就需要我们把章节和摘要中的句子对齐。为了对齐句子,我们首先需要一个度量来测量相似性。先前的工作大量使用 ROUGE 分数作为相似性度量。然而,胭脂分数分配相等的权重给每个字,然而,我们相信我们应该分配较高的权重给重要的字。为了结合这一点,我们使用*滑的逆频率加权方案,并将其应用于取 ROUGE-1、2 和 L 的*均值,以生成提取(R-wtd)。我们将这种 R-wtd 方法与其他相似性度量进行了比较,如 ROUGE-1、ROUGE-L、BERT 以及未加权和加权的 ROUGE + METEOR (RM)。我们使用 ROUGE-L F1 评分对这些相似性度量进行了自动评估和人工评估。需要人工评估来对照对齐的句子评估每个参考摘要。结果如下所示,R-wtd 在相似性指标中得分最高。
对齐方法
一旦我们建立了我们的相似性度量,我们现在探索不同的比对方法,以最终生成我们的黄金提取摘要。以前的工作中有两种主要方法:
- 汇总级对齐。选择最佳句子,与摘要进行比较
- 句子级对齐。选择最佳句子,与摘要中的每个句子进行比较
对于摘要级对齐,我们有两种变体:选择句子直到字数限制(WL)和选择句子直到胭脂分数不再增加(WS 摘要)。对于句子级对齐,我们有两种变体:Gale-Shapley 稳定匹配算法和 greedy 算法。结果如下所示,表明句子级稳定算法的性能明显优于其他对齐方法。

对验证集的人工评估[1]
实验和结果
为了评估,我们有三个提取模型:
- 分级 CNN-LSTM (CB)
- Seq2seq 注意(K)
- RNN(北)
由于我们的数据分析表明,摘要句通常选自不同的章节,因此我们实验了在单词和成分级别应用的对齐方法。我们的评估指标是 ROUGE-1、2、L 和 METEOR。每章有 2-5 个参考摘要,我们根据所有参考摘要评估我们生成的摘要。
结果

胭脂和流星的分数[1]
上述结果比较了三种不同提取模型的性能以及使用不同对齐方法的性能差异。我们可以看到,我们提出的比对方法在所有三个提取模型中都优于基线方法。使用我们的提取靶标,所有三个模型似乎表现相似,表明选择合适的方法产生提取靶标的重要性。鉴于 ROUGE 的不可靠性,我们进行了人工评估,并在我们的最佳性能模型(CB)上计算了每个比对方法的金字塔分数。人群工作者被要求识别哪个生成的概要最好地传达了采样的参考概要内容。结果显示如下。

金字塔评价[1]
结论和未来工作
我们已经表明,具有 R-wtd 相似性度量的句子级稳定匹配对齐方法比先前计算 gold 提取摘要的方法执行得更好。然而,在自动和人工评估中,关于提取在句子还是成分级别更好似乎存在矛盾。我们推测,这可能是因为我们在对提取成分的概要进行评分时没有包括额外的上下文,因此不相关的上下文不会违背系统,而在人类评估中,我们包括句子上下文,因此在生成的概要中包括较少的成分。
在未来的工作中,我们计划研究如何在不包含不相关上下文的情况下,将成分组合成流畅的句子。我们也想探索抽象概括,检查语言模型在我们的领域是否有效。这可能具有挑战性,因为语言模型通常有 512 个标记的限制。截断我们的文档可能会损害我们的新章节摘要模型的性能。
来源:
[1]f .拉德哈克,b .李,y .奥奈赞和 k .麦克欧文,2020 年。探索小说章节摘要的内容选择。arXiv 预印本 arXiv:2005.01840 。
特征提取/基于特征的情感分析
- https://towards data science . com/day-102-of-NLP 365-NLP-papers-summary-implicit-and-explicit-aspect-extraction-in-financial-BDF 00 a 66 db 41
- https://towards data science . com/day-103-NLP-research-papers-utilizing-Bert-for-aspect-based-sense-analysis-via-construction-38ab 3e 1630 a3
- https://towards data science . com/day-104-of-NLP 365-NLP-papers-summary-senthious-targeted-aspect-based-sensitive-analysis-f 24 a2 EC 1 ca 32
- https://towards data science . com/day-105-of-NLP 365-NLP-papers-summary-aspect-level-sensation-class ification-with-3a 3539 be 6 AE 8
- https://towards data science . com/day-106-of-NLP 365-NLP-papers-summary-an-unsupervised-neural-attention-model-for-aspect-b 874d 007 b 6d 0
- https://towardsdatascience . com/day-110-of-NLP 365-NLP-papers-summary-double-embedding-and-CNN-based-sequence-labeling-for-b8a 958 F3 bddd
- https://towards data science . com/day-112-of-NLP 365-NLP-papers-summary-a-challenge-dataset-and-effective-models-for-aspect-based-35b 7 a5 e 245 b5
- https://towards data science . com/day-123-of-NLP 365-NLP-papers-summary-context-aware-embedding-for-targeted-aspect-based-be9f 998d 1131
总结
- https://towards data science . com/day-107-of-NLP 365-NLP-papers-summary-make-lead-bias-in-your-favor-a-simple-effective-4c 52 B1 a 569 b 8
- https://towards data science . com/day-109-of-NLP 365-NLP-papers-summary-studing-summary-evaluation-metrics-in-the-619 F5 acb1 b 27
- https://towards data science . com/day-113-of-NLP 365-NLP-papers-summary-on-extractive-and-abstract-neural-document-87168 b 7 e 90 BC
- https://towards data science . com/day-116-of-NLP 365-NLP-papers-summary-data-driven-summary-of-scientific-articles-3 FBA 016 c 733 b
- https://towards data science . com/day-117-of-NLP 365-NLP-papers-summary-abstract-text-summary-a-low-resource-challenge-61 AE 6 CDF 32 f
- https://towards data science . com/day-118-of-NLP 365-NLP-papers-summary-extractive-summary-of-long-documents-by-combining-AEA 118 a5 eb3f
- https://towards data science . com/day-120-of-NLP 365-NLP-papers-summary-a-simple-theory-model-of-importance-for-summary-843 ddbcb 9b
- https://towards data science . com/day-121-of-NLP 365-NLP-papers-summary-concept-pointer-network-for-abstract-summary-cd55e 577 F6 de
- https://towards data science . com/day-124-NLP-papers-summary-tldr-extreme-summary-of-scientific-documents-106 CD 915 F9 a 3
- https://towards data science . com/day-143-of-NLP 365-NLP-papers-summary-unsupervised-pseudo-labeling-for-extract-summary-3b 94920 e04c 6
- https://towards data science . com/day-144-of-NLP 365-NLP-papers-summary-attend-to-medical-ontology-content-selection-for-ff 7 cded 5d 95 b
- https://towards data science . com/day-145-of-NLP 365-NLP-papers-summary-supert-forward-new-frontiers-in-unsupervised-evaluation-188295 f82ce 5
其他人
- https://towards data science . com/day-108-of-NLP 365-NLP-papers-summary-simple-Bert-models-for-relation-extraction-and-semantic-98f 7698184 D7
- https://towards data science . com/day-111-of-NLP 365-NLP-papers-summary-the-risk-of-race-of-bias-in-hate-speech-detection-BFF 7 F5 f 20 ce 5
- https://towards data science . com/day-115-of-NLP 365-NLP-papers-summary-scibert-a-pre trained-language-model-for-scientific-text-185785598 e33
- https://towards data science . com/day-119-NLP-papers-summary-an-argument-annoted-corpus-of-scientific-publications-d 7 b 9 e 2e ea 1097
- https://towards data science . com/day-122-of-NLP 365-NLP-papers-summary-applying-Bert-to-document-retrieval-with-birch-766 EAC 17 ab
- https://towards data science . com/day-125-of-NLP 365-NLP-papers-summary-a2n-attending-to-neighbors-for-knowledge-graph-inference-87305 C3 aebe 2
- https://towards data science . com/day-126-of-NLP 365-NLP-papers-summary-neural-news-recommendation-with-topic-aware-news-4eb 9604330 bb
- https://towards data science . com/day-140-of-NLP 365-NLP-papers-summary-multimodal-machine-learning-for-automated-ICD-coding-b32e 02997 ea 2
- https://towards data science . com/day-141-of-NLP 365-NLP-papers-summary-text attack-a-framework-for-adversarial-attack-in-aac2a 282d 72 c
- https://towards data science . com/day-142-of-NLP 365-NLP-papers-summary-measuring-emotions-in-the-the-新冠肺炎-现实世界-忧虑-d565098a0937
#NLP365 的第 147 天:NLP 论文摘要——一石二鸟:从结构化和非结构化数据生成文本的简单统一模型

阅读和理解研究论文就像拼凑一个未解之谜。汉斯-彼得·高斯特在 Unsplash 上拍摄的照片。
内线艾 NLP365
NLP 论文摘要是我总结 NLP 研究论文要点的系列文章
项目#NLP365 (+1)是我在 2020 年每天记录我的 NLP 学习旅程的地方。在这里,你可以随意查看我在过去的 290 天里学到了什么。在这篇文章的最后,你可以找到以前按自然语言处理领域分类的论文摘要,你也可以订阅# NLP 365 @http://eepurl.com/gW7bBP😃
今天的 NLP 论文是 一石二鸟:一个简单、统一的模型,用于从结构化和非结构化数据生成文本 。以下是研究论文的要点。
目标和贡献
展示了一个简单的基于双向注意力的 seq2seq 模型,该模型具有通过指数移动*均(EMA)训练的复制机制,可以在表格到文本生成和神经问题生成(NQG)中实现 SOTA 结果。我们表明,适当微调的简单模型也可以实现 SOTA 结果,而不是不断增加神经网络的复杂性,这鼓励我们在引入复杂模型之前彻底探索简单模型。
什么是表格到文本的生成任务?
目标是生成表的描述。具体来说,在本文中,我们探索了基于维基百科信息框生成传记,如下所示。

信息框的例子[1]
什么是神经问题生成(NQG)任务?
目标是从源文档中生成正确的有意义的问题,并且目标答案在其中。在本文中,我们使用了如下所示的小队数据集。

来自班数据集的样本[1]
具有注意和复制机制的双向 Seq2Seq
模型架构有 3 个主要组件:
- 编码器。编码器是一个 biLSTM,它将单词嵌入和附加的特定于任务的特性结合在一起。对于表到文本的生成,额外的特性是字段名和位置信息。对于 NQG,额外的特征是单个比特,指示该单词是否属于目标答案。
- 基于注意力的解码器。我们的解码器使用标准的注意机制和复制机制
- 指数移动*均线。这是模型性能的关键驱动因素。EMA 也称为时间*均。这里,我们有两组参数:a)训练参数和 b)评估参数,它是通过采用训练参数的指数加权移动*均来计算的,由衰减率控制。

整体架构[1]
实验和结果
我们使用 WIKIBIO 数据集进行表格到文本的生成,使用 SQUAD 数据集进行 NQG。WIKIBIO 数据集拥有超过 720,000 篇维基百科文章,并使用每篇文章的第一句话作为 infobox 的基本事实描述。SQUAD 数据集拥有 536 篇维基百科文章和超过 100,000 对问答。对于评估指标,我们使用 BLEU-4、METEOR、ROUGE-4 和 ROUGE-L。
结果
表格到文本生成和 NQG 的结果如下表所示。总的来说,我们的模型(没有 EMA)在所有指标上的表现都与之前的工作有竞争力。通过额外的 EMA 技术,我们的模型能够在除了 BLEU-4 以外的所有指标中实现 SOTA 结果,在 BLEU-4 中,我们的模型仍然具有竞争力。这着重强调了一个事实,即复杂的架构并不总是最好的方法,我们应该在探索更复杂的模型之前投入更多的时间来探索和改进基本模型,以获得更好的结果。

NQG [1]的测试集结果

表格到文本生成的测试集结果[1]
结论和未来工作
潜在的未来工作将是调查 EMA 技术在变压器模型上的使用,以及进行类似的研究,以检查在其他 NLP 任务中对复杂架构的需求。
来源:
[1]:沙希迪,h .,李,m .和林,j .,2019。一石二鸟:从结构化和非结构化数据生成文本的简单统一模型。 arXiv 预印本 arXiv:1909.10158 。
原载于 2020 年 5 月 26 日 https://ryanong.co.uk**的 。
特征提取/基于特征的情感分析
- https://towards data science . com/day-102-of-NLP 365-NLP-papers-summary-implicit-and-explicit-aspect-extraction-in-financial-BDF 00 a 66 db 41
- https://towards data science . com/day-103-NLP-research-papers-utilizing-Bert-for-aspect-based-sense-analysis-via-construction-38ab 3e 1630 a3
- https://towards data science . com/day-104-of-NLP 365-NLP-papers-summary-senthious-targeted-aspect-based-sensitive-analysis-f 24 a2 EC 1 ca 32
- https://towards data science . com/day-105-of-NLP 365-NLP-papers-summary-aspect-level-sensation-class ification-with-3a 3539 be 6 AE 8
- https://towards data science . com/day-106-of-NLP 365-NLP-papers-summary-an-unsupervised-neural-attention-model-for-aspect-b 874d 007 b 6d 0
- https://towardsdatascience . com/day-110-of-NLP 365-NLP-papers-summary-double-embedding-and-CNN-based-sequence-labeling-for-b8a 958 F3 bddd
- https://towards data science . com/day-112-of-NLP 365-NLP-papers-summary-a-challenge-dataset-and-effective-models-for-aspect-based-35b 7 a5 e 245 b5
- https://towards data science . com/day-123-of-NLP 365-NLP-papers-summary-context-aware-embedding-for-targeted-aspect-based-be9f 998d 1131
总结
- https://towards data science . com/day-107-of-NLP 365-NLP-papers-summary-make-lead-bias-in-your-favor-a-simple-effective-4c 52 B1 a 569 b 8
- https://towards data science . com/day-109-of-NLP 365-NLP-papers-summary-studing-summary-evaluation-metrics-in-the-619 F5 acb1 b 27
- https://towards data science . com/day-113-of-NLP 365-NLP-papers-summary-on-extractive-and-abstract-neural-document-87168 b 7 e 90 BC
- https://towards data science . com/day-116-of-NLP 365-NLP-papers-summary-data-driven-summary-of-scientific-articles-3 FBA 016 c 733 b
- https://towards data science . com/day-117-of-NLP 365-NLP-papers-summary-abstract-text-summary-a-low-resource-challenge-61 AE 6 CDF 32 f
- https://towards data science . com/day-118-of-NLP 365-NLP-papers-summary-extractive-summary-of-long-documents-by-combining-AEA 118 a5 eb3f
- https://towards data science . com/day-120-of-NLP 365-NLP-papers-summary-a-simple-theory-model-of-importance-for-summary-843 ddbcb 9b
- https://towards data science . com/day-121-of-NLP 365-NLP-papers-summary-concept-pointer-network-for-abstract-summary-cd55e 577 F6 de
- https://towards data science . com/day-124-NLP-papers-summary-tldr-extreme-summary-of-scientific-documents-106 CD 915 F9 a 3
- https://towards data science . com/day-143-of-NLP 365-NLP-papers-summary-unsupervised-pseudo-labeling-for-extract-summary-3b 94920 e04c 6
- https://towards data science . com/day-144-of-NLP 365-NLP-papers-summary-attend-to-medical-ontology-content-selection-for-ff 7 cded 5d 95 b
- https://towards data science . com/day-145-of-NLP 365-NLP-papers-summary-supert-forward-new-frontiers-in-unsupervised-evaluation-188295 f82ce 5
- https://towards data science . com/day-146-of-NLP 365-NLP-papers-summary-exploring-content-selection-in-summary-of-novel-a 13 fa 1 f 6111 b
其他人
- https://towards data science . com/day-108-of-NLP 365-NLP-papers-summary-simple-Bert-models-for-relation-extraction-and-semantic-98f 7698184 D7
- https://towards data science . com/day-111-of-NLP 365-NLP-papers-summary-the-risk-of-race-of-bias-in-hate-speech-detection-BFF 7 F5 f 20 ce 5
- https://towards data science . com/day-115-of-NLP 365-NLP-papers-summary-scibert-a-pre trained-language-model-for-scientific-text-185785598 e33
- https://towards data science . com/day-119-NLP-papers-summary-an-argument-annoted-corpus-of-scientific-publications-d 7 b 9 e 2e ea 1097
- https://towards data science . com/day-122-of-NLP 365-NLP-papers-summary-applying-Bert-to-document-retrieval-with-birch-766 EAC 17 ab
- https://towards data science . com/day-125-of-NLP 365-NLP-papers-summary-a2n-attending-to-neighbors-for-knowledge-graph-inference-87305 C3 aebe 2
- https://towards data science . com/day-126-of-NLP 365-NLP-papers-summary-neural-news-recommendation-with-topic-aware-news-4eb 9604330 bb
- https://towards data science . com/day-140-of-NLP 365-NLP-papers-summary-multimodal-machine-learning-for-automated-ICD-coding-b32e 02997 ea 2
- https://towards data science . com/day-141-of-NLP 365-NLP-papers-summary-text attack-a-framework-for-adversarial-attack-in-aac2a 282d 72 c
- https://towards data science . com/day-142-of-NLP 365-NLP-papers-summary-measuring-emotions-in-the-the-新冠肺炎-现实世界-忧虑-d565098a0937
第 148 天:NLP 论文摘要—一种基于转换器的源代码摘要方法

阅读和理解研究论文就像拼凑一个未解之谜。汉斯-彼得·高斯特在号航天飞机上拍摄的照片。
内线 AI NLP365
自然语言处理论文摘要是一个系列,在这里我总结了自然语言处理研究论文的要点
项目#NLP365 (+1)是我记录 2020 年每一天 NLP 学习历程的地方。请随意在此查看我在过去 300 天所学的内容。在本文的最后,您可以找到以前的论文摘要(按 NLP 领域分组,您可以订阅# NLP 365 @http://eepurl.com/gW7bBP😃
今天的 NLP 论文是 一种基于转换器的源代码摘要方法 。以下是该研究论文的主要收获。
目标和贡献
利用一个简单的基于变压器的模型与相对位置表示和复制注意机制,以生成源代码总结的 SOTA 结果。我们发现源代码标记位置的绝对编码阻碍了总结的性能,而相对编码显著提高了性能。
什么是源代码摘要?
目标是对源代码进行编码,并生成描述程序功能的可读摘要。
数据集
我们有两个评估数据集:来自 GitHub 的 Java 和 Python 数据集,如下所示。我们的评估指标为 BLEU、METEOR 和 ROUGE-L。

描述性数据集统计[1]
方法学
我们提出的模型是普通的变压器。我们将代码和概要编码为嵌入序列。普通的 Transformer 在编码器和解码器中堆叠了多头注意力和线性变换层。我们还在 Transformer 中包含了复制注意事项,以使模型能够从源代码中复制稀有令牌。
位置表示
在这里,我们探索了源代码标记顺序上的绝对位置编码和 Transformer 中的成对关系编码。绝对位置编码旨在捕获源标记的顺序信息,然而,我们发现顺序信息实际上对学习源代码表示没有帮助,并且会导致错误的总结。我们发现,正是令牌之间的相互作用影响了源代码的含义,这也是我们探索成对关系编码的原因。为了捕获输入令牌之间的这种成对关系,我们为每个令牌捕获两个位置 I 和 j 的相对位置表示。
结果
如下所示,我们的完整模型优于所有基线模型。事实上,在没有 CamelCase 和 snake_case 代码标记处理的数据集上训练的基本模型,在 ROUGE-L 度量上优于所有基线模型。我们的基线模型没有包含复制注意机制,我们表明复制注意机制确实提高了我们完整模型的性能。

BLEU、METEOR 和 ROUGE-L 的总体结果-我们的方法与基线方法的比较[1]
消融研究
位置表示的影响
下面的表 3 展示了对源和目标执行绝对位置编码的性能。它展示了当包含绝对位置编码时性能的下降。表 4 展示了学习源代码标记之间成对关系的好处。我们尝试了不同的裁剪距离,以及是否应该包含双向信息。不同裁剪距离的性能与我们完整模型的性能非常相似,包含方向信息的模型优于不包含方向信息的模型。

消融研究-变压器的相对位置表示[1]
不同的模型大小和层数
我们下面的结果表明,更深的模型(更多层)比更宽的模型(每层更多神经元)表现更好。我们怀疑更深的模型在源代码总结中更有益,因为它更多地依赖语义信息而不是句法信息。

消融研究 Java 数据集基础模型的隐藏大小和层数[1]
定性分析
我们下面的定性例子展示了复制注意力机制使模型能够用更合适的关键词生成更短的摘要。我们观察到,当我们使用相对位置表示时,源代码中的频繁标记具有较高的复制概率。

Java 与 Python 数据集的定性示例[1]
结论和今后的工作
未来的一项潜在工作是将代码结构合并到 Transformer 中,并将其应用到其他代码序列生成任务中,例如为源代码更改生成提交消息。
来源:
[1] Ahmad,W.U .,Chakraborty,s .,Ray,b .和 Chang,K.W .,2020 年。一种基于转换器的源代码摘要方法。arXiv 预印本 arXiv:2005.00653 。
最新论文
特征提取/基于特征的情感分析
- https://towardsdatascience . com/day-110-of-NLP 365-NLP-papers-summary-double-embedding-and-CNN-based-sequence-labeling-for-b8a 958 F3 bddd
- https://towards data science . com/day-112-of-NLP 365-NLP-papers-summary-a-challenge-dataset-and-effective-models-for-aspect-based-35b 7 a5 e 245 b5
- https://towards data science . com/day-123-of-NLP 365-NLP-papers-summary-context-aware-embedding-for-targeted-aspect-based-be9f 998d 1131
总结
- https://towards data science . com/day-144-of-NLP 365-NLP-papers-summary-attend-to-medical-ontology-content-selection-for-ff 7 cded 5d 95 b
- https://towards data science . com/day-145-of-NLP 365-NLP-papers-summary-supert-forward-new-frontiers-in-unsupervised-evaluation-188295 f82ce 5
- https://towards data science . com/day-146-of-NLP 365-NLP-papers-summary-exploring-content-selection-in-summary-of-novel-a 13 fa 1 f 6111 b
其他人
- https://towards data science . com/day-141-of-NLP 365-NLP-papers-summary-text attack-a-framework-for-adversarial-attack-in-aac2a 282d 72 c
- https://towards data science . com/day-142-of-NLP 365-NLP-papers-summary-measuring-emotions-in-the-the-新冠肺炎-现实世界-忧虑-d565098a0937
- https://towards data science . com/day-147-of-NLP 365-NLP-papers-summary-two-birds-one-stone-a-simple-unified-model-for-text-35253 aa 8289 e
#NLP365 第 149 天:NLP 论文摘要——mooc cube:mooc cs 中 NLP 应用的大规模数据仓库

阅读和理解研究论文就像拼凑一个未解之谜。汉斯-彼得·高斯特在 Unsplash 上拍摄的照片。
内线艾 NLP365
NLP 论文摘要是我总结 NLP 研究论文要点的系列文章
项目#NLP365 (+1)是我在 2020 年每天记录我的 NLP 学习旅程的地方。请随意查看我在过去 305 天里学到的东西。在这篇文章的最后,你可以找到以前按自然语言处理领域分类的论文摘要,你也可以订阅# NLP 365 @http://eepurl.com/gW7bBP😃
今天的 NLP 论文是MOOCCube:MOOCs中 NLP 应用的大规模数据仓库。以下是研究论文的要点。
目标和贡献
展示了 MOOCCube,这是一个大型多维数据存储库,包含 700 多门 MOOC 课程、10 万个概念和 800 万个学生行为以及外部资源。我们执行了一项初步的先决条件关系发现任务,以展示 MOOCCube 的潜力,我们希望这个数据存储库将为教育应用(如课程概念提取)开辟许多 NLP 和 AI 研究。
MOOCCube
MOOCCube 与现有的教育数据集有何不同?
- 大型多维数据集。MOOCCube 涵盖了 700 门课程、38K 个视频、200,000 名学生和 100,000 个概念以及 300,000 个关系实例
- 高覆盖率。MOOCCube 涵盖了所有的属性和关系,因为数据是从真实的 MOOC 网站获得的。如下所示,MOOCCube 的一个数据单元以课程、概念和学生为单位,代表学生 s 在课程 c 中学习概念 k。这允许 MOOCCube 提供这些数据单元的不同组合
- MOOCCube 可用于为不同任务构建数据集,如辍学预测和概念提取,而以前这是两个不同的数据集

MOOCCube [1]
数据集集合
MOOCCube 分为三个主要方面:
- 课程
- 概念
- 学生
课程提取
课程是一系列预先录制的视频,对于每个课程,我们提取了大纲、视频列表、教师和组织。我们提取了视频顺序和字幕,并使用 Wikidata 记录了教师和组织的详细描述。
概念和概念图
在这个维度中,我们旨在提取课程视频中教授的知识概念。对于每个视频,我们从字幕中提取 10 个最具代表性的课程理念。对于每个概念,我们使用 Wikidata 记录概念描述,并使用 AMiner 搜索前 10 篇相关论文。最后,我们建立了一个新的概念分类法,用先决条件链作为概念图来捕捉概念之间的语义关系。先决条件链是这样形成的,如果概念 A 有助于理解概念 B,那么概念 A 与概念 B 有一个先决条件关系。要建立这个先决条件链:
- 使用分类信息和视频依赖性减少候选概念对的数量
- 手动注释和带注释的标签用于训练不同的模型,以进一步构建更大距离的监督先决数据集
学生行为
这个维度倾向于支持课程推荐、视频导航、辍学预测以及课程与概念之间关系的研究。在这里,我们保存了 2017-2019 年* 20 万用户的注册记录和视频观看日志。视频观看日志由观看视频时的学生行为组成,例如常见的视频点、点击某个句子等。我们用用户标识匿名用户。
数据分析
下图比较了我们的 MOOCCube 数据集与其他教育数据集。我们的 MOOCCube 拥有最大的数据规模,在不同维度上,尤其是概念图维度上,都比以前的教育数据集大得多。此外,我们的 MOOCCube 涵盖了 MOOC 环境中所有不同类型的数据,这与之前涵盖学生行为或课程内容的教育数据集形成了对比。

现有教育数据集的描述性统计[1]
下图展示了我们的概念分布和注册用户的课程分布。总的来说,我们将概念分为 24 个领域。我们的数据集在工程课程中比自然科学中有更多的概念。在图 3 中,显示了 451 门课程注册了超过 100 个用户,并且超过 70%的用户观看了超过 10 个视频。

概念分布[1]

课程注册和视频观看的分布明细[1]
应用
作为使用 MOOCCube 的示例应用,我们执行了先决条件关系发现。这就是旨在回答“一个人应该先学什么”这一问题的任务。我们使用 MOOCCube 数据集再现了不同的方法,结果显示在以下先决条件中,表现出最好的 F1 分数,我们相信 MOOCCube 数据的高覆盖率有助于发现先决条件关系。此外,我们的两个基准 PCNN 和 PRNN 产生了有竞争力的结果,展示了我们的数据集的有效性。

精确度、召回率和 F1 值[1]
结论和未来工作
潜在的未来工作可能是 a)利用 MOOCCube 的更多数据类型来促进现有主题,b)为现有任务采用高级模型,以及 c)在在线教育领域发现更多创新的 NLP 应用。
来源:
[1]于,李,刘,张,钟,秦,王,杨,罗,李,李,刘,张,唐,2020 年 7 月.mooc cube:mooc 中 NLP 应用的大规模数据仓库。在计算语言学协会第 58 届年会的会议录(第 3135–3142 页)。
最新论文
特征提取/基于特征的情感分析
- https://towardsdatascience . com/day-110-of-NLP 365-NLP-papers-summary-double-embedding-and-CNN-based-sequence-labeling-for-b8a 958 F3 bddd
- https://towards data science . com/day-112-of-NLP 365-NLP-papers-summary-a-challenge-dataset-and-effective-models-for-aspect-based-35b 7 a5 e 245 b5
- https://towards data science . com/day-123-of-NLP 365-NLP-papers-summary-context-aware-embedding-for-targeted-aspect-based-be9f 998d 1131
总结
- https://towards data science . com/day-144-of-NLP 365-NLP-papers-summary-attend-to-medical-ontology-content-selection-for-ff 7 cded 5d 95 b
- https://towards data science . com/day-145-of-NLP 365-NLP-papers-summary-supert-forward-new-frontiers-in-unsupervised-evaluation-188295 f82ce 5
- https://towards data science . com/day-146-of-NLP 365-NLP-papers-summary-exploring-content-selection-in-summary-of-novel-a 13 fa 1 f 6111 b
- https://towards data science . com/day-148-NLP-papers-summary-a-transformer-based-approach-for-source-code-summary-f 07 ecde ACF 40
其他人
- https://towards data science . com/day-141-of-NLP 365-NLP-papers-summary-text attack-a-framework-for-adversarial-attack-in-aac2a 282d 72 c
- https://towards data science . com/day-142-of-NLP 365-NLP-papers-summary-measuring-emotions-in-the-the-新冠肺炎-现实世界-忧虑-d565098a0937
- https://towards data science . com/day-147-of-NLP 365-NLP-papers-summary-two-birds-one-stone-a-simple-unified-model-for-text-35253 aa 8289 e
#NLP365 的第 150 天:NLP 论文摘要——他们会不会——他们不会——他们:一个用于 Twitter 上姿态检测的非常大的数据集

阅读和理解研究论文就像拼凑一个未解之谜。汉斯-彼得·高斯特在 Unsplash 上拍摄的照片。
内线艾 NLP365
NLP 论文摘要是我总结 NLP 研究论文要点的系列文章
项目#NLP365 (+1)是我在 2020 年每天记录我的 NLP 学习旅程的地方。请随意查看我在过去 305 天里学到的东西。在这篇文章的最后,你可以找到以前按自然语言处理领域分类的论文摘要,你也可以订阅# NLP 365 @http://eepurl.com/gW7bBP😃
今天的 NLP 论文是Will-They-Won-Won-They:Twitter 上一个非常大的姿态检测数据集 。以下是研究论文的要点。
目标和贡献
提交最大的姿势检测数据集 Will-They-Won-Won-They(WT-WT),其中包含 51,284 条推文。所有注释都由专家手动标注,确保模型的高质量评估。我们还将 11 个现有的 SOTA 模型应用于我们的数据集,并表明现有的 SOTA 模型与我们的数据集相矛盾,表明我们的数据集对进一步开发模型的未来研究是有用的。最后,我们对娱乐业中的 M&A 操作进行了另一种诠释,并探讨了我们的最佳表现模型在应用于不同领域时的稳健性。我们观察到,我们的模型很难适应哪怕是很小的畴变。
WT-WT 数据集
该数据集涵盖了金融领域谣言验证的立场检测,特别是在并购领域。这是因为 M&A 过程有许多阶段,Twitter 用户对每个阶段的看法演变与谣言验证相似。构建 WT-WT 数据集的过程包括 4 个不同的步骤,包括 5 种不同的 M&A 运算,如下图所示。
- 资料检索
- 任务定义和注释指南
- 数据注释
- 质量评估

不同的有针对性的 M&A 行动[1]
资料检索
在这里,对于每个操作,我们首先使用 Selenium 来检索以下推文的推文 id:
- 提到两家公司名称或缩写的推文
- 提到其中一家公司的推文带有预定义的特定合并条款
日期范围涵盖拟议合并前的一年和合并发生后的六个月。然后,我们使用 Tweepy 通过 Tweets IDs 检索 tweet 的文本。
任务定义和注释指南
我们有四个姿势标签:
- 支持。支持合并的推特
- 反驳。对合并表示怀疑的推文
- 评论。对合并发表评论但不支持或反驳的推文
- 不相关。与合并无关的推文
根据目标实体的不同,同一样本可以有不同的标签。此外,我们的立场检测不同于有针对性的情绪分析,因为有人可以在不表达合并是否会发生的情况下推断出对合并的情绪。
数据注释
数据注释过程是由剑桥大学的 10 名金融学者分批对 2000 个样本进行的。
质量评估
注释者对之间的*均相关性是 0.67,显示了数据的高质量。我们还要求一位领域专家对 3000 条推文样本进行标注,并以此作为人类评估的上限。支持和评论样本在注释者之间引起了最大的分歧,因为我们认为这样的样本大多是主观的。不相关标签的包含导致了不相关样本和评论样本之间更高的不一致性,使得我们的数据集更具挑战性。
标签分发
下图展示了每个 M&A 工厂的标签分布情况。我们观察到反驳和支持样本的相对比例与并购被批准或被阻止之间存在相关性。像往常一样,评论推文比支持所有操作更频繁。

跨不同 M&A 运营的标签分布[1]
与现有语料库的比较
在这里,我们将我们的数据集与现有数据集进行了比较,如下表所示。如上所述,我们的数据集是最大的姿态检测数据集。除了规模之外,我们的注释过程涉及高技能的领域专家,而不是众包。此外,我们的数据集包含用于跨领域研究的不同领域。

Twitter 姿态检测数据集的描述性统计[1]
实验和结果
我们选择并重新实现了之前用于姿态检测的 11 个强模型。结果显示如下。SiamNet 在 F1 *均和加权*均分数方面表现最佳。像往常一样,SVM 为姿态检测提供了一个强大的基线。就不同的类别分类而言,模型在支持和评论类别之间似乎具有相对较高的错误分类数量。包含语言特征似乎减少了错误分类。CharCNN 获得了不相关样本的最佳性能,这表明我们应该为未来的架构使用字符级信息。

WT-WT 数据集中医疗保健操作的结果[1]
对畴变的鲁棒性
在这里,我们探索我们的最佳模型如何在娱乐行业的 M&A 事件上进行跨域实验。结果显示如下。当用相同的领域数据集训练和测试模型时,结果显示了很强的性能。当模型在健康或娱乐数据集上训练并在另一个领域上测试时,我们观察到性能显著下降,表明我们的模型具有很强的领域依赖性。

领域概括实验[1]
结论和未来工作
我们表明,现有的 SOTA 模型在我们代表人类上限的数据集上表现低 10%。潜在的未来研究可能涉及探索基于转换器的模型和数据集上的不同模型架构。此外,数据集包含多个领域,允许未来使用我们的数据集进行跨目标和跨领域的研究。
来源:
[1]康弗蒂,c .,伯恩特,j .,皮莱赫瓦尔,M.T .,詹尼察鲁,c .,托克斯瓦尔,f .和科利尔,n .,2020 年。will-They-would-They:一个用于 Twitter 上姿势检测的非常大的数据集。arXiv 预印本 arXiv:2005.00388 。
最新论文
特征提取/基于特征的情感分析
- https://towardsdatascience . com/day-110-of-NLP 365-NLP-papers-summary-double-embedding-and-CNN-based-sequence-labeling-for-b8a 958 F3 bddd
- https://towards data science . com/day-112-of-NLP 365-NLP-papers-summary-a-challenge-dataset-and-effective-models-for-aspect-based-35b 7 a5 e 245 b5
- https://towards data science . com/day-123-of-NLP 365-NLP-papers-summary-context-aware-embedding-for-targeted-aspect-based-be9f 998d 1131
总结
- https://towards data science . com/day-144-of-NLP 365-NLP-papers-summary-attend-to-medical-ontology-content-selection-for-ff 7 cded 5d 95 b
- https://towards data science . com/day-145-of-NLP 365-NLP-papers-summary-supert-forward-new-frontiers-in-unsupervised-evaluation-188295 f82ce 5
- https://towards data science . com/day-146-of-NLP 365-NLP-papers-summary-exploring-content-selection-in-summary-of-novel-a 13 fa 1 f 6111 b
- https://towardsdatascience . com/day-148-NLP-papers-summary-a-transformer-based-approach-for-source-code-summary-f 07 ecde ACF 40
其他人
- https://towards data science . com/day-141-of-NLP 365-NLP-papers-summary-text attack-a-framework-for-adversarial-attack-in-aac2a 282d 72 c
- https://towards data science . com/day-142-of-NLP 365-NLP-papers-summary-measuring-emotions-in-the-the-新冠肺炎-现实世界-忧虑-d565098a0937
- https://towards data science . com/day-147-of-NLP 365-NLP-papers-summary-two-birds-one-stone-a-simple-unified-model-for-text-35253 aa 8289 e
- https://towards data science . com/day-149-of-NLP 365-NLP-papers-summary-mooccube-a-large-scale-data-repository-for-NLP-3fb cab 37 bfef
DBS can——一种基于密度的无监督欺诈检测算法

帕特里克·托马索在 Unsplash 上的照片
欺诈检测方面的小数据科学
根据最*的一份报告欺诈交易造成的财务损失已达到约 170 亿美元,多达 5%的消费者遭遇过某种形式的欺诈事件。
鉴于如此巨大的财务损失,每个行业都非常重视欺诈检测。不仅仅是金融行业容易受到影响,异常现象在每一个行业都很普遍,并且可能采取多种不同的形式,例如网络入侵、业务绩效中断和 KPI 的突然变化等。
欺诈/异常/异常值检测长期以来一直是数据科学领域的热门研究课题。在不断变化的欺诈检测环境中,每天都在测试和使用新的工具和技术来筛选异常情况。在这一系列文章中,到目前为止,我已经讨论了六种不同的欺诈检测技术:
今天,我将介绍另一种称为 DBSCAN 的技术,它是基于密度的噪声应用空间聚类的缩写。
顾名思义,DBSCAN 是一种基于密度的无监督机器学习算法。它将多维数据作为输入,并根据模型参数(例如ε和最小样本)对其进行聚类。基于这些参数,算法确定数据集中的某些值是否是异常值。
下面是 Python 编程语言的简单演示。
Scikit-Learn 中的 DBSCAN 实现
Scikit-learn 有一个 DBSCAN 模块,作为其无监督机器学习算法的一部分。只需几个简单的步骤,这种算法就可以立即用于欺诈检测。
第一步:导入库
对于这个演示,我们需要三个关键库来处理数据、可视化和建模。
# data wrangling
import pandas as pd# visualization
import matplotlib.pyplot as plt# algorithm
from sklearn.cluster import DBSCAN
第二步:导入&可视化数据
我使用的是网上著名的虹膜数据集,所以你可以跟着练习,不用担心从哪里得到数据,如何清理这些数据。
# import data
df = pd.read_csv("[https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv](https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv)")print(df.head())

让我们选择一个数据子集来测试算法,并将它们可视化在散点图中。

二维数据散点图
第三步:建模
该模型采用的两个最重要的参数值是(i) esp ,其指定两点之间的距离,即,数据点彼此应该有多接*以被认为是聚类的一部分;以及(ii) min_samples,,其指定一个点在一个聚类中应该具有的邻居的最小数量。
# input data
data = df[["sepal_length", "sepal_width"]]# specify & fit model
model = DBSCAN(eps = 0.4, min_samples = 10).fit(data)
第四步:可视化
# visualize outputs
colors = model.labels_
plt.scatter(data["sepal_length"], data["sepal_width"], c = colors)

紫色中检测到异常值
步骤 5:创建异常值数据框
# outliers dataframe
outliers = data[model.labels_ == -1]print(outliers)

异常值的数据框架
总结
本文的目的是介绍 DBS can——一种基于聚类的无监督机器学习技术,用于欺诈/异常值/异常检测。它的实现可以简单到只需要使用sklearn库的五个步骤。当然,这只是一个简单的概念演示。真实世界的应用程序需要更多的实验来找到适合特定环境和行业的最佳模型。
DBSCAN 集群—解释
详细的理论解释和 scikit-learn 实现
聚类是一种对一组数据点进行分组的方法,将相似的数据点分组在一起。因此,聚类算法寻找数据点之间的相似或相异之处。聚类是一种无监督的学习方法,因此没有与数据点相关联的标签。该算法试图找到数据的底层结构。

简·梅乌斯在 Unsplash 上的照片
有不同的方法和算法来执行聚类任务,这些任务可以分为三个子类别:
- 基于分区的聚类:例如 k 均值、k 中值
- 等级聚类:例如聚集、分裂
- 基于密度的聚类:例如 DBSCAN
在这篇文章中,我将尝试详细解释 DBSCAN 算法。如果你想了解其他类型的聚类算法,你也可以访问下面的帖子:
详细的理论解释和 scikit-learn 实现
towardsdatascience.com](/k-means-clustering-explained-4528df86a120) [## 分层聚类—已解释
理论解释和科学学习范例
towardsdatascience.com](/hierarchical-clustering-explained-e58d2f936323)
基于密度的聚类
基于分区和层次聚类技术对于正常形状的聚类非常有效。然而,当涉及到任意形状的聚类或检测异常值时,基于密度的技术更有效。
例如,使用 k-means 算法可以很容易地将下图中的数据集分成三个聚类。

k 均值聚类
请考虑以下数字:



这些图中的数据点以任意形状分组或者包含异常值。基于密度的聚类算法在发现高密度区域和离群点方面非常有效。对于某些任务来说,检测异常值是非常重要的,例如异常检测。
DBSCAN 算法
DBSCAN 代表den sity-bassclustering ofa应用与 n oise。它能够找到任意形状的聚类和带有噪声的聚类(即异常值)。
DBSCAN 背后的主要思想是,如果一个点靠*来自该簇的许多点,则该点属于该簇。
DBSCAN 有两个关键参数:
- eps :指定邻居的距离。如果两点之间的距离小于或等于 eps,则认为这两点是相邻的。
- minPts: 定义一个聚类的最小个数据点。
基于这两个参数,点被分类为核心点、边界点或异常点:
- 核心点:如果一个点在其半径为 eps 的周围区域中至少有 minPts 个数的点(包括该点本身),则该点是核心点。
- 边界点:如果一个点可以从一个核心点到达,并且其周围区域内的点数小于 minPts,那么这个点就是边界点。
- 离群点:如果一个点不是核心点,并且从任何核心点都不可达,那么这个点就是离群点。
这些观点可以用形象化来更好地解释。下图摘自维基百科:

在这种情况下,minPts 是 4。红色点是核心点,因为在其半径为 eps 的周围区域内至少有4 个点。该区域在图中用圆圈表示。黄色点是边界点,因为它们可以从核心点到达,并且其邻域内的点少于 4 个。可到达意味着在核心点的周围区域。点 B 和 C 在其邻域内(即以 eps 为半径的周围区域)有两个点(包括点本身)。最后,N 是一个异常值,因为它不是一个核心点,不能从核心点到达。
我们已经学习了参数和不同类型点的定义。现在我们可以谈谈算法是如何工作的。这其实很简单:
- 确定 minPts 和 eps。
- 随机选择一个起始点,使用半径 eps 确定其邻域。如果邻域中至少有 minPts 个数的点,则将该点标记为核心点,并开始形成聚类。如果不是,则该点被标记为噪声。一旦聚类形成开始(假设聚类 A),初始点邻域内的所有点都成为聚类 A 的一部分。如果这些新点也是核心点,则它们邻域内的点也被添加到聚类 A 中。
注意:被标记为噪声的点可以被重新访问,并且是聚类的一部分。
- 下一步是在前面步骤中没有访问过的点中随机选择另一个点。然后同样的程序适用。
- 当所有点都被访问时,该过程结束。
使用 k-means 算法中的距离测量方法来确定点之间的距离。最常用的方法是欧氏距离。
通过应用这些步骤,DBSCAN 算法能够找到高密度区域并将它们从低密度区域中分离出来。
一个集群包括相邻的核心点(即彼此可到达的)以及这些核心点的所有边界点。形成集群的必要条件是至少有一个核心点。尽管可能性很小,但我们可能有一个只有一个核心点及其边界点的集群。
Scikit-learn 实现
我们首先使用 scikit-learn 的 datasets 模块创建一个样本数据集。创建样本数据点后,我们将使用 scikit-learn 的预处理模块中的 StandardScaler 类对值进行归一化。
注意:归一化数值很重要,因为这样更容易找到邻域半径(eps)的合适距离。
让我们首先导入库:
import numpy as npfrom sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScalerimport matplotlib.pyplot as plt
%matplotlib inline
我们将创建一个包含 3 个聚类的数据集,每个聚类的标准偏差为 0.5。样本数量是 400,我们也选择三个点作为质心(聚类的中心)。您可以使用 make_blobs 函数随意调整这些参数。
#Determine centroids
centers = [[0.5, 2], [-1, -1], [1.5, -1]]#Create dataset
X, y = make_blobs(n_samples=400, centers=centers,
cluster_std=0.5, random_state=0)#Normalize the values
X = StandardScaler().fit_transform(X)
我们还可以绘制数据集,以查看每个聚类的外观:
plt.figure(figsize=(10,6))
plt.scatter(X[:,0], X[:,1], c=y, cmap='Paired')

我们现在可以创建一个 DBSCAN 对象并拟合数据:
from sklearn.cluster import DBSCANdb = DBSCAN(eps=0.4, min_samples=20)db.fit(X)
我们只需要使用 eps 和 min_samples 参数定义 eps 和 minPts 值。
注意:我们不必指定 DBSCAN 的聚类数,这是 DBSCAN 优于 k-means 聚类的一大优势。
让我们来看一下 DBSCAN 确定的集群:
y_pred = db.fit_predict(X)plt.figure(figsize=(10,6))
plt.scatter(X[:,0], X[:,1],c=y_pred, cmap='Paired')
plt.title("Clusters determined by DBSCAN")

它能够检测异常值(用蓝色标记)。我们可以使用 labels_ attribute 来访问数据点的标签。噪声(或离群值)被赋予-1 标签。让我们检查异常值的数量:
db.labels_[db.labels_ == -1].size
18
该样本数据集中的分类实际上并不具有任意形状。但是 DBSCAN 在检测异常值方面表现得非常好,这对于基于分区(例如 k-means)或分层(例如凝聚)的聚类技术来说是不容易的。如果您还将 DBSCAN 应用于具有任意形状的集群的数据集,您也会看到 DBSCAN 的成功。
DBS can 的利弊
优点:
- 不需要预先指定簇的数量。
- 适用于任意形状的集群。
- DBSCAN 对异常值是鲁棒的,并且能够检测异常值。
缺点:
- 在某些情况下,确定适当的邻域距离(eps)并不容易,这需要领域知识。
- 如果集群在集群内密度方面差异很大,那么 DBSCAN 就不太适合定义集群。聚类的特征由 eps-minPts 参数的组合来定义。因为我们将一个 eps-minPts 组合传递给该算法,所以它不能很好地推广到具有很大不同密度的聚类。
感谢阅读。如果您有任何反馈,请告诉我。
参考文献
用于交易的 DBSCAN 聚类
金融中的人工智能
发展配对交易策略

图片来源:锐拍
由摩根斯坦利的量化分析师在 80 年代首创的 pairs trading 是一种交易策略,允许交易者在几乎任何市场条件下获利。这种策略包括监控两种历史上相关的证券。一旦发现相关性差异,如一只股票上涨,而另一只股票停滞不前,投资者就会做多表现不佳的证券,做空表现出色的证券,希望证券回到其历史相关性。在这种情况下,投资者从价格趋同中获利。
例如,通用汽车公司和福特汽车公司生产类似的产品(汽车),因此它们基于整个汽车市场分享类似的股票价格变动。如果通用汽车公司的股票价格大幅上涨,而福特汽车公司的股票价格保持不变,那么实施配对交易策略的人会做空通用汽车公司的股票,并买入福特汽车公司的股票,假设价格将回到其历史*衡点。如果通用汽车的股票下跌,投资者获利,如果福特的股票上涨,投资者也获利。然而,过去的价格并不总是未来趋势的指标,所以这种策略仍然有风险。为了帮助我们找到历史上相关的证券,我们可以使用 DBSCAN 聚类。
DBSCAN 聚类:简要说明

通过谷歌图片搜索的图片,标记为重复使用
机器学习可以用于许多交易策略,配对交易也不例外。基于密度的带噪声应用空间聚类(DBSCAN)可用于对股票进行聚类,并排除不适合聚类的股票。DBSCAN 的两个参数是 eps(被视为聚类一部分的点之间的距离)和 minPoints(形成密集区域的最小点数)。根据这些参数,DBSCAN 算法然后从我们提供给它的一组点中创建聚类。位于低密度区域的点被归类为异常值。K-means 是另一种流行的聚类算法,但它对异常值更敏感,这就是我们使用 DBSCAN 的原因。现在我们已经了解了 pairs trading 和 DBSCAN,让我们开始实现吧。
进口/数据
我们从必要的进口开始。值得注意的是,从量子*台进口的产品将用于量子*台 IDE 。
import matplotlib.pyplot as plt
import matplotlib.cm as cmimport numpy as np
import pandas as pdfrom sklearn.cluster import DBSCAN
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn import preprocessingfrom statsmodels.tsa.stattools import cointfrom scipy import statsfrom quantopian.pipeline.data import morningstar
from quantopian.pipeline.filters.morningstar import Q500US, Q1500US, Q3000US
from quantopian.pipeline import Pipeline
from quantopian.research import run_pipeline
我们将使用的预定义宇宙是 Q1500,它是一个大的流动股票集合。
study_date = "2019-12-31"
universe = Q1500US()
为了创建我们的渠道,我们使用了来自晨星的信息。
pipe = Pipeline(columns = {
'Market Cap': morningstar.valuation.market_cap.latest.quantiles(5),
'Industry':morningstar.asset_classification.morningstar_industry_group_code.latest,
'Financial Health':morningstar.asset_classification.financial_health_grade.latest},
screen = universe)res = run_pipeline(pipe, study_date, study_date)
res.index = res.index.droplevel(0) # drop the single date from the multi-index
让我们来看看我们的数据。我们看到它包含了 1486 只股票,以及对财务健康、行业和市值的描述。
print res.shape
res.head()

我们不能处理没有财务健康等级的股票,所以我们删除了它们。两只股票缺乏财务健康等级,因此被剔除。
res = res[res['Financial Health']!= None]
print res.shape

现在,我们将创建一个字典,用数字分数替换财务健康的分类数据。
res['Financial Health'] = res['Financial Health'].astype('object')
health_dict = {u'A': 0.1,
u'B': 0.3,
u'C': 0.7,
u'D': 0.9,
u'F': 1.0}
res = res.replace({'Financial Health': health_dict})
为了更好地理解我们的数据,我们使用。描述()以查看一些基本指标,如*均值和标准差。
res.describe()

每日回报
获取每日回报(股票价格的美元变化占前一天收盘价的百分比)用于我们的策略。然后我们以苹果公司的日回报率为例。
pricing = get_pricing(
symbols=res.index,
fields='close_price',
start_date=pd.Timestamp(study_date) - pd.DateOffset(months=24),
end_date=pd.Timestamp(study_date)
)returns = pricing.pct_change()
returns[symbols(['AAPL'])].plot()

类似于我们对缺乏财务健康等级的股票所做的,我们将不得不删除没有完整回报系列的股票。
returns = returns.iloc[1:,:].dropna(axis=1)
print returns.shape

PCA 和 DBSCAN
我们的下一步是使用主成分分析来降低回报数据的维度,提取每只股票的历史潜在公共因子负载,添加市值/财务健康值,并使用 DBSCAN。
prin_components = 50
pca = PCA(n_components=prin_components)
pca.fit(returns)

X = np.hstack(
(pca.components_.T,
res['Market Cap'][returns.columns].values[:, np.newaxis],
res['Financial Health'][returns.columns].values[:, np.newaxis])
)X = preprocessing.StandardScaler().fit_transform(X)clf = DBSCAN(eps=1.9, min_samples=3)
print clfclf.fit(X)
labels = clf.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
print "\nClusters discovered: %d" % n_clusters_clustered = clf.labels_

可能的配对总数超过 900,000 个,所以我们将大大减少这个数字,只对我们的配对交易策略中更好的候选配对。
ticker_count = len(returns.columns)
print "Total pairs possible in universe: %d " % (ticker_count*(ticker_count-1)/2)

clustered_series = pd.Series(index=returns.columns, data=clustered.flatten())
clustered_series_all = pd.Series(index=returns.columns, data=clustered.flatten())
clustered_series = clustered_series[clustered_series != -1]CLUSTER_SIZE_LIMIT = 9999
counts = clustered_series.value_counts()
ticker_count_reduced = counts[(counts>1) & (counts<=CLUSTER_SIZE_LIMIT)]
print "Clusters formed: %d" % len(ticker_count_reduced)
print "Pairs to evaluate: %d" % (ticker_count_reduced*(ticker_count_reduced-1)).sum()

形象化
由于数据目前聚集在 52 个维度中,我们可以使用 T-SNE 算法来可视化 2D 的数据,并查看 15 个集群。
X_tsne = TSNE(learning_rate=1000, perplexity=25, random_state=1337).fit_transform(X)plt.figure(1, facecolor='white')
plt.clf()
plt.axis('off')plt.scatter(
X_tsne[(labels!=-1), 0],
X_tsne[(labels!=-1), 1],
s=100,
alpha=0.85,
c=labels[labels!=-1],
cmap=cm.Paired
)plt.scatter(
X_tsne[(clustered_series_all==-1).values, 0],
X_tsne[(clustered_series_all==-1).values, 1],
s=100,
alpha=0.05
)plt.title('T-SNE of all Stocks with DBSCAN Clusters Noted')

让我们画出每个聚类中的股票数量。
plt.barh(
range(len(clustered_series.value_counts())),
clustered_series.value_counts()
)
plt.title('Cluster Member Counts')
plt.xlabel('Stocks in Cluster')
plt.ylabel('Cluster Number')

我们将可视化较小的集群以获得历史相关性,从而查看 DBSCAN 是否正确地完成了它的工作。正如我们所看到的,聚类中的股票价格确实有很高的相关性。
counts = clustered_series.value_counts()cluster_vis_list = list(counts[(counts<20) & (counts>1)].index)[::-1]for clust in cluster_vis_list[0:min(len(cluster_vis_list), 3)]:
tickers = list(clustered_series[clustered_series==clust].index)
means = np.log(pricing[tickers].mean())
data = np.log(pricing[tickers]).sub(means)
data.plot(title='Stock Time Series for Cluster %d' % clust)



获得对子
为了验证协整关系,我们可以使用 Quantopian 提供给我们的函数。然后,我们可以得到我们的配对列表。
def find_cointegrated_pairs(data, significance=0.05):
# This function is from [https://www.quantopian.com/lectures/introduction-to-pairs-trading](https://www.quantopian.com/lectures/introduction-to-pairs-trading)
n = data.shape[1]
score_matrix = np.zeros((n, n))
pvalue_matrix = np.ones((n, n))
keys = data.keys()
pairs = []
for i in range(n):
for j in range(i+1, n):
S1 = data[keys[i]]
S2 = data[keys[j]]
result = coint(S1, S2)
score = result[0]
pvalue = result[1]
score_matrix[i, j] = score
pvalue_matrix[i, j] = pvalue
if pvalue < significance:
pairs.append((keys[i], keys[j]))
return score_matrix, pvalue_matrix, pairscluster_dict = {}
for i, which_clust in enumerate(ticker_count_reduced.index):
tickers = clustered_series[clustered_series == which_clust].index
score_matrix, pvalue_matrix, pairs = find_cointegrated_pairs(
pricing[tickers]
)
cluster_dict[which_clust] = {}
cluster_dict[which_clust]['score_matrix'] = score_matrix
cluster_dict[which_clust]['pvalue_matrix'] = pvalue_matrix
cluster_dict[which_clust]['pairs'] = pairspairs = []
for clust in cluster_dict.keys():
pairs.extend(cluster_dict[clust]['pairs'])pairs

我们留下了一个包含 118 对和 88 个独特代码的列表。作为我们的最后一步,我们将再次使用 T-SNE 可视化我们的验证对。
stocks = np.unique(pairs)
X_df = pd.DataFrame(index=returns.T.index, data=X)
in_pairs_series = clustered_series.loc[stocks]
stocks = list(np.unique(pairs))
X_pairs = X_df.loc[stocks]X_tsne = TSNE(learning_rate=50, perplexity=3, random_state=1337).fit_transform(X_pairs)plt.figure(1, facecolor='white')
plt.clf()
plt.axis('off')
for pair in pairs:
ticker1 = pair[0].symbol
loc1 = X_pairs.index.get_loc(pair[0])
x1, y1 = X_tsne[loc1, :]ticker2 = pair[0].symbol
loc2 = X_pairs.index.get_loc(pair[1])
x2, y2 = X_tsne[loc2, :]
plt.plot([x1, x2], [y1, y2], 'k-', alpha=0.3, c='gray');
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], s=220, alpha=0.9, c=[in_pairs_series.values], cmap=cm.Paired)
plt.title('T-SNE Visualization of Validated Pairs');

最后,我们完成了寻找配对交易策略的目标。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
参考
[1]乔纳森·拉金,用机器学习进行配对交易,Github
先别走!
我是 Roshan,16 岁,对人工智能和金融的交叉领域充满热情。关于人工智能在金融领域的广泛观点,请查看这篇文章:https://towards data science . com/artificial-intelligence-and-its-application-in-finance-9f1e 0588 e 777。
在 Linkedin 上联系我:https://www.linkedin.com/in/roshan-adusumilli-96b104194/
DBSCAN —手动创建基于密度的集群

这篇文章也发表在这里
DBSCAN 代表带噪声的基于密度的空间聚类应用。它是一种无监督的机器学习算法,根据数据点的密度或数据的接*程度来进行聚类。也就是说,密集区域之外的点被排除在外,并被视为噪声或异常值。DBSCAN 算法的这一特性使其非常适合异常值检测和生成任意形状的聚类。像 K-Means 聚类 这样的算法缺乏这种特性,并且只产生球形聚类,并且对异常值非常敏感。就敏感性而言,我的意思是通过 K-Means 得到的球形聚类很容易受到单个异常值的影响,因为它们也包括在内。
关于 DBSCAN 的教程/文章通常包含大量数据集和核心程序,这使得读者很难理解核心概念,但在本文中,我们将把该算法应用于一个非常小的数据集来解释它。跳过一些计算,直接显示计算表。建议验证所有这样的计算,这样会让概念对你来说更形象。让我们取一个包含 13 个点的数据集,如下图所示:

二维数据便于可视化和理解,否则 DBSCAN 也可以处理多维数据。数据中可能的聚类在上图中已被标记,以可视化我们想要的聚类。上图中的点(1,5) (4,3) (5,6)位于标记之外,因此应视为异常值。DBSCAN 算法实际上应该生成聚类并排除异常值,正如我们在图中所做的那样。我们先来了解一下算法,以及其中涉及的各个步骤。
逻辑和步骤:
DBSCAN 算法有两个输入参数。每个点周围的半径( eps )和在该半径内该点周围的最小数据点数( MinPts )。例如,考虑点(1.5,2.5),如果我们取 eps = 0.3,那么半径= 0.3 的点周围的圆将只包含它内部的另一个点(1.2,2.5),如下所示:

因此,对于(1.5,2.5),当 eps = 0.3 时,邻域点的数量仅为 1。在 DBSCAN 中,针对这两个参数检查每个点,并通过以下步骤做出关于聚类的决定:
- 为 eps 和 MinPts 选择一个值
- 对于特定的数据点( x ),计算其与其他数据点的距离。
- 找出 x 的所有落在半径为 eps 的圆内的邻域点,或者仅仅是到 x 的距离小于等于 eps 的邻域点。
- 将 x 视为访问过的并且如果 x 周围的邻域点的数量大于或等于 MinPts 那么将 x 视为核心点,如果它没有被分配给任何聚类,则创建一个新的聚类并将其分配给该聚类。
- 如果 x 周围的邻域点的数量小于 MinPts,并且在其邻域中有一个核心点,则将其视为边界点。
- 包括所有的密度连接点作为一个单独的集群。(密度连接点的含义将在后面描述)
- 对数据集中的每个未访问点重复上述步骤,找出所有核心点、边界点和离群点。
请注意,上述步骤构成了一个递归过程。第一次循环计算后,一个点可能不会被视为任何核心点的边界点,但在下一次循环中可能会被视为边界点。
如果 x 周围的邻域点的数量大于或等于 MinPts,则 x 被视为核心点,如果 x 周围的邻域点小于 MinPts 但接*核心点,则 x 被视为边界点。如果 x 既不是核心点也不是边界点,则 x 被视为异常值。下图给出了一个想法。我们选择 eps = 0.6,MinPts =4,标记为核心点的点在其邻域内有 4 个其他点(>= min pts)&,标记为边界点的点在核心点的邻域内,但在其邻域内只有一个点(< MinPts)。离群点既不是边界点,也不是核心点。

运行中的算法
现在,让我们将 DBSCAN 算法应用于上述数据集,以找出聚类。我们必须首先选择 eps 和 MinPts 的值。我们选EPS= 0.6min pts= 4。让我们考虑数据集(1,2) &中的第一个数据点,计算它与数据集中每隔一个数据点的距离。计算值如下所示:

从上表可以明显看出,对于 eps 的假设值,点(1,2)在其邻域中只有两个其他点(1,2.5),(1.2,2.5),由于其小于 MinPts,我们不能将其声明为核心点。让我们对数据集中的每个点重复上述过程,并找出每个点的邻域。重复时的计算可总结如下:

仔细观察上表,最左边的一列包含了我们数据集中所有的点。在它们的右边是在它们附*的数据点,即距离它们的距离小于或等于 eps 值的点。在数据集中有三个点,(2.8,4.5) (1.2,2.5) (1,2.5),它们周围有 4 个邻域点,因此它们被称为核心点,并且如已经提到的,如果核心点没有被分配给任何聚类,则形成新的聚类。因此,(2.8,4.5)被分配给新的聚类,聚类 1,点(1.2,2.5),聚类 2 也是如此。还观察到核心点(1.2,2.5)和(1,2.5)共享至少一个公共邻域点(1,2),因此,它们被分配到相同的集群。下表显示了所有数据点的分类,分为核心点、边界点和异常点。看一看:

DBSCAN 算法在数据集中检测到三种类型的点:核心点、边界点和异常点。每个核心点将被分配到一个新的聚类中,除非一些核心点共享邻域点,否则它们将被包括在同一个聚类中。每个边界点将基于其邻域中的核心点被分配给聚类,例如,第一点(1,2)是边界点,并且在其邻域中具有核心点(1.2,2.5),其被包括在聚类 2 中,因此,点(1,2)也将被包括在聚类 2 中。整个分类可以总结如下:

为了理解 DBSCAN,需要理解三个术语:
1.直接密度可达:如果一个点在其邻域内有一个核心点,则称该点为直接密度可达。考虑点(1,2),它在其邻域中有一个核心点(1.2,2.5),因此,它将是一个直接密度可达点。
2.密度可达:如果一个点和另一个点通过一系列核心点连接,则称这两个点为密度可达。例如,考虑点(1,3)和(1.5,2.5),因为它们通过一个核心点(1.2,2.5)连接,所以它们被称为彼此可达的密度。
3.密度连通:如果有一个核心点是从这两点密度可达的,那么这两点称为密度连通。
到目前为止,DBSCAN 的算法必须是清晰的。它很漂亮,因为它排除了离群点,并使聚类具有任意形状,而不像 k-means 聚类 。
关于这篇文章的任何建议,你可以在下面发表你的评论或者通过 LinkedIn 联系我。
谢谢,
祝你玩得愉快😊
使用 Python 的 DBSCAN
包含 GitHub repo 的链接
带噪声应用的基于密度的空间聚类初学者指南(带示例)

KMeans 在处理任意形状的簇时有困难。图片由 Mikio Harman 提供
聚类是一种无监督的学习技术,它在数据中寻找模式,而不需要被明确告知要寻找什么模式。
DBSCAN 通过测量每个点之间的距离来做到这一点,如果足够多的点足够靠*,那么 DBSCAN 会将其分类为一个新的聚类。
如上所示,在测试数据中有两个不同的集群。另一种流行的聚类技术 KMeans 无法准确地对这些数据进行聚类,因为当 k=2 时, KMeans 在聚类之间创建了一个线性可分的边界。
DBSCAN 根据两个参数定义聚类:Epsilon 和 Min_Points
ε—一个点到另一个点的最大距离被认为是邻居。
Min_Points —在ε的范围内被认为是一个聚类所需的点数。
DBSCAN 的优势
确定输入参数需要最少的领域知识。
其他聚类算法,如 KMeans,要求用户知道数据中存在多少个聚类。
DBSCAN 不要求找到多少个聚类,而是要求用户输入每个数据点可以被认为是一个聚类的一部分的最大距离,以及形成一个聚类需要多少个数据点。
它能发现任何形状的星团。
由于 DBSCAN 基于 epsilon 和每个点的邻居数量来创建聚类,因此它可以找到任何形状的聚类。当集群具有相同的密度(点之间的距离)时,DBSCAN 工作得最好。当存在不同密度的簇时,这会使 DBSCAN 难以识别簇。
跟着走!
点击此处打开实现 Scikit 的 Google Colab 笔记本——从头开始学习 DBSCAN 和 DBSCAN2。如果你想了解更多关于引擎盖下发生的事情,请继续阅读。
**# Download the test package**
pip install -i [https://test.pypi.org/simple/](https://test.pypi.org/simple/) dbscan2==0.0.3**# Import it!**
from dbscan2 import dbscan2**# If you would like to plot the results import the following**
from sklearn.datasets import make_moons
import pandas as pd
为了从头开始理解和实现 DBSCAN,我们需要知道 DBSCAN 是如何对数据进行聚类的。除了ε点和最小点,还有三个基本术语需要理解:
噪声 —这是一个在 epsilon 内没有足够的邻居来成为聚类的一部分(包括其自身)的点。
边界点 —这是一个在ε内有邻居但没有足够邻居成为核心点的点。这些点构成了群集的边缘。
核心点——具有 epsilon(包括其自身)内所需最小点数的点。这些点连同边界点将形成一个簇。

图片由 Mikio Harman 提供
我们将使用一个类来实现 DBSCAN,并将其命名为 dbscan2。它将有两个主要方法:拟合和预测。
**def __init__()**
将使用标准化的两个特征数组ε和创建聚类所需的点数来初始化该类。它还将用一个簇标签和一个噪声标签来初始化。
class dbscan2():
def __init__(self,df, epsilon=1, min_points=5):
self.df = np.array(df)
self.epsilon = epsilon
self.min_points = min_points
self.cluster_label = 0
self.noise = 0
助手功能
我们将使用欧几里得距离来度量每个点之间的距离。欧几里德距离将测量从一对坐标到另一对坐标的普通直线距离。

图片来自维基百科
def dist(self, point1, point2):
"""Euclid distance function"""
x1 = point1[0]
x2 = point2[0]
y1 = point1[1]
y2 = point2[1]# create the points
p1 = (x1 - x2)**2
p2 = (y1 - y2)**2
return np.sqrt(p1 + p2)
我们需要的另一个助手函数叫做rangeQuery。该函数将帮助我们找出每个点在ε内有多少个邻居。
def rangeQuery(self, x):
"""Query database against x and return all points that are <=
epsilon"""neighbors = []for y in range(len(self.df)):
q = self.df[y, :2]**# If the distance is <= than epsilon then append to
neighbors list**
if self.dist(x, q) <= self.epsilon:
neighbors.append(y)return neighbors
**def fit():**
我们的拟合函数将遍历整个数据集,并确定数据集中每个点有多少个邻居。
如果单个点没有足够的邻居(neighbors < min_points,那么它将被标记为噪声。
如果一个点有足够多的邻居(neighbors ≥ min_points),那么该点将被分配一个新的聚类标签,并且它的所有邻居也将被赋予相同的标签。fit 函数将进入一个 while 循环,将所有的邻居添加到一个Queue中,以便它们可以与新发现的邻居的邻居一起被正确地标记为新聚类的一部分。
这个过程将继续,直到算法已经检查了所有点。
**def predict():**
进行预测时,算法将使用rangeQuery识别新输入点是否有任何邻居。如果是,那么新点将被预测为具有与其邻居相同的标签。
这是我们最终完成的类的样子
与 Scikit-Learn 版本相比如何?

图片由 Mikio Harman 提供
正如所料,我们从头开始的实现最终得到了与 Scikit-Learn 版本相同的结果。我们的 DBSCAN 版本需要更长的时间,我仍然会使用 Scikit-Learns 版本,但是希望从头开始实现该算法可以帮助您更好地理解如何使用 DBSCAN 找到任意的簇形状。
找到博客的代码 这里
参考
一种基于密度的算法,用于在带有噪声的大型空间数据库中发现聚类
揭开 XGBoost 第一部分的神秘面纱
揭开 XGBoost 的神秘面纱
想象树木
为什么为什么?
已经有很多关于 XGBoost 内部运作的去神秘化的、奇妙的博客。为什么是另一个?我一直认为应该有一个能把它们缝合在一起的。把理论和真实的例子结合在一起。一个真正去神秘化的。一个我自己可以参考的。所以,我想到了做一个系列。如下图。
我想把这个系列分成 5 个部分。
第一部分将介绍 XgBoost 背后的数学原理。更形象地说,把它印入我们的神经网络😀。
在 第二部分 中,我将深入探究使用 XGBoost 时各种参数背后的直觉——将它与数学和真实的例子缝合在一起。回答为什么和什么时候这样的问题。但只有最重要的参数。毫无疑问,这将是最有趣的。
在 第三部分 中,我将展示如何创建一个容器,超快,(在 GCP 上)使用它我们可以处理几乎所有的 ML 问题,特别是 XgBoost 使用 python 和 python 内核的 Jupyter 笔记本中的 R!!。
第四部分,我们将使用这个容器,看看我们在前面的部分中讨论的所有概念和直觉如何应用于一个公开可用的数据集。
第五部分,我将讨论我们在第二部分中没有涉及的其余参数背后的直觉。
那么,我们开始吧。
数学
对于这一部分,我们需要知道的只是一点高中微分学。如果你很久以前就离开了高中,对微分学只有一个模糊的概念,那也没关系,相信我:)
如果可能的话,读一点关于乙状结肠函数和逻辑损耗的内容。就是这样。我在参考资料部分有一些不错的链接。以后再做也没问题。
函数逼*
让我们直接从泰勒展开 Z= z 处的函数l(Z)**开始,不要担心它看起来是否吸引人。会让事情变得简单..

图一。泰勒级数/l(Z)在 Z=z 处的展开式。稍后当你看到图 3 时,你可以在图片的右下方看到一个小的图解。
这意味着,鉴于我们知道如何计算【l(Z)at【Z = a】,其一、二、三等阶导数 w . r . tZat【l(a),我们知道δZ;我们可以*似得到 l(Z=z) 其中Z=a+δZ,有些 val 接* a 。
例如,让我们说 l(Z) = Z 。 Z 的一阶和二阶导数分别为 2Z 和 2 。现在让我们说 a = 2 并且我们想要找到 l(Z=2.1) 。△Z= 0.1。让我们用泰勒展开式。
l(2.1) ~ l(2) + ((22)/1!)(2.1–2) + ((2/2!)(2.1–2) = 4 + 40.1 + 0.01
l(2.1) ~ 4.41。这就是,嗯,它到底是什么。酷!
注意,我只使用了上面表达式的一阶和二阶导数。第一,很明显,因为没有 Z 的三阶导数(是零—对吧?)因此第三项之后的所有项都将是 0。
第二,泰勒级数用作*似值。即使可能有更多有效的导数,我们也可以停在第三项(即直到二阶导数)。我们走得越远,分母和分子分别以指数方式增加和减少,所以不管怎样,它们并没有贡献太多。
现在, l(Z) = Z 已经不是那么有启发性的例子了吧?我知道,就像加油!对于 Z=a 的任意值,我们不需要泰勒级数来*似 Z 的值。咄!。其实,如果 l(Z) 对每一个 Z 都有一个固定的形式,而我们手边又有一个计算器,我们就再也不需要泰勒级数来进行一个“*似”了。
但是假设说 l(Z) 是 𝑒^Z (也就是 e 的 Z b.t.w 次方)而你想找 l(0.35) ,不用计算器。啊哈!抓到你了。🤓。但是你可以用泰勒展开式很容易地*似这个值。你知道 l(0)=1,δz = 0.35而且 e^Z 的一阶和二阶导数也是 e^Z.
所以l(0.35)~ = 1+1 * 0.35+1/2 * 0.35 * 0.35 ~ = 1.41125,已经相当接*正确答案 1.4190161 了。
这只是冰山一角。泰勒级数被广泛用于用较少的项表示函数,它在求极限、积分和最小值方面有应用。它还被广泛用于模拟自然力对自然界中物理规律的作用等。完全不同的话题。此外,有很多关于泰勒系列的博客。务必阅读它们。但不是现在!在你看完我的博客之后😀。
现在,让我们再挑战一下。比方说,我们想*似一个函数 l(Z=z) ,其中Z=a+δZ,但是δZ并不固定。啊?好的。坚持住。它的意思是,我们知道但是ZδZ可以变化。任务是推导出正确的△Z并由此得到下一个 Z s.t, l(Z=z) 是极小的,给定某些条件强加在什么值上△Z可以假定。**
参见下面的可视化

试图找到最小值 l(Z)的 Z 和δZ
现在,为了做到这一点,并且*似地【l(Z = Z)】,我们可以再次使用泰勒级数的技巧。给定,我们可以莫名其妙地计算出 l(Z=a) 及其一阶和二阶导数,我们可以找到最佳的δZ如果我们像下面这样求解。

图二。从泰勒展开式最小化得到函数 l 的最佳δZ 和最小值。
哇!简单对吗?所以如果选择△Z为-【G/H】,我们将得到次佳的 Z 为极小值【Z = Z】l(Z = Z)的值将为 l(a) -1/2(G /H)。
让我们把它放在上下文中。
我的图片(好,好,我的白板图片)

图三。不错——嗯?。您也可以在https://github . com/run 2/demystify-xgboost/blob/master/my board . jpg 找到此图片
这很像是电路板上的 XgBoost(或者更确切地说是 Boosting 算法)。别担心,我们会把它拆散的。我建议,把图片打印出来(来自 GitHub ),放在手边,以便你阅读博客的其余部分。一定要掩饰一段时间,看看你怎么看这件事。
比方说,我们手头有一个二元分类任务。最初,我们有一组样本,它们的已知监督标签 y 和默认模型分数值 y hat = 0(这意味着对于所有样本,默认概率值为 0.5;与 XGBoost 中默认 base_score 相同)。参见图 3 的左侧,以理解为什么使用 Sigmoid 函数,y hat = 0 得分给出 0.5 的概率。
下面是一个 sigmoid 函数,仅供我们参考。

图 4。Sigmoid 函数绘制概率值 p 与分数 y 的关系。为了达到 1.0 的概率,y 必须慢慢地从 0 移动到 5 左右。与获得 0 概率的情况正好相反。
现在给定 y hat = 0, 一组具有类似 c1,c2 特征的样本..c5,表示为 X ,以及已知的标签 y ,我们必须想办法修改y hats . t 对于标签为 0 的样本,它们向-5 移动,对于标签为 1 的样本则相反。让我们假设有一个函数可以让我们这么做。一个树函数,它会给我们下一个 y 帽子 s,目的是最小化一个损失函数l(XGBoost 上下文中也叫目标函数)?我们很快就会知道如何推导树函数。现在,我们姑且说它给了我们δy 帽子** s。**
所以无论你在哪里看到上面图 3 中的【f(x),那个 f ,就是一个树函数,或者简单的放一棵树。 f 由诸如树的深度( max_depth )、树叶中的最小样本权重(或 hessian 的和——我们很快就会知道)(min _ child _ weight)、在构造诸如 C1<v1(col sample _ by tree、colsample_bylevel、colsample_bynode 这些被称为树增强器参数。****
假设我们只有 5 个样本。在图 3 中,我们可以看到第一棵树 f1 有 4 个叶节点。我使用了一些说明性的条件,比如 c1 < v1 来构建树。没有条件标签的路径分别是对应标签路径的 非条件 。每个叶节点中可以有一个或多个样本。每个样本在叶节点上都有一个值。这被称为叶分数。这些叶子分数是树函数 f 对 X 的输出。
叶子中的所有样本将具有相同的权重、输出值或分数。(这与 CART 树中的叶子分数相同,以防你想到它)属于叶子的样本由它们的特征值如何与树函数 f 交互来决定。像树函数 f1 中的 x5,是在第四片叶子上,因为对于 x5,c1≥v1,c3≥v3。
现在,让我们开始用我们已经知道的来拼接图片。
如果你注意到,我们从所有样本的 y hat = 0 开始。 y 帽子 变量就像上面的【l(Z)中的 Z 。而 0 就像 中的一个 中的Z =一个** 。所有样品都有一个已知的标签**y。给定 y 帽子 和 y, 我们有一个如下的损失函数。这被称为逻辑损失函数。如果你还没有读过,那也没关系,只是假设对于二进制分类问题,这个函数总结了犯错误的代价或惩罚。所以我们试着把它最小化,以得到最好的模型。****

图五。我用 Mathpix 剪切工具直接从图 3 中的图片中剪切下来。使用它。很酷!。Btw,上面的 n,是样本数。
那么, y hat = 0 的损失是多少呢?如果 n 或样本数= 5?
*由于 y 可以是 0 或 1,并且 p 和 1-p 都是 0.5,因此对于所有样品,对数损失=-n * ln(0.5)=-5 -0.6931472 ~ = 3.465
显然,这只是所有样本 0.5 概率的损失。从这里开始,我们想做得更好,尽量减少损失。所以我们开始造树。我们的目标是使用我们的第一棵树 ft1 找到下一个 y 帽子 (即比默认值 0 更好的东西)。但是,我们必须在确保对 ft (树增强参数)施加限制的同时找到它。
假设我们已经找到了树 ft=1 。
现在,我们可以计算下一个更好的 y hat ,通过将每个样本的叶子分数加到 y hat = 0 。也就是说,叶子得分可以认为是△y 帽子** 。而 y 帽 0+△y 帽 0 给了我们 y 帽 1 。**
如果你在看图 3,你现在会明白在 t=1 时,样本具有不再等于零的 y hat 值。例如,样本 X1 有一个 y 帽 值= 0 + ft1(X1) 。样本 X3 和 X4 在第一棵树的同一片叶子上,具有相同的y hatvalue =0+ft1(X3)=0+ft1(X4)。诸如此类。

图 3 的相关部分
现在,我们可以再次计算损失。使用我们的损失公式。对吗?
只是这一次,不会是 n 乘以同一个 ln(0.5)值,因为,不同的样本有不同的 y 帽 s,我们来看一个图解。

图六。第一棵树后的损失。你为什么不做求和,并验证你得到相同的损失?我把正的δy hat 给了 x1,负的δy hat 给了 x2 和 x5。这不是随机的。这是因为,树会给他们分数,分别把他们推到 1 和 0 的最终目的地。对吗?。我将叶子 3 的δy hat 设置为零也是有原因的——我们在阅读时会更好地理解——但如果你注意到,叶子有 x3 和 x4,它们有相反的标签。x4 实际上在这个叶子中被错误分类了。由于这种混淆和错误的消除,叶子分数因此为 0。
太好了,我们把损失从 3.465 降到了 2.925。在这一点上不要太担心叶子的分数。我们会回来的。
此时,如果我们对损失还不满意,可以试试另一棵树。我们将有类似的先决条件和挑战。我们将有 y 帽子 (只是它不再全是零)。我们将会有一些树的限制。并且目标将是从 ft=2 s.t 得出一个δy hat,在 t=2 之后的损失使用 y hat 2 再次是给定前提条件下最小可实现的。

图 3 的相关部分。从树 1 到树 2。
这听起来很相似,对吗?寻找δZ,这将给我们下一个最好的 Z=z 其中 l(Z) 将最小。
让我们根据博客开头所示的泰勒展开式来编写损失函数,这样我们就可以*似计算下一个最佳损失和下一个最佳树,从而得到最佳的δy hats。
但是首先我们需要知道损失函数的一阶和二阶导数。它们分别被称为梯度和黑森。我跳过了梯度和 hessian 的推导,这有点不*凡,但是,它们非常简单和直观。如果你想看到一步一步的推导过程,请查看参考资料中的链接。

雾 7。Logistic 损失的梯度和 Hessian 分别为顶部和底部。但是究竟为什么二阶导数叫海森呢?有人知道吗?
太好了。因此使用图 5 中的损失函数,我们可以计算给定值 y hat 下的损失。 我们可以计算那个值的一阶和二阶导数,因为我们会从 y hat 知道 p (图 4)。我们需要找到下一个最好的。我们已经知道该怎么做了。对吗?我们还在等什么?
我们来形式化一下。
形式化 XGBoost
我们可以将损失函数写成

图 8。树 t 之后的损失函数,使用树 t 作为变量 ft 重写。y 是已知标签,y 是所有样本直到树 t-1 的叶子分数总和的向量。如果困惑,再看我图 3 的图片。
现在让我们像以前一样,用泰勒*似来分解它。

图九。损失函数使用泰勒展开和树变量 ft(xi)和正则化。
图 3 直观地解释了上面所写的一切,所以这应该很容易理解。任何困惑,请再次看到“我的照片”。
简单来说,树 t 后损失,取决于 y 帽 t ,也就是 y 帽 t-1 加上 ft(x)。 因此损失后树可表示为泰勒*似损失从【y 帽】t-1、、δ即【ft(x)。使用一阶和二阶导数,我们得到(1)的最终方程。
这里【ω(ft)】,代表对树函数/构建过程的不同约束和正则化。这其实是 XGBoost 非常重要的一部分。这是它比其他 Boosting 算法好得多的地方。像 max_depth 是一个约束,min_child_weight 是一个约束。然而,当正式化损失函数时,只需要考虑应用于叶分数或叶权重的 L1 和 L2 正则化。其他的是在构建树时由算法强加的。
所以重写

图 10。用树正则化参数重写损失函数。L 片叶子上的 n 个样本。注意,这里正则化应用于每个叶分数,而不是每个样本。这是有道理的,对吗?
但是,为什么我们需要调整权重呢?因为,权重或叶子分数,是推动 y 帽子 s 的东西,我们总是会有叶子,其中有混合的类,这意味着错误分类的样本。如果砝码太大,则可能会导致样品突然错误移动,从较好的 y 帽 到糟糕的 y 帽 。因此,控制权重将确保某棵树上的某条路径不会对 y hat 运动有太多发言权。如果树中的路径在某些局部条件下过度拟合了呢?稍后将详细介绍。
现在,我们知道 L1 正则化(由上面的最后一项表示,用α作为乘数),当最小化一个函数 w.r.t 到变量时,惩罚了它的变量的纯粹存在。它将试图使叶权重或分数 wj 趋向于 0。如果 wj 变得太小,我们的 y hat s 一点也不会变——对吗?。实际上,它会阻碍给出 wj > 0 的分数或模数的所有特征值条件。
这在 XgBoost 中并不常用。已经基于一些标准选择了这些特征,我们不希望仅仅因为一些叶子导致模数分数> 0 就让它们消失。取而代之的是,L2 正则化(倒数第二项)被广泛使用,它将允许叶子,但是阻止叶子权重过大。稍后在第二部分会有更多关于这个的内容。
回到家里,让我们只使用 L2 正则化和打破上述函数根据叶。然后通过最小化损失函数,让我们找到最优的δy hat或 ft(Xi) 或每个叶节点中的叶得分或叶权重。
首先,我们需要将所有样本的求和重新排列成所有叶的求和(每个叶内样本的求和)。为什么?因为正则化是对每片叶子进行一次。而损失是每个样本的。因此,我们对正则化因子的所有叶子求和,然后在每个叶子内,我们对样本求和。见下文。

图 11。最小化损失函数并找到每片叶子的重量。上面的 Sj 表示叶 j 中的样本。每个 j 或叶中的 ft(Xi)具有相同的值,由上面的 wj 表示。为了适应每个叶而不是每个样本的正则化参数,我们将求和重新安排为每个叶的样本求和。
好的,亲爱的。所以我们定义了每片叶子的最佳值 、wj 。现在我们也可以找到如下所示的最小损失。如上所述,L2 正则化是针对每片叶子的,而不是针对每个样本的。这很有道理,对吗?我们不希望正则化一个叶子中的每个样本。它们都有相同的重量。

图 12。L 叶树最小可能损失的推导。我跳过了几个步骤,但你几乎可以看穿它。
酷毙了。我们拥有一切来获得那个价值吗?我们总是从先前的状态(或先前的树)知道 y 帽子 s 所以我们知道pi;** 而我们也知道标签;因此,我们有一切来构建一棵树,并获得树叶的重量或分数。注意,上述损失是所有叶片 L 的总和,第三个括号内的表达式是单个叶片内的损失。**
被蒙蔽了!?
好吧,我骗了你,一点点!。在哪里?当在上面的图 11 中对函数求微分并等于 0 时。我哪里作弊了?当然了。叶子的数量。我的意思是,如果这是一个变量,我不能在区分和等同于总损失为 0 的时候忽略它。如果你已经明白了。聪明!!😎。
这确实不对。但是我们把 L 看作一个常数。也就是说,所有可能的树的叶子数量都是固定的。但这是不可能的,对吗?。从一堆特征中,假设一个最大深度为 6,我们可以有这么多不同类型的树,有不同数量的叶节点。
你是对的,但是那使它几乎不可能找到一个解决办法。所以我们考虑用最佳优先法来建一棵树。或者确切(贪婪)的做法。对于大多数数据集,这是 XGBoost 的默认 (自动)tree_method 。在这个方法中,首先,我们假设一棵树有一个节点。其具有一堆样本,并且损失是基于 y 帽子的先前状态来计算的。然后我们把那个节点分成两个节点 L=2,并遵循下面的过程。
假设 L=1 节点的损失为 lp 或损失母体。现在,对于该节点中的所有样本,我们遍历所有可能的列(使用树增强器参数中指定的列选择约束)及其值,并找到(column,value)组合以将其拆分为两个节点,其中 L=2 且 LossLC=(lc1+lc2)或 Loss children s.t, lp-lc 为正且最大值。也就是说,从 lp 到 lc 的损耗最大限度地降低。或者 lc 是损耗最小的。

图 13。既然我们知道 y hat,我们就知道 p。迭代所有列/值对,从而迭代所有 S1/S2 叶对,直到我们得到 lc 的最小值。这为我们提供了最佳优先方法中两个节点的下一个子树。
如果即使在考虑了所有列值元组之后,从 lp 到 lc 的损失不能减少,那么我们已经达到了节点的最佳损失。这个节点本身变成了一片叶子。否则,我们将树进一步扩展到下一个子树(直到我们达到最大深度),直到我们得到所有的叶子。
好吧,还记得吗?不久前,当我们在第一棵树后将损失从图 3 中的 3.465 减少到 2.925 时,我说,如果我们对损失减少不满意,我们尝试下一棵树?。好吧,但是为什么我们不能在一棵树上,用无限的深度得到最好的损失减少。还是最好的△Z遂 z 和 l(Z=z) 一气呵成?为什么我们需要建这么多树?
理论上我们可以尝试,无限深度,遍历所有可能的树。但是,我们不能保证只用一个函数就能达到绝对最小值。这也使得树和解决方案对变化非常敏感。然后,它变得对单个树的构建方式和整个训练数据过于敏感。这可不好。
这就是为什么 boosting 基于小步学习的哲学。想法是,保持低深度(最好低于 10),如果可能的话,创建数百棵树,一个接一个,一点一点地学习,直到我们在下一个树( 提前停止 )内不能再获得实质性的损失减少。
参见下面的可视化

在每一步,树构建函数 f 都受到一些规则的约束。在这个受约束的环境中,该算法正在寻找下一个最佳 Z,因此也是下一个最佳 y。该增量是函数 f 对样本及其特征值的结果。
此外,我们应该彻底使用子采样和列采样,以便每个新树具有不同的样本和列集,因此不存在与某些列、值、样本元组值的从属关系,从而在每个树中导致类似的分裂。
最后 Eta(学习率)
嗯,埃塔确实是人工合成的。它没有出现在上面的任何地方,因为它不是强制性的。这只是一个控制 delta 步长的聪明方法,而不涉及 lambda (L2)或 hessian 或 gradient 的复杂性。
η是介于 0 和 1 之间的分数。默认为 0.3。这将使δy hat或叶分数减少该分数。

这就是 Eta 的全部内容。t 代表一棵树,j 代表一片树叶。图 16。
通过保持δy hat为低,我们确保在样本 y hat 中没有突然的跳跃,并因此基于一些局部敏感的列值条件,由于在一些叶子中的局部损失最小化,概率。
仅此而已!理解 XGBoost 的数学是有难度的。让我们快速看一个可视化的表示。

直观地看损失和 Y 帽子如何从一棵树到另一棵树不断变化。图 17
所以,以上是我们所学的快速浏览。在左侧顶部,当 t=0,y hat = 0,pi = 0.5 时,所有样本都在同一点。一棵树接一棵树,单个样本的 y 值随着小的增量不断变化。基于总的损失最小化,这些增量可以是正的或负的。在每个采油树之后,在训练期间,测井曲线损失应该不断减少。然而,在某一点之后,LogLoss 可能开始增加。一些 y 帽可能与期望的方向相反,导致错误分类的样本。右边是 LogLoss,从一个较大的值开始,然后逐渐减小。这些是 XGBoost 使用 train 的观察列表和 logloss 的 eval_metric 进行训练时看到的值。图片的其余部分应该不言自明。
最后,当这样的模型用于预测时,对于未知标签样本,将样本落在每棵树上的所有叶子分数相加,以给出该样本的 y hat 分数。从 y hat 分数,使用 Sigmoid 函数,我们得到概率值,并因此基于阈值截止来标记。
快速测验
- 但是我们为什么需要埃塔呢?无论如何,它是综合的,求导和最小化数学不需要它!
- 为什么我不能是 1 岁?可以用 0 深度训练 XGBoost 吗?这是什么意思?会发生什么?
- 在我们使用深度为 0 的树的情况下,我们有或没有正则化或 eta 有什么关系?
- 黑森效应如何伽马或最大德尔塔步?
- 如何为二进制分类估计一个好的最小子权重?
- 我们应该使用阿尔法正则化吗?什么时候?
- 何时使用最小儿童体重或称体重?上面的数学在不*衡的班级情况下表现如何?
- 在不*衡的课堂情况下,当训练分布与看不见的分布不同时,我们应该如何处理体重秤的 pos 重量?
如果这些问题激发了你的探索精神,那么这就是第二部分的全部内容。
参考
所有资源文件都可以在
https://github.com/run2/demystify-xgboost/tree/master
** [## sigmoid 函数的导数\(\sigma (x) = \frac{1}{1+e^{-x}}\)
感谢为数学栈交换贡献一个答案!请务必回答问题。提供详细信息…
math.stackexchange.com](https://math.stackexchange.com/questions/78575/derivative-of-sigmoid-function-sigma-x-frac11e-x) [## 对数损失的梯度和海森如何计算?(问题基于一个数字示例…
我想知道 logloss 函数的梯度和 hessian 是如何在 xgboost 中计算的…
stats.stackexchange.com](https://stats.stackexchange.com/questions/231220/how-to-compute-the-gradient-and-hessian-of-logarithmic-loss-question-is-based) [## 逻辑回归:为什么是乙状结肠函数?
回答(第 1 题,共 12 题):在二项式回归中,我们希望将响应变量建模为以下变量的线性组合
www.quora.com](https://www.quora.com/Logistic-Regression-Why-sigmoid-function) [## 逻辑回归- ML 词汇表文档
假设我们得到了学生考试成绩的数据,我们的目标是基于以下因素来预测学生是否会通过考试…
ml-cheatsheet.readthedocs.io](https://ml-cheatsheet.readthedocs.io/en/latest/logistic_regression.html) [## 理解二元交叉熵/对数损失:一个直观的解释
有没有想过用这个损失函数到底是什么意思?
towardsdatascience.com](/understanding-binary-cross-entropy-log-loss-a-visual-explanation-a3ac6025181a)**
揭开 XGBoost 第二部分的神秘面纱
揭开 XGBoost 的神秘面纱
挖掘超参数
序幕
这是去神秘化 XGBoost 第一部分的延续。如果可能的话,准备一份打印件,因为我会在整个博客中提到它。
在这篇博客中,我将讨论我们在训练 XGBoost 模型时使用的概念和各种参数背后的直觉。很多时候,我们盲目的训练这样的模型。这个算法是如此的符合逻辑,正如你从第一部分中所理解的那样,即使盲目地使用所有的检查和*衡(正如我们将在下面讨论的),也很难得出一个草率的模型。
或者是?你怎么想呢?
在这篇博客的最后,我们应该能够更直观地看到参数,并在调整它们和推理为什么一个模型在看不见的数据上表现不佳时使用直觉。我将只讨论这个故事中的几个参数,其余的将在第五部分讨论。此外,你应该在第一部分中找到所有测验问题的答案。
我们开始吧..
直觉
梯度
我们从第一部分的数学中得到的最直观的东西是梯度的重要性。它是 XGBoost 如何创建和扩展树的基础。我们现在知道,叶分数=-G/(H+λ),节点中的损失与-G/(H+λ)成比例。拉姆达,记得吗?叶分数的 L2 正则化参数。
因此,为了减少从父节点到子节点的损失,我们需要减少子节点的损失,因此(带有负号)mod G 的值需要更大。g = p-y 的总和。因此,树函数需要找到列值条件,使得(p-y)的模和在每个子代中都很大。这发生在所有的(p-y)符号相同的时候,对吗?想想吧。
对,所以直觉上,一个好的分裂条件会试图将一个标签的样本分离到一个子节点中,而将相反标签的样本分离到其对应的兄弟节点中。它们混合得越多,( p-y)的和就越小。因此,良好的直观分割条件也将损耗降至最低。
再次直观地,权重或 delta 分数与梯度的负值成比例。这意味着δy hat将自身调整到梯度(或误差)的相反方向。这就是我们想要的!对吗?纠正错误。
随着这些树不断地校正整体误差,对于一个样本来说,【pi】(其从 y hat i) 不断地从一棵树变化到下一棵树。见第一部最后一张图。对于一个样本, y hat 可能随着它从一棵树移动到下一棵树而增加或减少。在每棵树的末端,()或渐变,就是那个样本的误差。或者是 i 的最后一个最佳预测值与真实标号之差。和【π-yi】的总和或误差(在一片叶子或覆盖物中所有样本的*均值👇)是保持控制所有树中的分裂逻辑的东西。**
这就是为什么我们说 XgBoost 从错误中不断学习。
粗麻布/封面
我们还在第一部分中了解到,对于二元 logistic 损失函数,hessian 是 p(1-p) 。在一个节点上,hessian 的和是 pi(1-pi) 的和。当 XGBoost 为二进制分类指定最小子权重时,该值被视为最小允许值。让我们想一想这个问题。
想象一下,在某棵树上,向下一定深度,有一个节点,当在某种条件下分裂时,给出两个节点,其中一个有 10 个样本。比方说,这些样本的 y hat 值,在进入树之前,就已经相当成熟,即 y hat t-1 s 接*自己的预期得分或者完全错误。让我们说 pi 因此,对于具有标签 1 的那些,已经在 avg 0.95 上,对于具有标签 0 的那些,已经在 avg 0.95 上。并且有一些错误分类的标签 1 样品具有 pi 0.05,反之亦然,标签 0 样品。
这片叶子值多少钱?就是~= 0.950.0510 ~= 0.475。即使有一些类 1 样本的 pi 在错误的一侧,反之亦然,对于类 0 样本,hessian 的和仍然是~= 0.475。
如果 XGBoost 的 最小子权重 设置为 1,则不允许此拆分。而不管它是否从所有可能的子节点中给出最低损失,这些子节点是从该节点上所有可能的特征值分裂条件中导出的。
凭直觉,一个低总和的黑森,或低 盖 意味着,我们正在考虑一个非常渺茫和局部的条件。低的 hessian 或 cover 会导致更高的 delta y hat s(因为它在分母中)的-G/(H+lambda)。给定默认的λ为 1,非常低的 hessian 几乎导致权重与梯度成比例。这种权重会对错误分类的样本造成大的错误分数移动(它们的 y 帽 将与它们的错误或梯度相反地移动,以及节点上多数类的样本,它们的 y 帽 将在期望的方向上移动,与整体梯度相反)。
如果,在分割后,每个孩子的样本量> 100;这样的分割是被允许的,因为黑森人的总数将远大于 1。0.950.05100 ~= 4.75.直觉上意味着。在如此大的样本量下,这种拆分更可能是有效的拆分,而不是过度拟合的拆分。我们也可以在看不见的数据中期待同样的特征。并且大的 hessian 将导致节点中所有样本的受控得分/权重(△y hat)。
或者,也可能是反过来。概率*均值为 0.85 和/或 0.15 的 10 个样本。黑森州的总和应该等于 1.275。在这种情况下,我们也没事。这是一个早期的分裂,大多数 T21π还没有趋向于 1 或 0。梯度很高,但会混淆,总的来说,最佳权重将导致受控的得分移动或增量。并且这种分叉不是过度配合的分叉。我们需要这样的分裂来开始校正梯度。
我很快就有了电子表格,它会让你想象这些动作。
因此,对于二进制分类,节点上的 hessians 的覆盖或和对样本的数量以及这些样本的概率(计算到最后一棵树)接* 1 或 0 是敏感的。概率越成熟(正确或错误),证明一个分裂所需的样本数就越高。
对于线性回归(实际上,这是一个很好的练习,如果你能再次计算线性回归的话),损失函数是均方误差,hessian 和为 1*n,即样本数。因此,对于线性回归,cover 就是一个节点上的样本数。
因此,为了形象化默认的 min child weight 为 1,认为需要至少 10 个样本在 pi 0.85 和 0.15 附*,或者至少 20 个样本在 pi 0.95 和 0.05 附*,至少 50 个样本在 0.98、0.02 附*,以此类推。如果您认为在您的用例中这是一个公*的节点纯度阈值,那么 1 是一个很好的数字。可以少去也可以多去。一般来说,不建议小于 1,除非你的样本量很小,只有几百个。
超过 的最小子体重 的 1 是安全的,保守的。然而,你爬得越高,矮树越难劈开。所以即使你有一个很高的最大深度,它也可能永远达不到那个深度。我们将很快讨论更多的深度。
梯度黑森权衡
你现在一定感觉到了,在 gradient 和 hessian 之间,有一场持续的拉锯战。渐变会尝试给出更高的 mod leaf 分数或 delta y hat s,而 Hessian 会降低分数或*均分数。
当一个模型刚刚开始,我们有高梯度和高 hessians 了。随着我们不断添加树木,我们有较低的梯度,黑森也变小了。事实上,在许多树之后,当大多数样本具有低梯度或误差时,hessian 几乎为零,唯一阻止我们爆炸权重或分数的是分母中的 lambda。
总的来说,这是一个控制的游戏,以便它永远不会太大,并根据每个节点上的误差在正确的方向上。
希腊字母的第 11 个
那么,对于 lambda 该怎么办呢?我会说,默认值 1 是一个非常好的值。它可以防止分数爆炸,同时也不会过多地降低梯度的权重。
如果我们增加λ,虽然没有明显的伤害。权重或叶分数将更小,因此模型将学习得更慢。将会有更多的树,更多的内存,需要更多的时间。但对模型没有伤害。但是,如果我们减少它,事情会反过来,我们可能会损害模型。怎么会?我们会在讨论 eta 的时候讨论。
但是,想想看,如果 lambda 小于 1,并且 y hat() s 非常接* 1 或 0(导致 hessian 的和几乎为 0 ),我们最终会得到分数或δy hat(,这可能超过样本上的误差或梯度。对吗?因此,我们将来回超越梯度。听起来不太好,对吧?**
Base_Score 和零深度树
现在我们知道了树木是如何生长的。如果我们有 0 深度的树呢?比如为什么要尽量把损耗从 lp 降低到 lc 。当我们在图 12 中求导时,L 或叶片数也可能是 1,对吗?完全正确,是的,我们可以在 XgBoost 中训练深度为 0 的树——试试吧。
但是会发生什么呢?既然,所有的样本都会在单个节点上,得到相同的分数,想一想,损失最小化的最好方法会是什么?纯直觉说,我们将需要根据类的分数改变 y hat s。假设我们有 200 个 0 类样本和 20 个 1 类样本。直觉上,我将开始从 0 到-5 减少所有样本的 y hat s,因为类 0 样本在数量上更大。
如果我们选择 w=-G/(H),就会发生这种情况。如果我们将那个加到 y hat = 0,我们将得到所有样本的一个分数,这将导致最小的对数损失,并且考虑到上面的例子,δ或 w 将肯定是负数。只是给你那个数字, y hat = -1.63 将是所有 220 个样本的最佳 y hat ,导致最小 LogLoss。
那么,XgBoost 会训练一轮就停下来吗?(假设我们停止在最佳对数损失)。如果我多轮呢?是的,它会停在一轮,但是,只有当我们不使用 lambda。如果我们使用 lambda 正则化和 eta (学习速率),XGBoost 将在几轮中不断减少 LogLoss,然后一旦无法再减少时,它将停止。为什么?因为我们知道λ和学习率都减慢了实际的△y 帽子** 或分数。**
所以如果 w = -G/H,它将在一轮后停止,但如果 w = eta*-G/(H+1),它将继续几轮。
很酷的事实——对吗?😀。那么,我们为什么不用它呢?因为那只会给我们一个取决于阶级分布的概率。我们可以通过简单的数学计算发现。我们不需要任何功能。当我们考虑到某个事物属于一个类的概率取决于它的特征和价值时,我们需要在条件上进行分解。我们将立即拥有两个节点。L = 2。而我们以 gain =lp-(lc1+【lc2】)回到 LP 和 lc。当我们一棵接一棵地建立子树时,我们试图最大化收益。
事实上,给定 200:20 的类分布,从简单的数学和对数损失的最小化得出的分数(y hat = -1.63)可以用作 base_score 而不是 0。也就是说,只有当你认为阶级分布对最终概率有很大的发言权(偏差)时。但是请注意,这是假设您的训练样本类分布将始终与未知分布完全相同,并且每个预测都将以该偏差开始。所以——请小心使用。不推荐。
使用级联模型时,基本分数有时也会得到不同于 0 的值。就像相同的样本依次经过不同的特征集和/或模型,其中第一个模型的输出变成了第二个模型的偏差,等等。
最大增量步长
让我们用一些真实的数据来理解这一点。我在一个节点中创建了一个示例数据集。它在类别 0 中具有 200 个样本的标签分布,在类别 1 中具有 20 个样本的标签分布。在一个条件下,节点分裂成两个节点。一个有 185 个样本,另一个有 35 个样本。假设这 185 人中,有 180 人来自 0 班,5 人来自 1 班。35 人中,0 班 20 人,1 班 15 人。见下图。这实际上看起来像一个很好的分裂,对不对?子 1 中的多数分数类 0 和子 2 中的多数分数类 1。
我已经给了样本一些先验概率值,假设父节点在一些树之后。因此, y hat s 已经远离全= 0。我将大多数 0 类样本(150 个)的概率设为 0.1,并保留不同程度的误差或梯度(下面的第 2 行和第 3 行)。类似地,我将大多数 1 类样本的概率设为 0.9 (8),并保持不同的梯度(下面的第 2 行和第 4 行)。然后我计算了所有的 G、H、损耗和重量/分数,假设λ为 1。对于父节点和两个子节点。见下文。

节点根据某种标准分裂成可能的子节点。不*衡的数据。您可以在https://github . com/run 2/demystify-xgboost/blob/master/DeMystifyXGBoost-example 1 . xlsx访问该电子表格。你可以看到每个单元格上的公式,看看我是如何计算这些值的。玩弄样本数量和或概率。损失,重量,新的概率等将自动改变!😃
让我们深入了解一下 Gs 和 Hs。
*对于 p= 0.1 的 0 级,H = 0.1 (1–0.1)= 0.09。G =(0.1–0)= 0.1。
对于 p = 0.9 的类 1,H 再次= 0.09,G =(0.9-1)=-0.1。
所以 G 的 mod 比 H 大,对吧?因此,如果我们有许多样本是 0 类,很少样本是 1 类,那么具有大多数 0 类样本的叶子将倾向于具有比 H 或 H + 1 高得多的 G。在示例中,我们可以看到在子节点 1 中,来自类 0 样本的 G 是 32.5 (K20)。对于 1 类样品,只有 1.6 克的一点点抵消。h 是 21.71。因此,我们最终得到一个权重或分数或δy hat=-1.36
如果我们允许这种分割,并且子节点以叶子结束,则子节点 1 中的所有类 1 样本将具有-1.36 的δy 帽** 。这意味着,被错误分类的第 1 类样本的概率将突然以相反的方向跳跃(与它们的梯度相反)。例如,2 个类别 1 样本将从概率 0.9 跳到 0.7。看到红色标记。**
这就是最大增量步长的用武之地。如果最大增量步长设置为 1,则不会发生上述分割,即使它导致最低 lc 。这将迫使算法搜索其他特征值组合,其中 lc 可能更高,但是分割将使得分数变化更小。
请注意,在上面的 excel 中,在损失母公司计算中,我没有使用我们在数学部分计算的 1/2 因子-1/2G /(H+1)(图 12 第一部分)。XGBoost 不应用这个 1/2 因子,因为它是父节点和子节点的常数乘数。
学习率
我们已经知道,eta 是要乘以叶分数的分数,通过保持【delta y hat】为低,我们可以确保基于一些局部敏感的列值条件,不会由于某些叶中的局部损失最小化而导致样本概率突然跳跃。
从上面 max delta step 题目中的例子来看,如果我们使用 eta 为 0.3,那么叶子分数和 delta y hat s 就会降为-1.360.3 = -0.4 和 0.0350.3=0.01。给定一个 最大增量步长 1,这是一个允许的增量。
因此,从子代 1 中的类别 0 误分类样本中,两个红色标记的样本将仅移动到 2.2–0.4 = 1.8 的 y hat ,概率为 0.85;相比于 y hat 而言,没有 eta 的概率分别为 0.84 和 0.7。因此,整体学习速度较慢(对于正确分割的样本),但误差较小(对于错误分割的样本)。
这里的关键问题是——eta 仅仅控制学习的速度吗?也就是说,它是否只会影响所需树木的数量。较大的数字为较小的η反之亦然?答案是否定的。
由于这种方式,每次分割查看梯度,并考虑其他因素,如最大增量步长、gamma(见下文)、最小子权重和其他树增强器参数,很可能高的 eta 或 eta =1 将导致算法进入不能再减少损失的位置(想想超过凹形损失曲线的谷值),并且基本上停止在非最佳的评估度量值。当λ从 1 减小时,可以看到相同的效果。
底线是,保持低 eta 没有坏处,除了学习速度慢。保持较高的 eta 可能会导致较差的模型。显然太低的 eta,像 0.01 也是不推荐的,因为我们的模型将保持几个小时的训练。因此,默认值 0.3 是一个好的开始,我们可以稍微降低它,看看评估指标是否更好。在这个去神秘化系列的第三部分中会有一个关于这个的部分。
微克
这就把我们带到了伽马射线。γ,再次,树增强参数是最小增益,或 lp-(lc) ,或 lp-(lc1+lc2) ,允许一个节点进一步分裂成两个以上的节点。让我们像下面这样改变上例中每个子节点中类 0 和类 1 的样本数。这是一个糟糕的分裂。我们在每个节点中有几乎 50%的 0 类样本,1 类样本也是如此。我再次计算了每个节点的 G H 和损耗。

节点根据某种标准分裂成可能节点。低增益。您可以在https://github . com/run 2/demystify-xgboost/blob/master/DeMystifyXGBoost-example 2 . xlsx访问该电子表格。你可以看到每个单元格上的公式,看看我是如何计算这些值的
我们可以看到,增益或者说 lp-lc 现在是= 0.966。上例中的增益约为 7。直觉上,这种分裂看起来也不太好。如果 gamma 设置为 1,这种分割将被排除。如果该增益是从所有列值组合中可获得的最佳增益,则该节点根本不会分裂。它将成为一个叶节点。
总体来说, lp 和 lc 依赖于-G/(H+λ)。因此,确保良好的损失减少基本上意味着获得一个分裂,其中在分裂的每个子代中有一个显著的 G. Or,相同符号(+或-)的梯度。我们在讨论梯度的时候已经讨论过了。
找到允许的最佳伽玛或最小增益并不容易,低于最佳伽玛或最小增益,就不允许分裂。我们需要真正确定我们的数据大小和分布,才能开始使用它。但是,如果“最大深度”设置为较高的值,具有正的 gamma 值,将会自动修剪树,这样就不会有不必要的分割,并且损失减少非常少。
即使我们不设置γ,算法的固有特性,即寻找具有最大增益的分裂,将避免低增益分裂。伽马射线是额外的保护,以确保树木是保守的。特别好使用,如果我们计划使用许多保守的模型,然后集合它们。
最小儿童体重和伽玛之间经常会出现混淆。如果你已经到达这里,希望没有这样的困惑。如果你注意到例 2 中的孩子 2,hessian 的和是 9.6 (K42)。如果最小子体重为 10,这将成为无效的分割。最小子重量确保一片叶子有足够的覆盖,从而控制重量或分数。Gamma 确保我们不会分割节点,这样从父节点到子节点的整体增益会非常低。所以他们不一样。
秤 pos 重量和 AUC
好吧,这个,我必须承认很难理解。我用了几次,但不知道它的头或尾,每次都有罪恶感。但是现在我们已经掌握了所有的数学知识,尤其是 excel 表格,这应该就像“吃米饭和扁豆汤”一样简单。
首先,我们再回忆一下 y hat 对概率的影响。

乙状结肠函数。图 17。
如我们所见,对于具有类别 1 或正标签的样本,在T5 处,y hatT7 为~= 5,它们几乎被完全分类。所以对于所有这样的样本,树中的△y 帽 s 应该是把 y 帽 s 从 0 推到 5。因此δy hat 应该是正的。对于类别 0 的样本,情况正好相反。****
第二,逻辑损失函数的本质是惩罚错误,而不是欣赏正确的事情。查看 ML 备忘单中关于物流损失以及 yln(p)或(1-y)ln(1-p)如何惩罚错误的参考资料。为了快速了解,请参见下面代表 yln(p)的图片。(1-y)ln(1-p)看起来肯定和你想象的一样。

yln(p)与 p 的关系。可以看出,当标签 1 样品的 p 较低时,损耗非常高。极端。
这种惩罚和纠正在模型中根深蒂固。在每次分割时,XGBoost 将尝试纠正错误分类的样本,而不是将已经做得很好的样本推到它们的期望值。
如果我们有一个坏的分裂,这是反对这种惩罚和纠正的,就像上面的例子 2,你会注意到,δy hats 有可能没有遵循期望的运动性质。两个子节点都有δy 帽** s 为负。然而,如果您注意到示例 1,子 1 的δy hat具有更多的类 0 样本,具有负值,而叶 2 的相反情况具有更多的类 1 样本。这也说明我们的分裂很糟糕。**
现在,在一个不*衡的阶级情况下,有时,基于我们想要达到的目标,上述惩罚和纠正并没有很好地发挥作用,即使是在一个好的分裂中。如果你注意到,例子 1 中的孩子 2 只有 0.03(没有 eta 和 0.01 有 eta)正δy hat移动。而孩子 1 具有 1.36 的负运动。这种对少数类样本的受限移动是不期望的,特别是,如果我们更关心阈值处的分类准确度,而不是损失的总体减少。
让我们稍微讨论一下。
第一,为什么在具有多数类 1 样本的子或可能的叶子上,δy 帽** 如此小?。这是因为几乎没有任何总体 g。即使它是具有多数分数类别 1 样本的叶子,也总是会有一些错误分类的类别 0 样本。由于与类别 1 样本相比,类别 0 样本如此之多,即使错误分类的样本也可能与正确分类的类别 1 样本一样多——因此它们将抵消总体 g 的很多。因此小δ帽 。**
相反,分数类 0 样本占多数的孩子,拥有大量样本。总体梯度严重偏正(K33 处为 27.7)。错误分类的 1 类样本非常少,超过了这个梯度。并由此,δy 帽子** 相当高且为负(-1.27)。**
所以 XGBoost 会因为样本数量而有偏差。它正在努力纠正错误。因为有如此多的类 0 样本,所以忽略将类 1 样本推向 1。它更关心的是将类 0 样本推向 0。
这将降低对数损耗。但是分类正确或不正确的第 1 类样本将会与错误分类的第 0 类样本混合在一个小概率范围内。将不会有一个强有力的门槛将它们区分开来。
如果我们更关心 FPR 的分类或 TPR 的准确性,上述行为就不太好。大多情况下,在不*衡的阶级情况下,积极的阶级是罕见的。比如预测地震。或者对恶意软件进行分类。这些模型需要在低 FPR 下运行,因为将一个干净的文件称为恶意软件并删除它,远比放过一个恶意软件要严重得多。
对于这种情况,更重要的是获得正确分类的阳性标记的样品,尽可能远离阴性标记的样品。因此,我们有一条分界线或阈值,在这条分界线上,较低的 FPRs 具有较高的 TPR。
这条线在哪里(在 0 和 1 之间)以及个体概率在哪里并不重要。即使所有 0 类样本都在 0.7 和 0.91 之间,所有 1 类样本都在 0.85 和 0.95 之间,我们也可以有一个良好的阈值,比如说 0.9。但是对数损失会很严重(见上图),因为 0 类样本离 0 很远。但是在我们的用例中,这可能没问题。
所以有时候,我们希望算法更偏向于在截止点给我们更好的分类,而不是总体上减少 LogLoss。
这就是 scale_pos_weight 的用武之地。在梯度和 hessian 中给予少数类更多的权重,以便这些样本以更大的跳跃更快地远离多数类样本。
scale_pos_weight 定义为= s1 =(负样本总和)/(正样本总和)。但是没有硬性规定。这取决于与多数样本相比,你对少数样本的重视程度。有人说,对于高度不*衡的类,scale_pos_weight 应该是 s2 = sqrt(负例之和)/sqrt(正例之和)。我们可以选择值> s1 和< s2,并尝试最符合我们评估指标的值。
让我们看看下面的例子 3。你不能真的看着它😀。从 Github 下载。

https://github . com/run 2/demystify-xgboost/blob/master/DeMystifyXGBoost-example 3 . xlsx。
这就是我所做的。
我采取了同样的 200:20 分配。在左边,我将样本分成两个节点,没有使用比例位置权重。在右边,我已经将样本分成两个节点,每个子节点使用相同的样本,但是这次对阳性样本赋予了额外的权重。
在左上角的父节点下,我首先展示了深度为零的树的效果。如果您注意到,我使用-G/H 来调整先前的 y hat 分数,以获得新的 y hat 分数。我还计算了假设深度为零的树的先前测井曲线损失和新测井曲线损失。你会注意到原木损失减少了。分数调整为-1.15。由于梯度变化,它不同于前面讨论的 200:20 分布的-1.63。如果您将 B3 到 JBOY3 乐队的所有概率更改为 0.5,您将看到-G/H 值更改为-1.63。
回到右边的两个子节点。秤位置权重用于计算 G 和 h。对于 1 类样品,其在计算中的存在由秤位置权重 4 加权。
如果你注意到,在没有秤重的情况下,分割后的原木损失从 61 减少到 51。而用秤称重量,原木损失从 61 减少到 55。因此,很明显,我们在使用称重法减少原木损失方面做得不是很好。但是实际的概率呢?
如果我们注意到,在左边,对两个孩子来说,重量或δy 帽子是负的。对于子节点 1,我们有一个很好的正 G。但是在子节点 2 中,即使它是一个 1 类的多数分数节点,总 G 也不可能是负的。因此,对于两个子节点,delta y hat 仅帮助类 0 样本。
在右边,这是一个不同的画面。我们在孩子 1 中仍然有一个负 G,但是它不那么明显了。δy hat与-1.27 相比为-1。但是奇迹发生在第二个孩子身上。现在我们的重力指数是负的-13.4。因为阳性标签样品上的额外重量。这导致正的δy hat,这将把正确分类的 1 个样本推向更高的 y hat 值,从而在它们和其他样本之间产生空间。
为了证明我的观点,我写了一些代码来找出有权重和无权重两种情况下的 FPR/TPR/阈值,并绘制它们的 ROC。(您将在本系列的第四部分找到代码)。对于这些计算,我需要样本的最终概率。我假设两个子节点都以叶子结束,因此它们的最终概率可以从它们之前的分数(B2 到 J2 或 N4 到 V4)加上δy hats(K39 K72 用于无权重的子节点,W41 W74 用于有权重的子节点)中导出。
这是中华民国的样子。带和不带秤的 Pos 重量。

3 个样本的 ROC 图。有秤显示重量和无秤显示。
如您所见,在 TPR 与 FPR 的早期 FPR 数据中,带秤重的模型胜过不带秤重的模型。这只是一棵树。当在许多树的模型中使用比例位置权重时,这种差异更加明显。有秤重模型的 AUC 为 0.956875,无秤重模型的 AUC 为 0.941375。
如果不使用秤 pos 重量,而是对单个样品进行称重,则适用相同的概念。在这种情况下,每片叶子中每个样本的梯度和 hessian 乘以样本权重。因此,对于第 I 个样本,gi = wi(pi-yi)和 hi = wi(pi)(1-pi)。对于多标签分类,我们可以根据需要调整所有样本的权重。
此时可能会出现一个问题。如果当我们被 AUC 困扰时,我们为什么不将其最小化,而不是 LogLoss。答案是,我们不能,因为 AUC 不是我们可以区分和等于零的东西。然后,可以在不同的操作点(即 FPR 值)获得 AUC 值。如果我们的目标是优化一个模型,仅仅是为了在一个操作 FPR 范围内增加 AUC,那么这些树将会过度符合那个特定的标准,因此将会失去一般性。因此,通过使用加权,我们可以增加 AUC,同时保持在优化日志损失的范围内。
培训课程分布与真实课程分布
在我们结束这个话题之前,还有最后一点。当培训课程的分布与真实课程的分布不同时,我们所学的知识如何发挥作用?在上面的 200:20 训练课分布的例子中,如果实时未看见的分布是不同的呢?显著地?比如五五开。或者就此而言,在任何这样的训练中,训练集(验证集)和看不见的实时数据的类分布是显著不同的?
希望你现在能明白,(特别是如果你已经玩过 excel 表的话)数学和损失最小化对职业*衡很敏感。因此,如果类别分布明显不同,模型将不会如预期的那样在实时不可见分布上执行(和验证)。
如果我们知道用于预测的看不见的数据是不*衡的,在我们开始使用体重秤之前,我们需要对它的不*衡程度有一个合理的认识。训练数据不必具有与未知数据相同的分布。更多的时候,我们有大量的回顾性训练数据,其中我们可以有更多的少数民族类样本。在这种情况下,我们可以继续使用整个数据并适当地调整权重或缩放 pos 权重,或者我们可以随机缩小类别以匹配未知的实时数据类别分布并创建多个模型和集合。
例如,如果我们在训练中有一个 200:40 的分布,但是我们知道在看不见的数据中有一个 200:20 的分布,我们可以创建两个 200:20 分布的模型并集成它们。或者,我们可以继续使用 200:40 的训练数据集,但是将体重秤位置权重更改为 sqrt(200)/sqrt(20)*1/2。引入最后 1/2 因子是因为训练集中的阳性样本数量是真实数据中的两倍。
这意味着,当你在训练数据中获得越来越多的少数类样本时,你可以慢慢减少你的体重秤位置权重。您将获得验证集和维持集或训练数据的可比 AUC。
要注意的主要事情是,维持集应该总是具有与真实的不可见数据相同的类分布。这样,在发布模型之前,您可以随时验证 AUC 或 LogLoss(无论您的评估指标是什么)在维持集上的表现是否符合预期。
在我写作的时候,我觉得,也许我会在我的系列文章的第 6 部分中详细讨论如何在 XGBoost 中处理不*衡的数据。深入地。
谢谢
这就是伙计们,在这个职位。下一篇文章将展示如何快速构建一个 docker 容器,在其中你将能够运行几乎任何 ML 内容,并在 Jupyter Lab 中使用 Jupyter 和 R。这将是第四部分代码的基础,在第四部分中,我将使用真实数据并构建模型来展示我们在第一部分和第二部分中讨论的所有内容。
参考
所有资源文件都可以在
https://github.com/run2/demystify-xgboost/tree/master
** [## sigmoid 函数的导数\(\sigma (x) = \frac{1}{1+e^{-x}}\)
感谢为数学栈交换贡献一个答案!请务必回答问题。提供详细信息…
math.stackexchange.com](https://math.stackexchange.com/questions/78575/derivative-of-sigmoid-function-sigma-x-frac11e-x) [## 对数损失的梯度和海森如何计算?(问题基于一个数字示例…
我想知道 logloss 函数的梯度和 hessian 是如何在 xgboost 中计算的…
stats.stackexchange.com](https://stats.stackexchange.com/questions/231220/how-to-compute-the-gradient-and-hessian-of-logarithmic-loss-question-is-based) [## 逻辑回归:为什么是乙状结肠函数?
回答(第 1 题,共 12 题):在二项式回归中,我们希望将响应变量建模为以下变量的线性组合
www.quora.com](https://www.quora.com/Logistic-Regression-Why-sigmoid-function) [## 逻辑回归— ML 词汇表文档
假设我们得到了学生考试成绩的数据,我们的目标是基于以下因素来预测学生是否会通过考试…
ml-cheatsheet.readthedocs.io](https://ml-cheatsheet.readthedocs.io/en/latest/logistic_regression.html) [## 理解二元交叉熵/对数损失:一个直观的解释
有没有想过用这个损失函数到底是什么意思?
towardsdatascience.com](/understanding-binary-cross-entropy-log-loss-a-visual-explanation-a3ac6025181a)**
应对数据灾难
在重大灾难中,您实际上可以做很多事情来挽救和改进您的数据产品。

大多数灾难都可以挽救数据项目。图片来源:汉斯·克劳斯,我们都算
您已经投入了大量的时间、金钱和精力来设计您的数据项目。你已经有了数据收集工具、分析计划和一个重要的研究问题。进入一个大的,完全破坏性的事件。您的数据项目——无论是社会部门的监测和评估、政府部门的循证决策、UX 还是企业部门的产品设计研究——都已跌落悬崖。你能做什么?在您从胎儿位置展开之后,实际上有很多事情可以做,以便在重大中断期间挽救甚至改进您的数据产品。
我有一些经过试验和测试的策略,可以帮助你的数据项目在新冠肺炎和所有相关影响的时候回到正轨。在经营一家数据咨询公司多年后,我曾经经历过数据灾难。在海地地震期间,我和我的团队与大型基金会和公司合作,开发紧急数据收集的新工具和保存地震前收集的数据价值的新方法。在孟加拉国 hartals(社会动乱)期间,我们与当地的国际发展组织和非营利组织合作,寻找至关重要的新方法,利用我们为不同目的收集的数据来回答新出现的问题,并找到在几乎完全关闭的情况下继续收集可靠数据的方法。在巴基斯坦的洪灾期间,我们与巴基斯坦政府和当地协会合作,建立了新的统计模型,以利用现有的、状态不佳的数据库,专注于保持社会响应知识的流动。
让我们看看,在当前的世界形势下,我们如何继续构建有用的、合乎道德的、可行的数据产品。
当我们的数据项目遇到重大中断时,我们需要切实可行、易于管理且严格的初步恢复措施。目标是尽可能多地保留您当前拥有的数据的价值,并以现在有意义的方式分析和理解它。首先确定三个基本要素会有所帮助。你在这三个方面的当前状态是你前进的起点。
- 你的研究问题怎么样了?
- 您当前的数据收集设计和方法可以通过哪些方式进行调整?
- 你的分析计划仍然是适当的和可行的吗?
更改数据收集模式
如果你没有收集太多或任何数据,你可能在适应方法上有最大的灵活性。首先,考虑改变你的数据收集模式。在新冠肺炎焦点小组时代,面对面的 UX 访谈和挨家挨户的数据收集并不是一个好的选择。有很多工具可以远距离收集可靠的数据。使用短信数据收集工具,使用手机数字调查,使用谷歌表格。我们尝试过的一个非常成功的选择是回到电话数据收集。这通常有两个目的——数据收集和个人联系支持。
更改数据收集设计。
如何收集数据的设计通常是某种抽样计划。这是您希望以有目的、有组织的方式收集数据的方式,以确保您的数据中所代表的人是您需要回答问题的人。这些设计中的大多数,像 RCT(随机对照试验)和分层或整群抽样,很可能不再是一个选项。我们在灾难或冲突情况下成功使用的两个设计是滚雪球抽样和激励抽样。如果您正在收集数据,减少您的广义采样工作,增加对收集最重要的剩余样本的最后一点的关注。对现有数据进行快速分析,引导您找到最需要的样本。
改变数据收集工具的设计。
一旦你适应了你的数据收集模式和设计,你就可以重新考虑你计划使用的数据收集工具了。根据多年的经验,我会提前告诉你——这可能太长了。减少问题的数量。并改变题型。如果你没有收集很多数据,你可以在不丢失数据的情况下修改这些。如果您已经收集了数据,可以考虑对您现有的数据做一个非常快速的高级分析,看看顶线趋势是什么。这可以帮助您了解哪些问题或工具的哪些部分产生了最有用的信息。保留那些部分。丢弃其余的。如果您已经完成了数据收集,请返回到您的数据中,尽可能详细地记录所有特定的时间、日期和地理位置。当您进入分析阶段时,您将需要这个来调整灾难影响。
寻找其他数据来源。
在冲突、灾难和疫情时期,合作总是关键。首先,我们差不多都在这种情况下。和你的关系网、你的资助者的关系网、你公司的其他分支机构和合作伙伴谈谈。看看谁的数据可以填补你数据中的漏洞,反之亦然。有很多关于隐私的规定需要得到尊重,在这些范围内,通过谨慎和慷慨的数据共享可以做很多事情。这也是考虑购买数据的时候,特别是如果你不再能够花费部分预算来收集数据。开放数据也是一种有价值的资源,有助于增强数据集的实力。请记住,无论何时您从外部来源获取数据,都必须通过数据传记对其进行审查。
你的分析计划仍然是适当的和可行的吗?
在动荡时期的分析阶段,你可能会面临许多问题。其中最常见的是:您的样本比您计划的要小,样本不能代表您希望了解的人,数据可能没有以您计划的速度或时间表收集,以及数据可能缺少结束线或“后”轮收集。
如果数据样本太小,可以使用专门的分析技术来优化所需的信息类型。在你所处的情况下,尽可能多地挤出知识。使用什么技术将取决于您的独特情况,但有些包括贝叶斯技术和小面积估计技术。您还可以将您的数据与其他数据集相结合,并使用针对这一事实进行调整的分析技术,这些技术通常也是贝叶斯。
即使在危机不太严重的时期,不具代表性的样本也比我们大多数人愿意承认的要普遍。是的,你的 RCT 可能已经结束了,但是你仍然可以转而使用为观察数据设计的因果分析方法。根据具体情况,混合效应模型、因果图、贝叶斯分析、一些匹配分析都是很好的起点。
混合效应模型(也称为分级线性模型或多级模型)对于没有在您计划的时间框架内收集的数据也非常有用。像这样的数据经常变得不*衡,这些技术可以帮助解决这个问题。
丢失底线、帖子或后续数据是最具挑战性的数据灾难情况之一。这是混合效应模型——尤其是非线性模型——可以帮助你估计最终会发生什么的另一种情况。你也可以研究荟萃分析。最终,这可能会让你回到第一步,调整你的研究问题。
您在数据项目上投入了大量的时间、精力和资源。虽然结果可能不像你预期的那样,但仍然有很多方法可以在紧急情况下利用你的能力,回答有意义的问题。
利用聚焦 Tversky 损失处理类别不*衡图像数据集
局灶性特沃斯基损失
课堂不*衡问题的损失比较以及为什么聚焦特沃斯基损失可能是你的最佳选择
当试图训练分割网络时,类不*衡数据集是经常遇到的问题。我第一次训练图像分割模型时,马上就获得了超过 96%的准确率。要么是我在不知不觉中取得了自第一个 CNN 成立以来最大的突破,要么是我的方法有问题。
我很快意识到,要分割的像素只占图像总像素的很小一部分。该模型所要做的就是预测一个全黑的图像(也就是没有分割),并且获得了超过 90%的准确率。这是在大多数图像分割任务中遇到的常见问题,其中背景类比其他类大得多。
在这个故事中,我讲述了用来处理班级失衡问题的技巧,以及为什么集中精力学习可能是你最好的选择。
概述
- 处理阶级不*衡的损失
- 什么是特沃斯基指数?
- 局灶性特沃斯基损失
- 结论
1.处理阶级不*衡的损失
a .加权二元交叉熵
通常用于处理类别不*衡的损失之一是加权二元交叉熵。正常的二值交叉熵的关键在于,它在计算损失时*等地考虑所有像素。在 90%的像素为 0 而只有 10%的像素为 1 的掩码中,即使网络错过了所有的 1,它也会收到较低的损失,这意味着网络没有学到任何东西。
加权二进制交叉熵(WBCE)试图通过加权正类来解决这个问题。

p(0 类)= p̂,p(1 类)= p
对于网络预测的每个 1 级,BCE 将 log(p) 加到损失上,而 WBCE 将𝜷log(p)加到损失上。
因此,如果β > 1,类别 1 的权重较高,这意味着网络不太可能忽略它(较少的假阴性)。反之,如果β < 1, class 0 is weighted higher, meaning there will be lesser false positives.
By controlling, the value of β, you can reduce the problem of class imbalance by weighting the smaller class higher. However, the optimal value of β is hard to ascertain and requires many rounds of trial and error.
Pros: Simple smooth loss surface that is fast in training
Cons: Difficult to optimise and find the sweet spot
b .骰子系数
众所周知,Dice 系数是图像分割的首选评估指标,但它也可以用作损失函数。虽然没有像二元交叉熵等其他损失函数那样广泛使用,但 dice 系数在处理类别不*衡时确实很神奇。
与 BCE 不同,dice 系数只考虑分割类,不考虑背景类。像素被分类为真阳性(TP)、假阴性(FN)和假阳性(FP)。

dice 系数是预测遮罩和地面实况的重叠的度量。因为它不考虑背景类,所以它不能支配较小的分割类。dice 系数输出[0,1]范围内的分数,其中 1 表示完全重叠。因此,(1-DSC)可以用作损失函数。
考虑到 dice 系数的最大化是网络的目标,直接使用它作为损失函数可以产生良好的结果,因为它在设计上对类不*衡数据工作良好。
然而,dice 系数的一个缺陷是存在爆炸梯度的可能性。在训练的早期,dice 系数接*于 0,这可能导致训练中的不稳定性,因为网络对权重进行大的改变会导致梯度爆炸。然而,使用批量规格化和 ReLUs,这很容易管理。
优点:无需手动优化任何参数,轻松解决等级不*衡问题
缺点:潜在的梯度爆炸,通常比 BCE 训练慢
2.什么是特沃斯基指数?
Tversky 指数(TI)是一种不对称的相似性度量,是 dice 系数和 Jaccard 指数的推广。

(1 — T1)可以用作损失函数
特沃斯基指数增加了两个参数,α和𝜷,其中α + 𝜷 = 1。在α = 𝜷 = 0.5 的情况下,它简化为 dice 系数。如果α = 𝜷 = 1,则简化为雅克卡指数。
通过设置α > 𝜷的值,可以更多地惩罚假阴性。这在高度不*衡的数据集中变得有用,在这种情况下,对损失函数的额外控制级别比正常的 dice 系数产生更好的小规模分割。
虽然 tversky 指数只是对 dice 系数的一个简单改进,但它可以证明在需要更精细控制的边缘情况下是有用的。
在 Salehi 等人的论文使用 3D 完全卷积深度网络进行图像分割的 Tversky 损失函数中,tversky 损失用于获得多发性硬化病变分割的最理想性能,多发性硬化病变分割是典型的类别不*衡问题。

不同损失版本的绩效比较。注:α和𝜷分别控制 FPs 和 FNs 本文与上图相反。
3.局灶性特沃斯基损失
聚焦特沃斯基损失(FTL)是特沃斯基损失的概括。损耗的非线性特性使您可以控制在不同的 tversky 指数值下损耗的表现。

γ是控制损耗非线性的参数。当γ趋于正 ∞ 时,随着特沃斯基指数(TI)趋于 1,损耗的梯度趋于 ∞ 。当γ趋向于 0 时,损耗梯度趋向于 0,当 TI 趋向于 1 时。
本质上,γ < 1, the gradient of the loss is higher for examples where TI >的值为 0.5,迫使模型关注这样的例子。这种行为在训练接*尾声时可能是有用的,因为即使 TI 接*收敛,模型仍然有学习的动机。然而,与此同时,在训练的早期阶段,它会将较容易的例子置于较高的权重,这可能导致较差的学习。
在类不*衡的情况下,当γ > 1 时,FTL 变得有用。对于 TI < 0.5. This forces the model to focus on harder examples, especially small scale segmentations which usually receive low TI scores.

A plot of the FTL with varying values of γ. In the case where γ = 1, it simplifies into a stanard tversky loss
In the image above, the blue line is the standard tversky loss. The purple line shows the higher gradient and higher loss when TI >为 0.5 的示例,这导致了较高的损耗梯度,而绿线显示了当 TI < 0.5.

(为 0.5 时较高的损耗。al,2018 )表格稍作修改,仅显示相关部分。γ的值在现实中是 3/4。本文用 1/γ代替γ。
上表摘自论文,一种新的病灶 Tversky 损失函数,采用改进的注意力 U-Net 进行病灶分割。
在公共汽车数据集中,FTL 在所有类别中都有显著改善。在国际标准行业分类数据集中,尽管总体 dice 系数最高,但该模型没有最高的精确度或召回率。
虽然用 FTL 训练的模型可能不具有最高的精确度或召回率,但重要的是要注意,当用 FTL 训练时,精确度和召回率之间的*衡是最好的,这表明解决类别不*衡的目标得到了满足。最终结果是最佳的整体 dice 系数。
4.结论
聚焦特沃斯基损失是解决阶级不*衡的一个简单方法。尽管最佳参数值需要一些反复试验才能确定,但您应该会看到以下结果:
α = 0.7, 𝜷 = 0.3, γ = 3/4
Keras 实施
要获得预先实施了注意力、递归和初始层的 U-Net 的完整实施,请检查https://github.com/robinvvinod/unet/。
阅读熊猫 CSV 时处理多余的空格
为什么我们关心空白?内置熊猫功能,自定义处理。1M 测试数据的创建和性能测试。

我的同事说。csv 不是一篇论文,所以我们不希望逗号后面有任何空格(或任何其他分隔符)。同样的观点也适用于 rfc4180 的创建者,RFC 4180 通常被理解为 CSV 文件的指导方针。尽管如此,他们仍然是有创造力的开发者。csv 导出带有不必要的空格。这些额外的字符不仅增加了我们数据的大小,而且会带来更大的麻烦。
在本文中,我们将:
- 回顾我们为什么关注 CSV 中的空格
- 使用 Pandas 的
[read_csv()](#2362)方法设置基准 - 探索
[skipinitialspace](#0f5a)参数 - 试试正则表达式分隔符
- 由于报价问题,放弃正则表达式分隔符
- 对加载的数据帧应用正则表达式
- 测试
[str.strip()](#990f)在所有字符串列上应用的列方式 - 解释为什么 NaN 很重要
- 使用
[faker](#b1dd)生成 100 万行测试数据 - 测量每个算法在空白区域清理的速度和有效性
像往常一样,你可以和我一起使用包含所有练习的 Jupiter 笔记本来遵循代码,这些练习可以从 GitHub 下载。
为什么空白是一个问题?
- 比较失败
有和没有空格的字符串是不一样的。"ABC" != " ABC"这两个 ABC 并不相等,但差别很小,你往往不会注意到。如果没有引号括住字符串,您很难ABC != ABC。但是计算机程序在解释中是不会被腐蚀的,如果这些值是一个合并键,你将会得到一个空的结果。
2.NaN 值
空白字符串、空格和制表符在很多情况下被认为是熊猫中用 NaN 表示的空值。但是不确定数量的空格不会自动转换成 NaN 值,您可能会得到意想不到的结果,因为例如count(NaN) = 0而count(" ")= 1。
3.大小
尽管空白几乎看不见,但是在文件中堆积数百万个空白,它们会占用一些空间。其他时候,它们可能会溢出数据库列的大小限制,导致更好的情况下出现错误,并修整最后一个字符,该字符的位置被前面的空格偷走。
熊猫里的空格怎么处理?
让我们开始探索 Python 的 Pandas 库中处理 CSV 中空白的选项。作为基准,让我们简单地导入。使用pd.read_csv()功能的带空格的 csv。
为了描述如何处理空白,我们将使用一个 4 行数据集(为了测试每种方法的性能,我们将生成一百万条记录,并在本文末尾尝试处理它)。我们的数据集包含这些列:
- Id 标识每行
- 街道有起始和结尾空白
- 有前导空格的城市
- 工资是数字
- 日期有日期格式
data = """Id,Street,City,Salary,Date
1, 5th Ave. , Indiana, 100, 2020-07-01
2, Downing Street , San Francisco, 200, 2020-07-02
3, , New York, 300, 2020-07-03
4, 1600 Amphitheatre, New York, 400, 2020-07-04
"""
您可以看到数据包含不必要的空白,我们的目标是尽可能有效地删除它们。
这样我们就不必将这些数据存储到一个. csv 文件中,我们稍后会读取该文件,我们将使用io.StringIO(data).将它传递给 Pandas
df = pd.read_csv(io.StringIO(data))
为了衡量我们有多成功,我将创建一个函数df_statistics()(见下文),它遍历所有列并计算:
- 字符串列:每行中数据的总长度
- 数字列:所有值的总和
- 其他列:行数
可选地,如果提供了一个带有expected长度的字典,它会将测量的长度或总和与我在数据帧中显示为一行的期望值进行比较。我们的基准实现了:

比较实际长度和预期长度的最终熊猫数据帧

为了更好的可读性,让我们调换一下数据帧
def df_statistics(df, expected=None):
"""Calculates the length of all items in the column and determine column types
length of string
sum of numbers"""
res = {}
for col in df.columns:
if pd.api.types.is_string_dtype(df[col]):
# calculate the length of each row and sum it
# careful, you cannot .apply(len) to columns which contain NAN, because NAN are float. - see [https://stackoverflow.com/questions/51460881/pandas-typeerror-object-of-type-float-has-no-len](https://stackoverflow.com/questions/51460881/pandas-typeerror-object-of-type-float-has-no-len)
l = df[col].str.len().sum()
else:
try:# if it doesn't work, it's probably numeric value, so let's only sum
l = df[col].sum()
except:
l = df[col].count()
# assigne lenght to the "column_name_lenght" column
res[str(col) + "_lenght"] = l
# if a dict with expected values was provided, let's use it to compare with real values
if expected:
res[str(col) + "_diff"] = l-expected[col]
# review the type of the colunmn
res[str(col) + "_type"] = df[col].dtype
return res
使用 skipinitialspace
因为.read_csv()是用 C 写的,为了提高效率,使用这个方法的参数是处理空白的最佳选择。为此,有一个skipinitialspace,它删除了分隔符后面的所有空格。

使用 skipinitialspace 的结果*乎完美
因为 City 列只包含前导空格,所以它们都被删除了。Steet 列的最后一行也是固定的,只包含两个空格的那一行变成了 NaN,因为两个空格被删除了,pandas 本身将空格表示为 NaN(除非另有说明,见下文)。)
但是如何处理行尾的空格,即最后一个字符或数据和分隔符之间的空格。熊猫没有任何skiptrailingspaces参数,所以我们必须使用不同的方法。
正则表达式分隔符
你知道在熊猫中可以使用正则表达式分隔符吗? read_csv 文档说:
此外,长度超过 1 个字符且不同于
'\s+'的分隔符将被解释为正则表达式,并将强制使用 Python 解析引擎。注意,正则表达式分隔符容易忽略引用的数据。Regex 示例:'\r\t'。
在我们的例子中,我们可以尝试分隔符sep="\s*[,]\s*"。\s*表示任意数量的空格,[,]表示逗号。在 Jupiter notebook 中,还必须指定engine="pyhton",因为 regex 分隔符是通过 python 脚本处理的,而不是原生的基于 c 的代码。让我们来看看结果:

我们不需要的所有空格都被删除,所有列都有预期的数据类型
结果似乎很完美。所有不需要的空格都被删除(all _diff 列等于 0),并且所有列都具有预期的数据类型和长度。但闪光的不都是金子。
带引号的正则表达式分隔符
手册中有一个重要的注释:regex delimiters are prone to ignoring quoted data.
我们的数据没有被引用。但如果是的话,假设这条街会被引用:
data = """Id,Street,City,Salary,Date
1,**"** 5th Ave. ", Indiana, 100, 2020-07-01
2,**"** Downing Street **"**, San Francisco, 200, 2020-07-02
3,**"** **"**, New York, 300, 2020-07-03
4,**"** 1600 Amphitheatre**"**, New York, 400, 2020-07-04
"""
那么正则表达式分隔符不仅会遗漏引号内的空格,而且还会将引号视为数据的一部分,额外空格的数量甚至会增加:

正则表达式分隔符与带引号的数据进行斗争,这不仅导致数据集中保留空格,而且引号也被视为字符串的有效部分
如果引号是为了屏蔽字符串中的分隔符(在我们的例子中是街道名称中的逗号),使其不被视为分隔符,则会出现更糟糕的情况。" Downing Street, London "受引号保护的是一个包含逗号的有效字符串,但如果我们使用 regex 分隔符,它会认为还有另一个分隔符而失败:
Expected 5 fields in line 3, saw 6\. Error could possibly be due to **quotes being ignored** when a **multi-char delimiter is used**.
所以正则表达式分隔符真的不是一个选项。
之后应用正则表达式
我们仍然可以使用正则表达式,但只是作为第二步。我们将 CSV 读数分为 3 个步骤:
- 阅读。csv,考虑带标准
read_csv()的报价 - 替换空格
- 删除空格后,将“”转换为 NaN
为了方便地测量这种操作的性能,让我们使用一个函数:
def **read_csv_regex**(data, date_columns=[]):
df = pd.read_csv(data, quotechar='"', parse_dates=date_columns)
# remove front and ending blank spaces
df = df.replace({"^\s*|\s*$":""}, regex=True)
# if there remained only empty string "", change to Nan
df = df.replace({"":np.nan})
return df

read_csv 处理引号,应用正则表达式将删除空格。
结果终于令人鼓舞。所有列都有预期的长度和类型。但是性能好吗?
剥掉绳子
Python 有一个本地方法来删除前面和结尾的空格— .strip(),我们可以很容易地在我们的数据上使用它。因为这是一个字符串操作,我们需要使用str.strip(),它只能应用于字符串列。因此,我们必须检查该列是否是字符串格式。
# use internal method api.types.is_string_dtype to find out if the columns is a string
if pd.api.types.**is_string_dtype**(df["column_name"]):
df["column_name"] = df["column_name"].str.strip()
同样,我们将操作包装到一个函数中,以便稍后在性能测试中使用它。像以前一样,我们将把所有空字符串转换成 NaN。
def **read_csv_strip**(data, date_columns=[]):
df = pd.read_csv(data, quotechar='"', parse_dates=date_columns)
# for each column
for col in df.columns:
# check if the columns contains string data
if pd.api.types.**is_string_dtype**(df[col]):
df[col] = df[col]**.str.strip()**
df = df.replace({"":np.nan}) # if there remained only empty string "", change to Nan
return df

结果与使用正则表达式相同。
在字符串列上使用str.strip()会导致相同质量的结果。比较每种方法的速度会很有趣。
注意:不要使用
df[col].apply(len),而要使用df[col].str.len(),因为apply(len)在 NaN 值上失败,这些值在技术上是浮点而不是字符串。
NaN 值
为什么我们要把所有的空弦都变成 NaNs?默认情况下,熊猫认为所有这些值都是 nan:
',' #不适用',' #不适用',' #不适用','-1。#IND ','-1。#QNAN ','-nan ','-NaN ',' 1。#IND ',' 1。#QNAN ','',' n/a ',' NA ',' null ',' NAN ',' N/A ',' NaN ',' NULL '
它有一个很好的理由,因为 NaN 值的行为不同于空字符串" "。
count(NaN) = 0而count("")=1- 您可以对 NaN 值应用
fillna()或dropna()方法
但是 pandas 只是将一个空字符串""转换成 NaN,而不是" "一个空格、两个空格、制表符或类似的空空格。这就是为什么我们必须在?csv 已加载到数据帧中。
特性试验
生成测试数据
每种建议的方法有多快?我们会认为内置方法是最快的,但是它们不符合我们的目的。让我们准备一些数据,以便了解操作的实际速度。
几行总是在一瞥之间被处理,所以我们需要大量的数据来测试性能,比如说一百万条记录。为此,我想试试 python 的faker库,它有一个快速的界面来创建随机的名字、地址和其他数据。
import faker
import random# initiate the faker with a seed
f = faker.Faker()
faker.Faker.seed(123)# generate million lines with extra white spaces
data = []
for i in range(1000000):
data.append([" " + f.address(),
" " + f.name() + " ",
" " + str(random.randint(1,1000000))])
我正在创建一个包含一百万行和三列的列表:
- 地址开头多留两个空格
- 以空格开头和结尾的名称
- 和用空格表示字符串的随机数
生成的数据帧具有以下参数
[In]: df = pd.DataFrame(data, columns=["Address","Name","Salary"])
df.info()
[Out]:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000000 entries, 0 to 999999
Data columns (total 3 columns):
Address 1000000 non-null object
Name 1000000 non-null object
Salary 1000000 non-null object
dtypes: object(3)
memory usage: 22.9+ MB
因为 faker 生成的地址不仅包含逗号,还包含换行符,所以当我们将它们导出到 csv 时,它们将被用引号括起来。示例地址:
" 1068 Peterson Cape
South Jacquelineville, RI 78829"
faker提供了许多方法。如果您想要单行地址,例如使用.street_address()或.street_address() + ", " + .city()。你可以在这里研究 faker 文档。
100 万样本的性能
可以肯定的是,我们测量了合理的处理时间,并且没有受到 CPU 的一些峰值使用的影响,例如,当防病毒软件运行时,我们将对上述每种方法进行 7 次测试。
import timedef process_seven_times(function, params={}):
processing_time = [] for i in range(7):
start = time.time()
df = function("test_data.csv", **params)
processing_time.append(time.time() - start) return processing_time, df
您可以为每个场景发布这段代码,但是最好使用 python 将函数存储在变量中的能力,准备一个包含所有函数的字典,并对其进行迭代。
functions = {"No space handling": {"function": pd.read_csv, "params": {}},
"Skipinitialspace": {"function": pd.read_csv, "params": {"skipinitialspace": True}},
"Regex Separator": {"function": pd.read_csv, "params": {"sep":"\s*[,]\s*", "engine":"python"}},
"Strip blank spaces": {"function": read_csv_strip, "params": {}},
"Load and apply regex": {"function": read_csv_regex, "params": {}},
"Load and apply regex column wise": {"function": read_csv_regex_col, "params": {}},
}
字典中的每个键都包括一个函数及其参数——skipinitialspace、separtor、engine 等。数据的路径总是相同的,所以我们不必作为参数重复多次。
我们还将存储处理时间,并使用df_statistics(df)计算统计数据
results = []
statistics = []for name, function in functions.items(): processing_time, df = process_seven_times(function, params=f["params"]) # create a Series with processing time and name it based on the function used
s = pd.Series(processing_time)
s.name = name
results.append(s) statistics.append(pd.DataFrame(df_statistics(df), index=[name]))
几分钟后,当我们测试完所有功能后,我们可以显示结果:
stats_perf_df = pd.DataFrame(results)
stats_perf_df["avg"] = stats_perf_df.mean(axis=1)
stats_perf_df, stats_perf_df["avg"].plot(kind="bar")

每个函数运行 7 次,表明大型数据集上的正则表达式操作非常慢。
性能测试证实了我们的预期。内置方法胜过自定义算法。尽管它们没有达到我们想要的效果,但我们可以使用str.strip()从加载的数据帧中移除空白。大约是。比没有剥离的过程慢 50%,但仍然比使用正则表达式快 5 倍。
您可能已经注意到,使用skipinitialspace可以在没有任何空白处理的情况下完成加载,因此,如果速度是我们关注的问题,将这个参数与加载的数据帧的后处理结合起来可以带来更好的结果。您可以再次运行性能测试,以确认这不是一个异常。
结论
在数据集被额外的空格污染的情况下,空白处理非常重要,这不仅是为了减少数据的大小,而且主要是为了正确地将数据与其他源连接起来,并接收数据和 nan 聚合的预期结果。
Pandas 包含一些内置参数,有助于处理最常见的情况。任何进一步的处理都必须由自定义函数来完成,这会降低处理速度。出于这个原因,请始终尝试与您的数据提供商达成一致。符合标准的 csv 文件。
您可以使用 github 上的这个 Jupyter 笔记本执行本文描述的所有代码。测试数据不包括在内,但您可以通过此笔记本生成它们。
探索前导和尾随零,字母和数字的分布,常见前缀,正则表达式…
towardsdatascience.com](/exploratory-data-analysis-passport-numbers-in-pandas-4ccb567115b6)
处理越来越不耐烦?在 AWS 上将您的实时 ML 服务推向生产!
为您的 ML 应用程序构建正确的云基础设施通常被低估。这里可以看到,由于广泛普及的云资源调配,这变得多么容易。

最*,我看到研究小组、学生或同事想出一个取得巨大成就的模型的次数令人吃惊。(我不是在说通过 CT 扫描检测 COVID 的 50 张图像的 95%准确性……)人工智能革命已经将它的一桶新应用带到了现实世界,但都面临着同样的问题:产品-市场-适合(这是一个太大的主题,无法在这里涵盖)和具体化。幸运的是,由于硬件价格的下降和云计算可靠性的提高,超大规模和大计算已经迅速普及。在本文中,我将花一些时间来讨论一组特定的 ML 应用程序的后者:实时服务。
其中,最受欢迎的当然是实时异常或欺诈检测、即时定价、社交媒体*台、聊天机器人或花式流媒体。在牵强的一端,你们中的一些在协作*台上工作的人已经使用了一些,甚至没有注意到通过推荐或音频流去噪。决策正在快速发展,急躁是最新一代人的最大特点之一,这迫使当前设计的应用程序必须巧妙应对实时交互和解释的需求。

Alriiiiiight,太多让人兴奋的理由了!我将尽我所能帮助您弄清楚构建这样的服务并使您的用户能够使用它们需要做些什么。
流式要求 101
在架构方面,流确实意味着你需要为两个利益相关者之间的持续信息流打开大门。该流将源自一个用户,并且必须保持活动,直到该用户或他的对应方关闭该流。在协议方面,这涉及到 WebSockets 的创建。从概念上讲,它们主要是一个允许信息同时从 A 传到 B,从 B 传到 A 的系统。这就是我们所说的全双工连接。

演职员表:fullstackpython.com/websockets.html
幸运的是,有多种方法可以将 WebSockets 服务包含到您的产品中。我给你一个沙盒模板,让你在我的 Github 上玩。在那个例子中,我使用砂箱作为基础,砂箱插座作为工人, gunicorn 作为主管。flask-sockets 附带了一个非常方便的包装,可以快速制作原型并对产品进行足够的控制。
烧瓶插座用法的沙盒示例
出乎意料的是,我总是发现测试一个依赖于 WebSockets 的端点比实际实现它更难。在这些可能性中,有一种是由 Ngrok 提供的,这种服务允许你通过安全的隧道管理将你的本地机器转换成具有公共地址的适当端点。然而,Ngrok 的免费版本有一些限制(一次 1 个服务,上限为每分钟 40 个连接)。在某些情况下,它非常方便,但在其他情况下就不那么方便了。我建议你随时尝试一下!😃
同时,只需使用下面的代码片段运行启用了 WebSocket workers 的 Flask 服务器:
运行本地接受 WebSockets 的实例的代码段
下面的代码片段通过这些工人将文件传输到您的应用程序:
流媒体应用的测试功能示例
前面的示例使您能够发送来自音频文件的流。很明显,您可以调整前面的代码片段来发送您的麦克风、视频帧、消息等输入……可能性是无限的!
AWS 上生产实例的技巧和提示

保留前面的步骤已经很不错了,因为它让你能够展示你从一开始就在起草的申请。最有趣的部分是把管道放到云上,让其他人也能使用。以下是要遵循的步骤,所有代码都可以在 Github 上找到:
- 以正确的方式建立你的 Docker 形象:
流式应用程序的 Dockerfile
这可能是您可以在本地运行的最后一个测试。在这一点上,浏览 Docker 是关于云基础设施的良好实践。容器化使您能够为自己保留一些云不可知论,同时控制您的版本。为了最大化这种不可知论,我的方法通常是使用 AWS 的 Elastic Beanstalk 实例,它可以非常无缝地运行我的 Docker 映像,并支持足够的配置。
- 基础架构草案:
安全性是一个大问题,但我不会在本文中详细讨论虚拟私有云和静态加密。我将从一个简单的概念证明开始,您可以在自己的云上运行和扩展。共享的代码片段将使您能够构建一个安全的 WebSocket 连接,通过经典负载*衡器捕获流,并通过 SSL 将该信息传输到您的应用程序。这里的这个应用程序仅仅是一个将接收到的数据存储在一个弹性文件存储器(仅仅是一个挂载的虚拟硬盘驱动器)上的应用程序,您可以在不同的实例之间共享它以供进一步处理。

- 举个有用的例子:

最后一步:实例配置!
这就是奇迹发生的地方。由于我必须浏览大量的论坛和文档,这当然是你会发现最有价值的地方!😃
- 使您的听众能够听到入站流:
。ebextensions/listeners.config
- 使您的实例能够在 WebSockets 端口上反向代理:
。ebextensions/websockets.config
对于配置的其余部分,一切都在.ebextensions目录中可用。在其他任务中,这些文件将启用 HTTPS ,在您的请求中启用头的使用,并且将您的弹性文件存储虚拟硬盘挂载到您的实例中。.Dockerrun.aws.json文件将与安装 EFS 端点的实例进行通信。
有多有用?让我向你介绍卡拉斯特!
阿拉斯特是一个设计用于紧急呼叫中心收集、分析和优先排序信息的*台。更好的信息可以帮助急救人员以更有效的方式应对紧急情况。通过从呼叫分析到可视化的一系列服务,CalAster 允许急救人员更好地了解紧急情况并做好心理准备。此外,CalAster 的优先排序工具可以有效地对来电进行分类。在自然灾害期间,当资源短缺,紧急呼叫中心不堪重负时,这一点尤其有用。以下是该架构过去的一瞥,让我们进入了 2019 年 代码的 决赛。

为了冒险者…
你们中的一些人可能已经在抱怨了,因为实时 ML 的真正界限通常是推理时间。当你在大型模型上工作时,即使是在 GPU 上,也很难让它运行得和你的入站流一样快。目前思考这个问题的方式仍在前进:策略中有模型量化和模型修剪。我将让您探索这两个 Github 库,它们仍在积极开发中!
Condensa 是 Python 中可编程模型压缩的框架。它附带了一组内置的压缩运算符,可用于针对 DNN 体系结构、硬件*台和优化目标的特定组合构建复杂的压缩方案。为了恢复压缩过程中的任何精度损失,Condensa 使用模型压缩的约束优化公式,并采用基于增强拉格朗日的算法作为优化器。
激流是一个函数、脚本和工具的集合,它使得超低位宽的神经网络能够被容易地高速训练和部署。激流建立在 Tensorflow 之上,用于训练,TVM 用于部署。激流模型使用一种称为融合胶的新型算子来取代二进制神经网络内部的所有浮点运算。通过将融合的粘合层与其他优化(如 Bitpack Fusion )相结合,Riptide 能够生成比 Raspberry Pi 上的浮点对等物运行速度快 4-12 倍的模型。
拜托,要有创意!
有那么多的问题需要解决,而解决这些问题的人却那么少。如果你有了一个想法,要知道有大量的信息可供你建立你的想法,并把它从一个概念变成一个有影响力的实际产品!
有兴趣保持联系吗?😄Twitter|LinkedIn|Github|Medium
使用主成分分析(PCA)处理高维数据
PCA 入门指南以及如何用 sklearn 实现(带代码!)

纳比尔·侯赛因在 Unsplash 上的照片
数据科学家在创建算法时的一个常见问题是变量太多。很自然,你会认为添加更多的信息只会让你的模型更好,但是你添加的每一个特性都会带来另一个维度。作为人类,我们只能想象二维或三维的事物。对于数据,此规则不适用!数据可以有无限多的维度,但这就是维度诅咒发挥作用的地方。
维数灾难 是数据科学家经常面临的悖论。为了提高机器学习模型的准确性,您希望使用更多的信息,但是添加的功能越多,维数(n)就会增加。随着特征空间的维数增加,配置的数量呈指数增加,并且反过来,观察覆盖的配置的数量减少。
作为数据科学家,我们的最终目标是创建能够快速运行且易于解释的简单模型。当我们有大量的特征时,我们的模型变得更加复杂,可解释性降低。为了处理这些复杂的数据集,主成分分析是降低数据维数的理想方法。
什么是主成分分析,用来做什么?
主成分分析 ,或者更俗称 PCA ,是一种在保持大部分重要信息的同时减少变量数量的方法。它将多个可能相关的变量转化为数量较少的不相关变量,称为 主成分 。主成分是原始变量的线性组合,这些变量在特定的正交维度上由它们的方差(或特征值)加权。PCA 的主要目的是将模型特征简化为更少的组件,以帮助可视化数据中的模式,并帮助模型更快地运行。使用 PCA 还可以通过消除高度相关的特征来减少过度拟合模型的机会。
需要注意的是,你应该只对 连续 变量应用 PCA,而不是分类变量。虽然从技术上讲,您可以对一位热编码或二进制数据使用 PCA,但它的效果不是很好。这是因为 PCA 被设计为最小化方差(方差),这在对二元变量执行时没有太大意义。如果您有混合数据,替代方法如MCA可能会更好。
那么,您如何知道您的 PCA 中保留了多少信息呢?
我们使用 解释方差比率 作为一种度量标准来评估您的主成分的有用性,并选择在您的模型中使用多少成分。解释的差异比率是由每个所选组件引起的差异的百分比。理想情况下,您可以通过添加每个组件的解释方差比率来选择要包括在您的模型中的组件数量,直到您达到大约 0.8 或 80%的总数,以避免过度拟合。
幸运的是,sklearn 通过他们的 很容易得到解释的方差比。解释 _ 方差 _ 比率 _ 参数!我们将在编码示例中使用它。

美国宇航局在 Unsplash 上拍摄的照片
使用 Sklearn 的 PCA 示例
- 首先,让我们为我们的长代码示例加载 iris 数据集。iris 数据集是一个著名的数据集,包含来自三个不同物种的 150 朵 iris 花的测量数据。
*from sklearn import datasets
import pandas as pd
iris = datasets.load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['Target'] = iris.get('target')
df.head()*

2.接下来,我们将把“features”列表中的所有列分隔成变量“X ”,把“target”变量分隔成变量“y”。
*# Create features and target datasets
features = ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
X = df[features].values
y = df['Target'].values*
3.在实现 PCA 之前,我们必须将数据标准化。这是绝对必要的,因为 PCA 使用我们数据的标准偏差计算我们数据在新轴上的新投影。PCA 给予方差较高的变量比方差较低的变量更大的权重,因此在相同的尺度上归一化数据以获得合理的协方差是很重要的。
*from sklearn.preprocessing import StandardScaler
# Standardize the features
X = StandardScaler().fit_transform(X)
# Preview X
pd.DataFrame(data=X, columns=features).head()*

4.现在,我们将使用 sklearn 导入 PCA,并将我们的原始数据(4 维)投影到 2 维。在这一部分中,sklearn 创建了一个协方差矩阵来计算特征向量(主分量)及其对应的特征值。 特征向量 确定新特征空间的方向,而 特征值 确定沿着新特征轴的数据的幅度或方差。
*# Import PCA from sklearn
from sklearn.decomposition import PCA
# Instantiate PCA
pca = PCA(n_components=2)
# Fit PCA to features
principalComponents = pca.fit_transform(X)*
5.为了更好地可视化主成分,让我们将它们与熊猫数据帧中与特定观察相关联的目标(花类型)配对。
*# Create a new dataset from principal components
df = pd.DataFrame(data = principalComponents,
columns = ['PC1', 'PC2'])
target = pd.Series(iris['target'], name='target')
result_df = pd.concat([df, target], axis=1)
result_df.head(5)*

6.现在,我们可以使用目标数据根据类别分布来可视化主成分。这段代码根据主要成分创建了一个散点图,同时根据每个示例被分类的花类型对示例进行了颜色编码。
*# Visualize Principal Components with a scatter plot
fig = plt.figure(figsize = (12,10))
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('First Principal Component ', fontsize = 15)
ax.set_ylabel('Second Principal Component ', fontsize = 15)
ax.set_title('Principal Component Analysis (2PCs) for Iris Dataset', fontsize = 20)
targets = [0, 1, 2]
colors = ['r', 'g', 'b']
for target, color in zip(targets, colors):
indicesToKeep = iris['target'] == target
ax.scatter(result_df.loc[indicesToKeep, 'PC1'],
result_df.loc[indicesToKeep, 'PC2'],
c = color,
s = 50)
ax.legend(targets)
ax.grid()*

7.我们可以看到,这三个类是截然不同的,也是完全可以分开的。我们可以得出结论,压缩的数据表示对于分类模型来说很可能是足够的。我们可以将整个数据集中的差异与使用。解释 _ 方差 _ 比率 _。
*# Calculate the variance explained by priciple components
print('Variance of each component:', pca.explained_variance_ratio_)
print('\n Total Variance Explained:', round(sum(list(pca.explained_variance_ratio_))*100, 2)*

我们可以看到,我们的前两个主成分解释了该数据集中的大部分方差(95.81%)!这是与原始数据相比所表示的总信息的指示。
摘要
这篇文章的要点是:
- PCA 是一种常用的降维技术。
- PCA 的目标是将模型要素简化为更少的不相关要素,以帮助可视化数据中的模式,并帮助它更快地运行。
- 仅对连续数据应用 PCA。
- 在应用 PCA 之前,请确保您的数据已经过规范化!!
感谢阅读!
如果你喜欢我的博文,可以关注我的媒体 这里 支持我。也可以通过我的 LinkedIn 这里 与我联系。
参考文献:
- https://towards data science . com/a-一站式主成分分析-5582fb7e0a9c
- https://deepai . org/machine-learning-glossary-and-terms/curse-of-dimensionality
- https://elitedata science . com/over fitting-in-machine-learning
- https://www . geeks forgeeks . org/principal-component-analysis-with-python/
- https://sci kit-learn . org/stable/modules/generated/sk learn . decomposition . PCA . html
- https://www . research gate . net/profile/Dominique _ Valentin/publication/239542271 _ Multiple _ communication _ Analysis/links/54a 979900 cf 256 BF 8 bb 95 c 95 . pdf
- https://www . vision dummy . com/2014/03/特征值-特征向量/
- https://sebastianraschka . com/Articles/2015 _ PCA _ in _ 3 _ steps . html
- https://etav.github.io/python/scikit_pca.html
- 熨斗数据科学课程第 37 节
流失分析中不*衡数据的处理
我们的实习团队在为一家 SaaS 公司进行客户保持分析时如何处理不*衡数据。

让我们看看如何在你的小众类中找到模式
在我们的加州大学戴维斯分校 MSBA 实习项目的客户保持分析部分,我们必须应对的主要挑战之一是我们数据中的不*衡。
今天,我将讲述:
- 什么是不*衡数据?
- 什么时候成问题了?
- 如何处理不*衡的数据?
- 我们应用的解决方案如何影响我们的项目。
什么是不*衡数据?
可用于分类问题的数据集有一个标签(例如,客户流失、糖尿病等。)和一组输入(如产品特性、健康指标等。)标签表明了类别,因此您可能会有一个“搅动的”与“活跃的”类型的客户。
严格地说,如果你的数据没有对半分割,那么它就不是“*衡的”。这很好。没有完美的数据集!甚至不是分类问题教程很流行的泰坦尼克或者酒质数据集。
一些数据集的分类比例为 90/10(即 90%的活跃客户,10%的流失客户),一些数据集的分类比例为 95/5,甚至 99/1。这将非常不*衡。
什么时候成问题了?
由于不*衡的数据可能有不同的比率,我们开始想知道什么比率是我们必须评估的实际问题。你的少数民族班有 10%的案例是个问题吗?5%?不到 1%?
这个答案和我每次问有见识的人一个有趣的问题得到的答案是一样的: 看情况!
对于如何划分你的类没有标准的界限。根据你正在解决的商业问题的类型和行业的类型,拆分可能会变得更有意义。例如,对于客户保留问题,80/20 的分割可能是可以接受的,但是对于医疗保健问题就不太好了。欺诈检测、在泰坦尼克号沉船中幸存、流失分析或 COVID spread 都可能在用于各自分类问题的类中使用不同的拆分。
在我们的实习项目中,这种不*衡不像 1%的少数阶级(被搅动的顾客)那样严重,但这仍然是我们决定解决的问题。
如何处理不*衡的数据?
有许多方法可以处理不*衡的数据。拥有人工智能硕士和博士学位的杰森·布朗利(Jason Brownlee)更详细地讲述了这个主题,以及许多其他关于机器学习掌握的有趣的机器学习教程。他还推荐这本书“深入研究一些关于处理阶级失衡的学术文献”。
今天,我们将学习 3 种方法:
- 检查您的指标
- *衡您的数据
- 什么也不做
1.检查您的指标

重要的是深入了解性能指标,理解准确性和精确性之间的区别。
当我们获得分类模型的结果时,我们通常首先查看的是我们所做的所有预测中正确预测的数量。这似乎很直观,因为我们想看看我们的模型表现如何。这是模型的精确度:预测总数的总正确预测。然而,我们需要记住,只看和的准确性是不够的!
“准确性不是处理不*衡数据集时使用的衡量标准。我们已经看到这是一种误导。”杰森·布朗利
在这篇帖子中,布朗利详细解释了为什么仅仅靠准确性不能给你足够的信息来做出决定。在我们的案例中,当进行流失分析并预测将流失的客户时,准确性意味着在所有客户中,我们正确地将多少实际流失的客户标记为“流失”(真阳性)以及将多少未流失的客户标记为“未流失”(真阴性):
因为有如此多的客户没有流失,高数量的真实否定使得准确率非常高,这将是误导,因为我们希望专注于那些确实离开的客户,并试图发现我们可以做些什么来防止其他客户发生这种情况。
精度在这里派上了用场。精确度是:在所有被标记为“流失”的客户中,我们正确标记了多少?这是被正确标记的客户(真阳性)与所有被标记为“流失”的客户(真阳性和假阳性)的比率。
对于我们来说,在处理数据中的不*衡之前和之后进行回顾,这个指标更有意义。如果你想了解更多关于性能指标的信息,计算机工程专业的学生 Salma Ghoneim 在这篇文章中对准确性、召回率、精确度、F 值和特异性做了出色的解释。
此外,您可能希望检查受试者操作者特征曲线下的面积(AUC ROC 或 AUROC ),以确定真阳性和假阳性之间的关系。另一篇帖子很好地解释了这个重要的概念,StatQuest 创始人 Josh Starmer 的这篇清晰的解释带你一步一步地了解细节。)
2.*衡您的数据

*衡数据可以用不同的方式完成!
- 欠采样:欠采样包括从你的过表示类中删除观察值。在这种情况下,这些将是活跃的客户。当你有一大堆数据时(布朗利称之为“几万或几十万个实例或更多” ),这样做是有意义的,但在这个项目中,情况并非如此。
- 过采样:过采样包括添加来自未被充分代表的类的观察副本。在这种情况下,这些将是搅动的客户。这是一个不错的方法,因为它*衡了数据,但我们仍然可以做得更好。
- SMOTE :这样更好! SMOTE 代表合成少数过采样技术。这种方法创建数据的合成样本,因此 SMOTE 使用距离测量来创建数据点的合成样本,而不是复制观测值,这些数据点不会离您的数据点太远。我们在客户流失分析中使用这个来*衡数据。
- ADASYN : ADASYN 代表自适应合成采样方法,它是一种对你的数据集应用 SMOTE 的改进方法。 ADASYN 查看数据的密度分布,以确定将要生成的样本数量。在我们的流失分析中,我们最初使用 SMOTE,但当我们了解到 ADASYN 是一种创建合成样本的改进方法后,我们将我们的方法切换到 ADASYN。
3.什么也不做

有时不同的视角比典型的解决方案更好。
这里什么都不做并不意味着我们解决了这个问题!这意味着,你可以考虑其他方法,比如收集更多数据(如果可能的话)或者使用不同的机器学习模型,而不是解决你数据中的不*衡。决策树和随机森林是很好的选择。你也可以试试 C4.5,C5.0 或者 CART,就像这个帖子上建议的那样。
美女(还有挑战!)的问题是决定使用哪种方法既能最大限度地提高模型性能,又能揭示数据中的洞察力。
我们应用的解决方案如何影响我们的项目。
一旦我们使用 ADASYN *衡数据集,我们就会看到在模型性能方面更好的结果。这使我们能够继续分析和评估不同模型如何回答我们的问题:哪些关键特征与离开/留在这家 SaaS 公司的客户最相关?我们能够找到隐藏在回答这个问题的数据中的金块,并帮助我们向这家 SaaS 公司的利益相关者提供可行的建议。
大团圆结局?
从那以后我们愉快地继续实习了吗?没有。我们在这个项目中遇到了更多的挑战,这让它变得更加有趣。剧透提醒:我们确实交付了强劲的成果,我们的利益相关者非常高兴,我们目前正在完成项目和我们的 MSBA 项目。
处理不*衡数据集
处理不*衡数据的技术

图片来自菲德尔·费尔南多,来自 Unsplash
现实问题中的不*衡数据集并不罕见。通俗地说,不*衡数据集就是类分布不均衡的数据集。不*衡的数据会在分类任务中产生问题。在深入研究不*衡数据的处理之前,我们应该知道不*衡数据集可能产生的问题。
我们将以一个信用卡欺诈检测问题为例,来理解不*衡的数据集以及如何以更好的方式处理它。
示例—信用卡欺诈检测

图片由负空间拍摄,来自 Pexels
信用卡欺诈检测的数据集取自 Kaggle。该数据集包含两天内发生的交易,其中
数据中的总交易数= 284,807
数据有两类: 0 和 1 分别代表合法交易和欺诈交易。绘制等级分布图将使我们对不*衡(如果存在的话)有所了解。

作者图片
合法交易总数为 284807 笔中的 284315 笔,占 99.83%。欺诈交易在整个数据集中只有 492 笔( 0.17% )。不*衡的数据集可能出现在其他场景中,如癌症检测,其中大量受试者为阴性,只有少数人患有癌症。
不*衡数据集可能造成的问题
如果我们使用准确性作为性能指标,这可能会产生一个巨大的问题。假设我们的模型预测每个交易都是合法的(哑模型)。在信用卡数据集上使用准确性度量将给出 99.83%的准确性,这是非常好的。是好结果吗?否
对于不*衡数据集,应使用其他性能指标,如精确召回 AUC 分数、F1 分数等..而且,模型会偏向多数阶级。由于大多数机器学习技术都被设计为能够很好地处理*衡的数据集,因此我们必须从不*衡的数据集创建*衡的数据。怎么做?
注意:在改变数据集之前,我们必须将数据集分为训练和测试,因为改变只是为了训练。
>>>from sklearn.model_selection import train_test_split
>>>X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.33,
random_state = 2, shuffle = True, stratify = y)
训练数据集的形状:
0: 190430 事务
1: 330 事务
我们将在本文中讨论从不*衡数据创建*衡数据集的三种方法:
- 欠采样
- 过采样
- 创建合成数据
1.欠采样
欠采样对数据中的多数类点进行重采样,使其等于少数类点。我们将使用欠采样从原始数据集创建一个新的数据集。我们将对信用卡欺诈检测中的合法交易(数量为 190490)进行随机抽样,以使 0 类数据点等于 330(少数类)。
>>>from imblearn.under_sampling import RandomUnderSampler
>>>rus = RandomUnderSampler(random_state=0)
>>>X_resampled_under, y_resampled_under =rus.fit_resample(X_train, y_train)

作者图片
欠采样的主要缺点是我们没有使用大量的数据,其中包含一些信息。在我们的示例中,我们删除了 190160(190490–330)个数据点。因此,我们在丢失信息,结果,我们不会得到显著的结果。
我们可以通过使用一种称为过采样而不是欠采样的技术来避免这种情况。
2.过采样
过采样是指对少数类点进行重采样,使其等于多数点的总数。少数类点的重复是一种这样的过采样技术。
除了重复之外,我们可以向两个类提供类权重。给少数类提供大的权重将会给出与复读相同的结果。
3.创建合成数据
重复数据的问题是它不提供任何额外的信息。增加数据信息的一种方法是创建合成数据点。一种这样的技术是 SMOTE(合成少数过采样技术)。顾名思义,SMOTE 是一种过采样技术。通俗地说,SMOTE 会为小众阶层创建合成数据点。它在少数阶级之间创造了新的实例。
我们可以使用 imblearn 库对训练数据集应用 SMOTE。
>>>from imblearn.over_sampling import SMOTE
>>>sm = SMOTE(random_state = 42)
>>>X_train_new, y_train_new = sm.fit_sample(X_train, y_train)

作者图片
结论
在处理现实世界的场景时,不*衡的数据集非常常见。如果机器学习模型出于训练目的而使用不*衡的数据集,则该模型是不健壮的。因此,*衡数据集是训练机器学习模型的首选。欠采样、过采样和 SMOTE 等技术可用于创建*衡数据。
感谢阅读!
处理熊猫数据框架中的列表值
这里有一些避免过多循环并获得良好结果的技巧

图 1 —标题图像。
您曾经处理过需要您处理列表值的数据集吗?如果是这样,你就会明白这有多痛苦。如果你还没有,你最好做好准备。
如果你仔细看,你会发现列表无处不在!这里有一些实际问题,你可能会遇到列表值。
- 音频或视频标签
- 调查数据中的开放式问题
- 所有作者、艺术家、制作人等的名单。参与创新产品

图 2 —滑稽猫视频的标签列表。
我最*参与了多个需要我分析这类数据的项目。经过几个小时的痛苦思考,我意识到必须在这里分享我的知识来节省你的时间。
我将向你展示你可能会遇到的各种问题,并为他们提供切实可行的解决方案。
快速准备
要学习本教程,请随意下载用于所有示例的虚构数据集。包括代码在内的所有资料均可在本报告中找到。
此外,请导入所有必要的库并加载数据框架。
import pandas as pd
import numpy as np
import matplotlib as plt
fruits = pd.read_csv("fruits.csv", delimiter = ";")

图 3 —数据集示例
列表值到底有什么问题?
请允许我直入主题:列表值打乱了你所知道的关于数据分析的一切。没有无休止的循环,最简单的操作也无法执行。让我给你看一个简单的例子:
对于示例数据集中的“年龄”列,我们可以很容易地使用 value_counts() 函数来计算该年龄被观察了多少次。
fruits["age"].value_counts()
## OUTPUT ##
8 3
10 2
6 2
9 1
7 1
5 1
如果我们想知道哪些水果被命名的次数最多呢?原则上,我们在“favorite_fruits”列中有所有需要的数据。然而,如果我们应用同样的函数,结果并非毫无用处。
fruits["favorite_fruits"].value_counts()
## OUTPUT ##
["strawberry", "raspberry", "blueberry"] 1
["mango", "pineapple", "orange"] 1
["blueberry", "watermelon", "apple", "raspberry"] 1
["apple", "pear", "peach"] 1
["pear", "strawberry", "raspberry"] 1
["banana", "maracuja", "watermelon", "apple", "pineapple"] 1
["peach", "strawberry", "apple", "blueberry"] 1
[] 1
["banana", "mango", "orange", "watermelon"] 1
["watermelon", "apple", "blueberry", "pear", "strawberry"] 1
这不起作用的原因是熊猫不能直接访问列表中的每一个元素。因此,Pandas 无法正确应用 value_counts() 等函数。那么,我们该怎么办呢?我现在就给你看!
问题 1:我的列表存储为字符串
你会经常遇到的一个问题是,熊猫会把你的列表读成字符串,而不是列表。
for i, l in enumerate(fruits["favorite_fruits"]):
print("list",i,"is",type(l))
这意味着您甚至不能遍历列表来计算唯一的值或频率。根据列表在数据帧中的格式,有一个简单或复杂的解决方案。在任何情况下,您都可以简单地使用我提供的代码。
你的琴弦是不是长这样:“['草莓','苹果','橘子']”?
在这种情况下,有一个使用 apply() 和 eval() 函数的快捷方法。
fruits["favorite_fruits"] = fruits["favorite_fruits"].apply(eval)
你的琴弦是这样的吗:“【草莓、苹果、橘子】”?
这一个更难,因为 eval() 函数将不起作用,因为 list 缺少内部引号以便被识别为 list 对象。快速而肮脏的解决方法是简单地给字符串加上引号,然后应用 eval() 。使用此功能:
def clean_alt_list(list_):
list_ = list_.replace(', ', '","')
list_ = list_.replace('[', '["')
list_ = list_.replace(']', '"]')
return list_
要将此应用于您的数据帧,请使用以下代码:
df[col] = df[col].apply(clean_alt_list)
请注意,在这两种情况下,Pandas 仍将为系列分配一个“O”数据类型,这通常用于字符串。但是不要让这个迷惑了你。您可以使用以下命令检查实际的数据类型:
for i, l in enumerate(fruits["favorite_fruits"]):
print("list",i,"is",type(l))
## OUTPUT ##
list 0 is <class 'list'>
list 1 is <class 'list'>
list 2 is <class 'list'>
list 3 is <class 'list'>
list 4 is <class 'list'>
list 5 is <class 'list'>
list 6 is <class 'list'>
list 7 is <class 'list'>
list 8 is <class 'list'>
list 9 is <class 'list'>
问题 2:获取唯一值或值计数
在这第一步之后,我们的名单最终被熊猫认可。但是,我们不能使用标准函数,因为它们不是为列表应用程序设计的。
至少我们现在可以对任何事情都使用循环。这种方法适用于小数据集,但对于大数据集可能会非常慢。例如,我必须分析大约 50 万首音乐曲目的多达 999 个标签的标签列表。这意味着,内部循环将有数以亿计的迭代,这将花费许多小时,并可能使我的计算机崩溃。一会儿我会告诉你一个更干净快捷的方法。但是,如果您真的想使用循环,下面是代码:
fruit_dict = {}
for i in fruits["favorite_fruits"]:
for j in j:
if j not in fruit_dict:
fruit_dict[j] = 1
else:
fruit_dict[j] += 1
这是我花了一段时间才想出来的干净方法。如果我们将 favorite_fruits 列概念化为一个 2D 数组,那么将其维度从 2 减少到 1 将允许我们再次应用典型的 pandas 函数。为此,您可以使用此函数:
def to_1D(series):
return pd.Series([x for _list in series for x in _list])
如果我们现在使用 value_counts() ,就会得到我们想要的结果。
to_1D(fruits["favorite_fruits"]).value_counts()
## OUTPUT ##
apple 5
blueberry 4
watermelon 4
strawberry 4
raspberry 3
pear 3
banana 2
pineapple 2
mango 2
peach 2
orange 2
maracuja 1
要获得唯一值,只需从链接的结果中提取它们。index() 跃然纸上。
在这一点上,我们可以产生我们的第一个有意义的可视化。
# Get unique items & counts
unique_values = to_1D(fruits["favorite_fruits"]).value_counts().index.tolist()
unique_value_counts = to_1D(fruits["favorite_fruits"]).value_counts().values
# Create plot
fig, ax = plt.subplots(figsize = (14,4))
ax.bar(unique_values, unique_value_counts)
ax.set_ylabel("Frequency", size = 12)
ax.set_title("Children's Favorite Fruits", size = 14)

图 4 —显示所有水果频率的条形图。
问题 3:所有唯一值的单独列
在这一点上,事情越来越先进。如果你对我们之前得到的结果满意,你可以到此为止。然而,你的研究目标可能需要更深层次的分析。也许您希望将所有列表元素相互关联起来,以计算相似性得分。例如,吃香蕉的孩子通常也喜欢芒果吗?或者你可能想知道哪种水果被大多数孩子列为最喜欢的水果。这些问题只有在更深层次的分析中才能得到解答。
为此,我将介绍两个有用的方法。它们在复杂性上有所不同,但在如何处理它们的结果上也有所不同。
方法 1
这是我偶然发现的一个非常简单快捷的方法。而且是这么有用!你所需要的只是一行代码。
fruits_expanded_v1 = fruits["favorite_fruits"].apply(pd.Series)

图 5 —使用方法 1 的水果列表的扩展版本。
如您所见,这个一行程序生成了一个数据帧,其中每个列表都被分割成单个元素。这些列表示水果在列表中的排列顺序。使用这种方法,您将始终获得一个形状为(n,len(longest_list))的数据帧。在这种情况下,10 个孩子中的 2 个说出了 5 种最喜欢的水果,这就产生了一个 10x5 的数据帧。
利用这个,我们可以找出哪种水果最常被命名为最受欢迎的水果。
fruits_expanded_v1.iloc[:,0].value_counts(normalize = True)
## OUTPUT ##
banana 0.222222 pear 0.111111 watermelon 0.111111 blueberry 0.111111 strawberry 0.111111 apple 0.111111 peach 0.111111 mango 0.111111
我们可以看到香蕉通常是孩子们最喜欢的水果。
或者,我们可以针对单个水果,找出它们在列表的每个位置被命名的次数。这是我为此写的函数:
def get_rankings(item, df):
# Empty dict for results
item_count_dict = {}
# For every tag in df
for i in range(df.shape[1]):
# Calculate % of cases that tagged the item
val_counts = df.iloc[:,i].value_counts(normalize = True)
if item in val_counts.index:
item_counts = val_counts[item]
else:
item_counts = 0
# Add score to dict
item_count_dict["tag_{}".format(i)] = item_counts
return item_count_dict
如果我们应用它,我们得到:
get_rankings(item = "apple", df = fruits_expanded_v1)
## OUTPUT ##
{'tag_0': 0.1111111111111111, 'tag_1': 0.1111111111111111, 'tag_2': 0.2222222222222222, 'tag_3': 0.2, 'tag_4': 0}
如您所见,我们可以使用这种方法很好地执行基于等级的分析。然而,这种方法对其他方法几乎没有用处。因为列不代表单个标记,而是代表一个等级,所以大多数基于标记的操作都无法正常进行。例如,用我们从方法 1 中得到的数据框架计算香蕉和桃子之间的相关性是不可能的。如果这是你的研究目标,使用下一种方法。
方法 2
这种方法更复杂,需要更多的资源。我们的想法是创建一个数据帧,其中的行保持不变,但是每个水果都被分配了自己的列。如果只有 kid #2 命名为 bananas,那么 banana 列的第 2 行将有一个“真”值,而其他所有地方都有“假”值(参见图 6)。我写了一个函数来执行这个操作。它依赖于循环,这意味着它将花费大量时间处理大型数据集。然而,在我尝试过的所有方法中,这是最有效的方法。
def boolean_df(item_lists, unique_items):
# Create empty dict
bool_dict = {}
# Loop through all the tags
for i, item in enumerate(unique_items):
# Apply boolean mask
bool_dict[item] = item_lists.apply(lambda x: item in x)
# Return the results as a dataframe
return pd.DataFrame(bool_dict)
如果我们现在应用这个函数
fruits_bool = boolean_df(
item_lists = fruits["favorite_fruits"],
unique_items = unique_values
)
我们得到了这个数据框架:

图 6 —布尔数据帧。
从这里,我们可以很容易地计算相关性。请注意,“相关性”并不是真正正确的术语,因为我们使用的不是公制或序数,而是二进制数据。要想正确,就用“联想”。我不会。
同样,有多种方法可以将这些水果联系起来。一个直接的方法是皮尔逊相关系数,它也可以用于二进制数据。熊猫有一个内置的功能。
fruits_corr = fruits_bool.corr(method = "pearson")

图 7——皮尔逊相关数据框架。
另一种方法是简单地计算一种水果和其他水果一起被命名的次数。这可以用矩阵乘法来解决。为此,我们需要将布尔数据帧转换为基于 first 的整数。
fruits_int = fruits_bool.astype(int)
然后,我们可以计算频率。
fruits_freq_mat = np.dot(fruits_int.T, fruits_int)
## OUTPUT ##array([[5, 3, 3, 2, 2, 1, 1, 1, 0, 2, 0, 1],
[3, 4, 2, 1, 1, 1, 1, 2, 1, 0, 1, 1],
[3, 2, 4, 3, 1, 2, 0, 0, 0, 1, 0, 0],
[2, 1, 3, 4, 2, 2, 0, 0, 0, 1, 0, 0],
[2, 1, 1, 2, 3, 1, 0, 0, 0, 1, 0, 0],
[1, 1, 2, 2, 1, 3, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 2, 1, 1, 0, 1, 1],
[1, 2, 0, 0, 0, 0, 1, 2, 1, 0, 1, 1],
[0, 1, 0, 0, 0, 0, 1, 1, 2, 0, 2, 0],
[2, 0, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0],
[0, 1, 0, 0, 0, 0, 1, 1, 2, 0, 2, 0],
[1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1]])
我们现在需要做的就是添加标签并将其转换回数据帧。
fruits_freq = pd.DataFrame(
fruits_freq_mat,
columns = unique_items.keys(),
index = unique_items.keys()
)

图 8 —频率数据帧。
如果你正在寻找一个好的可视化,你可以用 seaborn 库创建一个热图。
import seaborn as sn
fig, ax = plt.subplots(figsize = (9,5))
sn.heatmap(fruits_freq, cmap = "Blues")
plt.xticks(rotation=50)
plt.savefig("heatmap.png", dpi = 300)

图 9 —热图。
有了皮尔逊矩阵,我们可以很容易地建立一个水果推荐系统。比如你输入你喜欢香蕉,它会给你推荐一个 maracuja,因为那两个相关性最高(0.67)。你会惊讶于这个简单的方法有多么强大。我已经成功使用多次了。如果你想对频率数据帧做类似的事情,你需要先将数据标准化。然而,这是另一篇文章的主题。
我希望这份指南对你有用,能节省你的时间或启发你。感谢大家的阅读!
处理数据科学项目中的缺失数据
如何不因丢失数据而丢失有价值的信息

这是关于连接点…..它们在数据科学中是真实的。
缺失数据一直存在,一直是个问题。人们通常会根据数据集的大小和问题的严重程度来临时处理这些问题。
由于数据的激增以及随之而来的不可避免的价值缺失,它最*越来越受到关注。人们在如何处理这些问题上很有创意,甚至发表了关于缺失数据问题和处理方法的学术论文。
本文的目的是总结其中的一些讨论和技术,并演示如何在数据科学项目中导航。所以请容忍我。
什么是缺失数据
缺失数据是没有记录在数据集中的值。它们可以是单个单元格中缺少的单个值,也可以是整个观察值(行)中缺少的值。连续变量(如学生的身高)或分类变量(如人口的性别)都可能出现缺失数据。
缺失数据在自然科学或行为科学的任何领域都很常见,但在社会科学研究数据中尤其常见。
在编程语言中,丢失的值被表示为NA或NaN或者只是对象中的一个空单元格。

图:熊猫数据帧中显示为 NaN 的缺失值
缺失数据的来源
那么,缺失的价值观从何而来,它们为什么会存在?
举个例子吧。您正在对受访者样本进行问卷调查;在问卷中,你问了一个关于家庭收入的问题。现在,如果一个回答者拒绝回答这个问题呢?你会编造还是留空白?您可能会将该单元格留空,从而创建一个缺少值的实例。
或者一个丢失的值可能仅仅是由于人为错误引起的。有人可能输入了错误的数据(还记得异常值吗?)在数据清理或探索性数据分析(EDA)过程中被检测到并删除。
在另一个例子中,一些时间序列数据-特别是调查数据集-可能包含缺失的观测值。这可能仅仅是因为在一个系列的一年或几年中没有进行调查。
引起的问题
缺失值肯定是不可取的,但在统计和机器学习项目中,很难量化影响的大小。如果它是一个大型数据集,并且丢失了很小一部分数据,那么这种影响可能根本无法察觉。
但是,如果数据集相对较小,每个数据点都很重要。在这些情况下,丢失数据点意味着丢失有价值的信息。
在任何情况下,通常缺失的数据会造成不*衡的观察,导致有偏见的估计,在极端情况下,甚至会导致无效的结论。
如何处理丢失的数据
预防胜于治疗!
因此,最大限度地减少生产中丢失数据的发生是处理它们的最有效方法。如果你正在进行客户调查,尽量不要让任何一个字段为空,继续跟进未回答的问题。如果样本量很小,确定缺失值的可接受阈值。如果超过了阈值,则扩大样本量。设计实验或收集数据,明确地以最小化缺失值为目标。
如果不可避免,以下是处理缺失数据的一些其他常用方法:
- 案例删除:如果数据集相对较大,则删除带有缺失值的完整记录
- 替换:用(a)列*均值、(b)最*邻居的*均值、(c)移动*均值或(c)用最后一次观察值填充来替换缺失的单元格
- 统计插补:在给定数据集中其他信息的情况下,回归可能是确定缺失像元值的有效方法
- 敏感性分析:如果样本较小或缺失值相对较大,则进行多变量结果的敏感性分析。
数据科学解决方案
那么它在实践中是如何工作的呢?下面是几个带有 Python 代码的示例。出于演示的目的,我使用了美国大陆上星巴克位置的数据集。
1。检查缺失值
将pandas和numpy库以及数据集作为 pandas dataframe 导入。
# import libraries
import pandas as pd
import numpy as np# import data
df = pd.read_csv("starbucks_location.csv")
您可以用一行代码检查每一列中缺失值的总数。
df.isnull().sum()

您还可以检查缺失值占所有观察值的百分比。
df.isnull().sum()*100/len(df)
2.删除缺少的值
对缺失值的一种处理方法是,如果数据集相对较大且缺失案例较少,则完全丢弃观察值。
# drop all rows containing null
df.dropna()# drop all columns containing null
df.dropna(axis=1)# drop columns with less than 5 na values
df.dropna(axis=1, thresh=5)
3.归罪
您可以根据需要用适当的数据替换丢失的值。有很多方法可以做到这一点,看看哪种方法最适合你的目标。
# replace all na values with -9999
df.fillna(-9999)# fill na values with NaN
df.fillna(np.NaN)# fill na values with strings
df.fillna("data missing")# fill na values with mean of columns
df.fillna(df.mean())# replace na values with mean value of specific columns
df["col1"] = df["col1"].fillna(df.mean)
4.插入
如果是时间序列数据,你可以插值或使用移动*均。
# interpolation of missing values of all columns
df.interpolate()# interpolation of missing values of specific columns
df["col"] = df["col"].interpolate()# using moving average or rolling window
df['col'] = df['col'].rolling(window = 5).mean
最终想法
在这篇文章中,我总结了丢失数据的来源,它们引起的问题以及消除/处理它们的方法。一些统计软件包会在执行统计分析之前自动消除缺失数据,但这并不总是最好的选择。作为一名数据科学家,您需要更好地处理如何处理缺失的观察值,我在本文中强调了一些行业最佳实践。
处理数据产品中的模型不确定性

照片由 Rich Tervet 在 Unsplash 上拍摄,经作者许可编辑
随着软件越来越接*传统行业(想想拼车、金融科技、农业科技等等)。),越来越多的数据产品被构建来支持或自动化通常由人类专家做出的决策。当这种情况发生时,通常会有一个有效的疑问,即一个数据产品是否能够将解决方案自动化到足够高的标准,从而值得投资。
如果不加以管理,这种不确定性可能会阻碍优秀数据产品的生产。要么数据产品的开发方式会严重损害业务,因为数据科学家高估了他们模型的价值,要么人类专家会完全拒绝该产品,永远不会从他们的数据中实现任何价值。
我试图写下一些处理数据产品中设计不确定性的技巧:(a)在你的数据产品中建立参数化或敏捷性,(b)以敏捷的方式发展你的数据产品。这些概念对于产品管理来说通常并不陌生,但当数据科学家发现自己不得不成为自己的产品经理时,我认为从这个角度来表述是有用的。
在我们没有数据的地方建立参数化
我们应该把信用额度限制在 1000 万 PHP 还是 1500 万 PHP?有时,没有数据驱动的方法来回答这个问题,因为我们没有用户对这个政策会有什么反应的例子。领域专家可能也不愿意做出这个数字应该是多少的强有力的决定,但是在典型的软件开发环境中,有一种需求是将用户故事细化到精确的参数。
在这些情况下,最好的做法是花时间将这些决策参数化。我们可以将它们设置为目前有意义的值,但一旦我们有了新的信息,就内置到产品功能中来快速切换该参数(一旦我们有了足够的示例,就用一些机器学习的决策来替换它)。
通过这种方式,产品开发可以向前推进,而不必做出潜在的成本高昂且难以逆转的决策。
换句话说:你可以建立完美的预测,这样你就可以在推出数据产品时准确地知道会发生什么,或者你可以建立瞬间反应时间,这样你就永远不会真正需要预测。
不断发展的数据产品
不是所有的东西一开始都必须是神经网络;事实上,如果你开始一个项目时首先想到的是统计建模或机器学习,你可能会面临很多问题。
处理模型性能不确定性的一种方法是在您的自动化旅程中采取较小的步骤。您可以在这里看到三个不同的层面,在这三个层面上,数据在决策中扮演着越来越重要的角色。虽然从“直觉”到“数据驱动”再到“人工智能驱动”的进展是清晰的,并且可能没有人会发现试图在这个阶梯上前进的问题,但项目往往会在绿框(人工智能参与的水*)中出错。

作者照片
在这里,我们可以从典型的软件(基于规则的逻辑和基于事实的输入)开始,沿着绿色的盒子前进。一旦我们适应并继续收集数据/减少关于如何做出正确决策的不确定性,您就可以在链上前进并向其中添加更多的建模元素。
有两个因素会影响您跨越绿色轴的速度:
- 失败成本 —这是你试图自动化的决策所固有的。担保不良贷款的失败成本将比在电子商务网站上提供错误的推荐低得多。
- 数据完整性 —这是数据工程基础绝对重要的地方。像图像处理这样的问题是数据完整;100%确定某物是狗还是猫所需的任何信息都已经在图像中了。然而,当你试图借钱给某人时,你很难观察到那个人如何管理他/她的财务或经营他/她的生意的每个方面。如果你能以一种便宜且自动化的方式自动化数据收集,那么你就更有可能进步到更高级的决策自动化形式。
那么这一切意味着什么呢?
数据科学课程和训练营中教授的机器学习和人工智能是一种具有非常不确定的攻击面的解决方案(即,我们还不知道它到底适合解决什么类型的问题)。
这就是为什么当不再有大量的宣传时,很难让企业投资这项技术的一个重要原因,即使可能会带来巨大的、改变游戏规则的好处。
为了推进项目,数据从业者需要:
- 通过参数化构建内在敏捷的产品,以及
- 从简单的基于规则的系统一直到完全自动化的决策,以增量和敏捷的方式移动,最大限度地降低风险并在此过程中纳入新数据。
处理我们对新冠肺炎指数增长的系统性误判

Unsplash 上 Fusion 医疗动画
的照片
指数增长偏差使我们无法掌握指数增长的实际动态。让我们看看简单的数据可视化和分析技术。
由迪奥尼西斯·雷维斯和灭霸·巴洛梅诺斯合著。
这篇文章的一个稍加修改的版本首先发表在天秤座 MLI 的博客上,其中包括通过新冠肺炎比较分析工具生成的互动图表
我们人类正在遭受理性判断和理解世界的系统性缺陷。这种感知上的系统性错误被称为认知偏差。维基百科列出了 100 多种经过充分研究的认知偏见,如果你认为这些偏见与你无关,那么,你并不孤单。像我们大多数人一样,你只是受到偏见盲点的困扰,这本身就是一种认知偏见!
人类的直觉很难实现指数增长
随着当前新冠肺炎疫情的持续,困扰全球数百万居家隔离者的认知偏差是指数增长偏差【1】。我们的大脑不具备指数思维的能力。如果我们从前门走 30 步,我们可以很容易地估计我们会到达哪里,但是如果我们走 30 个指数级的步骤,也就是每次走一倍,我们就无法估计我们会走多远。1+2+4+8+16.答案是,我们会绕地球 26 圈!
冠状病毒呈指数传播,而不是线性传播。指数增长偏差使得公民很难评估疫情在他们国家的地位,包括未来几天的潜在后果。我们新冠肺炎系列博文的一个主要目的是展示和提供非专业人士也能理解的交互式可视化和工具,这将有助于缓解指数增长偏差障碍,并揭示支撑新冠肺炎数据的趋势和相关性。
对抗指数增长偏差的可视化方法
在深入研究视觉评估新冠肺炎疫情的方法之前,让我们考虑从 2 月 22 日至今(即 4 月 10 日)的每日死亡报告。我们选择了 5 个国家作为例子:意大利和西班牙,代表遭受严重影响的国家,但它们已经达到高峰,英国和美国,它们在晚些时候受到影响,在感染人数和死亡人数方面仍在恶化,最后,我们有比利时代表受影响病例增加相对较晚的国家。

如果我们绘制每个日期的累计(总体)死亡人数,我们会得到上面的图表。我们得到的印象是,意大利和西班牙的情况相似,英国的情况较温和,而美国的情况在快速恶化。但是,请注意,如果我们回到 4 月 4 日,那么我们只有到那时为止的数据,那么我们可能会得出结论,美国可能会像西班牙和意大利一样。就比利时而言,它似乎经历了一场温和得多且相对得到良好控制的疫情。在这张图表的交互式版本中,可以在原始帖子中找到,您可以在国家选择窗格中包含您选择的国家。这张图表是直观感受指数增长和评估每个国家情况的最佳方法吗?简单的回答是不!
我们建议依靠三种互补的技术:时间校准,使用对数标度和指数拟合。
时间校准
媒体和政策制定者发表声明,如“我们落后 X 国 2 到 3 周”,其中 X 通常是意大利。这种比较,如果正确的话,提供了一个具体的形势评估,并绕过指数增长偏差。
时间排列允许在爆发之间进行可靠的比较分析
要概括这样的比较分析,我们必须将所有国家在时间上对齐,就好像疫情是在同一天开始的一样。有许多方法可以实现这一点。一个不太详细的日期是第一天,即每个国家记录第一个病例的日期。一个稍微好一点的选择是让几个案例累积起来,并使所有国家在一个普通的日子里有一个固定的案例总数,例如 50 个。在下一张图中,我们遵循后一种方法。

我们现在所能得出的结论有了很大的改进。与意大利相比,西班牙的情况显然更糟(至少在第 45 天左右),与西班牙和意大利相比,美国的情况正在迅速恶化。英国的情况和意大利一样糟糕。另一方面,与我们在没有时间校准的情况下观察到的情况相比,比利时的情况似乎更糟。
当比较在时间上相隔很远或在发展的早期阶段发生的疾病爆发时,时间比对更为有益。
对数标度的使用
虽然时间排列揭示了每个国家疫情爆发的灵活性,但有一个明显的问题需要解决。每次疫情爆发的早期都被压缩在图表底部附*,很难进行比较。这是不可避免的,因为指数增长的本质,它需要一段时间才能开始,但不久,它就会飞速增长。接下来描述了这样一个例子,涉及美国、西班牙和希腊的确诊感染。

显然,很难对美国和西班牙疫情的早期阶段进行比较,对希腊的任何直观评估都是不可行的。
解决方法是将图表的纵轴从线性刻度改为对数刻度。这意味着,不是线性上升,而是 10,20,30…,1000 等等。以指数方式增加,例如 10 的幂,(10,100,1000…)。除非你精通数学,否则很难理解这一点。在对数尺度上可视化数据时,只需要带两件东西;a)我们在纵轴上保留的用于可视化情况 1 至 10 的空间等于我们为情况 11 至 100 或 101 至 1000、1001 至 10000 等保留的空间。这很有帮助,因为我们现在可以为与每次爆发相对应的小数据值提供更多空间。b)如果一个国家的病例呈指数增长,那么在对数尺度上,它们将出现在一条直线上。在以后的文章中,我们可能还会调查对数标度表示的潜力,揭示每个国家采取的最有影响力的遏制措施。让我们看看当纵轴是对数标度而不是线性标度时,前面的例子是怎样出现的:

解决了小值的混乱。一个额外的优点是,我们可以很容易地计算出每个国家将报告病例增加 10 倍所需的天数,比如从 1.000 到 10.000。我们只需要计算相应网格线之间的点,这揭示了在疫情的早期阶段,西班牙确诊病例的上升速度比美国要快。西班牙从 100 到 10000 用了 15 天,而美国用了 17 天。之后,西班牙的增长率放缓(从 10.000 到 100.000 又需要 15 天,而美国只需要 9 天)。
对数标度在关注疾病爆发的早期阶段是有益的
最常见的是,当冠状病毒传播与指数增长相关时,隐含着固定增长率的指数增长。增长率表示每天病例增加的百分比。10%的增长率意味着,如果你有 100 个案例,第二天就会有 110 个,或者当你有 1,000,000 个案例时,第二天就会有另外的 100,000 个案例。在对数标度图中,这意味着从对数标度图的一条网格线到下一条网格线需要相同的天数,这相当于所有的点都在一条直线上。幸运的是,真实数据显示,这种行为只是在疫情的早期阶段,比如在美国,从 100 例到 20,000 例,才是大致准确的*似值。此后,增长率越来越低,原因有几个,包括各州为遏制疫情采取的过度措施,以及病毒感染新人的能力逐渐降低,要么是因为潜在候选人生病并康复,因此具有免疫力,要么是因为他们去世了。
指数拟合
无法掌握指数级进化的现象意味着什么?这意味着当你有从 A 日到 B 日的一系列数据时,我们无法想象接下来几天的数据。那么,预测建模的帮助来了!我们可以采用一个被约束为服从指数增长行为的模型,并以数据驱动的方式(即使用从日期 A 到日期 B 的可用数据)对其进行调整,以使其最适合。这个动作被解释为:在所有可能的指数增长曲线(无限的)中,找到并使用尽可能紧密跟随可用数据的曲线。
假设固定增长,指数拟合估计预期的未来病例数
让我们以美国为例,找出最符合前 1.025 例确诊感染数据的指数曲线,即垂直虚线所示的 3 月 11 日(“使用至今的数据”)。

薄的透明曲线是预测的指数曲线,正如可以看到的那样,非常适合直到 3 月 27 日,其中病例总数约为 85.000。而且,如果我们用新冠肺炎比较分析工具复制这个图表,悬停在美国的指数曲线上,我们得到预测的指数拟合的增长率,是 32.51%。这意味着,据预测,美国每天的确诊感染人数比前一天增加了 32.51%。幸运的是,感染的真实增长率不是固定的,在 3 月 27 日之后,估计模型偏离真实数据,增长率下降。
家庭作业
假设 X 国的增长率固定为 10%。从 10 个案例到 1000 个案例需要多少天
如果你的答案是 100 天,不要担心,这是指数增长偏差造成的!
参考
【1】利维,M.R .和塔索夫,j . 2017。指数增长偏差和过度自信。《经济心理学杂志》, 58 ,第 1–14 页。
这个好例子摘自彼得·迪亚曼迪斯和史蒂文·科特勒著的《富足:未来比你想象的更好》,西蒙和舒斯特出版社,2012 年。
编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
提交研究论文后如何应对审稿人的拒绝
会经常发生的!

我要从头开始吗? 知识共享 4.0 BY-NC
你花了几个月甚至几年的时间,小心翼翼地将你的研究成果写成论文,提交给同行评议的期刊。你提心吊胆地等了两个月到 18 个月(迄今为止我的最小和最大范围),想听听你认为会成为你领域专家的人的意见(并不总是不幸的)。你们中的一些人担心自己的作品不够好,评论者会指出致命的缺陷。在他们内心深处的其他人会认为或者至少希望评论者会认识到他们有多聪明。通知来了,你的心沉了下去。编辑礼貌地拒绝了发表你作品的机会。
应对拒绝——接下来该怎么办?
尤其是研究生问我的最常见的问题之一是,在收到一封附有详细评论的拒绝信后,下一步该怎么做?首先要注意的是,拒绝是非常普遍的,所以不要过度担心。我仍然记得我在读博士时收到的第一个审稿人的评论。一位评论家的语气让我大吃一惊。他们似乎没有抓住论文的重点,表现得极其粗鲁和傲慢。
当时,我并没有意识到审稿人和编辑的评论会有多么多变。审阅过程可能非常随机,很难在多个审阅者之间获得一致性,如果编辑要让您进入下一阶段,通常需要这种一致性。事实上,在经济学领域,假设你的论文会被拒绝通常是最好的,尤其是如果你是一名早期职业研究员。这并不意味着你不应该期望发表你的论文,而是可能需要*均多次尝试,尝试的次数将取决于论文有多好,你在期刊选择方面有多雄心勃勃,以及你有多幸运。这里坚持是真正的关键。
在重新提交给另一个期刊之前,我应该对我的论文做些什么修改?
我收到了来自拒绝我论文的审稿人的非常有见地的评论,但我也收到了非常无用的评论,这些评论似乎在很大程度上反映了他们自己的主观偏见和成见,而不是对具体论文的优点或其他方面的任何仔细评估。作为一名研究生,很难分清哪个是哪个。我注意到有些人完全忽略了评论者的评论,直接重新提交到其他地方,而其他人可能会花几个月的时间在重新提交之前尽可能多地处理评论。
在决定如何做时,将审稿人的意见分为三大类可能会有所帮助,这种分类适用于任何特定论文的程度当然会有很大不同。
1。极有帮助
这可能采取的形式是被指向你不知道的新的相关文献。一个新的潜在渠道,可以帮助解释主要结果。一种稳健性或敏感性检查,可以进一步增加调查结果的权重。一个重要的方法细节被忽略或没有非常清楚地提出。关键论点表述不一致。一个未曾想到的关键政策含义。一般来说,那些不厌其烦地提供像这样有帮助的评论的评论者也会小心翼翼地用一种通融的语气来表达。话虽如此,即使语气似乎很严厉,也要试着超越这一点。
2。很少或没有用
这些完全没有抓住论文的要点。很难简单地描述,但可能采取对整个研究领域(如幸福经济学)或方法(如我不喜欢调查)的敌对评论的形式,而不是对具体论文的优点进行评估。评论也可能反映了这样一个事实,即该评论者有一篇与之竞争的论文,或者仅仅是这篇论文与他们以前的工作相矛盾,这反过来可能会损害(通常是无意识地)评论的公正性。居高临下或幼稚的评论——这通常采取批评方法的形式(例如使用固定效果),同时误解其实际涉及的内容,并经常使用高人一等的语气试图说服编辑他们有多么博学。更广泛地说,试图用过于复杂的批评和“抓住问题”的心态来打动编辑也是很不幸的。
3。之间的东西
我发现这些评论与写作风格和结构有关。例如,通过扩展背景部分,你可以更仔细地阐述与任何相关的丰富文献,这份报告将会有很大的改进。浓缩结论。扩展结论。你把 X 解释得太详细了。你解释的太详细了,等等。等等。
我的建议是,在重新提交之前,尽量处理好上面 1 条中的评论。审稿人和编辑之间的差异当然非常非常大(在未来的帖子中会有更多),但即使在与新审稿人打交道时不太可能出现这些相同的评论,你的论文也会通过考虑这些要点而得到加强。这反过来可能会增加未来评论者对你论文的喜欢程度。同样很有可能的是,同一位审稿人被要求再次审阅你的论文,他们很可能会欣赏你在回应他们的意见时所做的任何修改,或者如果你没有采纳他们的意见,他们会感到恼火。我建议安全地忽略第二类评论。他们不会改进你应该关心的论文。的确,你可能会再次得到同一个评论者,但很可能无论你做什么,评论者都会再次发现一些【致命缺陷】,并建议拒绝。
是否处理最后一类中的任何评论是一种*衡行为。你能做的任何提高论文清晰度的事情都会增加你的机会,但是有收益递减。你必须意识到所涉及的时间,特别是如果你还有新的研究机会去追求的话。同样值得记住的是,例如,如果一个评论者为一个更详细的阐述提出了令人信服的理由,另一个评论者可能会觉得有太多的细节掩盖了你的关键贡献。因此,如果你不小心的话,你可能会有点追不上你的尾巴。
虽然来自评论者关于风格和结构的评论可能是有帮助的,但我发现时间的流逝通常比任何评论者的评论更有效。当我收到拒绝后再次看论文时,我几乎总能找到各种方法让我的文章更清晰。事实上,即使我没有发现审稿人的评论特别有启发性,但我在收到拒绝后六个月彻底修改论文的情况并不少见。这可能反映了这样一个事实,即写作的清晰度在不断提高,我自己对相关主题的知识也可能在这段时间里有所提高,没有什么比用新的眼光看待事物更好的了,即使它们是你自己的。
亲爱的企业,首先是完美的电子表格和 SQL
让数据科学更贴*企业,并为企业的成功做好准备

让我们面对现实吧。尽管围绕数据科学已经炒作了几十年,但任何企业都很难采用它。
但是为什么呢?
如果你回到任何一家公司的历史,你首先会看到一个最独特的产品(MVP)的诞生。然后,支持公司可伸缩性的部门,如营销、运营和产品(包括工程)进入场景。接下来是让公司承担责任的支持部门,如财务和人力资源部门。一旦你获得了牵引力,你可能最终会开始考虑是否有一个专门的分析团队来为你构建可持续的报告。如果你愿意,可以称之为“支持支持部门”。
自从哈佛商业评论称“数据科学家”是 21 世纪最性感的工作让学习者一头扎进数据科学 101 以来,无数的在线课程、博客和教程视频激增。因此,我们创造了一群“数据科学”员工候选人。雇主呢?雇主是否知道公司正处于雇佣合适人才的哪个阶段,这些人才将推动公司利用数据科学?
在本文中,我将使用一个轶事来概述许多企业中的一个常见场景,并且我将讨论许多公司在为数据科学做好准备之前所经历的阶段。如果您希望了解更多关于让数据科学与任何业务相关的信息,请点击本文末尾的相关资源超链接。
介绍…Excel,您的测试版报告的诞生地
我们都经历过。当我们渴望知道答案,并且现在就想知道答案的时候。我们有这 6 个月的销售数据,我们只想知道收集的指标(客户详细信息,如年龄、居住地、他们选择的产品、支付的价格、他们成为客户多久了,等。给我们介绍一下我们的业务。
因此,我们打开一个新的工作表,开始键入我们已经有的 10 行,或者从已经很好地将其放入表格的人那里复制。或者进阶导入一些。csv 文件导入到电子表格中。

作者图片:贵公司的第一张纸 1
你可能不需要用图表来告诉你,在你的前 10 个(特殊的)客户中,3/10 来自多伦多(6/10 来自东海岸)。“苹果”是你最喜欢的产品,其次是“桔子”。你的*均客户生命周期是 4 个月。在 6 个月的时间里,这 10 个客户中,你总共从他们身上赚了 540 美元。
这就是了。你不需要一个分析团队,因为你还负担不起,数据样本仍然很小,你和电子表格可以一起完成这项工作。
大约 2 到 3 年后,“伟大的电子表格”诞生了
业务增长了,你,创始人,雇了一个分析师(Linda ),他会为你汇总所有的销售数据。首先,你教她你是如何做报告的,然后你给她一个方向或一个要求,她有自主权以她自己的方式构建报告。
GIF via GIPHY
除了这一次,你注意到报告上的数字一点也不一致。你让琳达重新做报告,但是数字看起来还是不太对。你试图进一步调查,要求她发送她用来整理报告的原始数据,但这太过分了。她从这份极其丰富多彩的报告中复制并粘贴了一行,并在至少两张纸上做了一个又一个 Vlookup,以首先获得参考文件或映射,然后获得数字。由于无法承受大量的手工工作,Linda 在处理了两年的报告后辞职了。
你的新员工 Jerry 受到了 Linda 和其他人创建的“伟大的电子表格”的欢迎。他开始做的正是琳达所做的,即使在周末也非常努力。又过了半年,Jerry 向您提出了对数据仓库的需求,并请求您提供资金。有趣的是,你问 Jerry 他是否解决了他一直激烈批评的“大电子表格”问题。
杰瑞有备而来。
他列举了自己为移除“大电子表格”所做的基础工作:
- 定义一个业务流程和所需的核心数据。 对于已经升级为成本报告仪表板的销售数据,他每周都会将供应商的发票(他让他们按照一定的格式)下载到一个 google drive 中。他一直在和工程团队的伙伴聊天,他正在学习如何按计划有计划地下载发票。其次,他与市场部建立了一个共享的 google sheet,这样他就可以收集客户订购的东西,并进行严格的数据验证,以标记无效的值。随着客户数据的积累,他根据日期将历史数据分块归档。
- 从简化的数据处理中自动构建报告。
财务部门需要供应商的发票来调节任何差异,因此他为他们提供了查看权限。在幕后,他在 Google Apps 脚本中有一个脚本计算,以方便对账,他将一周内所有订购产品 X 的客户与产品 X 的发票总额进行匹配。这解释了当客户订单和发票金额之间的数字不一致时,您在仪表板上看到的条件格式。他刚刚开始将运营成本纳入仪表板,以进一步帮助财务部门和您分析额外的业务支出。 - 记录整个业务流程,让事情变得简单。他很快意识到他不能仅仅因为知道东西在哪里就花一整天来回答人们的问题。他已经在管理数据的每个驱动器中创建了文档,因此用户可以在开始使用驱动器中的数据之前进行自我指导。随着他的所有权的增长,他审查和编辑他的关于新的或修改的业务流程的文档,并且如果其他用户没有遵循某些指导方针并最终得到糟糕的报告,他通常能够让他们承担责任。
你对此深信不疑,接着问 Jerry 为什么需要数据仓库。
Jerry 向您解释说,自从他加入以来,无论是产品数量、客户数量、运营成本类型还是其他方面,数据都在增长。当电子表格随意放置时,做更多的映射和 Vlookups 也变得越来越困难,而数据仓库可以通过连接轻松解决这个问题。他已经建立了一个系统来简化向数据仓库的迁移,因为他还有一整套 SQL 技能没有充分利用。
再见,伟大的电子表格;你好,SQL 数据库
在您批准了 Jerry 的数据仓库提议之后,您已经看到他再次忙于将数据推入数据仓库。您有幸成为第一批登录数据仓库的用户,了解他的数据迁移情况。他已经对您进行了关系数据库和 SQL 的一些基础培训,因此您了解了如何浏览表和运行一些查询。
欢迎您的是组织有序的模式和表。您可以看到customer,和类似customer_address, customer_orders的客户周围的维度表。在customer_orders,下面,您可以看到每个product_id都与每个订单相关联。更简洁的是在supplier模式下,你甚至可以看到supplier_product_id到product_id.的映射,你肯定财务部门看到这个也会非常兴奋!当然,operations模式仍在构建中,但是已经可以看到一个计划将product_id映射到每个cost_type的表。
Jerry 告诉你,在未来,他不再需要担心他的“电子表格管道”是否能正确地将数据输入到仪表板中。他只需要将仪表板与查询挂钩,该查询将为他提供电子表格管道所能提供的一切,如下所示:
SELECT date,
customer_firstname,
customer_lastname,
customer_address,
product_name,
customer_ordered_price,
SUM(customer_ordered_price) OVER (PARTITION BY product_name, date) AS ordered_product_total,
SUM(supplier_invoiced_price) OVER (PARTITION BY product_name, date) AS invoiced_product_total,
ordered_product_total — invoiced_product_total AS total_delta
FROM product_supplier_joined_view
WHERE SUBDATE(NOW(), INTERVAL 7 DAY);
尽管在工程团队开发进一步简化 Jerry 定义的业务流程的应用程序之前,电子表格仍然需要作为数据收集和转换的权宜之计,但这只是从应用程序而不是电子表格切换管道数据的问题。
Jerry 还提醒您,仍然有许多优秀的电子表格放在各个部门,因为这是每个人在处理临时报告时感觉最舒服的地方。他相信,只要有业务需求,并且业务需求被明确定义,他就能够通过将新数据合并到他的数据仓库中,将临时报告转变为常规报告。
好吧,我们可以开始数据科学了吗?

Artem Maltsev 在 Unsplash 上拍摄的照片
尽管如此,这个轶事是一个关于企业如何尝试数字化转型的理想主义案例研究。通常,“伟大的电子表格”是一个集体的努力,每个利益相关者可能有他们对报告格式的解释。数据收集过程可能根本不存在(例如,供应商发票仍然在纸面上或非结构化的 PDF 文件中)。您的分析师当时不具备所需的技能,也不具备简化报告渠道的远见。工程团队可能很难实现迎合业务需求的变化。现实世界是复杂的,你可能会在很长一段时间内被“伟大的电子表格”所困扰,直到有领导带领你远离它。
假设一家公司或多或少遵循了理想场景,它将更有能力开创数据科学。任何导致新流程的业务变化都意味着整个流程(数据收集、数据转换、数据消费)都应该经过深思熟虑的设计和记录。数据集成只是使数据对数据消费者可用的过程的一部分。例如,如果 Jerry 决定与公司的竞争对手进行价格匹配,他将需要确定在哪里以及如何(经常)获得数据,并在修改标识符后将其合并到他的数据仓库中,然后将该报告提交给相关的利益相关方。
本·韦伯撰写的“创业公司的数据科学”系列是游戏和金融科技行业经验丰富的数据科学家将他在公司建立数据基础设施的旅程转变为工具书的一个例子。
我最*换了行业,加入了一家初创公司,负责建立数据科学…
towardsdatascience.com](/data-science-for-startups-introduction-80d022a18aec)
韦伯用一种非常有趣的方式描述了“数据管道的演变”。我还认为数据本身经历了一次进化:
- 手动电子表格时代:分析师和数据制作者开始创建一个电子表格生态系统,它可以很好地处理几兆字节的数据,并且在处理临时报告时非常用户友好
- 公式/宏时代:增加了更多的业务逻辑,数据增长了,可以通过公式将数据“查询”到另一张表中作为参考。某些循环计算,映射,或格式可以写在谷歌应用程序脚本/VBA。
- 数据库时代:处理 8 张以上的 Vlookup 或等待后台宏完成运行不再是可持续的,处理数据的 web 应用程序可能已经启动,因此数据可以从 UI 或 API 导出。
虽然我同意 Weber 的观点,即由于可扩展性问题,公司应该尽最大努力避免电子表格,但我认为电子表格对于企业来说就像 SQL 对于数据库一样,是一种不会很快消失的通用语言。此外,除非证明报告原型对决策者有用,否则通常不会有正式的业务流程和工具支持,如 web 应用程序和/或数据库。有点进退两难的局面。
猫演示第 22 条军规
为了避免这种进退两难的局面,也为了避免让更多希望专注于更多统计建模(和更少的数据清理)的人才失望,我们必须从解决需求层次的底层开始。大多数企业不一定有那么多数据源(例如“测井”、“传感器”等。除了“伟大的电子表格”,所以在更精简的流程出现之前,没有任何捷径可以让电子表格系统尽可能地保持有序。
最后但同样重要的是,一份好的报告通常来自一个好的问题。除了报告可以回答的一些描述性测量(例如,这个月的销售额是多少?我们有什么样的客户统计数据?),还有说明性的衡量标准(例如,本月我们的活动有多少浏览量?我们产品的价格是如何波动的?).每当我们试图度量任何业务度量时,我们必须问自己这个特定的业务度量意味着什么,以及对它进行实验是否会影响或产生额外的业务度量。伊森·诺克斯的文章中有更多很棒的例子。
利用信息是一种熟练的行为,而不是数据产品的输出。
towardsdatascience.com](/is-your-company-too-dumb-to-be-data-driven-696932d597c3)
只有这样,我们才能正式进入数据科学的领域。
离别的思绪
如果你正在读这篇文章,你一定听说过关于数据科学的炒作。关于“洞察力驱动的企业”、“用机器学习预测你的企业”和“人工智能如何加速信息时代”的头条流行语。但帮助企业实现数据科学的最新分步指南仍然缺失。
为了将企业纳入这一系列数据科学宣传中,我们需要开始关注的是,在“数据驱动”之前,首先努力做到“数据就绪”。
“遗留系统”也可能意味着电子表格的海洋,其组织关系到向数据库迁移的容易程度。即使在 SQL 数据库启动并运行之后,还有一系列全新的问题,例如与其他数据源集成,以继续开发新的或现有的数据产品。
暂时忘掉数据驱动吧,您的公司是否有可靠的数据基础架构,数据是否衡量正确的事物?
我想用另一篇哈佛商业评论文章中的一段话来结束这篇文章,这篇文章强调了数字化转型的挑战。
成功需要汇集和协调比大多数领导者所意识到的更大范围的努力。在四个相互关联的领域(技术、数据、流程或组织变革能力)中,任何一个领域表现不佳,都可能破坏一项精心策划的变革。真正重要的事情,从创造和传达一个令人信服的愿景,到制定一个计划并即时调整,再到钻研细节,都与人有关。
多年来,我们参与、建议或研究了数百次数字化转型。这样做,我们已经…
hbr-org.cdn.ampproject.org](https://hbr-org.cdn.ampproject.org/c/s/hbr.org/amp/2020/05/digital-transformation-comes-down-to-talent-in-4-key-areas)**
文章中未直接引用但仍然相关的资源:
我的前一篇文章已经讨论了数据工程为什么以及如何帮助一个组织“数据就绪”。
我如何改变策略来帮助企业启动其数据基础设施和报告渠道
towardsdatascience.com](/voicing-for-data-engineering-the-unsung-hero-b91b6ef39dcd)
如果您想阅读更多关于以下方面的深度文章
- 电子表格最佳实践
- SQL 数据库的威力和局限性
- 如何在公司中扩展数据分析
请在下面评论,并随时让 Iris Huang 了解贵公司如何处理数据!😃**
亲爱的科技界白人同胞们:别说了。

帕特里克·托马索在 Unsplash 上的照片
我曾经坐在联合神学院的课堂上听康乃尔·韦斯特博士的讲座。他的话是预言诗;赋予黑人解放神学生命的口语诗。每堂课,他都会毫无例外地感谢那些他称之为自己黑人血统的人:爵士乐英雄、哈丽雅特·塔布曼、吉米·鲍德温(他这样称呼他),布鲁斯传统的伟大巨人,这样的例子不胜枚举。对韦斯特博士来说,如果不赞颂那些精神祖先为之奋斗的解放,就没有未来的解放。我会坐在教室里,作为一个 22 岁的白人,刚从大学毕业,被这股强大的力量对所有前人的热情和尊重所迷惑。
最*,我的同事 Timnit Gebru 博士在推特上发布了一个链接,链接到 machinelearningknowledge.ai 于 2019 年 11 月 24 日发布的时间表。这个时间线概述了“从 1943 年到 2019 年的深度学习简史。”格布鲁博士的推特上写道,“深度学习的男性专属历史,你说 AlexNet 创造了历史,但 ImageNet 没有,因为女性的贡献不算数。以及除了白人和白人邻居之外的任何人的贡献。”我很好奇格布鲁博士指的是什么,所以我很快点击了链接。
作为一名人工智能伦理的人类学家,以及一名研究深度学习发展史的人,我喜欢认为我对这样一条时间线上可能会发生什么有很好的感觉。但是我看到的让我震惊。在这个时间线上,没有一个女性被承认,只有两个非白人被承认(其中一个是围棋手,不是研究人员),也没有解释为什么。
让我们明确三点:
- 代表性很重要。
我们看到的代表人物改变了我们对历史、现在和未来的看法。作为一个领域的创始学者,我们提拔的人对未来谁会被吸引到这个领域以及这个领域未来会提出什么问题有着不可估量的下游影响。
2。事实很重要。
这不是一个简单的时间表,没有非白人非男性学者在该领域的好例子。费-李非博士通过她的研究创造了 ImageNet,从而永远改变了深度学习领域。达芙妮·柯勒博士首先在确保各种经济背景的学生能够从事以深度学习为基础的职业方面取得了巨大进步。Latanya Sweeney 博士在大数据应用于深度学习及其在隐私和安全领域的应用方面做出了不可估量的贡献。这个清单还在继续(应该有一天会全部写完!)
3。这是常态,不是例外。
这个时间线内的单一身份表示并不是深度学习历史的唯一讲述。这篇文章绝不是 machinelearningknowledge.ai 上的热门文章。不幸的是,他们的时间线是一个缩影,表明工业界和学术界显然默认白人男性的贡献高于女性和有色人种的贡献。当我在会议上与同事讨论深度学习的演变时,我们很少以女性或有色人种对该领域的重要贡献开始深度学习的故事,尽管有很多。
我们现在讲述的历史是一个道德声明,一个政治声明,一个哲学声明。我们如何讲述深度学习等领域的创始学者的故事,是我们对该领域过去、现在和未来价值的陈述。忽视女性和有色人种在该领域发展中的贡献是一个事实上的错误。然而,这也是违反道德的。
这是一篇适合所有人的文章,尤其是那些参与讲述技术发展故事或自己开发技术的白人男性。作为一个科技行业和学术界的白人,我想说以下的话。作为白人,是时候让我们的贡献去中心化,去支持那些在历史上被技术领域边缘化的人们的贡献了。毫不含糊地说,这意味着有意放弃机构权力,将我们从聚光灯下解放出来,最重要的是,在每一个层面上努力讲述那些在 — 之前来到这里的人的故事。
我离开了韦斯特博士的班级,更多的时候是试图回忆起我自己的祖先,那些用意志把我塑造成的人。纪念逝去的人是一种精神修行。我们必须挑战自己,完整地讲述前人的故事。此外,由于我们生活在的社会政治历史的阴影下,我们必须确保我们的研究积极地、毫无歉意地集中于那些被殖民时代悲剧性地隐藏起来的故事。
到目前为止,这篇文章一直在用华丽的方式简单地说:亲爱的技术领域的白人同胞们——别说了。别生气。不要自卫。不要再删除那些你不是主角的故事了。
自动驾驶汽车,如何应对不确定性?
不确定条件下的强化学习优化。
在这里,我与卢卡斯·沃格特、简·杜门和克里斯托弗·弗里贝尔一起展示了这项研究。
TL;技术系统的控制可以在模拟中得到优化。然而,事实上,无数的未知在等着我们。在这篇文章中,我们展示了噪声和传感器误差的增加如何影响强化学习代理的优化结果。

动机
“安全总比后悔好!”
大多数汽车司机都遵循这种想法,因为从长远来看,有时获得一个次优的结果比每次争取一个最佳结果更有利。例如,驾车者很少将车辆的性能发挥到极限,他们更愿意将可能导致事故的误判的可能性降至最低,并接受他们将比理论上可能的时间晚到达目的地的事实。在自动驾驶的发展过程中,这一观察提出了自动驾驶汽车的控制算法在考虑不确定性的情况下如何表现的问题,特别是因为不确定性可能导致误判,从而导致不当行为,这可能导致事故。
远程控制
试试我们新的远程控制环境
towardsdatascience.com](/do-you-want-to-train-a-simplified-self-driving-car-with-reinforcement-learning-be1263622e9e)
作为我们之前提到的问题的研究的基线,我们使用了 OpenAI 健身房的 LongiControl 环境[1],它提供了一种通过强化学习(RL)来训练代理的容易实现的可能性。我们将在以下段落中总结有关 LongiControl 的关键事实,但您可以在我们的第一篇文章 此处 或已发表的论文 此处 中找到更多信息。另外,你可以自己尝试一下 LongiControl,源代码可以在 GitHub 这里 找到。

远程控制环境
关键事实在远程控制环境中,车辆的目标是在给定时间内尽可能节能地完成单车道路线,而不造成事故。总之,这对应于在从 t₀ 到 T 的间隔中使用的总能量 E 的最小化,作为功率 p 的函数:

根据外部要求,如其他道路使用者或速度限制,必须同时满足以下边界条件:

其中 v 为速度, a 为加速度,a_dot 为急动度,其中()ₗᵢₘ,ₘᵢₙ和()ₗᵢₘ,ₘₐₓ分别代表下限和上限。因此,RL 代理试图通过他选择的动作来满足所有这些标准,同时最小化车辆的总能量消耗。
为什么要考虑不确定性?
并不是所有发生在现实世界应用中的影响都可以提前看到。未来是未知的,传感器误差会突然出现,最小的偏差都会导致不希望的结果:
为了弥合现实世界中的代理行为和模拟中的自动驾驶之间的差距,将现实的不确定性融入到模拟中是很重要的。这一研究领域通常被称为“ Sim 到 Real Transfer ”,如果你想了解更多,进一步的例子在[2]和[3]中给出。这一努力的第一步是在 RL 代理的训练环境中实现随机噪声和干扰。结果,典型的代理-环境交互的流程图现在看起来与通常不同。代理请求的动作和环境的新状态都通过随机发生的干扰来修改。

图 1:没有不确定性的主体-环境相互作用

图 2:具有不确定性的主体-环境相互作用
实现的不确定性
我们选择实施以下四种不同类型的干扰,以在代理的训练过程中制造不确定性。
S 在我们的场景中,滑移是重要的,因为它影响车辆的加速度,即代理的动作。

图 3:滑移对代理行为的影响
速度传感器的暂时故障是一种不太可能但有可能发生的事件,通常由传感器和控制板之间的数据传输错误触发。环境的状态向量包含车辆的当前速度。因此,智能体的行为对速度变化很敏感,需要学习如何处理当前车速的不确定性。

图 4:传感器故障对代理行为的影响
图 4 显示了暂时故障速度信号在 3 个位置的影响。从而速度值突然跳到零,然后再次显示正确的值。车辆在这些点继续行驶。只有强化学习代理接收到临时故障信号。
故障交通标志检测包含两种不同类型的随机干扰。首先,错误检测交通标志,尤其是速度限制。摄像机系统可以将给定的 50 公里/小时的速度限制识别为 60 公里/小时。这些错误可能导致代理对其环境的错误假设,这可能导致代理的不适当行为。正如您在图 5 中看到的,对即将到来的速度限制的不确定性导致了小的加速和减速交替阶段。这是由于希望在不同速度区之间建立*滑过渡,但即将到来的速度限制(过渡的目标值)是不确定的,因此过渡过程变得不确定,即显示随机偏差。

图 5:故障交通标志检测对代理人行为的影响
其次,直到下一个速度限制的距离的不精确测量。代理通过环境的状态向量接收这个距离,并相应地选择他的动作。距离信息对于确保不同速度限制的区域之间的*滑过渡而不超过当前速度限制是必要的。由于这些不确定性,代理人无法准确预测下一个速度限制生效之前还剩多少时间。因此,他开始加速汽车,以确保*稳过渡到下一个速度限制,但在加速后不久,代理人决定减速汽车,以避免因超速而受到奖励处罚。这个循环重复几次,因为代理基于不确定的(错误的)信息过早地启动了加速过程。

图 6:错误的距离测量对代理行为的影响
不确定条件下的优化

不确定情况下的行为
正如所料,在随机干扰环境中接受训练的智能体,在不确定的环境中比没有处理随机事件经验的标准智能体表现得更好。从图 7 和图 8 中可以看出,尽管环境嘈杂且行为随机偏差,但受过不确定性训练的智能体避免了超速。

图 7:没有不确定性的训练的代理

图 8:带着不确定性训练的代理
没有不确定性的行为
有一个考虑到可能的随机偏差影响的代理,并不意味着代理应该总是在有干扰的情况下工作。因此,在某个环境中没有偏差的行为也是智能体能力的一个有趣指标。在图 9 和图 10 中,您可以看到两个代理在无偏差环境中的行为。显而易见,不确定代理人与限速保持安全距离。通过这种行为,如果意外的随机偏差导致汽车突然加速,这将导致超过当前速度限制,则代理获得短时间的反应窗口。

图 9:没有不确定性的训练的代理

图 10:带着不确定性训练的代理
通过不确定性进行行为控制
不确定性的实现,除了增加训练过的代理的鲁棒性之外,还提供了在不改变回报计算结构的情况下改变代理的行为的可能性。为了训练代理,其行为可以在通过最终用户的训练过程之后被改变,有必要在训练期间改变所实现的不确定性的参数(例如,标准偏差或期望值)。例如,随机干扰的标准偏差越大,导致的防御行为越多,因为代理人期望抵消更大的偏差。因此,最终用户通过选择不同的行为模式来改变代理人的期望。所选择的行为模式改变环境状态向量中的值。该值影响分布的标准偏差和期望值,用于计算不确定性的随机影响。在图 11、12 和 13 中,你可以看到代理人的期望是如何影响最终行为的。

图 11:预期的大偏差→防御行为

图 12:预期的正常偏差→正常行为

图 13:预期的小偏差→攻击行为
摘要
在本文的最后,我们将总结最重要的几点。
在我们的第一篇文章中,我们展示了在建议的 RL 环境中,它适应于 OpenAI Gym 标准化,很容易原型化和实现最先进的 RL 算法。此外,LongiControl 环境适用于各种检查。除了 RL 算法的比较和安全算法的评估,在多目标强化学习领域的研究也是可能的。在我们的第二篇文章中,我们展示了不确定性对受过训练的代理人行为的影响。我们表明,不确定性本身就足以实现具有不同行为的智能体,并且不确定性可以对智能体的训练速度产生积极的影响。未来可能的研究目标是与已知路线的规划算法进行比较,并考虑非常长期的目标,如在特定时间到达。
LongiControl 旨在使社区能够利用强化学习的最新策略来解决自动驾驶领域的现实世界和高影响问题。

享受使用它😉
参考
[1] G. Brockman 和 V. Cheung 和 L. Pettersson 和 J. Schneider 和 J. Schulman 和 J. Tang 和 W. Zaremba,开放健身房 (2016),CoRR
[2]薛斌鹏(音译),具有动力学随机化的机器人控制的虚拟到真实转移 (2017),CoRR
[3] JoshuaTobinu.a .,将深度神经网络从模拟转移到现实世界的域随机化 (2017),CoRR
[## 德国萨克森州 Roman liener-Dresden |职业简介| LinkedIn
查看 Roman liener 在 LinkedIn 上的职业资料。LinkedIn 是世界上最大的商业网络,帮助…
www.linkedin.com](https://www.linkedin.com/in/roman-ließner-56346113b/)
亲爱的 Spotify——你为什么认为我是右翼?
一篇关于参差不齐的数据,缺乏对板球的热爱,为什么这会导致糟糕的体验以及如何解决它的帖子。
或者更准确的说,为什么你觉得我既是“政治—强左 _ 美”又是“政治—强右 _ 美”?
也许我的播放列表中有太多的机器引起了我的愤怒?或者还不够?
这是一篇关于下载你的数据档案(“GDPR 功能”)并看看下面是什么的帖子。这不是关于 Spotify 本身,公*地说,他们也有很多关于我和我对他们服务的使用的数据,这些数据非常准确,而是关于整体数据市场的现实,以及了解复杂公司的数据基础,这为我们作为消费者提供了很多有针对性的产品和体验。
在这篇文章中,我使用了一些来自我自己的数据导出的荒谬数据,因为它显然是不敏感的,与我无关,也不描述我自己。不管这个人是谁,他们肯定是个人物。

由乔舒亚·科尔曼拍摄。
有价值但确实参差不齐的数据
数据是新的黄金。或者石油,很难知道它现在是什么样子。不管怎样,出售数据是有利可图的。
那么,当你真的不知道什么数据是准确的时候,你会怎么做呢?嗯,在某些情况下你“推断”,在某些情况下,这可能以两种方式填充字段结束,这意味着你没有空属性,尽管你的值是有问题的。这看起来像什么?
[个人 1:
性别:男
性别:女]
或者对我来说,这是一个狂野的西部,我的政治背景是:
“3P _ 政治—活跃于政治 _ 美国”,
“3P _ 政治—隶属关系不明 _ 美国”,
“3P _ 政治—任何民主党人 _ 美国”,
“3P _ 政治—任何左派 _ 美国”,
“3P _ 政治—任何共和党人 _ 美国”,
“3P _ 政治—任何右派 _ 美国”,
“3P _ 政治—对政治感兴趣 _ 美国”,
“3P _ 政治—政治捐助者任何 _ 美国”,
“3P _ 政治
我的意思是,任何人看到它都会很快明白它不可能是准确的。然而,它当然不是空的,因为它不是空的,所以它可以作为数据提供。
不正确的数据让用户沮丧
即使我们采取 Spotify 和其他公司处理个人数据不关我们的事的立场,我们也不得不承认,基于这些数据,给我提供广告或报价的人不仅可能会完全错过我,还可能会破坏整个体验。
“3P _ 定制 _ BEV-PHEV-混动 _ 车主 _ 美国”,
“3P _ 定制 _ 宝马集团 3 _ 英国”,
“3P _ 定制 _ 宝马集团 5 _ 英国”
“3P _ 定制 _ 道奇车主 _ 2019 年 10 月 16 日 _ 美国”
Spotify 推断我拥有一辆混合动力车 BEV-PHEV(不管那是什么——尽管我当然应该知道),还有一辆宝马 3 系或者可能是 5 系,或者两者都有。你知道,活得精彩。和一辆道奇。也许不同国家不同的车?尽管我经常把我的 iPhone 插到我的车里(顺便说一下,不是宝马),这些有趣的猜测没有一个是正确的。
我为什么在乎?首先,我非常喜欢相关的内容。我不是很喜欢汽车,但也不是很喜欢板球。
“3P _ 板球爱好者 _ 盟”,
“3P _ 板球爱好者 _ 英国”,
然而,我会感谢与我实际相关的服务,比如推荐我实际会去吃的餐馆或我实际看的电影。
每个人都有数据,但最多是不完整的
有一种误解认为每个人都有很多数据。我无意贬低 Spotify,他们已经花费了大量的金钱和时间来建立他们的数据实践,我只关注其中很小的一部分。此外,这在任何方面都不是 Spotify 独有的。然而,它显示了数据和数据市场之间的明显差距,很难获得准确的数据,而且往往与用户相关的数据最终变得不可用,甚至具有破坏性。
现在法规已经允许个人从世界各地的许多数据*台下载他们的数据。这为开发者开发直接面向消费者的个人数据应用打开了一个新的机会海洋。
在 Spotify 上,开发者可以构建一个应用程序,根据综合数据点提供推荐或创建播放列表,例如查看来自网飞、Hulu 的数据。然后另一个开发人员可以构建一个更好的或不同的版本,以此类推。我们就是这样发展的。你会建造什么样的?
数据市场的开放将从根本上改变封闭的数据市场,也将改变用户如何真正从他们的数据中获得他们想要的价值。
如果你是 Spotify 用户,你应该可以访问类似的数据。你可以从 Spotify 的账户隐私页面下载。此外,您最终会得到一个包含 json 文件的 ZIP 文件,名为“推论. json”。如果你喜欢这种类型的东西,看看吧,我很想听听你被描述成什么类型的人?我肯定它是丰富多彩的。
死亡和数据科学:第二部分
为什么我们需要批判性地思考新冠肺炎时代的数据使用

纳赫尔·阿卜杜勒·哈迪在 Unsplash 上的照片
一个多月前,我写了这篇文章关于我们对死亡的恐惧,以及科技公司将如何利用这种恐惧来说服我们放弃我们的隐私。正如在构建大数据的大数据和医疗保健章节中所指出的,医疗保健领域关于大数据隐私的讨论明显低于商业和政治等其他领域(Paganoni 2019)。在这一章中,一位来自 Duquesne 大学的教授被引述为本质上说,“如果你想要技术上的医学创新,你必须放弃个人隐私,”将隐私框定为为了医学进步而必须牺牲的微不足道的奢侈品。后来,Paganoni 引用了信息专员办公室的这篇文章。帖子本身讨论的问题是,大量数据从皇家自由伦敦 NHS 基金会信托基金转移到谷歌 DeepMind 被认为违反了数据保护法。Paganoni 引用的部分是:
1。这不是隐私或创新之间的选择
令人欣慰的是,审判看起来是积极的。信托基金报告了成功的结果。有些人可能会认为,数据保护权是为此付出的小小代价。
但是,在浏览调查结果时,我注意到我们发现的缺点是可以避免的。创新的代价不一定是对法律保障的基本隐私权的侵蚀。我完全有信心,信托机构能够顺应我们的要求做出改变,并继续其有价值的工作。考虑到创新技术的部署,这也适用于更广泛的 NHS。
本质上,我们不需要为了医学的进步而牺牲我们的个人隐私,缺乏隐私更多的是疏忽的结果,而不是必要的。结合这一事实,即使我们认为是匿名的数据也可以非常容易地去匿名化,你会认为我们应该格外小心我们交给科技公司的数据,即使他们正在从事医疗保健技术。然而,随着新冠肺炎病毒的爆发,我们看到的情况正好相反。以这张地图为例,它根据社交距离给每个州打分。它给每个州打分的方式是通过查看智能手机的位置数据,确定从爆发前到现在移动减少的百分比,并根据减少的百分比给他们分配一个字母等级。当然,他们坚持认为数据是完全匿名的。在《华盛顿邮报》对本次的报道中,引用了未发布的首席执行官托马斯·沃勒的话:
“这里的一切都是在聚合的水*上,”Walle 说。“我们不能告诉或透露任何个人是否留在家中。”
然而,文章也指出:
隐私倡导者担心像 Unacast 这样的数据公司可能是不可靠的,因为他们在没有得到人们真正同意的情况下收集位置。
Walle 说,Unacast 从其获取位置数据的所有应用程序都必须让用户知道。但他拒绝透露任何应用的名称。我们知道很少有人阅读应用程序上的隐私政策——这些细则披露了他们使用你的位置的许多方式,例如将其出售给数据公司。
当数据收集者对他们从哪里获得数据不透明时,比如在这种情况下,Unacast 拒绝说出用于收集数据的应用程序的名称,这不是一个好迹象。结合这一事实,即政府目前正在与脸书和谷歌等科技巨头讨论如何利用他们收集的位置数据,你有一个潜在的灾难配方。问题是,这些科技巨头是私营企业。他们只对股东负责,因此对维护用户隐私没有直接兴趣。如果政府从他们那里获取数据,他们可以说他们不是直接从公民个人那里获取数据,而是从公司那里获取。从本质上说,我们必须相信这些私营公司会出于好心而适当地匿名化数据。当然,虽然可能有一两家公司确实在努力保持数据共享的透明和道德,但总的来说,我们不能相信企业会优先考虑公共利益,除非他们被迫这样做,而且看起来他们暂时没有被迫这样做。
Slate 最*发表了一篇文章,“你不应该把你的数据给谷歌来访问新冠肺炎测试,”讨论了谷歌可能如何开发一个系统,让人们访问他们的新冠肺炎测试结果,但要访问这些结果,你必须放弃更多的数据。这就像是我们的集体恐惧被操纵,给了公司我们通常不会给他们的数据。事实上,这句话说得很好:
随着新冠肺炎在我们的社区传播,人们利用这种情况获取经济利益的故事比比皆是。无良的疫情奸商将部落护具和清洁用品以天价出售。像这些商品一样,科技公司从新冠肺炎筛选中抽取的数据可能是下一个被囤积和利用的资产。
就像我们对死亡的恐惧已经在医疗保健领域被利用一样,当涉及到大数据时,我们对新冠肺炎更现实的恐惧正在被操纵,以使我们接受隐私的损失。更糟糕的是,虽然这种隐私的损失被认为是完全必要的,但事实是,一些使用这些个人数据的算法甚至不起作用,并可能造成伤害。在论文“紧急医疗数据:人工智能推断的健康信息”中,紧急医疗数据(EMD)是“人工智能从琐碎的数字痕迹中推断的健康信息”。马克斯指出,虽然潜在的隐私侵犯被认为是公共利益所必需的:
然而,几乎没有证据表明基于经验模态分解的剖析有效。更糟糕的是,它可能造成重大伤害,而当前的健康隐私和数据保护法存在漏洞,允许公共和私人实体在人们不知情或未同意的情况下开采 EMD
我们对死亡的恐惧已经被操纵来损害我们的隐私权,现在我们的恐惧加剧了,这种操纵只会增加。这就是为什么我们需要对这些私营公司的要求以及他们为保护我们自己的权利而采取或不采取的措施提出更多的批评,因为很明显,如果不被强迫,他们无意保护我们的权利。
[1]帕戈诺尼,玛丽亚·克里斯蒂娜。构建大数据:语言和话语方法。斯普林格,2019。
[2] Marks,Mason,《紧急医疗数据:人工智能推断的健康信息》(2020 年 3 月 14 日)。加州大学欧文分校法律评论(2021 年,即将出版)。可在 https://ssrn.com/abstract=3554118SSRN买到
死刑判决和种族偏见
当数据显示黑人的生命不那么重要时
这篇文章讨论了我们后奴隶制、后殖民主义和后种族隔离时代的一个非常严肃的话题。为什么当法律明确谴责不同的治疗或结果时,仍然有明显的差异?这些差异影响了部分公众舆论——顺便说一下,这应该影响到所有人,因为这个问题不会只在少数族裔身上得到解决。

这篇文章将揭露和解释黑人的生命不那么重要的情况。在俄克拉荷马州,从 1990 年到 2012 年,143 名罪犯被判处死刑。2017 年,皮尔斯等人收集并分析了杀人数据(4668 名罪犯)和死刑判决。它表明死刑判决的结果涉及到几个种族/民族的影响。这张纸包含了所有的细节。使用的术语(“非白人”、“种族”)来自该文件。我不喜欢“非白人”这个词,但我不能每次都用黑人、西班牙人、美洲原住民和亚洲人来代替它。我会在这个帖子里坚持下去。
1.有根据的猜测死刑的最佳/最差可能性?
虽然这个话题非常严肃,但我想知道你对潜在偏见的第一想法。假设有一个罪犯,因“故意(非过失)杀人”而被审判。我们对他一无所知。
什么会降低他被判死刑的可能性?
- 如果罪犯是白人则少判死刑。
- 如果被害人是不是白就少判死刑。
- 几率差不多,司法系统是公*的,不是吗?
- 你的问题有失偏颇(请说如何,有意思)。
你怎么想呢?你可以把你的答案写在下面的评论里。
2.从杀人罪犯到死刑,一个明显*等的结果
让我们回到俄克拉荷马州,那里的作者已经收集了 1990 年至 2012 年期间的凶杀案和死刑判决。

1990-2012 年俄克拉荷马州杀人罪犯和死刑判决统计。资料来源:Pierce 等人的论文
按种族/民族的概述让我们对这个故事有了初步的了解:
- 凶杀率(HR = HO/POP) :非白种人在凶杀罪犯中明显过多。尽管任何旨在减少凶杀案的预防/缓解战略都应考虑到这一点,但我们将遵循这篇文章,重点关注死刑率,因为这是司法系统的核心,而不是上游。
- 死刑判决率(DSR = DS/HO) : DSR 的白人与非白人杀人罪犯非常相似(3.2%比 3.0%)。
【DSR】的*等在这里是公*的核心概念,我们将从多个维度来计算它。DSR 被定义为死刑数量除以杀人罪犯数量。**
结果均等意味着类似的杀人案(在类似的重罪情节程度下)应该导致类似的死刑判决率* (DSR)。*
所以,不管罪犯是什么种族,DSR 看起来都是相似的。俄克拉何马州的整个故事已经讲完了吗?不,没有,远不止这些。
3.按受害者的种族/民族划分的死刑率讲述了另一个故事
另一个角度是考虑受害者的种族/民族,而不是罪犯的种族/民族。从字面上讲,这就是“黑人的命也是命”座右铭背后的思想。

1990-2012 年俄克拉荷马州按受害者种族/民族划分的死刑判决和 DSR 统计数据。资料来源:Pierce 等人的论文
结论是惊人的:与非白人受害者相比,白人受害者被判死刑的几率是白人受害者的两倍(2.05 =3.9%/1.9%)。
然而,在得出这些结果的差异是歧视性的结论之前,是否应该考虑其他强烈的 DSR 差异。
4.受害者性别也有很大的影响
应该考虑受害者的另一个特征:性别。它实际上有一个很大的影响:女性受害者的 DSR是 7.2% vs 1.6% 。换句话说,女性受害者被判死刑的几率是男性受害者的 4.5 倍(7.2%/1.6%)。
2 效果(受害者种族/民族和性别)如何组合?我们可以在这里争辩说,也许白人受害者中有更多的女性,这可以解释为什么白人受害者的 DSR 更高。在这种情况下,可能不存在歧视性影响(假设当受害者是女性时,可以更严厉地谴责)。**
当我们计算跨种族跨性别的死刑判决率时,这种假设情景消失了:

1990-2012 年俄克拉荷马州按受害者种族/民族和性别统计的死刑率。资料来源:皮尔斯等人的论文
没有辛普森式的扭曲效果:无论是女性还是男性,都有明显的白人与非白人的 DSR 差异。对于男性受害者来说,这种影响更为显著:与非白人受害者相比,白人受害者被判死刑的几率是 T4 的 2.9 倍(2.3%/0.8%)。
在总结之前,让我们考虑潜在的其他因素。
5.其他影响:重罪情节加重
在从之前的分析跳到关于受害者的种族/民族的歧视性影响的结论之前,我们需要思考和测试可能的混淆因素。
首先想到的是杀人案的重罪情节的程度。三级重罪情节加重犯被考虑在内,他们与 DSR 有最强的联系。它们的相对危险度分别为 1.7%(无强化者)、6.2%(有 1 个强化者)和 30.2%(少数有 2 个强化者)。
6.一个“因果”交互图来总结它
为了解释可能的混杂效应和推理其他条件不变的情况下,作者对之前提到的所有变量进行了逻辑回归。我鼓励你去看看论文中的结果(表 11)。但是为了简单起见,我把它翻译成了一个“因果图”,同时用指向 DSR 的箭头(+/-)表示回归系数的方向和强度。从犯罪者种族到受害者种族的最后一个箭头说明了白人犯罪者杀死大多数白人受害者,反之亦然。

死刑率的因果交互图。只画出重要的关系。来自datajms.com
画面变得更加清晰,死刑率是:
- 主要是由犯罪的严重程度决定的(最坏和最好情况的概率乘以 13)
- 然后由受害者的性别决定(女性受害者的几率大约乘以 5)
- 第三,受受害者的种族/民族驱使(白人受害者的几率大约是 1.8 倍。但请注意,仅在男性中,白人与非白人的比例为 3.2。
- 最后,受罪犯种族/民族的微弱驱动(非白人罪犯的几率增加约 1.3 倍)。
7.关于潜在种族/民族公*问题的结论
- 与其他影响相比,直接歧视(通过罪犯种族)相对较小。它是如此之小,以至于论文作者得出结论,没有证据支持这种直接影响。然而,逻辑回归表明,仍然有一个小的影响,但不是非常显著。
想象一个非白人罪犯的死刑率为 2%的案例。如果是白人,其 DSR 将降至 1.5%(几率除以 1.3)。 - 有一个明显的“黑人生活不重要”效应,这在男性中更为明显。
想象一个白人受害者案件,死刑率为 2%。在同样的条件下,非白人男性受害者的 DSR 下降到 0.6%(男性的几率除以 3.2)。
请注意,这两种效果一般都是部分抵消。我们提到典型案例是白人罪犯杀害白人受害者和非白人罪犯杀害非白人受害者。在这些情况下,这两种效应会部分抵消,所以观察到的 DSR 是相似的。然而,在不太频繁的“跨种族”杀人案中,的影响累积起来并导致 DSR 的显著差异。
所以,回答我们的第一个问题,给定一个杀人罪犯,我们对他了解不多:
- 答案 1(如果罪犯是白人,少判死刑)会使几率降低 23%(1–1/1.3)
- 答案 2(如果受害者不是白人,则少判死刑)一般来说会将几率降低 44%(1–1/1.8),如果受害者是男性,则降低 69%。
答案 2 正确:
受害者种族/民族 效应(杀害白人受害者的凶手受到更严厉的惩罚)强于 犯罪者种族/民族 效应(非白人犯罪者受到更严厉的惩罚)。
请注意,这份声明来自对 1990 年至 2012 年俄克拉荷马州死刑判决的分析。
更一般地说,注意到在美国的刑事司法系统中有压倒性的证据表明歧视性影响。这两篇华盛顿邮报的文章列了很多。
原载于 2020 年 6 月 3 日【https://datajms.com】。**
TensorFlow 中的调试
如何在不失去理智的情况下调试 TensorFlow 训练程序

戴维·克洛德在 Unsplash 上的照片
If debugging is the process of removing software bugs, then programming must be the process of putting them in.
Edsger Dijkstra. From https://www.azquotes.com/quote/561997
在我以前的一些帖子中(这里、这里和这里),我告诉过你一些关于我在 Mobileye(官方名称为 Mobileye,英特尔公司)的团队如何使用 TensorFlow 、亚马逊 SageMaker和亚马逊 s3 来训练我们的深度神经网络处理大量数据。在这篇文章中,我想谈谈 TensorFlow 中的调试。
众所周知,程序调试是软件开发中不可或缺的一部分,花费在调试上的时间常常超过了编写原始程序的时间。
调试是困难的,已经有很多关于如何设计和实现一个人的程序以增加错误的再现性,并简化根本原因分析的过程的文章。
在机器学习中,调试任务由于机器学习算法固有的随机性以及算法通常在远程机器上的专用硬件加速器上运行的事实而变得复杂。
TensorFlow 中的调试由于使用了符号执行(也称为图形模式)而变得更加复杂,这提高了训练会话的运行时性能,但同时也限制了自由读取图形中任意张量的能力,这种能力对于调试非常重要。
在这篇文章中,我将阐述调试 TensorFlow 训练程序的困难,并提供一些如何解决这些困难的建议。
出于法律目的,我想澄清,尽管我精心选择了副标题,但我不能保证我在这里写的任何东西都会防止你失去理智。相反,我认为我几乎可以保证,不管我写了什么,当你调试 TensorFlow 程序时,你可能会失去理智。但是,也许,你会少失去一点理智。
在我们开始之前,让我们澄清一下我们讨论的范围。
调试的类型
在本文的上下文中,调试指的是识别代码或数据中导致培训突然中断的错误的艺术。
另一种类型的调试(不在本文讨论范围之内)指的是修复或调整一个不收敛的模型,或者对某一类输入产生不令人满意的预测的模型(例如,车辆检测模型无法识别粉红色汽车)。该过程可能涉及定义和评估模型指标,收集和统计分析模型工件(如梯度、激活和权重),使用工具,如 TensorBoard 和 Amazon Sagemaker 调试器,超参数调整,重新架构,或使用增强和增强等技术修改您的数据输入。调整模型可能是一项极具挑战性、耗时且常常令人沮丧的任务。
错误的类型
在解决代码或数据中的错误方面,我喜欢区分两类错误:错误和怪物错误。
通过bug我指的是相对容易重现的问题。错误的例子是对输入张量大小的假设与训练数据不匹配,试图连接不匹配的张量,或对无效数据类型执行 tf 运算。这些通常不依赖于特定的模型状态和数据,并且通常相对容易重现。它们不一定容易修复,但与怪物 bug 相比简直是小儿科。
怪物 bug是偶发的、不可预测的 bug。仅在模型的特定状态、特定数据样本或模型状态和数据输入的特定组合上重现的错误可能会带来严重的挑战,并可能构成一个怪物错误。
以下是一个基于真实事件的场景示例,它肯定会增加您的血压:
现在是星期五下午,你的模特已经成功训练了几天。损失似乎正在很好地融合,你开始想象一个放松的,释放后的周末假期,在你选择的地方。你回头看了一会儿屏幕,注意到突然之间,没有任何警告,你的损失变成了 NaN。“当然”,你对自己说,“这一定是由于一些完全随机的、瞬间的、宏观的故障”,然后你立即从你最后一个有效的模型检查点恢复训练。又过了几个小时,这种情况又发生了,一次又一次。现在你开始恐慌,你周末天堂的梦幻图片现在被需要解决一个怪物错误的诱人努力的想法所取代。
我们一会儿将回到这个令人悲伤的例子。但是首先,让我们检查一些强制性的“调试”复选框。
Tensorflow 中的调试技巧
在调试的艺术上,更重要的是,在开发可调试代码的艺术上,已经花了很多笔墨。在本节中,我将提到一些与张量流应用相关的技术。这份清单并不全面。
保存模型检查点
这可能是我在这篇文章中写的最重要的东西。始终配置您的培训课程,使其定期保存您的模型的快照。
编程错误并不是你的训练失败的唯一原因...如果您在云中运行,您可能会得到一个现场实例终止,或者遇到一个内部服务器错误。如果您在本地运行,可能会停电,或者您的 GPU 可能会爆炸。如果你已经训练了几天,没有储存中间检查点,伤害可能是极端的。如果您每小时保存一个检查点,那么您最多丢失一个小时。TensorFlow 提供了用于存储检查点的实用程序,例如 keras 模型检查点回调。您需要做的只是,通过权衡存储检查点的开销和培训课程中意外中断的成本,来决定捕获此类快照的频率。
接触者追踪
我为我选择这一小节的标题向我的同辈人道歉,我实在忍不住了。通过联系跟踪,我指的是跟踪输入培训管道的培训数据的能力。
假设您的训练数据被分成 100,000 个 tfrecord 文件,其中一个文件有格式错误,导致您的程序崩溃或停止。缩小问题文件搜索范围的一种方法是记录进入管道的每个文件。一旦你点击崩溃,你可以回头看看你的日志,看看最*输入的文件是什么。正如我在以前的帖子中提到的,我们使用 Amazon SageMaker 管道模式功能进行训练。管道模式中最*增加的一项功能是管道模式服务器端日志,它记录了进入管道的文件。
记录进入 pipeline 的数据有助于提高重现 bug 的能力,这就引出了我们的下一点。
可复制性
bug 重现的容易程度直接影响到解决它的容易程度。我们总是想写我们的代码,以确保可重复性。这在 TensorFlow 程序中并不容易。机器学习应用通常依赖于随机变量的使用。我们随机初始化模型权重,我们随机增加数据,我们随机分割数据用于分布式训练,我们随机应用漏失,我们在每个时期之前混洗我们的输入数据,然后在创建批次之前再次混洗它(使用 tf.dataset.shuffle)。我们可以用我们记录的伪随机种子来播种所有的伪随机操作,但是请记住,可能有许多不同的地方引入了随机化,并且跟踪所有这些很容易成为簿记噩梦。我无法告诉你有多少次我认为我已经去除了随机化的所有元素,却发现我漏掉了一个。此外,还有一些无法植入的随机流程。如果使用多个过程来导入训练数据,您可能无法控制数据记录的实际输入顺序(例如,如果在 tf.data.Options ())中将 experimental_deterministic 设置为 false)。当然,您可以在每个样本进入管道时对其进行记录,但这将会产生很高的开销,而且可能会令人望而却步。
底线是,虽然构建可重复的训练程序是绝对可能的,但我认为更明智的做法是接受非确定性,接受训练的不可重复性质,并找到克服这种调试限制的方法。
模块化程序设计
创建可调试程序的一个关键技术是以模块化的方式构建应用程序。应用于 TensorFlow 训练循环,这意味着能够分别测试训练管道的不同子集,如数据集、损失函数、不同的模型层和回调。这并不总是容易做到的,因为一些训练模块(如损失函数)非常依赖于其他模块。但是有很大的创造空间。例如,在应用数据集操作的子集时,可以通过简单地迭代数据集来测试输入管道上的不同函数。可以通过创建一个只运行损失函数或回调的应用程序来测试损失函数或回调。人们可以通过用虚拟损失函数代替它来抵消损失函数。我喜欢使用多个输出点来构建我的模型,即能够轻松修改模型中的层数,以便测试不同层的影响。
在构建程序时,你对程序的模块化和可调试性考虑得越多,你以后遭受的痛苦就越少。
急切的执行
如果您是 TensorFlow 的普通用户,您可能会遇到诸如“急切执行模式”、“图形模式”和“tf 函数限定符”之类的术语。你可能听过一些(有些误导)的说法,比如“在急切执行模式下调试是小菜一碟”,或者“tensorflow 2 在急切执行模式下运行”。你可能和我一样,狂热地一头扎进了 tensorflow 源代码,试图弄清楚不同的执行模式,结果却在抽泣中崩溃了,你的自尊从此粉碎。为了全面理解它是如何工作的,我向你推荐张量流文档,祝你好运。这里我们将提到它的要点,因为它与调试有关。运行 TensorFlow 训练的最佳方式是在图形模式下运行。图形模式是一种符号执行模式,这意味着我们不能任意访问图形张量。用 tf.function 限定符包装的函数将在图形模式下运行。当您使用 tf.keras.model.fit 训练时,默认情况下,训练步骤以图形模式执行。当然,不能访问任意的图形张量,使得在图形模式下调试很困难。在急切执行模式下,您可以访问任意张量,甚至可以使用调试器进行调试,(前提是您将断点放在 model.call()函数中的适当位置)。当然,当你在热切执行模式下运行时,你的训练会运行得慢很多。要对您的模型进行编程以在急切执行模式下进行训练,您需要调用函数 model.compile() ,并将 run _ eagerly 标志设置为 true。
底线是,当你训练时,以图形模式运行,当你调试时,以急切执行模式运行。不幸的是,某些 bug 只在图形模式下重现而不在急切执行模式下重现的情况并不少见,这实在令人失望。此外,当您在本地环境中调试时,急切执行很有帮助,但在云中就不那么有用了。在调试怪物 bug的时候往往不是很有用...除非你首先找到一种方法在你的本地环境中重现这个 bug(下面会详细介绍)。
TensorFlow 日志记录和调试实用程序
尽量利用 TensorFlow 测井仪。调试问题时,请将记录器设置为信息最丰富的级别。
tf.debugging 模块提供了一堆断言实用程序以及数字检查功能。特别是,TF . debugging . enable _ check _ numerics实用程序有助于找出有问题的函数。
tf.print 函数能够打印出任意的图形张量,这是一个额外的实用程序,我发现它对调试非常有用。
最后但同样重要的是,添加您自己的打印日志(在代码的非图形部分),以便更好地了解您的程序出故障的地方。
解密张量流错误消息
有时候,你会幸运地得到一个 TensorFlow 错误消息。不幸的是,如何使用它们并不总是一目了然。我经常收到同事发来的带有神秘 TensorFlow 信息的邮件,请求帮助。当我看到消息时,例如:
tensorflow.python.framework.errors_impl.InvalidArgumentError: ConcatOp : Dimensions of inputs should match: shape[0] = [5,229376] vs. shape[2] = [3,1]
或者
node DatasetToGraphV2 (defined at main.py:152) (1) Failed precondition: Failed to serialize the input pipeline graph: Conversion to GraphDef is not supported.
或者
ValueError: slice index -1 of dimension 0 out of bounds. for 'loss/strided_slice' (op: 'StridedSlice') with input shapes: [0], [1], [1], [1] and with computed input tensors: input[1] = <-1>, input[2] = <0>, input[3] = <1>.
我问自己(稍微修改了一下,使帖子对孩子友好)“我到底应该怎么做?”或者“为什么友好的 TensorFlow 工程师不能给我更多的工作呢?”。但我很快让自己*静下来,(有时借助酒精饮料),并说:“Chaim,不要被宠坏了。回去工作吧,感谢你收到了任何信息。”你应该做的第一件事,是尝试在急切执行模式下重现错误,和/或使用调试器。不幸的是,如上所述,这并不总是有帮助。
无可争议的事实是,像上面这样的信息是没有多大帮助的。但是不要绝望。有时候,在一些调查工作的帮助下,你会发现一些线索,可能会把你引向正确的方向。仔细检查调用堆栈,看它是否提供了任何提示。如果信息包括形状大小,试着将它们与你的图形中可能具有相同形状的张量进行匹配。当然还有网上搜一下,看看别人有没有遇到过类似的问题,在什么场景下。不要绝望。
在本地环境中运行
自然,在本地环境中调试比在远程机器或云中调试更容易。当您第一次创建模型时尤其如此。你的目标应该是在开始远程训练之前,在你当地的环境中解决尽可能多的问题。否则,你很可能会浪费大量的时间和金钱。
为了提高可再现性,您应该尽量使您的本地环境与远程环境相似。如果您在远程环境中使用 docker 映像或虚拟环境,请尝试在本地使用相同的映像或虚拟环境。(如果你的远程培训是在亚马逊 SageMaker 上,你可以调出所用的 docker 图片。)
当然,远程培训环境中的某些要素可能无法在本地复制。例如,你可能遇到了一个只有在使用亚马逊 SageMaker 管道模式时才会重现的 bug,目前只有在云中运行时才支持。(在这种情况下,您可以考虑使用替代方法从 s3 访问您的数据。)
我希望我能告诉你,这里描述的技术将解决你所有的问题。但是,唉,事实并非如此。在下一节中,我们将回到我们上面举例说明的怪物 bug 场景,并介绍最后一种调试技术。
使用 TensorFlow 自定义训练循环进行调试
在我们上面描述的场景中,经过几天的训练,模型的特定状态和特定训练批次样本的组合,突然导致损失变成 NaN。
让我们评估一下如何使用上面的调试技术来调试这个问题。
- 如果我们对用于所有随机操作的种子保持细致的跟踪,并且没有不受控制的非确定性事件,那么理论上我们可以通过从头开始训练来重现 bug...但那需要几天时间。
- 在本地环境中或在急切执行模式下进行复制可能需要几周时间。
- 我们可以从最*的检查点恢复,但是如果我们可以从完全相同的样本恢复,并且具有所有伪随机生成器的完全相同的状态,我们将只能再现相同的模型状态和批样本。
- 添加 tf.prints 会有所帮助,但是会带来巨大的开销
- 添加TF . debugging . enable _ check _ numerics将非常有助于查明它失败的函数。如果函数中有明显的 bug,这可能就足够了。但是这并不能让我们重现这个错误。
理想情况下,我们将能够在损失变得不可收拾之前捕获输入和模型状态。然后,我们可以在受控(本地)环境中,以急切执行模式和调试器重现该问题。
问题是我们不知道问题将要发生,直到它真正发生。当损失被报告为 NaN 时,模型已经用 NaN 权重更新,并且导致错误的批次样本已经被迭代。
我想提出的解决方案是定制训练循环,以便我们记录每一步的当前样本,并且仅在梯度有效时更新模型权重。如果梯度无效,我们将停止训练并连同当前模型快照一起转储出最后一批样本。这可以带到您的本地环境中,在那里您加载模型,并在急切执行模式下输入捕获的数据样本,以便重现(并解决)bug。
我们一会儿将讨论代码,但是首先,说几句使用定制训练循环的利与弊。
定制培训循环与高级 API
TensorFlow 用户之间有一个由来已久的争议,即是否要编写定制的训练循环或依赖于高级 API,如 tf.keras.model.fit ()。
定制培训循环的支持者,预示着对如何执行培训进行逐行控制的能力,以及创造性的自由。高级 API 的支持者称它提供了许多便利,最显著的是内置的回调实用程序和分布式策略支持。使用高级 API 还可以确保您使用的是一个无错误的、高度优化的训练循环实现。
从 2.2 版本开始,TensorFlow 引入了覆盖 tf.keras.model 类的 train_step 和 make_train_function 例程的能力。这使用户能够引入某种程度的定制,同时继续享受 model.fit()的便利。我们将演示如何以这样一种方式覆盖这些函数,使我们能够捕获有问题样本输入和模型状态,以便进行本地调试。
自定义采集循环
在下面的代码块中,我们使用 train_step 和 make_train_functions 例程的自定义实现来扩展 tf.keras.models.Model 对象。为了全面理解这个实现,我建议您将它与 github 中例程的默认实现进行比较。您会注意到,为了使代码更具可读性,我删除了所有与指标计算和策略支持相关的逻辑。需要注意的主要变化是:
- 在将梯度应用到模型权重之前,我们测试 NaN 的梯度。只有当 NaN 不出现时,渐变才会应用于权重。否则,向训练循环发送遇到错误的信号。信号的一个例子可以是将损耗设置为预定值,例如零或 NaN。
- 训练循环存储每一步的数据特征和标签(x 和 y)。注意,为了做到这一点,我们将数据集遍历(下一个(迭代器)调用)移到了@tf.function 范围之外。
- 该类有一个布尔“崩溃”标志,通知主函数是否遇到了错误。
**class** **CustomKerasModel**(tf.keras.models.Model):
**def** __init__(self, **kwargs):
super(CustomKerasModel, self).__init__(**kwargs)
*# boolean flag that will signal to main function that
# an error was encountered*
self.crash = **False**
@tf.function
**def** train_step(self, data):
x, y = data
**with** tf.GradientTape() **as** tape:
y_pred = self(x, training=**True**) *# Forward pass*
*# Compute the loss value*
*# (the loss function is configured in `compile()`)*
loss = self.compiled_loss(
y, y_pred, regularization_losses=self.losses)
*# Compute gradients*
trainable_vars = self.trainable_variables
gradients = tape.gradient(loss, trainable_vars)
*# concatenate the gradients into a single tensor for testing*
concat_grads =
tf.concat([tf.reshape(g,[-1]) **for** g **in** gradients],0)
*# In this example, we test for NaNs,
# but we can include other tests*
**if** tf.reduce_any(tf.math.is_nan(concat_grads)):
*# if any of the gradients are NaN, send a signal to the
# outer loop and halt the training. We choose to signal
# to the outer loop by setting the loss to 0.*
**return** {'loss': 0.}
**else**:
*# Update weights*
self.optimizer.apply_gradients(
zip(gradients, trainable_vars))
**return** {'loss': loss}
**def** make_train_function(self):
**if** self.train_function **is** **not** **None**:
**return** self.train_function
**def** train_function(iterator):
data = next(iterator)
*# records the current sample*
self.x, self.y = data
res = self.train_step(data)
**if** res['loss'] == 0.:
self.crash = **True**
**raise** **Exception**()
**return** res
self.train_function = train_function
**return** self.train_function
**if** __name__ == '__main__':
*# train_ds =*
*# inputs =*
*# outputs =*
*# optimizer =*
*# loss =*
*# epochs =*
*# steps_per_epoch =*
model = CustomKerasModel(inputs=inputs, outputs=outputs)
opt = tf.keras.optimizers.Adadelta(1.0)
model.compile(loss=loss, optimizer=optimizer)
**try**:
model.fit(train_ds, epochs=epochs,
steps_per_epoch=steps_per_epoch)
**except** **Exception** **as** e:
*# check for signal*
**if** model.crash:
model.save_weights('model_weights.ckpt')
*# pickle dump model.x and model.y*
features_dict = {}
**for** n, v **in** model.x.items():
features_dict[n] = v.numpy()
**with** open('features.pkl','wb') **as** f:
pickle.dump(features_dict,f)
labels_dict = {}
**for** n, v **in** model.y.items():
labels_dict[n] = v.numpy()
**with** open('labels.pkl', 'wb') **as** f:
pickle.dump(labels_dict, f)
**raise** e
值得注意的是,这种技术有一个小的训练运行时成本,它来自于以急切执行模式而不是图形模式从数据集中读取数据。(天下没有免费的午餐。)精确的成本将取决于模型的大小;模型越大,感觉到的变化就越小。您应该在自己的模型上评估这种技术的开销,然后决定是否以及如何使用它。
摘要
只要我们人类参与到人工智能应用的开发中,编程错误的流行几乎是肯定的。在设计代码时考虑到可调试性,并获得解决 bug 的工具和技术,可能会防止一些严重的问题。
最重要的是,不要绝望。
调试 Jupyter 笔记本电脑将提高您的工作效率
使用调试提高 Jupyter 笔记本电脑的工作效率

蒂莫西·戴克斯在 Unsplash 拍摄的照片
天真的方式——伐木
我们在开发程序时都会遇到代码中的错误,日志记录是调试代码的一种很好的方式,可能也是最直观的方式。通常的做法是在代码中添加 print 语句,这有助于我们追踪许多问题的根源。
import random
def find_max (values):
max = 0
print(f”Initial max is {max}”)
for val in values:
if val > max:
max = val
return max
find_max(random.sample(range(100), 10))
优势:
- 容易的
- 不需要安装
缺点:
- 可能是垃圾邮件
- 很难确定容易出错的位置
古典之路——PDB
我们看到打印声明帮助我们找到关于问题的相关信息,但是这些工具不足以找到每个根本原因。当我们需要更强大的东西时,就该试试 Python 内置的交互式调试器了。
pdb 模块为开发者调试 Python 程序(包括 jupyter 笔记本)提供了一个交互式调试环境。要启动调试器,我们所要做的就是导入 pdb 内置模块并运行其 set_trace 函数。
import random
def find_max (values):
max = 0
import pdb; pdb.set_trace()
for val in values:
if val > max:
max = val
return max
find_max(random.sample(range(100), 10))
演示:
资料来源:https://www.youtube.com/watch?v=ZrM42wnZjt8
优势:
- 动态。
- 不需要安装。
- 成熟(更多的特性,好的文档,更少的 bug)。
缺点:
- 非常吓人。
- 陡峭的学习曲线。
其他资源:
Pixie 调试器
有些人会理直气壮地指出 Jupyter 已经支持 pdb 了,这就足够了,但是作为开发人员,我们倾向于选择简单的方式,也就是 GUI。
PixieDebugger 是 Jupyter 笔记本的第一个可视化 Python 调试器,包括源代码编辑器、局部变量检查器、控制台输出、在当前上下文中评估 Python 表达式的能力、断点管理和用于控制代码执行的工具栏。
import contextlib
with contextlib.redirect_stdout(None):
import pixiedust# New Cell
%%pixie_debugger
def find_max (values):
max = 0
import pdb; pdb.set_trace()
for val in values:
if val > max:
max = val
return max
find_max(random.sample(range(100), 10))
演示:
优势:
- 动态。
- 简单。
缺点:
- 需要额外安装。
- 在木星笔记本上工作,但不是在木星实验室。
- 不成熟(错误文档和任务评估失败)。
设置:
pip install pixiedust
其他资源:
Jupyter 实验室调试器
非常类似于 Jupyter 实验室自己制作的 pixie-dust GUI 调试器,它仍然很新,但是我们可以在笔记本单元格和源文件中设置断点,检查变量,导航调用堆栈等等。
import contextlib
with contextlib.redirect_stdout(None):
import pixiedust# New Cell
def find_max (values):
max = 0
import pdb; pdb.set_trace()
for val in values:
if val > max:
max = val
return max
find_max(random.sample(range(100), 10))
演示:

来源:https://blog . jupyter . org/a-visual-debugger-for-jupyter-914 e 61716559
优势:
- 动态。
- 简单。
- 没有额外的代码。
缺点:
- 需要额外安装。
- 需要一个新的翻译。
- 在木星笔记本上工作,但不是在木星实验室。
- 安装有些困难。
- 不成熟(错误文档和任务评估失败)。
设置:
对于每个 conda 环境
conda install -y -c conda-forge xeus-python=0.6.12 notebook=6 ptvsd
jupyter labextension install [@jupyterlab/debugger](http://twitter.com/jupyterlab/debugger)
其他资源:
荣誉奖
- ——服用类固醇的 pdb。
- pudb——PDB 与 GUI。
遗言
总之,有许多技术可以用来调试 Jupiter 笔记本:
- 首先,人们应该使用日志来隔离问题
- 超级用户应该花时间学习 pdb,因为你永远不知道它会对你有益。
- 最后,根据您使用的是裸机还是 Jupyter Lab,您应该使用 pixiedust 和 Jupyter 调试器。
我希望这篇文章能让人们在笔记本环境中更有效率。我希望我能够分享我对这个迷人话题的热情,并且你会发现它是有用的,并且一如既往地,我愿意接受任何建设性的反馈。
用 PyTorch 和 W&B 调试神经网络
生产中的机器学习
调试神经网络的技巧和诀窍

点击查看互动报道。所有代码都可以在这里获得。
在这篇文章中,我们将看到是什么使神经网络表现不佳,以及我们可以通过可视化梯度和其他与模型训练相关的参数来调试它的方法。我们还将讨论渐变消失和爆炸的问题以及克服它们的方法。
最后,我们将了解为什么适当的权重初始化是有用的,如何正确地进行初始化,并深入研究正则化方法(如剔除和批量归一化)如何影响模型性能。
神经网络 bug 从何而来?
如这篇文章所示,神经网络错误很难捕捉,因为:
1.代码不会崩溃,不会引发异常,甚至不会变慢。
2。网络仍在训练,损失仍会下降。
3。几个小时后,这些值收敛,但结果很差
如果你想更深入地了解这个话题,我强烈推荐你阅读安德烈·卡尔帕蒂的《训练神经网络的诀窍》。
调试神经网络时,没有一套确定的步骤可以遵循。但是这里有一个概念列表,如果实施得当,可以帮助调试你的神经网络。
那么我们如何更好地调试我们的神经网络呢?
调试神经网络时,没有一套确定的步骤可以遵循。但是这里有一个概念列表,如果实施得当,可以帮助调试你的神经网络。
模型输入
1。关于数据的决策: 我们必须了解数据的细微差别——数据的类型、存储方式、目标和特性的类*衡、数据的价值尺度一致性等。
2。数据预处理 : 我们必须考虑数据预处理,并尝试将领域知识融入其中。通常在两种情况下使用数据预处理:
- 数据清洗:如果去掉数据中的某些部分,即所谓的工件,目标任务就可以轻松完成。
- 数据扩充:当我们拥有有限的训练数据时,我们以多种方式转换每个数据样本,以用于训练模型(例如缩放、移动、旋转图像)。
这篇文章的重点不是糟糕的数据预处理所导致的问题。
3。在小数据集上过度拟合: 如果我们有一个 50–60 个数据样本的小数据集,模型将快速过度拟合,即损失将在 2–5 个时期内为零。为了克服这一点,请确保从模型中移除任何正则化。如果你的模型没有过度拟合,可能是因为你的模型架构不正确,或者你的损失选择不正确。当您尝试进行多类分类时,可能会使用 sigmoid 激活输出图层。这些错误可能是容易漏掉的错误。点击这里查看我演示这个的笔记本。
那么,如何避免这样的错误呢?继续读。
模型架构
1。从一个小的架构开始: 使用花哨的正则化器和调度器可能有些矫枉过正。如果出现错误,调试一个小型网络会更容易。常见的错误包括忘记将张量从一层传递到另一层,输入与输出神经元的比例不合理等。
2。预训练的模型(权重): 如果你的模型架构是建立在标准主干之上的,比如 VGG、Resnet、Inception 等,你可以在标准数据集上使用预训练的权重——如果可以的话,在你正在处理的数据集上找一个。最*一篇有趣的论文Transfusion:Understanding Transfer Learning for Medical Imaging表明,使用预训练 ImageNet 模型的几个早期层就可以提高训练速度和医学成像模型的最终准确性。因此,您应该使用通用的预训练模型,即使它不在您正在解决的问题的领域内。当应用于医学成像时,ImageNet 预训练模型的改进量不是很大。因此,也没有太多的保证。更多的话,我推荐阅读杰瑞米·霍华德的这篇惊人的博客文章。
Loss
1。选择正确的损失函数 : 首先,确保你对给定的任务使用正确的损失函数。对于多类分类器来说,二元损失函数不会有助于提高准确率,所以分类交叉熵是正确的选择。
2。确定理论损失 : 如果您的模型是通过随机猜测开始的(即没有预训练模型),请检查初始损失是否接*您的预期损失。如果你使用交叉熵损失,检查一下你的初始损失大约是-log(1/num_classes。你可以在这里获得更多建议。
3。学习率 : 该参数决定每次迭代的步长,同时向损失函数的最小值移动。你可以根据损失函数的陡度或*滑度来调整学习速率。但是这可能是一个耗费时间和资源的步骤。你能自动找到最佳的学习速度吗?
Leslie N. Smith 提出了一个非常聪明和简单的方法,在短时间和最少的资源内系统地找到学习率。你所需要的只是一个模型和一套训练集。该模型以小的学习率初始化,并对一批数据进行训练。相关的损失和学习率被保存。然后,学习率线性或指数地增加,并且用该学习率更新模型。
在本笔记本的中,您会发现这种方法在 PyTorch 中的实现。我实现了一个类LRfinder。方法range_test支持上面描述的逻辑。使用wandb.log(),我能够记录学习率和相应的损失。
if logwandb:
wandb.log({'lr': lr_schedule.get_lr()[0], 'loss': loss})
使用这个LRFinder来自动找到你的模型的最佳学习率。
lr_finder = LRFinder(net, optimizer, device)
lr_finder.range_test(trainloader, end_lr=10, num_iter=100, logwandb=True)
你现在可以前往你的 W&B 运行页面,找到 LR 曲线的最小值。以此作为你的学习率,在整批训练集中进行训练。

图 LRFinder 的结果。从这里捕获。
当学习率太低时,模型不能学习任何东西,并且它保持稳定。当学习率足够大时,它开始学习,你会发现曲线突然下降。曲线的最小值就是你正在寻找的最佳学习率。当学习率很高时,损失会爆炸,即损失突然增加。
如果你正在使用 Keras 建立你的模型,你可以使用学习率查找器,正如 PyImageSearch 在博客中所展示的。你也可以参考这个博客来了解 TensorFlow 2.0 中的实现。
激活功能
1。消失梯度的问题:10 年前,由于使用了 sigmoid/tanh 激活函数,在训练深度神经网络时存在一个主要问题。为了理解这个问题,读者应该理解前馈和反向传播算法以及基于梯度的优化。我建议你观看这个视频或者阅读这个博客来更好地理解这个问题。
简而言之,当执行反向传播时,计算损耗相对于每层权重的梯度,并且当我们在网络中继续向后移动时,损耗倾向于变小。每一层的梯度可以使用微分链规则来计算。由于 sigmoid 的导数范围仅为 0–0.25,数值上计算的梯度非常小,因此发生的重量更新可以忽略不计。由于这个问题,模型无法收敛或者需要很长时间才能收敛。
假设您正在构建一个不那么传统的神经网络架构。调试这种网络最简单的方法是可视化梯度。如果你使用 PyTorch W&B 构建网络,它会自动绘制每一层的渐变。点击查看我的笔记本。
你可以在笔记本里找到两个型号,NetwithIssue和Net。第一个模型使用 sigmoid 作为每层的激活函数。后者使用ReLU。两个模型中的最后一层都使用了一个softmax激活函数。
W&B 为 PyTorch 提供一流的支持。要自动记录梯度并存储网络拓扑,可以在 PyTorch 模型中调用 watch 并传递。如果还想记录参数值的直方图,可以将log='all'参数传递给观察方法。
在 W&B 项目页面中,在运行页面的Vanishing_Grad_1、VG_Converge 和VG_solved_Relu 中查找梯度图。为此,单击运行名称,然后单击梯度部分。

图 2: VG_Converge 梯度图。从这里抓拍。
在这次运行中,该模型在 MNIST 手写数据集上被训练了 40 个时期。它最终以超过 80%的训练测试准确率收敛。您可以注意到大多数历元的梯度为零。
2.死亡的 ReLU:ReLU 不是一颗神奇的子弹,因为当它们被喂食小于零的值时会“死亡”。如果大多数神经元在短期训练内死亡,网络的很大一部分可能会停止学习。在这种情况下,仔细看看你的初始重量或者给你的重量增加一个小的初始偏差。如果这不起作用,你可以试着用Maxout、Leaky ReLUs 和ReLU6 做实验,如MobileNetV2 论文中所示。
3.爆炸梯度问题:这个问题发生在后面的层比初始层学习得慢的时候,不像消失梯度问题,前面的层比后面的层学习得慢。当我们在各层中向后移动时,梯度呈指数增长,就会出现这个问题。实际上,当梯度爆炸时,由于数值溢出,梯度可能变成NaN,或者我们可能在训练损失曲线中看到不规则的振荡。在消失梯度的情况下,权重更新非常小,而在爆炸梯度的情况下,这些更新是巨大的,因为这错过了局部最小值并且模型不收敛。你可以观看这个视频来更好地理解这个问题,或者浏览这个博客。
让我们试着想象一下爆炸梯度的情况。看看这个笔记本这里我故意用一个大值 100 初始化权重,这样它们就会爆炸。


图 3:演示爆炸梯度。从这里抓拍。
注意梯度是如何向后呈指数增长的。conv1 的梯度值约为 10⁷,而 conv2 的梯度值约为 10⁵.错误的权重初始化可能是该问题的一个原因。
在基于 CNN 的架构中,通常不会遇到爆炸梯度。对于复发的神经营养不良来说,它们更是一个问题。查看这个线程以获得更多信息。由于爆炸梯度引起的数值不稳定,你可能会得到NaN作为你的损失。这个笔记本这里演示了这个问题。

图 4:南的损失。
有两种简单的方法可以解决这个问题。它们是:
1.渐变缩放
2。渐变剪辑
在链接笔记本中,我使用了渐变剪辑来克服这个问题。渐变裁剪将“裁剪”渐变或将其限制在某个阈值,以防止渐变变得过大。在 PyTorch 中,只需一行代码就可以做到这一点。
torch.nn.utils.clip_grad_norm_(model.parameters(), 4.0)
这里 4.0 是门槛。这个值适用于我的演示用例。查看笔记本中的trainModified函数,查看其实现。
权重初始化和其他正则化
1。权重初始化:这是训练神经网络最重要的方面之一。像图像分类、情感分析或下围棋这样的问题是无法用确定性算法解决的。你需要一个非确定性的算法来解决这样的问题。这些算法在算法执行期间做出决策时使用了随机性元素。这些算法充分利用了随机性。使用称为随机梯度下降的随机优化算法来训练人工神经网络。训练神经网络只是对“好”解决方案的非确定性搜索。
随着搜索过程(训练)的展开,我们有陷入搜索空间不利区域的风险。陷入困境并返回一个“不太好”的解决方案的想法被称为陷入局部最优。有时,消失/爆炸梯度会阻止网络学习。为了对抗这种权重初始化,一种方法是在搜索问题中引入仔细的随机性。这种随机性是在开始时引入的。使用小批量来训练shuffle=True是在搜索过程中引入随机性的另一种方法。为了更清楚地了解基本概念,请查看这个博客。
好的初始化有很多好处。它帮助网络实现基于梯度的优化算法的全局最小值(只是拼图的一部分)。它防止消失/爆炸梯度问题。良好的初始化也可以加快训练时间。这个博客在这里很好地解释了权重初始化背后的基本思想。
初始化方法的选择取决于激活函数。要了解更多关于初始化的信息,请查看这篇文章。
- 当使用 ReLU 或泄漏 ReLU 时,使用 He 初始化,也称为明凯初始化。
- 当使用 SELU 或 ELU 时,使用 LeCun 初始化。
- 使用 softmax 或 tanh 时,使用 Glorot 初始化,也称为 Xavier 初始化。
大多数初始化方法都是统一的和正态分布的。查看这个 PyTorch doc 获取更多信息。
查看我的笔记本这里看看你如何在 PyTorch 中初始化权重。

注意这些层是如何用kaiming_uniform初始化的。你会注意到这个模型非常适合。通过简化模型,你可以很容易地克服这个问题。

图 5:用更好的权重初始化训练的模型。从这里抓拍。
2。Dropout 和 Batch Normalization: Dropout 是一种正则化技术,它随机“退出”或“停用”神经网络中的少数神经元,以避免过拟合的问题。在训练期间,在应用了丢弃之后的层中的一些神经元被“关闭”。具有更少参数的神经网络集成(更简单的模型)减少了过拟合。与网络的快照集相反,丢失模拟了这种现象,而没有训练和维护多个模型的额外计算费用。它将噪声引入到神经网络中,以迫使它学习足够好的概括来处理噪声。
批处理规范化是一种改进优化的技术。在对输入数据进行训练之前对其进行标准化是一个很好的做法,这样可以防止学习算法出现振荡。我们可以说一层的输出是下一层的输入。如果该输出在被用作输入之前能够被标准化,则学习过程能够被稳定。这极大地减少了训练深度网络所需的训练时期的数量。批次规范化使规范化成为模型架构的一部分,并在训练时在小批次上执行。批处理规范化还允许使用更高的学习速率,并且让我们不必太在意初始化。
让我们实现上面讨论的概念,看看结果。查看我的笔记本这里,看看如何在 Pytorch 中使用批处理规范化和丢弃。我从一个基本模型开始,为这项研究设定基准。实现的架构很简单,导致过拟合。

图 6:注意测试损失最终是如何增加的。从这里抓拍。
注意测试损失最终是如何增加的。然后,在 Conv 阻塞后,我应用了丢弃率为 0.5 的丢弃层。要在 PyTorch 中初始化这一层,只需调用torch.nn的 Dropout 方法。
self.drop = torch.nn.Dropout()
退出防止了过度拟合,但是模型没有像预期的那样快速收敛。这意味着集合网络需要更长的时间来学习。在辍学的情况下,学习时不是每个神经元都可用。

图 7:使用压差作为正则项的损耗和度量图。从这里捕捉。
接下来是批量标准化。要在 PyTorch 中初始化这一层,只需调用torch.nn的BatchNorm2d方法。
self.bn = torch.nn.BatchNorm2d(32)
批处理规范化用较少的步骤来收敛模型。由于模型简单,过度拟合是不可避免的。

图 8:使用批量标准化的损失和度量图。从这里抓拍。
现在让我们一起使用这两层。如果你同时使用 BN 和 Dropout,请遵循这个顺序(查看这篇文章了解更多信息)。
CONV/FC -> BatchNorm -> ReLU(or other activation) -> Dropout -> CONV/FC

图 9:使用批量标准化和漏失的损失和度量图。从这里抓拍。
请注意,通过使用丢弃和批量标准化,可以消除过度拟合,同时模型收敛更快。
当您有一个大型数据集时,优化很重要,而正则化不那么重要,因此批量正则化对于大型数据集更重要。当然,您可以同时使用批处理规范化和删除,尽管批处理规范化也可以作为正则化,在某些情况下可以消除删除的需要。
笔记
- 文章调试神经网络的清单将是一个很好的下一步。
- 对神经网络进行单元测试并不容易。本文讨论如何对机器学习代码进行单元测试
- 我强烈推荐阅读为什么深度神经网络很难训练?
- 关于梯度裁剪的更深入的解释,请查看如何避免在使用梯度裁剪的神经网络中爆发梯度?
- Sayak Paul 撰写的《权重初始化对神经网络的影响》,他深入讨论了权重初始化的不同影响。
希望这篇博客对机器学习社区的每一个人都有帮助。我试着分享我自己的一些见解和许多好的阅读材料,以加深对这些话题的理解。调试神经网络最重要的方面是跟踪您的实验,以便您可以在以后重现它们。当涉及到跟踪你的实验时,重量和偏差真的很方便。有了可视化实验的所有最新方法,一天比一天简单。
我要感谢拉旺亚给我这个机会。在这个过程中我学到了很多东西。感谢 Sayak Paul 不断的指导。
调试你的神经网络,检查你的梯度

来源:https://upload . wikimedia . org/Wikipedia/commons/3/31/gradient 99 . png
当实现神经网络时,反向传播可以说是更容易出错的地方。那么,如果我们能够实现一些东西,让我们能够轻松地调试我们的神经网络,那该有多酷呢?在这里,我们将看到梯度检查的方法。简而言之,这种方法包括使用数值方法来*似梯度。如果它接*计算的梯度,则反向传播被正确地执行。但是还有更多,让我们看看。有时,可以看到网络在几个时期内停滞不前,然后继续快速收敛。我们还将看看如何解决这个问题。让我们开始吧!
博客中使用的所有可视化和 latex 代码都可以在这里找到
了解如何调试你的神经网络梯度检查这个仓库包含可视化和纹理文件…
github.com](https://github.com/Rishit-dagli/Debugging-Neural-Nets)
梯度的数值*似
为了让我们建立梯度检查,我们首先需要看看如何在数字上*似梯度。我发现用一个例子来解释很容易,所以让我们取一个函数 f(θ) = θ。让我们看看这个函数的图表

你可能已经猜到了一个简单的图表。像往常一样,让我们从θ的某个值开始,现在我们说θ = 1。所以,现在我们要做的是,不仅向右微移θ,得到(θ + ϵ),而且向左微移,得到(θ-ϵ).出于示例目的,我们假设ϵ = 0.01。现在让我们想象一下,忽略图中的比例,这只是为了演示。

所以现在我们的点(θ-ϵ)被命名为 b,而(θ + ϵ)被命名为 c。在这个图中,我们之前使用的是三角形 DEF,并计算它的高度/宽度,在这种情况下是EF/DE。事实证明,如果你用(θ + ϵ)和(θ-ϵ)之间的一个更大的三角形,你可以得到一个更好的梯度估计,为了说明我的意思,我指的是这个红色的三角形

因此,有一些论文讨论了为什么使用这个更大的三角形可以更好地逼*θ处的梯度,但就本文的范围而言,我不会详细讨论它们。简单解释一下,你现在有两个较小的三角形,你在这里用较大的三角形来考虑-

所以,我们刚刚看到了为什么你应该使用更大的三角形,这样做了,让我们得到那个三角形的数学。如果我们看到这里,我们可以简单地说
H = f(θ-ϵ) and,
F = f(θ+ϵ)
有了这两个结果,你可以说较大三角形的高度(h)为
h = f(θ+ϵ)-f(θ-ϵ)
用类似的论点,你也可以很容易地算出,这个三角形的宽度(w)是-
w = 2 ⋅ ϵ
双边导数
所以,如果你知道一点导数,你可以很容易地推断出-

其中g(θ)是指梯度。
现在让我们通过插入我们刚刚讨论的例子的值来检查我们上面写的等式有多真实。所以我会得到这样的结果。

现在让我们计算它的实际导数。我知道 f(θ) = θ,通过简单的导数 g(θ)=3 ⋅ θ,我们得到 g(θ)=3。我们做了一个很好的*似,*似误差只有 0.0001。现在让我们看看如果我们使用片面的传统方法会得到什么。如果你用单侧差来计算,你会得到*似误差为 0.0301 的3.0301。因此,我们在这里做了一个了不起的工作,大大减少了我们的*似误差!
你刚刚看到双边衍生品的表现比传统方法好得多。这给了你更大的信心,θ的 g 可能是 f(θ)导数的正确实现。这听起来好得难以置信!这种方法也有不好的一面。结果是运行速度是使用单边方法的两倍。但是我相信在实践中使用这种方法是值得的,因为它更加准确。
再深入一点
让我们回顾一下导数的正式定义。

这里需要注意的一件重要事情是限制。所以,对于非零的ϵ值,你可以证明,这个*似的误差,在ϵ的数量级。ϵ是一个非常小的数字,趋向于 0。所以,总结一下
error = O(ϵ²)
这里的O指的是骑士团。
但是你可以用简单的数学证明,如果你用单侧导数,你的误差会是,ϵ或者
error = O(ϵ)
ϵ是一个很小的数字,当然小于 1,所以ϵ >> ϵ。现在你可能明白为什么你应该使用双面差而不是单面差,我们将看到这如何帮助我们进行梯度检查。
梯度检查
梯度检查是一项非常有用的技术,多次帮助我轻松调试或找到我的神经网络中的错误。现在,我们将看到如何使用这种奇妙的技术来调试或验证您的实现和反向传播是正确的。这并不是什么新东西,但是让我们快速地看一下单个神经元的示意图,作为复习-

记住[x₁, x₂ ... x_n] go 作为输入,对于其中的每一个,我们都有参数(w,b ) (w,b)……(wⁿ,bⁿ).因此,要实现梯度检查,你应该做的第一件事是把你所有的参数,并重新塑造成巨大的矢量数据。所以,你要做的是把所有这些 w 和 b,分别改造成一个向量。然后你把所有这些向量连接成一个巨大的向量,叫做θ。所以现在我们可以用θ来写成本函数J,就像这样

所以现在我们的J或者成本函数就是θ的函数。
现在,你的 w 和 b 以同样的方式排序,你也可以把dw¹、db¹ … dwⁿ、dbⁿ连接成一个大向量,我们称之为dθ,它的维数与θ相同。我们将用一个类似的程序来做这件事,我们把所有的dw都做成向量,因为它们是矩阵,而b已经是向量了,那么就把它们连接起来。我觉得有一点可能会有帮助,w 的维数与 dw 的维数相同,b 的维数与 db 的维数相同,依此类推。这也意味着您可以使用同样的调整大小和连接操作。所以,现在你可能会有一个问题,“这里的dθ是θ的梯度或斜率吗?”我们稍后会讨论这个问题。
实施梯度检查
还记得我们把J写成θ的函数,现在我们把它写成这样-

做完这些,让我们经历一个θ也许是θ₅.的过程我们现在要做的是,计算θ₅的*似导数,精确地说,是对函数 j 的偏导数,还要注意,我们会用到之前讨论过的双侧导数。用数学的方式来表达它-

通过之前对双侧导数的讨论,我们也可以说,这是 j 对θ₅的偏导数,或者-

清楚了这一点,我们现在可以不仅对θ₅,而且对所有的i重复同样的过程,这样i ∈ (1, n)。所以这个的伪 Python 代码应该是这样的-

接*结果
所以,现在我们有两个向量dθ[approx]和dθ。而这些应该几乎是彼此相等的。但是现在我们会有另一个问题,那就是“我怎么知道两个向量是否*似相等?”
我现在要做的是计算两个向量之间的欧几里德距离。我们要做的是求差的元素的*方和,然后计算它的*方根,得到欧几里德距离。上面这句话可能看起来很混乱,相信我,确实如此!读两三遍,一旦你非常清楚这一点,继续前进。我们将进一步应用另一种方法,我们将归一化这些向量的长度。要做到这一点,我们只需简单地将它们各自的长度相加,然后除以它们之间的欧几里德距离。如果你现在感到困惑,坚持一个能帮助你的等式。

注意:这里我使用了矢量的 L₂范数的常规符号。如果你想知道为什么我们要归一化这个距离,这只是为了防止其中一个向量非常大或者非常小。
在实践中实施梯度检查
在对许多项目实施梯度检查时,我观察到ϵ = 10⁻⁶或 10⁻⁷的值在大多数时候起作用。所以,有了上面提到的相似性公式和ϵ的这个值,你会发现这个公式得出的值小于 10⁻⁷或 10⁻⁸,这太棒了。这意味着你的导数*似值很可能是正确的。如果是 10⁻⁵,我会说没问题。但是我会仔细检查我的向量的分量,检查没有一个分量太大,如果这个差的一些分量非常大,可能你有一个 bug。如果它给你 10⁻,那么我会非常担心,也许有一个错误。万一你得到比这个更大的值,那就真的有问题了!你也许应该看看θ的各个分量。这样做你可能会发现dθ[i]的值与dθ[approx.]非常不同,并使用它来找出你的哪个导数是不正确的。
我做了一个很棒的表格供你在做 ML 申请时参考-

参考表
在一个理想的情况下,当你实现一个神经网络时,你会做什么,经常发生的是,你会实现前向传播,实现反向传播。然后你可能会发现这张毕业支票的价值相对较大。然后怀疑肯定有 bug,进去,调试,。在调试一段时间后,如果您发现它通过了 grad 检查,并且值很小,那么您就可以更加确信它是正确的(并且也有一种解脱的感觉:)。这种特殊的方法经常帮助我发现我的神经网络中的错误,我建议你在调试你的网络时也使用这种方法。
更多提示
- 不要在培训中使用,仅用于调试
每个时期的毕业生报到会使它变得非常慢
- 如果算法梯度检查失败,请查看组件
如果你的算法没有通过等级检查,查看组件会有很大帮助。有时它还会提示您错误可能在哪里。
- 正规化
如果你的 J 或成本函数有一个额外的正则化项,那么你也要计算它的导数并把它们相加
- 针对辍学者的不同策略
辍学者所做的是随机移除一些神经元,这使得很难获得他们执行梯度下降的成本函数。结果是,丢弃可以被视为优化某个成本函数 J,但是它的成本函数 J 是通过对它们可以在任何迭代中消除的所有节点的指数大子集求和来定义的。所以成本函数 J 是很难计算的,你只是在每次剔除那些我们使用 dropout 的随机子集时对成本函数进行采样。因此,很难使用 grad check 来复查有遗漏的计算。所以我通常做的是在不辍学的情况下实施毕业检查。因此,如果您愿意,可以将 keep-prob 和 dropout 设置为等于 1.0。然后打开辍学,并希望我的辍学实施是正确的。
您也可以使用一些非常优雅的泰勒展开式来实现这一点,但是由于本文的范围,我们在这里不讨论这一点。
结束的
就是这样,你只是看到了如何轻松地调试你的神经网络,并很容易地找到其中的问题。我希望梯度检查能帮助你发现问题或者调试你的网络,就像它帮助我一样
关于我
大家好,我是里希特·达利
LinkedIn—l【inkedin.com/in/rishit-dagli-440113165/
网站 — rishit.tech
如果你想问我一些问题,报告任何错误,提出改进建议,给出反馈,你可以随时给我发邮件——
- rishit.dagli@gmail.com
- hello@rishit.tech
揭穿 Python For 循环:For 循环的幕后
了解 Python 中 for 循环的实际工作方式,以及对 Python 中迭代器的理解。

蒂内·伊万尼奇在 Unsplash.com 的照片
循环。任何编程语言中最基本的构造之一。一般来说,循环帮助遍历一系列对象,一次访问一个元素。与其他流行的编程语言一样,Python 也有自己的循环实现,并附带了 While 和 For 循环,所做的事情或多或少与循环相同。
当我在探索 python 的时候,我发现 For 循环中发生了一些非常惊人的事情,我认为这是值得一写的。乍一看,在一个 for 循环中会发生如此惊人的事情,这似乎很*常,但实际上非常有趣。本文将涵盖以下内容:
- 迭代器,它们是什么,如何工作。
- Python 中 for 循环的实际实现。
Python 中的迭代器
在我们开始揭穿“For 循环”之前,我们需要首先建立对迭代器的理解,因为迭代器在它的工作中起着重要的作用。
什么是迭代器?
在 python 中,一切都是一个对象,就像 python 中的任何其他对象一样,迭代器也是一个对象,但这个对象可以被迭代到上,并且在调用时一次返回一个元素。
迭代器在 python 中随处可见。我们将在列表理解、生成器中找到迭代器,正如你可能已经猜到的,它们也在“For 循环”中实现。
迭代器是如何工作的?
如前所述,迭代器是一个可以被迭代的对象。创建迭代器对象的必要条件是它必须实现两个特殊的方法
- iter()方法。当调用 iterable 时,这个方法返回一个 iterator 对象。
一个 iterable 是一个对象,我们可以从中获得一个迭代器。例如列表、元组、字符串。
- next()方法。这个方法一次从一个 iterable 中返回一个元素。它用于迭代一个迭代器对象。
让我们看下面一个简单的代码示例,以便更好地理解迭代器。
# a list which is an iterable
numbers = [1,2,3,4,5]# creating an iterator object from the iterable (numbers)
num_iterator = iter(numbers) # returns an iterator#Iterating through num_iterator using next() method
print(next(num_iterator)) # output: 1
print(next(num_iterator)) # output: 2
print(next(num_iterator)) # output: 3
print(next(num_iterator)) # output: 4
print(next(num_iterator)) # output: 5# when no more elements left, exception is raised
print(next(num_iterator)) # StopIteration Exception Raised
使用 iter()方法,我们从数字列表中创建了一个迭代器对象。然后,我们使用 next()方法手动遍历迭代器的所有元素。一旦我们到达数字的末尾,如果我们继续调用迭代器上的 next()方法,就会引发 StopIteration 异常。
Python 中 For 循环的实际实现
既然我们对 python 中迭代器的工作原理有了很好的理解,现在我们可以看看 Python 中的 For 循环的幕后发生了什么。
需要 for 循环吗?
从前面的代码片段中我们可以看到,我们手动遍历列表,这对于一个包含大量数字或元素的列表来说是非常繁忙的。一定有更好更优雅的方法来做同样的事情,那就是 via For 循环。因此,我们之前的代码可以转换为以下代码:
for number in numbers:
print(number) # output: 1,2,3,4,5
只需两行代码和相同的功能。太好了。
For 幕后循环
现在看一下下面的代码片段
num_iterator = iter(numbers)while True:
try:
# get the next item
number = next(num_iterator)
except StopIteration:
break
看着上面的代码,你可能想知道为什么这里有 while 循环,而我们一直在谈论 for 循环?你现在看到的实际上是一个 for 循环背后发生的事情。上面的代码是 python 中一个 for 循环的实际实现。
每当对 iterable 调用 for 循环时,在内部使用 iter()方法从 iterable 创建迭代器对象,并使用无限 while 循环在 try/catch 块中使用 next()方法迭代迭代器对象的值。一旦我们到达迭代器中的元素末尾,就会引发 StopIteration 异常,我们就跳出了无限循环。
所以“for 循环”只是一个无限的“while 循环”,带有迭代器的实现。讽刺。
摘要
在本文中,我们学习了什么是迭代器,它们是如何工作的,以及一个 for 循环是如何在 python 内部实现的,它只是一个无限的 while 循环。
如果你喜欢这篇文章,请看看我的其他文章。帮我达到 500 个追随者,跟随我在媒体上获得更多这样惊人的内容。谢了。
在介质上阅读 Furqan Butt 的文字。大数据工程师,Python 开发者。让我们连接…
medium.com](https://medium.com/@furqan.butt)
分散强化学习
强化学习新范式的详细概述
世界上许多协会,如生物生态系统、政府和企业,在物理上是分散的,但在功能上是统一的。例如,一家金融机构的全球经营政策是利润最大化,因此看起来像一个单一的实体;然而,这种实体抽象是一种错觉,因为金融机构是由一组独立的人类代理组成的,他们在没有协作的情况下解决他们的优化问题。在深度强化学习中,最大化目标函数的过程将策略参数化为从状态到动作的函数。策略函数参数根据定义的目标函数的梯度进行微调。这种方法被称为 整体决策框架 ,因为策略函数的学习参数仅使用目标函数进行全局耦合。

注意在 整体决策框架 中行动是如何被代理被动选择的。来源:https://bair.berkeley.edu/blog/2020/07/11/auction/
在简要介绍了集中式强化学习框架的背景之后,让我们继续讨论一些有前途的分散式强化学习框架。
分散强化学习:通过本地经济交易的全球决策
文献[1]提出了一类分散式 RL 算法,该算法在不同抽象层次上建立了社会(全局策略或超级代理)和代理(动作)之间的关系。一个 社会决策框架 被定义在最高抽象层次上,以理解由代理局部解决的优化问题和由社会全局解决的优化问题之间的关系。在每个州,地方一级的代理人在拍卖中出价,拍卖的获胜者将州从一个转变为另一个;之后,它将转换后的状态出售给其他代理,从而传播当地的经济交易链。现在出现了一个关于拍卖机制和社会的特征的问题,这使得简单地从代理优化他们的拍卖效用的全局解决方案的隐含出现成为可能。通过 克隆的维克瑞社会 在抽象的第第二阶段提供了上述问题的解决方案,这确保了代理的支配策略均衡匹配社会的最优策略。[2]中详述的维克瑞拍卖的真实性属性保证了上述结果。在第三抽象级别,提出了一类 分散强化学习算法 ,其利用代理的拍卖效用作为优化目标,并因此仅使用针对代理的可学习参数的信用分配来学习在空间和时间上是全局的社会政策,该可学习参数在空间和时间上是局部保存的。第四抽象级别涉及克隆维克瑞协会的实现,该协会利用提议的分散强化学习算法,并提出一组名为 信用保存维克瑞实现 的最佳设计选择,该设计选择在全局和局部级别都表现最佳。

注意在 社会决策框架 中,行动如何主动选择何时激活。来源:https://bair.berkeley.edu/blog/2020/07/11/auction/
社会决策
让我们通过将马尔可夫决策过程(MDP)和拍卖机制联系在一个统一的符号下来建立基于社会的决策框架。
在 MDP(全局)环境中,输入空间是状态空间,输出空间是动作空间。一个代理代表一个策略 π: S → A 。使用转移函数τ:s×a→s、奖励函数r:s×a→ℝ和折扣因子γ指定一个目标函数如下:**

在给定的状态 s 下,代理执行使 J(π)最大化的任务,并因此找到如下定义的最优动作:

在拍卖(本地)环境中,输入空间是单个拍卖项目 s,输出空间是出价空间𝔅.n 个代理中的每一个使用其各自的投标策略在竞争中对拍卖项目投标ψᵢ: {s} → 𝔅.设 b 是代表 n 个代理人出价的向量,那么每个代理人的效用可以用 vₛ 来定义:这个向量表示每个代理人对投标物品 s 的评价,以及由分配规则x:𝔅ⁿ→定价规则**p组成的拍卖机制**因此,效用函数可以规定如下:****

在拍卖理论中,一次拍卖是一个显性策略激励相容 (DSIC)如果在拍卖中独立于其他参与者的出价策略,对一个人的评估出价是最优的。维克瑞拍卖【2】将 Pᵢ(b 设定为第二高的出价,如果代理人 i 获胜则 Xᵢ(b)=1 为 0,如果代理人 i 失败则为 0,这就是 DSIC,意味着当每个代理人如实出价时会出现优势策略均衡。这导致社会福利最大化(∑vᵢ×Xᵢ(b),因此选择评价最高的投标人。DSIC 财产在维克瑞拍卖中的存在消除了代理在执行优化时考虑其他代理的需要,因此使用维克瑞拍卖构建的分散强化学习算法非合作地运行。**
定义
“一个 原语 (代理)ω是一个元组(ψ,ϕ),其中ψ: S→𝔅代表竞价策略,ϕ: S→S 代表转换。一个 社会 是一组被表示为ω^{1:N}.的原语**
最优出价(如[3]中所述):假设在每个州 s,如果代理 I 获胜,本地拍卖分配 Xᵢ(b)=1,如果代理 I 失败,分配 Xᵢ(b)=0。然后,所有的原始ω^i 投标各自的最优社会 q 值作为一个整体产生一个最优的全球政策。
最优竞价的优势策略(如[1]中所述):如果每个状态 s 的 vᵢ估值是最有利的社会 q 值,那么社会的最优全球政策与维克瑞机制下的原语的独特优势策略均衡相一致。——
经济交易视角

市场经济视角及其解释。来源:https://bair.berkeley.edu/blog/2020/07/11/auction/
因此,上述系统中的货币基于所收到的回报,并且财富分配的发生取决于未来的基元决定出价购买过去的基元所承担的信息处理劳动的成果,目的是将一种状态转换为另一种状态。

克隆的维克瑞协会。图 1 来源于[1]

对描述 clove Vickrey society 机制的上图的简明解释。来源:图 1[1]
基于策略的分散强化学习算法

来源:第 6 节[1]
在学习了利用克隆的 Vickrey 拍卖机制的分散强化学习算法的内部工作原理之后,如果您想了解更多关于使用该算法执行的实验,请参考第 7 节标题为[1]的实验。
在[1]中描述的分散强化学习算法模拟了由于使用克隆的维克瑞协会而导致的不合作的特征。在接下来的章节中,我们将熟悉另一种分散强化学习算法,但是是在合作控制环境中。
用于协同控制的深度分散强化学习
形式问题定义
给定一个由 N 个智能体控制的离散时间系统 f: X × U → U 表示为**

来源:文献[4]中的等式(1)
其中 xₖ ∈ X ⊆ ℝⁿ表示系统在时间步 k 的状态,
u_{i,k} ∈ Uᵢ ⊆ ℝ对智能体的控制 i ∈ ℕ = {1,…, N }和 U=U₁×U₂×…×U_{N} 联合控制空间。每个智能体 i ∈ ℕ根据当前状态 xₖ和控制 u_{i,k},从奖励函数 g: X × U → ℝ 中获得奖励 rᵢ。

来源:文献[4]中的等式(2)
每个代理的目标是适应他的控制律πᵢ: X → Uᵢ,在控制律元组
π=(π₁,π₂,…,π_{N})和γᵢ ∈ [0,1]作为折扣因子下,最大化他的长期折扣报酬

来源:文献[4]中的等式(3)
因此,确定性博弈可以由元组
G = (X, f ,U₁,…,U_{N},g₁,…,g_{N},γ₁,…,γ_{N})来定义,问题可以描述为:
问题陈述
给定博弈 g,每个代理人 i∈ N 知道系统动力学 f 和他自己的奖励函数 gᵢ.此外,每个代理 i∈ N 在时间步 k 接收他的当前报酬 r_{i,k},并且能够推导出其他代理的先前控制 u_{j,k1 },
∀ j∈ N{i},但是不能访问当前控制 u_{j,k},其他代理的控制法则πⱼ,它们的报酬函数 gⱼ或实际报酬。在这种情况下,每个智能体 i∈ N 的目标是调整其控制律πᵢ,以最大化上述定义的 Vᵢ^{π}。——【4】**
分散协同控制方法
为了解决上一节中提出的问题,用于协同控制的深度分散强化学习提出了一种依赖于时间的时间经验重放* (TER) 来解释由多个智能体组成的非*稳环境,使用虚拟经验重放 (IER) 来灌输系统的已知动态,并利用具有影响 Q 学习 (IQL) 的变量学习来诱导协调。这些机制是模块化的,因此让我们先介绍它们,然后再组合它们。***
时间体验回放(TER)
提出时间体验重放背后的基本概念是根据类似于优先体验重放的优先因子,将偏好更*的体验的想法与体验重放中可能的体验采样相结合。但是这里我们的关注点更倾向于最*的经历,因此我们引入了时间优先化* τ,它与收集状态转换后经过的时间成比例。***

来源:[4]中的等式(7)和(8)
因此,需要通过附加当前时间步长来生成新的体验元组,以灌输上述时间优先化因素。

来源:[4]中的等式(9)
然而,上述的 TER 方法在实践中导致了两个主要问题:(1)太多偏向于最*的经验可能导致代理的策略过拟合,以及(2)由于需要在每个时间步长为每个经验元组计算τ,这增加了采样过程的计算复杂度,使得 TER 在实践中不可行。为了克服上述问题,引入了两步采样过程。首先,从整个体验重放缓冲器 M. 中均匀随机地提取大小为 b 的宏批次 𝔅。随后,使用前面提到的时间优先化概率从𝔅采样大小为 t 的小批次tt≪b。这解决了这两个问题,因为通过从大小为 b 的𝔅采样降低了计算时间优先级的计算复杂度。此外,小批量均匀随机抽取防止在代理人的政策中过分强调最*的经历。**
此外,为了适应其他代理的策略变化,我们还需要考虑代理在其训练过程的不同阶段的可变探索率εₖ。当其他玩家的政策开始趋同时,降低探索会更有效。因此,我们提出了一个额外的勘探率依赖 b,产生一个时间相关的宏观批量 Bₖ.在早期训练过程中,即εₖ ≈ 1,经验应均匀随机抽样,这可以通过选择接*小批量 t 的 Bₖ来获得,而在后期训练过程中,即一旦εₖ → 0,Bₖ应接*最终的宏批量 b。随后,我们有如下宏批量:

来源:[4]中的等式(10)
想象中的经历回放(IER)
TER 对经验重放所做的修改为训练过程赋予了稳定性,因此代理人对变化的环境动态的接受度较低。此外,TER 避免了偏向于最*经验的学习,从而使智能体能够适应非*稳的环境动态。到目前为止,一个重要的假设是,环境动态与其他主体的行为分离,这通常是合理的,因为主体是独立和分散的。然而,我们知道系统动态,因此有可能通过边缘化其他代理的控制来使环境静止。这是想象的经历重演背后的基本概念(IER)。请注意,IER 仅用于模拟在正常环境条件下可能不会发生的体验。前面提到的常规经验元组可以用下面的底层系统动力学 f 和奖励函数 gᵢ来代替:

来源:文献[4]中的等式(12)
其中 u_{-i} = {u₁,…,u_{i-1},u_{i+1},…,uₙ},即除了代理 i. 之外的其他代理的控制。最终,想象体验可以通过将其他代理的控制 u_{-i}替换为 0 来模拟,如下所示:****

来源:文献[4]中的等式(13)
想象的体验实际上并不存储在 ERM 中,而是用于采样探索率相关概率用于确定除了观察到的体验之外,是否还计算了想象的体验。最初,在训练过程中,代理大多执行随机控制的探索。因此,不可能从初始阶段的抽样观察中推断出其他代理的策略,因此应用 IER 来稳定训练过程是最有用的;因为在 IER,体验是以这样一种方式模拟的,即只有智能体 i 与环境互动,没有来自其他智能体的探索噪音。因此,与当前时间步长 k 处的想象体验的模拟相关联的概率与εₖ(当前探索速率)成比例,因此,p(k)∞εₖ.**
随后,在培训过程的后期阶段,代理的策略开始趋同。与后期探索相比,更重视主体之间的协调和对合作伙伴政策的适应。因此,在训练的后期阶段,通过产生模拟代理之间合作的经验,IER 可以用于诱导代理之间的协调。相应的采样概率被建议为 p _ { coord }(k)∞(1 εₖ).为了诱导协调,想象的体验需要通过 IER 产生,这样最终的算法需要混合的合作-竞争任务类型。为实现上述目标,提出了以下三种方案。**

第一种情况:代理人 i 的控制被放弃,因此代理人 I 可以观察其他代理人自己如何行为,以及由此产生的环境转换是否有益。来源:文献[4]中的方程(14)

第二种情况:代理 I 的控制被设置为等于所有其他代理的联合控制的*均值。来源:文献[4]中的等式(15)

第三种情况:所有其他代理的控制被设置为等于代理 I 的控制。来源:在[4]中的等式(16)
通过从上述三种情景中产生想象的经验,协调的可能性被耗尽了。第一个场景导致代理评估空闲是否可接受,而第二个和第三个场景计算代理 i 是否复制其他代理的*均控制或者所有其他代理是否应该坚持代理 i 的控制。
影响 Q-Learning (IQL)
以前对 ER 的修改通过稳定环境来解决不稳定的环境问题。此外,在多主体强化学习中经常使用的一种机制是可变学习率。用于合作控制的深度分散强化学习提出了一种使用可变学习率的多智能体信用分配任务的新方法,该方法试图将可变学习率与智能体对回顾性观察到的状态转换的个体贡献相关联。同样,引入了一个称为影响因子的量,它表示代理对联合控制的贡献,从而表示观察到的状态转换。**

时间步长 k 时代理 I 的影响因子。来源:[4]中的等式(17)
假设在 IQL 中,代理共享相同的控制空间 U₁ =。。。= U_{N}并且所有代理的控制同等地操纵系统,我们可以如下描述更新规则:

IQL 更新规则。来源:文献[4]中的方程(18)
其中 0 ≪ β ≪ σ ≪ α ≪ 1。使用上述 IQL 更新规则,我们可以同意,当一个适当的积极的经验被观察到,Q 值估计大幅增加,只有当代理人可以被认为是事件的发生。另一方面,当负面体验发生时,如果代理人至少有部分责任,代理人大多不鼓励转换到相应的状态-动作对。此外,代理需要这种责任驱动的类型的学习行为来克服多代理设置中的信用分配挑战。**
算法
在了解了模块化节 ter、IER 和 IQL 之后,我们现在准备详细说明最终算法如下:

协同控制的深度分散 RL 算法。来源:[4]
在前面的章节中唯一增加并且没有解释的是配合系数 ψ_{i,k} =sgn()。如果ψ_{i,k}的值为 1,那么代理人 i 和其他人被称为正协调,因此没有必要模拟 IER 提到的协调经验χ_{idle}、χ_{coop1}和χ_{coop2}。而且,主要用于λ_{high} ≥ λ_{i,k} ≥ λ_{low}的学习率σ被更大的学习率α所代替。因此,代理被说服在培训过程中强调合作经验。在智能体负协调的情况下,ψ_{i,k}等于-1。这里,除了采样的体验χₖ,还模拟了人工想象的体验χ_{idle}、χ_{coop1}和χ_{coop2},因此,代理对所有这些体验进行训练。这里使用了最低的学习率β,因为代理接受培训的经验并没有实际发生,而只是为了协调而想象出来的。因此,模拟若干协调体验的繁重计算任务可以在很大程度上减少,并且主要集中在与最高预期训练进度相关的事件上。**
为了了解更多关于使用上述算法进行的实验和模拟,我强烈建议您参考第 4 节,标题为[4]中的结果。
在这一点上,我们已经涵盖了两种有前途的方法,旨在实现分散强化学习,一种是在非合作环境中(“分散强化学习:通过本地经济交易进行全球决策”),另一种是在合作环境中(“用于合作控制的深度分散强化学习”)。**
参考
- 分散强化学习:通过本地经济交易的全球决策。arXiv 预印本 arXiv:2007.02382 (2020)。
- 威廉.维克瑞。"反投机、拍卖和竞争性密封投标."《金融杂志》,第 16 卷第 1 期,1961 年,第 8–37 页。 JSTOR ,www.jstor.org/stable/2977633.**
- Baum,E. B.《走向一个由白痴组成的自由放任经济的心智模型》。在 ICML,第 28-36 页,1996 年。
- 《合作控制的深度分散强化学习》 arXiv 预印本 arXiv:1910.13196 (2019)。
去中心化人工智能&捍卫隐私:联邦学习的天才

来源: Unsplash
伦理和非侵入式机器学习
很有可能,你的手机现在就在你五英尺之内。
事实上,2013 年的一项研究发现,72%的人大部分时间都在手机的范围内。2015 年的一项研究发现,63%的参与者每天离开手机不到一小时。另有四分之一的人根本不记得离开过他们的手机。
很明显,我们的设备,尤其是我们的手机,不断地产生数据。它们充满了传感器——既有跟踪你的触摸动作和浏览历史的数字传感器,也有跟踪你的物理位置和运动的物理传感器。你的手机是你的数据化身,而且它非常容易获取,这可能会令人不安。
从机器学习的角度来看,这非常有帮助。随着数据的增多,这是一个创造更智能的模型,产生更吸引人和个性化结果的绝佳机会。无论是根据你的位置来管理定制的搜索结果,还是监控你的浏览和社交媒体活动,以推荐合适的产品来购买,更多数据的应用数不胜数。
然而,从伦理上来说,你的活动、网络、对话、运动并不真正属于你的前景应该是令人不安的,如果不是可怕的话。在数字时代处理用户数据的组织需要非常谨慎,以免被恶意利用和操纵。如今,许多数字用户理所当然地对他们的数据被如何使用持严格态度。
现在,必须提出一个重要问题:如何在支持(而不仅仅是承认)用户数据隐私的同时,实现大数据带来的更个性化和更具吸引力的体验?
Google 想出了一个解决这个难题的方法:联合学习。在 2016 年的一篇论文中介绍了联合学习,它不是一种特定的算法,而是一种以道德隐私保护方式从用户数据中挖掘洞察力的结构化策略。
然而,为了理解这一点,我们首先必须理解部署人工智能模型的其他传统方法是如何工作的。假设我们正在使用 YouTube 的 app,其中一个核心功能就是它的视频推荐算法。
通常,这些类型的重模型存储在云中,这是有意义的——它们有数十亿个参数,并查看无数个潜在的视频。将模型存储在云中,并让用户通过请求连接到它会更有效率。

由作者创建
用户发送的请求以数据的形式出现,并随响应一起返回。例如,当你正在浏览 YouTube 时,你的手机已经发送了你的数据——你的浏览历史,你感兴趣的话题等等。—到云端,云端返回你可能喜欢的视频(回应)。
基于新连接的数据和你是否实际点击了推荐的视频,YouTube 的推荐算法不断接收新的输入和反馈,以了解它做得如何。它采用新的训练数据,因此可以生成预测,这些预测会随着新的趋势、想法和运动而变化。
显然,这里有许多隐私问题。所有的数据都集中在一个地方——云——每当需要机器学习模型时,你的数据就会被发送到那里,这是很常见的。许多数据泄露是致命的,因为数据过于集中在一个位置。创造比特币背后的驱动力是对银行的同样担忧——集中的资金储备。
另一方面,离线推理消除了对云的严重依赖。当手机处于舒适的状态时,例如接通电源、高电量电池、连接到安全的 wi-fi,它会下载原始型号的缩小版、移动优化版。使用离线推理有几个好处:
- 隐私。显然,对云的持续请求是不需要的。您的数据在您的手机上本地化,手机直接接收来自下载模型的响应。
- 降低有害数据泄露的风险。当每个用户的数据被本地化后,即使黑客能够访问云,这些信息——模型的版本,用户手机上下载的模型的性能——也没有多大用处。这从一开始就降低了实施数据泄露的动机。
- 运行该模型需要更少的带宽和电池。不断维护与云的请求-响应对话,特别是当成千上万的用户在同一时刻做同一件事时,计算成本非常高。离线推理已经得到了很好的发展,使用了模型压缩等方法来产生强大的预测,同时占用很小的存储空间。
- 更低的延迟。因为模型是本地化的,因此只为一个客户服务,所以预测的响应时间要快得多。在数字界面的世界里,一秒钟的每一分钟都价值不菲。
- 即使没有互联网连接,该模型也可以运行。这对于任何产品来说都是一个有价值的特性。例如,考虑一下谷歌翻译:如果你不能把它弹出来,在任何地方翻译文字和视觉形式的语言,它还会受欢迎吗?
因此,在分布式系统中部署模型时,在线和离线推理是标准。显然,从数据管理的角度来看,离线推理更加安全和隐私,但是您不能同时训练模型。另一方面,在线推理不太安全,但模型可以更新。
任何公司都知道,如果他们保持静态,他们将很快失去对需求动态本质的青睐。由于离线推断的局限性,这对于捍卫隐私和安全数据来说并不是一个大胜利。
随着知识的增加,可以提出一个更具体的问题:如何训练深度模型——用新数据更新——同时保护用户数据的隐私?
在最初的概念中,Google 为这个问题规定了一个解决方案框架:
- 选择设备样本来参与训练。这些通常是目前处于“舒适”和活跃状态的手机。
- 当前模型参数被下载到每个设备上。
- 设备在预设的时间段(例如 20 分钟)内训练它们的离线模型,使用本地训练数据来更新模型参数。
- 在预设的一段时间后,手机会将它们的模型参数上传到云端。
- 一种算法获取每个模型的参数——这些参数根据用户与它的交互方式(提供的训练数据)而有所不同——并将它们聚合起来,形成一个更新的全局模型。
- 启动另一轮模型更新。

由作者创建
联合学习如此聪明是因为它解决了离线和在线推理的问题。它允许公司保护用户的隐私,同时随着市场流动动态地更新他们的模型。
联合学习的关键在于聚合算法。联合学习是一种分布式学习,在利用大数据的力量不断优化模型的同时保护隐私。提出的初始算法“联邦*均算法”工作得足够好,其本质上对接收的参数执行加权*均。
让我们举一个联合学习的例子。假设一个短信服务正在测试他们的语言模型,它会根据用户已经输入的内容推荐他们下一步要输入的单词。
选择 100 个用户进行训练,并将当前的模型参数发送到他们的手机上。然后,在接下来的 48 小时内,模特们将会收到基于她们表现的表现更新和培训。例如,假设一个模型在用户已经输入“你好”之后推荐“你”。
如果用户确实输入或选择了“你”,那么该模型就接收到了当前正确决策过程的强化。如果用户没有键入“你”,这是模型要学习的新训练数据。联合学习只能在这些能够纯粹从本地数据收集标签的模型上操作。
我们打字的方式都不一样——一个青少年的短信里充满了缩写(“how r u”、“brb”、“lol/lmao”等)。)与一位杰出的作家风格不同。一家想要成功的公司应该有一个能够应对所有这些受众的模型,然而通过短信,我们交流了一些最隐私的信息——秘密、密码、故事。通过联合学习,每个消费者细分的独特见解可以以保密和安全的方式进行汇总。
联邦学习的天真模型的一个问题是,模型,尤其是非常深的模型,本质上可以记住更新的信息,其参数仍然发送到中央服务器。已经提出了另一种聚合算法,差分私有联邦*均,以进一步保护包含在各个模型参数中的信息。
随着大数据持续快速增长,隐私日益成为首要问题。继续研究联邦学习并将其确立为人工智能的标准是关键。
要点
- 在数字时代,我们的手机和其他设备越来越依赖于你。您的活动、网络、行动和信息需要是安全和隐私的。
- 在线学习集中了人工智能。用户将他们的数据发送到云中的模型,模型返回预测并被更新。离线学习分散了 AI,代价是无法用新的见解持续训练一个全球模型。
- 联合学习结合了在线和离线学习的优点,通过在本地数据上训练模型,然后聚集参数以形成更新的全局模型。通过一个去中心化的系统,可以在不接触个人数据的情况下训练一个全局 AI。
感谢阅读!
分散你的网站
IPFS + ENS

unsplash.com/photos/Q1p7bh3SHj8
当主持一个网站时,你通常会使用一个专门的副总裁,比如数字海洋、 Linode 、谷歌,或者亚马逊。设置好你的服务器后,你可以在 Google Domains 或 NameCheap 注册一个域名。最后一步是编辑您的 DNS 记录,将您的域指向您的服务器。现在,您可以通过导航到您的域名来访问您的网站。但是,这有一个问题。你的 VPS 控制着你网站的托管,域名服务维护着你域名的控制权。如果你的 VPS 宕机或者你正在使用的公司突然被列入你所在国家的黑名单会怎么样?如果 ICANN 把你的域名抢走了怎么办?或者你的域名服务关闭了?
虽然这些不太可能,但它们很重要,让你思考如果你不能再托管你的网站或者你的域名被拿走了,你会怎么做。
使用 IPFS(星际文件系统)和 ENS(以太坊名称服务)你可以以完全分散的方式托管和服务你的网站。
IPFS 被描述为
一个对等超媒体协议
旨在使网络更快、更安全、更开放
你可以把 IPFS 想象成 HTTP 或者 CDN(内容交付网络)。这是一种查询资源的方式,只不过不是由谷歌、亚马逊等控制的几个大型数据中心托管的资源。这些文件是分散的,由世界各地的任何人在不同的节点上运行。
HTTP 基于 URL 查找资源,但是 IPFS 使用散列来查找其网络上的资源。
IPFS 哈希的一个例子是 QMS 4 ustl 54 uo 8 fzr 9455 qaxzwumihyvmcx 9 ba 8 nu H4 uvv,可以通过类似 Cloudfare 的网关访问,例如cloud flare-ipfs . com/ipfs/QMS 4 ustl 54 uo 8 fzr 9455 qaxzwumihvmcx 9 ba 8 nu H4 uvv。
这个散列指向用于托管您自己的 IPFS 节点的起始文件,正如您所看到的,它只显示了到其他文件的链接。

QMS 4 ustl 54 uo 8 fzr 9455 qaxzwumiuhyvmcx 9 ba 8 nuh 4 uvv
但是一个 IPFS 哈希也可以指向一个网站,比如最*刚刚部署到 IPFS 的 tornado.cash (一个加密混合器)。
可以通过 ipfs.io 网关ipfs . io/ipfs/qmrvfzwyojemdccdsik 15m 7 VN 2n 1 bfnz 14 nwvxrhizzzx 5/访问。
总之,IPFS 提供了几个主要的好处
✅分散内容网络
✅不可改变
抵制✅审查
部署到 IPFS
您可以通过启动自己的节点将网站部署到 IPFS。首先下载 IPFS 围棋实现然后打开终端并运行
ipfs daemon
然后,您应该会看到以下输出
Initializing daemon...
go-ipfs version: 0.4.22-
Repo version: 7
System version: amd64/darwin
Golang version: go1.12.7
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/192.168.1.7/tcp/4001
Swarm listening on /ip6/::1/tcp/4001
Swarm listening on /p2p-circuit
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip4/192.168.1.7/tcp/4001
Swarm announcing /ip6/::1/tcp/4001
API server listening on /ip4/127.0.0.1/tcp/5001
WebUI: [http://127.0.0.1:5001/webui](http://127.0.0.1:5001/webui)
Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
Daemon is ready
现在你已经准备好固定你的站点了
ipfs add index.htmladded QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu index.html
6 B / 6 B [=========================================================] 100.00%
为了确保您的站点留在网络上,您可以将它固定到您的本地节点
ipfs pin add QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuupinned QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu recursively
你现在可以通过你的网关导航到输出的散列,并看到你的站点ipfs.io/ipfs/QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu
固定到您自己的节点是很好的,但是,如果您的节点关闭或您托管的文件被删除,并且您的文件尚未通过网络传播,会发生什么呢?
一个很好的经验是将你的站点添加并固定到三个 IPFS 节点。你可以通过创建你自己的 IPFS 集群或者使用一个流行的已经设置好节点的固定服务来实现。如*特拉或太阳穴。
对于这个例子,我们将使用 Pintra。首先,导航到 pintra.cloud ,注册并导航到上传选项卡

上传单个文件或多个文件的目录。当您将文件添加并固定到本地节点时,您还可以固定来自的散列,以确保它在整个网络中传播。
如果你正在用 React 或 Gatsby 这样的框架创建一个 web 应用,你可以把你的build或public文件夹上传到 Pintra。或者你可以查看IPFS-部署来部署你的站点到 IPFS。
现在我们的网站托管在分散的抵制审查的 IPFS 网络上,但是导航到 ipfs.io/ipfs/QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu 很难记住,我们需要一个域名。
注册一个 ENS 域名
以太网名称服务提供
一种安全且分散的方式,使用简单、易读的名称来寻址区块链内外的资源。
ENS 不是在像 Google Domains 这样的网站上注册域名,而是一个非营利组织,提供不可变的.eth域名,并在以太坊区块链上注册。
.eth域名的主要目标是使加密货币地址可读。然而,ENS 增加了将你的域名链接到 IPFS 散列的支持,因此当一个.eth域名进入你的浏览器时,它将解析到你在 IPFS 的网站。
例如,我的.eth域名是 kohorst.eth 如果你将该域名输入你的加密钱包(如果有 ENS 解析器的话),它将解析为我的 eth 地址。更重要的是,如果你在浏览器中输入kohorst.eth/(如果它有类似勇敢的 ENS 解析器,如果没有你可以输入kohorst.eth.link它会解析)我的个人网站(托管在 IPFS)会解析!
第一步是购买你的 ENS 域名。导航至[app.ens.domains](http://app.ens.domains)并搜索您的域名。

注意:要购买 ENS 域名,您需要以太网和兼容 Web3 的浏览器/扩展。我个人用 Metamask 推荐这个入门教程。
选择您希望购买域名的年数,然后按照购买步骤进行操作。
在您签名并验证您的交易后,您必须等待交易在以太网区块链上得到验证。交易完成后,您可以点击您的域名进行管理。
它看起来会像这样

app.ens.domains/name/kohorst.eth
有很多东西你可以添加到你的 ENS 域名你的 ETH 地址以及其他加密货币,如 BTC 或 LTC,你的电子邮件,Github 甚至 Twitter 用户名。最重要的是,你可以添加你的 IPFS 哈希。
点击添加按钮,在Content下添加你网站的 IPFS 散列

您必须为要写入区块链的内容支付汽油费用,在交易被验证后,您应该能够导航到yourdomain.eth.link并查看您的 IPFS 网站!
IPFS 和常规域名服务
没有以太或者不想让你的域名在.eth结束?您可以将您的传统 DNS 指向您的 IPFS 哈希,这样您就可以保留您的.com域名。你可以在这里了解更多信息。
在谷歌域名中,你需要注册一个指向 IPFS 网关 IP 地址的 A 和 AAAA 记录。你可以使用nslookup来查找 IPFS 网关的 IPv4 和 IPv6 记录(一个功能良好的网关列表在这里可以找到)。
我使用的ipfs.io网关其记录是
A 209.94.90.1
AAAA 2602:fea2:2::1
在您的 DNS 上注册这些,然后创建一个带有 dns link 值的 TXT 记录,如下所示
"dnslink=/ipfs/<HASH>"

lucakohorst.com的 DNS 记录
就是这样!现在你的域名将指向你的 IPFS 网站。
[## 卢卡斯·科霍斯特
科霍斯特. eth](http://kohorst.eth.link/) [## IPFS 为分布式网络提供动力
IPFS 的目标是超越 HTTP,为我们所有人建立一个更好的网络。今天的网络是低效和昂贵的
ipfs.io](http://ipfs.io/) [## 以太坊名称服务
ENS 提供了一种安全、分散的方式来解决区块链内外的资源问题
ens .域](https://ens.domains/) [## 轻松添加文件到 IPFS
Pinata 通过我们简单的 IPFS API 和工具包简化了分散存储。我们的 IPFS 大头针服务提高了您的…
pinata.cloud](https://pinata.cloud/)
决定在人工智能原型中测试什么

paweczerwiński 在 unsplash 拍摄的照片
决定测试什么是定义人工智能原型的第一步,也是最重要的一步。这个决定影响了原型设计中的所有其他决定。
定义测试中的假设很重要,因为原型是杂乱的。杂乱的实验给出混乱的结果;把相关的隐藏在偶然事件中。
原型是最终产品的粗略*似。从原型中获得的知识可能会改变游戏规则,引人入胜,而且完全令人惊讶。但是要自信地从原型中学习,效果或洞察力需要很大。
从原型中得到一个发现并加以概括是非常容易的,但后来发现这种学习与原型本身的一些缺陷直接相关。原型和最终产品之间的微小差异会影响学习。一些细节,比如元素加载的速度,或者被限制在几个用户行程之内,会对用户的反应产生非常真实的影响。
有了原型,我们寻找大的效果。一旦我们的注意力被吸引,事情就会变得显而易见。不是优化。对于优化,在设计过程的后期进行,并考虑对大型用户组进行 A/B 或多变量测试。
由于测试中有许多元素,反馈会有噪声。很难理清用户告诉我们和展示给我们的东西的因果关系。
我们可能想要测试的内容类型包括:
技术细节
- 模型的性能。
- 交付模型结果的速度。
- 来自模型的反馈率以及用户是否可以直观地“教授”系统。
界面
- 人工智能功能的交互性如何。
- 人工智能特性有独立的元素吗?如何将这些与系统的其他部分区分开来。
消息传递
- 解释人工智能算法;它做什么以及如何学习。
- 教用户如何让产品学习。
- 模型结果的数值;期望用户有多擅长算术。
- 我们是否以及如何传达错误信息。
误差校正
- 如何在出错时安装故障保险?
- 如何确定模型是否已经崩溃?
- 当模型崩溃时我们该怎么办。
- 如何从灾难性错误中恢复?

测试来自 simonoregan.com的人工智能原型
将这些测试分开很重要。为了测试技术细节对用户的影响,最好已经完成了界面、消息和错误通信的最终设计。
消息传递与接口和错误处理紧密相关,通常不会单独测试。相反,接口和消息传递或者错误处理和消息传递将成对测试。
要记住的重要一点是,我们不希望快速交换这些排列,希望我们能观察到用户反应的细微差异,以帮助我们确定最佳组合。对于小用户群,结果在统计上肯定不显著,通常也不具有普遍性和相关性。
相反,选择一个具有明确定义的预先假设的配置,并观察用户的行为是否如预期的那样,如果不是,为什么不是。
感谢您的阅读🙏🏻
这篇文章最初发表于simonoregan.com。
如果你喜欢这个,你可能会喜欢【部署时代】——每周更新的工具和思考,揭示了 2020 年代的新兴技术和趋势。
网飞*年来的内容战略

利用文本挖掘进行内容分析(自然语言处理)
OVID -19 为我们的日常生活带来了新的标准。社交距离和隔离的做法让我们花更多的时间呆在家里,否则我们会在工作日通勤上班或周末逛商场。
作为一个喜欢看电影的人,我决定每天晚上在网飞看 1-2 部电影。当我啜饮咖啡,翻阅网飞的电影名时,我意识到我花了太多时间来决定我想看哪部电影。我通常按流派搜索 15-20 个标题,并在划分电影区域之前阅读它们的描述。鉴于网飞有太多的选择,我们不都花了很多时间来决定看哪部电影吗?当我继续搜索电影,仍然不确定选择哪部电影时,我想知道网飞的整个内容团队是否每天都在解决同一个问题: 我应该为我的订户选择哪些内容?
对于网飞这样的流媒体*台来说,内容将是增加其付费用户基础的最重要的战略杠杆之一。快速浏览一下网飞 2019 年第四季度的财务报表就会发现,其付费用户数量高达 1.67 亿。(见下图 1)
如果网飞所有的付费用户组成一个国家,比如网飞共和国,它将是世界上第九大人口大国,比第八名落后一百万。

图 1:每季度付费用户净增数;资料来源:Srinivas Vadrevu 基于 2019Q4 财务报表数据对 2017Q1 至 2019Q4 各季度付费用户净增数的分析

图二:每个季度免费试用用户;资料来源:Srinivas Vadrevu 根据 2019Q4 财务报表数据对 2017Q1 至 2019Q4 各季度试用用户的分析
此外,有趣的是,2018 年第四季度试用用户激增至 920 万,随后 2019 年第一季度付费用户数量增加了 960 万。2019 年第一季度,大部分试用用户成为付费用户并创造了付费用户高峰吗?
虽然 2019 年每个季度试用用户都在减少,但从 2019 年第二季度到 2019 年第四季度,付费净新增用户在增加。是用户直接创建付费账户没有试用期!?没有用户层面的数据,很难回答这些问题。
与每个用户的收入相比,每个用户的内容支出在这几个季度中有什么变化?
收入和营销支出在 2019 年第四季度财务报表的历史分部部分有所提及。由于网飞提供的内容类型不同,内容支出的计算也有所不同。

图 3:网飞内容的类型;来源:网飞投资者关系-2018 年 1 月
截至 2018 年 1 月的会计处理文件提到,内容支出将被计算为流媒体内容资产的加+流媒体内容负债的变化。
下表提供了过去 12 个季度中每个季度的付费用户增加、收入、内容支出和营销支出等财务数据的快照。

图 4:收入、营销和内容支出分析;来源:Srinivas Vadrevu 基于网飞财务报表 2019Q4 的数据进行的分析

图 5:每个付费用户的*均收入和支出;资料来源:Srinivas Vadrevu 基于网飞财务报表 2019Q4 的数据进行的分析
- 每付费用户的*均收入在过去 4 个季度中不断增长,从 2018 年第 4 季度的 29 美元增长到 2019 年第 4 季度的 32 美元
- 从 2017 年第一季度到 2018 年第四季度,每个付费用户在*台上的内容支出逐渐增加。它在 2019 年第一季度大幅下降 20%至 20 美元,并在过去四个季度中一直增长,直到 2019 年第四季度达到 27 美元。
- 在过去的 12 个季度中,*台上每个付费用户的营销支出几乎保持不变——2-3 美元

图 6:每个季度内容现金支出和付费净会员增加;来源:Srinivas Vadrevu 基于网飞财务报表 2019Q4 的数据进行的分析
为了解释前面提到的 2019 年第一季度每用户内容支出的下降,让我们来看看每个季度总内容支出和净付费用户增加之间的关系。2019 年第一季度,内容支出首次下降,付费新增用户创下* 12 个季度以来的新高。这解释了为什么在过去的 12 个季度中,每个用户的内容支出处于历史最低点。
但是,到 2018 年第四季度,每个季度的内容支出都以大约 7%的速度持续增长。在 2019 年第一季度,他们减少了 15%到 5 亿美元的内容支出。在下一个季度,即 2019 年第二季度,付费净用户的数量从 960 万急剧下降到 270 万。看起来上个季度的内容支出可能会对下个季度(2019 年第二季度)的净付费用户增加产生影响。
我计算了上述指标,只是为了检查内容支出是否有任何重大变化,我们认为 2019 年第二季度出现了这种变化。我敢肯定,大多数跟踪网飞的股票分析师现在正忙于对其财务报表进行内容分析,为即将于 2020 年 4 月 21 日发布的收益公告做准备。然而,我更感兴趣的是探索网飞多年来做出的内容选择,而不是内容支出/财务指标。由于它所做的内容选择不仅让其截至 2016Q4 的 8900 万用户欣喜不已,还在未来三年内带来了 7800 万付费用户的增长(包括我!).
“当我们取悦我们的会员时,他们看得越多,我们就成长得越多”——网飞 2019Q1 致股东的信
那么,网飞增加了哪些内容来取悦用户呢?
我越是纠结于上述问题,就越想找到一种方法来回答这个问题。碰巧的是,我在网飞理工大学的博客上看到了一篇优秀的文章,阐述了网飞如何依靠预测数据模型来评估其跨语言的内容消费。我认为这是一个对电影和分析都有热情的人的好博客。鉴于对数据驱动的决策的如此强调,以找出内容及其创作生命周期,我推测这些决策应该作为模式出现在它添加到其*台的标题中。我决定在新冠肺炎封锁期间利用这段额外的时间学习一点 NLP(自然语言处理),并检查我是否可以应用任何基本的 NLP 技术来理解网飞对其内容所做的选择。由于网飞依靠消费者层面的数据来得出这些选择,我们或许可以在这个过程中发现一些客户偏好。
数据来源
为了探索这一点,我查看了两个数据源来对其内容策略进行三角分析—
(1):季度致股东信中的内容部分——每个季度,网飞都会发布一封致股东信,其中有一个内容部分。在这一部分中,网飞介绍了其内容选择、原因以及该季度的表现。
数据来源:网飞在其网站上给股东的信https://www . Netflix investor . com/financials/quarterly-earnings/default . aspx
(2)网飞在其*台上的实际标题列表。就网飞传达其内容战略而言,上述数据来源是自上而下的方法。使用网飞上的标题和它们的描述,实际的内容策略可以被破译。
数据来源:我使用了来自 kaggle.com的数据集,主要基于从 flixable.com网站收集的数据。Flixable 包含美国网飞上当前可用的所有电视节目和电影。
上述数据集没有将内容分类为网飞分类的三种类型的内容。在本文中,我们不会按自制标题、品牌和授权标题以及仅授权标题对内容选择进行分类。
在合并金融数据集和 Kaggle 数据集后,我发现 2018 年第二季度获得一个标题的内容花费最高—$ 860 万美元,而 2019 年第一季度获得一个标题的内容花费最低,为$ 560 万美元。

图 7:每个季度的总内容花费和每个标题的花费;来源:Srinivas Vadrevu 基于网飞财务报表 2019Q4 的数据进行的分析
在此之前,我开始处理来自两个数据集的文本,这是朱莉娅·西尔格和大卫·罗宾逊的“用 R 进行文本挖掘”的一大亮点。我发现这上面的内容对学习文本挖掘和绘制下面的图表非常有帮助。
网飞传达了哪些关于它的内容?

Miguel Henriques 在 Unsplash 上的照片
分析致股东信的内容部分(自上而下)
为了理解网飞在内容部分使用的关键主题,我从网飞发布给投资者的致股东信中收集了内容部分。我整理了最* 30 个季度(2012Q3 到 2019Q4)的数据。从这个数据集中,我从文本中提取了二元模型标记,在去除了停用词之后,从语料库中创建了二元模型的网络可视化。下图创建了一个二元模型的网络结构(两个单词的组合)。比如说,“la”+“casa”=“la casa”是一个二元模型,“case de”是另一个二元模型。两个二元模型在节点“casa”处连接,形成网络结构“la casa de”。

图 8:2012 年第三季度至 2019 年第四季度(30 个季度)致股东信中内容部分的常见二元模型;(二元模型计数> 4);资料来源:Srinivas Vadrevu 基于从网飞致股东的信中收集的数据进行的分析
我已经把上面的二元模型分成了几个大的主题类别。让我们来看看网飞传达给股东的关键主题:
- 原创内容(字:“原创”,红泡泡左边) - 在最*的三十个季度里,网飞几乎都在突出自己的原创内容。原创+电影、原创+故事片、原创+内容、原创+纪录片、原创+节目和原创+系列等等。
- 热门/热播系列(《黄色泡泡》)——绝命毒师、Bojack 骑士、漫威的超胆侠、Le Casa de Papel (金钱大劫案——英文版) Turbo F.a.s.t .、发展受阻、神圣游戏和铁杉树林
- 大众喜剧个人————【黄泡】——演员:里奇·格威斯、编剧:杰姬·科恩
- 电视节目中的主要类型(节点词:“系列”,红色泡泡的右边部分)——电视剧、喜剧、儿童、动画、脚本系列、限量系列和电视系列。科幻流派
- 连续性- 网飞在推出后续剧集时都会提到这些剧集的名字——第二季、第三季和回归季
- 品种- 迎合品种繁多和口味多样;
- 地点聚焦--拉丁美洲和北美
- 优质- 奖项&节庆 (绿色泡泡)——传递优质内容。奥斯卡金像奖、金球奖、艾美奖提名、艾美奖奖和电影节等奖项经常被提及。
2014–2016 年至 2017–2019 年关键二元模型的变化

图 9:致股东信内容部分在三年时间窗内的常见二元模型——2017 Q1 至 2019Q4 和 2014Q1 至 2016Q4(计数> 4);资料来源:Srinivas Vadrevu 基于从网飞致股东的信中收集的数据进行的分析
当我在 2017 年至 2019 年和 2014 年至 2016 年的三年窗口中绘制常见二元模型时,除了上面提到的关键趋势外,内容重点还有一些变化。
- 与 2014 年至 2016 年相比,喜剧系列在 2017 年至 2019 年期间不再被频繁提及。
- 剧集和限量系列在 2017–2019 年被提及的频率更高
- 2014-2016 年第二季已经让位给 2017-2019 年回归的第三季。
- 当然,热门节目从 2014-2016 年到 2017-2019 年发生了变化
- 电视网络和互联网电视在 2017-2019 年没有被频繁提及
- 在过去的六年里,对原创内容的重视保持不变
那么,与之前的三年窗口(2014、2015、2016)相比,过去三年(2017、2018、2019)发生了什么变化?
*几年更强调剧情,限定剧集,延长季节,当然还有原创内容。较少强调喜剧系列、电视网络和网络电视

查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
B.从《网飞》的实际内容解读内容策略
将他们所说的和他们所做的结合起来。
分析网飞上的所有标题及其描述(自下而上的方法)
Kaggle 数据集(上述数据描述中的第二个数据集)包含过去 12 年(从 2008 年到 2020 年 1 月 18 日)收集的标题信息。数据集中的字段如下:标题的名称、类型(电视节目或电影)、导演、演员、参与制作的国家、在网飞上添加的日期、原始发行年份、分级(美国电影协会或电视家长指南)、标题的持续时间、在类别中列出以及标题的简要描述。我使用标题的描述来提取它的关键内容选择,并列出 _in 类别来提取流派。
B.1 流派
根据添加的日期,我将季度添加到数据集,以研究每个季度添加了什么类型(电影/电视节目)、流派和主题。截至 2020 年 1 月,数据集显示网飞总共有大约 6234 本书。其中 68%(4265 个)是电影,其余的 1969 个标题被分类为电视节目
让我们快速浏览一下从 2016 年第一季度到 2020 年第一季度*(到 2020 年 1 月 18 日)每个季度添加的图书分类。虽然网飞每个季度都会增加越来越多的片名,但%的电影似乎遵循着一种循环模式。(参见下面的图 10)
- *台上有电影的标题比例从 2017 年第一季度的 76%下降到 2017 年第三季度的 65%。
- 随后在 2018 年第一季度逐渐上升至 77%。然后,与 2018 年第一季度相比,2018 年 Q2 在该季度出版的图书总数下降了 48%(约 156 本)。电视节目的数量增加了 3 个标题,而电影标题减少了 159 个。这将百分比降至 70%
- 从 2018 年第三季度到 2019 年第四季度的下一季度,添加的电影片名的百分比持续下降,从 74%下降到 58%(最* 12 个季度最低)。
- 从 2019 年第四季度到 2020 年 1 月 18 日,电影片头%逐渐增加到 2019 年第四季度的 70%,2020 年第一季度截至 2020 年 1 月 18 日增加的片头的 80%。

图 10:根据电影和电视节目添加到网飞的季度,将标题分成电影和电视节目;资料来源:Srinivas Vadrevu 根据 Kaggle 的数据进行的分析
好了,这是关于标题的数量,让我们从数据中看一下热门类型
我们大多数人都偏爱几种类型。而有些人可能喜欢冒险、动作、犯罪、恐怖片等。其他人可能更喜欢爱情片、喜剧片或家庭电影。当我们浏览标题时,我们大多数人可能会根据流派来定位搜索。所以,我选择了流派作为一个重要的变量,来弄清楚网飞是如何添加电影和电视节目的。每本书通常分为 2-3 种类型。因此,我从数据集中的 listed_in 列中提取单词作为单词,去除停用词,以了解每年添加的标题下面列出了哪些热门流派。
2019 年新增的热门游戏类型

图 11:2019 年使用标题的 Listed_In 类别中的标记词提取的流派计数;资料来源:Srinivas Vadrevu 根据 Kaggle 提供的数据进行的分析
上图(图 6)描述了 2019 年按流派和类型(电影或电视节目)增加的标题数。电影和电视节目的五大流派完全相同
- 2019 年 Top 5 流派电影如下:国际、剧情、喜剧、动作、冒险。
- 2019 年电视节目的前 5 大类型如下:国际,戏剧,喜剧,犯罪,浪漫和儿童。
- 除了前三种类型,爱情片、纪录片和儿童片在电视和电影中也很常见。
- 与电视节目相比,电影中的顶级类型更加多样化。一些类型出现在电影的顶级类型中,但没有出现在电视节目的顶级类型列表中。惊悚、家庭、恐怖、奇幻、科幻、音乐剧和独立类型出现在电影的顶级类型列表中,但不包括电视节目。
- 犯罪、现实和动漫类型出现在电视节目的顶级类型列表中,但不在电影中。顶级电影类型列表中也没有基于语言的类型- 英国(英语)西班牙语和韩语。与电影相比,电视节目似乎更能迎合不同的口味和观众。
- 恐怖和奇幻成为 2019 年的热门主题,这些主题在 2018 年并不存在(见下图 7)
2018 年和 2017 年添加的热门类别

图 12:2018 年使用标题的 Listed_In 类别中的标记词提取的体裁统计;资料来源:Srinivas Vadrevu 根据 Kaggle 提供的数据进行的分析

图 13:2017 年使用标题的 Listed_In 类别中的标记词提取的流派计数;资料来源:Srinivas Vadrevu 根据 Kaggle 提供的数据进行的分析
2018 年和 2017 年展示了几乎相同的风格模式,除了一些变化-
- 电影:纪录片和独立电影在 2017 年位居电影体裁前 5,但在 2018 年和 2019 年让位于动作和冒险。
- 电视变化:自然和科学是 2017 年的热门题材,但它们在 2018 年被真人秀、脱口秀、动漫和脱口秀取代
网飞电影的总体类型分布是怎样的?

图 14:使用数据集中所有标题的 Listed_In 类别中的标记词提取的流派的计数;资料来源:Srinivas Vadrevu 根据 Kaggle 提供的数据进行的分析
我能使用上面的数据(图 14)更好地从网飞的 6234 个书目中搜索吗?虽然网飞根据你的搜索选择在“流行精选”和“趋势精选”中为你筛选内容,你仍然可以使用上述数据更好地搜索流派组合。
这里有一个浏览流派组合的提示——一个关于网飞的标题通常分为 2-3 个流派。所以,下次当你在网飞上按流派组合浏览标题时,你可以从上面的列表中选择不太常用的流派,滚动到更常用的流派标签,从而缩小搜索范围。例如,如果您想观看恐怖惊悚电影,并且不想使用遥控器键入 15-16 个字符,请浏览恐怖行(您首先会在这些行中看到一组更窄的恐怖标题),然后在该行的标题标签中查找恐怖片..
B.2 分析故事主题
这里有类型,然后是吸引观众的故事。主题或情节主线是吸引观众参与内容的重要因素。与我分析给股东的信的方法类似,我从数据集中的描述列中提取了去除停用词后作为二元模型的令牌。这些二元模型代表了每年增加的标题的主题。让我从数据集中挑选一些电影和节目来说明这些描述在数据集中是如何表达的。


查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
洛奇 :西尔维斯特·史泰龙因扮演洛奇·巴尔博亚而一举成名,洛奇是一名不知名的拳手,他曾作为宣传噱头向世界拳王阿波罗·奎迪开了一枪。
:这部引人入胜的续集以激动人心的高潮为特色,拳击手洛奇·巴尔博亚重返拳击台,与卫冕冠军阿波罗·奎迪进行复赛。
当一个小男孩失踪后,一个小镇揭开了一个神秘的故事,其中涉及秘密实验、可怕的超自然力量和一个奇怪的小女孩。
2020 年 1 月 18 日,网飞最热门的故事主题是什么?
使用上面的标题描述,我将所有的二元模型串在一起,并删除了停用词,以创建一个分别用于所有电影和电视节目标题的二元模型网络图。从网络图(图 15 和图 16)中,我大致确定了以下主题类别-

图 15 和图 16 的图例
将二元模型归入这些主题是我的判断。没有主题的名人是著名的明星或节目。我总共把二元模型分成了 8 类。请参见左侧的图例。

图 15:来自 4265 个电影标题的描述列的二元模型网络;资料来源:Srinivas Vadrevu 根据 Kaggle 的数据进行的分析

图 16:来自 1969 电视标题的描述栏的二元模型网络;资料来源:Srinivas Vadrevu 根据 Kaggle 的数据进行的分析
在上述主题类别中,有哪些顶级的双元模型?
纪录片/真实故事—
- 电影- 真实故事、纪录片、采访特辑、根据真人秀电视连续剧改编的电影
- 电视剧- 真实故事、真实故事、真实事件、真人秀系列、纪录片系列
- 影视剧通用— 真实故事
城市/地点—
- 电影- 纽约、洛杉矶、拉斯维加斯、旧金山、香港、墨西哥城、南非、北极和古代中国。偏远的岛屿,偏远的村庄,鬼屋,拖车公园,夏令营和寄宿学校。
- 电视节目- 纽约、洛杉矶和香港。没有提到具体的地点,如鬼屋等。
- 电影和电视节目的共同点- 纽约、洛杉矶和香港
职业—
- 电影- 警官、联邦调查局特工、绝密特工、首相、时装设计师、出租车司机、人力车司机、歌手兼作曲家、youtube 红人、法律学生、大学生、流行歌星、摇滚歌星、性工作者、毒枭、毒贩、讨债人和犯罪头目
- 电视节目- 警察、警官、联邦调查局特工、流行歌星、大学生和毒枭
- 电影和电视剧里常见的- 警察、毒枭、大学生和 FBI 特工
动作 —
- 电影- 权力斗争,路径交叉,力犯,返乡,联手,改变人生,家庭生活,挣钱,任务营救**
- 电视节目- 交叉路径,交叉路径,合力和时间旅行
- 电影和电视剧的共同点- 交集和合力
个人事件—
- 电影- 三角恋,真爱*安夜,改变人生,一丨夜丨情,公路旅行,家庭生活,绝症,车祸,夏令营,包办婚姻。
- 电视剧- 私生活,真爱
- 影视剧常见的 - 真爱
主题/重大事件—
- 电影- 二战、外星人入侵、内战、恐怖阴谋、连环杀手、武术、功夫、摩登时代、恶灵、漫画、电子游戏、访谈、嘻哈、社交媒体、房地产、人工智能。
- 电视节目- 二战、嘻哈、黑暗秘密、童话、贩毒、武术、有组织犯罪、连环杀手、社交媒体、神秘死亡和现代
- 电影和电视剧都常见- 二战、嘻哈、社交媒体、武术、连环杀手
个人属性 -
- 电影- 十几岁的女孩,温文尔雅,无拘无束,非裔美国人,中年人,已婚夫妇,童年好友,疏远的父亲,单身母亲
- 电视节目- 单身妈妈,无拘无束,爱玩。
电影和电视剧中常见的- 单身母亲,自由奔放的
标题属性 —
- 电影- 获奖、快节奏、真人秀、喜剧特辑、动作片、特色访谈、档案镜头、剧情片、科幻片
- 电视剧- 艾美奖、艾美奖提名、获奖、喜剧类、动画类、真人版、黑色喜剧类、剧情类、剧集类
- 普通- 获奖、喜剧、剧情
流行名称—
- 电影- 洛奇·巴尔博亚,巨蟒剧团,凯文·哈特,比尔·伯尔,杰夫·敦哈姆
- 电视节目- 电动游侠
图 12 中的柱状图展示了所有上述按移动/电视节目分类并按频率降序排序的二元模型。主要主题如下:
真实故事、纪录片、二战、武术、纽约、洛杉机、警官、真爱是网飞电影和电视节目的常见主题

图 17 在网飞所有标题的描述中使用“ngrams”提取的二元模型的计数;资料来源:Srinivas Vadrevu 根据 Kaggle 提供的数据进行的分析
在附录中,您可以找到过去四年(2016 年至 2019 年)二元模型的同比频率图。上述主题或多或少地出现了,只是时间顺序略有不同。
所以,如果我要写一个以网飞为结尾的故事,我会用下面的提示和标题描述。我用电影和电视节目中常见的关键主题想到了下面的提示
这位获奖的电影制作人导演了一个真实的故事,讲述了纽约市一名警察是一名自由奔放的大学生的单身母亲的故事。她与一个毒枭不期而遇,并找到了真爱,导致了三人之间的错误喜剧
该提示包含了网飞标题描述中经常出现的所有关键主题。如果网飞上的内容很好地反映了用户的偏好,那么上述主题可能会吸引观众。然而,可以肯定的是,哪些主题推动了票房表现或用户参与度,这值得进一步探索。
结论
关于它的内容,网飞告诉了它的股东什么?
在过去的三十个季度中,网飞一直强调创造原创内容,并强调其热门系列(原创和授权,绝命毒师等)。)和顶级喜剧明星。他们提到了第二季、第三季和回归季等后续季的发布,这通常是观众接受和参与的标志。他们非常强调内容的多样性和迎合观众的不同口味。他们将拉丁美洲和北美的内容带到*台上,并传达给股东。当然,他们总是提到奖项(奥斯卡金像奖、金球奖、艾美奖),作为向订户和股东展示内容质量的信号。
过去三年,网飞在内容方面给了用户什么?
与电影相比,2019 年电视节目受到了更多关注。虽然每个季度添加的标题都在增加,但*台上包含电影的标题的百分比从 2017 年第一季度的 76%下降到 2017 年第三季度的 65%。
**过去三年关注的类型:
- 在过去的三年里,网飞一直专注于国际(更广泛的观众群),戏剧,喜剧,浪漫,纪录片,武术,动作和冒险电影和电视节目。这与他们所说的基本一致。
- 与电视节目相比,电影似乎有更广泛的类型。一些在电影中更常见的类型,如惊悚片、家庭片、恐怖片、奇幻片、科幻片、音乐剧和独立片,在电视中并不常见。
- 有趣的是,犯罪、现实和动漫是电视剧中的热门类型,但在电影中却不是。顶级电影类型列表中也没有基于语言的类型——英国(英语)、西班牙语和韩语。
- 与电影相比,电视节目似乎更适合于吸引不同的口味和观众,因为它侧重于语言类型和国际内容(日本动漫)。
- 恐怖和幻想类型在 2019 年开始出现在顶级类型中。
网飞*三年新增内容主题:
(1)纪录片/真实故事——不少真实故事
(2)城市/地点— 电影和电视的常见地点—纽约、洛杉机和香港**
(3)职业— 电视电影中常见的职业—警察、毒枭、大学生、FBI 特工**
(4)动作- 电视剧和电影里的人物做的共同的事- 交集,合力。
(5)个人事件— 电视和电影中常见的个人生活事件*—真爱***
(6)话题/重大事件— 电视节目和电影常见 二战、嘻哈、社交媒体、武术
(7)个人属性--单亲妈妈,洒脱-**
(8)片名属性——获奖,喜剧**
(9)流行/热门名字
- 电影- 洛奇·巴尔博亚,巨蟒剧团,凯文·哈特,比尔·伯尔,杰夫·敦哈姆
- 电视节目- 权力流浪者
根据图 12,电视节目和电影的常见主题是: 真实故事、纪录片、二战、武术、纽约市、洛杉机、警官、真爱是网飞电影和电视节目的常见主题/二元模型。
那么,这是否意味着“灯光,摄像机和行动”的任何提示与上述二元模型?在读者中的任何制片人准备资助这个项目之前,他们可能会问上面的提示是否会在票房上取得成功,或者是否有望获得巨大的订户参与?我会在另一篇文章中通过将票房收入与主题和类型联系起来来尝试回答这个问题。在这个时候,我们所知道的是网飞在体裁和故事主题方面的内容选择。
快乐阅读!如果你想进一步了解《致股东的信》或《头条新闻》主题中的年度重要内容,我在下面添加了一些图表。
附录:

图 18:2012 年第三季度至 2015 年第四季度致股东信内容部分使用“ngrams”提取的二元模型计数;Srinivas Vadrevu 的分析;数据:Kaggle 上的网飞电影和电视节目数据集。https://www.kaggle.com/shivamb/netflix-shows

图 19:2016 年第一季度至 2019 年第四季度致股东信内容部分使用“ngrams”提取的二元模型计数;资料来源:Srinivas Vadrevu 的分析;数据基于https://www.kaggle.com/shivamb/netflix-shows

图 20:在网飞电影标题的描述中使用“ngrams”提取的二元模型的计数;资料来源:Srinivas Vadrevu 根据 https://www.kaggle.com/shivamb/netflix-shows的数据分析

图 21:在网飞的电视节目标题描述中使用“ngrams”提取的二元模型的计数;资料来源:Srinivas Vadrevu 根据 https://www.kaggle.com/shivamb/netflix-shows的数据分析
免责声明 : 本文中表达的所有观点均为 Srinivas Vadrevu(以下简称“作者”)的观点,并不代表作者曾经、现在或将来隶属的任何实体的观点。以上所有观点都不是统计推断,而是作者基于模式的观点。本文作者对本文内容中的任何错误或遗漏不承担任何责任或义务。你不应该依靠这篇文章来作出任何商业、法律、投资或任何其他决定。虽然作者试图保持文章中的信息准确,但作者不对本文中包含的图形、图表和数据的完整性、准确性、可靠性、适用性或可用性做出任何形式的明示或暗示的陈述或保证。
面向产品领导者的决策分析 A/B 测试
将直觉编入数学中,进行强有力的决策对话

图片来源:延斯·勒列
TL;DR 现有的 A/B 测试方法采用频率主义方法进行统计假设测试。这些将产品负责人的直觉排除在流程之外,甚至将其视为非法。贝叶斯基础上的决策分析方法翻转过来,给产品领导一个直观的定量语言。由此产生的 A/B 测试方法比以前有更多的批判性思维和假设透明度的空间。我为此开发的一个开源工具( Excel , HTML )帮助产品领导者建立数学直觉。
A/B 测试已经成为产品团队对小的变更进行迭代测试的一个规程,测试对象是一个小的但是有代表性的用户群。有很好的课程教你 A/B 测试的细微差别。然而,这些课程中的大部分是面向数据科学方向的人的。作为产品负责人,您正在寻找推动决策对话的方法。你已经对你的用户和你管理的产品有了大量的直觉,但是支持你的数据科学团队是“数据驱动的”,不会为你的直觉留出空间。反过来,你会发现自己变得不耐烦。这不是一个学术博士练习。您有时想知道您的数据科学团队是否理解您需要快速做出决策。当你获得数据并开始下结论时,你的数据科学团队会不断提醒你,你做得有些过头了。如果这些挫折听起来很熟悉,并且你一直在为缺乏统计知识而自责,那么我可能有一些好消息要告诉你。
如果让你失望的不是统计知识,而是统计本身的当前味道,那会怎样?如果有一种更好的味道,实际上更容易理解,旨在支持决策,并为您的直觉提供明确的空间,会怎么样?如果这种更好的风格已经被您的数据科学团队理解和欣赏,或者需要一点点高度可实现的提升,会怎么样?事实证明,传统的 A/B 测试是在“频率统计”的帮助下完成的统计学的这一分支在与决策的兼容性方面非常有限,并且与将你的直觉带入数学的概念完全不相容。通过在正式实验中取缔产品领导者的直觉,这个统计学分支实际上是问题的一部分。
如果让你失望的不是统计知识,而是统计本身的当前味道,那会怎样?
有更好的方法,贝叶斯 A/B 测试的变革之风已经吹向那个方向(见这里、这里、这里和这里)。在本文中,我将更进一步,讨论在贝叶斯基础上进行 A/B 测试的决策分析方法。原因很简单。产品领导者必须最终做出决策,而不是获得数据科学的博士学位。我将利用我的产品定位来设计对话,让您的直觉直接参与进来。如果你像我一样是一名工程师,只有当你能修补一些东西时,直觉才会产生。所以,我会让你接触一个我为此设计的教学工具:将你的产品直觉带入 A/B 测试的数学中,并推动高质量的决策对话。
在我们开始之前,让我们花一点时间在 frequentist A/B 测试的核心问题上。
频率主义者 A/B 测试的问题 没有决策的区分,频率主义者的统计就被迫创造出各种不必要的区分(比如统计力)。借助决策分析透镜,我们可以使用直接工具来测试我们决策的稳健性。这一点都不新鲜。事实上,贝叶斯决策分析透镜实验在 1970 年就已经解决了。今年是那篇论文发表 50 周年(2020!),这也是我写这篇文章和附带工具的动机之一。
对于那些从来没有听说过贝叶斯统计学派的产品领导,你可能想知道这有什么大惊小怪的。在本文中我不会深入探讨这个问题(因为我在这篇文章中已经这样做了),但是让我们快速浏览一下。虽然关于这一点可以说很多,但我将把重点放在最有力的论点上。统计学实验的目的是从一个我们可以接触到的很小的、有希望有代表性的子集里了解一些关于人口的情况。
换句话说,假设我们的数据是真实的,我们想知道我们的人口模型是否真实。frequentist A/B 测试的数学回答了完全相反的问题:假设人口模型是真实的,那么数据也是真实的吗?我们必须从假设总体呈正态分布开始,并在假设正态分布成立的情况下,尝试对偶然看到效果的可能性做出陈述(有一天,有人会向我解释偶然看到某个东西的可能性意味着什么)。这是一个正在解决的错误问题,我甚至不会谈论它是如何被草率解决的。我将引用美国统计协会 2016 年的历史性声明中的第 5 条,该声明敦促统计学家走向后 p 值世界:
一个 p 值,或统计显著性,并不能衡量一个效果的大小或一个结果的重要性。
然后,还有那些聪明的统计学家的所有复出之母,他们已经学会了频率主义和贝叶斯方法,“哦,如果有足够的数据,你采取哪种方法真的无关紧要。”这是一个危险的论点,因为尽管从技术上来说是正确的,但它让我们绕过了深入思考我们正在学习什么以及我们如何学习的问题。我们将在本文稍后正式进行这种批判。现在,我将注意到批判性思维是产品领导者的重要职责,我们必须努力找到将数据科学和产品管理的最佳天赋结合在一起的方法。
凭直觉学习我将为一篇关于贝叶斯统计的文章做些奇怪的事情。我不会向你扔任何数学方程式。相反,我将使用我认为容易理解的简单区别,并让您使用这个为此目的而构建的开源教学工具( Excel , HTML )来发展自己的直觉。顺便说一下,HTML 工具使用 FISH 架构,这意味着它是一个单独的 HTML 文件,你可以安全地下载到你的计算机中,它不会向任何地方传输任何数据。使用这个工具,你可以理解我的观点,这很容易理解。
设置
对于我们的 A/B 测试,让我们从一些设置开始。我们想知道在主页上增加行动号召按钮的大小是否会增加点击量。让我们假设我们的实验转移单元是“用户”,这意味着一个用户将只在实验组或控制组中,而不是两者都在。我们将我们的实验建模为独立的硬币投掷,其中每次硬币投掷代表特定用户的页面视图。页面视图是一个页面,有一个按钮,我们希望用户点击。如果用户点击按钮,这与我们的模型所说的掷硬币“正面落地”相对应
该模型假设抛硬币是相互“独立”的。在您的实验中,您需要确保您没有对同一用户的同一页面的多次浏览量进行计数。关于设计好的 A/B 测试,一般都有很好的建议,你会想去留意的,我就不多说了。我们感兴趣的关键指标是头部的长期比例,我们可以将其解释为按钮点击的长期比例。
请注意,这是经过仔细定义的,因此不是是一个概率。这很重要,因为很快,我们将会表达我们对这种区别的不确定性。你只能对没有内在不确定性的事物表达不确定性。为了理解这一点,考虑一下下雨的的概率。如果对“雨”的含义有任何不确定性,那么在一个不清楚的区别上再增加一个可能性是没有意义的。为了使下雨的可能性有意义,你和我必须就下雨的精确定义达成一致,这个定义不能有任何不确定性。
你只能对定义中没有内在不确定性的事物表达不确定性。
决策分析有一个很好的概念,可以帮助我们围绕这个问题进行思考。这被称为透明度测试。如果一个千里眼能够告诉我们这种区别在未来将如何解决,那么这种区别就通过了清晰度测试。透视者被定义为只能陈述关于未来的事实,但不能做出任何判断的人(虚构的)。例如,一个透视者不能告诉你你的模型是否正确,因为模型存在于你的头脑中,而不是存在于事实的世界中。只有当一个区别通过了清晰测试,我们才能给它一个概率。我们不能把概率放在正面概率上。但是我们可以对人头的长期比例设定一个概率,因为千里眼可以精确地告诉我们在长期中有多少人头出现(当然,我们必须同意多久是长期),因此,给我们长期比例。我将留给读者一个练习,让他们弄清楚像“假设正确的概率”这样的陈述是否通过了清晰性测试。我们在这里不需要这样的声明。
千里眼无法告诉你你的模型是否正确,因为模型存在于你的头脑中,而不是存在于事实的世界中。

工具中 A/B 测试的设置
您将从上面的截图中注意到,这里也有决策分析元素。具体来说,我们正在评估每次点击的价值。产品负责人往往会有这种感觉,所以我在这里就不深究了。对于我们的例子,我们将假设它是 1 美元。我们还在评估最终的发布受众规模(这里设定为 100 万),前提是我们决定推出该功能,以及这样一次发布的成本(设定为 2 万美元)。我们稍后将使用这些信息来指导我们的决策分析。
为实验和控制建立先验
好吧,那么这个词“优先”是什么意思?贝叶斯区分的好处在于,它们与该术语的英文含义一致。先验是指你在实验前的知识状态。我们人类基于我们所知道的来学习。如果我们什么都不知道,我们从数据中学到很多。如果我们对某件事了解得非常透彻,在我们改变主意之前,我们需要看到大量不确定的证据。这些明智的逻辑学习方法与统计假设检验不相容。相反,它们是贝叶斯方法的起点。我们必须利用我们所知道的兴趣的区别。
参与我们所知道的不仅仅是一个反思的练习。我们还在这里做一个建模决策,并以一种特定的形式表达我们的不确定性,这种形式代表了我们对的感受。还记得关于能够在数学中捕捉你的直觉的承诺吗?这就是我们在这里讨论的问题。如果现在你的闹钟响了,这是有原因的。我们都被灌输了为了科学而客观的饮食,但是再深入一点,最伟大的认识论者会告诉你一个坏消息,“科学是主观的。”问题不在于主观性,而在于我们对待主观性的方式缺乏严谨性和透明度。我更希望我们使用停止假装客观的语言,并乐于暴露我们的假设。这样,我们可以建立一种学习文化,而不是被我们不知道的假设所阻碍。

前科有三种选择。在工具中,单击要使用的工具。
当您在工具中展开“构建先验”部分时,您将看到三个选项。第一个是不知情的先验,它对应着这样一种信念:“我对兴趣的区别一无所知。”乍一看,有些人会声称这是正确的科学立场。乍一看,当你知道 好的按钮点击率很少达到 10%时,这是没有意义的。如果超过 20%,产品领导就不会想,“太棒了!”相反,他们在想,“实验出了问题,让我们找出原因。”现在,我们先不讨论这个论点,如果你有大量的数据,先验知识就不重要了。
第二个选项是对称先验,对应于:“我有一种感觉,用户点击率将达到*均 50%,并且它同样可能以对称的方式高于或低于该值。”这是一个非常具体和强烈的信念,看起来非常奇怪,鉴于我们对上述统一先验的批判。
最后,剩下不对称先验的第三种选择。你可能已经注意到了,我正在鼓励你用这个选项来表达自己。如果科学是关于以最严格的方式找到你的真理,如果这个分布允许你严格地表达那个真理,那么我将声称这是最好的科学选择。只要宣布出来,其他人就可以挑战你,如果他们愿意的话,用他们自己的前科。从数学上讲,所有这些选择都映射到 Beta 分布的特定形状参数上。Beta 版是一个灵活的发行版,它还有一个重要的特性。当我们通过增加形状参数将它与伯努利试验(掷硬币试验)结合起来时,很容易更新。在本文的其余部分,我们将不再深入研究贝塔分布的数学。
当你向下滚动你的选择,你会看到一些形状选项,像这样:

请注意,当我们增加缩放倍率时,方差如何下降。需要注意的关键是,概率是概率分布函数(PDF)曲线下面积的度量。总面积总是正好等于 1。
上面的例子可以让你表达你的信念,*均来说,你认为你会达到令人印象深刻的 10%的点击率。分布的粗细代表了你对此的确信程度。虽然设置这一点的技术方法是使用方差,但我引入了一个称为“先验标度能力”的区别,以使这一点更加直观。先验标度功效是一个乘以分布形状参数的数字,影响方差,但T5 而非 *均值。您可以看到,当您向右拖动缩放比例时,方差是如何下降的,而*均值保持不变。
让我们直观地想到这一点。你的先验是一种将你的直觉等同于数据的方式。如果你像我们这里一样以 1/10 的概率开始,你是说你的直觉相当于看到 1/10 的投掷。然后,如果你把标度力量设置为 10,你现在说你的直觉相当于 100 次投掷中的 10 个头。虽然这将*均值保持在 0.1,但方差减少了,因为投掷次数增加了,你应该理所当然地减少一点不确定性。随着你越来越确定,通过增加先前的能力,你正在减少你的不确定区域。实际上,看看显示分布百分位数的表格是如何变化的(这是我们的贝叶斯 80%置信区间)。当缩放比例为 1 时,它们开始于(0.012-0.074-0.226),当缩放比例为 100 时,它们结束于(0.088-0.1-0.112)。基本上,随着方差的下降,范围越来越窄。
假设我们可以接受先验均值为 0.1,标度为 2,这相当于 20 次投掷中有 2 次。这让我们在表达知识的同时,也为不确定性留下了足够的空间。我们现在可以继续为控件构建我们的先验。以类似的方式,让我们说,我们相信它产生按钮点击的可能性是一半,我们可以选择 0.05 作为先前的*均值,标度幂为 2。这个先验相当于 20 次投掷中有 1 次。我们现在准备进入下一阶段,从我们的实验中学习。
从实验中学习
建立先验知识后,您将希望充分利用现有的所有知识来设计好的实验,这些知识可以来自您所学的课程,也可以来自您的数据科学团队的指导。你在实验和控制中收集了你的数据。你现在可以开始学习了。打开工具中的“从实验中学习”部分,输入实验和控制中的投掷次数(页面浏览量)和点击次数。在我们假设的例子中,假设实验组的 10,000 次页面浏览中有 400 次点击,而对照组的 10,000 次页面浏览中有 300 次点击。最初,这使得后验分布看起来相当窄。

向实验组和对照组学习
我将在这里介绍另一个区别,“后验标度能力”,它类似于“前验标度能力”。我们将数据(投掷次数和头数)除以这个幂。这个操作可以让我们表达自己希望被数据影响到什么程度。如果我们将此值设为 1,那么我们将按面值获取全部数据。如果我们增加它,我们开始降低我们看到的数据的能力。直观地说,后验标度 100 意味着 100 次点击(和 100 次浏览量)会被计为 1。您正在设置从数据中学习的尺度。有了这个区别,你就能提高真正确定的标准。这就是我们如何应对这样的批评,即如果我们有“足够”的数据,先验并不重要。有了足够高的后验标度能力,这就很重要了。
虽然有一个很强的诱惑去问,“我们应该在哪里为后验规模力量设置障碍”,但是一个更好的问题是:我们的决策将如何基于后验规模力量而改变?注意上图中桌子下面的线条。他们报告有助于我们做出决策的价值指标。这个模型有一个简单的价值模型——我们将长期点击分数的*均值(也是下一个人点击的概率)乘以将获得已推出功能的用户数量和每次点击的价值。即使如此简单,我们也可以看到,最初,当数据被充分利用时,我们不应该启动,因为成本超过了收益。然而,如果我们缩小一点数据,保留更多的不确定性(通过增加后验标度能力),这种不确定性允许更高的点击率,因此,价值上升。在后验标度为 251 的情况下,我们的决策有一个交叉,如下面的灵敏度图所示(在工具的灵敏度部分)。

对后验标度能力的敏感性
这种敏感性分析告诉我们的是,我们推出的决定对我们对数据的怀疑是非常坚定的,但如果我们从表面上看数据,就会改变。为什么会这样呢?这与我们先前的信念有关。记住,我们一开始就相信实验会比控制组好一倍。为了在行动中看到这种信念,让我们一起将实验归零(在“从实验中学习”一节中为所有四个输入输入 0)。这将立即揭示,如果你根本不做实验,你应该只是发射。
也可以做相反的灵敏度分析。让我们对这些数据持怀疑态度,选择一个 400 的后验幂标度。这意味着你将每 400 次点击(和浏览量)视为 1 次点击(和浏览量)。让我们找出需要在控件中看到多少个头才能改变我们的想法。下面的分析清楚地表明,如果我们看到 414 次点击或更多,我们应该改变主意,重新考虑推出。

当后验标度功效= 400 时,对控制中头部的灵敏度
请注意,这个决策分析层比“统计能力”的概念有用得多,因为它让我们非常直接地进入决策对话。
最后,让我们看看改变我们的先验对分析有什么影响。让我们回过头来为实验组和对照组选择不知情的先验。我们会发现我们根本不应该发射任何规模的能量。下面的敏感性分析显示了这一点。

先验一致时的灵敏度
对称先验也讲述了一个类似的故事。实验组中没有足够的点击量来证明一次发布是合理的。

先验对称时的灵敏度
因此,我们可以看到,决策分析 A/B 测试允许我们整合先前的直觉,并做出与协同工作的决策,而不是违背我们的直觉。这种方法的美妙之处在于,夸张是绝对没有价值的。如果我们对自己的过去过于乐观,或者过于悲观,我们的决定就会因此而有所偏差。这种数学方法让我们能够说出直觉的全部真相,并据此进行学习。作为一名产品负责人,我希望您能理解这为您与数据科学团队的合作开辟了新的前景。数学允许他们从你的直觉中学习,让你的思维变得透明。你的主观性没有被取缔;相反,这个过程允许你和你的感受进行严格的交流,这样你和其他人可以互相学习,做出更好的决定。
我怀疑现有的 A/B 测试软件系统会发现很难从哲学上支持这种转变,而且这需要一些时间。这不仅仅是实现新的方程式。它是关于促进透明和强有力的对话。希望本文中提到的开源工具可以让您至少尝试一下本文中讨论的推理和决策,直到您的系统赶上这种思维。
感谢斯坦福大学的 Ronald A. Howard 教授在 1970 年如此果断地解决了这个问题,感谢加州大学洛杉矶分校的 Thomas Ferguson 教授开源了他的* 不完整的 beta 函数和 log gamma 实现 (这是我的工具用来产生置信区间的工具),他将塞西尔·黑斯廷斯的 归功于他 1955 年的著作 where 如果这篇文章中使用的决策分析(清晰度试验、千里眼相赠)引起你的兴趣,这里是的出处。这里是工具* 的 Github 页面。本文附带的 Excel 模型 在CC0下获得许可,可用于任何目的,无需署名。**
数据标注策略的决策框架
现实世界中的数据科学
打破关于数据标注工作流程和预算的常见误解,提供一个现实的决策框架,将您的数据标注策略从有缺陷变为完美。

[版权所有 Playment 公司]
去年,在 2019 年 CVPR 上,我与特斯拉人工智能高级总监 Andrej Karpathy 进行了一次短暂的会面。在我们的谈话中,我问了他一个相当天真的问题,“Andrej,你如何估计在特定场景下训练和验证自动驾驶汽车所需的标记数据量?”他停顿了一会儿,然后笑着说,“嗯,378 小时的数据。明天再问我吧,我的数字可能会更大方。”接下来的两分钟,我们一直在笑。
今天,众所周知,我们需要大量高质量的标记数据来训练和验证 ML 模型。但在见过数百名人工智能团队领导和多个处于人工智能发展旅程不同阶段的人工智能初创公司 CXO 后,我观察到市场对标记数据的获取有不*衡的理解。
大多数处于人工智能成熟度曲线高端的 ML 团队认为标签数据获取是他们的主要优先事项之一,并理解过程中涉及的不同层次的复杂性。然而,大多数玩家在远端为他们短暂的项目找到了一些变通方法。此外,我还观察到,几乎所有的 ML 公司都经历了一个自我实现的周期,即忽略数据管道的这一方面,最终构建大规模的软件和运营力量来处理他们标记的数据需求。
因此,可以肯定地说,当前人工智能生态系统中的一个大问题是,“如何经济高效地访问大量多样化和高质量的标记数据?”
数据标注过程固有的过度简化

数据标记操作:感知与现实
首先,将流程过度简化为一个简单的“租用-注释-支付”模型只会为实现自动化目标设置更多的障碍。任何功能性 ML 模型最重要的先决条件是高质量的标记数据。成本妥协只会让你陷入更深的困境。数据标签操作:感知与现实
标签预算通常被认为是每个人工注释者 7 美元的固定成本和所需的注释工时数的乘积。这种方法是完全不正确的,因为他们没有考虑 ML 工程师在设置注释过程中产生的各种隐藏成本。
数据标注过程中忽略的因素
让我们通过一步一步的过程来理解实际预算是如何超过简单的数学公式的。
步骤 1:ML 工程师首先创建指南,清晰地定义注释的类别和每个类别的期望设定点,以训练人类注释者。这一步重复几次,因为现实中,没有人第一次就做对了;指南需要多次迭代。
第二步:接下来,他/她需要发现或创建支持其数据格式的注释工具,生成高度精确的像素级注释,并提供可伸缩性以适应其大型数据集。这个评估/开发过程可能需要几天或几周时间。
步骤 3: 然后,工程师从第三方那里找到合适数量的有技能的人类注释者,或者雇佣兼职注释者。寻找合适的劳动力需要一个设计良好的试点计划和对多种劳动力的评估,然后是合适劳动力的谈判、签约(与财务和法律团队合作)。
步骤 4: 接下来,他/她建立工具基础设施,培训注释者使用工具,并提供注释需求作为任务。他们还创建和管理注释任务的截止日期。此外,他们还定期跟踪注释器的进度。
第五步:工程师然后设置工作流、逻辑或脚本来测试输出的准确性,向违约者提供反馈,并重新分配错误的标签以便返工。对每批注释重复此步骤。
步骤 6: 间歇地,他们重复上一步,直到标记的数据达到他们期望的精度水*。整个过程耗时耗力。
通常,数据标签预算并不包括每一个步骤的额外成本因素。真正的预算包括 ML 工程师的时间和精力成本,100 美元/小时或以上,加上注释者的成本——两者都比 7 美元/小时高 10 倍。
随着要注释的数据的特殊性、多样性和数量的增加,工具基础设施、劳动力和项目管理的复杂性也在增加。有效管理这些复杂的流程对于实现高质量的产出变得极其重要。
说实话,ML 工程师最好做他们最擅长的事情,而不是纠结于这些操作流程。
数据标注策略的现实决策框架

数据标记策略的决策框架[Copyright Playment Inc.]
对于这个框架的广泛应用,我使用了人工智能开发周期的三个阶段,以及三个主要的数据标记功能作为决策的基础。除了解释开发周期每个阶段中功能的复杂程度,我还额外提供了大概的预算,以简化决策者的类别评估。
我已经确定了设置过程的复杂性和数据标签所涉及的预算的真实性。现在让我们深入研究这些函数。在游戏中,我们将之前提到的六步流程分为三个重要功能(见上图):
- 注释工具
- 劳动力
- 项目管理
这些功能的复杂程度取决于为注释收集的数据量,以及所需的人工注释者的数量。例如,根据数据量,注释工具可以是 100%手动的,也可以是非常复杂的,带有各种自动验证检查或人工智能辅助,以最大限度地减少错误并确保更快的数据吞吐量。
工作人员可以 100%来自内部或外包,这取决于注释的数据量。当注释器需求超过 1000 个注释器时,您也可以选择多供应商模型。
10 个和 1000 个人类注释者的有效项目管理是非常不同的问题。前者几乎不需要任何东西,但后者需要复杂的软件和分析来训练标注者、分配标注任务、跟踪质量、速度等性能。这与监控装配线非常相似。
基于这个现实的框架,Playment 建立了一套复杂的技术和劳动力解决方案,以帮助小型、中型和大型公司无缝地为他们的数据管道提供燃料,以更快地激活人工智能应用程序。
结束语
这个决策框架符合大多数 ML 团队的要求。然而,数据安全性和自动化是在很大程度上影响架构决策的其他重要参数。它给这个原本简单的框架增加了一层额外的复杂性。欢迎在推特@ Playmentq上给 play ment 发 DM,或者发邮件给我们 hello@playment.io 讨论同样的问题。
我希望这个框架将有助于行业避免由于普遍的误解而导致的不正确的数据标签架构决策带来的陷阱;帮助 ML 社区以前所未有的速度构建高度精确的 AI 模型。
加速人工智能时代!
最初发表于 Playment 博客(【https://bit.ly/2Q6iqjm)和 LinkedIn(【https://bit.ly/2TM76vj)。
挖掘决策智能
数据科学
数据科学或如何决定如何决定

图片由 Unbox Science Pixabay 提供
谷歌的 Cassie Kozyrkov 一直在推广决策智能的理念。决策智能(Decision intelligence)这个术语是由 Kozyrkov 创造的,旨在将已知的决策方法、洞察力和最佳实践重新组合到一个公共的保护伞下。这些已知方法和见解的例子有:
- 分析学
- 统计学,频率主义者和贝叶斯
- 机器学习
- 决策科学
- 行为经济学
- 决策的心理学和神经学
上面的列表中有意省略了数据科学。数据科学是一个流行的术语,但没有很好的定义:所有的科学不都是数据科学吗?也许这篇文章是一个实验,看看术语决策智能是否更好地界定了一个连贯的兴趣领域。首先,决策智能的一个核心原则是,目前被称为数据科学的领域有很多都与决策有关;或大或小。一个人如何决定如何决定?这就是这篇文章的范围。
这种新划分的部分结果是,我们所知道的数据科学项目可以通过更精确地了解不同任务和所需角色的结构来更好地执行。
有没有决策架构或基础设施这样的东西,它看起来是什么样的?
这篇文章的目的是希望总结一下谷歌的 Kozyrkov 在不同博客和媒体上发布的大部分决策情报内容。总之,这是初步的,因为尽管它基于大量的博客文章,但它并不打算包含所有的内容。也不清楚是否所有信息都在网上公布。在这篇文章中,我将有目的地推动术语“决策智能”,作为一个实验,但也可以随意阅读“数据科学”。
这篇文章的概述
为了您的方便,这里列出了这篇文章中包含的部分和主题:
- 决策:从零到少到多
- 分析学
- 基于频率统计的假设检验
- 贝叶斯统计的一个例子
- 比较:分析、频率主义者和贝叶斯统计
- 机器学习
- 论可解释性、检验和偏见
- 做应用是可以的
- 决策智能过程
- 决策智能团队和决策者
- 一些附加的想法
- 最后的想法
决策:从零到少到多
游戏的名字是做出更明智的决定。在本节中,将介绍决策制定的初始分类,这将在下面的部分中详细阐述。
决策智能的一个中心思想是人们可以面对以下场景:
- 人们希望做出大规模的决策,大量的决策
- 人们希望做出一些具体的决定
- 一个人还没有准备好做决定,因为他缺乏洞察力
让我们从大规模决策开始。
机器学习符合这个法案。想估价几百万的房子?想把几十亿条推推荐给几百万人?想要给数十亿张照片添加标题吗?当前的信息革命在很大程度上是关于数据和决策的扩展,超出了以前的想象。在这场规模革命之前,决策的制定,更多的是在少数人的规模上,是统计学的领域,无论是频率主义者还是贝叶斯主义者。
统计有助于管理而不是消除基于人口样本数据而非全部人口信息做出决策所带来的不确定性。使用统计数据做出数百万个决策不符合该框架,需要使用例如 Bonferroni 校正来校正重复测试。但这有其局限性。更具体地说,对于频率主义者的方法,人们应该提出一个由零假设表示的默认行为过程。有规则要遵守,稍后会有更多。
最后,但同样重要的是,有时一个人只是还没有准备好如何思考手头的决定:需要的是灵感。在这种情况下,分析可以也应该有所帮助。
为了使这种分类更具实质性,我们将在接下来的章节中详细阐述这三个感兴趣的领域。
分析学
分析就是分析手头的数据,或多或少地忘记数据集之外的世界。一个优秀的分析师可以快速剖析数据集,并从数据中选择感兴趣的模式。分析是关于产生想法或产生更好的问题。统计学家可以在当前数据集之外使用另一个数据集提取其中一些问题进行归纳。在某些特定情况下,分析也足以推动决策,下一个例子将对此进行说明。
让我们假设一个人可以以相同的价格购买一批蓝色 t 恤或一批红色 t 恤在当地的集市上出售,但不能两批都买。没有既定的偏好,或默认的行动,一个随机询问周围的颜色偏好,以确定哪一批是更好的选择。如果在颜色上有任何多数票,那么在没有应用统计数据的情况下,采用多数票是可以的。为什么?因为你没有偏好,没有数学或统计学会让多数人的结果偏向少数人的结果。票数的差异可能毫无意义,但多数票仍然是最安全的赌注。
请注意,本例中没有任何政治信息,只是需要注意样品的采集地点与 t 恤的销售地点之间的关系。数学不会改变少数人投票的决定,但样本偏差的概念可以:但这不是一个数学问题。
使用假设检验来做决定。
基于频率统计的假设检验
在前面的示例中,没有默认操作。在很多情况下,有一个默认动作;这种默认操作通常是保持现状。无论是信任明智、相信明智还是投资明智,这种默认行为都有一定分量。(还有更多技术上的原因,后面会详细介绍。例如,一个人可能想知道一种特定的治疗是否值得。简而言之,在这种情况下,假设检验有助于在对人口样本进行处理后,形成关于人口参数的信念,即某种条件的存在与否。让我们更详细地阐述一下。
如果评估治疗,因果关系是很重要的。通常人们会使用随机试验,将人群样本分为治疗组和对照组。如果做得正确,这个实验包括一个要被证伪的零假设和另一个假设。在将治疗应用于对照组之后,基于两组的结果以及在它们之间发现的可能差异,可以计算出臭名昭著的 p 值或概率值。p 值是如果零假设为真,即如果没有影响,计算出的差异发生的概率。如果这个概率非常小,那么零假设被拒绝,取而代之的是另一个假设。
这个例子的目的不是深入假设检验的哲学细节,而是为了说明假设检验过程是为一个非常具体的目的而设计的。重复测试程序可能会产生类似的结果;强调客观事实和可重复性。该框架旨在用于必须做出少量明确决策的情况。增加决策的数量会遇到一些问题,这些问题只能在一定程度上得到解决。
如果决策不太明确,或者更复杂,贝叶斯统计可以提供一个很好的选择。虽然我在决策智能的上下文中没有看到很多关于贝叶斯统计的内容,但是由 Douglas Hubbard 定义的应用信息经济学(AIE)的框架可以提供一个很好的例子,作为与频繁主义统计的对比。
贝叶斯统计的一个例子
复杂的决策可能需要大量信息。这些信息有些可能就在手边,但有些可能没有。更一般地说,仅使用频率假设检验来制定复杂的决策可能被证明是不可克服的。不可能总是以严格的方式测试所有的东西。有时,预先的信念或专业知识是决策过程的一部分。贝叶斯统计允许你这样做。虽然先验信念的概念听起来可能模糊,但贝叶斯统计可能非常强大,因为人们可以使用观察来更新信念。希望下面的例子能让我们感受一下它的工作方式。请注意,这个贝叶斯统计的例子是有目的地偏向于一个应用的业务设置,并且非常*凡。
假设有人对建立一个系统感兴趣,任何系统。建立这个系统需要完成 1500 个单独的任务。先前的看法是,完成一项随机任务的小时数的 90%置信区间在 15 分钟到 7 小时之间。此外,先前的看法是,一小时工作的市场价格在 19.50 美元和 47.50 美元之间。使用这些信念,并假设两个信念的正态分布,可以通过运行蒙特卡罗模拟来计算系统人工成本超过 10.000 美元的概率。怎么会?人们可以从任务分布中抽取 1500 个样本,然后将每个样本乘以从小时率分布中抽取的样本,从而得到一个“实现”。通过多次重复这些步骤,可以创建人工成本的模拟概率分布;这种分布有助于推断可能的结果。
这种模拟之所以成为可能,是因为接受先验信念作为起点,这是贝叶斯统计的核心原则。尽管这个例子非常简单,但是这个框架允许复杂性扩展。为了表明我们没有践踏现实、观察和统计,我将进一步阐述 AIE 框架。在 AIE 框架内,提出了以下有科学证据支持的概念:
- 在一些训练之后,大多数人可以被训练来提供精确的/校准的概率或置信区间估计。
- 估计,虽然是一个很好的起点,但很容易受情绪和环境的影响。
- 估计中的任何不确定性都可以通过用样本观测值更新先验信念来减少。先验分布被转换成后验分布,其中证据被考虑在内。
- 减少分布不确定性所需的样本量小于预期;通常 5 到 100 个样本就能创造奇迹。
- 在不确定性最高的地方,观察的影响最大。
- 给定一些模型结果,就有可能评估添加额外信息的价值——表明哪些成本是合理的。
- 复杂决策的模块化使决策更可靠、更准确。
- 目标不一定是尽善尽美,而是击败当前的决策方法(通常只是专家建议)。
AIE 框架允许以显著的方式模块化和管理复杂的决策及其相关信息;这一切都有统计数据支持,尽管这个过程开始时可能只是一个思想实验。
是时候回顾和比较一下了。
比较:分析、频率主义者和贝叶斯统计
在前面的三个部分中,说明了三种不同决策框架的优点和缺点。在本节中,将讨论一些比较和对立,以增加更多的深度。
分析和频率统计通常共享共同的术语和计算,如均值、方差和 p 值。尽管如此,框架的目标是不同的,这可能会导致混乱。分析师可能会观察到一些统计数据中的差异,并获得 p 值。这个 p 值是什么意思?根据统计学家的说法,什么都没有。p 值属于假设检验的范畴,假设检验需要遵循一个明确定义的过程。统计学家可能就在这里。任何科学家获得一个数据集,把这个数据集翻个底朝天,获得一些统计数据的 p 值,然后声称已经验证了一个假设,都有可能丢掉工作。
人们不使用数据集作为灵感,然后使用相同的数据集进行假设检验。虽然拆分数据通常是可取的,但也只能起到这么大的作用。证明因果关系的受控实验设置如何?还是因果不相关?还是混淆了相关性?假设检验是否设置了显著性水*,该水*是如何设置的?是否针对测试的功效进行了调整?在用一组数据来检验一个假设之前,有许多问题需要回答。分析更多的是在过程的“商业”方面,可以提供有价值的见解,可以作为灵感;但是不要把它弄得乱七八糟。
另一方面,频繁假设检验的所有严格性都有其局限性。如果面对涉及大量信息的复杂决策,频率主义者的统计可能会有所欠缺。纯粹的数学严谨性并不是对所有情况都适用的。贝叶斯统计允许通过使用和验证关于当前问题的先验信念来调整决策。它允许分析哪些地方需要更多的信息或最有影响力,以及何时获取的成本与收益相称。任何数据计数都是有用的,在这种情况下,重要性不是关键问题。
在这个例子中,频率主义者和贝叶斯统计都专注于以严格的方式做出少量的决策。那么大规模决策怎么样,也就是机器学习?或者通俗点说就是 AI。
机器学习
人工智能这个术语是在上个世纪 50 年代引入的。从那以后,这个术语涵盖了许多方法。目前,它通常指的是机器学习,但肯定有更多的方法可以满足这一要求,并且在过去已经得到了应用。
科兹尔科夫把机器学习贴上标签,就是给事物贴标签。标签可以是各种各样的:猫、狗、数字、操纵杆运动。后一个例子表明,强化学习在机器学习下是错误的。如前所述,机器学习是大规模标注的首选工具。出于这个原因,机器学习可以更加软件密集型。这可能是对机器学习在计算机科学的羽翼下发展壮大这一事实的解释。
机器学习的主要考虑因素是偏差和方差。通过训练、验证和测试数据的概念来控制这些类型的错误。(或使用其变体。)从用户的角度来看,统计分布不太受关注。尽管在模型的优化和训练、验证和测试数据共享一个公共分布的假设中,这些仍然是相关的。
在机器学习中,非常强调模型性能。对于像预测性维护这样的纯技术应用,这并不奇怪,也没有理由担心。当涉及到对人类或其他动物做出决定时,道德问题很快就会出现。
论可解释性、检验和偏见
准确的说,算法永远不会有偏差,但数据可以。因此,使用这些算法和数据的模型的结果也可能有偏差。这是一个真正的问题。机器学习使得衡量决策变得非常容易。这也使得人们很容易犯大规模的错误。如果这些错误系统性地让大量人群处于不利地位,因为这个系统反映了最终创造者有时无意识的价值观,那么道德就岌岌可危,伦理讨论需要加入争论。但是让我们先来看一个关于偏见的小例子。
想象一下,一个系统可以识别技术人才的机器学习职位,为了做到这一点,系统会扫描简历并给简历打分。众所周知,区号可以作为许多隐藏变量的代理。随着学校教育变得越来越隔离,不难想象学校名称也会以同样的方式运作。让一个高级的 NLP 系统基本充当斯坦福、伯克利或者麻省理工的扫描仪有用吗?向一个已经缺乏多样性的行业添加更多相似的简介?在过程中的某一点上,模型的目标将必须被转换或形式化为一个函数,即可以被优化的目标函数。这种形式化和选择的数据一起引入了假设和无意识的偏见。最后一点,简历扫描仪不就是为了显示偏见而设计的吗?你必须知道你在做什么。
在欧洲,根据 GDPR,人们有权知道自动决策是如何计算出来的。至少可以说,在这个意义上,不是所有的模型都是透明的。而且很多根本不透明。如果条件不够完美,即使是简单的线性回归模型也会带来挑战。正是在这种背景下,SHAP 或石灰等方法被创造出来。这些方法旨在深入了解哪些特性对决策影响最大。这很有帮助。问题是这些方法提供了对底层算法的局部*似。这种解释可能是粗略的,或者不是普遍适用的。这引出了一个有趣的问题。
机器学习的全部意义在于,模型的工作太复杂,用手工编程太难。编程包括数据和规则输入和输出。机器学习由数据和答案组成,包括输入和排除。试图使规则透明化或多或少会违背初衷。如果这是可能的,那么人们应该对系统的规则进行编程。这并不意味着情况没有希望。另一种方法是严格测试模型的偏差。尽管测试一个模型可能无法捕捉到每一种形式的偏差,但它至少可以使它与一个可比较的过程一样公*。
如果到目前为止,所有的信息都让您有些眼花缭乱,那么没关系。整合所有不同的关注点并应用正确的方法是非常重要的,这是下一节的主题。
做应用是可以的
不同决策框架的实际应用,及其所有的含义,是相当复杂的。当它涉及机器学习时,还有繁重的工作、正常运行时间、监控、概念漂移,以及你在玩什么。突出所有的细节可能会很容易地填满课程中的一些学期,或者可能需要多个角色才能成功完成。这才是重点。
不一定要成为决策智能相关领域的科研人员。几乎相反,有足够的知识和考虑使应用决策智能成为一个专业。如何收集一些商业智慧?或者确切地了解决策智能在流程中的哪一点最有效?很容易融入更多的管理科学、行为经济学或心理学。
与此同时,科学目前在没有决策智能的情况下也做得很好。整个科学界已经想出了回答问题的方法。每个研究领域都有自己的一套公认的方法,旨在推动各自领域的决策。精算师、后勤学、心理测量学、生物学、流行病学,名单还在继续。这些领域中的许多方法是重叠的,但是每个领域中也有不同的方法。这些方法是为了应对这些领域中的特定挑战而开发的,并且在某种程度上与这些科学领域的背景相关联。决策智能是如何界定的,或者如何划定界限,这一点并不十分清楚。
决策智能过程
‘设计时要考虑到目的’,这个规则也适用于数据产品的设计;不是一切都变了。准确地指出数据产品的结果应该是什么,以及它如何准确地适应当前的过程,可以避免许多痛苦。弄清楚这一点后,我们可以看看可用的数据、算法,最后是要部署的合适模型。但是还有更多。
为产品设定性能标准怎么样?没有任何表演会。也许应用一些假设检验来确保这些标准得到满足?费用怎么样?知道了数据产品在过程中的位置和方式,人们应该能够估计其应用的好处。但是既然盈利是游戏,那么应该应用什么倍数来比较成本和收益呢?
目的是“让数据变得有用”。让我们把它分成三个不同的部分:
- make——决策智能过程旨在创造事物及其编码。虽然编码的最终结果很重要,但代码和/或框架(如 Tensorflow、sklearn 或 pandas)并不重要。
- 数据—如果处理数据,需要考虑分析和统计领域的一些方法方面。
- 有用—缩小一点,使数据有用需要设计适合业务的正确产品。这包括首先为什么这个模型如此伟大,产品背后的假设和价值是什么?
决定,决定,决定。这一切的决策者是谁?这就出现了一个问题,是选择独角兽数据科学家,还是创建数据产品的混合团队。让我们重温一下角色的话题。
决策智能团队和决策者
一个普遍的观点是,管理数据产品比管理大多数常规 IT 项目更难。数据科学工具和端到端*台的市场正在增长。在机器学习的情况下,很容易涉及相同数量的软件。除此之外,还有数据来源、模型验证和监控、模型偏差、数据标签等等。尽管如此,无所不能的数据科学家仍然很受欢迎。会不会是新兴的端到端*台能够将所有的复杂性缩减为独角戏?
端到端*台无疑提供了便利。不太引人注目的是,即使考虑到这些*台,仍然需要多样化的技能组合。在本节中,将列出一个可能角色的折衷列表。很少有人会雇佣所有这些角色,但是知道哪些角色被遗漏了是很好的:
- 领域专家
- 产品经理或产品所有者
- DevOps 和现场可靠性工程师
- 数据科学家
- 数据工程师
- 隐私专家/律师
- 伦理学家,律师
- 统计员
- 机器学习工程师
这是可能的角色的简短列表。这个列表有点重软件,这个团队可能涉及机器学习。这通常是大规模的。规模越大,责任越大。因此,虽然机器学习项目可以在小范围内执行,但扩大规模意味着增加责任。是的,数据科学家可以将模型部署到 SageMaker,但这通常不是目标,对吗?随着规模的变化,项目的性质也逐渐发生变化。这就是为什么其中一个角色被遗漏了,即决策者(决策科学术语)或数据科学领导者的角色。
在这篇文章中,数据智能项目中的问题越来越多。有人可能会说所有这些思考和细微差别都不是敏捷的。但是把敏捷和无知混为一谈只是明显的傲慢。GDPR 不是开玩笑的。拥有一个了解数据智能项目的机会和陷阱的应用专家迟早会变得非常方便。
是时候结束这一切了。
最后的想法
决策智能是关于重组当前的决策环境。虽然强调应用,但如果不理解理论和决策方法的深层机制,就不可能正确执行。这个问题既有实践的一面,也有理论的一面。如果更多的人对这些方法有一个更好的、更全面的和更深刻的理解,这将肯定有助于执行决策类型的项目。
属于决策智能的方法来自不同的研究领域,并且经常重叠。一些重复数据删除和清理肯定是有价值的。认识到决策制定中的共同模式,也许可以更好地将决策形式化,并通过这样做提高所有人的标准。
但是决策智能有明显的元特征。大多数决策方法都是达到目的的手段。方法经常被开发出来,因为特别需要一种新的看待事物的方式。这种需求是由经济学、生物学、物理学或工程学等领域驱动的。离开发明这些方法的背景,并不是所有的方法都有意义。决策方法本身并不是发明出来的:什么将推动决策智能领域的创新?决策智能提供了很好的起点,但是它是如何有界的呢?
话虽如此。我非常喜欢 Kozyrkov 的许多博客帖子以及这些帖子提供的宝贵见解。希望这篇文章能激发你的决策能力。
用 Python 实现多类问题的决策树算法
理解基尼指数、熵、信息增益、特征重要性和 CCP 阈值的数学

法托斯 Bytyqi 在 Unsplash 上的照片
介绍
决策树分类器是监督学习模型,在我们关心可解释性时非常有用。想象一下,通过在每一层基于多个问题做出决策来分解数据。决策树面临的最大挑战是理解后端算法,利用该算法,一棵树可以扩展为分支和子分支。在本文中,我们将更广泛地研究如何使用不同的杂质指标来确定每个节点的决策变量,如何确定重要的特征,更重要的是如何修剪树以防止模型过度拟合。要更好地理解决策树的工作原理,您可以参考下面的链接。
使用成本计算修剪构建、可视化和微调决策树的完整实践指南…
towardsdatascience.com](/decision-tree-classifier-and-cost-computation-pruning-using-python-b93a0985ea77)
概观
决策树由节点和分支组成。节点可以进一步分为根节点(树的起始节点)、决策节点(根据条件拆分的子节点)和叶节点(不会进一步分支的节点)。由于决策树遵循 if-else 结构,每个节点使用一个且仅一个自变量来分成两个或多个分支。自变量可以是分类的,也可以是连续的。对于分类变量,类别用于决定节点的分裂,对于连续变量,算法得出多个阈值作为决策者(Raschka,Julian and Hearty,2016 年,第 83、88、89 页)。
假设我们正试图为下面的数据集开发一个决策树。该数据集由学生 id、他们的性别信息、他们的学习方法和一个标识他们是否打板球的属性组成。我们可以区分预测变量和因变量与自变量或属性。因变量是“Plays Cricket”列,除了“Student ID”之外的其他属性将形成自变量集。
假设我们正试图为下面图 1 所示的数据集开发一个决策树。该数据集由学生 id、他们的性别信息、他们的学习方法和一个标识他们是否打板球的属性组成。我们可以区分预测变量和因变量与自变量或属性。因变量是“Plays Cricket”列,除了“Student ID”之外的其他属性将形成自变量集。

图一。包含学生信息和必要属性的表的快速概述。参考—由作者使用 PowerPoint 开发
决定分裂
作为这个问题的第一步,我们需要确定哪个独立变量可以用来分割根节点。我们用基尼杂质来决定学生在板球运动员和非板球运动员中的分支。我们将使用“性别”和“研究方法”来计算基尼系数,并考虑杂质分数最低的那个。请注意,决策树算法试图使每个节点尽可能同质。这与我们试图达到的结果是一致的,正确地预测学生是板球运动员还是非板球运动员。同质性是一种情况,在这种情况下,特定节点中的所有学生都属于其中一个类别,即他们要么是板球运动员(玩板球= Y),要么是非板球运动员(玩板球= N)。

图二。使用基尼指数和“性别”作为独立变量计算的加权*均杂质。参考—由作者使用 PowerPoint 开发

图 3。使用基尼指数和“研究方法”作为独立变量计算的加权*均杂质。参考—由作者使用 PowerPoint 开发
由于杂质是衡量节点同质性的指标,算法选择加权*均杂质分数最低的独立变量作为根节点的决策变量,在这种情况下,“性别”将用于创建决策树的第一次拆分。另外,请注意用黄色突出显示的数字,它们用于计算分割的信息增益。信息增益可以定义为杂质从父节点到各自子节点的变化,在这种情况下,我们需要检查根节点中的杂质是否高于分裂的加权杂质。如果信息增益大于 0,算法将继续使用决策变量分割节点。
我们如何修剪上面的树?
决策树通常会继续形成分支,直到每个节点变得同质。因此,该树可以很好地处理训练数据,但无法为测试数据生成高质量的输出。因此,这棵树应该修剪,以防止过度拟合。从上面的例子中,我们可以使用下面列出的因素来微调决策树。
- 标准 Python 使用基尼系数和熵。其他算法使用 CHAID(卡方自动交互检测器)、遗漏分类错误等。
- 从根节点/父节点到子节点,信息增益或最小杂质减少
- 每个节点中的样本数(最小或最大)
- 树的深度(算法应该形成多少个分支)
- 最大叶片数
使用 Python 的现实问题
了解基尼指数
问题陈述旨在开发一个分类模型来预测红酒的质量。关于问题陈述的细节可以在这里找到。这是一个多类分类问题的经典例子。我们不会研究代码,而是尝试使用 Python 中 sklearn.tree 的 DecisionTreeClassifier()来解释输出。
以下代码片段参考:Das,A. (2020)。使用 Python 的决策树分类器和代价计算剪枝。【在线】中等。可在:https://towards data science . com/decision-tree-classifier-and-cost-computing-pruning-using-python-b93a 0985 ea 77获得
#Reading the data
wine_df = pd.read_csv('winequality-red.csv',sep=';')# splitting data into training and test set for independent attributesfrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test =train_test_split(wine_df.drop('quality',axis=1), wine_df['quality'], test_size=.3,
random_state=22)
X_train.shape,X_test.shape#developing a model
clf_pruned = DecisionTreeClassifier(criterion = "gini", random_state = 100,
max_depth=3, min_samples_leaf=5)
clf_pruned.fit(X_train, y_train)#visualizing the tree
import iofrom io import StringIOfrom sklearn.tree import export_graphviz
# from sklearn.externals.six import StringIO
from IPython.display import Image
import pydotplus
import graphvizxvar = wine_df.drop('quality', axis=1)
feature_cols = xvar.columnsdot_data = StringIO()
export_graphviz(clf_pruned, out_file=dot_data,
filled=True, rounded=True,
special_characters=True,feature_names = feature_cols,class_names=['0','1','2'])from pydot import graph_from_dot_data
(graph, ) = graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())

图 4。使用基尼指数的决策树,深度=3,max_samples_leaves=5。请注意,为了处理等级不*衡,我们将葡萄酒分为品质 5、6 和 7。在上图中,5 对应于 class=0,6 对应于 class=1,7 对应于 class=2。
当我们看到一个多类算法时,我们不要对如何计算基尼指数感到困惑。在之前的例子中,我们用 P 和 Q 来代表打板球的学生和不打板球的学生。其中 P 是打板球的概率,Q 是不打板球的概率。在多类决策树的情况下,对于节点酒精< =0.25,我们将执行以下计算。
- p 代表葡萄酒质量为 5 的概率,即(514/1119) = 0.46
- q 代表葡萄酒质量为 6 的概率,即(448/1119) = 0.40
- r 代表葡萄酒质量为 7 的概率,即(157/1119) = 0.14
- 基尼指数= P+Q+R =(0.46)+(0.40)+(0.14)= 0.39
- 基尼系数= 1–0.39 = 0.61(见匹配)
上面的树被修剪了,这样我们可以更好地可视化模型。使用深度 3 或最大样本叶作为 5 没有统计学意义。
不使用 criterion = "gini ",我们总是可以使用 criterion= "entropy "来获得上面的树形图。熵的计算方法是-Plog(P)-Qlog(Q)。

图 5。使用熵的决策树,深度=3,max_samples_leaves=5。请注意,为了处理等级不*衡,我们将葡萄酒分为品质 5、6 和 7。在上图中,5 对应于 class=0,6 对应于 class=1,7 对应于 class=2。
了解功能重要性
特征重要性指的是为预测模型的输入特征分配分数的一类技术,该技术指示在进行预测时每个特征的相对重要性(Das,2020)。
## Calculating feature importancefeat_importance = clf_pruned.tree_.compute_feature_importances(normalize=False)feat_imp_dict = dict(zip(feature_cols, clf_pruned.feature_importances_))
feat_imp = pd.DataFrame.from_dict(feat_imp_dict, orient='index')
feat_imp.rename(columns = {0:'FeatureImportance'}, inplace = True)
feat_imp.sort_values(by=['FeatureImportance'], ascending=False).head()

图 6。自变量的特征重要性。
让我们试着理解下面的内容,以便更好地了解特性的重要性是如何决定的。
- 第一次分裂是基于酒精<=10.25; This variable with this threshold ensures minimum impurity of all other variables hence in the above table (Figure 5) you see that the feature importance is high
- The next split is based on sulphates
- When we look at the third level of the split, we see that there are three contenders, chlorides <=0.08, total sulfur dioxide <=88.5, volatile acidity <=0.87.
To decide which independent variable is important we need to understand the information gain by splitting these parent nodes into their respective child nodes.

Figure 7. Variables used to decide the split when depth =3.

Figure 8. Information Gain using volatile acidity≤0.87 as the threshold.

Figure 9. Information Gain using total sulfur dioxide≤88.5 as the threshold.
So, we see that the information gain by splitting Node “volatile acidity <=0.87” is higher than by splitting “total sulfur dioxide <=88.5” hence in the importance table “volatile acidity <=0.87” is placed above “total sulfur dioxide <=88.5”.
Understanding cost complexity
The cost complexity refers to the complexity parameter that is used to define the cost complexity measure Ra(T) of a given tree T. Ra(T) is written as:
Ra(T) = R(T) + a|T|
where |T| is the number of terminal nodes, R(T) is the total misclassification rate of the terminal node, and a is the CCP parameter. To summarise, the subtree with the highest cost complexity that is smaller than 【 will be retained. It is always good to select a CCP parameter that produces the highest test accuracy (Scikit Learn, n.d.).

Figure 10. Variation in train and test accuracy for different levels of alpha/a/CCP value.
Reference
- Raschka, S., Julian, D. and Hearty, J. (2016). Python:对机器学习的更深入的见解:利用使用 Python 的机器学习技术的好处:三个模块的课程。英国伯明翰:Packt 出版公司,第 83、88、89 页。
- sci kit-learn:python 中的机器学习,Pedregosa 等人,JMLR 12,第 2825–2830 页,2011 年。
- Scikit Learn (2019)。sk learn . tree . decision tree classifier—sci kit-learn 0 . 22 . 1 文档。[在线]Scikit-learn.org。可从以下网址获得:https://sci kit-learn . org/stable/modules/generated/sk learn . tree . decision tree classifier . html
- Scikit Learn(未注明)。后剪枝决策树与代价复杂度剪枝。【在线】可在:https://sci kit-learn . org/stable/auto _ examples/tree/plot _ cost _ complexity _ pruning . html # sphx-glr-auto-examples-tree-plot-cost-complexity-pruning-py。
- Das,A. (2020)。使用 Python 的决策树分类器和成本计算修剪。【在线】中等。可从以下网址获得:https://towards data science . com/decision-tree-classifier-and-cost-computing-pruning-using-python-b93a 0985 ea 77【2020 年 7 月 18 日获取】。
关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的业务、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以和我在 上联系 和 上推特;
决策树和随机森林—解释
详细的理论解释和代码示例
决策树和随机森林是用于分类和回归问题的监督学习算法。这两种算法最好放在一起解释,因为随机森林是一堆决策树的组合。当然,在创建和组合决策树时,需要考虑某些动态和参数。在这篇文章中,我将解释决策树和随机森林是如何工作的,以及使用这些模型时需要考虑的关键点。
决策树建立在反复询问问题以划分数据的基础上。用决策树的可视化表示来概念化分区数据更容易:

这是给动物分类的决策树。第一次分割是基于动物的大小。虽然问题看起来是“动物有多大?”,以“动物大于 1m 吗?”因为我们想在每一步把数据点分成两组。随着树越来越深,问题也越来越具体。
你在每一步问什么是最关键的部分,并极大地影响决策树的性能。例如,假设数据集的“要素 A”范围为 0 到 100,但大多数值都在 90 以上。在这种情况下,首先要问的问题是“特征 A 大于 90 吗?”。问“特性 A 大于 50 吗?”是没有意义的因为它不会给我们太多关于数据集的信息。
我们的目标是在每次分区时尽可能增加模型的预测性,以便模型不断获得关于数据集的信息。随机分割要素通常不会给我们提供关于数据集的有价值的信息。增加节点纯度的分割更能提供信息。节点的纯度与该节点中不同类的分布成反比。要问的问题是以增加纯度或减少杂质的方式选择的。
有两种方法来衡量一个分裂的质量:基尼系数和熵。它们主要测量杂质,并给出相似的结果。Scikit-learn 默认使用基尼指数,但您可以使用标准参数将其更改为熵。
基尼杂质
正如在维基百科上所述,“基尼杂质是一种衡量从集合中随机选择的元素被错误标记的频率,如果它是根据标签在子集中的分布随机标记的话”。基本上就是杂质随着随机性增加。例如,假设我们有一个盒子,里面有十个球。如果所有的球都是同样的颜色,我们就没有随机性,杂质为零。然而,如果我们有 5 个蓝色球和 5 个红色球,杂质是 1。
熵和信息增益
熵是不确定性或随机性的度量。一个变量的随机性越大,熵就越大。均匀分布的变量具有最高的熵。例如,掷一个公*的骰子有 6 个概率相等的可能结果,所以它有均匀的分布和高熵。

熵 vs 随机性
选择导致更纯节点的分裂。所有这些都表明“信息增益”,这基本上是分裂前后熵的差异。

当选择一个特征进行分割时,决策树算法试图实现
- 更多的预测
- 杂质少
- 低熵
现在我们已经了解了问题(或拆分)是如何选择的。下一个话题是题数。我们要问多少问题?我们什么时候停止?什么时候我们的树足以解决我们的分类问题?所有这些问题的答案将我们引向机器学习最重要的概念之一:过拟合。模型可以一直提问,直到所有节点都是纯的。纯节点只包括来自一个类的数据点。

模型可以一直提问(或者拆分数据),直到所有的叶子节点都是纯的。然而,这将是一个过于具体的模型,不能很好地概括。它在训练集上实现了高精度,但在新的、以前看不到的数据点上表现不佳。
正如你在下面的可视化中看到的,在深度 5,模型明显过度拟合。类之间的狭窄区域可能是由异常值或噪声造成的。


深度= 5 ( 图源)
控制或限制树的深度以防止过度拟合是非常重要的。Scikit-learn 提供超参数来控制决策树的结构:
max_depth: 一棵树的最大深度。树的深度从 0 开始(即根节点上的深度为零)。如果未指定,模型会一直分割,直到所有叶子都是纯的,或者直到所有叶子包含的样本数少于 min_samples_split。
min_samples_split: 拆分内部节点所需的最小样本数。只要一个节点的样本(数据点)多于 min_samples_split 参数指定的数量,该算法就会一直拆分节点。
最小杂质减少:进行拆分的目的是减少杂质(或不确定性),但并不是所有的拆分都能同样达到这个目的。此参数设置进行分割的阈值。如果这种分裂导致杂质的减少大于或等于阈值,则节点将被分裂。
这里可以看到 DecisionTreeClassifier() 的所有超参数列表。
随机森林
随机森林是许多决策树的集合。随机森林是使用一种叫做 bagging 的方法构建的,其中每个决策树都被用作并行估计器。如果用于分类问题,结果基于从每个决策树接收的结果的多数投票。对于回归,叶节点的预测是该叶中目标值的*均值。随机森林回归取决策树结果的*均值。
随机森林降低了过度拟合的风险,并且准确性比单个决策树高得多。此外,随机森林中的决策树并行运行,因此时间不会成为瓶颈。
随机森林的成功高度依赖于使用不相关的决策树。如果我们使用相同或非常相似的树,总体结果将不会比单个决策树的结果有太大的不同。随机森林通过自举和特征随机性实现不相关的决策树。
- Bootsrapping 是从带有替换的训练数据中随机选择样本。它们被称为 bootstrap 样本。下图清楚地解释了这一过程:

- 通过为随机森林中的每个决策树随机选择特征来实现特征随机性。随机森林中每棵树使用的特征数量可通过 max_features 参数控制。

特征随机性
自助样本和特征随机性为随机森林模型提供了不相关的树。
随机森林引入了一个额外的参数:
n_estimators: 代表一片森林中的树木数量。在一定程度上,随着森林中树木数量的增加,结果会变得更好。然而,在某个点之后,添加额外的树不会改进模型。请记住,添加额外的树总是意味着更多的计算时间。
利弊
决策树
优点:
- 通常不需要归一化或缩放要素
- 适合处理混合的特征数据类型(连续、分类、二进制)
- 容易理解
缺点:
- 倾向于过度拟合,并且需要集合以便很好地概括
随机森林
优点:
- 针对许多不同问题的强大、高度精确的模型
- 像决策树一样,不需要标准化或缩放
- 像决策树一样,可以一起处理不同的特征类型
- 并行运行树,因此性能不会受到影响
缺点:
- 与快速线性模型(即朴素贝叶斯)相比,对于高维数据集(即文本分类)不是一个好的选择
使用 Scikit-Learn 的示例
决策树和随机森林也可以用于回归问题。我之前做过一个关于预测二手车价格的项目。我将跳过所有的预处理,数据清理和 EDA 部分,并显示模型部分。对于回归任务,我使用了线性回归和随机森林回归。毫不奇怪,随机森林回归器有更好的性能。
我从一个人们用来卖二手车的网站上搜集数据。经过探索性的数据分析,我决定用网站上 ad 上的车龄、公里数、发动机大小和时长。目标变量当然是汽车的价格。数据集包含 6708 个数据点。

我使用了一个 RandomForestRegressor(),max_depth 设置为 5。由于它不是一个非常大和复杂的数据集,我只使用了 10 个估计器(决策树):

一个简单的随机森林回归模型在训练和测试数据集上都达到了大约 90%的准确率:

如果不使用适当的超参数,随机森林也可能过度拟合。例如,如果我在 max_depth 设置为 20 的情况下运行同一个模型,该模型会过度拟合。它在训练数据集上取得了更好的准确性,但在测试数据集上表现不佳:

max_depth = 20 会导致过度拟合
感谢您的阅读。如果您有任何反馈,请告诉我。
我的其他帖子
参考文献
- https://jakevdp . github . io/python datascience handbook/05.08-random-forests . html
- https://sci kit-learn . org/stable/modules/generated/sk learn . tree . decision tree classifier . html
- https://en . Wikipedia . org/wiki/Bootstrapping _(statistics)
- https://www . researchgate . net/figure/An-example-of-bootstrap-sampling-Since-objects-is-sub-sampled-with-replacement-some _ fig 2 _ 322179244
决策图表
在我们的日常生活中,我们与各种机器学习应用程序进行交互,并在不知不觉中使用它。最好的例子是从任何一个在线购物门户购买东西,在那里我们可以根据我们购买的东西得到几个推荐。
一种类型的机器学习算法是决策树,它是监督分类下的一种分类算法。
决策树是我们可能有意或无意使用过的东西。考虑一下买车的情况。我们会在考虑预算、安全性、颜色和价格等各种因素后选择汽车。我们首先检查了低于 X 的价格,然后是颜色,最后是安全性,然后得出了一个结论。

作者图片
查看上图,我们可以定义 决策树 是一个树形图的图形表示,用于确定行动过程。树的每个分支代表一个决定。
决策树能解决的问题?
它可以解决两类问题。
- 分类:根据 if-then 条件进行分类。如果一种花的颜色是红色,那么它就是玫瑰色,如果是白色,那么它就是百合色。
- 回归:有连续数据时使用回归树。
决策树的优势
- 简单易懂。
- 在数据准备方面很少努力。
- 非线性参数不影响性能。
缺点:
- 过拟合:在数据中有噪声的情况下。
- 不稳定性:由于数据的变化,模型可能变得不稳定。
决策树中使用的重要术语。
- 熵:它是对数据集中不可预测性的度量。例如,我们有一桶水果。这里所有的东西都是混合的,因此它的熵非常高。
- 信息增益:熵值降低了。例如,如果我们有一桶 5 种不同的水果。如果所有信息都保存在一个地方,那么获得的信息是最少的。但是如果我们将所有 5 种水果分开,我们会看到熵最小,因为它没有混合,而获得的信息最大。
- 叶节点:它是承载信息的决策树的末端。在上图中,我们可以说“购买”是叶节点。
- 决策节点:它是决策树的中间节点,在这里出现两个或更多新的分裂。在上图中,颜色是一个决策节点,因为它进一步分裂为红色和蓝色。
- 根节点:它是图中最顶层的节点,所有的信息都存储在这里,或者具有最高的熵。在图中,“汽车”是根节点。
如前所述,决策树可用于两种情况。让我们检查一下回归环境中的使用情况。
决策树:回归
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
df = pd.read_csv("../input/automobileEDA.csv")
df.head()

作者图片

作者图片
df.head()将给出每一列的前 5 行的详细信息。我们可以使用 df.tail()获得最后 5 行,类似地,使用 df.head(10)获得前 10 行。
数据是关于汽车的,我们需要使用上面的数据来预测汽车的价格
我们将使用决策树来预测汽车的价格。
df.dtypes
出局:
symboling int64
normalized-losses int64
make object
aspiration object
num-of-doors object
body-style object
drive-wheels object
engine-location object
wheel-base float64
length float64
width float64
height float64
curb-weight int64
engine-type object
num-of-cylinders object
engine-size int64
fuel-system object
bore float64
stroke float64
compression-ratio float64
horsepower float64
peak-rpm float64
city-mpg int64
highway-mpg int64
price float64
city-L/100km float64
horsepower-binned object
diesel int64
gas int64
dtype: object
dtypes 给出列的数据类型。
df.describe()

作者图片

作者图片
在上面的数据框中,列数据类型是 object、float 和 int64 的混合。因此,我们将只考虑那些数值为数字的列,并使所有的数字都浮动。
df.dtypes
for x **in** df:
if df[x].dtypes == "int64":
df[x] = df[x].astype(float)
print (df[x].dtypes)float64
float64
float64
float64
float64
float64
float64
float64
准备数据。
与分类任务一样,在本节中,我们将把数据划分为属性和标签,从而划分为训练集和测试集。我们将创建 2 个数据集,一个用于价格,另一个用于(df-price)。由于我们的数据框包含大量对象格式的数据,因此在本次分析中,我们将移除所有对象类型的列,对于所有 NaN 值,我们将移除该行。
df = df.select_dtypes(exclude=['object'])
df=df.fillna(df.mean())
X = df.drop('price',axis=1)
y = df['price']
这里,X 变量包含数据集中的所有列,除了标签“价格”列。y 变量包含“价格”列中的值,这意味着 X 变量包含属性集,y 变量包含相应的标签。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
为了训练该算法,我们将使用 DecisionTreeRegressor 类和 fit 方法。
from sklearn.tree import DecisionTreeRegressor
regressor = DecisionTreeRegressor()
regressor.fit(X_train, y_train)

我们来预测一下价格。
y_pred = regressor.predict(X_test)
让我们检查实际值和预测值之间的差异。
df=pd.DataFrame({'Actual':y_test, 'Predicted':y_pred})
df

实际值和预测值
from sklearn import metrics
print('Mean Absolute Error:', metrics.mean_absolute_error(y_test, y_pred))
print('Mean Squared Error:', metrics.mean_squared_error(y_test, y_pred))
print('Root Mean Squared Error:', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))

作者图片
import seaborn as sns
plt.figure(figsize=(5, 7)) ax = sns.distplot(y, hist=False, color="r", label="Actual Value")
sns.distplot(y_pred, hist=False, color="b", label="Fitted Values" , ax=ax) plt.title('Actual vs Fitted Values for Price')
plt.xlabel('Price (in dollars)')
plt.ylabel('Proportion of Cars')plt.show()
plt.close()

实际与预测
以上是实际值和预测值之间的曲线图。
决策树:分类
我们将使用决策树分类来预测模型的结果。
让我们导入所需的库。
import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
关于数据:
这些数据是关于一系列疾病的患者名单。通过该模型,我们将预测应该向患者提供哪种药物。
df = pd.read_csv("../input/drug200.csv")
df.head()

作者图片
计算数据的大小。
np.size(df)
出局:
1200
准备数据
我们将选取一些分析所需的列。
X = df[['Age', 'Sex', 'BP', 'Cholesterol', 'Na_to_K']].values
X[0:5]
出局:
array([[23, 'F', 'HIGH', 'HIGH', 25.355],
[47, 'M', 'LOW', 'HIGH', 13.093],
[47, 'M', 'LOW', 'HIGH', 10.113999999999999],
[28, 'F', 'NORMAL', 'HIGH', 7.797999999999999],
[61, 'F', 'LOW', 'HIGH', 18.043]], dtype=object)
在上面的数组中,数据集中的一些值不是数值,例如性别或 BP。不幸的是,Sklean 决策树不能处理这些变量。因此,我们需要将其转换成数字。pandas.get_dummies()将非数字变量转换为虚拟/指示变量。
from sklearn import preprocessing
le_sex = preprocessing.LabelEncoder()
le_sex.fit(['F','M'])
X[:,1] = le_sex.transform(X[:,1]) le_BP = preprocessing.LabelEncoder()
le_BP.fit([ 'LOW', 'NORMAL', 'HIGH'])
X[:,2] = le_BP.transform(X[:,2]) le_Chol = preprocessing.LabelEncoder()
le_Chol.fit([ 'NORMAL', 'HIGH'])
X[:,3] = le_Chol.transform(X[:,3]) X[0:5]
出局:
array([[23, 0, 0, 0, 25.355],
[47, 1, 1, 0, 13.093],
[47, 1, 1, 0, 10.113999999999999],
[28, 0, 2, 0, 7.797999999999999],
[61, 0, 1, 0, 18.043]], dtype=object)
上面我们已经把数值改成了 0,1,2。
*#target value*
y = df["Drug"]
y
出局:
0 drugY
1 drugC
2 drugC
3 drugX
4 drugY
...
195 drugC
196 drugC
197 drugX
198 drugX
199 drugX
Name: Drug, Length: 200, dtype: object
我们将在我们的决策树中使用训练/测试分割。让我们从 sklearn.cross_validation 导入 train_test_split。
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=3)
我们将创建一个测试和训练数据
我们将首先创建一个名为 Tree 的决策树分类器实例。
Tree = DecisionTreeClassifier(criterion="entropy", max_depth = 4)
Tree *# it shows the default parameters*
出局:
DecisionTreeClassifier(ccp_alpha=0.0, class_weight=None, criterion='entropy',
max_depth=4, max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, presort='deprecated',
random_state=None, splitter='best')
让我们预测一下我们的价值观。
pred =Tree.predict(X_test)
pred
在外
array(['drugY', 'drugX', 'drugX', 'drugX', 'drugX', 'drugC', 'drugY',
'drugA', 'drugB', 'drugA', 'drugY', 'drugA', 'drugY', 'drugY',
'drugX', 'drugY', 'drugX', 'drugX', 'drugB', 'drugX', 'drugX',
'drugY', 'drugY', 'drugY', 'drugX', 'drugB', 'drugY', 'drugY',
'drugA', 'drugX', 'drugB', 'drugC', 'drugC', 'drugX', 'drugX',
'drugC', 'drugY', 'drugX', 'drugX', 'drugX', 'drugA', 'drugY',
'drugC', 'drugY', 'drugA', 'drugY', 'drugY', 'drugY', 'drugY',
'drugY', 'drugB', 'drugX', 'drugY', 'drugX', 'drugY', 'drugY',
'drugA', 'drugX', 'drugY', 'drugX'], dtype=object)
让我们检查测试并预测值。
print (pred [0:5])
print (y_test [0:5])
出局:
['drugY' 'drugX' 'drugX' 'drugX' 'drugX']
40 drugY
51 drugX
139 drugX
197 drugX
170 drugX
Name: Drug, dtype: object
让我们检查模型的准确性。
from sklearn import metrics
import matplotlib.pyplot as plt
print("DecisionTrees's Accuracy: ", metrics.accuracy_score(y_test,pred))
出局:
DecisionTrees's Accuracy: 0.9833333333333333
创建一个决策树并将其可视化。
from sklearn import tree
plt.figure(figsize=(25,10))
tree.plot_tree(Tree,filled=True,
rounded=True,
fontsize=14);

作者图片
实际代码可在以下位置查看:
https://www . ka ggle . com/adityakumar 529/决策树分类
决策树:使用 Python 构建、修剪和可视化决策树
构建和调整机器学习模型,一步一步地解释

布兰登·格林的照片
B 二叉树是计算世界中最常见和最强大的数据结构之一。机器学习工程师如此喜欢决策树的主要原因是,它的处理成本很低,而且真的很容易理解(它是透明的,与神经网络的“黑箱”相反)。它使用分支方法来检查每个特性及其不同的结果,以找到目标值的模式。关于决策树和不同分支方法的更详细的解释,请看托马斯·普拉*格的这篇文章。
我们开始吧!
决策树模型
我们将使用来自卡格尔的泰坦尼克号数据集来预测幸存者。我们将导入数据并选择一些要使用的要素。“幸存”是我们的目标价值。
data = pd.read_csv(‘path_or_link/train.csv’)
data = data.loc[:,(‘Survived’,’Pclass’,’Sex’,’Age’,’SibSp’,’Parch’,’Fare’)]

数据样本
缺失值 我们有一些“年龄”的缺失值。为了解决这个问题,我们可以运行一些预测分析并填充这些点,但这不是本文的目标,所以我们将在以后的文章中讨论。现在,让我们只删除那些缺少值的行。
编码分类特征 为了将所有特征保持为数字格式,我们将对“性别”进行编码,这意味着将值从“女性”和“男性”转换为 0 和 1。
data.dropna(inplace=True)
#'inplace=True' applies the code to the 'data' object.from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
data.Sex = le.fit_transform(data.Sex)
将数据集分为训练集和测试集
x = data.iloc[:,1:] # Second column until the last column
y = data.iloc[:,0] # First column (Survived) is our targetfrom sklearn.model_selection import train_test_split
#this function randomly split the data into train and test setsx_train, x_test, y_train, y_test = train_test_split(x, y, test_size=.3)
#test_size=.3 means that our test set will be 30% of the train set.
构建决策树分类器 来自 sklearn 的 decision tree classifier()是一个很好的现成的机器学习模型,可供我们使用。它有 fit()和 predict()方法。
fit()方法是建模过程的“训练”部分。它找到算法的系数。然后, predict() 方法将使用训练好的模型对一组新数据(测试集)进行预测。
dtree = DecisionTreeClassifier()
dtree.fit(x_train, y_train) #train parameters: features and target
pred = dtree.predict(x_test) #parameter: new data to predict
准确性 为了确定我们的模型有多好,我们使用 sklearn 的另一个包来给它一个度量:
from sklearn.metrics import accuracy_score
accuracy_score(y_test, pred)#parameters: targets to be predicted and predictions from new data used before
准确度:0.75
这意味着我们的预测有 75%的准确度。
可视化树
我们可以绘制树来查看它的根、分支和节点。我们将使用一组新的库来完成这项工作。
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO
from IPython.display import Image
import pydotplusdot_data = StringIO()
export_graphviz(dtree, out_file=dot_data)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_png('/tree.png')
Image(graph.create_png())
StringIO() :创建一个对象(本例中为空)来接收一个点(图形描述语言)格式的字符串缓冲区(树将首先创建为字符串,然后创建为图像)。
export_graphviz() :该函数以点格式导出树,生成决策树的表示,并写入‘out _ file’。
graph _ from _ dot _ data():将使用 DOT 对象创建图形。
【Image():使用原始数据返回图像(png、jpeg、gif)。

决策图表
这棵树似乎很长。让我们改变几个参数,看看对精度是否有任何影响,并使树更短。
- 标准:定义将使用什么函数来测量分割的质量。选项有“基尼”和“熵”。
- Max_depth :定义树的最大深度。如果它是“无”,树将尽可能长,这时所有的叶子都是纯的(过度拟合模型的风险)。
dtree = DecisionTreeClassifier(criterion='gini')
dtree.fit(x_train, y_train)
pred = dtree.predict(x_test)
print('Criterion=gini', accuracy_score(y_test, pred))dtree = DecisionTreeClassifier(criterion='entropy')
dtree.fit(x_train, y_train)
pred = dtree.predict(x_test)
print('Criterion=entropy', accuracy_score(y_test, pred))
准确度结果:
标准=基尼:0.735
标准=熵:0.716
基尼系数法比熵值法略有改进。现在,让我们检查使用 max_depth 修剪树是否能给我们带来更好的结果。在下面的代码块中,我创建了一个简单的函数,使用不同的 max_depth 值(从 1 到 30)来运行我们的模型,并可视化其结果,以查看每个值的精确度有何不同。
max_depth = []
acc_gini = []
acc_entropy = []
for i in range(1,30):
dtree = DecisionTreeClassifier(criterion=’gini’, max_depth=i)
dtree.fit(x_train, y_train)
pred = dtree.predict(x_test)
acc_gini.append(accuracy_score(y_test, pred))
####
dtree = DecisionTreeClassifier(criterion=’entropy’, max_depth=i)
dtree.fit(x_train, y_train)
pred = dtree.predict(x_test)
acc_entropy.append(accuracy_score(y_test, pred))
####
max_depth.append(i)d = pd.DataFrame({‘acc_gini’:pd.Series(acc_gini),
‘acc_entropy’:pd.Series(acc_entropy),
‘max_depth’:pd.Series(max_depth)})# visualizing changes in parameters
plt.plot(‘max_depth’,’acc_gini’, data=d, label=’gini’)
plt.plot(‘max_depth’,’acc_entropy’, data=d, label=’entropy’)
plt.xlabel(‘max_depth’)
plt.ylabel(‘accuracy’)
plt.legend()

在这种情况下,gini 似乎对较长的树效果最好(正如我们在前面的精确度中看到的),但熵对较短的树效果更好,而且更精确(接* 0.82)。所以我们来画 max_depth=7,criterion=entropy 的树,看看是什么样子。
dtree = DecisionTreeClassifier(criterion=’entropy’, max_depth=7)
dtree.fit(x_train, y_train)pred = dtree.predict(x_test)
accuracy_score(y_test, pred)#Accuracy: 0.814

标准= '熵',最大深度=7
我们通过改变函数来创建分支并限制树以避免过度拟合,从而从 0.75 的准确度提高到 0.81。每个案例都是不同的,测试不同的参数以找到最适合您的场景是一个很好的实践。当你学习新的函数和机器学习模型时,不要犹豫阅读文档。它将为您提供更广泛的选项来根据您的需求定制模型。
现在,去吧,使用你的新技能,通过种一棵树来拯救地球。
使用 Python 实现决策树分类器和成本计算剪枝
使用 Python 中的成本计算修剪构建、可视化和微调决策树的完整实践指南

介绍
决策树分类器是监督学习模型,在我们关心可解释性时非常有用。想象一下,通过在每一层基于多个问题做出决策来分解数据。这是广泛使用的处理分类问题的算法之一。为了更好地理解它,让我们看看下面的例子。

用于决定特定一天的活动的示例决策树。改编自《Python 对机器学习的更深刻见解》(Raschka,Julian and Hearty,2016,第 83、88、89 页)
决策树通常包括:
- 根节点 —代表被进一步分成同类组的样本或总体
- 拆分——将节点分成两个子节点的过程
- 决策节点 —当一个子节点根据某种条件分裂成更多的子节点时,称为决策节点
- 叶节点或终端节点 —不再进一步分裂的子节点
- 信息增益 —为了使用条件(比如最具信息性的特征)来分割节点,我们需要定义一个可以优化的目标函数。在决策树算法中,我们倾向于最大化每次分裂的信息增益。在测量信息增益时,通常使用三种杂质测量。它们是基尼杂质、熵、分类和误差

带有树叶和树枝的决策树示例。参考—由作者使用 Lucid Chart 开发
5 编码嗅探如果你在数据科学行业工作,你必须知道
towardsdatascience.com](/are-your-coding-skills-good-enough-for-a-data-science-job-49af101457aa)
理解数学
为了理解决策树是如何开发的,我们需要更深入地理解如何在每一步使用一个杂质度量在每一步最大化信息增益。让我们举一个例子,我们有训练数据,包括学生信息,如性别、年级、因变量或分类变量,用于识别学生是否是美食家。我们有以下概述的信息。
- 学生总数— 20 人
- 被归类为美食家的学生总数— 10
- 不属于美食家的学生总数— 10 人
- p(吃货),一个学生成为吃货的概率= (10/20) = 0.5
- q(不是美食家,或 1-P),学生不是美食家的概率= (10/20) = 0.5
让我们将基于性别的学生分为两个节点,重新计算上述指标。
男同学(节点 A)
- 学生总数— 10 人
- 被归类为美食家的学生总数— 8
- 不属于美食家的学生总数— 2
- p(吃货),一个学生成为吃货的概率= (8/10) = 0.8
- q(不是美食家,或 1-P),学生不是美食家的概率= (2/10) = 0.2
女学生(节点 B)
- 学生总数— 10 人
- 被归类为美食家的学生总数— 4
- 不属于美食家的学生总数— 6
- p(吃货),一个学生成为吃货的概率= (4/10) = 0.4
- q(非美食家,或 1-P),学生非美食家的概率= (6/10) = 0.6
基尼指数(GIn) 对于节点 A 或男生= P + Q,其中 P 和 Q 分别是一个学生成为美食家和非美食家的概率。GIn(节点 A) = 0.8 + 0.2 = 0.68
基尼系数(GIp) 对于节点 A = 1-基尼系数= 1–0.68 = 0.32
Gini Index (GIn) 对于 Node B 或女学生= P + Q,其中 P 和 Q 分别是学生成为美食家和非美食家的概率。GIn(节点 B) = 0.4 + 0.6 = 0.52
基尼系数(GIp) 对于节点 B = 1-基尼系数= 1–0.52 = 0.48
我们在上面观察到的是,当我们根据学生的性别(男性和女性)将他们分别分成节点 A 和 B 时,我们分别有两个节点的基尼不纯度分数。现在,为了决定性别是否是将学生分为美食家和非美食家的正确变量,我们需要一个加权基尼杂质分数,该分数是使用下面列出的公式计算的。
加权基尼杂质=(节点 A 总样本数/数据集中总样本数)基尼杂质(节点 A) +(节点 B 总样本数/数据集中总样本数)基尼杂质(节点 B)
使用此公式计算上述示例的加权基尼系数,根据性别划分学生时的加权基尼系数= (10/20)0.32 + (10/20)0.48 = 0.4
分类问题涉及多个独立变量。变量可以是分类的,也可以是连续的。决策树非常适合处理不同数据类型的变量。决策树算法在决定每个节点的分裂时考虑了所有可能的变量。使用 的变量可以获得最大的加权杂质增益,被用作特定节点 的决策变量。
在上面的例子中,使用“性别”作为决策变量的加权杂质增益是 0.4,然而,假设使用“等级”作为决策变量,我们设法实现 0.56 的加权杂质增益,算法将使用“等级”作为决策变量来创建第一个分离。所有后续步骤都遵循类似的方法,直到每个节点都是同类的。
关于决策树算法的快速事实
- 随着算法继续将节点分割成子节点,直到每个节点变得同质,决策树易于过度拟合
- 与测试集相比,训练数据的准确性要高得多,因此应该修剪决策树以防止模型过度拟合。修剪可以通过控制树的深度、每个节点中样本的最大/最小数量、要分裂的节点的最小杂质增益以及最大叶子节点来实现
- Python 允许用户使用基尼杂质或熵作为信息增益标准来开发决策树
- 可以使用网格搜索或随机搜索 CV 对决策树进行微调。CV 代表交叉验证
三种不同杂质标准的目视比较
下面概述的代码片段提供了不同杂质标准的直观比较,以及它们如何随着不同的概率值而变化。注意下面的代码改编自 2016 年 S.Raschka,D.Julian 和 J . heartful 的《Python:对机器学习的更深刻见解》。
import matplotlib.pyplot as pltimport numpy as np#-----Calculating Gini Index
def gini(p):
return (p)*(1 - (p)) + (1 - p)*(1 - (1-p))#-----Calculating Entropy
def entropy(p):
return - p*np.log2(p) - (1 - p)*np.log2((1 - p))#-----Calculating Classification Error
def classification_error(p):
return 1 - np.max([p, 1 - p])#----Creating a Numpy Array of probability values from 0 to 1, with an increment of 0.01
x = np.arange(0.0, 1.0, 0.01)#---Obtaining Entropy for different values of p
ent = [entropy(p) if p != 0 else None for p in x]#---Obtaining scaled entropy
sc_ent = [e*0.5 if e else None for e in ent]#--Classification Error
err = [classification_error(i) for i in x]#--Plottingfig = plt.figure();
plt.figure(figsize=(10,8));
ax = plt.subplot(111);for i, lab, ls, c, in zip([ent, sc_ent, gini(x), err], ['Entropy', 'Entropy (scaled)','Gini Impurity',
'Misclassification Error'],['-', '-', '--', '-.'],
['black', 'darkgray','blue', 'brown', 'cyan']):
line = ax.plot(x, i, label=lab,
linestyle=ls, lw=2, color=c)
ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.15), ncol=3, fancybox=True, shadow=False)
ax.axhline(y=0.5, linewidth=1, color='k', linestyle='--')
ax.axhline(y=1.0, linewidth=1, color='k', linestyle='--')
plt.ylim([0, 1.1])
plt.xlabel('p(i=1)')
plt.ylabel('Impurity Index')
plt.show()

不同概率值的杂质变化。参考—上述代码片段的输出
动手练习
问题陈述旨在开发一个分类模型来预测红酒的质量。关于问题陈述的细节可以在这里找到。这是一个多类分类问题的经典例子。请注意,所有机器学习模型对异常值都很敏感,因此在构建树之前,应该处理由异常值组成的特征/独立变量。
不同特征/独立变量的一个重要方面是它们如何相互作用。皮尔逊相关可用于确定数据集中两个特征之间的关联程度。然而,对于像决策树这样基于决策的算法,我们不会丢弃高度相关的变量。
#---------------------------------------------Importing Required Libraries-----------------------------------
%matplotlib inlineimport numpy as np
import pandas as pdfrom sklearn.tree import DecisionTreeClassifierimport numpy as np
import pandas as pd
import seaborn as snssns.set(color_codes=True)from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split #--------------splitting data into test and train
from sklearn.tree import DecisionTreeClassifier #-----------Building decision tree modelfrom sklearn import metrics
from sklearn.metrics import accuracy_score,f1_score,recall_score,precision_score, confusion_matrix #-----model validation scores
%matplotlib inlinefrom IPython.display import display #---------------------for displaying multiple data frames in one outputfrom sklearn.feature_extraction.text import CountVectorizer #DT does not take strings as input for the model fit stepimport missingno as msno_plot #--------------plotting missing valueswine_df = pd.read_csv('winequality-red.csv',sep=';')
数据的快速描述性统计
wine_df.describe().transpose().round(2)

的输出。describe()函数
检查缺失值
#-------------------------------------------Barplot of non-missing values--------------------------------
plt.title('#Non-missing Values by Columns')
msno_plot.bar(wine_df);

说明数据集中非缺失值计数的图
异常值检查和处理
#--Checking Outliers
plt.figure(figsize=(15,15))
pos = 1
for i in wine_df.columns:
plt.subplot(3, 4, pos)
sns.boxplot(wine_df[i])
pos += 1

说明数据中存在异常值的箱线图
col_names=['fixed acidity', 'volatile acidity', 'citric acid', 'residual sugar',
'chlorides', 'free sulfur dioxide', 'total sulfur dioxide', 'density',
'pH', 'sulphates', 'alcohol']display(col_names)for i in col_names:
q1, q2, q3 = wine_df[i].quantile([0.25,0.5,0.75])
IQR = q3 - q1
lower_cap=q1-1.5*IQR
upper_cap=q3+1.5*IQR
wine_df[i]=wine_df[i].apply(lambda x: upper_cap if x>(upper_cap) else (lower_cap if x<(lower_cap) else x))
上面的异常值使用 Q1-1.5 * IQR 和 Q3+1.5*IQR 值进行了 winsorized 化。Q1、Q3 和 IQR 分别代表四分位数 1、四分位数 3 和四分位数间范围。
sns.pairplot(wine_df);

说明不同变量相互作用的配对图
理解不同变量之间的关系。注意—在决策树中,我们不需要删除高度相关的变量,因为仅使用一个独立变量将节点划分为子节点,因此即使两个或更多变量高度相关,产生最高信息增益的变量也将用于分析。
plt.figure(figsize=(10,8))
sns.heatmap(wine_df.corr(),
annot=True,
linewidths=.5,
center=0,
cbar=False,
cmap="YlGnBu")
plt.show()

说明不同属性相关性的热图
分类问题对阶级不*衡很敏感。类别不*衡是指相关属性中 1 的比例高于 0 的比例,反之亦然。在多类问题中,当其中一个类值的比例非常高时,就会出现类不*衡。类别*衡是通过组合属性“质量”的值来诱导的,该属性是本问题陈述中的因变量。
plt.figure(figsize=(10,8))
sns.countplot(wine_df['quality']);

该图显示了不同葡萄酒质量的记录计数
wine_df['quality'] = wine_df['quality'].replace(8,7)
wine_df['quality'] = wine_df['quality'].replace(3,5)
wine_df['quality'] = wine_df['quality'].replace(4,5)
wine_df['quality'].value_counts(normalize=True)
数据被分为训练集和测试集,以检查模型的准确性,并寻找过度拟合或欠拟合(如果有的话)。
# splitting data into training and test set for independent attributesfrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test =train_test_split(wine_df.drop('quality',axis=1), wine_df['quality'], test_size=.3,
random_state=22)
X_train.shape,X_test.shape
决策树模型是使用基尼标准开发的。注意,为了简单起见,我们将树修剪到最大深度为 3。这将有助于我们将树形象化,并将它与我们在最初部分中涉及的概念联系起来。
clf_pruned = DecisionTreeClassifier(criterion = "gini", random_state = 100,
max_depth=3, min_samples_leaf=5)
clf_pruned.fit(X_train, y_train)
请注意,可以调整以下参数来改善模型输出(Scikit Learn,2019)。
- 标准 —基尼系数用于决定变量,基于该变量,根节点和随后的决策节点应该被分割
- class_weight —无;所有类别都被赋予权重 1
- 最大深度—3;修剪完成。当“无”时,表示节点将被扩展,直到所有叶子都是同类的
- max_features —无;在决定一个节点的分裂时,考虑所有的特征或独立变量
- max_leaf_nodes —无;
- 最小杂质减少量—0.0;仅当分裂确保杂质减少大于或等于零时,才分裂节点
- 最小 _ 杂质 _ 分裂 —无;
- min _ samples _ leaf—1;叶子存在所需的最小样本数
- min _ samples _ split—2;如果 min_samples_leaf =1,则表示右节点和左节点应该各有 1 个样本,即父节点或根节点应该至少有两个样本
- 分割器——‘最佳’;用于在每个节点选择分割的策略。最好确保在决定分割时考虑所有特征
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO
from IPython.display import Image
import pydotplus
import graphvizxvar = wine_df.drop('quality', axis=1)
feature_cols = xvar.columnsdot_data = StringIO()
export_graphviz(clf_pruned, out_file=dot_data,
filled=True, rounded=True,
special_characters=True,feature_names = feature_cols,class_names=['0','1','2'])from pydot import graph_from_dot_data
(graph, ) = graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())

图示为深度=3 时的决策树模型
preds_pruned = clf_pruned.predict(X_test)
preds_pruned_train = clf_pruned.predict(X_train)print(accuracy_score(y_test,preds_pruned))
print(accuracy_score(y_train,preds_pruned_train))
该模型对训练和测试数据的准确率分别为 0.60 和 0.62。
特征重要性指的是为预测模型的输入特征分配分数的一类技术,这些分数指示了在进行预测时每个特征的相对重要性。
## Calculating feature importancefeat_importance = clf_pruned.tree_.compute_feature_importances(normalize=False)feat_imp_dict = dict(zip(feature_cols, clf_pruned.feature_importances_))
feat_imp = pd.DataFrame.from_dict(feat_imp_dict, orient='index')
feat_imp.rename(columns = {0:'FeatureImportance'}, inplace = True)
feat_imp.sort_values(by=['FeatureImportance'], ascending=False).head()

影响决策树拆分的五大特征
DecisionTreeClassifier()提供诸如 min_samples_leaf 和 max_depth 之类的参数来防止树过度拟合。可以把它想象成一个场景,我们明确定义了树的深度和最大叶子数。然而,最大的挑战是确定一棵树应该包含的最佳深度和叶子。在上面的例子中,我们使用 max_depth=3,min_samples_leaf=5。这些数字只是一个例子,用来观察树的行为。但是,如果在现实中我们被要求处理这个模型并得出模型参数的最佳值,这是具有挑战性的,但不是不可能的(决策树模型可以使用 GridSearchCV 算法进行微调)。
另一种方法是使用成本复杂性修剪(CCP)。
成本复杂性修剪提供了另一种选择来控制树的大小。在决策树分类器中,这种修剪技术由成本复杂性参数 cost 来参数化。CCPα值越大,修剪的节点数越多。
简单来说,成本复杂性是一个阈值。只有当模型的整体杂质被提高了大于该阈值的值时,模型才进一步将节点分裂成子节点,否则它停止。
CCP 越低,杂质越少。怎么会?
当 CCP 值较低时,即使杂质没有减少很多,模型也会将一个节点分割成子节点。随着树的深度增加,这一点很明显,也就是说,当我们沿着决策树往下走时,我们会发现分裂对模型的整体杂质的变化没有多大贡献。然而,较高的分割确保了类别被正确分类,即准确性更高。
当 CCP 值较低时,会创建更多的节点。节点越高,树的深度也越高。
下面的代码(Scikit Learn,n.d .)说明了如何调整 alpha 以获得具有改进的准确度分数的模型。
path = model_gini.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas, impurities = path.ccp_alphas, path.impuritiesfig, ax = plt.subplots(figsize=(16,8));
ax.plot(ccp_alphas[:-1], impurities[:-1], marker='o', drawstyle="steps-post");
ax.set_xlabel("effective alpha");
ax.set_ylabel("total impurity of leaves");
ax.set_title("Total Impurity vs effective alpha for training set");

显示杂质随α值变化的图像
让我们来理解深度和节点数随 alpha 的变化。
clfs = clfs[:-1]ccp_alphas = ccp_alphas[:-1]node_counts = [clf.tree_.node_count for clf in clfs]depth = [clf.tree_.max_depth for clf in clfs]fig, ax = plt.subplots(2, 1,figsize=(16,8))ax[0].plot(ccp_alphas, node_counts, marker='o', drawstyle="steps-post")
ax[0].set_xlabel("alpha")
ax[0].set_ylabel("number of nodes")
ax[0].set_title("Number of nodes vs alpha")
ax[1].plot(ccp_alphas, depth, marker='o', drawstyle="steps-post")
ax[1].set_xlabel("alpha")
ax[1].set_ylabel("depth of tree")
ax[1].set_title("Depth vs alpha")
fig.tight_layout()

该图显示了深度和节点数随 alpha 值的变化
理解当α增加时精度的变化。
fig, ax = plt.subplots(figsize=(16,8)); #-----------------Setting size of the canvas
train_scores = [clf.score(X_train, y_train) for clf in clfs]
test_scores = [clf.score(X_test, y_test) for clf in clfs]ax.set_xlabel("alpha")
ax.set_ylabel("accuracy")
ax.set_title("Accuracy vs alpha for training and testing sets")
ax.plot(ccp_alphas, train_scores, marker='o', label="train",
drawstyle="steps-post")
ax.plot(ccp_alphas, test_scores, marker='o', label="test",
drawstyle="steps-post")
ax.legend()
plt.show()

该图显示了当 alpha 值增加时准确度分数的变化
i = np.arange(len(ccp_alphas))
ccp = pd.DataFrame({'Depth': pd.Series(depth,index=i),'Node' : pd.Series(node_counts, index=i),\
'ccp' : pd.Series(ccp_alphas, index = i),'train_scores' : pd.Series(train_scores, index = i),
'test_scores' : pd.Series(test_scores, index = i)})ccp.tail()ccp[ccp['test_scores']==ccp['test_scores'].max()]
上面的代码提供了在测试数据中产生最高精确度的成本计算修剪值。
参考
- s .拉什卡、d .朱利安和 j .哈特(2016 年)。 Python:深入了解机器学习:利用 Python 的机器学习技术优势:三个模块的课程。英国伯明翰:Packt 出版公司,第 83、88、89 页。
- sci kit-learn:python 中的机器学习,Pedregosa 等人,JMLR 12,第 2825–2830 页,2011 年。
- Scikit Learn (2019)。sk learn . tree . decision tree classifier—sci kit-learn 0 . 22 . 1 文档。[在线]Scikit-learn.org。可从以下网址获取:https://sci kit-learn . org/stable/modules/generated/sk learn . tree . decision tree classifier . html
- Scikit Learn(未注明)。后剪枝决策树与成本复杂度剪枝。【在线】可在:https://sci kit-learn . org/stable/auto _ examples/tree/plot _ cost _ complexity _ pruning . html # sphx-glr-auto-examples-tree-plot-cost-complexity-pruning-py。
关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的商业、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以和我在 上联系 和 上推特;
每位数据科学家必备的决策树

图片来自我的图片是 CC0。作曲时: Pixabay 的
决策树介绍
决策树是一种非常有用的分类方法,非常适合用最少的代码启动和运行。
我使用了某种形式的决策树来预测客户流失的可能性、客户转换、新产品采用、新功能采用,以及许多其他有用的应用。
这个简短的介绍将让你了解使用决策树作为分类工具的主要好处和局限性。
我还将带您完成构建您自己的决策树的步骤,同样重要的是,测试它的性能。
何时以及为何使用决策树
说到分类,使用决策树分类器是最容易使用的方法之一。
为什么要使用决策树
- 非常容易理解
- 它可以很好地处理丢失的数据和异常值,因此需要更少的前期清理
- 您可以放弃分类变量编码,因为决策树可以很好地处理分类!
- 无需深入递归划分的细节,决策树就能够模拟非线性关系。
为什么不使用决策树呢
尽管有这么多好处,但它们并不总是完美的选择。
- 同样,它们可能很简单,也可能过于复杂,几乎无法概念化或解释。
- 更进一步说,如果一个树过于偏向或复杂,它可能会太好地迎合其训练数据,结果是过度拟合。
模特培训
说到这里,让我们开始吧。我不会谈论交叉验证或训练,测试分裂,但会张贴下面的代码。如果你想得到更多的解释,一定要发表评论。
首先,我们将数据分成训练集和测试集。
还要注意,我们将使用经典的泰坦尼克号数据集,它包含在 base R 中。
n <- nrow(Titanic)n_train <- round(0.8 * n)set.seed(123)
train_indices <- sample(1:n, n_train)
train <- Titanic[train_indices, ]
test <- Titanic[-train_indices, ]
现在我们将使用rpart包中的rpart函数来训练模型。这里需要注意的关键是,我们想要预测的变量是存活的,所以我们想要根据一些数据了解任何给定个体存活的可能性。可以由解释为*;换句话说,让我们理解一些变量的存在。如果在后面有一个。这意味着我们想用数据集中的其他变量来预测存活。或者,如下所示,我们可以明确地调用我们想要使用的变量。*
另外要注意的是,method是class。这是因为我们希望创建一个预测分类结果的分类树,而不是用于数字结果的回归树。最后,我们用来训练模型的数据是train。
model <- rpart(formula = Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked,
data = titanic_train,
method = "class")
可解释性
如前所述,决策树如此容易使用的原因之一是它非常容易解释。你可以沿着树的不同分支走向不同的结果。
rpart.plot(model)

在那里阅读有点困难,但是如果你放大一点,你会看到如果有人可能在泰坦尼克号上生活或死亡的第一个标准是你是否是男性。如果你是男性,你移到左边的分支,向下两个节点,不管你是成年人还是你的兄弟姐妹/配偶。因此,如果你是一个单身男人,你的生存几率非常小。
性能赋值
在我们分解指标之前,让我们预测一下测试集的值。与训练调用类似,您选择数据和预测类型。核心区别在于型号规格。
test$pred <- predict(object = model,
newdata = test,
type = "class")
在理解决策树的功效时,有各种各样的性能评估指标会非常方便。
准确(性)
这个指标很简单,你的预测有多少是正确的。caret的混淆矩阵函数就包含了这个。
混淆矩阵
caret包中的confusionMatrix功能非常有用。用于评估分类模型性能。加载这个包,把你的预测和实际数据传给它。
library(caret)
confusionMatrix(data = test$pred,
reference = test$Survived)

这个函数向你展示的第一件事就是所谓的混淆矩阵。这将向您显示一个预测值和实际值如何匹配的表格。所以预测值和参考值相同的对角线单元格代表我们得到的正确值。将这些记录加起来 149 (106 + 43)并除以记录总数,178;我们达到了 83.4%的准确率。
True positive:象限中引用和预测都为 1 的单元格。这表明你预测了存活,而他们确实存活了下来。
假阳性:这里你预测为阳性,但你错了。
真阴性:当你预测为阴性,并且你是正确的。
假阴性:当你预测为阴性,而你是不正确的。
需要记住的几个关键指标是灵敏度和特异性。敏感度是您正确预测的真实记录的百分比。
另一方面,特异性是衡量实际错误记录中你正确预测的部分。
在不*衡数据集上进行预测时,要记住特异性。一个非常常见的例子就是对垃圾邮件进行分类。99%的情况下它不是垃圾邮件,所以如果你预测没有垃圾邮件,你有 99%的准确率,但你的特异性是 0,导致所有的垃圾邮件都被接受。
结论
总结我们对决策树的讨论,我们知道它们非常有用,因为它们非常容易解释,只需要最少的预处理,它们可以模拟非线性关系,并且它们具有可以轻松修复不*衡分类问题的功能。不*衡数据集
另一方面,当对更复杂的关系建模时,决策树可能非常难以理解,并且很容易过度拟合。
当您开始利用这种建模技术时,请记住这一点。
我希望你喜欢这堂关于决策树的快速课。让我知道你是否想要更多的信息,或者你是否想要我在另一篇文章中报道一些事情。
祝数据科学快乐!如果你喜欢这个,来看看 datasciencelessons.com 的其他帖子吧!
决策树基础
学习基尼系数、熵以及如何构建决策树

当谈到决策树的时候,我总是想象当我的女朋友不知道她晚饭想吃什么的时候,我会问她一系列的问题:你想吃点面条吗?你想花多少?亚洲人还是西方人?健康还是垃圾食品?
制作一个问题列表来缩小选择范围,本质上是决策树背后的思想。更正式地说,决策树是一种算法,它根据观察值的特征将它们划分为相似的数据点。
决策树是一种监督学习模型,具有树状结构,即包含根、父/子节点、叶。决策树可用于分类或回归问题。下图是我用来判断她要不要快餐的二叉分类树的简短版本。

快餐还是非快餐决策树
I)如何构造决策树?
有两种流行的树构建算法:分类和回归树(CART) 和 ID3 。这两个模型之间的主要区别是它们使用的成本函数。成本函数决定问哪个问题以及如何分割每个节点。构建决策树的伪代码是:
- 选择一个具有最佳索引的特征。使用我将在下一节介绍的成本函数来计算指数
- 基于所选要素分割数据集
- 重复这个过程,直到它到达叶子(或满足停止标准)
在这篇文章中,我们将讨论两个成本函数:基尼系数和熵值
(二)基尼系数和基尼系数
1)基尼不纯
基尼系数是在 CART 方法中使用的损失函数。基尼系数衡量一个类别有多少噪音。首先,每个数据特征可能包含许多类别。例如,天气特征可以有类别:下雨、晴天或下雪;一个数字特征如等级可分为两个块:< 70 或≥70。基尼系数可以通过以下公式计算:

基尼杂质公式
注意最大基尼系数是 0.5。这可以用一些微积分知识来检验。我创建了一个玩具数据集,以更好地说明成本函数对决策树的影响。
import pandas as pd
classification=['Freshman','Freshman','Sophomore','Junior','Freshman','Sophomore']
hour_of_practice=['>2h','>2h','>2h','<2h','>2h','<2h']
pass_the_quiz=['Yes','Yes','Yes', 'Yes', 'No','No']
df=pd.DataFrame({'Classification':classification,
'hour of practice':hour_of_practice,
"Pass the quiz":pass_the_quiz })
df

观察:大一(F)3 人,大二(S)2 人,大三(J)1 人。从数据来看,大一大二学生学习 2h 以上通过测试,学习 2h 以下不及格。学弟骗系统,一直过关。
让我们计算分类栏的基尼系数:

基尼值告诉我们数据集中存在的噪声值。在这种情况下,初级没有噪声,因为我们知道所有初级都将通过测试。另一方面,大二学生的噪音最大。
2)基尼指数
基尼指数将类别噪声结合在一起得到特征噪声。基尼指数是基尼系数的加权总和,基于该类别在特征中的相应分数。公式是:

基尼指数公式
将基尼指数应用于分类我们得到:

特征“分类”的基尼指数
你应该能够手工计算出学习时间的基尼指数。为了多样化,我创建了下面的代码来计算基尼系数和基尼系数:
# Input Format(df, feature name, category name ,target name, list of all classes)
# where df is the current node observationdef gini(df,feature,category,target,classes_list):
df=df[df[feature]==category]
def P_i_K(i):
return len(df[df[target]==i])/len(df)
result=1-sum([(P_i_K(i))**2 for i in classes_list])
return result# Input Format(df, feature name, target name, list of all classes)def Gini_index(df,feature,target,classes_list):
def P_k_a(category):
return len(df[df[feature]==category])/len(df)
result=0
for category in df[feature].unique():
gini_value=gini(df,feature,category,target,classes_list)
P_k_a_value=P_k_a(category)
result+=gini_value*P_k_a_valuereturn resultprint("Gini Index of Classification",
Gini_index(df,"Classification","Pass the quiz",['Yes','No']))
print("Gini Index of hour of practice",
Gini_index(df,"hour of practice","Pass the quiz",['Yes','No']))>>> Gini Index of Classification 0.38888888888888884
>>> Gini Index of hour of practice 0.41666666666666663
由于分类比小时练习噪音小,所以第一次分割针对分类特征。在讨论完熵的概念后,我们将把树形象化。
III)熵和信息增益
1)熵
在物理学中,熵代表随机变量的不可预测性。公*硬币中出现头或尾或尾的几率为 50/50,因此其熵值为 1,这是随机性的最高值。另一方面,具有值 0 表示相应的事件是命中注定的。熵与基尼系数相似,都表明了类别的不可预测性。熵的公式是:

熵公式
将此公式应用于大一、大二和大三学生,我们得到:

特征“分类”的熵
如上所述,二次熵的行为就像一枚公*的硬币,所以它有最高的价值。新生的值非常接* 1,因为它的类是不*衡的。
信息增益
在获得每个类别的熵之后,我们可以将它们组合起来,以获得特征的信息增益值。我们获得的信息越多越好。公式是:

信息增益公式
将此公式应用于我们的“分类”功能会产生:

我还提供了计算熵和信息增益的代码:
# Input Format(df,feature name K,category name,target name, list of all classes)
# Pass feature, category None if want to find the entropy of the whole observation
import math
def entropy(df,feature,category,target,classes_list):
if (feature!=None)|(category!=None):
df=df[df[feature]==category]
def P_i_k(class_):
return len(df[df[target]==class_])/len(df)
result=0
for class_ in classes_list:
P_i_k_value=P_i_k(class_)
if P_i_k_value!=0:
result+=P_i_k_value*math.log(P_i_k_value,2)
return -1*result# Input Format(df,feature name K,category name,target name,list of all classes)
def InfoGain(df,feature,target,classes_list):
H_T=entropy(df,None,None,target,classes_list)
def P_i_a(category,feature):
return len(df[df[feature]==category])/len(df)
result=0
for category in df[feature].unique():
result+=P_i_a(category, feature)*entropy(df,feature,category,target,classes_list)
result=H_T-result
return resultprint("Information Gain of Classification",
InfoGain(df,'Classification','Pass the quiz',['Yes','No']))
print("Information Gain of hour of practice",
InfoGain(df,'hour of practice','Pass the quiz',['Yes','No']))>>>Information Gain of Classification 0.12581458369391152
>>>Information Gain of hour of practice 0.044110417748401076
因此,分类有更多的信息,所以这将是我们的第一次分裂。
IV)可视化树
在这两种方法中,分类是首选。第二个分割是剩余的特性,**小时的学习,我们得到下面的树:

我们数据集的决策树
注意,这个树是极端有偏差的,因为数据集只有 6 个观察值。真实数据上的决策树要大得多,复杂得多。
v)停止分裂树的标准
随着数据变得越来越复杂,决策树也在扩展。尽管如此,如果我们保持树的增长,直到所有的训练数据被分类,我们的模型将会过度拟合。因此,学会何时停止是非常重要的。让我们来看看一些常用的标准:
节点中的观测值数量:理想的上限是总训练数据集的 5%。
节点的纯度:基尼指数显示当前数据集的每个特征有多少噪声,然后选择噪声最小的特征来应用递归。我们可以在这里设置基尼系数的最大值作为停止标准,通知分行是时候做决定了。
树的深度:我们可以预先指定深度的限制,这样树在面对复杂数据集时不会过度膨胀。
最大特征:由于树是按特征分割的,减少特征的数量将导致树的大小减小。只有选择具有高信息增益或低基尼系数的特征才是好主意。
六)结论
当我们看到树是如何构造的以及它是如何调整的,我们可以得出一些关于决策树的结论:
- 很容易解释。决策树类似于人类做决策的方式。因此,决策树是一个简单的模型,可以为企业带来巨大的机器学习透明度。
- 它不需要缩放/标准化数据,因为没有涉及使用数据值的计算。
- 未必创造出最好的树。原因是决策树背后的构造只关注每个节点的最优特征。不能保证最终结果是最优解。
- 也许过度拟合。很难阻止树的子样本停留在某些节点上。拥有一个从特定群体中学习的树会导致过度拟合。
你可以访问我的 GitHub 库下载代码。感谢阅读!
决策树:永远记住的 6 件关键事情
我们不需要深入算法背后的数学知识就能了解决策树。

在本帖中,我们将介绍决策树背后的基本原理以及一个实际的实现。
决策树是通用且强大的机器学习算法,可以执行分类和回归任务,甚至多输出任务。决策树也是随机森林的基本组件,是当今最强大的机器学习算法之一。
下面你会发现一个决策树的基本实现(如何训练模型并可视化其分裂),这是使用著名的 IRIS 数据集完成的。
**# Importing the necessary libraries**
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn import tree
from sklearn.tree import DecisionTreeClassifier**# Load iris**
iris=load_iris()
X= iris.data[:,:2]
y= iris.target**# Creating the decision tree object**
decision_tree= DecisionTreeClassifier(max_depth=2)**# Training the Model**
classifier=decision_tree.fit(X,y)
可视化决策树和拆分
**# Visualizing the decision tree**
plt.figure(figsize=(15,10))
tree.plot_tree(classifier, filled=True)

决策树及其分裂的可视化
print(tree.export_text(classifier))

打印决策树拆分
Scikit-Learn 使用 CART(分类和回归树)来训练决策树,后者只产生二叉树:非叶节点总是有两个子节点。
其思想是决策树使用一个单一特征 k 和一个阈值 tk (例如 X[0] < 5.45)将训练集分成两个子集。
如何选择 k 和 tk ?
它通过寻找(k,t k )的最佳对来产生最纯粹的子集(根据它们的大小加权)。
CART 算法试图最小化的成本函数是:

Cart 训练算法(成本函数)“按作者分类的图像”
然而,其他算法,如 ID3,可以生成具有两个以上子节点的决策树(Quinlan 1986)
”还没等龚转发一个小故事来消消气,就已经是相当的焦头烂额了。我从一位教授那里学到了这个著名的算法(ID3 ),这让我着迷,而这位教授正是这个算法的发现者😊"
计算复杂度
即使在处理较大的训练集时,预测也非常快,这是因为决策树需要从根到叶遍历整个树,因为它们通常是*衡的,遍历它们大约需要遍历:

(决策树的计算复杂性)“作者图片”
熵还是基尼杂质?
考虑到决策树及其家族的众多特性之一,它们需要很少的数据准备,它们根本不需要特征缩放。
然而,非常重要的是要注意这种差异。

(基尼系数杂质和熵方程)“作者图片”
大多数情况下,这并没有很大的区别,它们往往导致类似的树。但是,主要区别是:
- 基尼杂质计算起来略快(等式 1)。然而,当它们不同时,基尼系数分离出它自己分支中最常见的类别
- 熵(等式 2)产生稍微更*衡的树。
在 Scikit-learn 中,默认情况下,模型是用基尼系数杂质设置的。
决策树参数
(CCP _ 阿尔法=0.0,类 _ 重量=无,标准= '基尼',
最大深度=2,最大特征=无,最大叶节点=无,
最小杂质 _ 减少=0.0,最小杂质 _ 分离=无,
最小样本 _ 叶=1,最小样本 _ 分离=2,
最小重量 _ 分数 _ 叶=0.0,预排序= '已弃用',
随机状态=无
正则化超参数
对训练数据做了一些假设:假设数据是非线性的。在大多数情况下,如果决策树不受约束,树结构将非常适合数据集,过度适合数据,不能很好地推广到测试数据。
作为一个非参数模型,它有很多参数。但是因为参数的数目在训练之前没有确定,所以模型可以自由地坚持训练数据。为了避免过度拟合训练数据,我们需要在训练过程中限制决策树的自由度(正则化)。
这可以通过限制决策树的最大深度数来实现,特别是在 Scikit 中,通过设置 max_depth 超参数 (默认设置为 none: Unlimited)来实现学习。减少后者将使模型规范化,并降低过度拟合的风险

来自:数据科学堆栈交换
从上图中我们可以看到,拥有一个 max_depth 为 5 ,会产生一个方差很大的模型,而限制决策树的最大深度对减少模型的过拟合起着关键作用。当然,将它减少到两个对更好地规范模型有巨大的影响。
此外,决策树喜欢制作正交边界(所有分割都垂直于轴),如上图所示,这使它们对训练数据中的小变化非常敏感,并使模型非常不稳定。防止这种情况的一种方法是采用随机森林,后者可以通过对许多树进行*均来限制这种不稳定性,这个模型将在未来的帖子中详细分析。

来源:Takashi J. OZAKI via KDnuggets
该算法的 6 个关键要点:
- 易于解释(非参数模型),功能强大,用途广泛。
- 使用少量训练数据进行有效学习,但是对训练数据的微小变化非常敏感。
- 不需要功能缩放。
- 关于训练数据的假设很少(数据是非线性的)。
- 很可能会对训练数据进行过度拟合(没有很好地推广)。
- 喜欢正交决策边界。
希望这个简短的 ML 故事能提供信息!谢谢你
决策树:构建 DTs 的逐步方法

马里乌斯·马萨拉尔在 Unsplash 上的照片
介绍
决策树(DTs) 是一种用于分类和回归的非参数监督学习方法。目标是创建一个模型,通过学习从数据特征推断的简单决策规则来预测目标变量的值。决策树通常用于运筹学,特别是决策分析,以帮助确定最有可能达到目标的策略,但也是机器学习中的一种流行工具。
语境
在本文中,我们将讨论以下主题
- 通常什么是决策树
- 决策树的类型。
- 用于构建决策树的算法。
- 构建决策树的逐步过程。
什么是决策树?

图 1-基于是/否问题的决策树
上图是一个简单的决策树。如果一个人是非素食者,那么他/她吃鸡肉(最有可能),否则,他/她不吃鸡肉。一般来说,决策树会问一个问题,并根据答案对人进行分类。该决策树基于是/否问题。在数字数据上构建决策树同样简单。

图 2-基于数字数据的决策树
如果一个人开车时速超过 80 英里,我们可以认为这是超速,否则不是。

图 3-分级数据的决策树
这里有一个更简单的决策树。该决策树基于分级数据,其中 1 表示速度太高,2 表示速度较低。如果一个人超速超过等级 1,那么他/她就是严重超速。如果这个人在速度等级 2 之上但在速度等级 1 之下,那么他/她超速了,但没超速那么多。如果这个人低于速度等级 2,那么他/她在速度限制内驾驶得很好。
决策树中的分类可以是类别的,也可以是数字的。

图 4-复杂 DT
这里有一个更复杂的决策树。它结合了数字数据和是/否数据。在很大程度上,决策树很容易使用。你从顶端开始,一路向下,直到你无法再前进。样本就是这样分类的。
树的最顶端被称为 根节点 或者仅仅是 根。 中间的节点称为 内部节点 。内部节点有指向它们的箭头和远离它们的箭头。末端节点被称为 叶节点 或者仅仅是 叶节点 。叶节点有指向它们的箭头,但没有远离它们的箭头。
在上面的图中,根节点用矩形表示,内部节点用圆形表示,叶节点用倒三角形表示。
构建决策树
构建决策树有几种算法。
- CART-分类和回归树
- ID3-迭代二分法 3
- C4.5
- CHAID 卡方自动交互检测
我们将只讨论 CART 和 ID3 算法,因为它们是主要使用的算法。
手推车
CART 是一种 DT 算法,根据因变量(或目标变量)是分类变量还是数值变量,分别生成二进制 分类或回归树。它以原始形式处理数据(不需要预处理),并且可以在同一个 DT 的不同部分多次使用相同的变量,这可以揭示变量集之间复杂的相互依赖关系。

图 5-样本数据集
现在我们将讨论如何从原始数据表中构建决策树。在上面给出的例子中,我们将建立一个决策树,使用胸痛、良好的血液循环和阻塞动脉的状态来预测一个人是否患有心脏病。
我们必须知道的第一件事是哪个特性应该在树的顶部或根节点中。我们先来看看胸痛是如何预测心脏病的。

图 6-胸痛作为根节点
有两个叶节点,分别对应胸痛的两种结果。每一个叶子包含有心脏病和没有心脏病的患者的数目,用于对应的胸痛条目。现在我们对良好的血液循环和阻塞的动脉做同样的事情。

图 7-良好的血液循环作为根节点

图 8-阻塞的动脉作为根节点
我们可以看到,这三个特征都不能很好地区分心脏病患者和非心脏病患者。值得注意的是,在所有三种情况下,患有心脏病的患者总数是不同的。这样做是为了模拟真实数据集中存在的缺失值。
因为没有一个叶节点不是 100% '有心脏病'就是 100% '没有心脏病',所以都认为 不纯。 为了决定哪种分离最好,我们需要一种方法来测量和比较 杂质。
CART 算法中用于测量杂质的指标是 基尼杂质分数 。计算基尼系数很容易。我们先来计算一下胸痛的基尼杂质。

图 9-胸痛分离
对于左边的叶子,
**Gini impurity = 1 - (probability of ‘yes’)² - (probability of ‘no’)²**
= 1 - (105/105+39)² - (39/105+39)²
Gini impurity = 0.395
类似地,计算右叶节点的 Gini 杂质。
**Gini impurity = 1 - (probability of ‘yes’)² - (probability of ‘no’)²**
= 1 - (34/34+125)² - (125/34+125)²
Gini impurity = 0.336
现在我们已经测量了两个叶节点的基尼系数,我们可以计算总基尼系数,用胸痛来区分有和没有心脏病的患者。
叶节点不代表相同数量的患者,因为左叶代表 144 名患者,而右叶代表 159 名患者。因此,总 Gini 杂质将是叶节点 Gini 杂质的加权*均值。
Gini impurity = (144/144+159)*0.395 + (159/144+159)*0.336
= 0.364
同样,“血液循环良好”和“动脉阻塞”的总基尼系数计算如下
Gini impurity for ‘good blood circulation’ = 0.360
Gini impurity for ‘blocked arteries’ = 0.381
“良好的血液循环”在树中具有最低的杂质分数,这象征着它最好地分离了患有和未患有心脏病的患者,因此我们将在根节点使用它。

图 10-根节点处良好的血液循环
现在我们需要弄清楚“胸痛”和“动脉阻塞”如何区分左淋巴结的 164 名患者(37 名有心脏病,127 名无心脏病)。
就像我们之前所做的那样,我们将把这些‘胸痛’患者分开,并计算基尼杂质值。

图 11-胸痛分离
基尼系数为 0.3。然后我们对“堵塞的动脉”做同样的事情。

图 12-阻塞动脉分离
基尼系数为 0.29。由于“阻塞的动脉”具有最低的基尼系数,我们将在图 10 的左侧节点使用它来进一步分离患者。

图 13-阻塞动脉分离
我们只剩下“胸痛”,所以我们将看到它如何很好地分离左侧淋巴结中的 49 名患者(24 名有心脏病,25 名无心脏病)。

图 14-左侧淋巴结的胸痛分离
我们可以看到胸痛在区分病人方面做得很好。

图 15-最终胸痛分离
这些是树的这个分支左边的最后的叶子节点。现在,让我们看看当我们尝试使用“胸痛”来分离具有 13/102 个患者的节点时会发生什么。请注意,这个节点中几乎 90%的人没有心脏病。

图 16-右侧淋巴结的胸痛分离
这种分离的基尼系数为 0.29。但是在使用胸痛来分离患者之前,母节点的基尼不纯度是
Gini impurity = 1 - (probability of yes)² - (probability of no)²
= 1 - (13/13+102)² - (102/13+102)²
Gini impurity = 0.2
如果我们不使用“胸痛”来区分患者,杂质会更低。所以我们将使它成为叶节点。

图 17-左侧已完成
此时,我们已经完成了树的整个左侧。按照相同的步骤,计算出树的右侧。
- 计算基尼系数。
- 如果节点本身得分最低,那么就没有必要再分离患者,它就变成了一个叶节点。
- 如果分离数据导致改进,则选择杂质值最低的分离。

图 18-完整的决策树
ID3
除了用于测量纯度/杂质的方法之外,使用 ID3 算法构建决策树的过程几乎类似于使用 CART 算法。ID3 算法中用于测量纯度的度量被称为 熵 。

熵是一种度量样本子集中某个类的不确定性的方法。假设项目属于子集 S,具有两个类别正和负。熵被定义为表示 x 是正还是负所需的位数。
熵总是给出一个介于 0 和 1 之间的数。因此,如果使用属性分离后形成的子集是纯的,那么我们将需要 0 位来判断是正还是负。如果所形成的子集具有相等数量的正项和负项,那么所需的位数将是 1。

图 19。熵与 p(+)的关系
上图显示了熵和正类概率之间的关系。正如我们所看到的,熵达到 1,这是最大值,这时一个项目有相等的机会成为正的或负的。当 p(+)趋于零(象征 x 为负)或 1(象征 x 为正)时,熵最小。
熵告诉我们每个子集在分裂后有多纯或不纯。我们需要做的是汇总这些分数,检查拆分是否可行。这是通过信息增益完成的。


图 20。构建 ID3 树
考虑我们上面讨论的 CART 算法的这部分问题。我们需要从**chest pain**和**blocked arteries**中决定使用哪个属性来分离包含 164 个患者(37 个患有心脏病,127 个没有心脏病)的左侧节点。我们可以将分裂前的熵计算为

让我们看看**chest pain**如何区分病人

图 21-胸痛分离
可以计算左侧节点的熵

类似地,右边节点的熵

使用**chest pain**分裂后熵的总增益

这意味着,如果在当前情况下,如果我们选择**chest pain**来分割患者,我们将获得关于患者是否患有心脏病的 0.098 比特的确定性。对**blocked arteries**、、做同样的事情,得到的增益是 0.117。既然用**blocked arteries** 分裂给了我们更多的确定性,那就摘了吧。我们可以对所有节点重复相同的过程,以基于 ID3 算法构建 DT。
注意:可以通过对所需增益值施加最小阈值来决定是将节点分成 2 个还是将其声明为叶节点。如果获得的增益高于阈值,我们可以分裂节点,否则,将其作为叶节点。
摘要
以下是这篇文章的要点
- 决策树背后的一般概念。
- 决策树的基本类型。
- 构建决策树的不同算法。
- 使用 CART 算法构建决策树。
- 使用 ID3 算法构建决策树。
参考
- 参考 youtube 上的这个播放列表,了解更多关于使用 CART 算法构建决策树的细节。
2.关于使用 ID3 算法构建决策树的更多细节,请参考 youtube 上的这个播放列表。
PS:-我将很快发布另一篇关于回归树和随机森林的文章。 敬请期待 😃
请在这里查看我关于数据科学和机器学习的其他文章。欢迎在评论和LinkedIn上寻求更深入的讨论。
决策树解释
学习机器学习决策树的所有知识

来源: Unsplash
在这篇文章中,我将简单地解释决策树。它可以被认为是一个傻瓜帖子的决策树,然而,我从来没有真正喜欢过这个表达。
在我们开始之前,这里有一些额外的资源,可以让你的机器学习生涯一飞冲天
*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*!
- For more awesome Data Science news, tools, educative articles and platforms* [***subscribe to my newsletter***](https://z-ai.medium.com/subscribe)!
订阅我的专属列表!获取你喜欢的所有新鲜文章<3! By signing up, you will create a Medium…
z-ai.medium.com](https://z-ai.medium.com/subscribe)
Introduction and Intuition
In the Machine Learning world, 决策树是一种非参数模型,可用于分类和回归。
这意味着决策树是灵活的模型,不会随着我们添加更多的特征而增加它们的参数数量(如果我们正确地构建了它们),并且它们可以输出分类预测(像植物是否属于某种类型)或者数字预测(像房子的价格)。
它们由两种元素构成:节点和分支。在每个节点上,我们会评估数据的一个特征,以便在训练过程中拆分观察值,或者在进行预测时使特定的数据点遵循特定的路径。

在每个节点,对一个变量进行求值,以决定走哪条路径。
构建决策树时,通过 递归 评估不同的特征,并在每个节点使用最能拆分数据的特征来构建决策树。这个后面会详细解释。
也许开始解释的最好方法是看看决策树是什么样子的,以建立如何使用它们的快速直觉。下图显示了这些树的一般结构。

决策树的图形。来源。
在该图中,我们可以观察到三种节点:
- 根节点:是开始图的节点。在普通的决策树中,它评估最能分割数据的变量。
- 中间节点:这些是评估变量的节点,但不是进行预测的最终节点。
- 叶节点:这些是树的最终节点,在这里进行类别或数值的预测。
好了,现在我们对什么是决策树有了一个大致的概念,让我们看看它们是如何构建的。
决策树的训练过程
正如我们之前提到的,决策树是通过递归分割训练样本来构建的,使用的是最适合特定任务的数据特征。这是通过评估某些指标来完成的,如分类决策树的 基尼指数 或 熵 ,或回归树的 残差或均方差 。
如果我们在节点处评估的特征是离散的或连续的,则过程也是不同的。对于 离散特征对其所有可能值进行评估,从而为每个变量计算出 N 个度量,N 为每个分类值的可能值的数量。对于连续特征,训练数据的每两个连续值(从最低到最高排序)的*均值被用作可能的阈值。
对于某个节点,该过程的结果是变量列表,每个变量具有不同的阈值,以及每个变量/阈值串联的计算度量(Gini 或 MSE)。然后,我们选择变量/阈值组合,该组合为我们提供用于结果子节点的特定度量的最高/最低值(度量中的最高减少或增加)。
我们不会深入研究这些指标是如何计算的,因为这与这篇介绍性文章的主题无关,但是如果你感兴趣,我会在最后留下一些资源供你深入研究。目前,只要把这些度量(分类树的基尼系数和回归树的均方误差)想象成某种我们想要减少的误差。
让我们看一个两个决策树的例子,一个分类决策树和一个回归决策树,以更清楚地了解这个过程。下图显示了为著名的鸢尾数据集构建的分类树,其中我们试图使用花瓣宽度、长度、萼片长度等特征来预测三种不同花朵的类别

为 Iris 数据集构建决策树
我们可以看到,根节点从三个类别中的每一个的 50 个样本开始,并且基尼指数(因为它是分类树,所以基尼指数越低越好)为 0.667。
在该节点中,最好地分割不同类别的数据的特征是以 cm 为单位的 花瓣宽度 ,使用值 0,8 作为阈值。这产生了两个节点,一个具有 Gini 0(只有一种花的完美纯节点),另一个具有 Gini 0.5,在那里两种其他种类的花被分组。
在这个中间节点(来自根节点的错误路径)中,使用阈值 1,75 来评估相同的特征(是的,这可能发生,并且如果该特征很重要,它实际上经常发生)。现在这导致了另外两个子节点,它们不是纯粹的,但是基尼系数很低。
在所有这些节点中,对数据的所有其他特征(萼片长度、萼片宽度和花瓣长度)进行评估,并计算其结果基尼指数,然而,给我们最好结果(最低基尼指数)的特征是花瓣宽度。
树没有继续增长的原因是因为决策树总是配置一个停止增长的条件,否则它们会一直增长,直到每个训练样本都被分成它自己的叶节点。这些停止条件是树的最大深度、叶节点中的最小样本或误差度量的最小缩减。
现在让我们检查一下回归树,为此,我们将使用 波士顿房价 数据集,结果如下图:

为波士顿住房数据集构建的决策树
从上图可以看出,现在我们没有基尼指数,而是有了 MSE (均方差)。与前面的基尼系数示例一样,我们的树是使用最大程度地减少这种误差的特征/阈值组合来构建的。
根节点使用阈值为 9.725 的变量LSTAT(%区域中人口的下层状态)对样本进行初始划分。我们可以看到,在根节点我们有 506,我们分为 212(左子节点)和 294(右子节点)。
左边的子节点使用阈值为 6.631 的变量 RM ( 每个住所的房间数),右边的节点使用阈值为 16.085 的相同的 LSTAT 变量,产生了四个漂亮的叶节点。像以前一样,在每个节点上评估所有其他变量,但这两个变量是最好的数据分割变量。
厉害!现在我们知道决策树是如何构建的。让我们来学习它们是如何被用来做预测的。
用决策树做预测
使用决策树预测新样本的类别或数值目标值非常容易。这是这类算法的主要优点之一。我们所要做的就是从根节点开始,查看它所评估的特性的值,并根据该值转到左边或右边的子节点。
重复这个过程,直到我们到达一个叶节点。当这种情况发生时,根据我们面对的是分类问题还是回归问题,可能会发生两种情况:
a) 如果我们面临一个分类问题,预测的类别将是该叶节点上的类别的模式。还记得在分类树中,我们在中间的叶节点上有 value = [0,49,5]吗?这意味着到达该节点的测试样本最有可能属于在该节点上具有 49 个训练样本的类,因此我们将其分类。
b) 对于一棵回归树,我们在最后做出的预测是目标变量在这个叶节点上的值的*均值。在我们的住房示例中,如果叶节点有 4 个价格为 20、18、22 和 24 的样本,则该节点的预测值将是 21,这是在此结束的 4 个训练示例的*均值。
在下图中,我们可以看到如何为先前的回归树预测一个新的测试样本(一栋房子)。
注: 仅显示树中使用的房屋特征。

特定样本遵循的路径和给定预测的值。来自*面图标的图标。
好吧!现在我们知道如何使用决策树进行预测。让我们通过学习他们的优点和缺点来结束。
决策树的利与弊
优势:
- 决策树的主要优势是如何容易解释。当其他机器学习模型接*黑盒时,决策树提供了一种图形和直观的方式来理解我们的算法做什么。
- 与其他机器学习算法相比,决策树需要更少的数据来训练。
- 它们可用于分类和回归。
- 他们是简单的。
- 他们容忍缺失值 s。
不足之处
- 他们很容易使过度拟合训练数据,并且对异常值敏感。
- 他们是弱学习者:单个决策树通常不会做出很好的预测,因此多棵树经常被组合起来形成“森林”以产生更强的集成模型。这将在以后的文章中讨论。
订阅我的专属列表!获取您喜欢的所有新鲜文章<3! By signing up, you will create a Medium…
z-ai.medium.com](https://z-ai.medium.com/subscribe)
Conclusion and additional resources
决策树是简单而直观的算法,正因为如此,在试图解释机器学习模型的结果时,它们被大量使用。尽管很弱,但它们可以结合起来产生非常强大的 bagging 或 boosting 模型。在接下来的文章中,我们将探索其中的一些模型。
如果你想知道构建一棵树的完整过程,可以看看下面的视频:
就这些,我希望你喜欢这个帖子。随时 在 Twitter 上关注我 在@ jaimezorno*。还有,你可以看看我在数据科学和机器学习上的帖子*这里 。好好读!
关于机器学习和数据科学的更多资源,请查看以下资源库: 如何学习机器学习 !有关职业资源(工作、事件、技能测试),请访问AIgents.co——数据科学家的职业社区&机器学习工程师 。
还有,更多类似这样的帖子关注我上媒 ,敬请关注!**
还有,你可以订阅我的邮箱列表在这里获取最新更新和独家内容: 订阅邮箱列表 。
最后,为了更深入地了解决策树和机器学习,看看下面文章中描述的书:
让你的机器学习知识更上一层楼
towardsdatascience.com](/the-book-to-really-start-you-on-machine-learning-47632059fd0e)
非常感谢您的阅读,祝您有美好的一天!**
决策树:ID3 算法讲解
本文旨在详细地解释 ID3 算法(用于构建决策树的众多算法之一)。我们用一个假的样本新冠肺炎数据集来解释这个算法。

图片提供:【http://keeperofthesouls.com/uncategorized/hello-world/
什么是决策树?
简而言之,决策树是一种包含节点(矩形框)和边(箭头)的结构,它是从数据集(由代表特征/属性的列和对应于记录的行组成的表)构建的。每个节点要么用来**(称为决策节点)或 表示一个结果 (称为叶节点)。
决策树示例

上图描绘了一个决策树,用于对一个人是适合还是不适合进行分类。*
这里的决策节点是' ''这个人是不是不到 30 岁?'这样的问题这个人吃垃圾食品吗?等。树叶是两种可能的结果之一,即。适合和不适合。查看决策树,我们可以说做出以下决定:
如果一个人不到 30 岁,不吃垃圾食品,那么他是健康的,如果一个人不到 30 岁,吃垃圾食品,那么他是不健康的,等等。***
初始节点称为根节点* (蓝色)最终节点称为叶节点 (绿色),其余节点称为中间节点或内部节点。
根节点和中间节点代表决策,而叶节点代表结果。***
ID3 简介
ID3 代表迭代二分法 3,之所以这样命名是因为该算法在每一步都迭代地(重复地)将要素二分法(划分)为两个或更多个组。
由罗斯·昆兰发明的 ID3 使用自上而下的贪婪方法来构建决策树。简单地说,自顶向下方法意味着我们从顶部开始构建树,而贪婪方法意味着在每次迭代中,我们选择当前时刻的最佳特征来创建节点。
最常见的是,ID3 仅用于具有名义特征的分类问题。
数据集描述
在本文中,我们将使用新冠肺炎感染的样本数据集。整个数据集的预览如下所示。
****+----+-------+-------+------------------+----------+
| ID | Fever | Cough | Breathing issues | Infected |
+----+-------+-------+------------------+----------+
| 1 | NO | NO | NO | NO |
+----+-------+-------+------------------+----------+
| 2 | YES | YES | YES | YES |
+----+-------+-------+------------------+----------+
| 3 | YES | YES | NO | NO |
+----+-------+-------+------------------+----------+
| 4 | YES | NO | YES | YES |
+----+-------+-------+------------------+----------+
| 5 | YES | YES | YES | YES |
+----+-------+-------+------------------+----------+
| 6 | NO | YES | NO | NO |
+----+-------+-------+------------------+----------+
| 7 | YES | NO | YES | YES |
+----+-------+-------+------------------+----------+
| 8 | YES | NO | YES | YES |
+----+-------+-------+------------------+----------+
| 9 | NO | YES | YES | YES |
+----+-------+-------+------------------+----------+
| 10 | YES | YES | NO | YES |
+----+-------+-------+------------------+----------+
| 11 | NO | YES | NO | NO |
+----+-------+-------+------------------+----------+
| 12 | NO | YES | YES | YES |
+----+-------+-------+------------------+----------+
| 13 | NO | YES | YES | NO |
+----+-------+-------+------------------+----------+
| 14 | YES | YES | NO | NO |
+----+-------+-------+------------------+----------+****
这些列不言自明。y 和 N 分别代表是和否。受感染列 Y 和 N 中的值或类别分别表示受感染和未受感染。
用于生成决策节点的列,即。“呼吸问题”、“咳嗽”和“发烧”被称为特征列或仅称为特征,用于叶节点的列,即“受感染”被称为目标列。
ID3 中的指标
如前所述,ID3 算法在构建决策树的每一步都会选择最佳特征。
在你提问之前,这个问题的答案是:“ID3 如何选择最佳功能?”ID3 使用信息增益或仅使用增益来寻找最佳特征。
信息增益计算熵的减少,并测量给定特征分离或分类目标类的程度。具有最高信息增益的特征被选为最佳特征。
简单来说,熵是无序度的度量,数据集的熵是数据集目标特征中无序度的度量。
在二进制分类的情况下(其中目标列只有两种类型的类),如果目标列中的所有值都是同质的(相似的),则熵为 0 ,如果目标列中两个类的数值相等,则熵为 1 。
我们将数据集表示为 S,熵计算如下:
****Entropy(S) = - ∑ pᵢ * log**₂**(pᵢ) ; i = 1 to n****
其中,
n 是目标列中的类的总数(在我们的例子中,n = 2,即“是”和“否”)
是类“I”的概率或“目标列中具有类 I 的行数”与数据集中的“总行数”之比。****
特征栏 A 的信息增益计算如下:
*********IG(S, A) = Entropy(S) - ∑((|Sᵥ| / |S|) * Entropy(Sᵥ))*********
其中 Sᵥ 是 S 中特征列 A 具有值 v 的行集合,| Sᵥ |是 Sᵥ 中的行数,同样 |S| 是 S. 中的行数
ID3 步骤
- 计算每个特征的信息增益。
- 考虑到所有的行不属于同一个类,使用信息增益最大的特征将数据集 S 分割成子集。
- 使用具有最大信息增益的特征制作决策树节点。
- 如果所有行都属于同一个类,则将当前节点作为一个叶节点,并将该类作为其标签。
- 对剩余的特征重复,直到我们用完所有的特征,或者决策树具有所有的叶节点。
在我们的数据集上实现
如前所述,第一步是找到最佳特征,即具有最大信息增益 (IG) 的特征。我们现在将计算每个特征的 IG,但是为此,我们首先需要计算 S 的熵
在我们的数据集 S 总共 14 行中,有 8 行具有目标值 YES 和 6 行具有目标值 NO 。 S 的熵计算如下:
*********Entropy(S) = — (8/14) * log₂(8/14) — (6/14) * log₂(6/14) = 0.99*********
注意:如果我们的目标列中的所有值都相同,熵将为零(这意味着它没有或没有随机性)。
我们现在计算每个特征的信息增益:
发热 IG 计算:
在此(发热)特性中,有值为是的 8 行和值为号* 的 6 行如下所示,在 8 行中,有是发热的 6 行有目标值是和*******
*********+-------+-------+------------------+----------+
| Fever | Cough | Breathing issues | Infected |
+-------+-------+------------------+----------+
| YES | YES | YES | YES |
+-------+-------+------------------+----------+
| YES | YES | NO | NO |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| YES | YES | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| YES | YES | NO | YES |
+-------+-------+------------------+----------+
| YES | YES | NO | NO |
+-------+-------+------------------+----------+*********
如下图所示,在 6 个行中号有 2 个行有目标值是和 4 个行有目标值号
*********+-------+-------+------------------+----------+
| Fever | Cough | Breathing issues | Infected |
+-------+-------+------------------+----------+
| NO | NO | NO | NO |
+-------+-------+------------------+----------+
| NO | YES | NO | NO |
+-------+-------+------------------+----------+
| NO | YES | YES | YES |
+-------+-------+------------------+----------+
| NO | YES | NO | NO |
+-------+-------+------------------+----------+
| NO | YES | YES | YES |
+-------+-------+------------------+----------+
| NO | YES | YES | NO |
+-------+-------+------------------+----------+*********
下面的模块演示了发热的信息增益的计算。
*******# total rows **|S| = 14****For v = YES, |Sᵥ| = 8
Entropy(Sᵥ) = - (6/8) * log₂(6/8) - (2/8) * log₂(2/8) = 0.81****For v = NO, |Sᵥ| = 6
Entropy(Sᵥ) = - (2/6) * log₂(2/6) - (4/6) * log₂(4/6) = 0.91**# Expanding the summation in the IG formula: **IG(S, Fever) = Entropy(S) - (|S**ʏᴇꜱ**| / |S|) * Entropy(S**ʏᴇꜱ**) -
(|S**ɴᴏ**| / |S|) * Entropy(S**ɴᴏ**)****∴** **IG(S, Fever) = 0.99 - (8/14) * 0.81 - (6/14) * 0.91 = 0.13*********
接下来,我们计算特征**【咳嗽】【呼吸问题】的 IG 。 你可以使用这个免费的在线工具来计算信息增益。******
*******IG(S, Cough) = 0.04
IG(S, BreathingIssues) = 0.40*******
由于特征呼吸问题具有最高的信息增益,它被用于创建根节点。因此,在这个初始步骤之后,我们的树看起来像这样:****

接下来,从剩下的两个未使用的特征,即发烧和咳嗽,我们决定哪一个最适合呼吸问题的左支。
由于呼吸问题的左分支表示是,我们将使用原始数据的子集,即呼吸问题列中值为是的行集。这 8 行如下图所示:****
*******+-------+-------+------------------+----------+
| Fever | Cough | Breathing issues | Infected |
+-------+-------+------------------+----------+
| YES | YES | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| YES | YES | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| NO | YES | YES | YES |
+-------+-------+------------------+----------+
| NO | YES | YES | YES |
+-------+-------+------------------+----------+
| NO | YES | YES | NO |
+-------+-------+------------------+----------+*******
接下来,我们使用上面显示的子集 S ʙʏ ( S et 呼吸问题 Y es)来计算发烧和咳嗽特征的 IG:
注意:对于 IG 计算,熵将从子集 S ʙʏ而不是原始数据集s计算****
*******IG(Sʙʏ, Fever) = 0.20
IG(Sʙʏ, Cough) = 0.09*******
发烧的 IG 大于咳嗽,所以我们选择发烧作为呼吸问题的左分支:
我们的树现在看起来是这样的:****

接下来,我们为呼吸问题的右分支找到具有最大 IG 的特征。但是,由于只剩下一个未使用的特性,我们别无选择,只能将其作为根节点的右分支。我们的树现在看起来像这样:****

没有更多未使用的特性,所以我们在这里停下来,跳到创建叶节点的最后一步。
对于发烧的左叶节点,我们看到原始数据集中具有呼吸问题和发烧两个值的行子集为是。****
*******+-------+-------+------------------+----------+
| Fever | Cough | Breathing issues | Infected |
+-------+-------+------------------+----------+
| YES | YES | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| YES | YES | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+
| YES | NO | YES | YES |
+-------+-------+------------------+----------+*******
由于目标列中的所有值都是 YES,我们将左叶节点标记为 YES ,但是为了使其更符合逻辑,我们将其标记为 Infected。
类似地,对于发烧的右节点,我们看到原始数据集中具有呼吸问题值的行的子集为是,而发烧为否。****
*******+-------+-------+------------------+----------+
| Fever | Cough | Breathing issues | Infected |
+-------+-------+------------------+----------+
| NO | YES | YES | YES |
+-------+-------+------------------+----------+
| NO | YES | YES | NO |
+-------+-------+------------------+----------+
| NO | YES | YES | NO |
+-------+-------+------------------+----------+*******
此处值中除外大部分都是否,因此否或未感染成为我们的右叶节点。* 我们的树,现在看起来是这样的:*****

我们对节点咳嗽重复相同的过程,但是这里左右叶结果是相同的,即无或未感染,如下所示:****

看起来很奇怪,不是吗?我知道!呼吸问题的正确节点与类为“未感染”的叶节点一样好。这是 ID3 的缺点之一,它不做修剪。
修剪是一种通过删除不必要的节点来减少决策树的大小和复杂性的机制。更多关于修剪的信息可以在这里找到。
ID3 的另一个缺点是过度拟合或高方差,即它学习它使用的数据集如此之好,以至于它无法对新数据进行归纳。
摘要
我们详细介绍了 ID3 算法的过程,并看到了使用该算法创建决策树是多么容易,只需使用两个度量标准,即熵和信息增益。
希望你们喜欢,伙计们!!!
感谢阅读
参考资料:
https://www . cise . ufl . edu/~ DDD/cap 6635/秋季-97/Short-papers/2.htm
傻瓜决策树
直观的方法

在 Unsplash 上由 Collie Coburn 拍摄的照片
让我们看看我最喜欢的泰坦尼克号数据集。完整的数据集可以在这里找到。为了便于说明,我只取了八个数据点。实际数据集包含大约 700 个数据点。

我们的目标是创建一个决策树,可以预测一个人是否会生存。在这种情况下,我在数据集中只使用了四个特征,即 Pclass、Sex、SibSp、和abowed
- Pclass —机票等级(1、2 或 3)
- 性别——乘客的性别(男或女)
- SibSp——兄弟姐妹/配偶的数量(0、1 或 2)
- 上船——乘客在哪里上船(C、S 或 Q)
在我们进入决策树之前,让我们先了解一下数据科学背景下的树的解剖结构(参见下图中的树)。
- 一棵树有节点和分支。
- 分支连接节点。
- 用分支连接的节点之间存在父子关系。(节点 C 是节点 A 的子节点)
- 节点的深度定义为从该节点到根节点的分支数(节点 G 的深度为 2)。
- 没有子节点的节点称为叶节点。(节点 E、F、G 和 D 是叶节点)

树木解剖学
我们的目标是构建这样一个树,其中每个树节点代表一个特征测试(例如,乘客的性别是什么?),每个分支 (M 或 F)代表测试的结果,每个叶节点代表一个类标签(幸存与否)。我知道我在一行里说了很多,但是一旦你看到下面的图表,就很容易理解了。该图显示了对特征性别的测试,该特征在其分支上有两个可能的结果( M 和 F )。 M 的叶节点包含 3 个非存活者(3 个负),而 F 的叶节点包含 3 个存活者和 2 个非存活者(3 个正 2 个负)。简单。

样本测试
您可能已经听说过,ML 模型应该足够简单,以高精度预测看不见的(测试/实时)数据(记住!偏倚和方差的权衡。如果在树的上下文中思考,深度最小(或者叶节点最少)的树将是最简单的。现在的问题是,我们如何创建这样一个简单的测试树?换句话说,我们应该选择哪些测试,以什么样的顺序,来防止一个树变得复杂?
为了构建这样一棵树,在每一步中,我们都将贪婪地选择一个可以更均匀地分离数据集的测试(我们将在几分钟内讨论均匀性)。让我们在上面提到的泰坦尼克号数据集的背景下选择一个测试。我们有四个测试可供选择:
- Pclass 测试
- ****性测试
- SibSp 测试
- ****开始进行测试
我们一个一个来看。
+ ' —存活标签
' - ' —未存活标签

可能的测试
这里的目的是选择最好的测试。所谓最好的测试,我们指的是更清楚地区分幸存者和非幸存者的测试。仅仅为了举例说明,我将通过计算测试中清晰分离的数据点的数量来判断测试的质量(或者给它们打分)。一旦他们被评分,我们将选择最高分的测试。下面的计算将有助于更清楚地理解同质性的含义。
在 Pclass 测试中(查看上图进行可视化):
- ****二级明明有三个数据点,全部都没有存活下来。因此,这个群体显然是同质的。所以,它被授予三个点。
- ****第三类有一个数据点,并且完全同质。所以,奖励一分。
- ****第一类不是同质的(两个幸存者和两个非幸存者)。所以,它被授予 0 分。
因此,Pclass 检验的总同质点是 4 (3 + 1)。同样,如果你计算其他测试的同质性:
性别测试— 3 分
SibSp 测试— 2 分
上船测试— 0 分
因此,最明显的赢家是 Pclass 测试。这个测试产生最大的同质性。现在我们已经决定了第一个测试,这是到目前为止树的样子。

中间决策树
下一步会有点棘手。我们必须选择另一个测试,试图将 4 个(剩余的)非同类数据点(属于第一类)分成同类数据点(或叶节点)。
同样,我们列出所有的测试,并找到它们的同质性得分。测试结果是这样的。我们没有考虑 Pclass 测试,因为该测试将不再能够均匀地划分剩余的 4 个数据点。

二级测试
这一次明显的赢家是性测试(4 分)。因此,我们最后的决策树是—

最终决策树
因此,如果我们必须解释这个模型,那么一个人幸存了,如果—
a.他们有一张三等票。或者,
b .他们有一张头等票,他们是女。
这种方法的唯一问题是它不适用于大型数据集。原因是,几乎不可能找到一个测试来清晰地划分数据点,从而均匀地划分。有各种方法来衡量同质性。在这里阅读它们—
我希望上面讨论的例子至少能够给你提供一个关于决策树如何工作的直觉。
从根向上的决策树
手动构建一个最优决策树,以理解这个 ML 拥护者令人惊讶的常识性机制。

决策树是数据科学中的基本模型类型之一。幸运的是,他们提供了一个很好的例子,说明计算机如何自动化简单的人类直觉来构建大型复杂的模型。事实上,决策树优化了一个简单的标准,它反映了我们在日常生活中如何做决定。了解预测模型如何反映我们自己的心理模型,让我们能够批判性地思考它们可能会如何出错,以及一个好的模型是什么样子的。
本教程概述
本文的目标是提供一个交互式的决策树理论介绍。学完本教程后,您应该能够:
- 描述决策树的结构和功能。
- 使用熵和信息增益的概念手工构建一个小决策树。
- 关于算法实现如何大规模构建决策树的原因。
访问本教程的代码
本文中的代码和可视化都是使用 numpy、pandas 和 Altair(图片由作者提供,除非另有说明)在 Python 中生成的。您可以使用下面的方法跟随图表并与之交互。既然目的是手工构建自己的决策树,那么这个强烈推荐!
- 方法一: Github 。克隆或派生存储库,并通过 binder/environment.yml 中的 YAML 文件安装环境
- 方法二: NBViewer 。访问带有交互式图表的笔记本版本。
- 方法三:粘合剂。在线访问笔记本的完整实时版本。您可以修改并运行笔记本,甚至可以用另一个数据集进行尝试。
- 方法 4:按照整篇文章中的链接查看 Datapane 上的交互式图表。
什么是决策树?
决策树是一种逻辑模型,可以帮助您根据已知数据做出预测。这种预测包括某事是否会发生,或者某个项目是否属于某个类别。例如,根据患者的病史预测肿瘤是恶性还是良性。
这种预测是通过一系列是或否的问题做出的。病人吸烟吗?”是一个帮助决策树将数据划分为子集的问题,每个子集都有自己的行为。如果这个行为比整个数据集更容易预测,那么这个决策树是有效的。让我们用一个日常的例子来具体说明这一点。
决策树的日常例子
毫无疑问,你已经在人生的某个阶段做了一个决策树。让我们以度假打包行李为例。你应该带泳衣吗?您的决策过程可能看起来有点像这样:

灰色表示树的实际结构,而紫色箭头表示关键术语。
决策树总是从单个节点(顶部灰色气泡)开始,代表要问的第一个问题。在这个例子中,我们询问我们的目的地是否有游泳的地方。这个问题被称为分裂。它必须是“是/否”——请注意,我们通过在 80 度处创建一个阈值来处理温度定量标度。
最终,我们到达一个“叶”节点。这是我们做决定的地方。还要注意,每个节点都是两个“子”节点的“父”节点,除非它是叶节点。
构建好的决策树
这个模型对我们来说有直观的意义。但是,请记住,在机器学习中,我们必须评估模型,我们经常会处理复杂的数据集,而我们对这些数据集的直觉有限。那么我们该如何评价上面的模型呢?更广泛地说,区分好模型和坏模型的特征是什么?几个例子会对我们有所帮助。


一个好的决策树产生相对“纯”的子节点,一个坏的决策树通过问一个不相关的问题来延续不确定性。
在左边,我们有一个好的决策树的例子。我们可以评估这种心理模型的有用性的一种方法是问我们自己,在我们最*的 10 次旅行中,它会有怎样的表现,这里用彩色方块表示。红色代表不需要泳衣的旅行,蓝色代表需要泳衣的旅行。
我们可以看到,我们最初有一个 60/40 的分割,但是我们的“否”分支全部是红色的。换句话说,在我们过去的 10 次旅行中,有 3 次我们事先知道没有游泳的地方,在所有这些旅行中,我们都没有后悔没有穿泳衣。所以当我们对这个问题回答“不”的时候,我们可以非常确定我们正在做出正确的决定。
在我们过去的 10 次旅行中,有 7 次我们知道可以游泳的地方,而在这 7 次中的 6 次中,这是正确的选择。最后一个发生了什么?可能是太冷了,也可能是泳池意外关闭。好的一面是,对于我们的两个分支,我们能够做出比不提问时更好的猜测。
糟糕的决策树
在右边,我们有一个问题,似乎和泳衣没有任何关系。此外,我们可以看到,我们的问题将我们过去的旅行细分为两个子集,每个子集都具有相同的“把它带回家”或“把它留在家里”分裂。如果两个是/否分支有相同的分布(60/40),那么问这个问题并没有给我们任何新的信息。那么,我们当初为什么要费神问这个问题呢?
定义一个“好的”决策树
我们可以根据这一观察结果,暂时声明我们构建决策树的目标是产生问题尽可能少的“纯”子节点。因此,如果这是树的目标,那么每一次分割都应该旨在尽可能地“净化”其子节点。
坚持这个“纯洁”的概念,因为它很快就会有用。与此同时,让我们转向一个真正的数据科学问题。
在泰坦尼克号数据集上手工构建决策树
对于我们真正的问题,我们将使用泰坦尼克号的数据集。每一行都是一名乘客以及人口统计和旅行信息,比如他们的年龄、性别和机票等级。通常的目的是预测乘客是幸存还是死亡。

泰坦尼克号数据集的前 5 行。
我们如何着手建立一个决策树来预测哪些乘客幸存下来?什么是好的第一次分裂?
没有任何统计或可视化工具,我们所能做的就是任何关于这个数据集或领域的现有知识。也许我们看过电影,猜测幸存的女性比男性多。或者我们可以利用对世界和船的设计的了解来猜测头等舱的乘客比三等舱的乘客过得好。
当然,作为数据科学家,我们经常会被要求根据新领域的数据或者我们之前没有多少直觉的数据建立模型。换句话说,我们需要一种数据驱动的方式来选择好的拆分。我们可以从每个特性在每个类中的分布开始(存活和死亡)。我们将使用堆积条形图表示分类特征,使用 KDE (核密度估计,基本上是一个*滑的直方图)图表示定量特征。


5 个特征中幸存和死亡乘客的分布。
我们如何使用分布来确定候选人分裂?当查看分类变量时,我们希望选择一个分布与其他类别明显不同的类别。例如,我们可以看到男性和女性的存活率不同。对于定量变量,我们寻找一条线比另一条线高得多的区域。年龄似乎符合这个要求,独自旅行的人也是如此(家庭规模< 1 )。
但是现在我们有几个潜在的分裂,我们如何评估它们是否有好处呢?我们如何比较多个选项?
还记得我们之前讨论的“纯子节点”目标吗?我们可以用这个概念来建立一个分割的“好”的定量测量。
熵和信息增益
我们将定义熵,一个节点纯度的度量标准,以及信息增益,一个从父节点到其子节点的熵的度量标准。下面你会找到定义和公式。如果这有点令人困惑,请随意跳到下面的图片,该图片展示了上下文中的指标。
熵
- 衡量节点“纯净”程度的指标。
- 基于两个类别的比率,例如幸存者与非幸存者的比率。
- 范围从 0 到 1。0 表示纯节点(所有幸存者或反之亦然),1 表示 50/50 分割。请注意,熵为 1 对应于“最坏的情况”,我们最不可能做出有根据的猜测。
信息增益
- 分割降低熵的程度(降低越大越好,因为目标是 0)。
- 等于父节点的熵减去子节点熵的加权*均值。
- 构建决策树的算法在具有最高信息增益的每个节点上寻找分裂。

熵和信息增益公式
可视化父节点和子节点的熵
通过在决策树结构上叠加计算,我们可以更直观地了解如何选择最佳拆分。下图评估了分割类=第三类的信息增益。

拆分“类=第三”的信息增益计算。
橙色和蓝色的方块显示了每个节点的存活/死亡情况。对于每个节点,我们也有熵、存活率和人数。总之,这些事实讲述了一个关于数据集的故事,并允许我们评估这种拆分可能有多好:
- 我们的数据集整体由 891 人组成,其中 38%幸存。因为 38/62 的分裂非常接* 50/50,所以我们的熵几乎是 1。
- 491 名乘客(55%)属于三等舱。这些人只有 24%的存活率,比总体水*要差得多。对于这个子集,熵因此下降到 0.8。
- 在右边的分支,我们有头等舱和二等舱的乘客,他们更有可能幸存。这个子集有 56%的存活率。然而,尽管我们已经了解了这个群体的一些重要情况,这里的熵实际上比整个数据集中的要高一点。56%的存活率比人口 40%的存活率更接* 50/50——注意,在确定熵时,方向并不重要。
- 因为我们分裂的一边有明显较低的熵,而另一边基本上保持不变,低熵子集更大,这种分裂确实降低了总熵。这体现在底部的信息增益公式中。
- 这种分离的信息增益是 0.076。请注意,这个数字作为一个绝对量(相对于目标变量的总熵)有意义,但与其他分割相比最有用。
手工构建决策树
有了信息增益的概念,我们现在可以计算个体分裂的相对价值。构建决策树的算法可以快速评估许多潜在的分裂,以找到最佳分裂。要手动完成这项工作,我们需要一个工具来帮助我们。
这种交互式可视化让我们尝试了许多潜在的分裂。以前的功能分布图已经增加了选择分割的功能,只需单击条形图中的类别或*移定量功能即可。当选择分裂时,下面的子图表列出了左和右子集的信息增益和熵。
注意,为了可读性,熵和信息增益数字被乘以 100。否则,上面的例子可以完全重现。
用于调查可能分裂的交互式可视化。查看数据面板上的大图。
构建决策树的下一层
在信息获取方面有一个明显的赢家:男性/女性是迄今为止最好的划分。然而,假设我们想要一个更复杂的多变量模型,我们可以在左侧和右侧重复这个过程,以确定每个节点的最佳分割。我们现在正在构建一个如下所示的模型:

您可以使用以下女性和男性子集的交互式可视化。这个版本增加了一个折线图,显示所有可能的分割的信息增益。寻找任何有趣的场景,其中多个分割具有相似的信息增益值。
女
为女性子集选择最佳分割。
男
为男性子集选择最佳分割。
将我们的手工制作的圣诞树与 Scikit-Learn 的版本进行比较
现在,我们可以将这个简单的手工制作的模型与实现决策树算法产生的版本进行比较,比如 scikit-learn 中的版本。以下代码执行基本的数据清理和特征工程,然后构建模型并输出其结构。

scikit-learn 决策树的结构。输出来自 export_text()方法。
该模型具有 0.312 的总信息增益(从第一节点到叶子),以及 0.796 的精确度。你也有同样的发型吗?
结论
我们有时认为机器学习模型是一种与我们自己完全不同的智能类型。然而,在这种情况下,至少,建模的过程是植根于我们可能用来解决问题的相同类型的常识性解决方案。决策树是使用简单的迭代贪婪最大化熵构建的,熵是一个我们有直觉的量。
此外,熟悉树构造算法有助于我们作为数据科学家理解和欣赏我们可以用几行代码创建的模型中固有的权衡。
在我关于决策树的下一篇文章中,我们将基于这些概念来分析更复杂的决策树的结构,并理解树如何能够过度适应一个训练集。理解好的决策树的结构特征,并将不同类型的结构放入分类法中,对于数据科学家来说是非常有用的技能。
脚注
分割的替代术语包括规则或测试节点。我在这里使用 split 来引起人们对谓词如何将数据集分割成子集的注意。
数据集由 Kaggle 上“列车”子集中的 891 名乘客组成。年龄列的缺失数据已被估算。详情见源代码。
你会经常看到基尼杂质作为分裂节点的替代标准。例如,scikit-learn 将此作为默认标准,并能够切换到信息增益。虽然这种数学略有不同,但概念上的考虑是相同的,并且在实践中使用哪一种并不重要。
决策树——如何在纸上画出它们

图片来自 Pixabay
本文将讨论:
- 决策树——监督机器学习中一种著名的分类算法
- 决策树背后的基础知识以及如何在没有计算机的情况下开发决策树
你应该已经知道的:
- 统计和概率基础
说到机器学习中的分类问题,像逻辑回归、判别分析等算法。是那些浮现在人们脑海中的。还有一种非常直观、易于解释和理解的分类算法,称为决策树算法。基于树的模型可以用于回归和分类,但是我们在这里只讨论分类的情况。下面画了一个典型的决策树,让你熟悉这个概念:

上面的决策树显示了在一个随机的家庭中找到一台电视的机会。显而易见,上面的树表明,如果一个人的月收入超过 1000 美元,他就会在家里拥有一台电视,否则就会失去。上面的树可以看作是根据下面的数据开发的模型的可视化表示。这里的“月收入“是预测变量,“在家看电视”是反应变量。

让我们用一个简单的方法来处理上面的数据集。总共有 10 个数据点,在月收入栏下,有 6 个真值和 4 个假值。现在,我们先只分析真值。在 6 个真值中,有 4 个在国内电视栏下对应行有是,有 2 个有否反对。考虑中的行如下所示:

上述数据被认为是不纯的,因为存在混合响应值(4 是2否)对同一预测值为真。对我们来说,理想的数据集应该是只有是对真值或否对真值的数据集。在这种情况下,决策应该是非常容易和直接的。但是由于回答是混合或不纯的,我们不会在这里做出任何结论,让我们分析月收入栏下的其他值:

上面的数据集也是不纯的,对于假的同一个预测值,这里有一个混合响应变量值。由于大多数反对真的值是是,反对假的值是否,这意味着发现是反对真的概率更大,反对假的否的概率也更大,因此决策树如上图所示。单一预测变量模型看起来很简单。当模型中涉及多个变量时,事情就变得复杂了。我们很快就会看到这一点,但是让我们把注意力转移到上面介绍的一个术语上,叫做杂质。
杂质及其测量
杂质意味着我们的数据是多么的不均匀。在上面的例子中,正如已经提到的,如果预测器列中的每个真值在响应列中都有一个是,事情会变得更加简单,反之亦然。在几乎所有的实际情况下,情况并非如此,我们通常会得到混合数据集。我们需要找到一种测量杂质的方法。已经有两种方法来衡量数据的不纯或不均匀程度:

虽然它们都在相同程度上测量杂质,并导致了类似模型的发展,但我们在这里只考虑熵。让我们讨论熵方程中的各种参数。 Pi 是目标/响应变量中第 I 类的概率,例如,如果目标变量的类分布为[0,0,1,0,1,1,0,1,1],P(0) = 4/9,P(1) = 5/9。将这个概念应用于表 1,我们将得到 P(是)= 5/10 和 P(否)= 5/10。转到另一个参数,注意以 2 为底的对数函数的使用。如果你想知道更多关于等式中基数 2 的用法,你应该读读 这个 。
现在我们已经有了熵的等式,让我们首先计算所有数据的熵(表 1)。因为是值出现了 5 次,并且否值也出现了 5 次,所以我们有:

现在让我们计算在真分割下的数据的熵(表 2)。这里的目标变量是“在家看电视”有两个类“是”和“否”。是值出现 4 次,而否出现 2 次。

假设目标变量只有一个类别(完全纯),那么熵应该是:

这示出了具有完全同质性的数据集的熵= 0,并且很容易示出完全不纯的数据集(以相等的数量存在的每个类别观察)的熵为 1。
同样,在错误分割下的数据的熵将是:

引入收入变量后,数据的净熵可以通过对其拆分下的两个熵值进行加权*均来计算

熵的流动需要被清楚地理解。最初,它是 1,真分割将它减少到 0.917,假分割将它减少到 0.811。收入变量的净减少量为 0.874。这就是我们所期待的,通过变量的引入,熵(异质性的杂质)的减少。总缩减量为 1–0.874 = 0.126。这个数(0.126)被称为信息增益,是决策树模型开发中非常重要的参数。
这就是如何通过熵计算来计算杂质的程度。现在让我们在模型开发中应用这个概念。
模型开发
现在,除了上述通过月收入猜测电视拥有量的信息之外,假设后来我们注意到,不仅月收入,还有另一个影响结果的变量,该变量是一个人的位置,他是住在城市还是农村。让更新后的数据集如下所示:

无论我们目前知道什么,上面的数据集给我们带来了一个两难的选择。两难的问题是:我们的决策树是从收入预测器开始还是从位置预测器开始。我们将尝试通过对两个预测值进行熵计算来解决这一难题,但让我们将位置变量与目标变量分开,如下所示:

让我们分别计算收入和位置变量下的熵:

如你所见,月收入的熵低于位置变量的熵,我们可以说月收入变量比位置变量更能降低系统的异质性,信息增益为 1–0.874 = 0.126。按照信息增益标准,我们的决策树应该再次从月收入变量开始,如下所示:

虽然我们已经找到了第一个变量,但我们不能就此结束。我们还有另一个变量可以使用,它可以提高我们模型的效率。现在下一个问题是把它放在哪里,沿着树。对于位置变量,我们有两个可能的位置&都将传递不同的数据值给它&因此有不同的信息增益。我们将把它放在信息获取最大的地方。让我们计算一下,找出答案。
真值栏如下所示:

月收入一栏下的数值是一样的。根据列值分离 location 列,我们将得到如下所示的表:

上述计算可以如下图所示:

如果我们将位置变量置于错误分割下,计算和数据表将如下所示:

月收入一栏下的数值是一样的。根据列值分离 location 列,我们将得到如下所示的表:

上述计算可以想象为:

因为错误分割下的信息增益小于真实分割,所以决策树看起来像:

找到城市预测值的是值的概率大于否值,因此有上述安排。
上面的树表明,如果收入低于 1000 美元,家庭中将没有电视,如果收入高于 1000 美元,则我们必须检查家庭的位置,如果是城市,则可以找到电视,否则就是其他。
决策树就是这样发展起来的。决策树的结果通常不如其他分类模型(如逻辑回归或线性判别分析)准确,但当理解或解释系统的需要大于预测的需要时,它们是有用的。
现在你已经理解了开发决策树的概念,让我们来理解决策树中使用的各种术语。
节点:节点是表示决策树中一个变量的东西,比如收入和位置就是节点。
根节点:树开始的节点,如上述决策树中的收入。
叶节点:最底层的节点,在这里决定目标变量的值,例如 location 是上述树中的叶节点。
拆分:将一个节点拆分成两个或多个子节点的过程称为拆分
到目前为止,我们所做的任何事情的 Python 代码如下所示:

如果你觉得上面的概念很有趣,你可以进一步阅读下面提到的主题:
谢谢,
玩得开心:)
如果你对这篇文章有任何疑问,你可以通过 LinkedIn联系我
原载于 2020 年 4 月 4 日 http://wildregressor.com。
机器学习中的决策树
手推车初学者指南
有没有想过人类大脑在做决定时是如何工作的?在走上任何道路之前,要理解无限的可能性,所有关于奖励和惩罚的心理计算都必须考虑,以实现最佳的决策路线。是的,我们的大脑确实是一个杰作,我们将讨论如何教会我们的计算机决策的艺术。
决策树是用于分类和回归任务的监督学习中的预测工具。它们现在被称为 CART ,代表“分类和回归树”。决策树方法按照从根到叶遍历树状图形的算法,在每一步基于特定条件分割数据集。在每一个阶段,树的节点代表问题的可能测试用例,沿着节点的任何边前进代表一个可能的解决方案。

决策树
让我们看看决策树是什么样子的。

基本决策树
该图说明了一个简单的决策场景,其中一个人必须决定他/她是否有资格投票。因此,决策树从根开始,尝试根据用户的输入做出决策。在这里,这是一个分类问题,一个人只有当他/她是这个国家的公民并且年满 18 岁时才有资格投票。
您现在可能会想,这可以在任何编程语言中使用简单的 if-else 语句来实现。但是,我向你保证,事情要比这复杂得多。
当涉及到庞大而复杂的数据集时,在整个树中进行决策时需要考虑各种参数。因此,决策树帮助我们做出这些决定。
让我们看一个实际的例子,我们将根据一个人的属性来预测他是否能被录用。
招聘预测
让我们从导入数据集开始。
import numpy as np
import pandas as pd
from sklearn import tree # import decision tree from scikit learn librarydf = pd.read_csv("PastHires.csv" , header = 0) # Read the dataset
让我们看看这里有什么。

为了能够使用机器学习,数据集中的每个字母条目都必须转换为数字。
转换“已雇用?”中的“Y”条目、“顶级学校”、“实习”和“聘用”列设置为 1,所有“N”项设置为 0。
# Convert the alphabetical entries to numerical entries
d = {'Y': 1, 'N': 0}
df['Employed?'] = df['Employed?'].map(d)
df['Top-tier school'] = df['Top-tier school'].map(d)
df['Interned'] = df['Interned'].map(d)
df['Hired'] = df['Hired'].map(d)
让我们也把他们的资格映射成数字。0 分代表理学士,1 分代表理硕士,2 分代表理博士。
d = {'BS': 0, 'MS': 1, 'PhD': 2}
df['Level of Education'] = df['Level of Education'].map(d)
数据集现在看起来像这样,
df.head()

“已雇用”列中的目标列是我们需要预测的列,其余列是我们在做出决策时考虑的功能。
因此,将 features 列从目标中分离出来。
# List the factors involved in making the decision to hire or not
features = list(df.columns[:6])
features
在构建我们的树之前,让我们在 x 中调用我们的特性,在 y 中调用我们的目标。
y = df["Hired"]
X = df[features]
是时候建造我们的圣诞树了。我们将使用树包中的 DecisionTreeClassifier() 方法来制作我们的树。
clf = tree.DecisionTreeClassifier() # Decision tree Classifier
clf = clf.fit(X,y)
决策树现在已经准备好了。为了可视化树,我们必须安装 pydotplus 和 graphviz 包。
pip install pydotplus graphviz
现在,想象决策树。
from IPython.display import Image
from sklearn.externals.six import StringIO
import pydotplusdot_data = StringIO()
tree.export_graphviz(clf, out_file=dot_data,
feature_names=features)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
😲是啊!我们刚刚得到了一个惊人的决策树,可能是这样的。

决策树
推理
让我们分析一下我们刚刚得到的决策树,它对于理解这个算法是如何工作的至关重要。在任一点上,从树的右边往下,表示一个人被雇用,从左边往下,表示这个人没有被雇用。可以观察到一个人“就业?”值> 0.5 的列立即被雇用。被雇佣的人。列的值小于 0.5,但在“Interned”列中的值大于 0.5。类似地,可以评估树中的其他节点。该树有某些度量标准,它为自己设置了这些度量标准,以便在遍历该树时逐步做出决策。
预言
随机森林
随机森林只不过是大量的决策树。它将树的数量作为输入,并生成许多决策树的组合。最后,在分类的情况下,预测基于众数,在回归的情况下,预测基于*均数。
我们将使用 sci-kit 学习库中的 RandomForestClassifier() 方法。让我们生成 10 个这样的决策树。
from sklearn.ensemble import RandomForestClassifierclf = RandomForestClassifier(n_estimators=10) # Set number of decision trees
clf = clf.fit(X, y)
我们将使用这个随机森林来预测一个具有特定属性的人是否会被雇佣。对具有以下特征的人的预测:
- 15 年的经验
- 已经被雇佣了
- 4 名前雇主
- 博士资格
- 顶级学校毕业的,而且
- 已经实习
print (clf.predict([[15, 1, 4, 2, 1, 1]]))
[1]
现在,让我们预测另一个有特征的人:
- 1 年经验
- 未就业
- 0 以前的雇主
- 学士资格证书
- 不是来自顶级学校
- 没有实习过
print (clf.predict([[1, 0, 0, 0, 0, 0]]))
[0]
结果
我们看到,在第一种情况下,非常适合这份工作的人甚至不需要一直沿着决策树往下走,就立即被归类为被雇用。在第二种情况下,这个人不符合公司雇佣他所需要的特征。
在运行多个测试用例的预测时,我们可以观察到,预测的值有时会发生变化。这是因为随机森林分类器方法每次运行时都会考虑随机生成的树。这是完全正常的,因为我们在虚构的数据集中只使用了 14 个条目。随着数据集大小的增加,需要考虑的不同组合也越来越多,这可以提高决策树的纯度。
耶!🙌我们刚刚建立了一个决策树,可以根据一个人的属性来预测他是否可以被录用。
希望你们都明白决策树在机器学习领域的重要性。如有任何疑问,请随时通过我的 LinkedIn 联系我。完整的代码可以在我的 GitHub 上找到。
谢谢大家!
决策树:参数优化
当我们开始处理数据时,我们(通常总是)观察到数据中几乎没有错误,比如缺失值、异常值、没有适当的格式等等。简而言之,我们称之为不一致性。这种一致性或多或少会扭曲数据,并妨碍机器学习算法进行正确预测。
之前我们观察了异常值如何影响我们的分析。此外,我们观察到,k-NN 分类器在我们去除异常值并优化其参数后提高了准确性,而对我们来说,我们的决策树分类器表现不佳。一种猜测是,我们没有优化分类器的参数,所以在本文中,我们将看看分类器是否不适合这项任务,或者需要更多的考虑。
如果您还没有阅读这篇文章,您可以在这里找到它:
介绍
medium.com](https://medium.com/@babandeepsingh411993/effect-of-outliers-in-classification-ed7e8b6d39f8)
让我们看看是否可以使用 DT 分类器的参数来提高我们的准确度。
*class* sklearn.tree.**DecisionTreeClassifier**(***, *criterion='gini'*, *splitter='best'*, *max_depth=None*, *min_samples_split=2*, *min_samples_leaf=1*, *min_weight_fraction_leaf=0.0*, *max_features=None*, *random_state=None*, *max_leaf_nodes=None*, *min_impurity_decrease=0.0*, *min_impurity_split=None*, *class_weight=None*, *presort='deprecated'*, *ccp_alpha=0.0*)
判断标准
衡量分割质量的函数。有两个最突出的标准是{ '基尼','熵' }。
基尼指数是通过从 1 中减去每一类概率的*方和来计算的。它倾向于更大的分区。

熵或信息增益将类别概率乘以该类别概率的对数(基数=2)。

我们使用这两个标准并检查它们与 max_depth、minimum_samples_split、minimum_weight_fraction_leaf 的相互作用如何。
最小重量分数叶
要求位于叶节点的权重总和(所有输入样本)的最小加权分数。当未提供 sample_weight 时,样本具有相等的权重。
fractions = [0,0.1,0.2,0.3,0.4,0.5]from sklearn.metrics import accuracy_score
min_weight_fraction_leaf = []
acc_gini = []
acc_entropy = []for i in fractions:
dtree = DecisionTreeClassifier(criterion='gini', min_weight_fraction_leaf=i )
dtree.fit(X_train, y_train)
pred = dtree.predict(X_test)
acc_gini.append(accuracy_score(y_test, pred))
####
dtree = DecisionTreeClassifier(criterion='entropy',min_weight_fraction_leaf=i)
dtree.fit(X_train, y_train)
pred = dtree.predict(X_test)
acc_entropy.append(accuracy_score(y_test, pred))
####
min_weight_fraction_leaf.append(i)
d = pd.DataFrame({'acc_gini':pd.Series(acc_gini),
'acc_entropy':pd.Series(acc_entropy),
'min_weight_fraction_leaf':pd.Series(max_depth)})
# visualizing changes in parameters
plt.plot('min_weight_fraction_leaf','acc_gini', data=d, label='gini')
plt.plot('min_weight_fraction_leaf','acc_entropy', data=d, label='entropy')
plt.xlabel('min_weight_fraction_leaf')
plt.ylabel('accuracy')
plt.legend()
从下图中,我们可以观察到,对于这两个标准,精度都较高,为 0.3。
为什么?
在向叶节点、终端节点中的样本提供权重之后,我们得到了相似的准确度、可能相似的信息增益以及两个标准之间共享的杂质。这意味着我们得到的是纯节点。

最小 _ 样本 _ 分割
分割内部节点所需的最小样本数:
- 如果是 int,那么就把
min_samples_split当做最小数。 - 如果是 float,那么
min_samples_split是一个分数,ceil(min_samples_split * n_samples)是每次分割的最小样本数。
min_samples_split = []
acc_gini = []
acc_entropy = []
for i in range(2,20,1):
dtree = DecisionTreeClassifier(criterion='gini', min_samples_split=i )
dtree.fit(X_train, y_train)
pred = dtree.predict(X_test)
acc_gini.append(accuracy_score(y_test, pred))
####
dtree = DecisionTreeClassifier(criterion='entropy',min_samples_split=i)
dtree.fit(X_train, y_train)
pred = dtree.predict(X_test)
acc_entropy.append(accuracy_score(y_test, pred))
####
min_samples_split.append(i)
d = pd.DataFrame({'acc_gini':pd.Series(acc_gini),
'acc_entropy':pd.Series(acc_entropy),
'min_samples_split':pd.Series(max_depth)})
# visualizing changes in parameters
plt.plot('min_samples_split','acc_gini', data=d, label='gini')
plt.plot('min_samples_split','acc_entropy', data=d, label='entropy')
plt.xlabel('min_samples_split')
plt.ylabel('accuracy')
plt.legend()

从上面的图表中,我们可以看到熵在 min_samples_split 为 7 时工作得更好。
为什么?
从数学上来说,熵考虑了样本和它们的信息增益来建立一棵树。因此,在样本数量的最佳值下,我们可以获得更多关于进一步分割的信息。另一方面,虽然基尼系数在较大的分区中效果最好。我们拥有的数据包含杂质,这些杂质会导致精度随着 min_samples_split 的增加而降低。
最大深度
树的最大深度。如果没有,则扩展节点,直到所有叶子都是纯的,或者直到所有叶子包含少于 min_samples_split 样本。因此,让这两个参数协调工作是一个很好的做法。
max_depth = []
acc_gini = []
acc_entropy = []
for i in range(1,30):
dtree = DecisionTreeClassifier(criterion='gini',max_depth=i )
dtree.fit(X_train, y_train)
pred = dtree.predict(X_test)
acc_gini.append(accuracy_score(y_test, pred))
####
dtree = DecisionTreeClassifier(criterion='entropy', max_depth=i)
dtree.fit(X_train, y_train)
pred = dtree.predict(X_test)
acc_entropy.append(accuracy_score(y_test, pred))
####
max_depth.append(i)
d = pd.DataFrame({'acc_gini':pd.Series(acc_gini),
'acc_entropy':pd.Series(acc_entropy),
'max_depth':pd.Series(max_depth)})
# visualizing changes in parameters
plt.plot('max_depth','acc_gini', data=d, label='gini')
plt.plot('max_depth','acc_entropy', data=d, label='entropy')
plt.xlabel('max_depth')
plt.ylabel('accuracy')
plt.legend()

由此,我们可以清楚地看到,基尼指数跑赢了熵值。
为什么?
如我们所知,基尼系数考虑到了等级的概率,因此,基尼系数的程度在 0 和 1 之间变化,其中 0 表示所有元素都属于某个等级,或者如果只存在一个等级,1 表示元素随机分布在各个等级中。基尼指数为 0.5 表示某些阶层的人口分布均等。
在我们的例子中,我们可以得出结论,在 max_depth = 6 时,我们观察到低杂质节点,从而增加了我们的模型的准确性。
结论
回顾我们上面的讨论,我们可以得出以下结论:
- 基尼指数为我们提供了最高的精确度,最大深度= 6。
- 熵和基尼指数可以在适当选择最小权重分数叶的情况下表现相似。
- 在 min_samples_split 为 7 的情况下,对于更多样本将提供更多信息增益的基本假设,熵的表现优于基尼系数,并且随着杂质的增加,熵倾向于扭曲基尼系数。
因此,采用基尼和 max_depth = 6 作为标准,我们获得了 32%的精度,这比没有使用参数优化提高了 18%。因此,合理地优化参数,将增加模型精度并提供更好的结果。
参考
- https://sci kit-learn . org/stable/modules/generated/sk learn . tree . decision tree classifier . html
- https://blog.quantinsti.com/gini-index/
决策树:理解集成方法的基础
一个伟大的机器学习基础模型,但不是一个伟大的最终模型。

https://imgflip.com/memegenerator/Two-Buttons
集成方法是一种利用决策树优势的极好方法,同时减少了决策树过度拟合的倾向。然而,它们可能变得相当复杂,并可能变成黑盒模型。作为数据科学家和机器学习工程师,我们可以做的最好的事情之一是,当我们调用 sklearn 时,确保我们知道在引擎盖下真正发生了什么。fit()方法。这就是我们今天要用决策树做的事情。
在本文中,我们将回顾:
- 决策树的优点
- 决策树的缺点
- 基于决策树的集成方法
- 决策树如何工作:决策树算法,分裂(选择)标准
决策树有哪些优点?
决策树之所以伟大,有多种原因。我们来看看吧!
- 决策树可用于 回归或 分类,尽管它们更常用于分类问题。一般来说,如果你想对回归模型使用决策树,你应该使用集成方法。
- 决策树是 非参数的 ,这只是一种奇特的说法,即我们不对我们的数据如何分布做出任何假设,我们的模型结构(参数)将根据用户输入和我们样本中的观察结果来确定,而不是根据数据来确定。当我们有很多数据,但没有太多关于数据的知识时,非参数模型是很好的。
- 决策树是 可解释的 ,这意味着在我们建立模型之后,我们还可以对我们的数据进行推断,而不仅仅是预测。在 sklearn 中,我们可以使用来完成这项工作。特征 _ 重要性 _ 属性。
- 决策树是 快速 的,因为它们简单且“贪婪”。虽然在构建最终的可部署模型时,我们可能不会优先考虑速度,但如果我们只是试图构建一个模型来初步了解我们的数据,这可能是一个巨大的好处(下面将详细讨论这是如何工作的!).
- 最后, 数据预处理更容易 使用决策树,因为我们不必扩展我们的数据——在每个节点发生的分裂一次担心一个特征!根据用于确定分裂的算法,分类特征也可以不进行数字编码。然而,使用 scikit-learn 当前的 CART 算法(稍后再介绍更多),您将希望使用推荐的sk learn . preprocessing . labelencorder对分类数据进行预处理。
决策树有哪些缺点?
正如我们所看到的,使用决策树有很多好处…取决于具体情况。如果我们的样本量很小,这可能不是最佳选择;对于回归,如果我们认为我们将预测训练样本所包含内容之外的目标值,这可能不是最佳选择。除了环境因素,决策树和所有模型一样,也有一些缺点。
- 决策树最显著的缺点就是 容易过拟合 。决策树过拟合,因为您可以为训练数据中的每个目标值找到一个叶节点。事实上,这是 sklearn 中决策树分类器 / 回归器的默认参数设置。虽然您可以调整一些超参数,如 max_features、min_samples_split、min_samples_leaf 和 max_depth,但正是由于这一缺点,简单的决策树经常被替换为更复杂的表亲:集成方法。
- 决策树也是 局部优化 的,或者说是贪婪的,这只是意味着它们在任何给定的节点决定如何分裂时没有提前考虑。相反,进行分割是为了最小化或最大化所选择的分割(选择)标准——基尼或熵用于分类,MSE 或 MAE 用于回归——在该分割处,我们将在后面详细讨论。
- 由于分裂的贪婪本质, 不*衡类 在处理分类时也对决策树提出了一个主要问题。在每次拆分时,树决定如何最好地将类拆分成接下来的两个节点。因此,当一个类具有非常低的代表性(少数类)时,这些观察值中的许多可能会在多数类节点中丢失,然后对少数类的预测甚至会比它应有的可能性更小,如果有任何节点预测它的话。
基于决策树的集成方法
现在我们已经对简单决策树的优缺点有了很好的了解,我们将讨论是什么使它们成为集成方法的一个很好的基础估计。基于决策树的一些最流行的集成方法是:
- 随机森林(回归器/分类器)
- 极度随机化的树(回归器/分类器)
- 装袋(回归器/分类器)
- 自适应助推器(回归器/分类器)
- 梯度增强(回归器/分类器)
- 回归器/分类器
所有这些集成方法都采用决策树,然后应用 bagging (bootstrap aggregating)或 boosting 作为减少方差和偏差的方法。要快速了解集合方法以及打包和提升技术,请查看我在大会上为数据科学课程制作的幻灯片:
决策树如何工作
如果没有例子,很难谈论决策树是如何工作的。这张图片取自 sklearn 决策树文档,是 sklearn Iris 数据集上决策树分类器的绝佳代表。为了更容易理解,我添加了红色、蓝色和灰色的标签。

原图:https://scikit-learn.org/stable/modules/tree.html;我自己的蓝色、红色和灰色标签
我们在这里看到,每个拆分都是二进制的,或者只拆分成两个子节点。虽然这对于决策树来说不是必须的,但是许多实现,包括 sklearn 的,都局限于二进制分割,因为考虑任何更大的东西计算量都太大——树永远不会适合。这也不会有很大的不同,因为二进制分割可以通过简单地嵌套两个二进制分割获得与多路分割相同的结果!然而,由于决策树算法的复杂性,当仅限于二进制分割时,所进行的分割计算可能会导致与允许更多分割的算法略有不同的分割。同样,限制二进制分割不是主要问题,只是需要考虑的事情。所以最后:树如何决定从哪里分裂??
决策树算法
“决策树算法”可能听起来令人生畏,但它只是决定如何构建树的数学(“简单”…我们将进入它!).目前在 sklearn 中实现的算法被称为“CART”(分类和回归树),它仅适用于数字特征,但适用于数字和分类目标(回归和分类)。在每个节点上,它确定将为模型产生“最大信息增益”的特征和该特征的分割阈值。这个“信息增益”是基于用户指定的分割标准来测量的。
如果你喜欢数学,这里有一个信息增益的公式,取自 sklearn 文档(其中 G =信息增益,n =阈值左侧/右侧的数据点数,Nm =数据点总数,H =选择的分裂标准函数,Q =节点 m 的数据,θ=被评估的特征和阈值):

https://scikit-learn.org/stable/modules/tree.html
但基本上,你需要知道的是“信息增益”衡量给定的分裂如何分裂我们的数据,以使每个子节点中的数据点的目标值最同质(分类)或彼此最接*(回归)。
那么,在每个节点上,特征和分割阈值是如何选择的呢?这是一个好问题,回答有些复杂!一般来说,该算法将扫描每个特征的每个可能的阈值分割,计算每个不同分割的“信息增益”,然后选择产生最高信息增益的分割(如何测量取决于下面描述的分割标准)。现在,当特性是一列 1 和 0,或者一组离散的选项时,这更直观,因此几乎没有可能的拆分需要考虑。然而,当我们有一个连续的数字特征,它变得更加复杂。
sklearn 文档和 Google 搜索“CART algorithm decision trees how to find split threshold for continuous variables sk learn”的时间未能让我发现连续变量的分裂阈值是如何确定的——是不是每个唯一值都被视为分裂点,从而以指数方式增加了计算负载?如果唯一值比设定的箱数多,这些值是否被装入设定数量的箱中?或者也许算法只是在*均值、中间值或正中间分裂!
经过几个小时的搜索,这篇来自 2014 年的 Stackoverflow 评论终于回答了这个问题:当确定连续变量的分裂阈值时,sklearn 决策树算法(CART)不支持!相反,它会执行计算量很大的任务来检查每个可能的分裂,也就是说,它会对该特征的所有值进行排序,然后查找相邻值之间的每个*均值,并查找该分裂的信息增益得分(除非两个值之间的差距小于 1e-7,这是一个任意的小步骤)。
所以现在我们知道了在确定分割时要评估什么,这就引出了一个问题:我们如何决定在每个节点使用哪个特征和阈值:分割标准!
分割(选择)标准
根据什么特征和该特征的什么值来分割节点取决于用户指定的标准:用于分类的 gini 或熵,用于回归的 MSE 或 MAE。虽然我们可以详细讨论所有这些,但是对于本文来说,最有帮助的是考虑所有这些标准都是衡量一个分割在根据目标值创建最同质的子节点时有多大帮助。
对于分类,gini 和熵使用不同的公式来评估“如果我们使用这种拆分,每个类的多少个观察值将被拆分到每个子节点中?”他们各自的公式来自 sklearn 文档,同样,对于那些有数学倾向的人来说:
基尼

https://scikit-learn.org/stable/modules/tree.html
熵

【https://scikit-learn.org/stable/modules/tree.html
另一方面,对于回归问题,MSE(均方误差)和 MAE(*均绝对误差)评估该节点中的每个目标值与每个子节点的*均目标值的接*程度,MSE 将较大的误差加权为比较小的误差更差。这些也是线性回归中损失函数的常用指标。来自 sklearn 文档的公式如下:
均方误差

https://scikit-learn.org/stable/modules/tree.html
*均绝对误差

https://scikit-learn.org/stable/modules/tree.html
这样你就知道了——决策树是由什么组成的,因此,它也是我们所钟爱的集成方法的基础。如果你已经做到了这一步,感谢你坚持和我在一起,或者跟随你的好奇心,或者为完成你可能正在做的任何项目而奉献。我希望这份关于决策树及其底层工作的概述能对你继续提高思维和数据科学技能有所帮助!数据处理愉快!
来源
https://sebastianraschka . com/FAQ/docs/parametric _ vs _ nonparametric . html
https://medium . com/@ dataakkadian/what-are-parametric-vs-nonparametric-models-8 BFA 20726 f4d
https://sci kit-learn . org/stable/auto _ examples/预处理/plot _ 离散化. html
https://stack overflow . com/questions/25287466/sklearn-ensemble-and-trees 中连续变量的宁滨
决策树回归器—停止用于未来预测!
内部 AI

Scikit-learn 是 Python 中最著名的机器学习库之一。它提供了几种分类、回归和聚类算法,在我看来,它的主要优势是与 Numpy、Pandas 和 Scipy 的无缝集成。
Scikit-learn 由开发人员编写得非常好,只需几行代码,我们就可以通过许多不同的算法来检查模型预测。我觉得有时候,Scikit-learn 的这种优势会在不经意间对其不利。机器学习开发者。经验相对较少的人在没有掌握特定算法的显著特征和局限性的情况下实现不适当的预测算法。
在本文中,我将讨论为什么我们不应该使用决策树回归算法来进行涉及外推数据的预测。
目标
我们有豌豆从农场采摘到 1142 天的铁、钙和蛋白质含量。让我们假设,与蛋白质含量相比,测定铁和钙的含量更容易、更经济。
我们将使用这些数据来训练决策树回归算法,然后根据与铁含量、钙和天数相关的新数据点来预测蛋白质含量。
样本数据文件
我认为数据文件是不言自明的。这些行显示了自收获以来豌豆的铁、钙和蛋白质含量。

步骤 1——我们将导入包 pandas、matplotlib 以及 DecisionTreeRegressor 和 NumPy,我们将使用它们进行分析。
from sklearn.tree import DecisionTreeRegressor
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
第二步- 将完整的数据样本数据 excel 文件读入名为“数据”的 PandasDataframe 中。
data= pd.read_excel("Peas Nutrient.xlsx")
我不会关注初步的数据质量检查,如空白值、异常值等。和各自的修正方法,并假设不存在与差异相关的数据序列。
步骤 3- 我们将把完整的数据集分成两部分,即训练和测试设备。顾名思义,我们将使用训练数据集来训练决策树回归算法,并根据测试集中的数据将蛋白质预测与实际含量进行比较。
在下面的代码中,从第 1 天到第 900 天的数据记录被分割为训练数据,从第 901 天到第 1142 天的数据记录被分割为测试数据。
Training_data= data[:900]
Test_data=data.loc[901:1142]
第四步- “经过天数”、“铁含量”、“钙含量”是用于预测的自变量。预测的“蛋白质含量”是因变量。通常,自变量用“X”表示,因变量用“y”表示。
在下面的代码中,“蛋白质含量”数据列从数据帧中删除,剩余的数据(即独立变量数据点)被声明为 X_train。类似地,除了“蛋白质含量”之外的所有数据列都被删除,并声明为 y_train。
X_train=Training_data.drop(["Protein Content "], axis=1)
y_train=Training_data.drop(["Days Passed", "Iron Content " ,"Calcium Content "], axis=1)
在下面的代码中对测试数据集重复相同的过程,即从第 901 天到第 1142 天的值,
X_test=Test_data.drop(["Protein Content "], axis=1)
y_test=Test_data.drop(["Days Passed", "Iron Content " ,"Calcium Content "], axis=1)
步骤 5- 用训练数据集训练决策树回归器模型。此外,检查分数以了解算法在该数据上训练得有多好。
tree_reg = DecisionTreeRegressor().fit(X_train, y_train)
print("The model training score is" , tree_reg.score(X_train, y_train))
满分 1.0 本身就说明模型的过拟合。

步骤 5- 为了解决在训练模型期间由于树的无约束深度而导致的过度拟合,我们将设置最大深度为 4 的约束。
tree_reg = DecisionTreeRegressor(max_depth=6).fit(X_train, y_train)
print("The model training score is" , tree_reg.score(X_train, y_train))
这解决了模型对训练数据的过度拟合,并且模型准备好基于测试数据点来预测蛋白质含量。

步骤 6- 在下面的代码中,基于各自的“经过天数”、“铁含量”和“钙含量”数据,预测测试数据集(即从第 901 天到第 1142 天)的“蛋白质含量”。
y_pred_tree = tree_reg.predict(X_test)
步骤 7- 我们将通过决策树回归模型绘制预测的蛋白质含量,并与第 901 天至第 1142 天的测试数据集中的实际蛋白质含量进行比较。
plt.plot(X_test["Days Passed"],y_test, label="Actual Data")
plt.plot(X_test["Days Passed"],np.rint(y_pred_tree), label="Predicted Data")
plt.ylabel("Days Passed")
plt.xlabel('Protin Content (in Grams)')
plt.legend(loc='best')
plt.show()

我们可以看到,在具有 0.93 分数的训练数据集中训练得相当好的决策树回归器模型在预测测试数据上的蛋白质含量方面失败得很惨。该模型预测所有天的蛋白质含量都相同,约为 51.34。
我们不应该使用决策树回归模型进行涉及外推数据的预测。这只是一个例子,我们机器学习从业者的主要收获是在开始建模之前考虑数据、预测目标、算法的优势和局限性。
在为机器学习监督算法选择独立变量时,我们可能会犯类似的错误。在文章中,“如何为机器学习监督算法识别正确的自变量?”我已经讨论了一种结构化的方法来识别适当的独立变量,以做出准确的预测。
用代码破译失传的语言

来自皮克斯拜的本·伯顿的图片
机器学习正在帮助语言学
语言就像人一样,他们出生,生活,死亡。然而,由于一些占主导地位的语言,一些语言在其自然寿命之前就消亡了。当主导语言在世界上变得更加普遍时,使用人数较少的地方语言就会灭绝。比如你在用现代最通用的语言读这篇文章,虽然不是我的母语!
一种语言是如何消亡的?
一种语言灭绝的第一个迹象是孩子们只在家里说他们父母的语言。他们在所有的社会、教育和职业生活中使用主流语言。
一两代人之后,这种语言只有老人说。如果孩子们只和他们的祖父母说一种语言,这种语言就有灭绝的危险。

死亡、灭绝和失传的语言
死语言不是任何社区的母语。拉丁语是一种死语言。有些人懂拉丁语,但没有一个国家或社区的母语是拉丁语。
一种已经灭绝的语言是一种不再有人使用的语言。即使没有人说一种已经灭绝的语言,也有那种语言的书籍、论文和纪念碑,我们知道如何阅读和学习。目前,已知的灭绝语言有 573 种。
失传的语言是一种灭绝的语言,我们知道它存在过,但我们不知道如何阅读。绝大多数灭绝的语言都是失传的语言。
发现一种语言
语言研究者 David Graddol 估计,到 2050 年,90%的现有语言将会灭绝。当一种语言消失时,整个文化也随之消失。至少有 12 种失传的语言等待被编码,但没有一种语言像古埃及语那样幸运。他们没有罗塞塔石碑!

大英博物馆中的罗塞塔石碑,图片由来自 Pixabay 的Kris sard拍摄
因为对一种语言进行编码是一个耗时的过程,人类花费了几十年的努力来发现语言和这些语言背后的文明。大多数古代文字没有空格和/或标点符号。语言学家可能要花一辈子的时间才能从这些古代文字中找出一种语言。自然语言处理(NLP)方法是否有助于提高编码灭绝语言的速度和准确性?

由 Sumeyye Akin 创作的哥特式书法,由作者创作的图片
人工智能破译一种失传的语言
来自麻省理工学院计算机科学和人工智能实验室(CSAIL) 的 Enrico Santus,Jiaming Luo,Frederik Hartmann,,Regina Barzilay 开发了一种新算法来破译文字中丢失的语言。
最*的工作
机器学习算法可以通过将丢失的语言与现存的语言联系起来,成功地破译这些语言。通过识别最接*的现存语言,破译过程变得很容易。例如,Ugaritic 语言是在希伯来语的帮助下解决的,因为人们知道它们来自同一语系。这被称为“基于同源词的解读”
最*工作的问题
如果失传语言的语系无法识别,科学家怎么办?例如,关于伊比利亚语的相*已知语言就没有共识。它可以是希腊语、拉丁语或巴斯克语。现有的算法在破译伊比利亚语时不能正常工作。
新方法
CSAIL 团队开发的模型可以解决这个问题。因为它们的模型提供了丢失语言中的欠切分单词和已知语言中的词汇。手稿中丢失的语言不被认为与任何现代语言相似。相反,该模型试图将丢失文本中的跨度与已知标记进行匹配。
方法
该模型被设计成适用于伊比利亚等语言。然而,由于缺乏地面真实,在实验设置中使用了 Gothic 和 Ugaritic。该模型被应用于破译的语言,以便能够检查模型的性能。
这个模型的副产品
该模型不假设语言之间有任何相似之处。令人惊讶的是,它找到了一种关系的衡量标准,并识别出与失传语言本身最相似的语言。
未来的工作
Regine Barzilay 和她的团队希望将他们的工作扩展到从上下文中寻找单词的含义,即使他们不知道如何阅读它们。
结论
该模型提出了一种从非分离文本中提取相关词的解码模型,而不需要假设丢失语言和已知语言之间的相似性。在 Gothic、Ugaritic 和 Iberian 上的结果表明,该模型可以有效地处理欠切分文本,即使丢失的语言与任何已知语言都不相关。
当失落的语言被加密,失落的文明也被发现!
用机器学习和神经科学解码大脑信号
成为 X 教授,解开我们心灵的秘密

乔希·希尔德在 Unsplash 上的照片
在 x 战警漫画中,查尔斯·泽维尔教授是最强大的变种人之一。他拥有读心术和移动物体的精神力量。
想成为 X 教授?请继续阅读!
我们的大脑是一个强大的器官,它是人类神经系统的指挥中心。它像一台大电脑一样工作,它发送、接收和处理信息。
如果我们能拦截这些信号呢?通过创造一个读取思想的装置,你可以释放心灵感应的力量!
一个脑机接口允许使用我们的大脑信号解码我们的意图。这意味着你甚至不需要移动肌肉!
想象一下,如果我想发一条短信。我开始盯着键盘,在我想输入的字母上。我的手机开始输入我正在思考的单词和句子!
这看起来像科幻小说,你认为人类离实现这样的壮举还有几年的时间吗?几十年来,科学家一直在开发和完善这项技术。
在这篇文章中,让我与你分享令人兴奋的研究,我们可以通过盯着闪烁的灯光来控制外骨骼!
枕叶
人脑是一个惊人的三磅重的器官,控制着我们所有的身体功能。它处理我们所有的思想,它是人类智力、创造力、情感和记忆的神经生物学基础。我们的大脑分为几个部分,每个部分都有一个主要功能。

大脑的侧面,显示了 4 个脑叶[ 来源
在这个实验中,我们的重点是枕叶。那是我们的视觉处理中心,处理我们视觉的部分。它处理并使我们的大脑能够识别我们正在看的东西。
我们可以从大脑中收集的数据类型
脑机接口 (BCI)的目的是在大脑和外部设备之间建立直接的通信通道。这使得它的用户能够通过大脑活动与电脑互动。
BCI 不像大脑那样是一个读心术装置。相反,它检测大脑发出的能量的变化。人类大脑包含大约 860 亿个神经元,每个神经元都与其他神经元相互连接。每当我们思考或移动肌肉时,这些神经元都在工作,被能量激活。BCI 能识别大脑中的这些能量模式。

用脑电图监测棘波放电[ 来源
脑电图 (EEG)是一种记录大脑信号的流行技术。它是非侵入性的,所以我们不需要切开我们的头骨来收集我们的大脑信号。
脑电图通过放置在头皮上的一系列电极记录大脑产生的能量。这包括一个人戴着脑电图帽,电极放在特定的点上。这些电极检测大脑活动,即从我们的大脑发出的电能。
在这个实验中,我们想要记录与我们眼睛正在看的东西相关的大脑信号。通过将电极放置在枕叶区域,电极将从我们所看到的东西中获取信号。在这种情况下,闪烁的灯光。这种类型的脑电信号称为稳态视觉诱发电位。
稳态视觉诱发电位
稳态视觉诱发电位 (SSVEP)是当我们看到闪烁的东西时产生的信号,通常频率在 1 到 100 Hz 之间。在这个实验中,这些闪烁的灯是闪烁的 LED 灯。这些闪烁的灯是“刺激物”。
考虑一个脑机接口系统,其目标是解码用户输入的两个可能选项中的一个,即“左或“右”。有两个刺激,一个用于选择“左”选项,另一个用于选择“右”。
这两种刺激以不同的频率闪烁,11 Hz 代表“左转”;而“右转为 15 Hz。用户通过关注其中一个刺激来选择选项。例如,通过聚焦“左”刺激,来选择“左选项。
当用户专注于一种刺激时,该特定刺激的频率可以在枕叶处被拾取。通过从 EEG 信号中提取刺激的频率,我们可以确定用户正在关注哪些灯。这就是 BCI 系统如何将 SSVEP 大脑信号翻译成外部设备的指令。
这个视频展示了一个现场演示,展示了我们的眼睛所关注的东西是如何影响 SSVEP 信号的。
实验装置
韩国大学设计了一个使用 SSVEP 控制下肢外骨骼的实验环境。用户可以通过将注意力集中到所需的刺激来控制外骨骼。
用户可以选择五种可用操作之一来操作外骨骼。这对应于以不同频率闪烁的五个发光二极管。
- 向前走(9Hz)
- 左转(11Hz)
- 向右转(15Hz)
- 站立(13Hz)
- 坐下(17Hz)

受试者穿着外骨骼,专注于视觉刺激发生器的 LED 摘自论文
如果打算向前移动,用户关注以 9 Hz 闪烁的 LED 二极管。同样,通过聚焦以 15 赫兹闪烁的 LED 二极管,它将操作外骨骼向右转。
在实验过程中,有语音指令来指导用户。他们的任务是按照给出的指令,通过聚焦相应的 LED 灯来操作外骨骼。

使用 8 个通道进行 SSVEP 采集的 EEG 通道布局[摘自论文
为了构建监督学习分类器,收集的脑电信号是输入数据,分配的任务是标签。对于这个实验,作者在 EEG cap 上选择了八个电极,这对应于输入数据中的八个通道。
他们还执行了快速傅立叶变换,将信号从时域转换到频域。这导致输入数据中有 120 个样本。因此,输入数据是一个 120x8 尺寸的信号。
卷积神经网络分类器
No-Sang Kwak 等人提出了一种使用卷积神经网络的鲁棒 SSVEP 分类器。在论文中,他们将其命名为 CNN-1。它有两个隐藏层,内核大小分别为 1x8 和 11x1。接下来是具有 5 个单元的输出层,代表外骨骼运动的五种可能动作。学习率为 0.1,权重初始化为正态分布。

CNN-1 架构。由两个卷积层和一个输出层组成[摘自论文
作者还实现了另外两个神经网络和三种信号处理方法,以与 CNN-1 进行性能比较:
- CNN 架构#2 (CNN-2) :类似于所描述的 CNN 架构,但是它在输出层之前包括一个附加的 3 单元全连接层
- 前馈(NN) :一个简单的 3 层全连接前馈神经网络
- 典型相关分析(CCA) : 典型相关分析是寻找目标频率和信号之间相关性的流行方法。CCA 一直是 SSVEP 分类的首选方法
- 多元同步指数(MSI) : 多元同步指数估计两个信号之间的同步,作为解码刺激频率的指数
- CCA + k *邻(CCA-KNN) :与 k *邻的典型相关分析
这些方法用于比较上述 CNN-1 架构的性能。我没有提供每个分类器的细节,因为 CNN-1 具有最好的性能,这是我们的重点。
估价
作者用 13500 个训练数据和 1500 个测试数据进行了 10 重交叉验证。下表显示了每个分类器的分类精度。

受试者的 10 倍交叉验证结果,比较不同的分类方法[摘自论文
该表显示,CNN-1 的性能优于其他神经网络架构。CNN-1 也比 CCA 表现得更好,CCA 是用于 SSVEP 分类的流行方法。总的来说,神经网络的结果比 CCA 更稳健,因为 CCA 表现出明显较低的性能。
深度神经网络通常在处理大量数据时表现更好。找出超越传统方法所需的数据量。作者验证了不同训练样本大小的性能。

10 倍交叉验证结果,改变训练数据量,比较不同的分类方法【摘自论文
CNN-1 在每个数据量上都优于其他神经网络。然而,对于少于 4500 个训练数据样本,CCA-KNN 显示出更好的分类性能。

图欣·乔杜里在 Unsplash 上拍摄的照片
总结
在这项研究中,目标是建立一个具有深度学习分类器的鲁棒 BCI 系统。卷积神经网络在 SSVEP 分类中表现出良好的性能。
BCI 系统有很大的潜力来帮助残疾人控制设备,如外骨骼(如钢铁侠)或轮椅(如 X 教授)。
但是构建一个可靠的 BCI 系统对 T4 来说是一个挑战,要将这些设备从实验室推向大众市场还需要付出巨大的努力。
40%的吸尘器,40%的看门人,20%的算命师。
towardsdatascience.com](/data-scientist-the-dirtiest-job-of-the-21st-century-7f0c8215e845) [## 脑-机接口中的深度学习
推动该领域发展的现状和挑战
towardsdatascience.com](/deep-learning-in-brain-computer-interface-f650d00268d0) 


参考
Kwak,N.S .,Müller,K.R .和 Lee,S.W .,2017 年。用于流动环境下稳态视觉诱发电位分类的卷积神经网络。
林,张,吴,魏,高,2006。基于 SSVEP 的 BCIs 基于典型相关分析的频率识别。
张,杨,徐,程,姚,2014。基于 SSVEP 的脑机接口频率识别的多元同步指数。
BTS 的“灵魂地图:7”中的数据科学
使用“Spotify”和“Genius”web API 的数据分析 BTS 的新专辑。
BTS 母公司的名字“大热门娱乐”中的形容词似乎不足以描述他们创造的全球超级明星。称 BTS 只是大而成功是完全荒谬的,传奇和开创性可能会接*。事实上,BTS 音乐会上的歇斯底里是如此之大,以至于根据纽约时报的报道,他们音乐会上的噪音水*“远远超过了永久性听力损失成为严重问题的噪音水*”。来自首尔的乐队为韩国的 GDP 贡献了巨大的46.5 亿美元,超过了国家航空公司,这是一个滑稽的讽刺,因为 BTS 实际上不能飞大韩航空。BTS 军(青春可爱代表 MC)的一些 sasaeng 粉丝非法获取了他们的航班详情,并在飞行过程中对他们穷追不舍,导致他们无法乘坐任何商业航空公司的航班。
如果 BTS 可以时间旅行到 7 年前,在他们出道的顶点,为他们将要打破的每一个里程碑在许愿井里轻弹一枚硬币,这个井将会窒息。他们今天的现实也许比七重奏所能想象的任何梦想都要大。在这种激烈的超级明星和点金术的水*下,他们带着他们的第四张 EP -《灵魂地图:7》卷土重来。在专辑发行前的几个月里,BTS 推广了多首单曲,在标志性的交通枢纽——纽约中央车站(Grand Central Terminal)为《今夜秀》( The Tonight Show)表演,在詹姆斯·柯登的《拼车卡拉 ok 》( car pool Karaoke)的一辆迷你面包车中亮相,接受了多次采访,并在美国和韩国精心进行了推广。事实上,该小组的马克奈jung kook 甚至提高了他的英语技能来表达对他的美国军队的爱和感激。这张专辑收到了 400 万张预购单,一经发行就高居各大排行榜榜首。
新专辑的任务是承认和利用他们的成功故事,但也在面对前所未有的媒体审查时锻造乐队的前进道路。这是一个关于他们自己的爱情故事,一个理所应当的我们做到了顿悟,伴随着一声责任的叹息,承认他们现在正在进入未知的水域——以前没有人去过的地方,唯一要打破的记录是他们自己创造的。
BTS 主要用朝鲜语演唱他们的歌曲,而且几乎立刻就可以在网上找到翻译的歌词,供他们的国际观众翻译。我接入了 genius Web API 来了解每首歌曲的注释数量。我在 R 中使用了' GenuisR '包,它提供了一个访问 Genius web API 的简单接口。制作client_id和client_secret所需的 API 客户端访问管理页面可以在这里找到。下面是标注轨迹数据的小窥——
**
灵魂地图的天才注解:7 s 来源于天才 API
为了可视化数据,我使用了 Highcharts JS 包的 R 包装器highcharter()。你可以从我之前的一篇文章这里阅读更多关于 R 中highcharter()的应用。不出所料,分析最多的歌曲是 BTS 迄今为止最热门的歌曲——《恋爱中的男孩》(ft。哈尔西)“后跟”上(英尺。Sia)”。接下来的两首歌是比较内省的,属于组合的说唱歌手。郑号锡的“Outro: Ego”是对他们旅程的致敬“不是郑号锡的生活,而是郑浩石的生活闪过”,当童年的照片出现时,他说,菅义伟的感人表演是“插曲:阴影”。“名声就像一个影子,”菅义伟在 2018 年韩国超级巨星首次英国演出前告诉 卫报 。“有光明,也有黑暗;它会一直跟着你,而不是你可以逃避的东西。”他带着这种想法,并使它成为他火热的说唱专辑《开场》中的主要克星。
“我想成为说唱明星/我想成为第一,”他在愤怒吞没的布道中开始,公然展示他的野心。但现在,这位一度苦苦挣扎的制片人渴望的成功已经真正得到了保障,这并不像他想象的那样美好。“我害怕,高飞是可怕的,”他辞职。没人告诉我这里有多孤独。”回到名义阴影的想法,他后来从它的角度说唱,警告自己:“我们是一个整体,有时我们会发生冲突/你永远不能打断我,这你必须知道。歌词让人想起阿姆罗《差点成名》中有先见之明的警告“小心你许下的愿”,甚至还有阿姆罗在中描绘的【坏蛋】中的“一个艺术家//饱受折磨、被困在自己的图纸中的悲惨肖像”。**
这个组合的每个成员都有一个故事,他们自己独特的风格和音乐要求这张专辑慷慨地为每个人留出空间。它充满了成员之间的独唱和二重唱,允许他们从自己的镜头讲述他们的故事,并导致音域和流派的混杂。“这种类型是 BTS”——郑国、和金最*说。为了对旋律中这些深奥的潮起潮落进行分类,我根据它们的“能量”和“价”将 20 首歌的 EP 分成了四个桶,即来自 Spotify Web API 的音乐积极性声音分数。
为了访问 Spotify 应用程序接口,我使用了“Spotifyr”包提供的接口。Spotify web developer API 访问需要一个唯一的client_id和一个client_secret,可以在这里制作。Spotify 创建的“Spotify for Developers”网站对于热衷于使用 Spotify 界面的开发者来说也是一个极好的资源。你也可以把你自己的 Spotify 账户和你的播放列表链接起来,对你实际听的内容做一些书呆子式的分析。你可以在 R 这里、这里、这里和这里找到一些整合 Spotify web API 的精彩用例。
下面是 Spotify 的一些声音属性及其得分的一小部分-

为了创建歌曲的可视化效果,我在 R 中使用了精彩的 ggplot2 ,这是一个基于图形语法的声明式可视化创建系统。图表中的分散气泡根据它们主要代表的情绪进行着色,并根据情绪的强度来确定大小。
“我认为把音乐分成不同的类型没什么意义”,菅义伟曾表示。他的《插曲:影子》在音乐积极指数上生闷气,得分为 0.15。哈尔西“在 0.75 的时候高兴地跳起来,这个组合叛逆地自由奔跑——显然解散了流派定义的一致性。

追踪来源于 Spotify API 的分类基础能量和化合价分数
《CREA》杂志的编辑在报道了这个团体后曾宣称,“BTS 彼此深爱着对方,他们不知道该怎么办。”。他们分享的这种自然的镜头给了粉丝一些支撑,并有助于跟上他们狂热的工作日程。V 和姬敏的二重唱《老友记》被粉丝亲切地称为Vimin,是对他们友谊的致敬——从同学和热门练习生到最大的音乐乐队的一部分,他们确实走过了很长的路。“有一天当这种欢呼*息,留在我身边”,他们许下承诺,像满怀希望的未结婚的少年恋人,不为前方的世界所知,低吟着,“为了永恒,留在这里”。**“我记得我们的制服,我们的回忆,我们的每一部电影”他们对自己的童年时光致以甜蜜的敬意。这首歌是有毒的男子气概和大男子主义的对立面,是一个令人愉快的清新故事,讲述了一个毫不掩饰的老派兄弟关系。
在能量和效价上得分都很高,最快乐曲目奖授予了《假面》中的泡泡糖流行歌曲《爱你的男孩》。哈尔西”,目前是 24 小时内观看次数最多的 YouTube 视频的记录保持者。而 Jungkook 的《我的时间》和金的《月亮》,一首献给粉丝的歌——“你是我的地球,我看到的都是你”,得分在清冷宁静的桶里。

数据来源于 Spotify API

数据来源于 Spotify API

数据来源于 Spotify API
当 Big Hit 创始人 Bang PD 首次招募团队的领导者和说唱歌手(当时被称为说唱怪物)时,其意图是创建一个以嘻哈为中心的团队。他只是在判断了市场情绪和商业可行性后才转而创建偶像团体,导致许多倾向于嘻哈的练习生退出公司。RM 和 Suga 该组合目前的说唱歌手保持坚定和忠诚。现在有了“MOTS 7”,他们出道 7 年后转变成一个商业上可行的偶像团体似乎已经完成。为了可视化 BTS 专辑中的声音元素的过渡,我使用 r 中“ggridges”包中的geom_ridgeline()函数创建了 ridgeplots ,然后我为这张专辑使用了“speechness”、“ Acousticness ”和“ Liveness ”评分,并将其与他们的首张专辑“2 Cool 4 Skool”并列。web developer API 将speechineness定义为音轨中口语词的存在, liveness 定义为歌曲被现场听众录制的概率,而 acousticness 定义为歌曲是有声歌曲的可能性。进化是清楚的。尽管《MOTS 7》拥有多达 20 首歌曲,而他们的首张专辑中只有 9 首,但这张专辑的整体活跃度和音质得分明显较低。整张专辑中充斥着刺耳的假声、混乱的弦乐、射击效果和轻快的合成音,这证明了有多达 74 人被列为作家或制作人,厨房里有一大群令人眼花缭乱的厨师。
大多数艺术家都会进化。就连甲壳虫乐队也不得不从《爱我吧》过渡到《嘿,裘德》。艺术是生活的反映,随着生活的变化,艺术家创作的艺术也在变化。但是这张专辑中的一些歌曲缺乏 BTS 专辑中通常期望的真实性&真实性,尤其是因为他们主要在这些属性上给自己打上了烙印。这似乎是该公司为品牌激活的最新尝试,一些数字是专门为他们售罄的体育场巡演和西方观众制作的。从建造 BTS 主题酒店,创作电影纪录片到制作基于 BTS 成员生活的 K 剧,Big Hit 似乎在利用一切可以携带 BTS 标签的东西,这张专辑中的一些歌曲似乎就是为了做到这一点——过度生产的诅咒放大了这一点。这是一个世纪以来的难题,路易莎·梅·奥尔科特在《小妇人》中把她的女主角卖给了婚姻,这是该书在 19 世纪 60 年代获得商业可行性的必要条件,我真的希望我们生活的现代进化将允许 BTS 就这样放过他们的女主角。**
我在 2011 年开始积极听 K-Pop,2NE1,Big Bang 和 Shinee 统治着这个行业,不可能不落入他们的陷阱。9 年后,2NE1 的 Bom 被指控贩毒,Big Bang 的 Seungri 卷入卖淫丑闻,Shinee 的主唱 Jonghyun 去年悲惨地自杀。就在最*,Exo-M 成员陈透露他之前未公开的女友和现在的未婚妻怀孕后,据报道收到了死亡威胁,许多 K-pop 粉丝称这是绝对的背叛。K-pop 行业的压力很大,BTS 目前处于第一线。他们经常被当成男性瓷娃娃,他们的公司决定他们头发的颜色,并派保安队陪他们去洗手间,甚至连最基本的隐私都不给他们。在一个过度净化和自负的 K-pop 产业中,V & Suga 对与名声和不断侵犯隐私作斗争的坦率令人耳目一新。在他们离开去服义务兵役之前,他们以七重奏的身份制作了最后几张专辑,我希望 BTS 的信息能更深入,不要被他们众多的制作人和词曲作者过滤掉。
**Suga 想要什么,Suga 就得到什么。这个曾经在首尔苦苦挣扎的送货员已经公开对 BTS 的下一步行动雄心勃勃。当 BTS 刚刚出道时,他宣布在韩国的奥林匹克体育场销售一空,billboard top hot 100 当没有任何 K-pop 团体接*时,在格莱美上表演,他说接下来,房间里荒谬的喘息声。他们以惊人的方式完成了这一切。如果尊敬的规则曾经存在,BTS 不知道他们。下一步是什么?菅义伟最*说,首尔的反叛分子获得了格莱美奖。格莱美家离现在还有 9 个月,如果这次菅也能如愿以偿,我们将拭目以待。
….
使用人工智能解码 cxo
基于人工智能的洞察用例
这已经是忙碌的一天,你突然有机会明天会见一位财富 100 强全球 CDO(首席数字官)。一生中只有一次机会来推销你的主张,但你没有时间或带宽。你将如何准备?我们正在进入人工智能时代…考虑到时间紧迫,有没有不同的准备方式?
与过去不同的是,今天有大量的个人和公司数据。
这里有一个框架来帮助准备…
- 第一级:你可以预期 CDO 会像其他 CDO 一样思考……所以让我们来研究一下 CDO 在想什么。数以千计的首席信息官/ CDO 杂志文章迎合了他们的思维过程,人们可以将每篇文章矢量化,并找出主题
- 第二级:顶级首席执行官通过采访、获得文字记录和演讲,留下了他们思维过程的巨大足迹。让我们仔细分析其中的 100 条,以了解特定个人的主要优先事项是什么。这也能让你了解 CDO 在 1 级列表中关注哪些主题
- 第三级:CDO 将处理直接的客户问题。跨多个*台(例如:Twitter)有大量的客户反馈。利用 API,并使用机器学习技术对提出的问题进行分类。这将指出 CDO 面临的一系列紧迫问题
下面是如何简化成一个图表,以便快速使用。这是美国一家顶级航空公司的 CDO。

CDO 优先考虑建立一个个性化和旅行分析应用程序,但似乎正在努力解决一些问题,如航班延误时缺乏沟通,优质客户的等待时间,令人困惑的网站和 wifi+机舱娱乐问题,所有这些都与个性化密切相关。答对了,这是谈话中需要提到的吗?
CDO 被用作一个例子,但这个框架适用于任何 CXO。下面是一家发展最快的时装零售商的首席执行官的例子。这里的重点是了解公司对 AI 的关注点是什么。

这位首席执行官专注于利用人工智能来构建新的设计和虚拟现实,以改变客户体验。他们甚至与 AI/ML 建立了合作关系,让该公司的工程师重新获得技能。
这是另一个了解全球医疗保健专业的地理和主题重点是利用收入成绩单的例子。

这位首席执行官总是谈论医疗保健,但越来越多的“数字”和“机器人”进入了对话。中国仍然是一个主要的关注点。
你肯定会遇到这样的情况:这样的数据足迹不存在,或者公司是 B2B 的,不是面向消费者的。在这种情况下...
- 四级:每个 CXO 都想知道他/她的客户的消费者在想什么,因为这会影响他/她的客户。“客户的消费者”观点也是如此。以下是汽车零部件供应商 CXO 根据其客户的消费者反馈想要了解的信息。人们对 SUV 的持续关注和对混合动力汽车兴趣的增加是零件供应商 CXO 想知道的,但可能无法直接获得。

好了,你已经为会议做好了准备,现在你有了一个大规模可扩展的、无偏见的 insight assistant,它可以在你需要的任何时候做上述所有事情,而不会在几个小时内有任何自负或懒惰。
总之,人工智能技术组合在一起可以增强你的能力和智力,为我们在工作中经常面临的任务做准备。
通过使用人工智能工具整理海量数据,并对其进行解码以获得洞察力,非常有用的决策干预是可能的。人工智能的力量在于它作为一个大规模可扩展的个人洞察助理,与我们的生活无缝融合。
(注:使用的 AI 工具包括但不限于向量空间交集、属性模型、分类器、主题标识符等。这里的重点是展示一个 AI 用例。该方法在作者的各种其他博客中有所涉及,在此不做介绍)
解码 Python 的*args 和**kwargs 函数参数
Python 中可选的函数和方法参数是如何工作的?

在 Python 函数中使用*args 和**kwargs
在使用 Python 函数时,您一定碰到过*args (args)或**kwargs (kwargs)参数。在初学者定义中,这些函数允许你用 Python 写一个变量或“n”个参数的函数。
虽然这是最外行的定义,但这些功能分别有特定的用途。实际的语法是*前导 args,而**前导 kwargs。
*参数
如果您将*args 作为函数的一个参数传递,函数现在可以接受比定义的参数数量更多的参数。
def myFun(arg1, arg2, arg3, arg4) :
print("arg1:", arg1)
print("arg2:", arg2)
print("arg3:", arg3)
print("arg4:", arg4)
args = ("My", "name", "is","Vishal")
myFun(*args)
位置参数作为元组收集。函数定义中的这些参数(arg1、arg2、arg3、arg4)以连续的方式从*args 中获取值。
def myFun(name, *args):
print(name)
if args:
print(args)myFun("Vishal") #name parameter passed
myFun("Vishal",1,2,3) #name and args parameter passed
当你在第一个函数调用中传递你的名字时,它将返回你的名字——在这个例子中是“Vishal”。
当第二次调用该函数时,它传递 name 参数和三个数字。定义函数时,这三个数字存储在*args 中。
因此,输出将看起来像这样
Vishal # For first function callVishal # For second function call
(1,2,3)
args 的其他功能可能以这种方式派上用场:
def fun(*args):
args=args + (4,)
return args
print(fun(1,2,3))
在 args 元组中传递(1,2,3)之后,可以使用下面这段代码增加元组的大小。
args=args + (4,)
因此,您将看到该函数的输出如下所示:
(1,2,3,4)
*** 克沃格*
使用kwargs 与使用*args 几乎相同,但是在kwargs 中,您可以传入关键字参数。
def myFun(**kwargs) :
for key, value in kwargs.items() :
print("%s == %s" % (key, value))
myFun(first='Foo', second='Baz', third='Bar')
运行该函数后,该函数将返回 kwargs 的键和值。
first==Foosecond==Bazthird==Bar
以*args 解释中定义的例子为例:
def myFun(name, **kwargs):
print(name)
if kwargs:
print(kwargs)myFun("Vishal") #name parameter passed
myFun("Vishal",one=1,two=2,three=3) #name and kwargs parameter passed
第一个函数调用只会将“Vishal”发送到定义中的名字,“Vishal”会返回。
在第二次调用中,关键字参数将与名称一起作为字典存储在 kwargs 中。
Vishal # For first function callVishal # For second function
{‘one’:1,’two’:2,’three’:3}
您也可以使用这些参数,例如:
def fun(**kwargs):
kwargs['name']='Vishal'
return kwargsfun(roll=12, subject='Data Science')
现在,这个函数将向 kwargs 字典中再添加一个键值对。输出看起来会像这样。
{'roll': 12, 'subject': 'Data Science', 'name': 'Vishal'}
Python 以其独特的功能令人惊讶。而且,使用*args 和**kwargs 是每个初学者都必须知道的事情,因为它们经常会派上用场,尤其是当你想让你的函数在参数方面更加灵活的时候。
如需反馈和讨论,请通过我的 Linkedin 找到我!
无需代码即可解码 Scala
深入 Scala 的内部工作和内存管理

我在使用 Spark 时遇到了 Scala,Spark 本身就是用 Scala 编写的。我有着Python的背景,对Java一无所知,我发现Scala在开始时有点令人困惑,但是随着时间的推移,我越来越喜欢它,现在,它是我大多数用例的首选语言。
凭借经验,我已经掌握了一些 scala 及其工作原理。请继续阅读,了解更多关于 scala 的信息,主要是非编码部分,代码是如何执行的。也许你会使用它很长一段时间,但有些东西仍然会让你感到惊讶。
此外,我不会深入讨论如何在Scala中编码,因为我相信学习一门语言没有比用它构建一些东西更好的方法,这可以在以后的时间里讨论。
Scala 的酷在哪里?
我对Scala的第一印象是Java++(好吧,这是相当蹩脚的),但我认为Scala是一个更好的Java,具有几乎相似的结构和更少的代码。
Scala( 代表可扩展语言)是运行在 JVM 上的面向对象& 函数式编程语言的组合。截至 2020 年 10 月,Scala 的最新版本是 2.13.3
在 scala 中一切都是对象,事实上,据说 scala 比 Java 更面向对象。让我们看看如何:
- 像 1,2 这样的整数是
Int类的对象,而Int类的方法可以在整数上调用,例如,你可以像这样在整数上调用一个方法:
print(-1.abs) # absolute value of -1
1
- 函数是 Scala 中
Functiontrait 的对象。(读作)
Scala 允许惰性求值,可用于资源的优化使用。Scala 的惰性求值允许表达式,代码直到第一次使用才被求值。Scala 的这一特性是 Spark 工作的基本原则,即 Spark 是延迟评估的。
Scala 自动做类型干涉,我们并不总是需要在声明的时候定义变量的类型。在大多数情况下,编译器可以在编译时检测到变量的类型。(类型推理如何工作)
Scala 看起来是解释型的,但实际上它是编译型的,所以速度更快,尽管乍看起来 Scala 似乎是一种解释型语言,至少对我来说是这样。因为我们有一个可用的 scala shell,我们可以在其中执行测试代码,就像 Python 一样,我还假设 scala 是一种解释型语言。
scala命令启动一个交互式 shell,在这里 Scala 表达式被交互式地解释。外壳是 REPL,它在引擎盖下编译代码&运行编译好的代码。
Scala 与 Java 紧密集成,所以如果需要的话,你可以混合 Java 和 Scala 来编写代码。此外,几乎所有的 Java 库都可以导入 Scala。
最后, Scala 是用 Scala 写的,就是这么酷!(参考)
Scala 代码是如何工作的?
Scala 代码被编译成 Java 字节码,由 Java 虚拟机(JVM)执行,这实质上就是我们如何混合使用 Java 和 Scala 代码。
JVM 是一种抽象的计算机器,它使计算机能够运行 Java 程序。由于 scala 代码被编译成 Java 字节码,所以它是通过 JVM 执行的。
JVM 基本上就是 Java 神了(也 对于我们 scala peeps ),越早学会越好。它负责所有的事情,从加载代码、验证代码、执行代码、内存管理、从操作系统分配资源,最后是运行时环境。
Scala 中的内存管理
Scala 运行在 JVM 上,所以它采用类似 Java 的内存管理。所有的执行都依赖于内存&我们可以将内存管理定义为从操作系统分配资源,并释放不必要的内存以避免出现 OOM 错误。(将在后面讨论)
在更高的层次上,JVM 内存由三部分组成:堆、栈和其他。让我们试着一个一个去理解每一个组件。

JVM 内存架构(图片由我在http://draw.io/上创建)
许多
堆存储实际的对象,并在 JVM 启动时创建。只有一个堆空间由所有 JVM 进程共享。另外,请注意垃圾收集器(或 GC)只在堆内存上运行。
堆的大小可以是固定的,也可以是可变的,这取决于 GC 策略。用户可以使用–Xmx 选项设置最大堆大小,默认为 64 MB。
堆
堆栈区域是用线程创建的。它存储对堆内存中存储的对象的本地引用。
由于其 LIFO 结构,堆栈非常适合为方法清理空间,因此,我们不需要随机访问数据。
其他的
这个部分存储特定于 JVM 的代码和数据。
垃圾收集器(特别提及):
随着时间的推移,未被引用的对象会导致堆内存增加,清理堆内存是内存管理的一个重要组成部分。但作为用户,我们不必担心自己清理这些未被引用的对象,即所谓的垃圾。GC 或垃圾收集器为我们完成了这项工作。
垃圾收集器是一个守护进程,它清理由未使用或未引用的对象占用的不必要的内存。
虽然用户并不总是需要干预 GC、JVM 内存管理或 scala 的内部工作,因为大部分工作都是它自己完成的,但是了解内部工作可能会帮助我们更好地理解代码,并知道在哪里花费精力。另外,这很有趣!
此外,这是 JVM 内存架构的高级概述,它在更深的层次上变得更加有趣,包括各个组件,如年轻一代、老一代、小型 GC 等。我可能会写一篇同样的后续文章,让我知道你的反馈。
快乐编码,
再见。
解码:最先进的对象检测技术
在这篇文章中,我正在解码当前艺术对象检测的主要构建模块,并看看它如何与一些商业云视觉 API 进行比较,如谷歌云视觉、微软计算机视觉 API。

图片来自 EfficientDet 纸
Eefficient det 是一个神经网络架构,它实现了State-Of-T he-Art(SOTA)结果( ~55.1 *均精度)的对象检测(微软 COCO 数据集)任务,其复杂度远低于以前的检测器[]EfficientDet 的关键构件是
- 复合缩放
- 双向特征金字塔网络
复合缩放

常规缩放变量[宽度(b)、深度、分辨率(d)]、复合(e)。图片来自高效网论文
S 在宽度(b)、深度(c)或分辨率(d)上放大 ConvNets 被广泛用于实现更好的精度,但是在二维或三维上放大时需要繁琐的手动调整,并且仍然会导致次优的精度和效率。复合缩放(e)使用单个复合系数ϕ,根据以下等式以原则方式缩放网络宽度、深度和分辨率。

复合缩放公式,图片来自 EfficientNet 论文。
给定基线网络和目标 flops,复合缩放被公式化为优化问题,如以上等式所示,找出用于缩放基础网络的缩放系数,并且分两步完成:
“1。固定ϕ = 1,假设多 2 倍的可用资源,根据上述等式对⍺、β、𝛾进行网格搜索。
2。固定⍺、β、𝛾为常数,放大基线网络用不同的ϕ"**3
左上等式的参数ℱᵢ(输入层)、Lᵢ(层数)、Hᵢ(高度)、Wᵢ(宽度)、Cᵢ(通道数)是基线网络的预定义参数,如下面的有效网络详情表所示,w、d、r 是用于缩放网络宽度、深度和分辨率的系数。上面右边等式的参数ϕ控制模型缩放的资源,而⍺、β、𝛾分别控制深度、宽度或分辨率缩放。由于复合缩放不会改变基线网络中的图层运算符,因此拥有强大的基线网络也至关重要。"基线网络是通过利用多目标神经架构搜索来选择的,该多目标神经架构搜索优化了精确度和 FLOPs "3。
双向特征金字塔网络

融合多尺度特征的特征网络设计,图片来自 EfficientDet 论文
多尺度特征融合聚合不同分辨率的特征和广泛使用的实践来学习尺度不变特征。特征金字塔网络[ FPN ] (a)融合自上而下从第 3 级到第 7 级的特征并受限于一个方向的信息流,路径聚合网络[ PANet ] (b)在 FPN 的顶部添加自下而上的路径,NAS-FPN (c)使用神经架构搜索来查找跨规模的特征网络拓扑,需要 1000 多个小时的搜索。还发现使用 NAS-FPN 的网络不规则且难以解释。[ 2
BiFPN (d)将双向跨尺度连接与加权特征融合相结合。下面的等式和框图描述了级别 6 的融合特征。

来自 EfficientDet 论文的等式

六级 BiFPN 特征融合
P7_in,P6_in (x,y,w)分别是 6/7 级的输入特征,P5_out 是 5 级的输出特征,P6_out (x,y,w)是 6 级的输出融合特征。使用最*邻插值对 P7_in 特征进行上采样,使用最大池对 P5_out 特征进行下采样,用于第 6 级的特征融合。加权添加层实现快速归一化融合,通过对加权添加层中的每个权重应用 Relu 来确保正权重。**
高效检测架构
EfficientDet 架构使用 4 个主要网络:EfficientNet 主干网、BiFPN、边界框预测和类预测网络。

完整的 EfficientDet 架构,图片来自 EfficientDet 论文
输入图像分辨率:由于 BiFPN 使用 3-7 级的特征,输入分辨率必须能被 pow(2,7) = 128 整除,并且输入图像根据以下等式进行缩放

输入比例方程
BiFPN 网络:由于深度需要四舍五入到最小整数,深度线性缩放。对于宽度(通道数)呈指数增长的 BiFPN,执行宽度网格搜索,并选择最佳值 1.35

主干网络: EfficientDet 使用没有任何改变的 EfficientNet 网络,以重新使用预先训练的 imagenet 模型的权重。下表显示了高效网络 B0 和 B7 网络的详细信息。

高效的网络细节

MBConv 框图
EfficientNet 使用移动反向瓶颈 MBConv 作为构建模块,并依赖于深度方向可分离卷积和残差连接的思想,从而实现更快的训练和更好的准确性。如上图所示,这些 MBConv 模块根据主干网络中的复合缩放系数ϕ ( num_repeat )进行缩放。
盒/类预测网络:盒和类预测网络的宽度根据 BiFPN 网络的宽度进行缩放,深度根据下面的等式进行线性缩放。

来自 EfficientDet 论文的等式
下表显示了根据复合系数ϕ.的 EfficientDet 检测器的比例配置

EfficientDet 网络的缩放配置,图片来自 EfficientDet 纸张
使用预先训练的 COCO 模型进行推理:
*****#Make sure python3 pip3 is installed and updated**sudo apt-get update
sudo apt install python3-pip
sudo -H pip3 install -U pip (to upgrade the pip to latest version)**#Clone EfficientDet git repo** git clone [https://github.com/google/automl.git](https://github.com/google/automl.git)cd ~/automl/efficientdet**#Install all the EfficientDet requirements**
pip3 install -r requirements.txt**#Download the pretrained weights. Bold d0 represent the model version and can be in the range d0-d7.** wget [https://storage.googleapis.com/cloud-tpu-checkpoints/efficientdet/coco/efficientdet-**d0**.tar.gz](https://storage.googleapis.com/cloud-tpu-checkpoints/efficientdet/coco/efficientdet-d7.tar.gz)tar zxf efficientdet-d0.tar.gzmkdir -p ./savedmodels/efficient-d0**# Export saved model.** python3.6 model_inspect.py --runmode=**saved_model** --model_name=efficientdet-d0 --ckpt_path=./efficientdet-d0 --hparams="image_size=1920x1280" --saved_model_dir=./savedmodels/efficientdet-d0**#Make output dir and do inferencing with the saved model** mkdir -p outdir
python3.6 model_inspect.py --runmode=**saved_model_infer** --model_name=efficientdet-d0 --saved_model_dir=./savedmodels/efficientdet-d0 --input_image=**path_to_input_image** --output_image_dir=./output --min_score_thresh=0.6***

输入图像(左),EfficientDet-D0 输出(右)

谷歌视觉 API 的输出,https://cloud.google.com/vision

Azure Vision API 的输出,https://Azure . Microsoft . com/en-in/services/cognitive-services/computer-Vision/# features

输入图像(左),EfficientDet-D0 输出(右)

谷歌视觉 API 的输出,https://cloud.google.com/vision

Azure Vision API 的输出,https://Azure . Microsoft . com/en-in/services/cognitive-services/computer-Vision/# features
E 就云视觉 API 而言,在测试图像上,fficientDet 输出看起来更好。需要进行详细的对比分析,以确定生产云视觉 API 的效率和质量。采用新型 BiFPN 和复合缩放的 EfficientDet 无疑将成为未来目标检测相关研究的新基础,并将使目标检测模型在实际应用中更加有用。****
感谢您阅读这篇文章,我希望这对您有所帮助。如果你有,请在你最喜欢的社交媒体上分享,这样其他人也可以找到它。此外,如果有不清楚或不正确的地方,请在评论区告诉我们。
参考资料:
- https://ai . Google blog . com/2020/04/efficient det-forward-scalable-and . html
- https://arxiv.org/pdf/1911.09070v7.pdf
- https://arxiv.org/abs/1905.11946
- https://arxiv.org/pdf/1801.04381.pdf
- https://github.com/google/automl/tree/master/efficientdet
解码:最先进的推荐系统
"****"被宣布为应用数据科学领域的最佳论文,最*在 2020 年 8 月 23 日至 27 日举行的 SIGKDD-2020 中。在这篇博客中,我将介绍 HRNN 元推荐模型的关键部分,该模型在各种数据集上实现了最先进的性能,并在sky trax-reviews-dataset上对 HRNN 和 HRNN 元模型进行了比较,以实现个性化的航空公司推荐。

均方根误差:20 米电影镜头和网飞[ 越低越好 ]的 Sqrt((真实评分-预测评分) ),图片由作者提供
****HRNN-梅塔有效且高效地结合了以下主要思想,用于能够适应不同使用情况的 black-bok 推荐系统
- 用于会话间和会话内动态的分级递归神经网络( HRNN )。
- 字段因子分解机器( FFM )从元中提取丰富的上下文特征。
- ****反馈编码理解隐含否定。
- 使用采样的高效训练技术。
HRNN:
推荐系统已经从矩阵分解发展到关注两个重要的来源 1)事件的时间顺序 2)用户/项目元。事件的时间顺序用序列网络建模,如 LSTM 或 GRU 或香草 RNN 。这些网络基于用户历史预测用户可能与之交互的下一个项目的概率,但可能会发现由于消失梯度而对长时间用户会话建模具有挑战性。
为了对长会话建模,通过考虑不活动时段或使用任何其他事件,将会话划分为短会话。
通过使用两个序列网络来学习用户和会话表示,建议使用分层网络来模拟这些长用户会话,如下图所示。在第一个会话期间,用户状态被随机初始化,在会话结束时,SessionRNN 初始化用户表示,如第一个图像所示,这又初始化了 SessionRNN 中下一个会话的状态,如第二个图像所示,并且还可以在整个第二个会话中使用,如第三个图像所示。

图片来自https://youtu.be/M7FqgXySKYk[21:52]

图片来自 https://youtu.be/M7FqgXySKYk[22:25]

图片来自 https://youtu.be/M7FqgXySKYk[22:54]
想了解更多关于 HRNN 的细节,请看 Alexandros Karatzoglou 的精彩视频。
FFM:
“HRNN 被扩展为包括用户和物品特征,如位置、物品价格等,通过场感知多层感知将上下文信息堆叠在相应的用户/物品潜在向量之上,这种扩展我们称为 HRNN 元。”【1】**
在因式分解机器中,每个特征只有一个潜在向量来学习潜在效果,而在场感知因式分解机器中,每个特征有几个潜在向量,并且根据其他特征的场,其中一个用于做内积。
例如,考虑三个特征 ESPN、Vogue 和 NBC,属于领域出版商,而另外三个特征耐克、古驰和阿迪达斯,属于领域广告商。

图片来自[ 5
FM→wes pn w Nike+wes pn w male+w Nike w male。
FFM →威斯普,一个女的,P +威斯普,G 男的,P +女的,G 男的,一个
该原始数据首先被转换为 libffm 格式,然后在馈送到网络之前被转换为 one-hot 编码。
LIBFFM 的数据格式为:
为了将原始数据转换为 FFM 格式,我们构建了两个字典,一个用于字段,一个用于要素
**#Field Dictionary** DictField[Publisher] -> 0
DictField[Advertiser] -> 1
DictField[Gender] -> 2**#Feature Dictionary** DictFeature[Publisher-ESPN] -> 0
DictFeature[Publisher-Vogue] -> 1
DictFeature[Publisher-NBC] -> 2
DictFeature[Advertiser-Nike] -> 3
DictFeature[Advertiser-Gucci] -> 4
DictFeature[Advertiser-Adidas] -> 5
DictFeature[Gender-Female] -> 6
DictFeature[Gender-Male] -> 7**#Tranforming above example to FFM Format**
1 0:0:1 1:3:1 2:7:1 (since all features are cateogorical, the values are all ones)
反馈编码
连同用户特征、反馈事件(例如,评级、购买、成本、观看持续时间等。)被连接作为输入上下文来预测下一项,如下面的 HRNN 元单元格所示。这提供了对隐式负面的更好的响应,如没有任何点击的刷新、内容打开但没有视频视图等。

HRNN-meta 单元格,图像来自[ 1 ]
抽样
计算 softmax 以找出大词汇量中下一个项目的概率在计算上是具有挑战性的,并且在文献中提出了各种采样策略以利用 softmax 进行有效训练,例如:噪声对比估计、重要性采样、负采样等。有两种方法
- 软最大*似值
- 基于抽样的
所有基于采样的方法都使用一些其他损失来*似 softmax,这对于计算是有效的,并且在训练时最有用。
关于抽样策略的更多细节,请看看来自 Sebastian Ruder 的精彩博客。HRNN 依赖于负采样,其中是噪声对比估计的*似值,并将 softmax 转换为逻辑损失。通过将项目频率提高到 0.75 次幂来对负项目进行采样。
****HRNN 元是目前在亚马逊个性化中可用,下图显示了它是如何工作的。

图片来源:https://aws.amazon.com/personalize/
我们在sky trax-reviews-dataset上使用 Amazon Personalize 对 HRNN-meta w.r.t HRNN 进行了快速检查,该数据集有大约 41.4K 条航空公司评论,用于基于用户历史和评论的个性化航空公司推荐。为了使用 Amazon Personalize 训练一个 HRNN 模型和HRNN-梅塔模型,在创建一个环境后,我们按照个性化样本进行上下文推荐,使用 HRNN-梅塔 vs HRNN 的离线指标结果非常令人印象深刻,如下图所示。
- ****~ 80%覆盖率提高,
- 中的 ~17% 表示倒数排名和 ndcg ,
- ****~ 14%精度提高。

HRNN-meta vs HRNN 离线指标比较,图片由作者提供
如果你觉得这很有趣,并想训练 HRNN 元,请跟随开始亚马逊个性化样本,它将带你从环境创建到在定制数据集上训练推荐器模型。
结论
HRNN 元通过有效地将基于会话的推荐与场感知因子分解相结合来提供情境化的推荐,从而提供了一种高效/有效的推荐解决方案。还提供了各种方法,如项目趋势分解来改善冷启动项目推荐。探索像 BERT4Rec 这样的其他最*的方法将会很有趣,并且也可以看到用变压器代替 GRUs 的潜力。
感谢您阅读这篇文章,我希望这对您有所帮助。如果你有,请在你最喜欢的社交媒体上分享,这样其他人也可以找到它。此外,如果有不清楚或不正确的地方,请在评论区告诉我们。
参考:
- https://assets . Amazon . science/96/71/d1f 25754497681133 c 7 aa 2 b 7 EB 05/temporal-contextual-recommendation-in-real-time . pdf
- https://aws.amazon.com/personalize/
- https://www . slide share . net/Amazon web services/add-real time-personal ization-and-recommendation-to-your-applications-aim 395-AWS-reinvent-2018
- https://openreview.net/pdf?id=ByzxsrrkJ4
- https://www.csie.ntu.edu.tw/~cjlin/papers/ffm.pdf
- https://github.com/ycjuan/libffm
- https://arxiv.org/pdf/1602.02410.pdf
生成响应时需要了解的解码策略
区分波束搜索、随机采样、Top-K 和 Nucleus

不同的采样技术。注意,我们在这个例子中没有使用强生成模型。
介绍
深度学习已经被部署在 NLP 的许多任务中,例如翻译、图像字幕和对话系统。在机器翻译中,它用于读取源语言(输入)并生成所需的语言(输出)。类似地,在对话系统中,它用于在给定上下文的情况下生成响应。这也被称为自然语言生成(NLG)。
该模型分为两部分:编码器和解码器。编码器读取输入文本,并返回一个表示该输入的向量。然后,解码器获取该向量并生成相应的文本。

图 1:编码器-解码器架构
要生成文本,通常是通过一次生成一个标记来完成的。如果没有适当的技术,生成的响应可能非常普通和乏味。在本文中,我们将探讨以下策略:
- 贪婪的
- 波束搜索
- 随意采样
- 温度
- Top-K 抽样
- 细胞核取样
解码策略
在解码过程中的每个时间步长,我们取向量(保存从一个步骤到另一个步骤的信息),并用 softmax 函数将其转换为每个单词的概率数组。

等式 1: Softmax 函数。x 是时间步长 I 处的令牌。u 是包含词汇表中每个令牌的值的向量。
贪婪的方法
这种方法是最简单的。在每个时间步,它只选择最有可能的记号。
Context: Try this cake. I baked it myself.
Optimal Response : This cake tastes great.
Generated Response: This is okay.
但是,这种方法可能会产生次优的响应,如上例所示。生成的响应可能不是最佳响应。这是由于训练数据通常具有类似“这是[…]”的例子。因此,如果我们一次生成最可能的令牌,它可能输出“是”而不是“蛋糕”。
波束搜索
穷举搜索可以解决前面的问题,因为它将搜索整个空间。然而,这在计算上将是昂贵的。假设有 10,000 个词汇,要生成一个长度为 10 个单词的句子,将需要(10,000)个⁰.

图 2:波束宽度=2 的波束搜索(源
波束搜索可以应对这个问题。在每个时间步,它生成词汇表中所有可能的标记;然后,它将选择概率最大的前 B 名候选人。那些 B 候选人将移动到下一个时间步,并且重复该过程。最后只会有 B 人选。搜索空间只有(10000)* b。
Context: Try this cake. I baked it myself.
Response A: That cake tastes great.
Response B: Thank you.
但有时,它会选择一个更优的方案(对策 B)。在这种情况下,这是完全合理的。但是想象一下,这个模型喜欢玩安全的游戏,并且在大多数情况下不断地产生“我不知道”或者“谢谢你”,这是一个非常糟糕的机器人。
随意采样
或者,我们可以研究随机方法,以避免反应是通用的。我们可以利用来自 softmax 函数的每个令牌的概率来生成下一个令牌。
假设我们正在生成上下文的第一个单词“我喜欢看电影”,下图显示了第一个单词应该是什么的概率。

图 3:每个单词的概率。x 轴是令牌索引。即,索引 37 对应于单词“耶”
如果我们使用贪婪的方法,将选择一个令牌“I”。然而,通过随机抽样,令牌 i 有 0.2 左右的概率发生。同时,任何概率为 0.0001 的令牌也可能出现。只是可能性很小。
温度随机抽样
随机抽样本身可能会偶然产生一个非常随机的单词。温度用于增加可能令牌的概率,同时减少不是可能令牌的概率。通常情况下,范围是 0 < temp ≤ 1. Note that when temp=1, there is no effect.

Equation 2: Random sampling with temperature. Temperature t is used to scale the value of each token before going into a softmax function

Figure 4: Random sampling vs. random sampling with temperature
In Figure 4, with temp=0.5, the most probable words like i , yeah , me ,产生的几率较大。同时,这也降低了不太可能发生的事件的概率,尽管这并不能阻止它们的发生。
Top-K 抽样
Top-K 采样用于确保不太可能的单词根本不会有任何机会。对于一个世代,应该只考虑前 K 个可能的记号。

图 5:3 个随机抽样的分布,带 temp 的随机抽样和 top-k
如果我们使用温度=0.5 或 1.0 的随机抽样,50 到 80 之间的令牌指数有一些小概率。对于 top-k 采样(K=10),这些令牌没有机会被生成。请注意,我们也可以将 Top-K 采样与温度相结合,但是您可能已经了解了这个概念,所以我们选择不在这里讨论它。
这种采样技术已在许多新一代任务中采用。它的性能相当不错。这种方法的一个限制是需要在开始时定义前 K 个单词的数量。假设我们选择 K = 300 然而,在解码时间步长,模型确定应该有 10 个极有可能的单词。如果我们使用 Top-K,这意味着我们也将考虑其他 290 个可能性较小的单词。
细胞核取样
细胞核采样类似于 Top-K 采样。nucleus sampling 不是关注 Top-K 单词,而是关注 Top-V 单词的最小可能集合,使得它们的概率之和≥ p。然后,不在 V^(p 中的记号被设置为 0;其余的被重新缩放,以确保它们的总和为 1。

等式 3:细胞核取样。V^(p)是最小的代币。P(x|…)是给定先前生成的从 1 到 i-1 的记号 x,生成记号 x 的概率
直觉是,当模型对一些记号非常确定时,潜在候选记号的集合很小,否则,将会有更多的潜在候选记号。
C 确定→那几个记号概率大=几个记号之和足以超过 p.
不确定→很多记号概率小=需要很多记号之和才能超过 p.

图 6:Top-K 和 Nucleus 采样的分布
将 nucleus 采样(p=0.5)与 top-K 采样(K = 10)进行比较,我们可以看到 nucleus 不认为令牌“you”是候选。这说明它可以适应不同的情况,选择不同数量的令牌,不像 Top-K 采样。
摘要
- 贪婪:一次选择最可能的令牌
- 波束搜索:选择最可能的响应
- 随机抽样:基于概率的随机抽样
- 温度:缩小还是放大概率
- 前 K 个采样:选择前 K 个可能的令牌
- 细胞核取样:动态选择 K 的数量(排序)
通常,研究人员的首选是波束搜索、top-K 采样(带温度)和原子核采样。
结论
我们已经讨论了一系列解码响应的不同方法。这些技术可以应用于不同的生成任务,即图像字幕、翻译和故事生成。使用具有坏解码策略的好模型或者具有好解码策略的坏模型是不够的。两者之间的良好*衡会让这一代人更有趣。
参考
霍尔茨曼,a .,布茨,j .,杜,l .,福布斯,m .,,崔,Y. (2020)。神经文本退化的奇特案例。在国际学术交流会议。
自然语言生成(NLG)是一项生成文本的任务。像机器这样的自然语言生成任务…
towardsdatascience.com](/word-sequence-decoding-in-seq2seq-architectures-d102000344ad) [## 波束搜索的直观解释
波束搜索的简单易懂的解释
towardsdatascience.com](/an-intuitive-explanation-of-beam-search-9b1d744e7a0f)
解码支持向量机
直观理解支持向量机的工作原理

Honey Yanibel Minaya Cruz 在 Unsplash 上拍摄的照片
SVM 是一个非常简单但强大的监督机器学习算法,可用于分类以及回归,虽然它普遍用于分类。它们在中小型数据集上表现非常好,并且非常容易调优。
在这篇博文中,我们将建立我们对支持向量机的直觉,并了解其背后的数学原理。我们将首先了解什么是大间隔分类器,并了解该算法的损失函数和成本函数。然后我们将看到正则化如何为 SVM 工作,以及什么支配着偏差/方差的权衡。最后,我们将了解 SVM 最酷的特性,那就是内核技巧。
为了轻松掌握概念,您必须具备一些关于线性回归和逻辑回归工作原理的必备知识。我建议你在阅读时做笔记,以便充分利用这篇文章,这将是一个漫长而有趣的旅程。所以,事不宜迟,让我们开始吧。
大间距分类器
让我们马上从一个例子开始,假设我们有一些包含 2 个类的数据,为了简单起见,假设它只有 2 个特征,我们可以用许多不同的方法来分离这 2 个类。我们可以使用线性以及非线性的决策边界来做到这一点。
SVM 所做的是试图尽可能广泛地将这两个类分开,因此在我们的示例中,它将选择黄线作为其决策边界。

图 1
如果黄线是我们的决策边界,那么圈起来的绿色和红色类点(图 2)是离我们的决策边界最*的点。这些点之间的距离被称为余量,SVM 试图最大化这个余量。这就是为什么支持向量机也被称为大间隔分类器的原因,这使得 SVM 具有更好的泛化精度。

图 2
在高维空间中,这些点只不过是 n 维向量,其中 n 是数据中特征的数量。最接*决策边界的点的样本(这里是红色和绿色的圆圈点)被称为支持向量。我将绿色的支持向量称为正支持向量,红色的称为负支持向量。决策边界完全取决于这些点,因为它们是决定我们的边界长度的点。如果我们改变支持向量,我们的决策边界也会改变,这也意味着支持向量以外的点在形成决策边界时并不重要。
优化目标
要找到决策边界,我们必须:
- 定义我们的假设
- 定义损失函数
- 使用损失函数计算所有训练点的成本函数
- 使用优化算法,如梯度下降或序列最小优化,以最小化成本,并达到我们的理想参数
SVM 的假设相当简单,重量为 w

图 3
这里你需要理解的一个关键点是,这个假设只不过是数据点和决策边界之间的距离,所以每当我说假设这个词的时候,就把它想成是这个距离。
在我们看到 SVM 的损失函数到底是什么之前,让我们看看单个训练例子的成本

图 4
第一项是 y = 1 时的损耗,第二项是 y = 0 时的损耗,而“y hat”只是我们在图 3 中定义的假设。我知道我已经给出了很多方程,不要担心,让我们开始理解它们。

图 5
这是实际类分别为 1 和 0 时的开销。如果你不明白 1 和-1 是从哪里来的,不要担心,当我们看到损失函数的公式时,你就会明白了。
让我们首先看看 y = 1 时的第一种情况。我们知道当假设为非负时,我们的预测是 1。所以对于我们假设的那些值,我们的成本一定是最小的,但这里不是这样。为什么只有当假设大于或等于 1 而不是 0 时,我们的成本才达到最小值,即值为 0?答案可以在大间隔分类器的思想中找到。
****
图 6
我们的假设对于所有位于边缘的 1 类点都是 1,换句话说,对于我们的正支持向量,假设是 1。因此,对于远离决策边界(甚至比支持向量更远)的所有点,假设将具有大于 1 的值,因此成本将最小化。如果我们有在边缘之间的点,即它们比支持向量更接*决策边界,对于它们,假设将小于 1。这些点越接*决策边界,我们的成本就越高。然而,只要假设是非负的,这些点仍然被分类为 1。
现在让我们看看 y = 0 时的第二种情况
****
图 7
类似于我们的第一种情况,这里假设的值将为-1,对于所有恰好位于边缘距离的 0 类点,或者换句话说,对于所有的负支持向量,假设将为-1。随着假设开始在负方向上增加,或者数据点开始变得更加远离决策边界的负支持向量(在我们的情况下,随着红色点开始变得更加远离决策边界),成本达到 0,即最小值。这里,当这些点位于边缘之间或者当它们开始越来越接*决策边界时,成本开始增加,但是只要假设是否定的,这些点就被分类为 0。
综上所述,SVM 成本函数不仅会对错误分类产生不利影响,而且会在点开始越来越接*决策边界时产生不利影响,因此我们的优化算法必须找到权重,以保持类之间的距离(或余量)。
现在我们已经通过一个训练例子的成本理解了 SVM 背后的直觉,让我们看看铰链损耗的公式是什么。

图 8
现在,如果你再看一下图表,你就会明白 1 和-1 是从哪里来的。损失基本上只是说
- 对于 y = 1,如果假设值大于或等于 1,则损失为 0。如果假设介于 0 和 1 之间或为负,则损失保持正值并线性增加。
- 对于 y = 0,如果假设值大于或等于-1,则损失为 0。如果假设介于-1 和 0 之间或为正,则损失为正并线性增加。
我们已经看到了铰链损耗的样子,也看到了单个训练示例的成本,我们现在需要做的就是将这两个方程结合起来,形成“m”个训练示例的成本函数。这是我们得到的结果:

图 9
等一下…这些多余的字母是从哪里来的??

正规化
在上式中,“C”称为正则化参数。这是一个控制正则化数量的超参数。然而,SVM 的正则化与逻辑回归或线性回归中的正则化略有不同。让我们以逻辑回归为例,成本函数的形式如下:

图 10
这里,B 是正则项(L2 或 L1 ), A 是代价项,或者像有些人所说的拟合项。在逻辑回归中,通过改变正则化参数“λ”的值,我们基本上是在告诉优化算法需要给予正则化项的注意力的数量,这就是我们如何控制偏差/方差的权衡。但是 SVM 成本看起来是这样的:

图 11
这里 A 也是拟合项,B 是正则项,然而正则化参数与拟合项相关联。因此,现在通过改变我们的正则化参数的值,我们告诉优化算法对拟合项给予多少关注,或者对正则化项给予多少关注。直观上,C 和 lambda 是成反比的。
例如,我们有一个非常大的 C 值。即使存在单个异常值,大的 C 值也会尝试最小化错误分类的点,我们将得到紫色的决策边界,而不是 C 值合理时得到的绿色决策边界。

图 12
如果 C 非常小,那么裕度将会更大,但是错误分类的机会将会增加。

图 13
所以基本上,随着 C 增加我们的模型过拟合数据的趋势增加,随着 C 减少我们更倾向于欠拟合数据。****
内核技巧
核心技巧是支持向量机如此强大的原因。它允许算法学习更复杂的决策边界,而不仅仅是线性的。那么什么是内核呢?让我们首先来看看假设和使用核 SVM 的成本函数。

图 14
如你所见,方程没有太大变化。假设中有“f”而不是 X,这是新特征的矩阵。我们从一个函数中得到这些特性的值,这个函数就是我们所说的内核。现在在我们的成本中,“y hat”代表这个新制定的假设。
现在让我们理解这些函数是如何计算的。假设我们有一个包含 2 个特征的数据集,我们在下面可视化一个训练示例,这里 l1、l2 和 l3 是我们选择的一些地标,现在不要担心它们的值是什么。

图 15
我们的核是 X 的函数。使用这些函数,我们计算模型的新特征。因此,对于每个地标,我们将有一个如下的特征:

图 16
这些函数或核可以是不同的类型,如高斯核、多项式核,或者如果我们只使用我们的一般特征而不使用核,它有时被称为线性核。高斯核是最广泛使用的,所以我们将在这篇文章中讨论。
如果我们使用高斯核,我们的特征看起来会是这样:

图 17
回到我们之前的例子,让我们了解使用高斯核如何影响我们的决策边界。
如果我们假设 X 几乎等于 l1(它们之间的距离几乎为 0),那么高斯核输出接* 1 的值。

图 18
另一种情况可能是,如果 X 离一个点非常远,比如 l1,那么内核将输出一个接* 0 的值。
因此,点和界标之间的距离越大,特征值越低,点和界标之间的距离越*,特征值越高。现在举个例子,让我们看看决策边界是如何形成的。
****
图 19
这里,X1 非常接* l1,它也接* l2,但相对远离 l3,因此 f1 和 f2 的值较高,但 f3 的值非常低。(我只是出于解释的目的假设了这些值)。将它代入我们的假设,我们将得到一个正值,并预测 X1 为 1。
另一方面,X2 更靠* l3,而远离 l1 和 l2。所以 f1 和 f2 的值会很小,f3 会更大。代入这些值给我们一个否定的假设,因此我们预测 X2 为 0。
由此我们可以看到,距离 l1 和 l2 更*的点被预测为 1,距离 l3 更*的点被预测为 0,因此这是我们得到的*似决策边界。

图 20
这给了我们一个直观的理解,如何使用核可以让 SVM 学习更复杂的函数,而不仅仅是一个线性函数,但是这些标志是如何选择的呢?
这个问题的答案很简单,每个地标对应我们的每个数据点。这意味着对于具有“m”个训练示例的数据集,我们将有“m”个界标,因此我们将计算“m”个新特征。

图 21
因此,对于具有“m”个示例的数据集,我们将计算“m”个特征。现在,我们用这种方法计算所有数据点的特征。这里要注意的一点是,对于第 I 个数据点,第 I 特征值总是为 1(使用高斯核)
偏差/方差权衡
我们已经讨论了当我们改变 C 时,决策边界是如何受到影响的。如果 C 很大,则存在高方差和低偏差,如果 C 很小,则存在高偏差和低方差。
让我们探讨σ对我们的偏差和方差的影响。高斯核使用最广泛,因此了解σ如何影响我们的决策函数很有好处。为了简单起见,让我们假设我们有一个只有一个特征的数据集

图 22
这里 l(i)是第 I 个标志,我们可以看到,如果σ很大(绿线),那么高斯核从一个训练示例到另一个训练示例变化非常*滑,无论我们的训练示例或标志的值是多少,如果σ很大,那么变化将是最小的,因此我们的模型将对数据进行欠拟合。我们将有高偏差和低方差。
现在,对于一个小的σ值(红线),高斯核的变化从一个训练示例到另一个训练示例将是剧烈的,因此它将给我们一个过度拟合的模型。我们将有高方差和低偏差。因此,随着σ增加,偏差增加,随着σ减少,方差增加。
最佳化
为了优化 SVM 成本公式,我们使用 SMO(序列最小优化)。没有必要去理解 SVM 的成本函数是如何被优化来实现 SVM 的,大多数可用的软件包都可以为我们做到这一点。然而,如果你对它背后的数学感兴趣,那么你可以查阅参考文献
至此,我们可以结束对支持向量机的讨论,如果你坚持到最后,恭喜你,你现在一定对 SVM 算法的工作有了直观的理解。
希望你觉得这篇文章有用并且容易理解,请在评论区提供有价值的反馈:)
参考
解码你的基因
神经网络能解开我们 DNA 的秘密吗?
我通过总结激动人心的新研究论文来探索人工智能对传统科学的影响。在这篇文章中我讨论的是另一篇很酷的论文:《深度递归神经网络对牛津纳米孔测序数据的 DNA 碱基修饰检测》( 《自然通讯》,10,2449,2019 )。
1 |你背后的代码
你身体的每一部分都是你的 DNA(脱氧核糖核酸)的产物,DNA 是一种复杂的遗传密码,精确地描述了你的细胞应该做什么。我们都知道 DNA 分子著名的双螺旋形状:它由称为“碱基”(胞嘧啶[C]、鸟嘌呤[G]、腺嘌呤[A]和胸腺嘧啶[T])的不同化学单元组成,它们结合在一起形成美丽的螺旋链。这有点像二进制计算机代码,但不是 1 和 0 的序列,而是 Cs、Gs、As 和 Ts。这些链中 CGAT 碱基的精确序列编码了你和地球上其他动物的一切。

DNA 的双螺旋结构。图片来自pixabay.com
一个真正重要的生物过程是 DNA 甲基化:这是一个简单的化学甲基(CH3)被添加到正常的 DNA 碱基中:下图显示了这种变化有多小。虽然这种变化看起来很小,但它可能对基因调控、衰老甚至癌症产生巨大影响。人们甚至认为这些甲基化可以作为癌症治疗的治疗靶点!

正常胞嘧啶(DNA 中的 C 碱基)和甲基化版本的比较。在知识共享许可的许可下复制。
2|用纳米技术绘制 DNA 变化图
显然,我们能够绘制出我们遗传密码中的修改是非常重要的……但这实际上很难做到。目前的技术噪音大,分辨率低,因此确实需要改进。最*的一个想法是基于一种非常酷的纳米孔技术。你可以看看这个很棒的视频展示了它是如何工作的,但基本上离子电流是通过含有微小纳米孔的聚合物膜。当感兴趣的分子穿过这些小孔,从膜的一侧移动到另一侧时,电流以特有的方式受到干扰。所以你放入 DNA 分子,你会得到一个 2D 序列的变化的电子信号,可以用来识别遗传密码。这项技术最*被用来在仅仅 7 小时 内测序新冠肺炎的全部遗传密码!
尽管这个系统非常擅长获得整个 DNA 序列,但要定位存在微妙甲基化的位置有点困难,因为理解信号是依赖于上下文的。甲基化可以通过比较甲基化和未甲基化 DNA 序列的纳米孔电子信号来定位。

显示 DNA 穿过膜在电子信号中产生干扰的示意图。
3 | ML 能帮上什么忙?
如果你在序列数据中寻找模式,RNNs(递归神经网络)是最好的架构。如果你不熟悉,让我们快速看一下它们是如何工作的。
典型的“前馈”神经网络遵循将随机初始化的权重和偏差应用于输入以预测输出的过程。当将生成的输出与目标输出进行比较时,会计算出一个误差(或“损失”)。这种损失然后通过网络传播回来,以更新权重和偏差,目的是提高输出。在训练期间,这个过程用不同的输入反复重复,直到网络有希望学会产生准确的输出。这只是一个非常简单的概述,但总结了主要原则。
如果您预测的不是单个输出,而是一系列输出,该怎么办?从概念上讲,RNN 可以被认为是一系列相连的前馈网络,信息在它们之间传递。被传递的信息是隐藏状态,它代表所有先前输入到网络的信息。在 RNN 的每一步,前一步生成的隐藏状态以及下一个序列输入都会被传入。然后,这将返回一个输出以及要再次传递的新隐藏状态。这使得 RNN 能够保留迄今为止看到的序列信息的“记忆”,并使它们对于理解序列数据非常有用。你可以在这里找到一个更加数学化的描述。
让我们来看看 RNNs 究竟是如何破译 DNA 修改的。

通过 RNN 表示信息的移动
4|用 RNNs 解开 DNA
在本文中,开发了一种新工具“DeepMod”。这是一个双向 RNN(它向前和向后传递序列信息),具有长短期记忆(LSTM);点击查看 lstm的精彩摘要。
DeepMod 将参考遗传密码和纳米孔电信号作为输入。电信号中的“事件”(由纳米孔测序仪产生的一系列信号点)与参考中的 DNA 代码对齐。这是使用 BWA-MEM 实现的,这是一种将 DNA 序列与参考基因组匹配的比对算法。这种算法能够匹配长达百万碱基的 DNA 序列!
作者使用输入信号的 7 特征向量描述;与事件相关的信号*均值、标准偏差和信号点数,结合 DNA 碱基的四个特征描述(A、C、G 或 T)。这作为网络的输入(见下面的体系结构),预测信号事件是否是修改碱基的结果。
该算法首先使用来自大肠杆菌细菌 DNA 的数据进行训练和优化。发现具有 3 个隐藏层的 21 单元 LSTM 在保持合理的计算成本的同时实现了高精度的结果。对几个不同大肠杆菌数据集的分析显示了惊人的单碱基甲基化图谱分辨率。此外,该网络在识别哪些碱基被甲基化方面显示出很高的精确度(高达 0.99)。

显示具有 LSTM 的 DeepMod RNN 的结构的图表,表明电子输入如何通过网络输出对感兴趣位点甲基化的预测。在知识共享许可下,经原文许可复制。
T4:这能绘制出人类的遗传密码吗?
是啊!尽管 Deepmod 只在细菌 DNA 数据上进行训练,但它被用来对人类 DNA 中的甲基化进行准确预测。这项跨物种测试确实令人兴奋,因为它表明,在一个物种上训练的模型可以用来精确绘制该模型从未见过的物种的 DNA 结构。也许这个模型也可以应用到不同物种的负荷上,看到这些结果真的会很令人兴奋!
这是一个很好的例子,说明了神经网络归纳新任务和加快科学学习速度的能力。这也是一个很好的例子,机器学习被应用于当前的科学问题,以产生一个即时和实用的解决方案。DeepMod 代码现在可以在线获得,作者计划为未来的用户维护和更新它。这个工具分析人类 DNA 修改的高速和高精度能力可能有助于理解和治疗不同的疾病,如癌症,所以这是一个非常酷的结果!

图片来自pixabay.com
6|最终想法
尽管取得了这些巨大的成果,但还是有一些事情需要记住:
- DeepMod 只对两种类型的 DNA 甲基化进行了训练和测试,但实际上有许多不同的类型。需要更多的测试来了解这个模型是否可以用来定位真实 DNA 中存在的大范围的修饰。
- 该模型没有检测 RNA(核糖核酸),DNA 的单链表亲。对于编码、解码和基因表达来说,这是一种必不可少的生物分子,所以看看这个模型在这项任务中的表现将会非常有趣。
- 最后,该模型严重依赖于使用 BWA-MEM 将输入信号与参考 DNA 进行比对。如果对齐不良,模型的性能将受到严重影响,并且在培训时需要记住这种依赖性。
总的来说,这是一个非常有前途的神经网络物理应用,如果你喜欢这个简短的总结,我鼓励你阅读原始论文以获得关于 DeepMod 框架、训练和验证过程的更深入的细节。
逐步分解量子机器学习算法。
二元分类器的变分电路。

量子计算机在 15 年前被认为是科幻小说。
现在,这些机器真实存在,并在云上公开。我们相信它们可以解决在经典计算机上无法解决的问题,应用于化学、最优化、机器学习、密码学和许多其他领域。
10 月,谷歌宣布了量子优势,这意味着量子计算机第一次能够比任何现有的经典计算机更快地执行特定任务。实际上,在谷歌和 IBM 之间有一场争论,谷歌声称这项任务在经典计算机上需要 10,000 年的时间,而 IBM 则表示几个小时就可以完成。在所有情况下,量子计算机都需要几分钟,因此这是该技术潜力的证明。
在这篇文章中,我有兴趣解释量子计算如何用于机器学习。
我将展示如何用一台 2 量子位的量子计算机构建一个简单的二进制分类器。
在第一部分,我为不熟悉量子计算的读者介绍了量子计算的基础知识。然后我解释了 ML 中 QC 的一般用法,并分解了算法的不同部分。最后给出了在 iris 数据集上的实验结果。
玛利亚·舒尔德、阿历克斯·鲍恰洛夫、克里斯塔·斯沃雷和内森·维贝的作品详细解释了这种方法。
量子计算 101

资料来源:xkcd.com
现在让我们描述一下理解本文其余部分所需的量子计算基础知识。
量子物理学的基本原理是在足够小的尺度下,世界变得具有概率性。一个粒子不能像宇宙中的行星、恒星那样用固定的坐标来描述,而是用波函数来描述,波函数是粒子位于空间某个区域的概率。
量子态
理解量子态对于量子计算的进一步发展至关重要。
量子系统的大多数特征都不是确定性的(有些是确定性的,比如质量或电荷),它们是概率性地分布在一组可能的状态中。然而,测量这些特征将产生一个单一的值,以及相关的概率。这叫做测量。
比如一个电子既不是自旋向上也不是自旋向下,而是以 0.5 的概率自旋向上或者自旋向下。自旋的测量结果将是 50%的时间向上自旋,50%的时间向下自旋。
这种与不同状态相关的概率组合被称为量子态。你应该把量子系统看成一个骰子。骰子没有固定的数值,只允许你掷出去读取结果。那么你会说骰子的状态是 1,2,3,4,5,6,每个概率是 1/6。如果你考虑一个得到 6 的概率为 0.5 的作弊骰子,你会说骰子的状态是概率为 0.1 的 1,2,3,4,5 和概率为 0.5 的 6。
量子态的通俗例子是薛定谔的猫,它有一定概率可以是死的,也可以是活的。打开盒子就是在“测量”猫的状态。
量子态用括号符号|s >表示。对于电子来说,它应该是|上>或|下>。不同状态的线性组合如下所示。

一般的量子态。
在这种情况下,𝑎_s 被称为与状态|s >相关的振幅,它是一个复数,如|𝑎_s|是系统处于状态|s >的概率。
同样的原理,量子计算机的基本砖块是量子比特,或量子比特。与经典比特相反,量子比特没有确定值 0 或 1,而是以某种概率处于状态|0 >或|1 >。
更正式的说法是,一个量子位记为|q> = 𝑎|0>+𝑏|1>,𝑎和 b 是两个复数,比如|𝑎| +|𝑏| =1。
一个量子位可以处于|0 >或|1 >状态,但是几个量子位会发生什么呢?
两个量子位的状态被标注为|00 >、|01 >、|10 >和|11 >,这给出了 4 种可能的状态。
3 个量子比特呢?您有 8 种可能性:|000 >,|001 >,|010 >,|011 >,|100 >,|101 >,|110 >,|111 >
你可以通过在一个 ket 上并列不同量子位的值来记录任意数量量子位的状态,比如|000110101010 >。为了简化它,请注意所获得的二进制字符串的十进制等效值,例如|101 >是|5 >。
一般来说, n 个量子位给出 2 个 ⁿ 个可能状态。意味着有了 300 个量子比特,你可以拥有比宇宙中原子数量还要多的状态!!这是量子计算潜力的关键要素。
于是, n 个量子位的一般量子态是一个复数矢量,其*方模之和等于 1。

n 个量子比特的一般量子态。
量子态也用矢量格式表示,如下例所示。可以看出,范数*方总是等于 1,因此常数 1/sqrt(2)和 1/sqrt(3)。

量子算符
一旦我们有了量子态,对它进行操作就好了。这是量子算符的工作。
量子算符是量子态上的线性算符,因此它们可以由复矩阵 A. 表示。此外,它们是酉矩阵,这意味着 A 的逆是它的共轭转置,记为 A 。
这个性质确保量子算符的输出保持量子态,这意味着振幅的*方模的和是 1。
量子算符也被称为量子门,类似于经典计算。给量子计算机编程就是写一系列要在量子位上执行的门。
作用于一个量子位的基本门的两个例子是标为 X 的非门和标为 h 的哈达玛门。

矩阵格式的 x 门和 H 门。
X 门翻转量子位(类似于经典的非门),H 门创建量子位的相等叠加状态(在经典计算中没有等价物)。我们有以下身份:
- X|0> = |1 >
- X|1> = |0 >
- X(𝑎|0>+𝑏|1>) = 𝑎|1>+𝑏|0>
- H|0> = (|0> + |1>)/sqrt(2)
- H|1> = (|0> -|1>)/sqrt(2)
为什么使用量子计算有优势?
到目前为止,我们已经看到,量子态是离散的概率分布,量子算符可以对这些分布进行线性运算。也可以通过测量状态从分布中取样。
创建一个分布,进行计算并从中取样也可以由经典计算机完成(例如用 numpy.random )。然而,这不是立即的,并且需要几个隐藏的中间步骤(创建伪随机整数生成器、从统一规律采样、取 cdf 的逆,等等)。所有这些过程通常是昂贵的。
量子计算机是一种物理设备,它将利用量子力学定律,以一种廉价的方式为你进行所有这些概率运算。
经典位的基本运算是进行 1+1、0+0、1+0、翻转位等。有了这组基本操作,您就能够对两个整数的加法进行编码,然后进行乘法运算,接下来就是其他算法了。
量子计算机的基本操作是创建一个骰子,投掷它并读取结果。从那里,你创建许多其他算法。这些算法有时可以为在传统计算机上执行的相同操作提供巨大的加速。
计算机科学的核心是把问题分成简单的步骤,然后交给一台机器,让它非常快速地执行这些简单的步骤。有了量子计算,你把你的问题分成了比以前更多的步骤,量子计算机可以非常快地执行这些步骤。你希望总成本低于一台传统计算机的成本。
身体上是什么?

来源:IBM Research ( Flickr )
存在很多技术,所有硬件提供商都在尝试自己的技术。它可以是硅中捕获的电子、冷原子或光子,我们可以单独控制它们。其他方法,如拓扑量子位,使用的基本粒子只在这种情况下研究。
在所有情况下,它归结为能够在个体水*上控制基本粒子。这是非常困难的,因为一切对环境的噪音都很敏感,这解释了建造量子计算机的困难。
总而言之,量子态是代表离散概率分布的复矢量。
量子算符是这些向量上的线性算符,其输出保持量子态。
衡量一个状态就是从潜在的概率分布中取样。
量子计算机是比经典计算机执行这些操作更快的物理设备。
在机器学习中使用
在二元分类问题中,比方说将图像标记为猫或狗,目标是从训练集构建预测器。换句话说,我们希望构建一个函数 f 比如 f(图像) ∈ { 猫,狗 }给出尽可能接*现实的结果。
通常情况下, f 的图像代表图像属于某一类或另一类的概率,例如, f(图像)= P(图像=狗)。
这种概率形式非常适合量子计算,我们希望建立一个量子态|ψ>,例如
|ψ(image)> =P(image = dog)|0>+P(image = cat)|1>
实际上,|ψ>是通过一组参数化门和输入数据构建的。多次测量可以估计不同的结果概率。
优化电路就是找到最接*现实可能性的参数。这一步对于所有的 ML 算法都是一样的,只是这次我们通过量子测量来计算结果。
我们希望在量子计算机上执行所有这些操作会比在经典计算机上更便宜。具体来说,我们希望制备和测量量子态比在 CPU 和 GPU 上执行矩阵产品更快/更便宜。
对于狗/猫分类问题,卷积神经网络表现得非常好,量子计算不太可能会更好。但是对于不同的配置,在高维空间中,有可能在特定问题上性能会更好。
参数化量子电路
量子计算探索的一个完整领域是变分电路或参数化量子电路的使用。
参数化量子电路的一般思想是创建具有可调参数的量子电路,并且该电路的有效测量将接*感兴趣的量。然后,我们可以根据电路的参数最小化这个感兴趣的量。
让我们深入一个具体的例子来说明这一点。
我们考虑以下门,并将其应用于|0 >。

我们有 U(𝜃,ϕ,λ)| 0 > = cos(𝜃/2)|0>+e^(Iϕ)sin(𝜃/2)|1>。
假设我们想最大化结果的熵,也就是
E(𝜃,ϕ,λ)=-p(u | 0 > = 0)log*(p(u | 0>= 0))-p(u | 0>= 1)log(p(u | 0>= 1))= -cos(𝜃/2)**log(cos(𝜃/2))-sin(𝜃/2)**log*(sin(𝜃/2))
那么,最佳参数是𝜃 = π/2,ϕ和λ可以取任意值。
这个例子非常简单,所以一切都可以通过分析来计算,但在更复杂的电路中,概率是通过多次测量来估计的。
当你想用一个容易计算的参数化概率分布(如高斯混合分布)来*似一个未知的难以处理的概率分布时,这个过程与变分法(变分法的名字由此而来)是一样的。
在分类问题中,人们想要创建以下参数化的量子态:
|ψ(图片; 𝜃 ) > = P(图片=狗;)|0>+p(image = cat;)| 1>**
请注意,上述表达式中的 𝜃 与前一个门的𝜃参数不一样。
训练的步骤是找到最好的等概率接*现实。这是通过经典的优化技术如梯度下降来实现的。******
问题是
我们考虑一个二进制分类问题,在{0,1} 中输入实向量𝑥,二进制输出 y 。
我们想要建造一个量子电路,它的输出是一个量子态
|ψ(x;**)>=p(y = 0 | x;)|0>+p(y = 1 | x;)| 1>************
该算法
所提出的算法由 3 个步骤组成:
- 状态准备
- 模型电路
- 测量
第一步叫做态准备,它包括将经典数据嵌入量子态。有几种方法可以做到这一点,其中一种被称为振幅编码。它包括把一个矢量的坐标映射成一个量子态的振幅值。它要求向量标准化,并具有二维幂。当数据集不满足这一条件时,可以填充并重正化向量。****

振幅编码程序。
对于熟悉量子电路符号的读者来说,状态准备电路如下:

2 量子位和 4 维输入向量的状态准备电路。
第二步是模型电路,严格来说还是分类器。参数化酉算子 U(𝜃) 是创建的,使得|ψ(x;𝜃)>=u(𝜃)|ϕ(x)>。这是一系列的将军 U ( 在前面的小节 ) 和 CNOT 盖茨(更多关于 CNOT 门的信息在这里)。****
最后一步是测量步骤,通过执行几次测量来估计属于某个类别的概率。这相当于从分布中多次取样。****
最终电路如下:

量子分类器的最终电路。
培养
执行训练以最小化二进制交叉熵损失。
使用批量随机梯度下降。计算损失函数的梯度并不明显。幸运的是,它们可以通过其他量子电路来估计。
这部分我就不赘述了,因为它比较技术性,需要更多的量子计算知识。如果你想了解更多,我鼓励你去看看这个笔记本(最后的链接)。
实验和结果
该算法已经在 iris 数据集的二进制分类上进行测试,该数据集具有大约 100 个 2 个特征的点。它已经用 IBM 开发的框架 Qiskit 实现了。完整的代码和详细的解释可以在这里找到。
如图所示,该算法运行良好。它在验证集中达到了几乎 100%的准确率。
主要的不方便就是很慢,至少在我一般电脑上的 Qiskit 模拟器上。代码当然可以优化,但是必须记住,这只是一个验证一般方法的玩具示例。这个问题必须足够复杂,量子计算才有用。

算法的最终结果。
结论
量子计算是一种完全不同的计算范式。在大状态空间上计算概率分布并对其进行线性运算是一种自然的方法。
这是一个很好的机器学习工具,但我们需要等待更好的硬件来开发实际的用例。
谢谢你的帮助,有很多信息,我尽量让它简洁。我希望你能更好地理解量子计算,以及如何将其用于机器学习。
欢迎分享您的反馈,您可以在 LinkedIn 上联系我,或者对文章发表回应。
参考资料和资源
- 玛利亚·舒尔德、亚历克斯·鲍恰洛夫、克里斯塔·斯沃雷和内森·维贝,以电路为中心的量子分类器 (2018)
- 同样的算法由 Xanadu 在 PennyLane 库中实现:https://PennyLane . ai/qml/demos/tutorial _ variable _ classifier . html
- 完整代码及解释笔记本:https://github.com/Slimane33/QuantumClassifier
去融合混淆矩阵
数据科学家使用模型从数据中得出一些结论。在监督学习的情况下,由于输入和输出(标签)都可以用于我们的数据,我们可以尝试找到一个将输入映射到标签的函数。该模型将从一组特定的数据中学习,结果将在另一组数据中进行测试。我们将参考训练数据作为我们用于第一个任务的值和用于后者的测试数据。一旦模型被测试,下一步就是在做任何决定之前找出它的性能。混淆矩阵是用于描述分类模型成功与否的表格。
混淆矩阵中的元素
我们从分类器中决定的可以是‘肯定的’或‘否定的’(是/否——有/没有)。另一方面,从我们与之比较的原始数据来看,也有两种可能的结果:“真”或“假”(是/否——有/没有)。因此,我们的表现是对来自实际数据和预测的“真/假”与“正/负”的验证。我们想衡量我们对测试数据的预测有多成功。
我们的预测分为 4 类,由可能的组合来代表。

2 * 2 种可能的结果!!!
- 真阳性(TP): 我们预测‘是’,并且它是正确的(“真”)
- 真否定(TN): 我们预测‘不’,也是正确的。
- 假阳性(FP): 我们预测了阳性结果,但它被错误地预测了。
- 假阴性(FN): 我们预测了一个阴性结果,它是“假的”
根据混淆矩阵计算的指标

实际阳性:TP + FN 和预测阳性:TP + FP
这 4 个数字说明不了什么,因为我们对积极结果的百分比一无所知。我将介绍从混淆矩阵中计算出的 3 个指标。
精度。这个百分比帮助我们确定我们的模型有多“准确”,即模型做出正确预测的百分比。然而,使用准确性作为评估模型的主要度量标准存在一些限制。我们在研究中没有考虑假阴性。对于一家招聘公司来说,我们会拒绝一个符合条件的候选人。
大多数情况下使用更好的度量标准:精确度和召回率(或灵敏度)。
Precision 讲述了我们的分类器在检测正面观察时的性能。正确分类的阳性与预测阳性总数的比率。预测的阳性率有多少是正确的?
精度= TP/(TP+FP);分母是预测的总阳性数
回忆(也称为 TP 率):模型在挑选积极的观察时有多敏感。它回答了这样一个问题:模型捕捉到的阳性占所有实际阳性的百分比是多少?
回忆(或敏感度)= TP / (TP+FN)
每个环境都是独特的,基于场景,数据科学家将决定什么样的指标适合他的模型。此外,他还必须考虑什么样的错误是可以接受的。这将帮助他选择假阳性和假阴性之间的界限。
如果你有任何想法,并想讨论,请让连接。
解构咖啡:分割烘焙、研磨和分层以获得更好的浓缩咖啡
使用分离咖啡混合物的断奏浓缩咖啡的下一次进化
一年多前,我开发了一种叫做断续浓缩咖啡的技术,用筛子将咖啡渣分成细粒、中粒和粗粒。然后我做了一个分层(断奏)镜头,首先放精细层,然后是粗糙层,然后是中间层。我发现每一层都提供了特定的味道,有助于整体的味道,通过这种方法,我得到了更好的味道。然后我就开始胡思乱想了。

分裂断奏捣实拍摄使用中等和黑暗的烘烤。
我开始考虑咖啡烘焙。我不喜欢单一产地的咖啡,因为我发现它们不均衡,而且我已经在家烘焙了三年。通常,我会将一颗非洲的咖啡豆和一颗南美的咖啡豆混合在一起,制成一种很棒的混合物。我在烘烤前混合,因为我不想把时间花在烘烤两次和烘烤后混合上。


然而,分离颗粒大小的一个自然延伸是分离咖啡混合物以分离豆类。我忍不住让过程变得更复杂,因为在那个时候,我有最复杂的浓缩咖啡准备程序。我介绍了历史、断续浓缩咖啡和断续捣实的咖啡的技术,并展示了几个月来收集的一些数据,以展示它如何在味道和 EY 方面产生更好的照片。



技术发展
为了实验,我分别烘焙了两种咖啡豆的典型混合物。我将混合物分开,并分别磨碎和过筛。我开始尝试一个六层的断奏镜头:2 个精细层,2 个粗糙层,和 2 个中间层。我通过交替选择哪一层先出现,哪一层从分离中受益最大来检测味道。我发现只有精细的那一层需要被分离,但是哪一层先出现对这项技术的益处有影响。


在第一个实验中,我分别烤了哥伦比亚蜂蜜工艺的布宜诺斯艾利斯格沙和卢旺达干工艺的鲁西齐尼亚卡伦佐。然后我把它们分别磨碎过筛,开始测试。我立刻看到了分数差异。我不知道它们有多重要,在我开始分割所有镜头的时候,我只会在烤肉的前两个镜头中改变方向。






细豆 1,细豆 2,夯实,粗混合,中混合,夯实
我收集了一些不同烧烤的数据,这些数据不足以得出任何强有力的结论,但肯定会有不同烧烤之间的差异。这是一场正面交锋:

这种比较着眼于无分割与两种不同方向:

对断奏捣固的交叉应用
断奏捣固是断奏击球的派生物。我在研究一些夏威夷的深色烘焙咖啡,我发现把所有的咖啡渣都放在过滤器里太乱了。于是我开始只放一半,分发,捣实,接着放另一半。与此同时,我对断奏浓缩咖啡有了更深的理解,我发现中间层(断奏镜头中的顶层)是决定镜头如何根据其夯实程度来判断是否成功的关键层。
我尝试在常规击球的前半段做一个较重的夯实,然后在上半段做一个较轻的夯实,于是断奏夯实技术诞生了。我开始跟踪底层压力,我发现底层压力在 300 克到 500 克之间是最佳的。对于顶层,我使用一个校*机,我跟踪校*机的深度。
当我对这种技术感到更加安全后,我开始将烤肉分成四层。我将称重并分配前两层,夯实,称重并分配后两层,然后整*。

对于断奏夯实准备,我还发现了分裂豆子的好处。准备工作包括两层,顶层和底层,底层比第一层夯实得更紧。类似于分割一杯不连续的浓缩咖啡,顶层不需要被分割。为了简单起见,我通常把它分开。
数据和分析
我花了一年的时间收集这些数据,但困难在于确保我有可控制的样本。在过去的一年里,我的技术发生了很大的变化,我会定期采集一些有无分裂的样本。最*,我整理了数据集,我发现我有合理数量的样本来说服自己,这种现象不是因为我的确认偏差,而是可以观察到的。

原始数据
绩效指标
最终得分是 7 个指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)记分卡的*均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水*。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难,会影响最终得分。
使用折射仪测量总溶解固体(TDS ),该数字用于确定提取到杯中的咖啡的百分比,并结合一杯咖啡的输出重量和咖啡的输入重量,称为提取率(EY)。
分裂分析
查看所有数据的一些散点图,很难看到常规镜头和分裂镜头的分离。这是由于我的数据收集造成的数据不*衡。

所以让我们把这些数据简化成每次烘烤的最佳组合,普通的和分开的。

模式似乎有点清晰,但我们有成对的数据,所以让我们比较一下每个镜头。就品味(最终得分)而言,分镜头似乎比普通镜头更好,对 EY 来说,它们往往更好。

当在折线图而不是散点图上查看时,我们可以对照片进行排序,并查看它们的表现。有一些异常,但不是随机的。

我们可以通过统计测试来了解这些结果差异是否具有统计显著性。就口味而言,他们是,但 ey 在分布上还是有点太接*了。需要更多的数据,但与此同时,我一直在努力增加 EY,所以我希望即使 EY 保持不变,味道也在改善。我没有足够的数据来显示这种或那种趋势。

我们可以通过烘焙和不连续浓缩咖啡或不连续捣实咖啡来进一步分解这些数据。就味道而言,有些烤肉并没有太多好处,但有些却有。对 EY 来说,有一种烤肉尤其成问题(2020 年 4 月 6 日)。

对于 2020 年 4 月 6 日的烘烤,其中两个镜头基于顶部或底部分割烘烤,而不是同时分割顶部和底部层。因此,这是 9 克的一个烤,9 克的另一个,而不是 4.5 豆 1,4.5 豆 2 在底部和顶部相同。除去这两个样本,EY 现在有了统计上的显著改善(阈值是 p 值< 0.05)。

我们可以扩展数据,将相同的常规镜头与不同的分裂镜头进行多次比较,因为分裂镜头的数量远大于常规镜头。并不是所有的分镜头都很棒。我只是在比较最好的分镜头和普通镜头。其中一些镜头有较低的最终得分和/或 EY,因为他们参与了其他实验,如加热豆,冷却研磨,或修改分配器。

健全性检查
其中一个不受控制的变量,也是我所希望的,是产出与投入的比率。理想情况下,每个镜头都是一样的,但是艺术的一部分是视觉上的结束。有些人使用天*,但我一直使用量杯,我知道给出期望输出水*的音量范围。然后我在拍摄后用标尺测量输出。在这次收集开始时,该比率通常为 0.9 比 1.1,到最后,该比率已经漂移到 1.2 比 1.4。
让我们假设 EY 和比率之间有一个线性关系,我们可以做一个最佳拟合线,如下所示。有各种各样的摆动,但我们仍然可以使用它来调整所有的 EY 到 EY 在 1:1 的比例。用于这种线性关系的镜头比成对的镜头多,因为我尽可能多地包括了那些烘烤的镜头,即使它们没有成对。
然后,我们可以看看调整后的 EY 氏综合症的配对,并测试统计显著性。同样,我们在 2020 年 4 月 6 日的烧烤中遇到了类似的问题,因为它们不是以相同的方式进行断奏和篡改。去除这些因素后,分割镜头和常规镜头之间的差异具有统计学意义。

这个结果不应该太令人惊讶,因为成对的镜头是在同一时间帧内拍摄的,所以比率的范围通常是相似的。
我在这里展示了一个基于断奏概念的作品,通过将烘焙咖啡豆分开来进一步改进浓缩咖啡。其结果是口味和提取得到了改善。这种分割烘焙的断奏技术对我的浓缩咖啡日常工作产生了持久的影响,这些实验进一步证明了浓缩咖啡的制作过程仍然是神秘的,还有发展的空间。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。
我的进一步阅读:
解构关于置信区间的常见误解
置信区间的逐步推导以及我们如何经常曲解它们。

置信区间通常被用作区间估计的常规方法。如果你曾经应用过这种方法,你可能会遇到这种说法:
- 对于 90%的置信区间,真实参数位于该区间内的概率为 90%。
似乎是合法的,不是吗?至少,在我看来,一开始是合法的。这是对置信区间最常见的误解之一。根据[ 1 ]的数据,59%的被调查研究人员落入了这个陷阱。我也不例外。
因此,让我们回到起点,在一个简单的环境中应用置信区间,并认识到为什么这种常见的误解是错误的。
区间的求导
假设我们想估计一个城市居民的*均身高。假设这个城市生活着一百万人,身高呈正态分布。假设我们知道真实的分布参数,比如说,*均身高是1.8m标准差是 0.1m 。这些是总体参数,我们通常不知道,希望通过测量来估计。

居住在城市中的所有人的身高分布。
当然,如果我们测量一百万人的身高,就可以得到真实的*均值,根本不需要任何估算。但在现实中,我们通常进行有限的实验,并希望使用总体中的一些有限样本来估计真实参数。
假设我们随机抽取 50 个人,测量他们的身高。这 50 个人是我们人口中的一个样本。我们给它们取一个代号“Subset-1”。我们可以通过计算子集 1 的*均身高(样本*均值)来估计城市中所有人的*均身高。这样做,我们就会得到一个所谓的 点估计 。

50 个随机人群*均身高的点估计
然而,如果我们随机抽取另一个 50 人的子集,*均身高的值会有所不同。每个随机子集都会给我们不同的结果。我们应该如何选择能够更好地估计真实值的唯一子集呢?
没有办法确定哪个子集会给我们更好的结果。为了将这种不确定性考虑在内,我们可以计算一个区间来估计真实的均值。那就是所谓的 区间估计 。
我们来找这样一个区间:
这是对真实*均身高(样本*均值)的估计:

50 个人的不同子集将产生不同的估计,这就是为什么*均身高也是具有某种分布的随机变量。这是带有参数的样本*均值的采样分布:

其中 s 是样本的估计标准差:

对于子集 1,我们得到以下结果:

因此,对于基于子集 1 的*均高度分布,我们得到:

让我们画出这个分布图:

子集 1 的*均高度的估计分布
我们预计,如果我们对不同人群重复测量,*均身高值将遵循相同的分布。例如,这种测量值的 90% 将匹配区间【1.757;1.803] 。让我们放大 x 轴,并在图表中查看:

子集 1 *均高度的估计分布
这是子集 1 的 90%置信区间。
如果我们使用常用的公式和 Z 表,我们会得到相同的结果:

那么,我们如何解释上述区间的 90%置信水*呢?
考虑到这个区间的形成方式,我们可以得出结论,该区间覆盖了 50 个随机人的*均身高测量值的 90%。因此,人们可以期望在未来 90%的测量中找到这样一个区间内的*均高度。我们可以通过随机抽取 100 个 50 人的子集,计算*均身高,并将其与我们的分布进行比较来检查:

红色虚线——由 50 名随机抽样的人重复计算 100 次*均身高的结果。
但是这样的期望肯定不能满足现实。正如我们所看到的,落在估计的90%区间之外的测量值(红色虚线)的数量远大于 10。原因是我们已经根据某个随机样本均值计算了我们的区间。90%的观测值只有与真实值相匹配才会落在估计区间内。我们可以绘制真实区间,因为我们知道真实参数:


红色虚线—100 次估计的结果,50 个随机人群的*均身高
但是,如果我们重复我们的测量,并建立一个置信区间,比如说,20 个随机抽样的子集,每个子集 50 人,会发生什么?以下是我们将得到的结果:

蓝线——20 个随机样本的 90%置信区间,每个样本 50 人。红色虚线——真实*均值。
可以看出,20 个置信区间中有 2 个不包括真实*均值。因此,如果我们继续进行这样的实验,一个给定的置信区间包含真实参数的几率将趋于 90% 。这就是信心水*的意义所在。
现在让我们回到主要问题:
我们是否可以说,一旦创建了一个区间,真参数(我们例子中的*均身高)就会以 90%的概率落在这样一个区间内?
答案是否定的,没有办法得出这样的概率。一旦创建了区间,真实的参数要么在区间内,要么在区间外,没有人能明确地确定它到底落在哪里。我们只能说这样的区间可能包含真实均值的频率,这就是置信度的意义所在。
置信区间的本质是它们可能包含真实值。在我们的例子中,置信区间倾向于包含 90%试验中的真实值。但这并不意味着对于某个特定的区间,有 90%的机会在该区间内找到真实值。
最后,让我们看一看原始资料,发现纽曼(作为置信区间的最初支持者)写到了它[ 2 ]:
构建置信区间的理论统计学家可以与机会游戏的组织者进行比较,在该游戏中,游戏者有一定范围的可能性可供选择,而无论他实际选择什么,他获胜的概率以及银行失败的概率都具有永久相同的值,1 — α 。赌徒对赌什么的选择,超出了银行的控制,对应于真实意义的不受控制的可能性,具有这样或那样的价值。银行赢得游戏的情况对应于真实均值实际值的正确陈述。在这两种情况下,在一长串未来“游戏”中“成功”的频率是大致已知的。另一方面,如果银行的所有者,比方说,在轮盘赌的情况下,知道在特定的游戏中球停在了区域№1,该信息不会以任何方式帮助他猜测赌徒们是如何下注的。同样,一旦抽取了样本,确定了置信区间的值,这里采用的概率计算就无助于提供里面的真实值是什么这个问题的答案。
结论
如果遇到或者需要计算一个置信区间【a;b] 对于置信水* α ,你需要记住:
- 置信水*不意味着真实值落入[a;b] 是等于α;
- 置信水* α 是而不是落在α内的样本数据的百分比;b];
- 置信水* α 是而不是真实*均值落在内的实验百分比;b] 。
置信水* α 意味着通过使用不同的样本进行重复的区间计算,我们将得到一个置信区间的百分比,包括一个倾向于 α的真实总体参数。
如果你发现一些置信区间概念令人困惑,我鼓励你去看看维基百科文章[ 3 ]中的其他误解和研究。
用 Python 修饰类中定义的方法
类中的方法修饰符

图片来自 Roselyn Tirado via Unsplash
装饰方法
Decorators 为 Python 中的函数和方法添加功能提供了一种方便而优雅的方式。装饰器可以通过多种不同的方式实现。decorators 的一个有用用例涉及到将它们与类中定义的方法一起使用。在我们创建的类中修饰方法可以扩展已定义方法的功能。例如,我们可以实现数据完整性检查,或者将方法调用的输出写入文件。我们选择做什么真的取决于我们自己。方法装饰者只是为我们提供了以优雅的方式扩展功能的工具。
和往常一样,用一个例子可以很好地展示 decorators 和方法的使用。
在下面的例子中,我创建了一个名为 NumericalOps 的简单类,它需要两个参数,val1 和 val2。在 init 构造函数中,这些参数被设置为对象中的属性。接下来,我在这个类中定义了 2 个方法,即 multiply_together 和 power。
让我们提出一个相当琐碎和做作的场景。我希望对象中设置的两个属性 val1 和 val2 是数字整数。multiply_together 方法只是将两个值相乘,然后返回该操作的值。重要的是,在 Python 中,可以对一个字符串进行乘法运算,比如用一个整数。当我们创建 NumericalOps 类 x 的实例并传入两个参数 2 和' my_string '时,就演示了这一点,如下例的控制台输出所示。

为了提供数据输入完整性,可以使用装饰器来装饰类中定义的方法。目前,在示例中,装饰器@integer_check 被注释掉了。
为了提供数据完整性,我将编写一个名为 interger_check 的装饰器。要装饰一个类中的方法,首先使用“@”符号,后跟装饰函数的名称。
装饰器只是一个函数,它将一个函数作为参数,然后返回和另一个函数。在这里,当我们用 integer_check 修饰 multiply_together 时,integer 函数被调用。multiply_together 方法作为参数传递给 integer_check 函数,并返回 inner。然后调用本地内部函数,它接受我们称为 ref 的对象,并使用 isinstance 函数检查属性。如果传递了一个非整数类型,例如“my_string”,则会引发一个 TypeError 异常,并且会向控制台输出一条消息,告诉用户他们哪里出错了。但是,如果两个参数都是整数,inner 将返回原始方法,并将对象作为参数传递。
这个例子的源代码可以在我的 GitHub 页面上找到,这里的和下面的。

对多个方法使用同一个装饰器
为了增加 decorators 的可用性和实用性,我们可以将它们的实现设计为使用多种方法。
同样,这最好用一个例子来说明,所以让我们以上一节中的例子为基础。
让我们提议,我也希望 integer_check 装饰器验证我们在 power 方法中使用的指数也是一个整数。这在逻辑上是有意义的,因为当我们调用 power 方法时,它只是调用 multiply_together 方法,并将该方法的返回值乘以指数。因此,在每种情况下,我都需要确保 val1、val2 和指数都是整数。
为了实现这种行为,我对 integer_check 装饰器进行了修改。我只是在装饰器内部定义的局部内部函数中为 expo 参数设置了一个默认参数。现在,如果我们在我们的实例 y 上调用 power 方法,inner 将被返回,然后用我们在内部定义中标记为 ref 的对象和 expo 值进行调用。
在条件块中,如果 expo 被传递,我们使用 isinstance 函数检查它的类型,如果它不是整数,则引发错误,或者如果指数和 val1 和 val2 都是整数,则返回带有对象和指数的方法。
有用的是,我们仍然可以在 multiply_together 方法上使用 integer_check 装饰器,因为 expo 的缺省值为 None。
现在,我们有了一个装饰器,它可以在我们的类中跨多个方法执行用户输入验证。

使用整数作为输入,我们在控制台输出中得到预期的行为。

对于错误的输入(非整数类型),我们得到一个有用的指示性错误消息。

这个例子的源代码可以在这里找到。
摘要
当然,和往常一样,给出的例子相当琐碎和做作。还有其他方法来实现这里看到的行为,不需要装饰者。我在这里的目的是演示装饰器是如何工作的,以及如何将它们整合到您的代码设计中。对于那些感兴趣的人,我还写了另外两个教程,详细介绍了如何使用装饰器来装饰函数 s,以及装饰器本身如何成为一个类。这两篇文章的链接可以通过访问链接找到。
Python 中装饰器的介绍
了解如何改变对象的行为

来源:https://www . dreams time . com/photos-images/autumn-scene . html
介绍
我们习惯于在函数中传递和返回各种数据类型。是时候开始从函数传递和返回函数了。我们举个例子。

在这个例子中,我们有一个名为test的函数,它根据一个条件调用两个内部函数中的一个。

然而,我们也可以返回对函数的引用,而不是调用函数。然后可以使用该引用来调用该函数。我们再举一个例子。

在这个例子中,我们返回的是_inner而不是_inner().,这种引用的返回和以后的使用是 Python 中装饰器的基本思想。
装修工
装饰器只不过是 Python 中函数的包装器。它将感兴趣的函数作为参数,在调用它之前和之后执行某些任务并返回结果。

我们传递一个引用say_hello给我们的装饰器,然后它返回一个wrapper.,我们用这个包装器调用我们的函数。
现在,我们不希望每次使用 decorators 时都键入所有这些内容。我们不需要。由于 Python 的语法糖,我们可以做同样的事情,如下所示:

现在让我们稍微修改一下装饰函数。现在,它非常有限。它不接受任何参数,也不返回函数返回的值。我们来补充一下。

这是编写装饰函数的一个很好的模板。让我们尝试一些简单的例子。这些不是最好的例子,但是,我希望它们可以作为一个好的起点和尝试新奇事物的动力。
1.检查统计数据
我们已经看到标准化在任何数据科学应用中都是重要的一步。因此,每当我们归一化某个东西时,我们可能想要检查归一化前后的*均值和标准偏差。为此,我们可以这样做

当我们在卷积后归一化图像以确保所有值都在 0 到 255 之间时,也可以使用这种方法。
2.强制性文件
您可以使用__doc__属性访问功能文档。如果您正在开发一个能够自动生成文档的高级应用程序,您会希望确保您的所有代码都有文档记录。让我们试试:

查看 Python 中的 inspect 库,了解更多关于如何在 Python 中检查和使用活动对象的信息。
3.注释
类似于文档,我们可以改变注释在 Python 中的行为。当我们在 Python 中使用注释时,通常是为了确保输入和输出是某种类型。
但是,我们可以将注释用于其他用途。也许我们可以使用 output 注释将输出强制转换为预期的数据类型,如果它还不是该类型的话。

结论:
这就是本文的全部内容。我希望它能很好地介绍 Python 中的装饰者。从这里开始。了解装饰者更高级的用例。学习如何将它们应用到课堂上。学习其他库,把它们和 decorators 结合起来,构建一些有用的东西。
Decorators 和元类(下一篇文章)可以作为强大的工具,按照您想要的方式定制 Python。
~快乐学习
@ Python 中的 Decorators🍃(高级)
提升你的 Python 编程水*(奖励 : *args **kwargs )…..🔥

B 自己比赛吧,它确实包含了很多代码。✌
这些为什么难以理解,不用我解释,就是你在这里的原因(不要指望理论只有代码)。但是你真的需要写装饰者吗?
编写 Python 代码的乐趣应该在于看到短小、简洁、易读的类,这些类用少量清晰的代码表达了大量的动作——而不是让读者厌烦得要死的大量琐碎代码。古迪奥·范·罗森。(python 的创造者)
目录:(可点击)
- 什么是装修工?
- 操纵 Python 函数。
1 。给多个变量分配一个函数。
2。在函数中创建函数。
3 。将一个函数作为参数传递给其他函数。
4。函数可以返回其他函数。 - 如何表示和使用装饰者。
- 装饰者的真实例子。
1。=>获取某个功能的执行时间。2
。Deco=>并行运行 python 函数。
3。ShowMe=>*获取 CPU 时间文件等一个 python 函数。***** - Python 内置的类装饰器。
1。@ class method
2。 @staticmethod
3。@属性
加成:学习如何使用*args & **kwargs
decorator 只不过是在不改变现有方法的情况下向现有方法添加新功能的函数。
要理解 Decorators,你需要理解 Python 中的函数,函数是一级对象,也就是说,我们可以给同一个函数分配多个变量,或者我们甚至可以将它们作为参数发送给其他函数。
让我们看看用 python 函数可以做的一些很酷的事情。
1.将一个函数赋给多个变量。
**>>> **def** func(x):
... return x.upper()
>>> func("roar")
'ROAR'>>> new_func = func ***# Assign func to a variable.***>>> new_func("meow")
'MEOW'>>> **del** func
# We can call the new_func even after deleting the func
>>> new_func("meow "*2)
'MEOW MEOW '**
2.在函数中创建函数。(对C/C++程序员来说是新的。)
****def** factorial(n):
*"""
Calculates the factorial of n,
n => integer and n >= 0.
"""*
**if** type(n) == int **and** n >= 0:
**if** n == 0:
**return** 1
**else**:
**return** n * factorial(n-1) ***#*** ***Recursive Call***
**else**:
**raise** **TypeError**("n should be an integer and n >= 0")**
上面的代码有什么缺陷?
factorial(10)递归检查 10,9,8,7…的类型,这是不必要的。我们可以通过使用内部函数很好地解决这个问题。
****def** factorial(n):
*"""
Calculates the factorial of n,
n => integer and n >= 0.
"""*
**def** inner_factorial(n):
**if** n == 0:
**return** 1
**else**:
**return** n * inner_factorial(n-1)
**if** type(n) == int **and** n >=0:
**return** inner_factorial(n)
**else**:
**raise** **TypeError**("n should be an integer and n >= 0")**
嘿,你可以用一个室内设计师。好的,让我们等等。
3.将函数作为参数传递给其他函数。
****import math
def** sin_cos(func, var):
print("Call this" + **func.__name__** +"function")
print(func(var))sin_cos(**math.sin**, 60) # -0.3048106211022167
sin_cos(**math.cos**, 45) # 0.5253219888177297**
4.函数可以返回其他函数。
****def** sound(range):
"""
Args: range (Type of sound). (<class 'str'>)
Return: function object of the sound (<class 'function'>)
"""
**def** loud(x):
print(x.upper() + '🐯')
**def** low(x):
print(x.lower() + '🐱')
**if** range == 'loud':
**return** loud
**else**:
**return** lowtiger = sound("loud") ***# you can use this as a functions.***
tiger("roar..") **# ROAR..🐯**cat = sound("low")
cat("MEOW..") **# meow..🐱****
当我第一次看到这个的时候,我也有点困惑。对于每个范围,sound返回其各自的函数。一个更有用的例子是创建一个 n 次多项式。
***Ref:* [https://www.python-course.eu/python3_decorators.php#Functions-returning-Functions](https://www.python-course.eu/python3_decorators.php#Functions-returning-Functions)**def** polynomial_creator(a, b, c):
"""
**Creates 2nd degree polynomial functions**
"""
**def** polynomial(x):
**return** a * x**2 + b * x + c
**return** polynomial
p1 = polynomial_creator(2, 3, -1)
p2 = polynomial_creator(-1, 2, 1)x = -2
print(x, p1(x), p2(x)) # -2 1 -7**
简短练习: 试写一个以次数和参数为自变量,返回一个 n 次多项式的函数。

查尔斯·德鲁维奥在 Unsplash 上拍摄的照片
完成了基础工作,接下来就很棘手了。(👀)
让我们从一个简单的装饰器开始,它在函数运行之前打印出它的名字。
🦋用你自己的例子来试试吧🦋
🔥 Pro 提示:通过使用*args你可以给一个函数发送不同长度的变量。*args将其作为元组接受。了解更多 [*args](https://realpython.com/python-kwargs-and-args/) 和 [*kwargs](https://realpython.com/python-kwargs-and-args/)
decorators 的语法与我们在上面的例子中表达的不同。通常用**@** ( 美化你的代码)来表示。
🦋用你自己的例子来试试吧🦋
🔥 ProTip: 通过使用 Code-Medium 你可以直接从你的 Medium 文章中 创建 & 编辑 GitHub Gists。(如上图)。
注意:使用 decorator 包装函数时,原始函数的属性,如 doc (docstring)、name(函数名)、module(定义函数的模块)将会丢失。
尽管可以在 decorator 函数中覆盖它们,但 python 有一个内置的 decorator @ wraps 来做这件事。
如果你仔细看,我会打印每个函数的输出,如果你想返回一个输出的话。您需要在包装函数中添加一个额外的 return。
使用 decorators 时返回的用法。

为了更好地理解,让我们看一些装饰者的真实例子。
- 定时器: 跟踪一个函数运行所用的时间。
🏄♂️理解args 和kwargs 复制代码并通过传递不同的变量来运行它🏄♂️**
🔥 Pro 提示:您可以通过使用original_looper = looper.__wrapped__ ( 假设您已经使用了 *@wraps*)解包来访问原始函数
2. Deco: 一个自动并行化 python 程序的库Link。******
Alex Sherman 创建了这个简单的库,名为 deco,它允许 python 函数并行运行,只需添加一个装饰器很酷吧..!。**
你要并行运行的函数用 @concurrent
修饰,调用并行函数的函数用 @synchronized 修饰
****@concurrent** # We add this for the concurrent function
**def** process_lat_lon(lat, lon, data):
#Does some work which takes a while
**return** result
# And we add this for the function which calls the concurrent function
**@synchronized
def** process_data_set(data):
results = **defaultdict**(dict)
**for** lat **in** range(...):
**for** lon **in** range(...):
results[lat][lon] = process_lat_lon(lat, lon, data)
**return** results**
亲提示🔥:更快运行 python 代码的类似但先进的科学计算库是 numba 。
3. Showme : ShowMe 是一组简单的非常有用的 Python 函数装饰器。它允许您查看跟踪信息、执行时间、cputime 和函数文档。 链接 。
打印传入的参数和函数调用。
****ref:** [https://github.com/navdeep-G/showme](https://github.com/navdeep-G/showme)@showme.trace
def complex_function(a, b, c, **kwargs):
...
>>> complex_function('alpha', 'beta', False, debug=True)
calling haystack.submodule.complex_function with
args: ({'a': 'alpha', 'b': 'beta', 'c': False},)
kwargs: {'debug': True}**
打印功能执行时间。
**@showme.time
def some_function(a):
...
>>> some_function()
Execution speed of __main__.some_function:
0.000688076019287 seconds**
打印功能 CPU-执行时间。
**@showme.cputime
def complex_function(a, b, c):
...
>>> complex_function()
CPU time for __main__.complex_function:
3 function calls in 0.013 CPU seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.013 0.013 0.013 0.013 test_time.py:6(test)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}**
参考资料部分提供了更多示例的链接。
到目前为止,您已经了解了装饰人员是如何工作的,并且创建了自己的装饰人员。让我们看看一些内置的 Python 装饰器。

流行的内置 Python 装饰器
**@classmethod:** 创建类的一个实例。(通 *cls* 非 *self* )
**示例:假设你从不同的数据类型中获取数据,而不是创建多个类,我们可以使用@classmethod 来处理它。
Python 中@classmethod 的用法。
**@staticmethod:** 你可以在不创建类实例的情况下使用这个装饰器的方法。(无需通过 *self* )
举例 : 假设你想为一个包含一些逻辑但却是该类的 not 属性的类创建一些 helper 函数。
**@Property**:OOPs 中使用get & set命令的一种方式。
每次你调用set或get到盒子的maxlimit值,它会通过@property和@maxlimit.setter.
参考文献:
- 高级 Python 作者 Brend Klein。
-如果你喜欢 python 你会爱上 真正的 Python 。
-详细介绍@ property如何工作。
——牛逼巨蟒 装修工 。**
我知道这很长,但是如果你到了这里👏敬你。不断学习,不断成长。
Python 中的装饰者:数据科学家的基础
用一个具体的例子来理解基础!

戈兰·艾沃斯在 Unsplash 上的照片
Python 中的 Decorators 用于扩展可调用对象的功能,而无需修改其结构。基本上,装饰函数包装另一个函数来增强或修改它的行为。
这篇文章将向你介绍 Python 中装饰者的基础知识。
让我们编写一个包含装饰器实现示例的 Python3 代码:
装饰定义
def **decorator_func_logger**(**target_func**):
def **wrapper_func**():
print("Before calling", **target_func**.__name__)
target_func()
print("After calling", **target_func**.__name__)
return **wrapper_func** def **target()**:
print('Python is in the decorated target function')**dec_func** = **decorator_func_logger**(**target**)
**dec_func()*****Output:***air-MacBook-Air:$ **python DecoratorsExample.py**
('Before calling', 'target')
Python is in the decorated target function
('After calling', 'target')
上面的装饰结构帮助我们在调用目标函数之前和之后在控制台上显示一些注释。
下面是定义装饰器的简单步骤;
- 首先,我们应该定义一个可调用的对象,比如一个装饰函数,其中也包含一个包装函数。
- 装饰函数应该将一个目标函数作为参数。
- 它应该返回包装函数,该函数扩展了作为参数传递的目标函数。
- 包装函数应包含一个目标函数调用以及扩展目标函数行为的代码。

多鲁克·耶梅尼西在 Unsplash 上拍摄的照片
def **decorator_func_logger**(**target_func**):
def **wrapper_func**():
print("Before calling", **target_func**.__name__)
target_func()
print("After calling", **target_func**.__name__)
return **wrapper_func**@**decorator_func_logger**
def **target()**:
print('Python is in the decorated target function')**target()*****Output:***air-MacBook-Air:$ **python DecoratorsExample.py**
('Before calling', 'target')
Python is in the decorated target function
('After calling', 'target')
在 Python 提供的语法糖的帮助下,我们可以简化 decorator 定义,如上所示。
注意@decorator _ func _ logger被添加在我们想要修饰的 target 函数之前。然后我们可以直接调用目标函数。不需要像我们在第一个例子中所做的那样,显式地分配装饰器。

多鲁克·耶梅尼奇在 Unsplash 上拍摄的照片
用参数定义多个装饰器和装饰函数
**import time***def* **decorator_func_logger(*target_func*):**
*def* **wrapper_func(*****args, **kwargs****):**
print("Before calling", target_func.__name__)
**target_func(*****args, **kwargs****)**
print("After calling", target_func.__name__)
return **wrapper_func***def* **decorator_func_timeit(*target_func*):**
*def* **wrapper_func(*****args, **kwargs****):**
ts = time.time()
**target_func(*****args, **kwargs****)**
te = time.time()
print (target_func.__name__, (te - ts) * 1000)
return **wrapper_func****@decorator_func_logger
@decorator_func_timeit**
*def* **target(*loop*):**
count = 0
print('Python is in the decorated target function')
for number in range(loop):
count += number**target(100)
target(3000)*****Output:***air-MacBook-Air:$ **python DecoratorsExample.py**('Before calling', 'wrapper_func')
Python is in the decorated target function
('target', 0.015974044799804688)
('After calling', 'wrapper_func')('Before calling', 'wrapper_func')
Python is in the decorated target function
('target', 0.47397613525390625)
('After calling', 'wrapper_func')
通过使用' @ '语法在目标函数之前添加几个装饰器,可以很容易地用多个装饰器来装饰目标函数。装饰器的执行顺序将与它们在目标函数之前的排列顺序相同。
注意,在我们的目标函数中有一个参数 loop 。只要包装函数使用相同的参数,这就没有问题。为了确保装饰器可以灵活地接受任意数量的参数,包装器函数使用了 (*args,kwargs)** 参数。
关键要点
- Decorators 定义了可重用的代码块,您可以将这些代码块应用到可调用的对象(函数、方法、类、对象)来修改或扩展其行为,而无需修改对象本身。
- 考虑到你的脚本中有许多函数执行许多不同的任务,你需要给所有的函数添加特定的行为。在这种情况下,将相同的代码块复制到函数中以获得所需的功能并不是一个好的解决方案。你可以简单地修饰你的函数。
结论
在这篇文章中,我解释了 Python 中 decorators 的基础知识。
这篇文章中的代码可以在我的 GitHub 库中找到。
我希望这篇文章对你有用。
感谢您的阅读!
TensorFlow 2.0 中的自回归过程表示
张量流中自回归过程的一阶泰勒级数表示
张量流 2.0
与业务相关的时间序列通常是非连续的,或离散的,基于时间的过程。从操作上来说,对于企业来说,知道或者能够量化一个时间序列在未来什么时候会达到顶峰或者低谷可能是有用的。目标是捕捉趋势和周期模式,并预测未来大于 1 个样本的信号。示例笔记本可在本文的张量流公式部分获得。
趋势、周期性和噪声
在大多数与商业相关的应用中,时间序列在一段时间内具有非常数的均值和方差,或者可以说是非*稳。这与电路、音频系统和通信系统分析中使用的静态信号和系统形成对比。*均值变化的方向表示时间序列的趋势。噪声的变化也可能是某个随机过程的函数。这种噪声可能随着时间的变化而增大或减小。
有一个粒度时间限制到哪个周期或循环模式可以被捕获。在数字信号处理中,奈奎斯特速率是捕获周期为 n 的重复出现的模式所需的最小采样周期。本质上,采样速率需要小于重复出现模式的半个周期。例如,假设数据中有一个功能,它每 6 个小时测量一次销售额。可以捕获的最精细的模式是每 12 小时重复一次的模式。
自回归模型公式
自回归模型和开环反馈系统(一种控制系统)有一些相似之处。这两个系统都依赖于模型先前的输出。我们希望这两个系统都是稳定的,也就是说,不会爆发成指数输出。这些系统的不同之处在于,自回归预测可能依赖于多个滞后输入特征。自回归模型的形式如式(0)所示。

其中 T 是滞后要素的数量,w 表示自回归权重,y(t-i)表示滞后时间序列,y*(t+1)是 t+1 时的预测值。
目标是使用一阶泰勒级数*似值创建自回归模型的线性化形式。自回归公式是递归的,这意味着下一个值取决于前一个值的级联。y(t+1)处的值是使用时间步长 t 周围的 f(t+1)的泰勒级数展开来估计的。等式(2)显示了使用一阶泰勒级数*似的 y(t+1)的估计值。注意,等式(2)右侧的-1 常数将被权重吸收。

其中 f(t)是一个递归密集层,它用一些误差项表示 y(t),y*是预测输出,w_t 是权重,T 是滞后特征的数量。等式(2)示出了简单情况下的泰勒级数展开,其中 y(t+1)取决于先前的值,即 f(t+1)。我使用 f(t)而不是 y(t)的原因是因为 y(t)代表实际滞后的数据点,而不是依赖于时间的自回归函数。
在方程(3.1)中,f(t+1)相对于 f(t)的偏导数是相对于 w(t)取的。这种偏导数产生 f(t),即前一个函数值,可以用一阶泰勒级数展开式再次展开。有趣的是,这将导致类似于自回归公式的模型公式。区别在于滞后特征是有限的和离散的,而不是无限的。

(3.2)可以通过用每个滞后时间步长的先前时间序列值替换递归层 f(t)而被重新表述为线性模型,即 f(t)的值被 y(t)替换。最后,可以添加额外的滞后成分来创建自回归模型。
用于训练自回归模型的最终形式在等式(4)中示出。截距被限制为自回归权重之和。这使得该模型对中心趋势没有偏见,并且随着时间的推移具有适应性。

其中 N 是数据点的数量,T 是滞后要素的总数,w 表示自回归权重,y(t-i)表示滞后时间序列,y*(t+1)是 t+1 时的预测值。等式(5)中所示的目标函数 MSE 相对于参数是可微分的,并且可以用 TensorFlow 来优化。
应用同样的逻辑,可以预测多变量时间序列。所有时间序列的前一个值用作协变量,以同时预测所有时间序列的下一个值。在这种情况下,截距是输出节点的自回归权重之和。多元公式允许堆叠多个自回归层,以创建深度自回归模型。
澳大利亚墨尔本的每日最低温度和降雨量
澳大利亚墨尔本日最低温度和降雨量数据集用于建立自回归预测模型。该数据集包括从 1981 年开始的 3625 天的温度和降雨量。有一些丢失的值,但是这些值是为每个系列插入的。这些序列同时预测使用深度自回归模型。
温度
下图显示了整个时间段墨尔本的气温。随着时间的推移,温度似乎有明显的周期性变化。

降雨
下图显示了墨尔本不同时间段的降雨量系列。降雨量被限制在每天 0 厘米的降雨量,这使得使用自回归模型建模变得困难。为了使用降雨量,创建了降雨量的 60 滚动*均值,如下图所示。


数据集构建
- 这两个系列,即温度和降雨量,在训练之前首先被标准化。
- 数据集是通过为时间序列中的每个观察值创建 365 个滞后特征来构建的。例如,观测 365+1 将具有之前的 365*2 特征。
- 前 365 个观察值从训练数据集中排除,以避免丢失值。
- 两个时间序列的最后 1,130 个观测值,即 3 年,被用作检验预测有效性的保留集。
张量流公式
下面的代码块显示了上述自回归模型的 TensorFlow 代码。示例笔记本可在这里找到。

该模型具有大小为(N,M)的输入,其中 N 是数据点的数量,M 对应于降雨和温度的 730 个滞后特征。大小为 30 的隐藏层与自回归激活一起使用。该模型用随机梯度下降、均方误差损失、Adam 优化器、早期停止和小学习率来训练。虽然利用了早期停止,但它可能不是必要的,因为自回归模型产生的结果应该是固有地正则化的。
滚雪球自回归时间序列
可以通过将以前的预测滚雪球式地加入自回归模型来创建预测。滚雪球式的时间序列的方差可能有随时间增加的趋势,或者变得不稳定,即使实际的时间序列是稳定的。一个不合适的模型可能会变得不稳定,并随着时间的推移而发生变化。如果预测的滚雪球式的时间序列始终偏于实际趋势之上或之下,就会出现不稳定性。在模型公式中,约束截距应随着时间的推移产生更大的稳定性和适应性。
为了评估预测稳定性,该模型在不同的随机训练验证分裂上训练了 100 次,并且创建了 100 个模型。为保留集上的每个模型生成了一个滚雪球式的时间序列。期望值和标准差分别用于创建预测和置信区间。
温度预报结果

降雨量(60 滚动*均值)预测结果

在上面的图中,实际观测值、训练预测值和滚雪球式预测值分别用绿色、蓝色和橙色系列表示。温度的预测值和预报值似乎捕捉到了全球周期模式。然而,100 个预测的变化没有捕捉到时间的变化。降雨量的预测值(60 个滚动*均值)在训练数据集中似乎过拟合。过度拟合可能是由于使用了滚动*均特征。该系列的趋势在崩溃为周期性模式之前,准确地捕捉了约 1 年的预测值。大约 1 年后未能准确捕捉到趋势。
结论
自回归函数的一阶*似用于制定目标函数和模型定义。发现自回归激活层的截距被约束为输入权重的和。通过堆叠自回归层,使用 TensorFlow 2.0 创建了深度自回归模型。该模式被用来同时预报澳大利亚墨尔本的温度和降雨量。自回归公式不适用于截断时间序列,需要滚动*均变换来预测降雨量。这些预测是通过将以前的预测滚雪球式地回归到模型中来创建的。该模型似乎捕捉到了小的全球趋势和周期性模式。
FB Prophet 预测比较
该模型与 FB Prophet 相比如何?Prophet 是一个完整的时间序列预测套件,有许多可调参数。为了比较,我使用了来自快速入门教程的开箱即用模型。
Prophet 似乎使用了周期图模型。它基本上挑选出顶部的周期频率 f,并将其包装在正弦和余弦函数中,以创建特征集,即 sin(f)和 cos(f)。该软件包似乎也使用了逻辑回归模型的输出。逻辑回归模型预测序列是上升还是下降。该软件包似乎支持向预测中添加额外的变量,但似乎还不支持同步多变量预测。该比较已添加到示例笔记本中。
温度预报结果

降雨量(60 滚动*均值)预测结果

在上面的图中,实际观测值、训练预测值和滚雪球式预测值分别用绿色、蓝色和橙色系列表示。温度的预测值和预报值似乎捕捉到了全球周期模式。100 个预测的变化捕捉到了随时间的变化。温度趋势似乎是上升的,但这可能不是实际趋势。降雨量的预测值(60 个滚动*均值)似乎反映了一种一般的年度周期模式。该模式在整个验证过程中是一致的。降雨量似乎呈下降趋势,但这可能不是实际趋势。
深度语境化的词汇表征——一种新的词汇嵌入方法

桑迪·米勒在 Unsplash 上拍摄的照片
单词表示是现代自然语言处理系统的组成部分。单词表示基本上给了我们一种方法,将一段文本转换成我们的计算机系统可以阅读的数字。
多年来,已经开发了许多单词表示法,旨在捕捉单词的语义和句法依赖性。开发能够捕捉人类语言微妙之处的好的单词表示是一项极其困难的任务。好的单词表示应该把相似的单词放在一起。例如,单词flight的表示应该比单词apple.的表示更接*于单词plane的表示。另一个重要的考虑是语言的多义性。这是一个单词在不同的上下文中呈现不同含义的能力。举个例子,
一天一个
*Apple*医生远离我。*Apple*今天发布了其最新的 iPhone 型号
在上面的两个句子中,单词“Apple”有不同的含义,单词表示必须考虑到这一点,而不是独立于上下文计算单词的相同表示。
单词编码的历史
对单词进行编码的最简单的方法可能是标签编码或者对每个唯一的单词进行一次热编码。标签编码遇到了在机器学习模型中加入偏差的问题。被给予较高标签的单词可以被模型感知为更重要。

标签编码的例子
为了缓解这个问题,独热编码用一个向量来表示每个单词,该向量的特定位置被标记为 1,其余位置都是 0。向量的长度是我们的训练语料库中的总字数,可以是几千万。拥有如此巨大和稀疏的向量会导致计算和存储问题,从而使这种表示对于现实世界的应用不切实际。

一键编码的例子
2013 年,谷歌通过开发其 Word2Vec 模型取得了突破,在单词表示领域迈出了巨大的步伐。Word2Vec 考虑了单词含义的上下文相关性质,这意味着它基于分布式语义的思想。通俗地说,我们可以用下面这句名言来总结这一点。
从一个人交的朋友你就可以知道他说了什么——约翰·鲁珀特·弗斯
因此,为了计算一个单词的表示,我们将首先尝试学习该单词出现的上下文。与出现在远处的单词相比,在一个句子中彼此靠*的单词将被给予相似的表示。经过训练的 Word2Vec 模型为我们提供了有意义的输出,如下所示:

这里我们展示了 Word2Vec 为每个单词找到的最相似的单词——摘自 TurkuNLP 小组的在线演示。
尽管它没有遭受简单方法的不良属性,但它确实有一些限制。
- 它不能为模型以前没有见过的单词产生表示。这些被称为词汇之外的单词。
- 它不能很好地学习生僻字的表达。
斯坦福研究人员发布的模型 GloVe ,是分布式语义学小组的又一成员。尽管它通过考虑除了局部上下文之外的单词的整体共现统计来改进 Word2Vec 模型,但是它仍然遭受与 Word2Vec 相同的问题。
那么,一个算法如何计算出它以前没有见过的单词或者很少在文本中出现的单词的表示呢?进入 深度语境化的文字表述 ,甚至在 NAACL 2018 正式发表之前就受到了很多关注。所提出的模型在几乎每个 NLP 基准上都取得了最先进的结果。由于这一点,以及它的独创性,它被授予了 NAACL 的杰出论文这个模型如何解决与先前模型相关的问题?
让我们深入这项突破性的工作,并尝试分解细节。
介绍
这篇论文提供的第一个观点是,为了解释词汇之外的单词,我们必须将单词分解成原子单位并对它们进行处理。这使得该模型能够获得对单词形成过程的一些洞察。例如,该模型没有将单词“destroying”作为输入,而是将单词视为字符组合的并集‘de+stabilize+ing’。
本文讨论的第二个问题是语言多义性问题。它认识到一个词根据上下文可能有一个以上的意思。所以它不会给一个单词分配任何一个向量。相反,它通过将整个序列作为输入来计算单词的表示。
ELMo:来自语言模型的嵌入

埃尔莫模型:摘要——由阿鲁纳布·戈什创建
ELMo 主要由三个单元组成——(I)卷积神经网络(CNN),(ii)双向长短期记忆(LSTM),以及(iii)嵌入。
模型的输入?
ELMo 的输入完全是基于字符的。我们使用字符嵌入将每个字符转换成一个矢量,然后传递给 CNN 层。字符嵌入使我们能够超越以前模型的缺点。首先,字符嵌入可以提取单词嵌入可能遗漏的语言细节。其次,我们可以有效地表示词汇以外的单词,这是一个巨大的飞跃。
CNN 层的作用?
CNN 层将他们正在处理的单词的字符嵌入作为输入,并通过拾取 n-gram 特征来计算更强大的表示。CNN 层本质上是从呈现给它的令牌阵列中计算特征,从而提取一些统计、时间和空间信息。该输出然后被传递到双向 LSTM 层。
双向长短期记忆层的作用?
我们知道,LSTM 的核心是保存它已经看到的输入信息。这对于序列建模任务非常有用,因为记住先前的上下文是至关重要的。一般来说,LSTM 的是单向的;也就是说,他们只考虑过去的信息来预测结果?
另一方面,双向 LSTM 考虑来自两端的输入,一个来自过去,另一个来自未来,以做出预测。它可以通过考虑两个 LSTM 来做到这一点,一个从过去到未来,另一个从未来到过去。通过连接来自两个 LSTMs 的隐藏状态,它可以在任何时间点保存关于整个序列的信息。
举例来说,这是向前和向后 LSTM 将处理的内容:
前锋 LSTM: 她去玩了……
落后的 LSTM: …用她的球棒和球。
如你所见,双向 LSTM 通过理解过去和未来,擅长预测缺失的单词。
嵌入/输出
这就是 ELMo 模型真正脱离以前的架构的地方。以前的架构只是使用 LSTM 模型的最终隐藏状态作为单词表示,而 ELMo 考虑了 LSTM 所有隐藏状态的线性组合。LSTM 隐藏状态的权重是特定于任务的。这意味着,根据制图表达的用途,ELMo 模型将为每个图层赋予不同的权重。这是非常有利的,因为正如作者所展示的,不同的层捕获了语言的不同属性。
在他们的内在评估中,他们已经表明较高级别的 LSTM 状态捕捉单词意义的上下文相关方面,而较低级别的状态模拟语言句法的方面。同时暴露所有这些层允许模型选择它认为对手边的任务更有用的表示。例如,较高级别的层可能更有利于词义消歧任务。相比之下,较低级别的层对于诸如词性标注之类的任务可能更有用。
以这种方式组合内部状态允许非常丰富的单词表示
结果
实验结果证明了 ELMo 模型的有效性。ELMo 在一系列自然语言处理问题上,从问题回答到情感分析,都有显著的进步。ELMo 生成的表示很容易添加到现有的架构中,增强的模型实现了最先进的性能!
以下是 ELMo 达到最先进(SOTA)性能的任务:

论文结果— 艾尔默,作者 allenlp
这种无所不包的结果,以及它的应用的普遍性,使得这篇论文成为自然语言处理领域的一个重要里程碑。
结论
本文介绍了一种学习单词的高质量深度上下文相关表示的通用方法。这允许我们利用从单个模型获得的知识,并将其应用于不同的任务。我们不是为一个新任务从头开始训练一个模型,而是把 ELMo 学到的表示传递给它。
通过这个模型,我们可以利用迁移学习和半监督学习的力量。我们已经在计算机视觉中看到了这种方法的好处。众所周知,当任务中的数据不足时,在 ImageNet 数据集上进行预训练以扩充新模型是提高性能的一种好方法。
有了 ELMo,我们现在可以进入语言模型迁移学习的领域。看到我们将来如何在它的基础上发展是令人兴奋的!
下次见!
用于量子计算机的深度卷积神经网络
这项工作发表在《2020 年学习表征国际会议论文集》(ICLR)上,详细内容可以查看相关的论文 。

爱因斯坦和他令人费解的自我。(来源:我自己)
量子计算机会被用来做什么?量子计算机很有希望帮助解决许多领域的难题,包括机器学习。
在这项工作中,我们提出了在量子计算机上卷积神经网络 (CNN)的理论实现。我们称这种算法为 QCNN ,我们证明它可以比 CNN 运行更快,并且具有良好的准确性。这是与约尔达尼什·克里尼迪斯和阿努帕姆·普拉卡什的合作作品。
为了实现这一点,我们不得不提出卷积乘积的量子版本,找到实现非线性和合并的方法,以及对代表图像的量子态进行断层成像的新方法,这种量子态代表图像保留有意义的信息。
CNN 和量子计算机的超短介绍
简而言之,我们可以说量子物理系统可以描述为 2^n 维的某个希尔伯特空间中的向量,其中 n 是粒子数。事实上,这些向量代表了许多可能观测值的叠加。
另一方面,机器学习,特别是神经网络,粗略地利用向量和矩阵来理解或处理数据。量子机器学习(QML)旨在使用量子系统对矢量进行编码,并通过新的量子算法对其进行学习。一个关键的概念是,在许多向量上使用量子叠加,我们可以同时处理它们。

谷歌的量子计算机最*实现了“量子至上”。(来源:谷歌)
我不会深入解释量子计算或 QML。更多细节,我邀请新人阅读之前关于量子 k-means 的帖子(发表在neur IPS2019):
这项工作发表在 2019 年 NeurIPS 会议录上,你可以查看相关论文了解更多细节,以及…
towardsdatascience.com](/quantum-machine-learning-a-faster-clustering-algorithm-on-a-quantum-computer-9a5bf5a3061c)
卷积神经网络(CNN)是一种用于图像分类、信号处理等的流行且有效的神经网络类型。在大多数层中,卷积乘积应用于输入,被视为图像或张量。随后通常是一个非线性和汇集层。如果你不熟悉,网上有很多教程,尤其是这个技术介绍。

3D 张量输入 X^l (RGB 图像)和 4D 张量核 K^l.之间的卷积积(来源:我自己)
量子卷积层
在这一章中,我将通过集中在一层来解释什么是量子 CNN。
作为矩阵乘法的卷积乘积
这里的核心思想是,我们可以用矩阵乘法来重新表示卷积积。

X^l 和 K^l 之间的卷积等价于它们的整形形式 A^l 和 F^l.之间的矩阵乘法。输出 Y^l+1 可以被整形为卷积结果 X^l+1.(来源:我自己)
该算法首先加载量子叠加矩阵的所有行和列。然后我们使用之前开发的量子内积估计来*似输出的每个像素。实际上,这就像只计算一个输出像素(图上的红点),但在量子叠加中这样做允许同时计算所有像素!然后,我们可以同时对它们中的每一个应用非线性。
不幸的是,我们所拥有的只是一个所有像素并行存在的量子态,这并不意味着我们可以访问所有像素。如果我们打开“量子盒”并查看结果(一个测量,我们将每次随机只看到一个输出像素。在我们打开盒子之前,这里有所有的“漂浮”。就像著名的活死人猫。没错。
只提取有意义的信息
为了处理这个问题,我们引入了一种方法来只检索最有意义的像素。事实上,量子叠加中的每个输出像素都有一个振幅,关系到被看到的概率如果我们测量这个系统的话。在我们的算法中,我们强制这个幅度等于像素值。因此,高值的输出像素更有可能被看到。
在 CNN 中,输出中的高值像素非常重要。它们表示输入中存在特定模式的区域。通过了解不同图案出现的位置,神经网络理解图像。因此,这些高值像素携带有意义的信息,我们可以丢弃其他像素,希望 CNN 能够适应。

图像上量子效应(噪声、随机性、采样)的小例子。这给人一种直觉,即我们在仅采样高值像素后仍然可以“理解”图像。(来源:我自己)
请注意,在对这些输出像素进行采样时,我们可以在存储它们时应用任何类型的池(技术细节请参见论文)。我们将这些像素存储在一个传统的存储器中,这样我们可以重新加载它们作为下一层的输入。
更快的运行时间
传统上,CNN 层需要时间(输出大小 x 内核大小 ) 。这就是为什么用大量大型内核来训练这些网络会变得昂贵。我们的量子 CNN 需要时间((σx 输出大小) x Q) 其中 σ 是我们从输出(< 1)中抽取样本的比例, Q 代表一束量子精度参数和数据相关参数。不再依赖内核大小(数量和维度),这可以允许更深层次的 CNN。更多细节参见文件。
量子反向传播
有了这个量子 CNN 的设计,我们现在想用量子算法来训练它。训练包括按照梯度下降规则更新核参数。一个更快的量子算法也可以在这里找到,它几乎等同于通常的梯度下降,但有一些额外的误差。
实验
QCNN 和量子反向传播看起来不错,但是隐含了大量的*似、噪声和随机性。尽管有这些人工制品,CNN 还能学习吗?在学习分类手写数字(MNIST 数据集)的任务上,我们比较了小型经典 CNN 的训练和 QCNN 的模拟。这表明 QCNN 可以以相似的精度学习。

量子和经典 CNN 训练曲线的比较。 σ 是每层之后从输出中抽取的高值像素的比例。除了太小的 σ 之外,QCNN 可以以良好的准确度学习。注意,这个数值模拟很小,只给出直觉,不是证明。(来源:我自己)
结论
在这项工作中,我们设计了第一个量子算法,通过引入量子卷积积和一种新的检索有意义信息的方法,几乎精确地复制了任何经典的 CNN 结构。它可以允许一个明显更快的 CNN,有更深更大的输入或内核。我们还开发了一个量子反向传播算法,并模拟了整个训练过程。
开放性问题:我们能在更大的架构上训练 QCNN 吗?用其他数据集?当然,当一台完整的量子计算机准备就绪时,量子 CNN 会有多好?
参考
[1] J. Allow, I. Kerenidis 等.前馈神经网络的量子算法(2018)
[2] Y. LeCun,Y. Bengio 等.基于梯度的学习应用于文档识别。IEEE 会议录(1998)
[3] G. Brassard,P. Hoyer 等.量子振幅放大与估计AMS 当代数学丛书。(2000)
[4] I. Kerenidis , J. Landman 等. q-means:一种无监督机器学习的量子算法。”载于神经信息处理系统进展(NeurIPS) (2019)。
[5] S. Chakraborty,A. Gilyén 等人在 ICALP (2019)的会议录 中的分组编码矩阵幂的力量:通过更快的哈密顿模拟改进回归技术
深度卷积 Vs Wasserstein 生成对抗网络
了解 b/w DCGAN 和 WGAN 的差异。使用 TensorFlow 2.x 实现 WGAN

丁满·克劳斯在 Unsplash 上的照片
在本文中,我们将尝试了解两种基本 GAN 类型(即 DCGAN 和 WGAN)的区别,还将了解它们的区别以及 WGAN 在 TensorFlow 2.x 中的实现。我使用 TensorFlow 的官方教程代码 DCGAN 作为本教程的基础代码,并针对 WGAN 对其进行了修改。你可以在这里找到。
DCGAN
- DCGAN 像其他 GAN 一样由两个神经网络组成,即一个生成器和一个鉴别器。
- 生成器将随机噪声作为输入,并输出生成的假图像。
- 鉴别器将真实和伪造图像作为输入,并输出值 b/w 0 和 1,即图像真实或伪造的置信度。
- DCGAN 使用二进制交叉熵作为损失函数。
- 生成器看不到真实图像,仅通过来自鉴别器的反馈进行学习。
- 生成器的目标是通过生成逼真的假图像来欺骗鉴别器。而鉴别器的目标是正确识别真实和伪造的图像。
DCGAN 中的问题
DCGAN 中出现的一些问题是由于使用了二进制交叉熵损失,如下所示。
- 模式崩溃:这是一个术语(在 GAN 的上下文中),用来定义 GAN 无法生成不同的类镜像。例如:当用 MNIST 数据集训练时,GAN 可能只能生成一种类型的数,而不是所有 10 种,即它可能只生成“2”或一些其他数。你也可以举一个例子,甘只能够产生一个品种的狗,如哈士奇,但甘训练所有品种的狗。
- 消失梯度:由于鉴别器的置信值是只能为 b/w 0 和 1 的单个值,并且目标是获得尽可能接* 1 的值,因此计算的梯度接*于零,并且因此,生成器不能获得太多信息并且不能学习。因此,这可能导致一个强鉴别器,这将导致一个差的发生器。
解决办法
上述问题的一个解决方案是使用接*推土机距离的 Wasserstein 损失(EMD 是从一个分布到另一个分布所需的努力量。在我们的情况下,我们希望使生成的图像分布等于真实的图像分布)。WGAN 利用了 Wasserstein 损耗,所以我们现在来谈谈 WGAN。
WGAN
如上所述,WGAN 利用了 Wasserstein 损耗,因此让我们了解发生器和鉴别器的目的。
瓦瑟斯坦损失
- 因此,我们的损失是鉴别器输出对真实图像的 b/w 期望值与鉴别器输出对所产生的伪图像的期望值之差。
- 鉴别器的目标是最大化这个差异,而生成器的目标是最小化这个差异。
- 注 : 为了使用 Wasserstein 损耗,我们的鉴别器需要是 1-L (1-Lipschitz)连续的,即梯度的范数在每个点上必须至多为 1。
让我们来看一种加强 1-1 连续性的方法。
梯度惩罚
梯度惩罚用于加强 1-L 连续性,并作为鉴别器梯度的正则化添加到损失中。以下是计算梯度损失的步骤。
- 通过(real _ image * epsilon+fake _ image *(1—epsilon))从真实和虚假图像计算插值图像。
- 然后,计算鉴频器输出相对于插值图像的梯度。之后,计算梯度的范数。
- 然后,惩罚被计算为(norm-1)的*方的*均值,因为我们希望范数接* 1。
生成器和鉴别器的目标
因此,发生器的最终目标是增加鉴频器假输出的*均值。鉴别器的目标是加权惩罚的 w 损失。
训练 WGAN
训练 WGAN 时,鉴别器每步训练多次,而生成器每步训练一次。
结论
WGAN 导致稳定的训练,并解决了我们在 DCGAN 中面临的模式崩溃和消失梯度的问题。
但这一切都是有代价的,即 WGAN 在训练时比 DCGAN 慢。
你可以在这里找到这篇文章的完整代码。敬请关注即将发布的文章,我们将在 TensorFlow 2 中实现一些有条件和可控的 gan。
所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的内容。希望你阅读我即将发表的文章。哈里奥姆…🙏
参考
由 DeepLearning.AI 提供关于 GANs 生成对抗网络(GANs)是强大的机器学习模型…
www.coursera.org](https://www.coursera.org/specializations/generative-adversarial-networks-gans) [## Keras 文档:WGAN-GP 覆盖` Model.train_step '
作者:A_K_Nain 创建日期:2020/05/9 最*修改时间:2020/05/9 内容简介:用 Wasserstein 实现甘…
keras.io](https://keras.io/examples/generative/wgan_gp/)
使用 Amazon SageMaker 进行深度需求预测
介绍
在本文中,我们探索如何使用深度学习方法,通过使用亚马逊 SageMaker 进行需求预测。
TL;DR :这个项目的代码可以在 GitHub 上获得,只需一次点击 AWS CloudFormation 模板就可以设置所需的堆栈。
什么是需求预测?
需求预测使用历史时间序列数据来帮助简化跨业务的供需决策过程。例子包括预测
- 下个月将在多个地点雇佣客户代表
- 下个季度跨多个地区的产品销售
- 视频流服务第二天的云服务器使用情况
- 下周多个地区的用电量
- 物联网设备和传感器等能源消耗
时间序列预测概述
任何用时间索引的数据都是时序数据。时间序列数据分为单变量和多变量。例如,单个家庭的总用电量是一段时间内的单变量时间序列。这是一个单变量时间序列的样子,一些预测用绿色表示

预测为绿色的单变量时间序列: GluonTS 教程
当多个单变量时间序列相互叠加时,称为多变量时间序列。例如,一个街区中 10 个不同(但相关)家庭的总用电量构成了一个多变量时间序列数据。这样的数据封装了更多的信息,比如在邻域内的相关性。因此,我们有可能利用这些共享的信息对每个家庭进行更好的预测。
时间序列预测的现状方法包括自回归方法,如
- 单变量时间序列数据的自回归综合移动*均 (ARIMA)
- 向量自回归 (VAR)用于多变量时间序列数据
这些经典方法的一个缺点是,它们需要在模型训练之前进行繁琐的数据预处理和特征工程,例如合并各种数据归一化、滞后、不同的时间尺度、一些分类数据、处理缺失值等。所有通常用*稳性假设。然而,深度学习(DL)模型可以自动执行这些步骤。此外,众所周知,在数据足够多的领域,如计算机视觉或自然语言处理中,DL 方法已经超过了经典方法,但是时间序列数据呢?
时间序列预测的深度学习
在时间序列预测中使用深度学习方法已经成为一个主要的研究点,特别是对于(*稳/非*稳)多变量时间序列数据。借助高度优化的专用框架,如 Apache MXNet 、 PyTorch 和 TensorFlow ,具备快速 GPU 支持的训练和推理能力。
研究表明,DL 方法优于前述经典方法 ARIMA 和 VAR,特别是在处理大量具有分类特征和缺失值的(相关)多变量时间序列数据时。一个原因是神经网络模型可以预测新事件的季节性,因为这些全局模型在整个数据集上共同学习模式,并且可以更好地将学习到的规律外推至新系列。一种这样的方法是 LSTNet,来自用深度神经网络建模长期和短期时间模式。
LSTNet 是如何工作的?
*LSTNet 是最先进的 DL 预测方法之一。 我们已经把它 贡献给了 GluonTS ,它目前是基于 MXNet Gluon API 。LSTNet 的优势在于它将传统的自回归线性模型与非线性神经网络部分并行结合。这使得非线性 DL 模型对于违反尺度变化的时间序列更加鲁棒。
以下是 LSTNet 架构,其中包含一个*
- 卷积为第一层,后面是
- 递归和跳跃递归层
- 结合非线性特征和线性特征的全连通层

图片取自 用深度神经网络 建模长期和短期时间模式
数据
在本次演示中,我们将使用多变量时间序列 电力消耗数据。可以通过 GluonTS 直接下载数据的干净版本。数据包含3211 小时频率的时间序列,其中
- 训练数据从2012–01–01 00:00:00开始,到2014–05–26 19:00:00结束
- 测试数据具有从2014–05–26 19:00:00到2014–05–27 19:00:00的附加数据
这是熊猫数据框架中标准化训练数据的快照

组件和架构概述
数据集存储在 S3 存储桶中。使用亚马逊 SageMaker 的项目有如下三个主要组成部分:
- 标准化数据的预处理步骤,设计为微服务来处理重型作业
- 训练一个 LSTNet 模型,并检查预测的指标,如 sMAPE
- (可选)部署并创建一个连接到 Amazon CloudWatch 进行监控的实时预测 HTTPS 端点
*这个完整的代码项目可以在 GitHub 中获得。遵循单键设置的说明。
以下是视觉架构指南:*

深度需求预测架构
使用 Amazon SageMaker MXNet Estimator 进行训练
因为我们使用 GluonTS,我们需要通过提供train.py作为我们的入口点,使用 MXNet 估计器来训练我们的模型。例如,我们为context_length=12的 1 个时期训练我们的模型,T1 是过去 12 小时电力消耗的训练窗口大小,以预测未来 6 小时prediction_length=6的测试窗口大小。
*import logging
from sagemaker.mxnet import MXNetCONTEXT_LENGTH = 12
PREDICTION_LENGTH = 6hyperparameters = {
'context_length': CONTEXT_LENGTH,
'prediction_length': PREDICTION_LENGTH,
'skip_size': 4,
'ar_window': 4,
'channels': 72,
'scaling': False,
'output_activation': 'sigmoid',
'epochs': 1,
}estimator = MXNet(entry_point='train.py',
source_dir='deep_demand_forecast',
role=role,
train_instance_count=1,
train_instance_type='ml.p3.2xlarge',
framework_version="1.6.0",
py_version='py3',
hyperparameters=hyperparameters,
output_path=train_output,
code_location=code_location,
sagemaker_session=session,
container_log_level=logging.DEBUG,
)estimator.fit(train_data)*
韵律学
时序预测中最常见的评估指标之一是
- 对称*均绝对百分比误差 (sMAPE),用于量化模型预测不足或预测过度的程度,其中时间 t 的预测为英尺,时间 t 的实际值为的

图片取自 维基百科
When 可以直观地将其与另一个有用的指标进行比较,即*均绝对标度误差 (MASE),其值越接*零,通常预测就越好。我们使用牛郎星 Python 包来交互式地检查它们的关系。

最后,我们可以交互式地可视化预测与训练和测试数据。例如,以下是训练、测试和预测结果中前 10 个时间序列协变量的样本。

如您所见,在捕捉总体趋势方面,该模型在 1 个时期内表现相对较好。人们可以使用 Amazon SageMaker Python SDK 中的 HyperparameterTuner 来获得这些数据的最新结果。
部署端点
根据业务目标,例如在发电站设施中,当我们对模型离线运行的方式感到满意时,我们可以直接在 Amazon SageMaker 笔记本电脑中部署一个端点,如下所示:
***from sagemaker.mxnet import MXNetModelmodel = MXNetModel(model_data,
role,
entry_point='inference.py',
source_dir='deep_demand_forecast',
py_version='py3',
framework_version='1.6.0',
)predictor = model.deploy(instance_type='ml.m4.xlarge', initial_instance_count=1)***
之后,我们可以用一些request_data点击端点,在一行代码中获得带有自动 JSON 序列化和反序列化特性的预测
***predictions = predictor.predict(request_data)***
结论
***感谢您通读这篇文章!
在这篇博客中,我们通过使用 Amazon SageMaker 进行预处理、训练、测试和部署,展示了深度学习模型如何用于需求预测应用。我们很想听听你的意见。如有任何问题、评论或反馈,请使用 GitHub 问题。***
承认
最后但同样重要的是,我要感谢 Vishaal Kapoor 、 Jonathan Chung 和 Adriana Simmons 在撰写本文时提供的宝贵反馈。
了解更多信息
亚马逊 SageMaker:https://docs.aws.amazon.com/sagemaker/index.html
用亚马逊 SageMaker 进行深度需求预测:https://github.com/awslabs/sagemaker-deep-demand-forecastGluonTS:https://arxiv.org/pdf/1906.05264.pdf和https://github.com/awslabs/gluon-tsLSTNet:https://arxiv.org/pdf/1703.07015.pdf
[1]: Dua,d .和 Graff,C. (2019)。 UCI 机器学习知识库 ,加州尔湾:加州大学信息与计算机科学学院
采用 TensorFlow 2.x 的深度确定性和双延迟深度确定性策略梯度
DDPG 和 TD3 的 TensorFlow 2.x 实施

摄影爱好在 Unsplash 上
在本文中,我们将使用 TensorFlow 2.x 实现深度确定性策略梯度和双延迟深度确定性策略梯度方法。我们不会深入研究理论,只会涵盖基本内容。在你继续学习之前,建议你先熟悉一下 DQN 和双 DQN。对于这篇文章,我将菲尔博士的 Td3 PyTorch 代码转换为 TensorFlow,对于 DDPG,我采用了他的目标网络更新方法。请参考他的 youtube 频道这里(编码 RL 的最佳 youtube 频道)。
DDPG:
DDPG 用于有连续活动空间的环境。DDPG 结合了 DQN 和演员评论家的方法。让我们试着用代码来理解。
网络:
- 我们的批评家网络将状态和行为作为输入,这些输入被连接在一起。
- 批评家网络输出特定状态下的行动值。
- 我们正在使用一个连续的环境,这就是我们使用 tanh 激活(输出值 b/w -1 和 1)的原因,输出是动作的长度,即在“LunarLanderContinuous-v2”中,一个动作被表示为一个数组[-1 1],所以这里的长度是 2。
代理类别和操作选择:
- 在 DDPG,我们有演员和评论家的目标网络,就像在 DQN 我们有目标网络一样。
- 请注意,我们已经编译了目标网络,因为我们不想在将权重从主网络复制到目标网络时出错。
- 我们还使用了重放缓冲区来存储体验。
- 对于动作选择,首先,我们将状态转换为张量,然后将其传递给 actor-network。
- 为了训练,我们在动作中添加了噪音,为了测试,我们不会添加任何噪音。
- 我们将剪切最大和最小动作值的动作 b/w 范围。
更新目标网络:
- 更新 ddpg 和 td3 中的目标网络使用软更新,即我们每次都会稍微更新权重。
- 网络可以按照研究报告中的解释进行更新。

图片经由https://arxiv.org/pdf/1509.02971.pdf
训练功能:

图片来自https://arxiv.org/pdf/1509.02971.pdf
- 首先,我们从重放缓冲区中抽取经验样本,并将它们转换成张量。
- 评论家损失的目标值是通过使用行动者的目标网络预测下一个状态的行动来计算的,然后使用这些行动,我们使用评论家的目标网络来获得下一个状态的值。
- 然后,我们应用贝尔曼方程计算目标值(target _ values = rewards+selfγ* target _ next _ state _ values * done)。请注意,在训练时,此处的“完成”存储为(1-完成)。
- 我们的预测值是从缓冲样本中提取状态和动作的主评价网络的输出。
- 然后根据目标值和预测值的 MSE 计算临界损失。
- 参与者损失被计算为批评家主要值的负值,输入作为主要参与者预测的行动。
- 然后,我们用 0.005 的 tau 更新我们的目标网络。
训练循环:
- 我们的训练循环很简单,即它在每个行动步骤中相互作用并储存经验和学习。
TD3PG:
TD3 受到双 DQN 的启发,解决了评论家值被高估的问题,与 DDPG 相比有以下变化。
- 除了他们的目标网络之外,使用两个主要的评论家网络。
- 延迟演员网络的更新。
- 动作噪音调节。
我们将只讨论 DDPG 代码的不同之处。
代理类别:
- 在代理课程中,我们有两个主要的评论家网络和他们各自的目标网络。
- 在动作选择中,我们在一些步骤之后停止向动作添加噪声。
训练功能:
- td3 列车功能与 DDPG 列车功能只有 3 处不同。
- 首先,通过添加噪声,然后在最大和最小动作的范围内裁剪动作,来自演员的目标网络的动作被规则化。
- 第二,下一状态值和当前状态值都是目标评论家和两个主要评论家网络。并且对于下一个状态值和当前状态值都考虑最少两个网络。
- 第三,在每 2 步之后训练演员网络。
所以,这都是关于实现上的差异。现在让我们看看训练结果。
DDPG vs TD3PG:
这两个图显示了在过去 100 集内,两种算法在“LunarLanderContinuous-v2”中达到*均分数 200 所拍摄的集。

由作者制作并通过 matplotlib 生成的图像
正如你所看到的,TD3 算法在 400 集的最后 100 集中得到了*均 200 英镑的奖励。而 DDPG 在 560 集之后只得了 100 分。

由作者制作并通过 matplotlib 生成的图像
实施时需要注意的事项:
在编写 RL 代码时,要记住以下几点。
- 神经元的数量、隐藏层数、学习速率对学习有巨大的影响。
- 张量和 NumPy 数组的形状应该是正确的。很多时候,实现是正确的,代码也是有效的,但是代理没有学到任何东西,只是因为张量的形状不正确,并且当对这些张量进行运算时,会给出错误的结果。
你可以在这里找到这篇文章的完整代码和这里。敬请关注即将发布的文章,我们将在 TensorFlow 2 中实现更多 RL 算法和深度学习算法。
所以,本文到此结束。谢谢你的阅读,希望你喜欢并且能够理解我想要解释的内容。希望你阅读我即将发表的文章。哈里奥姆…🙏
参考资料:
[## 具有深度强化学习的连续控制
我们将深度 Q 学习成功背后的思想应用于持续行动领域。我们提出一个…
arxiv.org](https://arxiv.org/abs/1509.02971) [## TD3:学习用人工智能跑步
学习构建强化学习中最强大和最先进的算法之一,TD3
towardsdatascience.com](/td3-learning-to-run-with-ai-40dfc512f93) [## 菲尔的机器学习
你好。在 Neuralnet.ai,我们涵盖了各种主题的人工智能教程,从强化…
www.youtube.com](https://www.youtube.com/channel/UC58v9cLitc8VaCjrcKyAbrw)
深度确定性政策梯度(DDPG):理论与实施
深度确定性策略梯度(DDPG)是一种结合了 Q 学习和策略梯度的强化学习技术。DDPG 作为一个演员兼评论家的技术包括两种模式:演员和评论家。执行元是一个策略网络,它将状态作为输入,输出精确的动作(连续的),而不是动作的概率分布。批评家是一个 Q 值网络,它将状态和行为作为输入,输出 Q 值。 DDPG 是一个“关”——政策法。DDPG 用于连续动作设置,而 DDPG 的“确定性”是指演员直接计算动作,而不是动作的概率分布。DDPG 被用在连续的动作场景中,是对普通演员兼评论家的改进。
有很多实现 DDPG 在线的库,但是它们有很大的开销,对于初学者来说不容易理解。我决定编写一个简单的 TF2 实现,涵盖 DDPG 方法的重要部分。
让我们深入研究这项技术的理论。
理论
在 DQN,通过对所有动作的 Q 值取 argmax 来采取最优动作。在 DDPG,演员是一个政策网络,正是这样做的。它直接输出动作(动作可以是连续的),绕过 argmax。

政策网络
车型
该策略是确定性的,因为它直接输出动作。为了促进探索,一些高斯噪声被添加到由策略确定的动作中。为了计算一个状态的 Q 值,执行器输出被馈入 Q 网络以计算 Q 值。这仅在计算 TD 误差期间进行,我们将在后面描述。

演员和评论家被拴在一起
为了稳定学习,我们为评论家和演员创建了目标网络。这些目标网络将基于主网络进行“软”更新。我们稍后将讨论这些更新。
损失函数
现在我们已经描述了模型架构,我们继续展示如何训练模型,或者更确切地说,两个模型的损失函数是什么。评论家(Q)和演员(mu)的损失函数是,

演员和评论家的损失
我们先分析行动者(政策网)损失。损耗就是这些状态的 Q 值之和。为了计算 Q 值,我们使用评论家网络并传递由演员网络计算的动作。我们希望最大化这个结果,因为我们希望获得最大的收益/Q 值。
临界损失是一个简单的 TD 误差,我们使用目标网络来计算下一个状态的 Q 值。我们需要最小化这个损失。为了向后传播误差,我们需要 Q 函数的导数。对于临界损失,Q 值的导数是直接的,因为μ被视为常数,然而,对于因子损失,μ函数包含在 Q 值内。为此,我们将使用链式法则,

演员损失链规则
我们现在有所有的损失和衍生品。
目标更新
为了在训练期间增加稳定性,我们包括目标评论家和演员网络,以在 TD 误差计算中计算下一状态的 Q 值。与主/当前网络相比,目标网络是延迟网络。基于主网络定期更新目标的权重。在 DQN,目标定期复制主网络权重,这被称为“硬更新”。在 DDPG,我们执行“软更新”,其中只有一小部分主要权重以下列方式转移,

目标网络更新 rle
τ是通常被选择为接* 1(例如 0.999)的参数。
有了这个理论,我们现在可以看看它的实现。
履行
型号
现在我们到了模型创建阶段。在这个实现中,我们将使用一个简单的健身房环境( Pendulum-v0 )。我们的演员和评论家网络将只由密集的层组成。我们提醒读者,行动者是以国家为输入的政策网络,其输出是行动。批评家将状态和动作作为输入,并输出状态-动作对的 Q 值。在评论家网络的最初 DDPG 论文中,动作在中间层进入网络,而不是从开始进入网络。这样做只是为了提高性能/稳定性,我们不会诉诸这种伎俩。对我们来说,行动和状态输入将从一开始就进入批评网络。我们编写一个函数来生成演员和评论家,
模型生成器功能
函数 ANN2 使用 input_shape 和 layer_size 参数生成评论家和演员网络。两个网络的隐藏层都有【relu】激活。演员的输出层将是一个【tanh】,(映射连续动作-1 到 1),评论家的输出层将是“无”作为其 Q 值。演员网络的输出可以通过一个因子来缩放,以使动作对应于环境动作范围。
模型初始化
我们初始化 4 个网络:主要演员和评论家以及目标演员和评论家,
模型初始化
重放缓冲器
与其他深度强化学习技术一样,DDPG 依赖于使用重放缓冲区来实现稳定性。重放缓冲区需要保持新旧体验的*衡。
简单的重放缓冲实现
训练
现在我们直接使用上面定义的损失函数来训练我们的网络。为了在 TF2 计算损耗和梯度,需要在 TF 中进行计算。GradientTape()块。TF2 建议对不同的网络使用不同的梯度带。我们训练的实施看起来像这样,
训练循环
让我们快速浏览一下这段代码。我们首先从重放缓冲区中取样。对于参与者,我们首先计算状态(X)上的动作,然后使用 critic 使用计算的动作和状态(X)来计算 Q 值。在反向传播过程中,critic 保持不变,因为我们只区分 wrt 因素变量。损失中的负号是存在的,因为在优化中我们希望最大化这个损失。
对于临界误差,我们使用目标网络来计算用于 TD 误差计算的 Q 目标。使用主评价网络计算当前状态(X) Q 值。在这个过程中,行动者保持不变。
车型更新
目标模型需要基于主模型进行更新。我们使用前面描述的等式更新它们,
这就完成了我们对 DDPG 方法的实施。
结果
我们在钟摆 v0 环境下运行 DDPG 100 集,得到如下回报。

培训回报
完整的代码实现可以在这里找到。
参考文献
- 深度强化学习的连续控制。
- DDPG 实现: Github
- 打开艾 DDPG
使用 Python 深入研究层次分析法

Clem Onojeghuo 在 Unsplash 拍摄的照片
对这种多标准决策方法的高度概述,以及一个使用案例。
前言
在一生中,一个人会做出许多决定,从几乎没有影响的最微不足道的决定,到会改变一生的决定。几乎总是,这些情况涉及 X 个选项和 Y 个判断标准。

示例 A
想象你在超市,你想买早餐麦片。你站在一排排的麦片前,不确定该买哪一种。你在找什么?
- 价格 :麦片不能太贵
- 口味 :可能是里面有巧克力的东西?
- 营养 :混合水果或燕麦的东西。
这些是您浏览产品时想到的一些标准。比方说,你拿起水果圈,磨砂片和幸运符。你在脑海中运行每一个标准,并将它们相互比较。然后你做了一个决定,把磨砂薄片放进你的购物车。
示例 B
你正在加纳一个小村庄的市政厅主持一个会议。作为水利项目代表团的负责人,您被分配到在村子里安装一系列水泵的任务。在你面前的是各种各样的利益相关者——村里的长者、地质学家和工程师。
在这次会议中,你将选择安装水泵的地点,并列出一系列标准—
- 地下水位: 该地点必须有相当高的地下水位;
- 人口 :附*必须有最小数量的人居住才能使装置有用;
- 费用 :运行材料和物资的费用必须在项目资金之内。
你与村里的长者、地质学家和工程师交谈,拟定了 15 个可能修建水泵的地点。经过多次讨论和权衡意见后,你将范围缩小到 5 个在选择标准列表中排名靠前的地方。
尽管这两个例子在影响范围和应用领域上有很大的不同,但问题是非常相似的——在面对多种、通常是相互冲突的标准时做出决定。
在这篇文章中,我将对层次分析法提供一个高层次的解释,这是解决这种多准则决策问题的一种可能的技术。在这个过程中,我还将向您展示如何用 Python 从头开始实现这项技术。
介绍
层次分析法是托马斯·萨蒂教授在 20 世纪 70 年代提出的一种多准则决策方法。
这是一种通过在数学框架内量化主观信念来帮助决策者做出明智决策的方法。
AHP 是关于不同数量的相对测量,是决策分析和运筹学领域的交叉点。

图 1—布鲁内利 2015 年[1]
AHP 在许多领域都很流行,从供应链到可持续系统、环境管理、投资组合选择等等。它之所以受欢迎,是因为它非常直观,允许决策者以透明的方式整理他们的主观信念。
该过程
层次分析法,本质上就是给不同的选项分配不同的权重,并对其进行汇总的过程。然而,美妙之处在于得出这些权重的方式,以及主观信念的量化。
让我向你们简单介绍一下 AHP 的高度直观的过程—
- 第一步:定义流程的最终目标。在上面分享的例子中,目标分别是购买早餐麦片和选择合适的安装点;
- 第二步:列出你手头上实现目标的各种选择。这些选项被称为‘备选方案’。
- 第三步:列出你评估上述选择的不同标准。这些可能涉及标准的子级别,并且完全取决于您想要的详细程度,尤其是当选项彼此非常相似时。
- 第 4 步:从第 1 步到第 3 步建立层次结构。如果你熟悉图论,那么你可以想象这是一个有向无环图。每个节点之间的连接暗示了它们在评估中的考虑。

图 2——评估层级的示例[2]
- 步骤 5 :每一个标准和子标准的成对比较,以确定它们的权重。
- 步骤 6 :将每个备选方案与每个子标准进行成对比较,以确定其权重。
- 步骤 7 :对每个备选方案的所有这些权重(加权算术和)进行总体求和,并根据这个加权和对它们进行排序。
- 第八步:计算一致性比率。这是与临界值表相比,主观评估一致性的度量。如果发现不一致,请返回步骤 5。
所以从这些步骤中,你可以看到这个过程是如何得到它的名字的,以及为什么它在应用方面如此受欢迎。现在,让我们来看看这个过程的核心——主观信念的量化。
评估
AHP 的关键词是成对 比较。我们都知道一次比较三个以上的选项有多难。为了消除这一困难,Saaty 教授建议对备选方案/标准进行成对比较。这种比较/评估是通过指定代表不同重要程度的强度来完成的,这是他用语言学定义的[3]。

对于每个标准/子标准/目标[1],被评估/评定的备选方案被编译成一个 n x n 成对比较矩阵 A 。

这里, wi 和 wj 是上表中重要的权重或强度。您可以立即看到评估矩阵是对称的,这使得计算更加容易。
一旦创建了评估矩阵,下一步就是将其转换成向量。该向量对矩阵中存在的信息进行编码,并被称为优先级向量。
有几种方法可以计算这个优先级向量。一种方法是获得 Perron-Frobenius 特征向量[4],或者简单地获得矩阵的归一化特征向量。另一种方法是计算相应行上的元素的几何*均值除以归一化项,使得优先级向量的分量最终加起来为 1 [1]。这种方法是归一化特征向量方法的一种*似。
评估的最后一步是为每个子标准生成的优先级向量的加权算术和,并对它们进行排序以对备选方案进行排序。
一致性比率
层次分析法的基本假设是决策者是理性的。这基本上意味着决策者被假定为每次对相同的问题都应用相同的主观信念。然而,在现实中,情况可能并非如此。Saaty 教授通过提出一致性指数 CI 来解决这种不确定性

其中λ_ max是成对比较矩阵的最大特征值,并且 n 是备选方案的数量。
为了缩放不同大小的矩阵,开发了一致性比率 CR

其中, RI_n 是从足够大的一组大小为 n 的随机生成矩阵中获得的 CI 的*均估计值。Saaty 教授给出了 RI_n 的查找表,

如何使用 CR? —根据 Saaty 教授的说法,在实践中,应该接受 CR ≤ 0.1 的矩阵,拒绝大于 0.1 的值。CR = 0.1 的值基本上意味着这些判断有 10%的不一致性,就好像它们是随机给出的一样。通过选择较低的 CR,可以尝试减少这种不一致性,唯一的方法是返回并重新评估主观权重。
唷,这有很多理论,所以让我们继续用 Python 实现一个简单的用例
用 Python 实现层次分析法
据我所知,目前只有一个开发良好的 python 库用于 AHP — pyAHP,但是让我们使用前面描述的过程从头开始编写代码。这里,我将使用[1]中的一个典型用例来说明这个过程。(说实话,在 Excel 中实现相当容易!)
代码可以在我的 GitHub 仓库中找到
问题定义
假设你想去欧洲度假,你计划去几个有趣的城市。你心中有几个城市——马德里、汉堡和巴黎,但你的预算只允许你去其中的一个。为了帮助您获得最大的回报,您决定使用 AHP 来帮助您缩小合适城市的范围。
目标、标准和备选方案
总体目标显然是你个人的满意度。备选方案是{罗马、马德里、巴黎},让我们想象您选择以下标准来评估每个城市—{气候、观光、环境}。让我们建立等级制度-

图 3——用例的层次结构(图片由作者提供)
导入库
好了,让我们从导入两个库开始评估过程
import numpy as np
import pandas as pd
创建成对比较矩阵
我们利用了比较矩阵的对称性质,只接受上三角矩阵的输入。
# Number of options
n = 3# Creating default matrix of ones
A = np.ones([n,n])# Running a for loop to take input from user and populate the upper triangular elements
for i in range(0,n):
for j in range(0,n):
if i<j:
aij = input('How important is option{} over option{} ?: '.format(i,j))
A[i,j] = float(aij) #Upper triangular elements
A[j,i] = 1/float(aij) #Lower triangular elements
请记住,我们的标准集是{气候、观光、环境},因此选项 0 是气候,选项 1 是观光,选项 2 是环境。我们运行这段代码来为标准权重生成成对比较矩阵。
How important is option0 over option1 ?: 0.5
How important is option0 over option2 ?: 0.25
How important is option1 over option2 ?: 0.5
这可以解释为—
气候比观光机会重要两倍,比城市环境重要四倍。观光机会的重要性是城市环境的两倍

一旦生成矩阵,我们通过归一化最大特征值的特征向量来计算优先级向量。该特征向量中的元素是标准的权重。
e = np.linalg.eig(A)[1][:,0]
p = e/e.sum()>>> array([0.14285714, 0.28571429, 0.57142857])
这两段代码被组合成一个函数
def pairwise_matrix(n):A = np.ones([n,n])
for i in range(0,n):
for j in range(0,n):
if i<j:
aij = input('How important is option{} over option{} ?: '.format(i,j))
A[i,j] = float(aij)
A[j,i] = 1/float(aij)#Computing the priority vector
eig_val = np.linalg.eig(A)[0].max()
eig_vec = np.linalg.eig(A)[1][:,0]
p = eig_vec/eig_vec.sum()
return p, eig_val
我们称这个函数为生成成对比较矩阵和优先级向量,用于根据每个标准评估每个备选方案。记得我们的备选方案集是—{罗马、马德里、巴黎}。

每个矩阵的优先级向量是—
pr_c = pairwise_matrix(3)[0] #All Criteria
pr_c0 = pairwise_matrix(3)[0] #Criteria 0: Climate
pr_c1 = pairwise_matrix(3)[0] #Criteria 1: Sightseeing
pr_c2 = pairwise_matrix(3)[0] #Criteria 2: Environment#Priority Vector for Criteria 0 pr_c0
>>> array([0.44444444, 0.44444444, 0.11111111])#Priority Vector for Criteria 1 pr_c1
>>> array([0.6, 0.3, 0.1])#Priority Vector for Criteria 2pr_c2
>>> array([0.09090909, 0.18181818, 0.72727273])
我们还计算了每个比较矩阵的一致性比率。对于 n= 3,RI_n 应为 0.5247。所有矩阵的最大特征值是 3。因此,根据之前的公式,每个矩阵的 CR 将为 0,即< 0.1 and hence acceptable.
The final step is to get their weighted arithmetic sum to yield the rank vector
r = pr_c0*pr_c[0] + pr_c1*pr_c[1] + pr_c2*pr_c[2]
print(r)>>> [0.28686869 0.25310245 0.46002886]
The weighted arithmetic sum for 巴黎比罗马或马德里高得多,因此它被指定为 rank1,其次是罗马和马德里。
这就对了!在 AHP 的帮助下,你成功地将自己的主观分析量化,决定飞往 巴黎 !
结论
AHP 的主要缺陷是当由不同的一组人评估时,备选方案的排序颠倒了。另一个问题是将其纳入运筹学的哲学基础。
话虽如此,层次分析法仍然是一种流行的 MCDM 方法,并且相对容易实现和解释。除了 python 之外,还有一些商业软件,比如 SuperDecisions,可以帮助您创建层次结构并执行成对评估。
有更多的 MCDM 方法来弥补层次分析法的不足,并且在数学基础方面更先进。一些想到的是 PROMETHEE,托普西斯等。
参考
[1]布鲁内利,马特奥。2015.层次分析法简介。斯普林格在运筹学中的作用。第 83 页。978–3–319–12502–2(电子版)。
[2]https://en . Wikipedia . org/wiki/Analytic _ hierarchy _ process _ % E2 % 80% 93 _ car _ example
[3] T.L .萨蒂,用层次分析法进行决策。里面的《服务科学》2008 年第 1 卷第 1 期
[4]https://en . Wikipedia . org/wiki/Perron % E2 % 80% 93 Frobenius _ theorem
我希望这篇文章对你有所帮助,并感谢你的反馈!
再见!
深入探究自组织地图的竞争学习
互联网上无监督人工神经网络中自组织映射(SOMs)竞争学习背后的最佳解释!

自组织映射是最流行的无监督学习人工神经网络之一,其中系统没有关于输入数据的特征或特性以及输出数据的类别标签的先验知识。网络根据样本输入模式之间的相似性来学习形成样本输入模式的类别/聚类。集群中的模式具有相似的特征。关于什么特征对于分类是重要的,以及有多少类,没有先验知识。网络本身会针对不同类别的输入进行调整,正如其名称所示,它们会自我组织。加权层中的节点数量对应于不同类别的数量。它基于竞争学习。

自组织地图网络结构
什么是竞争学习?

在竞争学习中,与权重相关联的节点相互竞争以赢得输入模式(向量)。对于每个不同的输入模式,具有最高响应的节点被确定并被宣布为获胜者。仅训练与获胜节点相关联的权重,以使它们更类似于输入模式(向量)。所有其他节点的权重不变。赢家通吃,输家一无所有。所以它叫做赢家通吃算法(输家什么也得不到)。
节点的强度=加权和
为输出节点 1

Y1 = X1W11+ X2W21 + X3W31 +..……+ XDWD1
每个节点与具有 D 个元素的权重向量相关联
输入向量X—【X1,X2,X3……】。,XD]
Y1 的权重向量——【W11,W21,W31,…。,WD1]
训练算法
- 估计类别数(输出节点数)
- 随机设置权重并归一化
- 应用标准化的输入向量 X
- 计算每个节点的强度(即加权和)
- 确定具有最高响应的节点 i
- 宣布节点 i 为‘获胜者’(I具有与 X 最相似的权重)
- 训练节点 i 的权重,使它们更加类似于 X
培训过程

培训期间:
- 获胜者的权重向量变得更加等于当前输入向量
- 换句话说,当前的输入向量被传递给胜利者
培训后:
- 获胜者携带它赢得的输入(获胜节点的权重向量现在保留它已被训练的输入模式)
- 任何类似于先前的连续输入选择该节点作为获胜者
大多数神经网络专家不知道训练过程背后的理论。据说在训练期间,获胜者的权重向量变得更等于当前输入向量。但是大多数人缺乏关于使权重向量等于输入向量的理论的知识。所以在这里我想用神经竞争的基础数学来解释这个理论。
标量和向量
数量
- 标量只有大小,如长度、面积、体积、速度、质量、密度、压力、温度
矢量
- 向量既有大小又有方向,例如位移、方向、速度、加速度、动量、力、重量
输入向量和权重向量的归一化
- 为了便于训练,输入向量和权重向量都被归一化为一个单位长度
- 标准化过程解释如下
考虑矢量
x =[X1 X2 X3……XD]
X 的范数=

正常化

- 矢量的范数被称为矢量的“强度”,即它的大小
- 归一化向量的范数是 1(单位向量)
- 即如果 X 是矢量
例如 X = [0.2,0.1,1.4,0.2];
标准化的
X = [0.1397 0.0698 0.9778 0.1397]
归一化的范数
x = 0((0.1397)2+(0.0698)2+0.9778)2+0.1397)2)= 1
正常化
标准化向量的元素介于 0 和 1 之间。当输入特征来自不同的尺度时,例如[1.2 0.001 10.6],归一化使它们达到统一的标准。当权重向量也被归一化时,训练过程变得简单。当所有输入模式被归一化为单位长度时,它们可以被表示为单位球体中的不同半径(不同方向)。

标准化为单位长度的输入模式,单位长度由单位球体中的半径表示
下图显示了单位球体中的归一化权重向量和该现有球体中表示的输入向量。

单位球中表示输入向量和权重向量
这里每个向量的长度= 1。
正常化前后

正常化前后
网络对训练集进行编码所需的是权重向量与该集中存在的任何聚类对齐。每个集群至少由一个节点表示。那么当一个向量被呈现给网络时,就会有一个节点,或者一组节点,对输入做出最大的响应。
两个向量的相似性

两个向量的相似性
- 如果 X1 = [x1,x2,x3,x4]且 Y1 = [y1,y2,y3,y4],则 X1 = Y1
惟一可能是
x1 = y1
x2 = y2
x3 = y3
x4 = y4
X1 和 Y1 被称为是“相同的”。
- 考虑向量 X 和 Y
点积 X.Y = |X||Y|。Cos q
|X|-向量长度
q——两个向量之间的夹角
如果|X| = 1 且|Y| = 1
X.Y = Cos q 和 0 <= Cos q <= 1
If q -> 0(那么 Cosq -> 1)
两个单位矢量重合
也就是说,两个向量(X 和 Y)的等于
即 X 与 Y 重合

训练两个向量使其相等的过程
X.Y = |X|。| Y | Cosq= 1.1 . Cosq
当 q - > 0 矢量 X =矢量 Y
所以我们改变两个向量之间的角度 q,以使两个归一化向量相等。
som 的培训
因此,在训练过程中,我们为给定的输入模式找到一个具有最高响应值的获胜节点。然后,使获胜者的权重向量更等于当前输入向量。根据上面的数学解释,我们在训练期间所做的是调整归一化输入向量和获胜节点的归一化权重向量之间的角度,直到这两个向量彼此一致。换句话说,直到两个矢量相等。
训练使得特定节点的权重类似于所施加的输入。换句话说,输入向量以其权重的形式被“转移”到获胜节点。当应用相似的输入向量时,相同获胜者的加权和将是最高的。

培训过程
类似地,对所有输入模式继续这一过程,直到输入向量与每个输入模式的获胜节点的权重向量一致。
训练方程——koho nen 学习规则

Kohonen 学习规则
我们可以使用 Kohonen 学习规则来验证这一数学解释,在 koho nen 学习规则中,仅对输出为 1 的获胜输出节点调整网络权重。否则,权重调整为零,因为输出为零。当输出为 1 时,通过使获胜节点的输入向量 X 和权重向量 W 彼此相等来调整权重。这是通过调整这两个向量之间的角度来实现的。当两个向量彼此一致时,网络被训练,并且不需要进一步的权重调整。对所有的输入模式继续这个过程,直到人工神经网络被完全训练。
最终想法

我希望这篇文章能帮助你理解无监督人工神经网络中自组织映射(SOMs)竞争学习背后的实际理论。写这篇文章的目的是与世界其他地方分享我的经验丰富的讲师的重要知识。这一切都要归功于我的大学高级讲师 H.L. Premaratne 博士,
- 神经网络和模式识别
- 图像处理和计算机视觉
这是根据他的要求写的,因为互联网上缺乏解释这一理论的文章。我希望你们都能从这方面的专家那里获得宝贵的知识。
谢谢大家!!!…
深入探究网飞的推荐系统
网飞如何通过个性化实现 80%的流时间

在 Unsplash 上由 Thibault Penin 拍摄的照片
在这个时代,网飞是大多数人的同义词,是电影和电视节目的首选流媒体服务。然而,大多数人不知道的是,网飞在 20 世纪 90 年代末开始采用订阅模式,将 DVD 邮寄到美国的家庭。
Netflix 奖
2000 年,网飞推出了个性化电影推荐,2006 年,推出了 Netflix 奖、机器学习和数据挖掘竞赛,奖金为 100 万美元。当时,网飞使用了其专有的推荐系统cinema tech,该系统的均方根误差(RMSE)为 0.9525,并要求人们将这一基准提高 10%。一年后能够实现目标或接*目标的团队将获得奖金。
一年后,2007 年进步奖的获得者使用了矩阵分解(T10)和受限玻尔兹曼机器(T12)的线性组合,实现了 0.88 的 RMSE。在对源代码做了一些修改后,网飞将这些算法投入生产。值得注意的是,尽管一些团队在 2009 年实现了 0.8567 的 RMSE,但该公司并没有将这些算法投入生产,因为需要工程努力来获得边际精度增加。这为现实生活中的推荐系统提供了重要的一点——模型改进和工程努力之间总是存在积极的关系。
流媒体——新的消费方式
网飞没有采纳 Netflix 奖项的改进模式的一个更重要的原因是,它在 2007 年引入了流媒体。随着流媒体的出现,数据量急剧增加。它必须改变其推荐系统生成推荐和接收数据的方式。

快进到 2020 年,网飞已经从美国邮寄 DVD 的邮件服务转变为拥有 1.828 亿用户的全球流媒体服务。因此,它的推荐系统从预测收视率的回归问题转变为排名问题、页面生成问题、用户体验最大化问题(定义为最大化流媒体播放的小时数,即个性化所有可以个性化的内容)。本文旨在解决的主要问题是:
网飞用什么作为它的推荐系统?
网飞作为一个企业
网飞有一个基于订阅的模式。简单来说,网飞的会员越多,收入就越高。收入可以被视为三个因素的函数:
- 新用户获取率
- 取消率
- 前成员重新加入的比率
网飞的推荐系统有多重要?
80%的流时间是通过网飞的推荐系统实现的,这是一个非常令人印象深刻的数字。此外,网飞相信,创造一个用户体验,将寻求提高保留率,这反过来又转化为客户获取的节省(估计截至 2016 年每年 1B 美元)。
网飞推荐系统
网飞如何对头衔进行排名?
很明显,网飞利用了基于行的两级排名系统,排名发生在:
- 每行内(最强的建议在左边)
- 跨行(最强烈的建议在顶部)

来源:网飞科技博客
每行突出显示一个特定的主题(例如,前 10 名、趋势、恐怖等),并且通常使用一种算法来生成。每个成员的主页由大约 40 行多达 75 个项目组成,这取决于成员使用的设备。
为什么是行?
优势可以从两个角度来看——1)作为用户,当呈现一排相似的项目时,它更连贯,然后决定他或她是否有兴趣观看该类别中的某些内容;2)作为一家公司,收集反馈更容易,因为向右滚动一行表示感兴趣,而向下滚动(忽略该行)表示不感兴趣(不一定不相关)。
有趣的事实:你知道吗,艺术品也会根据你的个人资料和喜好而个性化?点击了解更多!
用的是什么算法?
网飞使用了其论文中提到的各种排名器,尽管每个模型的架构细节并没有具体说明。以下是它们的概要:
个性化视频排名(PVR) —这是一种通用算法,通常根据某种标准(例如暴力电视节目、美剧、爱情片等)并结合用户特征和受欢迎程度等次要特征来过滤目录。

PVR 生成项目的示例
Top-N Video Ranker——类似于 PVR,除了它只看排名的头部,看整个目录。这是优化使用的指标,看看目录排名的头部(如地图@K,NDCG)。

前 N 名排名生成标题的示例
趋势现在排名更靠前——这种算法捕捉了网飞推断为强预测因素的时间趋势。这些短期趋势可能从几分钟到几天不等。这些事件/趋势通常是:
- 具有季节性趋势并会重复发生的事件(如情人节导致浪漫视频消费上升)
- 一次性的短期事件(如冠状病毒或其他灾难,导致对相关纪录片的短期兴趣)

趋势 Now ranker 生成标题的示例
继续查看排名者 —该算法查看成员已经消费但尚未完成的项目,通常为:
- 情节性内容(如戏剧系列)
- 非情节性的内容,可以一点一点地消费(例如,完成一半的电影,独立于情节的连续剧,如《黑镜》)
该算法计算成员继续观看的概率,并包括其他上下文感知信号(例如,自观看以来经过的时间、放弃点、观看的设备等)。

继续观看排名器生成标题的示例
在 Justin Basilico [2]的演讲中,他介绍了 RNNs 在时间敏感序列预测中的应用,我认为这种算法中使用了 RNNs。他设计出,网飞可以利用特定成员过去的游戏以及上下文信息,并以此预测该成员的下一个游戏可能是什么。特别地,使用连续时间和离散时间上下文作为输入执行得最好。

来源:来自[2]的剪辑幻灯片
视频-视频相似性排名—也就是因为你看了(BYW)
该算法基本上类似于基于内容的过滤算法。根据成员消费的项目,该算法计算其他类似的项目(使用项目-项目相似性矩阵)并返回最相似的项目。在其他算法中,这一个是非个人化的,因为没有利用其他的边特征。然而,它是个性化的,在某种意义上说,它是一个有意识的选择,显示一个特定项目的类似项目,一个成员的主页(更多细节在下面的页面生成)。

BYW 生成标题的示例
行生成过程
上述每个算法都经历了下图所示的行生成过程。例如,如果 PVR 正在查看言情标题,它将找到符合该类型的候选,同时拿出证据来支持一行的呈现(例如,该成员先前观看过的言情电影)。根据我的理解,这种证据选择算法被合并(或一起使用)到上面列出的所有其他排序算法中,以创建一个更精确的项目列表排序(见下面网飞的模型工作流程图)。
这个证据选择算法 使用“所有【网飞】显示的信息都在页面的左上方,包括网飞奖上被重点关注的预测星级;大纲;显示的关于视频的其他事实,例如任何奖项、演员阵容或其他元数据;以及[网飞]用来在用户界面的行和其他地方支持[他们的]建议的图像。【1】”
五种算法中的每一种都经历了相同的行生成过程,如下图所示。

来源:网飞科技博客[3]
页面生成
在算法生成候选行(已经在每个行向量中排序)之后,网飞如何决定显示这 10,000 行中的哪一行呢?

网飞的工作流程模型
历史上,网飞一直使用基于模板的方法来解决页面生成的问题,即大量的行争夺宝贵的屏幕空间。这是一项不仅注重准确性,而且同时提供多样性、可访问性和稳定性的任务。其他考虑因素包括硬件能力(使用什么设备)以及哪些行/列在第一眼和滚动时是可见的。
这意味着网飞想要准确地预测用户在那个时段想看什么,但不要忘记他/她可能想继续看中途中断的视频。与此同时,它希望通过提供一些新鲜的东西来突出其目录的深度,并可能捕捉到成员所在地区正在发生的趋势。最后,当用户与网飞互动了一段时间,并习惯于以某种方式浏览页面时,稳定性是必要的。
有了所有这些要求,我们就可以理解为什么基于模板的方法一开始就能很好地工作,因为我们可以随时满足一些固定的标准。然而,在提供良好的会员体验方面,拥有许多这样的规则自然会使网飞处于局部最优状态。
那么我们如何处理这个行排序问题呢?
基于行的方法
基于行的方法使用现有的推荐或学习排序方法来对每行进行评分,并基于这些分数对它们进行排序。这种方法可能相对较快,但缺乏多样性。一个成员可能最终会看到一个满是符合他/她兴趣的行的页面,但是行与行之间可能非常相似。那么我们如何融合多样性呢?
分阶段进场
对行上升方法的一个改进是使用阶段式方法,其中每一行都像上面的方法一样评分。但是,从第一行开始按顺序选择行,每当选择一行时,都会重新计算下一行,以考虑它与前面的行以及已经为页面选择的前面的项目的关系。这是一个简单的贪婪的阶段式方法。
我们可以通过使用 k 行前瞻方法来改进这一点,在计算每行的得分时,我们考虑接下来的 k 行。然而,这两种方法都不能获得全局最优。
机器学习方法
网飞使用的解决方案和方法是一种机器学习方法,他们的目标是通过训练一个模型来创建一个评分函数,该模型使用他们为其成员创建的主页的历史信息,包括他们实际看到的内容,他们如何互动以及他们玩了什么。
当然,还有许多其他功能和方式可以为算法表示主页中的特定行。它可以简单到使用所有的项目元数据(作为嵌入)并聚合它们,或者按位置索引它们。不管用什么特性来表示页面,主要目标是生成假设的页面,并查看用户会与哪些项目进行交互。然后使用页面级度量进行评分,例如 Precision@m-by-n 和 Recall@m-by-n (它们是对 Precision@k 和 Recall@k 的改编,但是是在二维空间中)。

页面级指标(来源:学习个性化主页)
冷启动、部署和大数据
冷启动问题
古老的冷启动问题——网飞也有。传统上,网飞试图通过要求新成员填写一份调查来“启动”推荐,从而获得一些用户偏好信息来抑制这种行为[6]。如果跳过这一步,推荐引擎将会提供一组多样且受欢迎的标题。
此外,最*在这个新冠肺炎时期,网飞党(一个 Chrome 扩展)被创建,在我看来,这对于抑制这个冷启动问题有巨大的影响,因为这些数据可能会被送回网飞进行分析。

简单地说,网飞曾经是单人活动(至少是可以被网飞监控的)。你可以一个人在家或者和一群朋友一起看比赛,但是网飞不知道你和谁一起看比赛。有了网飞派对,网飞可能会创建一个你与谁互动过的图表,并可能会执行一种类似协同过滤的算法,为新用户做推荐。
这都是关于测试的
线下评价和线上评价的差距依然存在。虽然离线指标有助于评估我们的模型在训练数据上的表现,但不能保证这些结果会转化为用户体验的实际改善(即总观看时间)。因此,网飞团队建立了一个令人难以置信的高效 A/B 测试流程来快速测试他们构建的这些新算法。
请记住,A/B 测试本身是一门艺术,因为有许多变量需要考虑,包括如何选择控制和测试组,如何确定 A/B 测试是否具有统计意义(即,从整体上改善整体用户体验),选择控制/测试组大小,在 A/B 测试中使用什么指标,等等。

从根本上说,离线评估有助于网飞确定 何时 将模型投入 A/B 测试,以及 将哪些 模型投入 A/B 测试。你可以在这里阅读更多关于网飞的 A/B 测试实验过程。
数据,数据,数据和更多的数据
通过在线流媒体,网飞管理和访问的数据是无限的。只有采用正确的架构才能管理如此大量的数据,即分离离线在线 和 *线 计算。
使用离线计算,对数据量和算法计算复杂性的限制较少,因为它以批处理方式运行,具有宽松的定时要求。但是,它很容易在两次更新之间变得陈旧,因为最新的数据也没有并入。对于个性化架构,一个关键问题是以无缝的方式结合在线和离线计算。
通过在线计算,我们期望对最*的事件和用户交互做出响应,因此必须实时完成。因此,在线计算不能太复杂且计算成本高。此外,回退机制是必要的,例如恢复到预先计算的结果。
有了*线计算,我们在这两种方法之间找到了一个折中方案,它可以执行类似在线的计算,但不需要实时服务,允许它(计算和服务)异步。这为对每个事件进行更复杂的处理打开了大门,例如更新推荐以反映在成员开始观看电影后立即观看了该电影。这对增量学习算法很有用。
下图显示了网飞的详细建筑图。

来源:个性化和推荐的系统架构[5]
要深入了解这些组件是如何使用的,请阅读下面的博客文章。
结论

来源: UX 星球:Binging on the Algorithm
也就是说,是时候狂欢了——看男孩们!在新冠肺炎的艰难时期保持安全。感谢上帝给了网飞。
支持我! —如果你喜欢我的内容并且没有订阅 Medium,请考虑支持我并通过我的推荐链接在这里(注:你的一部分会员费将作为推荐费分摊给我)。
参考
[1] 网飞推荐系统
[2] 个性化的最新趋势:网飞的观点
[3] 学习个性化主页
[4] 一切都是为了测试:网飞实验*台
[6] 网飞的推荐系统如何运作
降维并深入主成分分析
以及求解的 Kaggle 数据集
内容
在本帖中,我们将了解:
- 降维的需要
- 降维方法
- 基于奇异值分解的 PCA 算法
- 特征向量和特征值的直觉
- 使用 PCA 时要记住的提示
- 卡格尔的 MNIST 数字数据集上的五氯苯甲醚插图
在迄今为止的这一系列机器学习帖子中,我们深入研究了上一篇帖子中的第一个无监督学习算法(K-means)。在这篇文章中,我们将深入了解另一种流行的无监督学习算法,称为主成分分析(PCA)。与 K-means 不同,PCA 不是一种聚类算法,而是一种用于降维的算法,同时试图复制原始数据集的特征,这在很大程度上是这样做的。在这篇文章中,在深入研究 PCA 的技术细节和数学知识之前,我将尝试为 PCA 中的每一个概念提供直觉。所以,在了解 PCA 是干什么的之前,让我们先了解一下什么是降维。
降维
数据集的维度相当于该数据集中存在的要素数量。数据集中的要素数量越多,其维度就越高。术语“特征”和“尺寸”经常互换使用。降维是将数据从高维空间转换到低维空间,以便低维表示试图复制原始数据集中的所有特征,尽管是以压缩的形式。
降维的需要
当数据集中的特征(维度)数量增加时,表现良好的机器学习模型的性能会显著下降。当在如此大规模的数据集上训练模型时,它无法将训练数据集的模式推广到真实世界的数据集,导致过度拟合,从而导致性能下降。
拥有包含大量要素(维度)的数据集的另一个缺点是,它在加载到数据帧时会消耗大量的主内存。在训练占用如此大量内存的机器学习模型时,训练过程变得缓慢,因为模型必须处理大量数据。在这里,你可以争辩说,我们可以使用小批量的数据来训练模型(小批量梯度下降),以减少数据占用的内存。但是有个问题。假设我们在 k 批量加载数据。如果原始数据具有 n 个特征,那么模型在每个小批量所占用的内存将与 k x n 成比例。如果通过降维,我们可以将特征的数量从 n 减少到n’,那么每个小批量将占用与kxn’成比例的内存,这比第一种情况占用的内存少得多。现在,我们可以通过减少批处理大小 k 来补偿第一种情况下占用的大量内存。但是,提供具有大量要素的较少数据将无法捕获数据中的模式,因为数据点的数量越少,数据点稀疏分布的概率就越高。
在真实世界的数据集中,有许多相互关联的特征,即并非所有的特征都是相互独立的。对于健壮的机器学习模型,我们希望输入数据的特征彼此独立,因为大量的依赖特征使得模型偏向这些特征。
上述所有案例都强调了一个事实,即对于具有大量特征(维度)的数据集,我们需要在训练任何回归器/分类器来执行预测任务之前减少特征的数量。高维数据的上述弊端通常被称为 维数灾难 。

将 D 尺寸缩小至 d 尺寸(来源)
降维方法
降维问题可以分为两个部分:
(一)特征选择
(二)特征提取
特征选择是一种技术,其中我们有一个包含大量特征的数据集,我们选择这些特征的子集用于训练过程。这个子集可以通过直觉或一些统计技术来确定,如递归特征消除(RFE),我们在这篇文章中用来解决 Kaggle 的巨大数据集。然而,这种方法并不有效,因为随着一些特征的丢失,我们可能会丢失数据中的重要信息。
在要素提取中,我们从现有数据集构建新要素(少于实际要素数)。我们应该只选择特征提取,前提是我们可以处理原始数据集中特征的丢失。特征提取是一种通过创建少量特征(维度)来复制数据集特征多样性(方差)的优秀技术,但其代价是个体特征身份的损失,即提取的特征不能被人类理解,因为它们由数字而不是其他值组成。有助于特征提取的算法有:
㈠主成分分析
㈡t-分布随机邻居嵌入(t-SNE)
在下面的章节中,我们将详细介绍主成分分析(PCA)。
注意:特征提取通常优于特征选择,但在构建机器学习模型时,我们应该始终使用原始特征集来训练初始模型,因为在某些情况下,维数减少不会产生比基础模型更大的改进。

(来源)
主成分分析
PCA 是一种无监督学习算法,也是最广泛使用的降维算法之一。在一行中,PCA 只不过是将一个 n 维特征空间的轴变换到一个 k 维特征空间,这对数据集的方差几乎没有影响。数据的方差是定义数据点在原始特征空间中如何分布的属性,并且在执行 PCA 时保留该属性是很重要的,以便从给定特征中获得最大变化的数据点,缺少该属性会导致所得到的机器学习模型性能不佳,因为该模型将不能概括模式。每个 k 维度被称为主分量,其中 k 是 PCA 算法的输入。这些主成分中的每一个都根据它们所获得的方差以降序排序。例如,当将 100 维的特征空间减少到 10 维的特征空间时,第一主成分(维度)捕获最大的方差,第二主成分捕获稍小的方差,等等。
现在我们对 PCA 有了一个概念,在深入研究 PCA 算法之前,让我们先来看一个 PCA 的例子。为了便于说明,我们将通过一个例子来说明 PCA 如何通过保留数据的方差将二维特征空间转换成一维特征空间。
考虑下面的散点图。该散点图有一些数据点(蓝点),其中每个数据点由 x 轴和 y 轴上的值表示。正如我前面提到的,PCA 只不过是数据方向上的轴的变换,使得经过 n 变换的轴(k < n)中的 k 指向数据的方向。这里 k = 1,n = 2。将 PCA 应用于给定的数据会将二维特征空间的轴转换为由下面所示的虚线轴表示的轴。我们可以清楚地看到,这两个轴中只有一个轴似乎能够很好地逼*所有的数据点,因此,我们可以成功地说,给定的数据只能在一维而不是二维中表示,因此,PCA 发挥了它的魔力。

(来源)
但是 PCA 是如何知道在这个特定方向上变换轴的呢?PCA 从轴的随机变换开始,然后测量所有数据点在每个轴上垂直投影时的总*方距离(投影误差)。这可以被认为是 PCA 的成本函数,并且该算法的目标是最小化该成本函数。作为结果,最小化过程产生上面的轴的虚线变换。当绘制数据点的散点图时,从下图中我们可以看到水*轴单独代表所有数据点的能力有多好,同时保留了沿该轴的大部分方差。与水*轴相比,垂直轴具有非常小的数据方差,并且如果水*轴已经捕获了我们想要的最小阈值方差(例如> 90%),那么我们可以说 PCA 已经成功地完成了将二维特征空间转换成一维特征空间的工作。

(来源
注:将二维特征空间转换为一维特征空间,上述过程与线性回归非常相似。但请记住,这里的目标不是构建一条概括所有数据点的直线,而是在数据方向上变换轴,这对于二维问题可能类似于线性回归,但对于 PCA 在高特征空间中的应用,最终结果非常不同。
看过 PCA 如何工作的例子后,让我们深入研究 PCA 算法。
主成分分析算法
在深入算法之前,我会推荐(非强制)阅读这个关于栈交换的答案。你不需要读完整的答案,跟着它直到你开始发现事情变得复杂,然后从这里继续这篇文章。请放心,在这篇文章结束时,你会很好地掌握 PCA 算法。
PCA 是机器学习中较难的算法之一,因为它涉及到复杂线性代数的使用。PCA 的整个算法可以分为两步:
㈠数据标准化
(ii)输入相关矩阵的特征分解
标准化数据是数据预处理步骤,也是 PCA 算法的重要组成部分,因为它将不同数据特征的所有数据值降低到相同的尺度。这分两步实现:均值归一化和特征缩放。在均值归一化中,从每个要素的所有值中减去该要素的均值。因此,每个特征的新*均值为零。一旦执行了均值归一化,即使在均值为零之后,数据值仍然可能分布得很开。每个特性的值在不同的范围内,对于 PCA,我们希望这些值在特定的范围内。为此,我们可以将每个特征的归一化*均值除以每个特征的标准差。这一过程的总体效果是,我们获得了特定范围内所有特征的数据值,这些数据值集中在该范围内(由于*均值为零)。上述过程的公式如下所示:

其中 x̅ 是一个特性的所有值的*均值, σ 是标准偏差,x’是最终的标准化值。
在讨论特征分解之前,让我们将输入训练特征从输出标签中分离出来,因为 PCA 是一种无监督的学习算法。如果输入数据集具有 n 个训练特征和 m 个训练示例,则表示数据的矩阵大小为 m x n ,即训练示例表示为行,特征表示为列。既然这个矩阵代表的是输入数据,那我们就称之为 X 。我们知道,当我们对该数据执行 PCA 时,特征数 n 将减少到 k 。我们把 PCA 后得到的形状 k x m 的输入矩阵称为 Z 。
让我们一步一步地进行特征分解。
- 特征分解的第一步包括为输入数据构建相关矩阵。这通过输入矩阵的转置和原始输入矩阵的矩阵乘法来计算,并表示为 XᵀX 。相关矩阵是一个 n x n 矩阵,顾名思义,它计算数据集的要素之间的相关程度。相关矩阵中的所有值都在-1 和 1 之间,其中正值表示 2 个值强相关,负值表示 2 个值不相关。相关矩阵是对称矩阵,因为相关(a,b) =相关(b,a) 。下图是已经应用了 PCA 的数据集的相关矩阵的热图。我们可以看到,所有的对角线值都接* 1,这表明每个特征都与其自身有很强的相关性,但所有其他值都是负的,这表明每个特征与其他特征几乎没有相关性。这就是应用 PCA 后的最终相关矩阵。然而,相关矩阵 XᵀX 需要转换成这样的矩阵,为此,相关矩阵 XᵀX 的特征向量和特征值发挥作用。在继续之前,你应该看一下这个视频,以便直观地了解矩阵的特征向量和特征值代表什么。然而,我已经在下面的一节中简要介绍了这一点。

2。一旦计算出相关矩阵,我们可以使用奇异值分解对原始输入矩阵 X 进行(特征)分解。通过奇异值分解,我们可以将矩阵 X 分解成如下 3 个矩阵:

在哪里

二维数据的奇异值分解
NS 表示矩阵的零空间,并且 λ(n) 表示对应于特征向量 v(n)的特征值。
我们如何想出 SVD 用于 PCA 的想法是许多统计学家和数学家的天才之作,但为了进一步了解如何使用通过 SVD 分解的矩阵,我推荐观看这个视频,以满足自己将矩阵的本征分解为 3 个矩阵是正确的。
理解特征向量和特征值
术语“eigen”是一个德语词,意思是“特性”。特征向量和特征值是矩阵的特征。矩阵可以被认为是多个向量的组合,并且特征向量是一个这样的特殊向量,其指向数据的最大方差的方向,并且特征向量的长度是其特征值。一旦变换(如 PCA)应用于矩阵,特征向量的方向不会改变(对于所有其他普通向量,它会改变),但对应于该特征向量的特征值会改变。在这里,我们不需要关心计算特征向量和特征值的过程,因为这是一个非常复杂的步骤,是 python 中线性代数库的一部分,其中有针对该计算的优化实现。
3。一旦我们分离出特征向量和特征值,我们就可以通过测量它们在向量 Vᵀ 中对应的特征值来对矩阵 U 中的值进行降序排序。一旦我们有了按特征值降序排列的特征向量,第一个特征向量捕获原始数据的最大方差,第二个特征向量捕获比第一个稍小的方差,依此类推。这里每个特征向量被称为一个主分量。在下一节中,我们将看到如何选择主成分的数量。
4。现在假设我们已经选择了第一个 K 个主成分,那么我们通过下面提到的公式中的矩阵乘法得到最终的简化特征矩阵:

这里,U[:k]是形状(n,k)的 U 矩阵的前 k 个特征向量的切片,X 是形状(m,n)的输入特征矩阵。结果存储在矩阵 Z 中。我们也可以从 Z 中取回原始输入矩阵,但其中的数据值将是原始值的*似值,但我们会取回原始特征。

X_approx 是一个(m,n)形矩阵。
现在,当我们构建 Z 的关联矩阵时,它应该类似于前面显示的热图。这表明 PCA 已经成功地应用于输入数据,因此我们已经成功地消除了所有相互关联或冗余的特征。
选择主成分的数量
早先我们假设我们在应用 PCA 之后选择 K 个主成分。但是,如何选择 K ?我们希望通过这 K 个主成分,获取原始数据的最大方差。然而,所需的变化量取决于手头的机器学习任务。但是,建议我们保留原始方差的 90% — 99%之间的方差,并尽可能使用最少的主成分。为了确保这一点,我们首先从第一个主成分开始,并测量它捕获的方差。然后,我们考虑前两个主成分,并测量这个组合捕获了多少方差。重复这个过程,直到我们得到 K 个主成分,产生期望的方差。导致我们得到这个期望方差的主成分的总数是用于进一步训练机器学习模型(回归器/分类器/神经网络)的维度(主成分)的最终数量。检查给定主成分是否保留 99%方差的公式如下:

应用 PCA 时要记住的要点
- PCA 应该仅应用于训练数据集。对于交叉验证和测试数据集,应该只应用由 PCA 创建的 X - > Z 映射。
2)可能发生的是,由于 PCA 有助于减少输入特征的数量,它也可以防止模型的过度拟合。虽然这在一定程度上是正确的,但在实践中,总是试图通过正则化方法来解决过拟合问题,因为应用 PCA 在这方面没有太大的区别。
3)对于每一个具有大量特征的机器学习问题,使用 PCA 进行降维可能是诱人的,但是我们应该总是尝试用原始特征集来训练我们的第一个模型。如果这不能产生理想的结果,那么我们应该考虑对输入特征应用 PCA。
PCA 算法到此为止。我们已经学习了 PCA 是如何帮助降维的,以及它背后的数学原理。为了巩固这些概念,我在 Kaggle 上创建了这个笔记本(详见下一节),它也展示了 PCA 如何可视化一些主要组件。
问题陈述
我们使用包含 784 个特征值的 MNIST 数字数据集,其中每个特征代表一个像素值。这个问题的任务是制造一个数字识别器。我还没有创建一个识别数字的模型,因为它将使用神经网络,我还没有讨论过神经网络,但 784 有很多特征,通过对输入数据应用 PCA,您会看到大约 300 个特征足以捕捉数据的 95%的方差,这是一个非常好的特征减少。如果你对它们有一定的了解,你可以在遵循这里的 PCA 步骤之后,尝试训练一个神经网络来自己从减少的特征中识别数字。问题的数据集可以在这里找到。
让我们从导入所需的库和测量输入数据的形状开始。
import numpy as np
import pandas as pd
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import matplotlib
%matplotlib inlinefrom sklearn.decomposition import PCA
import osfor dirname, _, filenames **in** os.walk(‘/kaggle/input’):
for filename **in** filenames:
print(os.path.join(dirname, filename))

df = pd.read_csv("/kaggle/input/digit-recognizer/train.csv")
df.head()

df.shape

给定的数据集有 42000 个训练样本、784 个特征和 1 个输出标签。让我们将输入要素与输出标注分开。
test_df = df['label']
train_df = df.drop('label', axis = 1)
现在,我们需要在应用特征分解之前将数据标准化。
*# Standardize the data* from sklearn.preprocessing import StandardScaler
X = train_df.values
X_std = StandardScaler().fit_transform(X)
在下面的步骤中,我们首先为输入数据构建相关矩阵,然后计算特征向量和相应的特征值。一旦我们有了这些特征向量,我们就根据特征值按降序对它们进行排序,并计算每个特征向量所代表的方差的百分比。
*# Calculating Eigenvectors and eigenvalues of Cov matirx* mean_vec = np.mean(X_std, axis=0)
cov_mat = np.cov(X_std.T)
eig_vals, eig_vecs = np.linalg.eig(cov_mat)*# Create a list of (eigenvalue, eigenvector) tuples* eig_pairs = [ (np.abs(eig_vals[i]),eig_vecs[:,i]) for i **in** range(len(eig_vals))]*# Sort the eigenvalue, eigenvector pair from high to low* eig_pairs.sort(key = lambda x: x[0], reverse= True)*# Calculation of Explained Variance from the eigenvalues* tot = sum(eig_vals)
var_exp = [(i/tot)*100 for i **in** sorted(eig_vals, reverse=True)] *# Individual explained variance* cum_var_exp = np.cumsum(var_exp) *# Cumulative explained variance*
通过打印变量 var_exp 和 cum_var_exp ,您可以观察每个特征向量对方差的贡献,正如预期的那样,当我们遍历特征向量时,个体方差会减小,但累积方差最终会达到 100%。让我们画出每个特征向量的方差来验证我们的观察。
plt.plot(list(range(784)), cum_var_exp, label = 'Cumulative Variances')plt.xlabel('Feature No.')
plt.ylabel('Variance %')
plt.title('Cumulative Variance % v/s Features')plt.show()

plt.plot(list(range(784)), var_exp, label = 'Individual Variances')plt.xlabel('Feature No.')
plt.ylabel('Variance %')
plt.title('Individual Variance % v/s Features')plt.show()

从上述两个图中可以清楚地看出,大部分方差是在 200-300 个特征之间捕获的,300 个特征之后的个体方差接*于零。因此,使用 200-300 个特征将是一个非常好的选择,因为已经捕获了接* 95%的变化。因此,让我们使用前 300 个特征执行 PCA,并可视化由前 25 个特征向量-特征值对捕获的特征类型。
n_components = 300
pca = PCA(n_components= n_components).fit(train_df.values)
eigenvalues = pca.components_n_row = 5
n_col = 5*# Visualizing first 25 eigenvectors through their eigenvalues* plt.figure(figsize=(13,12))
for i **in** list(range(n_row * n_col)):
offset =0
plt.subplot(n_row, n_col, i + 1)
plt.imshow(eigenvalues[i].reshape(28,28), cmap='jet')
title_text = 'Eigenvalue ' + str(i + 1)
plt.title(title_text, size=6.5)
plt.xticks(())
plt.yticks(())
plt.show()

上面的子图描绘了 PCA 方法决定为数字数据集生成的前 25 个最佳方向或主分量轴。当我们将第一个分量“特征值 1”与第 25 个分量“特征值 25”进行比较时,很明显,在搜索中,每个经过的特征向量正在生成更复杂的方向或分量,以最大化新特征子空间中的方差,这支持了先前研究的理论。
在绘图时,我使用了“jet”彩色地图,但是你可以在这里尝试许多值,看看哪一个给出了最好的视觉效果。
到目前为止,我们只是将数据视为独立的像素。让我们将这些像素绘制成 28 x 28 像素的图像,以便能够看到数字的图像,而不只是看到 1 和 0。
*# plotting some numbers from the dataset* plt.figure(figsize=(14,12))for digit_num **in** range(0,50):
plt.subplot(7,10,digit_num+1)
grid_data = train_df.iloc[digit_num].to_numpy().reshape(28,28)
plt.imshow(grid_data, interpolation = "none", cmap = "gist_gray")
plt.xticks([])
plt.yticks([])plt.tight_layout()

从上面的 50 位图像中,我们可以看到所有图像的顶部、底部、左侧和右侧都是黑色的。这意味着对应于这些列的像素值是多余的,因此是无用的。在 PCA 将移除的许多类型的冗余特征中,这可能是其中最突出的。
最后,我们将使用 10000 个数据点和 30 个主成分,并尝试查看每个主成分捕获的方差是否大于后续主成分。如果是这样的话,这意味着常设仲裁院成功地完成了任务。
X = train_df[:10000].values*# Standardizing the values* X_std = StandardScaler().fit_transform(X)*# Call the PCA method with 30 components.* pca = PCA(n_components = 30)
pca.fit(X_std)
X_30d = pca.transform(X_std)
y = test_df[:10000].values plt.scatter(X_30d[:,0], X_30d[:,1])
plt.xlabel('First Principal Component')
plt.ylabel('Second Principal Component')
plt.show()plt.scatter(X_30d[:,0], X_30d[:,9])
plt.xlabel('First Principal Component')
plt.ylabel('Tenth Principal Component')
plt.show()plt.scatter(X_30d[:,0], X_30d[:,19])
plt.xlabel('First Principal Component')
plt.ylabel('Twentieth Principal Component')
plt.show()plt.scatter(X_30d[:,0], X_30d[:,29])
plt.xlabel('First Principal Component')
plt.ylabel('Thirtyth Principal Component')
plt.show()

上面每个图中的横轴表示第一主成分,纵轴具有第二、第十、第二十和第三十主成分。我们可以清楚地看到,在每个图中,数据沿水*轴的分布更大,而在随后的图中,沿垂直轴的分布显著减小,这意味着初始主成分比其他成分捕获更多的方差。这证明了 PCA 实现的正确性。
这个帖子到此为止。我们在这篇文章中深入研究了主成分分析,这确实是我们迄今为止所涉及的最困难的话题之一。在下一篇文章中,我们将详细介绍异常检测算法。
深入查询 Elasticsearch。过滤器与查询。全文搜索
或者如何理解缺少哪些官方文档

如果我必须用一句话来描述 Elasticsearch,我会说:
当搜索与分析大规模相遇时(接*实时)
Elasticsearch 是目前十大最受欢迎的开源技术之一。公*地说,它结合了许多本身并不独特的关键特性,然而,当结合起来时,它可以成为最好的搜索引擎/分析*台。
更准确地说,Elasticsearch 之所以如此受欢迎,是因为它结合了以下特点:
- 使用相关性评分进行搜索
- 全文搜索
- 分析(聚合)
- 无模式(对数据模式没有限制),NoSQL,面向文档
- 丰富的数据类型选择
- 水*可伸缩
- 容错的
为我的副业项目与 Elasticsearch 一起工作时,我很快意识到官方文档看起来更像是从所谓的文档中“压榨”出来的。我不得不在谷歌上搜索了很多次,所以我决定收集这篇文章中的所有信息。
在本文中,我将主要写查询/搜索 Elasticsearch 集群。有许多不同的方法可以实现或多或少相同的结果,因此,我将尝试解释每种方法的利弊。
更重要的是,我将向您介绍两个重要的概念——查询和过滤上下文——它们在文档中没有得到很好的解释。我会给你一套规则,告诉你什么时候用哪种方法更好。
如果读完这篇文章后,我想让你记住一件事,那就是:
查询时真的需要给文档打分吗?
查询上下文与过滤上下文
当我们谈论 Elasticsearch 时,总会有一个相关性分数。相关性分数是一个严格的正数,表示每个文档满足搜索标准的程度。该分数相对于分配的最高分数,因此,分数越高,文档与搜索标准的相关性越好。
但是,过滤器和查询是两个不同的概念,在编写查询之前,您应该能够理解这两个概念。
一般来说,过滤上下文是一个是/否选项,其中每个文档要么匹配查询,要么不匹配。一个很好的例子是 SQL WHERE后跟一些条件。SQL 查询总是返回严格符合条件的行。SQL 查询不可能返回不明确的结果。
过滤器被自动缓存,不会影响相关性分数。
另一方面,elastic search查询上下文向您展示每个文档与您的需求的匹配程度。为此,查询使用分析器来查找最佳匹配。
经验法则是对使用过滤器:
- 是/否搜索
- 搜索精确值(数字、范围和关键字)
使用查询进行:
- 不明确的结果(某些文档比其他文档更适合)
- 全文搜索
除非你需要相关性分数或全文搜索,否则请尽量使用过滤器。滤镜“更便宜”。
另外, Elasticsearch 会自动缓存过滤器的结果。
在第 1 部分。第二。我将谈到查询(可以转换成过滤器)。请不要混淆结构化 vs 全文和查询 vs 过滤器——那是两回事。
1.结构化查询
结构化查询也称为术语级查询,是一组检查文档是否应该被选择的查询方法。因此,在许多情况下并不真正需要相关性分数——文档要么匹配,要么不匹配(尤其是数字)。
术语级查询仍然是查询,因此它们将返回分数。
术语查询
返回字段值与条件完全匹配的文档。术语查询在某种程度上是 SQL select * from table_name where column_name =...的替代
术语查询直接进入倒排索引,这使得它很快。当处理文本数据时,最好仅对keyword字段使用term。
GET /_search
{
"query": {
"term": {
"<field_name>": {
"value": "<your_value>"
}
}
}
}
默认情况下,术语查询是在查询上下文中运行的,因此,它会计算得分。即使返回的所有文档的分数都相同,也需要额外的计算能力。
带过滤器的术语查询
如果我们想加速术语查询并将其缓存,那么它应该被包装在一个constant_score过滤器中。
还记得经验法则吗?如果您不关心相关性分数,请使用此方法。
GET /_search
{
"query": {
"**constant_score**" : {
"**filter**" : {
"term" : {"<field_name>" : "<your_value>"}
}
}
}
}
现在,该查询不计算任何相关性分数,因此速度更快。而且,它是自动缓存的。
快速建议——对于text字段,使用match而不是term。
请记住,术语查询直接指向倒排索引。术语查询接受您提供的值,并按原样搜索它,这就是为什么它非常适合查询没有任何转换就存储的keyword字段。
条款查询
您可能已经猜到,术语查询允许您返回与至少一个精确术语匹配的文档。
术语查询在某种程度上是 SQL 的替代品select * from table_name where column_name is in...
理解 Elasticsearch 中的查询字段可能是一个列表很重要,例如{ "name" : ["Odin", "Woden", "Wodan"] }。如果您执行的terms查询包含以下名称之一,那么该记录将被匹配——它不必匹配字段中的所有值,而只需匹配一个值。
GET /_search
{
"query" : {
"terms" : {
"name" : ["Frigg", "Odin", "Baldr"]
}
}
}
术语集查询
与术语查询相同,但这次您可以指定在查询的字段中应该有多少确切的术语。
您可以指定需要匹配的数量——一个、两个、三个或全部。但是,这个数字是另一个数字字段。因此,每个文档都应该包含这个编号(特定于这个特定的文档)。
范围查询
返回查询字段值在定义范围内的文档。
相当于 SQL select * from table_name where column_name is between...
范围查询有自己的语法:
gt大于gte大于或等于lt小于lte小于或等于
字段值应≥ 4 且≤ 17 的示例:
GET _search
{
"query": {
"range" : {
"<field_name>" : {
"gte" : 4,
"lte" : 17
}
}
}
}
范围查询也适用于日期。
正则表达式、通配符和前缀查询
Regexp 查询返回字段与您的正则表达式匹配的文档。
如果你从未使用过正则表达式,那么我强烈建议你至少了解一下它是什么以及什么时候可以应用它。
Elasticsearch 的 regexp 是 Lucene 的。它有标准的保留字符和运算符。如果你已经使用过 Python 的re包,那么在这里使用它应该不成问题。唯一不同的是 Lucene 的引擎不支持^、$等锚点运算符。
您可以在官方文档中找到 regexp 的完整列表。
除了 regexp 查询,Elsticsearch 还有通配符和前缀查询。从逻辑上讲,这两个只是正则表达式的特例。
不幸的是,我找不到关于这 3 个查询的性能的任何信息,因此,我决定自己测试一下,看看是否有什么显著的不同。
在使用rehexp和wildcard查询比较通配符查询时,我没有发现任何性能差异。如果你知道有什么不同,请, tweet me。
已有查询
由于 Elasticsearch 是无模式的(或者没有严格的模式限制),当不同的文档有不同的字段时,这是一种相当常见的情况。因此,知道一个文档是否有某个字段是非常有用的。
GET /_search
{
"query": {
"exists": {
"field": "<your_field_name>"
}
}
}
2.全文查询
全文查询适用于非结构化文本数据。全文查询利用了分析器。因此,我将简要概述 Elasticsearch 的分析器,以便我们可以更好地分析全文查询。
弹性搜索的分析管
每次将text类型的数据插入到 Elasticsearch 索引中时,都会对其进行分析,然后存储在倒排索引中。因为 analyzer 还适用于全文搜索,所以根据您对 analyzer 的配置,它会影响您的搜索功能。
分析仪管道 由三个阶段组成:
字符过滤器(0+) →记号赋予器(1) →记号过滤器(0+)
总有一个记号赋予器和零个或多个字符&记号过滤器。
1)字符过滤器 按原样接收文本数据,然后它可能在数据被标记化之前对其进行预处理。字符过滤器用于:
- 替换匹配给定正则表达式的字符
- 替换匹配给定字符串的字符
- 清除 HTML 文本
2)记号赋予器 将字符过滤后接收的文本数据(如果有)分解成记号。例如,whitespace tokenizer 简单地通过空白字符(这不是标准的)来分隔文本。因此,Wednesday is called after Woden.将被拆分成Wednesday, is, called, after, Woden.。有许多内置标记器可用于创建定制分析器。
标准记号赋予器 在删除标点符号后用空格将文本断开。对于绝大多数语言来说,这是最中性的选择。
除了标记化, 标记化器 还执行以下操作:
- 跟踪代币顺序,
- 注意每个单词的开头和结尾
- 定义令牌的类型
3)令牌过滤器 对令牌应用一些变换。您可以选择将许多不同的令牌过滤器添加到您的分析器中。一些最受欢迎的是:
- 小写字母
- 词干分析器(适用于多种语言!)
- 删除重复项
- 转换为等效的 ASCII 码
- 模式的变通方法
- 令牌计数限制
- 令牌的停止列表(从停止列表中删除令牌)
现在,当我们知道分析器由什么组成时,我们可能会考虑如何处理我们的数据。然后,我们可能通过选择合适的组件来组成一个最适合我们情况的分析器。分析器可以在每个字段的基础上指定。
理论够了,我们来看看默认分析器是怎么工作的。
标准分析仪为默认分析仪。它有 0 字符过滤器,标准记号,小写和停止记号过滤器。您可以随心所欲地构建您的定制分析器,但是也有一些内置分析器。
一些最有效的开箱即用分析器是语言分析器,它们利用每种语言的特性进行更高级的转换。因此,如果您事先知道数据的语言,我建议您从标准分析器切换到数据语言之一。
全文查询将使用索引数据时使用的同一分析器。更准确地说,您的查询文本将与搜索字段中的文本数据经历相同的转换,因此两者处于同一级别。
匹配查询
匹配查询是查询text字段的标准查询。
除了text类型字段之外,我们可以将match查询称为term查询的等效查询(而在处理文本数据时,term应该只用于keyword类型字段)。
GET /_search
{
"query" : {
"match" : {
"<text_field>" {
"query" : "<your_value>"
}
}
}
}
默认情况下,传递给query参数(必需的)的字符串将由应用于搜索字段的分析器进行处理。除非您使用analyzer参数自己指定分析仪。
当您指定要搜索的短语时,它会被分析,结果总是一组标记。默认情况下,Elasticsearch 将在所有这些令牌之间使用OR操作符。这意味着至少应该有一个匹配——尽管匹配越多,得分越高。您可以在operator参数中将其切换到AND。在这种情况下,要返回文档,必须在文档中找到所有的标记。
如果您希望在OR和AND之间有一些东西,您可以指定[minimum_should_match](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/query-dsl-minimum-should-match.html)参数,该参数指定应该匹配的子句的数量。它可以用数字和百分比来指定。
fuzziness参数(可选)允许你省略错别字。 Levenshtein 距离用于计算。
如果您将match查询应用到keyword字段,那么它将执行与term查询相同的操作。更有趣的是,如果您将存储在倒排索引中的令牌的确切值传递给term查询,那么它将返回与match查询完全相同的结果,但速度更快,因为它将直接进入倒排索引。
匹配短语查询
与match相同,但顺序和接*度很重要。匹配查询不知道顺序和接*度,因此,只可能用不同类型的查询来实现短语匹配。
GET /_search
{
"query": {
"match_phrase" : {
"<text_field>" : {
"query" : "<your_value>",
"slop" : "0"
}
}
}
}
match_phrase查询有slop参数(默认值为 0 ),负责跳过术语。因此,如果指定slop等于 1,那么短语中的一个单词可能会被省略。
多匹配查询
多匹配查询的工作与match相同,唯一的区别是它应用于多个字段。
GET /_search
{
"query": {
"multi_match" : {
"query": "<your_value>",
"fields": [ "<text_field1>", "<text_field2>" ]
}
}
}
- 可以使用通配符指定字段名称
- 默认情况下,每个字段的权重相等
- 每个字段对分数的贡献可以增加
- 如果在
fields参数中没有指定字段,则将搜索所有符合条件的字段
multi_match有不同类型的。我不会在这篇文章中一一描述,但我会解释最流行的:
best_fields type(默认)更喜欢在一个字段中找到搜索值的标记的结果,而不是在不同字段中找到搜索标记的结果。
most_fields与best_fields型有些相反。
phrase类型的行为与best_fields相似,但搜索的是类似于match_phrase的整个短语。
我强烈建议浏览一下官方文件,看看这些领域的分数是如何计算出来的。
3.复合查询
复合查询将其他查询包装在一起。复合查询:
- 组合 te 分数
- 更改包装查询的行为
- 将查询上下文切换到筛选器上下文
- 以上任意组合
布尔查询
布尔查询 将其他查询组合在一起。它是最重要的复合查询。
布尔查询允许您将查询上下文中的搜索与过滤上下文搜索相结合。
布尔查询有四个可以组合在一起的事件(类型):
must或“必须满足条款”should或“如果满足条款,相关性分数的附加分数”filter或“必须满足该条款,但不计算相关性分数”must_not或“与必须成反比,对相关性得分没有贡献”
must和should → 查询上下文
filter和must_not → 过滤上下文
对于熟悉 SQL 的人来说must是AND而should是OR运算符。因此,必须满足must子句中的每个查询。
提升查询
对于大多数查询来说,Boosting 查询类似于boost参数,但并不相同。提升查询返回匹配positive子句的文档,并降低匹配negative子句的文档的分数。
常数分数查询
正如我们在前面的term查询示例中看到的,constant_score查询将任何查询转换成关联分数等于boost参数(默认为 1)的过滤上下文。
总结一下,Elasticsearch 适合现在很多用途,有时候很难理解什么是最好用的工具。
我希望您记住的主要一点是,您并不总是需要使用最先进的功能来解决简单的问题。
如果您不需要相关性分数来检索数据,请尝试切换到过滤器上下文。
此外,理解 Elasticsearch 如何在幕后工作是至关重要的,因此我建议您始终了解您的分析器是做什么的。
在 Elasticsearch 中有更多的查询类型。我试着描述一下用得最多的。我希望你喜欢它。
让我知道你是否愿意阅读另一个帖子,在那里我给出了所有问题的真实例子。
我计划在 Elasticsearch 上发布更多帖子,所以不要错过。
这是一个相当长的,所以如果你到了那里:
About meMy name is Artem, I build [newscatcherapi.com](https://newscatcherapi.com/) - ultra-fast API to find news articles by any topic, country, language, website, or keyword.I write about Python, cloud architecture, elasticsearch, data engineering, and entrepreneurship.
深入研究 ROC-AUC
为什么 ROC 曲线和曲线下面积对分类很重要?

来源:图片由来自 Unsplash 的 Geran De Klerk 提供
相信大部分人如果对数据科学感兴趣的话,之前都听过 ROC 曲线或者曲线下面积。然而,ROC 曲线到底是什么,为什么 ROC 曲线下的面积是评估分类模型的良好度量?我在上一篇文章中简要介绍了分类的顶级指标,但我将在本文中更详细地介绍。
一些背景信息
ROC 的全称是接收机工作特性。它最初是在第二次世界大战期间为雷达信号探测的使用而创建的。美国已经用它来提高雷达探测日本飞机的准确性。这就是为什么它被称为接收机工作特性。
AUC 或曲线下面积就是 ROC 曲线下的面积。在我们进入什么是 ROC 曲线之前,我们需要快速了解混淆矩阵。

来源:作者-困惑矩阵
从上图可以看出,混淆矩阵是你的预测(1 或 0) vs 实际值(1 或 0)的组合。根据你的预测值和你是否正确分类,它被分为 4 个部分。例如,真阳性是您正确地将病例分类为阳性的病例数,而假阳性是指您错误地将病例分类为阳性的病例数。
混淆矩阵只包含绝对数字。然而,基于这些数字,我们可以开发许多新的基于百分比的指标。真阳性率和假阳性率就是其中的两个。
- 真阳性率(TPR):在真阳性案例中,有多少百分比被正确地捕获到模型中
TPR=TP/(TP+FN)
- 假阳性率(NPR):在真正阴性的病例中,有多少百分比实际上是假阳性。
NPR=FP/(FP+TN)
好了,现在让我们进入 ROC 曲线!
什么是 ROC 曲线?

来源:作者 ROC 曲线示例
从图中可以看出,ROC 曲线只是 TPR 对 NPR 的曲线。好了,故事结束了…
开个玩笑!
你可以从图表中读到更多的信息。这里我想问的第一件事是:模型结果的 TPR、FPR 只有一套,你是如何形成这么多的点来绘制图形的?
这又回到了分类模型的工作原理。当你建立一个像决策树一样的分类模型,你想根据输入来分类股票明天是上涨还是下跌。分类模型将首先根据您提供的历史值计算增加或减少的概率。之后,基于阈值,它将决定结果是增加还是减少。
没错,这里的关键词就是门槛。不同的阈值产生不同的 TPR 和 FPR。它们代表不同的点,形成 ROC 曲线。根据历史数据,如果增加的可能性超过 50%,您可以将输出选择为“增加”,但是您也可以增加阈值,并且只有在超过 90%的可能性时才显示“增加”。如果你选择 90%的信心,而不是 50%,你会更有信心,你选择显示'增加'的股票很可能会增加,但你可能会错过一些潜在的股票。
为什么我在图上画蓝色虚线?
我们知道,曲线下面积(AUC)越大,分类就越好。理想或完美的曲线是一条从(0,0)到(0,1)然后到(1,1)的垂直线,这意味着该模型可以 100%区分正面和负面情况。然而,如果你随机选择每种情况,TPR 和 FPR 应该以同样的速度增长。蓝色虚线显示了当您盲目猜测每种情况下的阳性或阴性时的 TPR 和 FPR 曲线,对于该对角线,曲线下面积(AUC)为 0.5。
如果我改变门槛,TPR、FPR 和 ROC 曲线会发生什么变化?

看 ROC 曲线上的两个点。绿点有一个非常高的阈值,这意味着只有当你有 99%的把握时,你才能将这个案例归类为阳性。红点具有相对较低的阈值,这意味着如果你有 90%的信心,你可以将该病例归类为阳性。
TPR 和 FPR 从绿点到红点的变化是什么?
TPR 和 FPR 都增加了。当您降低阈值时,可以识别更多的阳性病例,因此 TP 增加,TP/(TP+FN)也增加。另一方面,由于阈值的降低,你不可避免地会错误地将一些负面情况归类为正面情况,因此 FP & FP/(FP+TN)也会增加。
我们可以看到,TPR 和 FPR 是正相关的,你必须在最大限度地捕捉正面案例和最小化负面案例的错误分类之间进行*衡。
如何选择 ROC 曲线上的最优点?

很难定义最佳点,因为您应该为业务案例选择最合适的阈值。然而,一般规则是最大化(TPR-FPR),在图中用橙色和蓝色虚线之间的垂直距离表示。
从上面的图表中我们可以看到,在这三个点中,红点的 TPR-FPR 最大,应该被认为是最优点。从红点移到绿点,门槛变得更加严格。然而,大量的阳性病例没有从模型中捕获,错误分类病例的减少低于比例。从红点移动到蓝点,阈值变得更加宽松,并且增加了比正确识别的正点更多的错误分类的正点。
为什么 ROC 曲线下的面积是评估分类模型的良好指标?
一个好的机器学习模型的度量应该显示模型的真实和一致的预测能力。这意味着如果我改变测试数据集,它不应该有非常不同的分数。
ROC 曲线不仅考虑了分类结果,还考虑了所有类别的预测概率。例如,如果输出基于 51%的概率被正确分类,那么如果使用另一个测试数据集,它很可能被错误分类。此外,ROC 曲线还考虑了跨越不同阈值的表现,因此它是评估不同组中的病例的分离程度的综合指标。
分类模型的可接受 AUC 分数是多少?
正如我之前展示的,对于二元分类问题,如果你随机选择,你可以获得 0.5 AUC。因此,如果你正在解决一个二元分类问题,一个合理的 ROC 分数应该是> 0.5 。一个好的分类模型通常具有 AUC 分数> 0.9,但是它完全依赖于应用。
如何用 Python 计算 AUC 并绘制 ROC 曲线?
如果只是想找 AUC 评分,可以参考 sklearn 度量包这里。
如果你想为你的模型结果绘制 ROC 曲线,你可以参考这里的
# Calculate FPR, TPR and AUC
from sklearn.metrics import roc_curve, auc
fpr, tpr, treshold = roc_curve(y_test, y_score_new)
roc_auc = auc(fpr, tpr)#Plot ROC curve
plt.plot(fpr, tpr, color='darkorange',
label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()
下面是我在本文中使用的绘制 ROC 示例图的代码。你需要两个输入,y 的真实值和预测概率。注意 roc_curve 函数只需要正例的概率,而不需要两类的概率。如果你有一个多类分类的问题,你也可以使用这个包,在上面的链接中有一个如何绘制的例子。
如果您有兴趣了解评估分类模型的其他顶级指标,可以参考下面的链接:
与回归模型不同的是,当我们评估分类模型的结果时,我们不能只关注预测…
medium.com](https://medium.com/@songhaowu/top-5-metrics-for-evaluating-classification-model-83ede24c7584)
深层少炮异常检测
入门
利用一些标记的异常实例来执行异常的异常通知检测
由于缺乏大规模的标记异常数据,现有的(深层或浅层)异常检测方法通常被设计为无监督学习(在完全无标记的数据上训练)或半监督学习(在专门标记的正常数据上训练)。因此,当在许多真实世界异常检测应用中这样的信息可用时,它们难以利用先验知识(例如,一些标记的异常)。这些有限的标记异常可能源自已部署的检测系统,例如一些成功检测到的网络入侵记录,或者它们可能来自用户,例如少量由客户报告并由银行确认的欺诈性信用卡交易。由于假设在训练过程中只有非常少量的标记异常可用,该研究路线中的方法可以归入“少量异常检测”这一大类。但是,它们与一般的少投学习也有一些根本的区别。我将在最后讨论更多的差异。在这篇文章中,我将分享我们在利用深度学习技术解决这个问题方面的一些令人兴奋的工作。
研究问题
给定一组大的正常(或未标记)训练数据和非常有限数量的标记异常数据,我们的目标是适当地利用这些小的标记异常数据和大的正常/未标记数据来学习异常检测模型。
基于深度距离的异常检测方法
REPEN [1]可能是第一个深度异常检测方法,旨在利用少数标记的异常来学习基于异常的检测模型。REPEN 的关键思想是学习特征表示,使得异常在随机数据子样本中具有比正常数据实例更大的最*邻距离。这种随机最*邻距离是最有效的异常测量方法之一,如[2,3]所示。REPEN 的目标是学习为这种最先进的异常测量量身定制的特征表示。REPEN 的框架如下图所示。

REPEN 的框架
REPEN 被强制学习比随机数据子集 x_i,…,x_{i+n-1}中的正常实例 x+更大的异常 x-的最*邻距离。总体目标如下

其中 Q 是从未标记/正常训练数据中采样的随机数据子集,f 是神经网络使能的特征学习函数,nn_dist 返回数据子集 Q 中 x 的最*邻距离。
正如你在上面看到的,当大量的训练数据只包含正常数据或者完全没有标记的数据时,REPEN 可以工作。在后一种情况下,我们也没有标记的异常数据,REPEN 使用一些现有的异常检测器来产生一些伪标记的异常数据。所以,REPEN 也可以在完全无人监管的环境下工作。
虽然标记的异常数据是有限的,但是与它的无监督版本相比,REPEN 可以实现非常显著的准确性性能。一些令人印象深刻的结果可以在下面找到。随着标记异常的数量从 1 增加到 80,AUC 性能快速增加。

REPEN 的源代码发布在
这个库向您展示了一个深度异常检测(或异常检测)算法,它使用三元组网络来…
github.com](https://github.com/GuansongPang/deep-outlier-detection)
深度偏离网络:一种端到端异常检测优化方法
与 REPEN 专注于基于距离的异常测量的特征表示学习不同,偏差网络(DevNet [4])旨在利用有限的标记异常数据来执行端到端异常得分学习。下图显示了关键的区别,前者优化了表示,而后者优化了异常分数。

侧重于表示学习的方法与端到端异常检测方法
具体来说,如下面的框架所示,给定一组训练数据实例,所提出的框架首先使用神经异常分数学习器为其分配异常分数,然后基于先验概率定义一些正常数据实例的异常分数的均值,作为指导后续异常分数学习的参考分数。最后,该框架定义了一个损失函数,称为偏差损失,以强制异常的异常分数与正常数据对象的异常分数在统计上有显著的偏差。在 DevNet 的实现中,高斯先验被用于使用基于 Z 分数的偏差损失来执行异常分数的直接优化。

DevNet 的框架
DevNet 的损失函数如下所示

其中,dev 是基于 Z 得分的偏差函数,定义如下

其中 phi 是基于神经网络的映射函数,其将输入 x 投影到标量输出,mu 和 sigma 从高斯先验中提取。这种损失使得 DevNet 能够将正常实例的异常分数推至尽可能接* mu,同时在 mu 和异常的异常分数之间强制至少 a 的偏差。
DevNet 在广泛的真实世界数据集上进行评估。一些结果如下所示。DevNet 的性能明显优于几个最先进的竞争方法,包括 REPEN、深度一类分类器、少镜头分类器和无监督方法 Forest。更有趣的结果可以在[4]中找到。

DevNet 的源代码和数据集发布在
作者:庞关松,,安东·范·丹亨。偏差网络深层异常检测(KDD19)。偏差…
github.com](https://github.com/GuansongPang/deviation-network)
少量异常检测与少量分类
在少量异常检测中,有限的异常样本可能来自不同的异常类别,因此表现出完全不同的流形/类别特征。这从根本上不同于一般的少量学习(主要是分类任务),其中有限的例子是特定于类的,并假设共享相同的流形/类结构。因此,在少量异常检测中,必须小心处理来自一些新型异常类别的未知异常。两篇文章[5,6]旨在解决这个问题。我将在后面讨论这两项研究。
除了上面介绍的两种方法之外,还有一些其他的论文解决了同样的问题。详情请见调查报告[7]。
参考
[1]庞,曹,陈,刘,(2018 年 7 月)。基于随机距离的异常值检测的超高维数据的学习表示。在第 24 届 ACM SIGKDD 知识发现国际会议的会议记录中&数据挖掘(第 2041-2050 页)。[2]庞,g,廷,K. M .,[3]阿尔布雷希特,D. (2015 年 11 月).LeSiNN:通过识别最不相似的最*邻来检测异常。在 2015 年 IEEE 国际数据挖掘研讨会(ICDMW) (第 623–630 页)。IEEE。
[3]杉山,m .,T22 博格瓦德特,K. (2013 年)。通过采样进行基于距离的快速异常检测。在神经信息处理系统的进展(第 467–475 页)。
【4】庞,g,沈,c .&范登亨格尔,A. (2019,7 月)。基于偏差网络的深部异常探测。在第 25 届 ACM SIGKDD 知识发现国际会议论文集&数据挖掘(第 353–362 页)。
【5】庞,g,沈,c,金,h .&亨格尔,A. V. D. (2019)。深度弱监督异常检测。 arXiv 预印本:1910.13601 。
【6】庞,g,亨格尔,A. V. D,沈,c .&曹,L. (2020)。用于未知异常检测的深度强化学习。arXiv 预印本:2009.06847 。
【7】庞,g,沈,c,曹,l,&亨格尔,A. V. D. (2020)。用于异常检测的深度学习:综述。arXiv 预印本:2007.02500 。
我的情节糟透了。以下是我如何修复它们。
你的,在某种意义上,可能也是。

你的工作效率取决于你与他们交流的能力。
我想我们都同意,在数据科学领域,初学者比学长多。因为这种差异,大部分在线课程、教程都是为初学者设计的。特别是,教授数据可视化的课程大多是在探索性数据分析的背景下教授的。结果你看看 Kaggle 或者 GitHub ,到处都是写满剧情的 EDA 笔记本。
我从来不认为这是一件坏事,而是说数据可视化的实践从一开始就变得非常有限。DV 在现实世界中有许多应用,而不仅仅是在死气沉沉的笔记本中,你必须知道如何为任何观众和任何场合创造情节。
当我说我的情节很糟糕时,我暗示如果我把它们带离它们的舒适区(EDA),它们将不会有任何好处。我会说它们对我的 EDAs 来说已经足够好了,但是它们绝对不适合数据科学世界之外的人。
这篇文章介绍了一些不常用的方法来设计你的情节,使它们更容易理解,并为任何不精通技术的人做好准备。
免责声明:这篇文章是为那些已经对 Seaborn,Matplotlib 和 Pandas 有一些经验的人设计的。此外,它不是一个关于如何创建某种类型的地块的教程,而是给你一个全面的样式指南。
概观
∘ 设置
∘ 设置上下文
∘ 设置样式
∘ 注释文本,深度引导
∘ 休息一下,观看一些鱼
∘ 去除棘或轴以更加清晰(去除棘)
∘ 轴标签和标题
∘ 颜色和调色板
设置
我将使用诺贝尔奖数据集。它包含了从成立到 2016 年诺贝尔奖获得者的数据,可以从 Kaggle 下载。对于样式,我将同时使用 Matplotlib 和 Seaborn。
此外,知道如何使用 Matplotlib 的 OOP 接口也很重要。这个界面,配合 Seaborn,允许你无限定制你的情节。如果你不熟悉,我另外写了一篇文章:
[## 一劳永逸地澄清困惑:fig,ax = plt.subplots()
了解 Matplotlib 中的图形和轴对象
towardsdatascience.com](/clearing-the-confusion-once-and-for-all-fig-ax-plt-subplots-b122bb7783ca)
设置背景
准备在除 EDAs 之外的任何其他地方显示您的图被称为解释性数据分析。这是你让你的情节尽可能完美的地方。解释性分析(EA)应该主要关注使用简单而强大的图表来洞察数据集,并且应该为任何受众而设计。
如果你是做 EA 的,人们并不关心你的代码有多好,模块化,可复制。他们只是想了解数据。我建议你为自己做探索性的数据分析,然后,在一个单独的笔记本上总结你的分析要点。这个笔记本应该更多的是讲故事的类型,这真的很重要。
所以,现在让我们来谈谈如何设置情节的背景。这里的上下文只是指你应该如何根据你在哪里显示它们来缩放你的图。
Seaborn 提供从小规模到大规模的 4 种选择。分别是纸、笔记本、谈资、和海报。让我们来看看它们的区别:

希伯恩的不同背景
对于 EDA 来说,最好还是坚持用notebook。然而,如果你正在做一个演示,或者写一篇涉及情节的博客文章,使用talk。上下文不会改变绘图本身,但会放大和缩小刻度线。我使用with上下文管理器来临时设置上下文。还有一个等效功能sns.set_context()不能和(嗯哦) with一起使用。
设置样式
Matplotlib 和 Seaborn 中都有几种样式。Matplotlib 不仅如此,还包括 Seaborn 的风格。改变风格会对你所有的情节产生影响。选择一个大多是基于个人喜好,但有时你将不得不根据你的情节来选择。
如果有许多条形图或线图,最好选择带有背景网格的主题。网格使估计条形的高度或线图的值变得更加容易:

如果不使用线条或线条,则不需要网格。这几种风格你随便选一个:white、dark、ticks。我在这篇文章中只给出了 Seaborn 风格,它们可以使用sns.set_style()来设置。然而,如果你想使用 Matplotlib 样式,该列表可在这里获得。让我们看一个 Matplotlib 的例子:
plt.style.use('dark_background')

注释文本,深度指南
不管你的情节有多美,有多丰富,有时候读起来还是很困难的。因此,您可以使用注释和箭头来指向情节的重要部分,而不是以文本墙的形式提供描述。这一节是关于在图的任何部分放置文本。
首先,让我们向一个空图形放置一个文本:

我们创建一个空的支线剧情。然后,我设置轴限制来绘制更大的图形。annotate()接受的第一个参数是要放置的文本。下一个也可能是最重要的参数是xycoords。它可以接受一定范围的值,但最好将其设置为data。这意味着我们基于我们的数据来定义文本的坐标。因此,当我将xy参数设置为(3,3)时,它会根据轴值来放置它们。让我们在上一个文本的上方 1 点处添加另一个文本:

我们调整了xy的 y 值,将一个文本放在前一个文本之上 1 磅。请注意,因为我将xycoords设置为data,所以单位被计算以匹配轴刻度。如果我们在XAxis上有日期,你可以向xy提供一个日期来指定x坐标。
有时,网格节点可能不是放置文本的最佳位置。您可能希望指向绘图的特定部分,但希望文本从其他偏移位置出现。例如,上面的示例将文本放置在(3,3)坐标处。但是如果我们想要指向同一个点,但是想要文本出现在稍微偏上和偏左的位置呢?Matplotlib 为这些情况提供了另外两个参数:

textcoords就像xycoords接受不同的缩放单位一样。如果我们将textcoords设置为offset points,matplotlib 将 x 和 y 值解释为我们想要将文本移动xy多少个单位。所以解释上面的代码,我们想要注释(3,3)点,但是想要文本出现在上面 30 点和左边 25 点。这种方法非常灵活,因为它允许以我们想要的任何方式控制文本的位置。
现在,让我们回到我们的例子。我们有一个计数图,但不是让观众猜测,我们想把每个酒吧的高度放在自己的顶部。这对解读有很大帮助。来看看剧情:

要在每个条形上方放置一个文本,我们必须找出每个条形的高度。我将图分配给变量的原因是它提供了一些关于图的附加属性:
任何带条形的图都有一个我们可以使用的有用属性,称为patches:
如您所见,图中有 6 个Rectangle对象,就像图中有 6 个条一样。我们打印了第一个条形,从输出中可以看出它的高度是 175。现在,让我们循环遍历每个Rectangle对象,并获得它们的高度和它们的x坐标:
为了获得高度或y值,我们使用.get_height()函数,为了获得x值,我们使用.get_x()。我们还应该得到宽度,这样我们就知道每个条形的中心在哪里。

好吧,我们有短信,但是看起来很奇怪。我们必须给他们一些喘息的空间和一些格式化。我们将使用我们之前讨论过的偏移文本功能:

这就对了,你在顶部放置了每个条形的高度。要达到正确的条件需要一些努力,所以我建议你重读这一节并自己练习。
标注图有许多其他方法,我无法在本文中一一介绍。所以,我就题目单独写了一篇。请查看:
[## 掌握 plt.annotate()让您的情节更上一层楼
上帝保佑所有阅读 Matplotlib 文档的人
towardsdatascience.com](/finally-learn-to-annotate-place-text-in-any-part-of-the-plot-d9bcc93c153f)
休息一下,看些鱼

为了更加清晰起见,去掉了脊线或轴(去除脊线)
因此,我们正在逐步改进我们的简单计数图。在我们输入每个条形的精确值后,没有必要保存YAxis,因为它没有给出任何信息。同样,我们也不需要Y记号标签。

despine()功能可通过 Seaborn 获得。为了给它更多的灵活性,你必须指定使用ax的子情节。这就是为什么我一直用fig和ax对象来处理 Seaborn。Matplotlib 和 Seaborn 是一股需要共同应对的力量。
在接下来的部分,我将改进我们的计数图。因此,为了避免重复,我将围绕情节的主要部分包装一个函数。此外,我将改为单一颜色,稍后我会解释原因:
坐标轴标签和标题
现在,我们最后来谈谈轴标签和标题。它们相当简单,我相信大多数人已经熟悉我将要谈到的方法。首先,我将展示如何改变标签和标题的字体大小和颜色。

对于我们的情节,默认黑色是好的,但我只是想展示一个例子。事实上,一个信息丰富的标题就足够了。我们不需要轴标签。我会将它们移除,并切换回黑色:

颜色和调色板
谈到颜色,有许多事情需要考虑。第一个是数据类型。根据您的数据,有不同的调色板可供选择:
- 圆形调色板:如果你的数据没有顺序,这是最好的选择。
- 顺序调色板:如果您的数据具有一致的范围,从低到高,反之亦然,请使用这些调色板。
- 发散调色板:最好在数据的高点和低点都令人感兴趣时使用。
还有,在颜色不增加任何新信息的情况下,尽量避免使用颜色。或者使用色盲调色板。对于我们的计数图示例,颜色不编码任何新数据。这就是为什么我对所有的条使用单一的颜色。
现在,让我们看另一个使用顺序调色板的例子。我将使用预加载的钻石数据集作为示例:

这里,小节有特定的顺序。这就是为什么使用连续调色板是好的。让我们看另一个例子:

如你所见,选择正确的调色板非常重要。以下是可用的调色板:












palplot()创建这些好看的调色板图,而color_palette()给出当前图。我建议你阅读这篇文章,了解更多关于调色板和颜色的信息。
为任务选择正确的绘图
为不同的观众选择正确的剧情至关重要。我不是在谈论为数据选择正确的图。相反,选择一个以尽可能简单的方式描述您的数据的洞察力。
关于单条支线剧情的一般经验法则:确保一条主线剧情包含的变量不超过 4 个。它没有增加新的信息,反而增加了新的难度。理想是两三个。如果需要更多,请尝试在两个或多个单独的图中显示您的结果。
绘图类型:选择易于阅读的绘图,如条形图、线图或散点图。复杂的图,即使它们给了数据深刻的洞察力,也不容易被许多人解释和理解。在探索性数据分析中,尝试使用工具箱中的一切来最好地理解您的数据。在解释性阶段,用简单的情节概括要点。不要包括像 KDE(核密度估计),小提琴图,盒图,蜂群等图。除非你想让你的观众眼睛流血(或者耳朵流血,如果你在演讲的话)。
多个支线剧情:尽量避免。如果单个图形上有多个图,它们会变得难以阅读,因为比例会变小。在进行分析时,首先使用分面或小多次波来理解数据。然后,在你的 FacetGrid 或支线剧情网格中选择最重要的支线剧情,并单独显示它们。或者并排,如果有两个。确保你显示的支线剧情不超过 3 个。这个需要一个例子:
sns.relplot(x='carat', y='price',
data=diamonds, col='cut', col_wrap=3)

这个 FacetGrid 比较了每种钻石切割的价格和克拉数。对于一个普通人来说,这是很难接受的,他们可能不会看每一个。例如,他们可能感兴趣的是理想钻石的价格如何变化。因此,您获取第一个子情节并单独显示它,而不显示整个 FacetGrid。你可能需要在这方面下点功夫:

这个方法好多了。你可以在关注最重要的部分的同时,快速提及其他剧情的进展。
包扎
呼,这是很多。我给了你很多信息。但这是最好的结果。看完文章,你现在已经准备好把任何情节变成杰作了。使用这里讨论的方法进行解释性数据分析或数据故事讲述。如果你想从成千上万的人中脱颖而出,你也可以在探索性数据分析中使用它们。去打动一些人吧!
请留下反馈,分享文章。作为一名作家,你的支持对我来说意味着一切!这里还有一些关于数据可视化的文章:
[## 掌握 Seaborn 的三分之一:用 relplot()统计绘图
如果你能在锡伯恩做到,就在锡伯恩做吧
towardsdatascience.com](/master-a-third-of-seaborn-statistical-plotting-with-relplot-df8642718f0f) [## 掌握 Seaborn 中的 catplot():分类数据可视化指南。
如果你能在锡伯恩做到,那就在锡伯恩做吧,#2
towardsdatascience.com](/mastering-catplot-in-seaborn-categorical-data-visualization-guide-abab7b2067af)
深度混合学习——传统 ML 与最先进 DL 的融合
一种融合机器学习和深度学习的方法

图片来源: Pixabay
考虑到非结构化数据分析的最新方法,深度学习在提出复杂的算法和模型架构、从非结构化数据中自动展开特征以及为现实世界的问题提供更现实的解决方案方面发挥着极其重要的作用。在我们开始讨论之前,如果你想看一看我在 GIDS AI/ML 2020 大会上展示的与深度混合学习相关的会议记录,请看看:
[## 应用机器学习可解释技术:使 ML 模型可解释和可信…
应用机器学习可解释技术:使 ML 模型可解释和可信赖的实践…
www.amazon.com](https://www.amazon.com/Applied-Machine-Learning-Explainability-Techniques/dp/1803246154?encoding=UTF8&pd_rd_w=Wr6SJ&content-id=amzn1.sym.716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_p=716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_r=6P2PM599T97MRG7NZD9J&pd_rd_wg=m4qUW&pd_rd_r=6e349d93-5ba0-4bfe-9055-905c0153fe58&linkCode=li3&tag=adib0073-20&linkId=35506e1847de5c011fc57aa66c2b1d8e&language=en_US&ref=as_li_ss_il)
现在,深度学习受欢迎的主要原因之一是因为它消除了对非结构化数据进行手动特征工程的需要,这是非常困难的,并且几乎所有经典的机器学习算法都依赖于此。在经典的机器学习方法中,对数据集的理解和对数据集进行特征工程的能力决定了算法的最终性能和准确性。另一方面,由完全连接的神经网络层驱动的深度学习模型的最终分类或聚类层可能会在被馈送“较少”数据时导致过拟合,或者甚至在大多数时候,这些模型需要不必要的计算能力和资源的使用,这在经典的机器学习算法中是不存在的。
[## 应用机器学习可解释技术:使 ML 模型可解释和可信…
应用机器学习可解释技术:使 ML 模型可解释和可信赖的实践…
www.amazon.com](https://www.amazon.com/Applied-Machine-Learning-Explainability-Techniques/dp/1803246154?encoding=UTF8&pd_rd_w=Wr6SJ&content-id=amzn1.sym.716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_p=716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_r=6P2PM599T97MRG7NZD9J&pd_rd_wg=m4qUW&pd_rd_r=6e349d93-5ba0-4bfe-9055-905c0153fe58&linkCode=li3&tag=adib0073-20&linkId=35506e1847de5c011fc57aa66c2b1d8e&language=en_US&ref=as_li_ss_il)
那么,如果我们尝试利用这两种方法的优点,并将它们融合在一起,会怎么样呢?
这可以通过深度混合学习来实现,深度混合学习是合成的融合网络,可以通过深度学习和机器学习相结合来实现。在本文中,我们将学习如何使用深度混合学习,其中我们将使用深度学习方法从非结构化数据中生成或提取特征和使用经典机器学习方法使用非结构化数据构建高度准确的分类模型。因此,使用深度混合学习(DHL) —我们可以利用 DL 和 ML 的优点,减少这两种技术的缺点,并提供更准确、计算成本更低的解决方案。
我们将尝试应用 DHL 来解决斯坦福大学 ML 小组公开发布的 CheXpert 数据集的图像分类问题。简而言之,该项目是关于自动放射图形图像分析,以诊断各种病理。换句话说,我试图从胸部 x 光图像中对不同的疾病状况进行分类。 代码演练在我的个人网站有。

来自 CheXpert 数据集的胸部 x 光图像
根据我们的方法,我们将主要尝试检查两件事:
1.使用独立的 DNN 或 ML 模型检查 DHL 的准确性
2.用 DNN 模型检查算法的计算时间
但是让我们讨论一个简单的 DHL 的模型架构,如下所示:

简单的深度混合网络模型架构(图片由作者提供)
从上图中,我们可以看到一个简单的深度混合网络模型架构。这里,DNN 层只有 4 层,然后是 ML 分类层,我在这里试验了像 AdaBoost,XGBoost 和 Random Forest 这样的 ML 分类算法。对于更复杂的问题解决和更好的模型性能,我建议使用更复杂的 DNN 层,但对于本文,我们的目的不是建立一个超级精确的模型,而是研究 DHL 相对于 ML 和 DL 的改进。
现在,简单的独立 DNN 模型架构如下所示:

简单的 DNN 模型建筑,这将是与 DHN 进行比较的基础
如果我们仔细观察,DNN 层在两种情况下实际上是相同的。 代码演练在我个人网站有。 现在,当我们在大约 10,000 幅图像上训练这两个模型并在 2000 幅图像上检查模型性能时,考虑到在两种情况下用于训练模型和生成特征的时期数是相同的(60 个时期)并且在两种情况下其他超参数调整是一致的,以下是对两种方法观察到的混淆矩阵和 AUC 分数:
- 对于独立的 DNN 型号

独立 DNN 模型的模型评估指标(图片由作者提供)
使用准确度、精确度、召回率、F1 分数、AUC 分数和混淆度量的模型评估度量在 2000 幅测试图像上获得的结果看起来确实很有希望,但是我们将主要使用 AUC 分数和混淆矩阵结果来比较这两种方法。
在我的系统中,60 个时期的总训练时间花费了将* 45 分钟用于训练数据。
2.对于 DHN-阿达布模型

DHN-AdaBoost 模型的模型评估指标(图片由作者提供)
我们确实看到了更好的结果!几乎所有的参数都增加了 6–7 %,这实际上是性能上的重大改进。
现在,您是否想知道在同一台机器上完成培训过程需要多长时间?大概花了 33 分钟!所以,现在我们看到这种方法稍微快一点!
如果我们尝试 DHN 的另一种变体呢?
3.针对 DHN-XGBoost 车型

DHN-XGBoost 模型的模型评估指标(图片由作者提供)
我们再次看到一些有趣的结果。这种变体,虽然表现略好于独立的 DNN 模型,但不知何故,这种方法的训练时间几乎是 48 分钟,这比我们看到的 DHN-阿达布斯和独立的 DNN 模型。
现在,如果我们尝试一种像随机森林这样的非增强技术作为最终分类层,会怎么样呢?模型的表现会更好吗?让我们来了解一下!
4.对于 DHN-随机森林模型

DHN-RF 模型的模型评估指标(图片由作者提供)
不幸的是,在这种情况下,与其他变体相比,结果相当差。但是训练时间很少!同样的训练系统,同样的配置,整个训练过程在 30 分钟内就结束了! 代码演练在我个人网站有。
那么我们可以完全排除这个变种吗?
嗯,也许不是,因为可能有某些数据集,这个变种的 DHN 可能会工作得很好! 如果你想看看代码片段,请访问我的博客文章。
总的来说,我们确实看到深度混合网络在 AUC 指标和模型训练时间方面实际上比独立的 DNN 模型表现得更好。并且 DHN-AdaBoost 变体表现最好。但是你对这个概念和过程感兴趣吗?你有兴趣自己实现它并检查结果吗?如果这两个问题的答案都是肯定的,请给我留言或评论,看看这篇文章的代码演练,您就可以亲自尝试一下,充分利用深度混合学习的优势!
因此,这就把我们带到了本文的结尾。在 我的个人网站 中,我试图提供更多关于 深度杂交网络 关于其他数据集和其他用途的细节。希望我能帮上忙!继续关注:【https://medium.com/@adib0073】**和我的网站:https://www.aditya-bhattacharya.net/**
* [## 应用机器学习可解释技术:使 ML 模型可解释和可信…
应用机器学习可解释技术:使 ML 模型可解释和可信赖的实践…
www.amazon.com](https://www.amazon.com/Applied-Machine-Learning-Explainability-Techniques/dp/1803246154?encoding=UTF8&pd_rd_w=Wr6SJ&content-id=amzn1.sym.716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_p=716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_r=6P2PM599T97MRG7NZD9J&pd_rd_wg=m4qUW&pd_rd_r=6e349d93-5ba0-4bfe-9055-905c0153fe58&linkCode=li3&tag=adib0073-20&linkId=35506e1847de5c011fc57aa66c2b1d8e&language=en_US&ref=as_li_ss_il)
***更新如果你喜欢这篇文章,并希望更多地支持我为社区所做的贡献,请看看我的书“ 【应用机器学习可解释技术 ”,这是 GitHub 资源库,其中包含许多关于书中各个章节的实践教程:https://GitHub . com/packt publishing/Applied-Machine-Learning-explability-Techniques。如果你喜欢 GitHub 资源库中提供的教程,请在资源库中做 fork 和 star,以示你对这个项目的支持!请订购本书的 实体本 或 电子本 以示支持。
深入分区数据库
关于数据库中数据如何分区的所有内容

数据库是任何应用程序设计中不可或缺的一部分,在应用程序设计中,进程会写入和管理数据。尽管可能永远不需要从头开始设计数据库,但了解其设计以及不同数据库处理数据的方式将有助于您选择最合适的数据存储,从而提供所需的可伸缩性和性能。本文将详细介绍数据库如何处理数据分区。
什么是数据分区?
数据库中的数据被分成多个分区。每个分区都被定义为每个数据恰好驻留在一个分区中。一个节点可以包含多个分区。进行分区是为了确保可伸缩性,因为整个数据可能无法放入单个节点。不同的分区可以驻留在不同的节点上。每个节点都可以用自己的分区提供查询服务。这个过程也被称为分片。除了分区,每个分区还被复制到多个节点以确保可用性。

数据分区(来源:微软文档
倾斜的分区和热点
创建数据分区所遵循的技术可能会导致分区之间的负载分布不均匀。一些分区比其他分区提供更多的查询。这种不公*的划分被称为倾斜。在极端情况下,整个负载可以在单个分区 ie 上结束。5 个分区中有 4 个是空闲的。具有不成比例的高负载的分区被称为热点。这种分区效率较低,会导致节点间的负载分布不均匀。
数据分区的方法
我们将讨论三种不同的数据分区方法:
- 随机分布
- 按键范围分区
- 通过键的散列进行分区
密钥的随机分布
一种简单的方法是将数据随机*均分配到不同的分区中。这将导致相等的数据分布,但是没有办法确定哪个键位于哪个分区。这将使阅读变得极其困难。
按键范围分区
另一种方法是将关键字划分为不同的范围,并将每个范围分配给一个分区。例如,值为 A–E 的键可以位于分区 1,F–K 位于分区 2,L–R 位于分区 3,依此类推。范围需要等间距。例如,具有关键字 F、G、H 的数据可以更少,并导致形成其中具有更多关键字的范围(F-K)。

按键分区(来源: AWS 博客
这种方法的优点是数据在分区之间均匀分布,并简化了范围查询。但是这种方法的问题是它可能导致热点的形成。考虑一种情况,其中密钥依赖于时间戳。在这种情况下,所有的写流量都将移动到单个分区。
通过键的散列进行分区
另一种方法可以是计算密钥的散列,并且每个分区可以被分配一个散列范围。在这种情况下,一个好的散列函数不需要在加密方面很强,但应该均匀地分布数据。

通过范围键的散列进行分区(来源: AWS 文档
它将在不同的分区之间*均分配数据和负载,但是使得范围查询变得困难。
分区和辅助索引
辅助索引用于根据不同于主键的字段高效地查询数据。分区将如何解决二级索引上的查询?如果整个数据都驻留在一个分区中,那么为整个数据创建一个二级索引并使用它就很简单了。分区使辅助索引上的查询变得复杂。这种查询有两种方法:
- 按文档划分二级索引(或本地索引) :这样每个分区维护自己的本地二级索引。查询作为分散和收集工作,即它需要从每个分区收集结果,然后合并它。

按文档划分二级索引(来源: 设计数据密集型应用)
2。 按项划分二级索引(或全局索引) : 这里有一个覆盖全部数据的全局二级索引。对于每个键,它存储它所在的分区。由于单个节点可能无法容纳完整的索引,因此全局索引也可以划分到不同的节点中。例如,带有键 A-R 的索引可以驻留在节点 1 上,而驻留在节点 2 上。全局索引增加了写入延迟,但提供了更快的读取速度。

按项目划分二级索引(来源: 设计数据密集型应用
重新*衡分区
随着时间的推移,数据可能会增长,查询类型可能会改变,或者需要替换、删除或添加一些节点。这种情况包括将数据从一个节点移动到另一个节点。重新*衡的要求是:
- 重新*衡后,负载应该在节点间*均分配。
- 在重新*衡时,数据库应该能够提供读写 ie。数据存储应该可用。
- 不应在节点之间移动不必要的数据。
重新*衡可以自动完成,也可以手动完成。
再*衡战略
- 怎么不做:为什么不通过 hash(key) mod N 给一个分区分配键,其中 N 是节点数?因为随着 N 的变化,它将需要大量的重新洗牌和分区移动。
- 固定分区数量:决定分区数量。分区数量可以大于节点数量(N)。每个节点将包含许多分区。当删除或添加一个节点时,一些现有分区可以移动到新节点。
- 动态分区:在固定分区的情况下,分区无法适应不断增长的数据量。在动态分区中,您可以决定分区的初始数量。随着分区大小随着数据的增加而增加,它会拆分以创建新的分区。同样,如果数据被删除,它也会收缩。拆分后,其中一个分区可以分配给不同的节点。
- 按节点比例划分:在这种情况下,每个节点包含固定数量的分区。每个分区的大小与数据集的大小成比例增长。当添加一个新节点时,一些现有的分区被分成两半,一半被移动到新节点。分区边界是随机选取的,因此需要通过键的散列进行分区。
资源
要阅读更多关于数据库和应用程序设计的内容,我强烈推荐阅读 Martin Kleppmann 的“设计数据密集型应用程序”。
希望你喜欢这篇文章!
用于少镜头学习的深核和高斯过程

缺少一个可靠的预测器
在这篇文章中,我们将对 Patacchiola 等人的论文 中的关键概念进行分解,并展示一个简单的关于少量拍摄图像回归任务的例子。本文假设了一些关于高斯过程的背景知识,以及它们是如何在监督学习中使用的(比如获得后验分布和选择核函数)。我们将讨论少投学习的高层次方面,并对该方法进行总结,但不涉及太多的数学细节,这些可以在上面链接的论文中读到。
链接到我的其他文章:
简介
少量学习(FSL)是学习理论和 ML 架构的一个领域,它专注于理解监督学习模型如何从少量训练样本中有效地学习和预测。FSL 的相关方面是优雅地获得预测的不确定性,并增加模型的鲁棒性和泛化能力。FSL 是一个重要的研究领域,因为很大一部分生产监督的机器学习系统,如特斯拉的自动驾驶仪,需要大量的数据和训练时间,以便至少在某种程度上是可靠的,即使这样也容易出现重大泛化问题(因此我仍然喜欢驾驶自己的汽车)。与此相关的是,这些系统必须能够处理呈现给它们的信息的模糊性,并在它们的预测中给出不确定性的度量,以便在现实生活情况中是稳健的。

特斯拉新推出的 HW3 自动驾驶硬件系统。每个特斯拉“芯片”都集成了一个 GPU 和两个用于神经网络预测的特殊硬件加速器。此外,这次有更多的传感器,而不仅仅是摄像机,但同样的原理也适用于处理雷达和超声波回波的摄像机数据。
许多最受欢迎的监督学习模型,如深度神经网络(DNNs)和提升树,在训练样本数量少于数千个时,无法给出足够可靠的预测,更不用说数十个甚至一个样本了。从动物和人类学习的角度来看,少射学习来得相当自然。一个天真的动物(通常)不需要不止一次地吃一种有毒的水果来避免它和后来其他模糊相似的水果。然而,由于 没有免费的午餐 ,某些 FSL 方法存在局限性,比如讽刺的是,当我们有大量样本时,正如我们将看到的。
我的一篇早期文章介绍了在 oldschool Tensoflow (TF 1.x)中实现的一个有趣的 FSL 架构,该架构利用了从高斯过程(GP)分类器模型到深度神经网络的知识提炼,其中来自 GP 和 DNN 的联合损失在 DNN 进行了优化,以便训练 DNN 从极少的训练样本中给出更现实的预测,这些预测反映了数据中的不确定性。2019 年底,Patacchiola 等人推出了一种新方法,该方法将深度神经网络和 GPs 的结合进行了进一步,也许更优雅。为简便起见,我们将他们的方法称为深度内核传输或 DKT。
DKT 方法的主要贡献是在少量回归和跨域分类(即,在不同数据集上训练分类器)方面优于 FSL 专业 DNNs 的性能。
基本概念
简而言之,在预测阶段,DNN 获得我们希望 GP 拟合的(高维)输入,并对其应用非线性维度缩减,将其转换为低得多的维度表示。然后,将变换后的输出馈入 GP 核函数,并通过常规 GP 后验计算来计算后验。
在训练过程中,使用一个证据 损失对 DNN 和 GP 核的参数进行联合优化,该损失是 GP 的联合对数边际概率或可能性。DNN 和 GP 各自通过采用(部分)梯度 w.r.t .获得其各自的相对于联合证据损失的损失,并通过合适的优化器进行更新(Adam 是作者的选择)。

DKT 培训流程图
值得注意的是,DNN 和核仍然是分开的,即 DNN 不是整个核,也不能取代 GP 核的形式的选择(事实上,作者声明径向基核和谱核在他们的实验中表现良好)。DNN 的参数实际上是神经网络的权重,GP 核的参数是核函数中的参数(如 RBF 核中的参数 σ )。
原则上,当处理 2D 图像或张量并计算 GP 后验时,这解决了高维计算难题。通过多类分类中不同类的几个示例或回归任务中的几个示例训练 DNN,允许 DKT 将 GP 的预测属性与 DNNs 的信息表示能力相结合。
神经网络反馈协方差核
核函数 k( x,x’)计算两个“点”之间的协方差,或一般的向量、矩阵或张量。这个核函数用于填充协方差矩阵 K 的元素,我们用它来计算 GP 中的后验分布。

然后,我们使用由其权重*参数化的 DNNφ将我们的训练数据前馈到由 θ 参数化的合适的内核θ。*

经验贝叶斯*似

用参数的点估计逼*边际似然后的联合损失
拥有贝叶斯 GP 框架的好处在于,我们可以假设所有要拟合的参数和输入( φ,θ, x ) 在以目标输出为条件的一些高维空间中形成联合高斯分布。事实上,一般 GP 概念是贝叶斯推理的一个极好的例子。我们拥有作为输入和模型参数的先验数据,以及作为目标的证据数据,并且我们计算后验分布,该后验分布填充我们假设对数据进行建模的核函数的无限维空间希尔伯特空间。
然而,当试图计算预测中的全部后验概率时,出现了一些计算问题,因为需要变分推断方法来计算全部后验概率,并且会使计算变得难以进行。作者通过将参数集(由 hats 表示)固定为点估计值(在联合高斯公式中,参数集被假设为分布,与贝叶斯神经网络中的权重分布假设完全相同)来*似后验概率,并对对数联合边际似然性应用直接的最大似然估计,这被称为经验贝叶斯或 MLE II 型*似,因此边际似然性由上面的正则似然函数 L *似。损失的解析项由作者给出:

*似后损失的解析项
其中协方差矩阵 K 由核θ填充(吸收了高斯噪声参数), y 是目标集合, N 是训练示例或跨域任务(例如,不同数据集)的数量。每组参数和 θ 然后在它们各自对 L 的偏导数上得到更新。这种损失形式的好处在于,它自然地用-log|K|项进行了正则化,这不利于模型的复杂性。
所有这些要花多少钱?
可能和最高期权特斯拉 Cybertruck 一样多。从我收集的信息来看,训练一个 Convnet 的时间复杂度大约为 O(n⁵,计算损耗的矩阵求逆运算至少为 O(n),因此有理由假设我们在训练 DKT 时至少有巨大的 O(n⁵) + O(n ) = O(n⁸的时间复杂度。当然,权衡的结果是在少量的学习中,你只需要很少的训练样本。然而,与此同时,全球定位系统的独特优势是预测本身的预测不确定性的可用性。人们将不得不训练大量的 dnn 或增强树,以获得类似的稳健的不确定性度量。
几个镜头影像回归
好吧,那么这个模型实际上做得有多好?让我们看看试图从一幅图像中的人脸预测人类年龄的问题…只有 98 幅图像可以用来训练。这些图片来自 https://github.com/JingchunCheng/All-Age-Faces-Dataset 的
为了简单起见,我们将调整图像的大小为 80x80 像素的固定大小,并将其下采样为只有一个颜色通道的灰度图像。我们还将使用一个简单的 RBF 内核,因为这对作者来说似乎工作得很好。回购情况如下:
https://github.com/hhl60492/deep-kernel-transfer
一些实施注意事项:
- 最初的 repo 使用 PyTorch 并启用了 CUDA,但是在我的 fork 中,CUDA 依赖性被移除了,因此没有 CUDA/GPU 支持的读者可以运行该模型
- 修改了一些数据加载器脚本和张量的内部形状,以允许对 AAF 图像进行训练-在复杂的 ML 模型/管道中,将数据争论和处理抽象为单独的脚本,并尽可能模块化数据加载和训练/预测组件是一个好主意!
结果
GPNet 回归模型在 98 个随机选择的男性和女性 80×80 JPG 灰度图像上训练,以它们的年龄标签(来自图像文件名)作为目标,持续 100 个时期。发现将年龄目标标准化为[-1,1]对于给出有用的结果是必要的。一般来说,这是深度学习系统的一个大问题,因为必须仔细选择与网络中的激活函数(尤其是回归的输出节点)和损耗(参见对数 RMSE 损耗)相对应的输入和目标归一化(或缺乏归一化)。
此外,在训练之前,没有对图像应用数据增强、对比度调整、去噪或其他处理方法,以证明该方法的稳健性。
在没有 GPU 的慢速 Core i5 笔记本电脑上,此培训只需不到几分钟的时间。一组 5 幅图像的选定测试结果如下:
**Test image filelists/AAF/test/07896A10_gs.jpg **pred 13.78601193428039 95% CI[ -18.663501739501953 , 46.23552858829498 ] target: 9.999999403953552**Test image filelists/AAF/test/07275A76_gs.jpg **pred 68.74524354934692 95% CI[ 36.295726895332336 , 101.19476318359375 ] target: 75.99999904632568**Test image filelists/AAF/test/testA27_gs.jpg **pred 27.942177653312683 95% CI[ -4.507339000701904 , 60.39169430732727 ] target: 26.999999582767487**Test image filelists/AAF/test/07588A05_gs.jpg **pred 9.622436761856079 95% CI[ -22.82707691192627 , 42.07195341587067 ] target: 5.0000011920928955**Test image filelists/AAF/test/07455A02_gs.jpg **pred 7.124289870262146 95% CI[ -25.32522678375244 , 39.57380652427673 ] target: 2.000001072883606****
结果非常好,绝对*均年龄误差只有 4.7 岁左右。此外,给出了置信区间(负区间值可以指示较年轻年龄的不确定性偏差),因此确定性较低的预测具有较宽的区间,反之亦然。一些有趣的事情可以尝试,将旋转/扭曲的图像以及非人类的物体/脸给模型,看看测试结果是什么。同样,随着更多的训练时期,可以预期更好的结果和更小的置信区间。
总的来说,结果是在或超过人类水*的表现…毕竟,你能猜出在下面的测试集中的人的年龄吗?同样,你能估计出这个猜测 95%的置信区间吗?

一些测试图像。我的个人资料图片(testA27_gs.jpg)上的预测相当吓人。
最后注意:由于将 GP 映射到交叉熵损失之后,使用这种方法的少数镜头分类任务有点复杂,但公式在论文中,代码也包含在原作者的报告中。
结论
我们看到了 DKT 是如何组合在一起的,GPs 在预测方面的有趣之处,以及它们如何应用于少量学习中的问题。如果未来的安全关键型实时机器学习系统,如特斯拉的 autopilot 或竞争对手,结合了 GPs 的一些元素,以提高它们在各种现实世界环境中的鲁棒性,而不仅仅是白天沙漠中的一些空高速公路,我不会感到惊讶。一如既往,请随意回复这篇文章,祝数据科学快乐。
神经网络讲解—深度学习 101
人工神经网络的结构及其工作背后的直觉
过去几十年见证了渗透和计算能力的巨大繁荣,在这场信息革命中,人工智能从根本上改变了人们和企业做出决策的方式。这些前沿人工智能解决方案的海报男孩——深度学习和神经网络,尽管它们大肆宣传,但只有少数人理解。
在本文中,我将尝试解释什么是神经网络,它们是如何工作的,以及它们的优势和局限性。希望能让你相信,它们比想象的要简单得多。
注意:深度学习是机器学习的一个子集,如果你不确定它是如何工作的,我建议你先看看这篇文章。
在开始之前,让我们探索一个更简单的问题,建立一些基本概念。
逻辑回归
假设我们是一家信用卡公司,目标客户是没有足够信用记录的人。通过使用用户的历史数据,我们想要决定是否应该给新的申请人发放信用卡。
假设我们做出决策的数据如下。
年龄
薪水
教育
城市
公司
指定
注意:我意识到后 4 个是“定性”变量,但是对于这个例子,让我们假设我们可以以某种方式量化它们
最后的决定是“是”或“否”,从而使它成为一个分类问题。为了解决这个问题,我们将对我们的线性回归方法做一个小小的修改——在将变量乘以它们的权重(我们在线性回归中使用的斜率或系数的技术上正确的名称)并将它们相加(和常数)之后,结果可以是任何数字,并且为了将其转换为是/否决策,我们将必须进一步处理它,即通过一个函数传递它。

对于 g 的一个选择可以是简单的阈值函数:

即。如果变量和权重的和积是 z < 0,则判定为否,如果 Z > =0,则判定为是
然而,通常,我们可能需要结果的概率,而不是绝对的是或否,而且因为计算最佳权重的算法更适合*滑(或者用技术术语来说,可微分)函数,所以我们使用一种称为 sigmoid 的不同函数。

将所有这些联系在一起,对于新客户,我们可以输入不同的变量(年龄、工资等。),将他们与权重的乘积求和,应用 sigmoid 函数,得到他有资格办卡的概率,这整个过程就叫逻辑回归。
激活功能
通过逻辑回归走弯路的原因是为了引入激活函数的概念。逻辑回归中使用的阈值或 sigmoid 函数是激活函数的例子。
任何应用于变量和权重的和积的函数(注意,每个变量都有相应的权重)被称为激活函数。除了上面讨论的阈值和 sigmoid 函数之外,其他一些常用的函数
ReLU(整流线性单位):

这意味着如果 Z 是正数,则原样返回,否则返回 0。
双曲正切值:

这是在 y 轴上向下拉伸的 sigmoid,因此它的中心在(0,0)而不是(0,0.5)
这些函数及其微小的变化是神经网络中最常用的激活函数,原因超出了本文的范围。
神经网络简介
将上面讨论的逻辑回归单元推广到可变数量的输入,我们得到:

即。每个单元(也称为神经元)接收几个输入,输出一个数字。
注意:
对于逻辑回归示例,激活是 sigmoid 函数,输出是预测的概率。
在线性回归的情况下,没有激活函数(也称为线性激活函数,即。g(z) = z),输出就是我们预测的数。
回到我们之前检查申请人的信用卡资格的例子。对于我们的分类任务,代替逻辑回归模型,我们可以创建神经网络来获得更好的结果。

为了创建神经网络,第一步只是将几个单元或神经元堆叠在一起以创建一层。

请注意,每个蓝色圆圈是一个处理单元(神经元),它执行输入(年龄、工资、教育等)和权重的和积,并应用激活函数(比如 ReLU)来给出输出。每个神经元都有不同的权重集,并返回不同的输出。
现在,就像这一层,我们的输入是数据的变量(年龄,工资,教育等),我们可以让这一层的输出( O1,O2,O3,O4 )流入下一层作为它的输入。

我们可以继续像这样增加层。为了完成神经网络,我们添加了一个输出神经元,它将最后一层的输出作为其输入,并返回最终输出(对我们的用例来说是/否决定)。

恭喜你。我们的神经网络准备好了!
对于任何申请人,关于他们的输入变量的数据将进入第一层的 4 个神经元中的每一个。每个神经元将输出一个数字,这一组 4 个数字将作为第二层的输入,第二层的 2 个输出将被发送到最终输出神经元,最终输出神经元的功能就像逻辑回归一样,并返回我们对申请人资格的预测概率。
上面的每个蓝色或绿色圆圈是一个神经元,它们有各自的权重。这些权重必须由模型“学习”,只是线性回归中的线,其中模型学习什么斜率给出最接*训练数据的结果。这是通过称为反向传播和梯度下降的过程发生的,这超出了本文的范围。
但一旦我们“训练”了模型,即学习了所有神经元的最佳权重,输入数据被发送到神经网络,每个神经元将其输入和权重相乘,对总和应用激活并将其发送到下一层,直到我们有最终结果。
注意:通常,ReLU(或其变体之一)用作中间层中的激活,对于输出层,激活由手边的任务决定——线性(或无激活)用于回归任务,Sigmoid 用于分类。
隐藏层
蓝色层(输入和最终输出神经元之间的层)称为隐藏层。这些都是模型“深”的地方。没有这些,我们的模型将是一个简单的线性或逻辑回归。
那么添加隐藏层的整个过程的好处是什么,它们的输出意味着什么。
隐藏层神经元试图捕捉数据中的潜在模式,这将有助于模型预测个人的信誉。
例如,其中一个神经元可以推断他的收入是否足以支付他所在城市的*均生活费用。例如,另一个神经元可以关注公司和职位,以了解他们的工作保障;另一个神经元可以关注年龄、教育和职位,以了解他们的工作表现。其中一个人甚至可以关注候选人的年龄和教育资格,以推断他是否有可能继续深造,如果这被证明是信用卡公司决定他/她的资格的相关因素。
这些推论有助于 NN 对申请人的资格做出更好的决定。像候选人的薪水是否充足、工作保障、表现等方面的见解。将是比直接使用输入变量(年龄、工资、教育等)更好的判断他/她的资格的指标。
注意:一个神经元专注于某个变量仅仅意味着它对那个变量有更高的量级(正的或负的)权重。神经元将使用梯度下降算法自动调整它们的权重,以给出最接*它们被训练的数据的输出。
上面提到的推论只是神经元可能正在计算的例子。在现实中,检查神经网络(检查神经元的权重),我们可能会发现一些模式,这些模式可能不符合我们对一般领域的理解,或者不能被人类直接解释,但已经被神经网络识别为与对给定数据进行预测相关。因此,神经网络也被称为黑盒模型。因为即使模型预测的准确度很高,但结果通常是不可解释的,也就是说,其用户甚至其开发者通常无法解释他们为什么会得到他们正在得到的结果。
处理图像的深度学习模型(卷积神经网络或 CNN)可以在一定程度上得到解释。

例如,在上面用于面部识别的 CNN 的表示(来源)中,我们可以看到,在第一层中,模型正在识别不同角度的直线和曲线。在第二层中,这些线条和曲线被组合起来以识别面部的不同部分,如眼睛、鼻子、嘴唇等。第三层使用这些部分来识别不同类型的脸。识别面部的最终结果将由这些不同类型的面部的加权和产生。
注意:层的数量和每层中神经元的数量被称为超参数,其期望值由数据科学家通过反复试验找到。不像权重,(又名参数,其最优值是通过微积分或其他数学方法找到的。
离别笔记
上面描述的 NN 是一种适合于结构化(或表格)数据的体系结构。对于非结构化数据,我们有不同的体系结构—卷积神经网络用于图像数据,递归神经网络用于文本、声音或其他顺序数据。在这些架构中,各层的结构有些不同,以便为它们的用例产生更好的结果。
希望这让你对什么是神经网络(NNs)和深度学习有了基本的了解,并且它没有看起来那么复杂。😃
深度学习算法——完全指南
深度学习正在吞噬世界。
炒作始于 2012 年左右,当时一个神经网络在图像识别任务上实现了超人的性能,只有少数人能够预测将要发生的事情。
在过去的十年里,越来越多的算法变得可行。越来越多的公司开始在日常业务中添加它们。
在这里,我试图涵盖所有最重要的深度学习算法和架构,这些算法和架构是多年来为计算机视觉和自然语言处理等各种应用而构想的。
其中一些比另一些使用得更频繁,每一种都有自己的优点和缺点。
我的主要目标是让你对这个领域有一个大致的了解,并帮助你理解在每个特定的情况下你应该使用什么算法。因为我知道对于一个想从头开始的人来说这看起来很混乱。
但是在阅读完指南之后,我相信你将能够认识到什么是什么,并且你将准备好马上开始使用它们。
因此,如果你正在寻找一个真正完整的深度学习指南,让我们开始吧。

来源:theaisummer.com
深度学习在科学界和企业界越来越受欢迎。自 2012 年卷积神经网络在图像识别竞赛(ImageNet 大规模视觉识别挑战赛)中获得前所未有的准确性以来,每年都有越来越多的研究论文问世,越来越多的公司开始将神经网络融入他们的业务。据估计,深度学习目前是一个 25 亿美元的市场,预计到 2023 年将达到 181.6 亿美元。
但是什么是深度学习呢?
根据维基百科:“深度学习(也称为深度结构化学习或差分编程)是基于具有表示学习的人工神经网络的更广泛的机器学习方法家族的一部分。学习可以是有监督的、半监督的或无监督的”。
在我看来,深度学习是一组受人脑处理数据和创建决策模式的工作方式启发的算法,是对称为人工神经网络的单一模型架构的扩展和改进。
神经网络
就像人脑一样,神经网络由神经元组成。每个神经元接收信号作为输入,将它们乘以权重,求和并应用非线性函数。这些神经元一个挨着一个堆叠在一起,组织成层。
但是我们这样做能得到什么呢?

来源:维基共享
事实证明,神经网络是优秀的函数逼*器。
我们可以假设每一个行为和每一个系统最终都可以用一个数学函数来表示(有时是一个非常复杂的函数)。如果我们设法找到那个函数,我们就能从本质上理解这个系统的一切。但是找到这个函数非常困难。所以,我们需要估计一下。进入神经网络。
反向传播
神经网络能够使用大量数据和一种称为反向传播的迭代算法来学习所需的功能。我们向网络输入数据,它产生一个输出,我们将该输出与期望的输出进行比较(使用损失函数),然后根据差值重新调整权重。
并重复。并重复。使用称为随机梯度下降的非线性优化技术进行权重调整。
过一段时间后,网络会变得非常擅长产生输出。因此,训练结束了。因此,我们设法逼*我们的函数。如果我们将一个未知输出的输入传递给网络,它会根据*似函数给出一个答案。
让我们用一个例子来说明这一点。假设出于某种原因,我们希望用树来标识图像。我们向网络输入任何类型的图像,它就会产生一个输出。因为我们知道图像实际上是否有树,所以我们可以将输出与我们的真实值进行比较,并调整网络。
随着我们传递的图像越来越多,网络犯的错误会越来越少。现在我们可以给它一个未知的图像,它会告诉我们图像中是否包含一棵树。很酷,对吧?
多年来,研究人员对最初的想法进行了惊人的改进。每一种新的体系结构都针对一个特定的问题,其中一种实现了更好的准确性和速度。我们可以将所有这些新模型分为特定的类别:
前馈神经网络(FNN)
前馈神经网络通常是全连接,这意味着一层中的每个神经元都与下一层中的所有其他神经元相连接。所描述的结构被称为多层感知器,起源于 1958 年。单层感知器只能学习线性分离模式,但多层感知器能够学习数据之间的非线性关系。

来源:维基百科常见
他们非常擅长分类和回归等任务。与其他机器学习算法相反,它们不那么容易收敛。他们拥有的数据越多,准确性就越高。
卷积神经网络(CNN)
卷积神经网络采用了一种称为卷积的功能,其背后的概念是,我们不是将每个神经元与所有下一个神经元相连,而是仅将它与少数神经元(感受野)相连。
在某种程度上,他们试图正则化前馈网络以避免过度拟合(当模型只学习预先看到的数据而不能概括时),这使得它们非常善于识别数据之间的空间关系。

来源:维基共享
这就是为什么他们的主要用例是计算机视觉和应用程序,如图像分类、视频识别、医学图像分析和自动驾驶汽车,在这些应用程序中,他们实现了真正的超人性能。
它们也非常适合与其他类型的模型(如递归网络和自动编码器)结合使用。一个这样的例子是手语识别。
递归神经网络(RNN)
递归网络非常适合与时间相关的数据,它们用于时间序列预测。他们使用某种形式的反馈,将输出返回给输入。你可以把它想象成一个从输出到输入的循环,以便把信息传递回网络。因此,他们能够记住过去的数据,并在预测中使用这些信息。
为了获得更好的性能,研究人员已经将原始神经元改造成更复杂的结构,如 GRU 单元和 LSTM 单元。LSTM 单元已经被广泛用于自然语言处理中的任务,例如语言翻译、语音生成、文本到语音合成。

来源:维基共享
递归神经网络
递归神经网络是另一种形式的递归网络,不同之处在于它们以树状形式构造。因此,他们可以在训练数据集中建模分层结构。
由于它们与二叉树、上下文和基于自然语言的解析器的联系,它们传统上用于 NLP 的应用中,如音频到文本的转录和情感分析。然而,它们往往比循环网络慢得多
自动编码器
自动编码器主要用作无监督算法,其主要用例是维度缩减和压缩。他们的诀窍是试图使输出等于输入。在其他工作中,他们试图重建数据。
它们由一个编码器和一个解码器组成。编码器接收输入,并在较低维度的潜在空间中对其进行编码。解码器获取该向量,并将其解码回原始输入。

来源:维基百科常见
这样,我们可以从网络的中间提取一个维数更少的输入表示。天才,对吧?
当然,我们可以用这个想法来复制相同但稍有不同甚至更好的数据(训练数据扩充、数据去噪等)
深度信念网络和受限玻尔兹曼机器
受限玻尔兹曼机器是具有生成能力的随机神经网络,因为它们能够学习其输入的概率分布。与其他网络不同,它们只包含输入和隐藏层(没有输出)。
在训练的前一部分,他们接受输入并产生一个表示。在后向传递中,他们从表示中重建原始输入。(与自动编码器完全一样,但在一个网络中)。

来源:维基共享
多个 RBM 可以叠加形成一个深度信念网络。它们看起来完全像完全连接的层,但它们在训练方式上有所不同。这是因为它们按照 RBMs 的训练过程(如前所述)成对训练层
然而,dbn 和 RBM 已经被科学界抛弃,取而代之的是变化的自动编码器和 gan
生成对抗网络
gan 是由 Ian Goodfellow 在 2016 年推出的,它们基于一个简单而优雅的想法:你想要生成数据,比如说图像。你是做什么的?
你建立两个模型。你训练第一个生成假数据(生成器),第二个辨别真假(鉴别器)。你让他们互相竞争。
生成器在图像生成方面变得越来越好,因为它的最终目标是欺骗鉴别器。鉴别器变得越来越擅长区分真假图像,因为它的目标是不被愚弄。结果是我们现在有了来自鉴别器的难以置信的真实的假数据。
生成性对抗网络的应用包括视频游戏、天文图像、室内设计、时尚。基本上,如果你的领域中有图像,你可以潜在地使用 GANs。Oooh,你还记得深度假货吗?是啊,那都是甘斯做的。
变形金刚(电影名)
变压器也是非常新的,它们主要用于语言应用,因为它们开始使循环网络过时。他们基于一种叫做注意力的概念,这种概念被用来迫使网络专注于一个特定的数据点。
你不用过于复杂的 LSTM 单位,而是使用注意力机制来根据重要性衡量输入的不同部分。注意力机制只不过是另一层权重,其唯一目的是调整权重,使输入片段优先,而其他片段不优先。
事实上,转换器由许多堆叠的编码器(形成编码器层)、许多堆叠的解码器(解码器层)和一堆关注层(自我关注和编码器-解码器关注)组成
转换器被设计为处理有序的数据序列,例如自然语言,用于各种任务,例如机器翻译和文本摘要。如今,BERT 和 GPT-2 是两个最著名的预训练自然语言系统,用于各种 NLP 任务,它们都基于 Transformers。
图形神经网络
非结构化数据通常不太适合深度学习。在许多真实世界的应用程序中,数据是非结构化的,并以图形格式组织。想想社交网络、化合物、知识图表、空间数据。
图形神经网络的目的是对图形数据进行建模,这意味着它们识别图形中节点之间的关系,并生成图形的数字表示。就像嵌入一样。因此,它们可以在任何其他机器学习模型中用于各种任务,如聚类、分类等。
自然语言处理中的深度学习
单词嵌入
单词嵌入是单词到数字向量的表示,以某种方式捕获它们之间的语义和句法相似性。这是必要的,因为神经网络只能从数字数据中学习,所以我们必须找到一种方法将单词和文本编码成数字。
- Word2Vec 是最流行的技术,它试图通过基于上下文预测单词(CBOW ) 或基于单词预测周围的单词(Skip-Gram)来学习嵌入。Word2Vec 只不过是一个简单的两层神经网络,以单词作为输入和输出。单词以一键编码的形式输入到神经网络中。
- 在 CBOW 的情况下,输入是相邻的字,输出是想要的字。在 Skip-Gram 的情况下,情况正好相反。
- Glove 是另一个扩展 Word2Vec 思想的模型,它将 word 2 vec 与潜在语义分析等矩阵分解技术相结合,这些技术被证明是非常好的全局文本统计,但无法捕捉局部上下文。所以这两者的结合给了我们两个世界最好的东西。
- 脸书的 FastText 使用了一种不同的方法,用字符级的表示代替单词。
- 上下文单词嵌入用递归神经网络代替 Word2Vec,在给定句子中的当前单词的情况下,预测下一个单词。这样,我们可以捕捉单词之间的长期依赖关系,每个向量都包含当前单词和过去单词的信息。最著名的版本叫做 ELMo ,它由两层双向 LSTM 网络组成。
- 注意力机制和变形金刚正在让 RNN 过时(如前所述),通过加权最相关的单词,忘记不重要的单词。
序列建模
序列模型是自然语言处理的一个组成部分,因为它出现在许多常见的应用程序中,如机器翻译,语音识别,自动完成和情感分类。序列模型能够处理一系列输入或事件,例如单词文档。
例如,假设你想把一个句子从英语翻译成法语。
为此,您需要一个序列到序列模型(seq2sec) 。Seq2sec 型号包括一个编码器和一个解码器。编码器获取序列(英语句子)并产生输出,即输入在潜在空间中的表示。这个表示被馈送到解码器,解码器给我们新的序列(法语句子)。
编码器和解码器最常见的架构是递归神经网络(主要是 LSTMs ),因为它们在捕捉长期依赖性和转换器方面表现出色,往往更快、更容易并行化。有时,它们也与卷积网络结合使用,以获得更高的精度。
伯特和 GPT-2 被认为是两个最好的语言模型,他们实际上是基于转换器的序列模型。
计算机视觉中的深度学习

来源:维基共享
定位和目标检测
图像定位的任务是定位图像中的对象,并用边界框标记它们,而对象检测也包括对象的分类。
这些相互关联的任务是由计算机视觉中一个叫做 R-CNN 的基本模型(及其改进)来处理的。RCNN 及其前身快速 RCNN 和快速 RCNN 利用了区域建议和卷积神经网络。
外部系统或网络本身(在更快的 RCNN 的情况下)以固定大小的盒子的形式提出一些感兴趣的区域,该盒子可能包含对象。这些框通过 CNN(如 AlexNet)进行分类和校正,CNN 决定框中是否包含对象,对象是什么,并确定边界框的尺寸。
单发探测器
单发探测器和它最著名的成员 YOLO(你只看一次)放弃区域提议的想法,他们使用一组预定义的盒子。
这些框被转发给 CNN,CNN 为每个框预测一定数量的具有置信度得分的边界框,它检测位于其中的一个对象,并将该对象分类到一个类别中。最后,我们只保留得分高的包围盒。
多年来,YOLOv2、YOLOv3 和 YOLO900 在速度和精度上都比最初的想法有所改进。
语义分割
计算机视觉中的一个基本任务是基于图像中所有像素的上下文将其分类,也称为语义分割。在这个方向,全卷积网络(FCN)和 U-网是两个最广泛使用的模型。
- 全卷积网络(FCN) 是一种具有一个卷积和一个去卷积网络的编码器-解码器架构。编码器对图像进行下采样以捕获语义和上下文信息,而解码器进行上采样以检索空间信息。这样,我们就能以尽可能小的时间和空间复杂度来检索图像的上下文。
- U 网基于跳跃连接的巧妙想法。它们的编码器具有与解码器相同的大小,并且跳跃连接将信息从第一个传输到后者,以便增加最终输出的分辨率。
姿态估计
姿态估计是在图像和视频中定位人体关节的问题,它可以是 2D 或 3D。在 2D,我们估计每个关节的(x,y)坐标,而在 3D 中是(x,y,z)坐标。
PoseNet 在该领域占据主导地位(它是大多数智能手机应用程序的首选模型),它使用卷积神经网络(没想到会这样,是吧?).我们将图像输入 CNN,然后使用单姿态或多姿态算法来检测姿态。每个姿势都与一个置信度得分和一些关键点坐标相关联。最后,我们保留置信度最高的那些。
包扎
这就是了。当时所有必不可少的深度学习算法。
当然,我不能包括所有已发表的架构,因为它们实际上成千上万。但是它们中的大多数都是基于这些基本模型中的一个,并用不同的技术和技巧对其进行改进。
我也相信我需要很快更新这个指南,因为在我们说话的时候新的论文就要出来了。但这就是深度学习的美妙之处。新突破的空间如此之大,以至于有点可怕。
现在轮到你了。去用这些算法构建你自己的令人惊奇的应用程序吧。或者甚至创建一个新的,会在我们的列表中出现。为什么不呢?
玩得开心,继续学 AI。
原载于 2020 年 2 月 26 日 https://theaisummer.com。
深度学习和信息论
付费墙是否困扰着你?点击 这里 可以绕过去。
试图建立对信息论概念的直觉和数学理解,以及如何将其应用于深度学习
如果你试图理解机器学习背后的数学,包括深度学习,你会遇到信息论的主题——熵、交叉熵、KL 散度等。信息论的概念在机器学习领域一直很流行,从决策树的分裂标准到生成对抗网络中的损失函数。
如果你是机器学习的初学者,你可能没有努力去深入理解“背后的数学。fit() ”,但随着你的成熟和遇到越来越复杂的问题,理解数学或至少数学背后的直觉变得至关重要,以便在正确的地方有效地应用正确的技术。
当我开始的时候,我也犯了同样的错误。我会将“交叉分类熵”视为神经网络中的损失函数,我认为这是理所当然的——这是一种适用于多类标签的神奇损失函数。我将“熵”视为决策树中的一个分裂标准,我只是在不了解它是什么的情况下进行实验。但是随着我的成熟,我决定花更多的时间去理解基础知识,这极大地帮助了我获得正确的直觉。这也有助于理解流行的深度学习框架 PyTorch 和 Tensorflow 实现不同损失函数的不同方式,并决定何时使用什么。
这篇博客是我总结我对信息论的基本概念的理解,以及不同深度学习框架的实现如何不同。我试图解释的每一个概念都以介绍和加强直觉的方式开始,然后提供与之相关的数学作为奖励。我总是发现没有什么比数学更能理清思路了。
信息论
在 20 世纪早期,全世界的计算机科学家和数学家都面临着一个问题。如何量化信息?我们来考虑下面的两句话:
- 明天会下雨
- 明天会下大雨
作为人类,我们直觉地理解这两个句子传递了不同的信息量。第二个比第一个信息量大得多。但是,如何量化呢?你如何用数学语言来表达?
克劳德·e·香农(Claude E. Shannon)带着他的开创性论文《沟通的数学理论》(A Mathematical Theory of Communication)[1]进入了我们的讨论。香农介绍了作为统计过程的交流的定性和定量模型。在许多其他的想法和概念中,他引入了信息熵和“比特”的概念,比特是信息测量的基本单位。
信息论非常庞大,但是我将尝试用一个简短的术语表来总结关键的信息。
- 信息被认为是要通过称为信道的介质传输的符号序列。
- 熵是在给定一些符号分布知识的情况下,一串符号中的不确定量。
- Bit 是一个信息单位,或者一个符号序列。
- 传递 1 比特的信息意味着将接收者的不确定性减少 2
熵
让我们举一个例子,用它来阐明熵背后的直觉。无处不在的“盒子里的球”的例子和任何例子一样好。
有一个装有 100 个球的盒子,这些球有四种不同的颜色——蓝色、红色、绿色和黄色。让我们假设盒子里每种颜色有 25 个球。一个发送器从容器中随机拾取一个球,并将该信息发送给一个接收器。对于我们的例子,让我们假设发射机在印度,接收机在澳大利亚。让我们假设我们处于 20 世纪早期,那时电报是远距离通讯的主要方式之一。电报信息的问题在于,它们是按字数收费的,所以如果你有预算,你需要小心你发送的内容(这可能现在看起来不重要,但我向你保证它会的)。这只是给公式增加了一个限制——你不能通过电报发送真正的单词“blue”。英语没有 26 个符号,只有两个符号——0 和 1。

现在,让我们看看我们将如何对这四个响应进行编码。我相信你们都知道二进制数字系统。因此,如果我们有四个结果,我们可以使用长度为 2 的代码得到唯一的代码。我们用它来为我们的四个结果分配一个代码。这是固定长度编码。

另一种思考方式是减少不确定性。我们知道这四种结果的可能性都是相等的(各有 1/4 的概率)。当我们传递关于捡球颜色的信息时,不确定性减少了 4。我们知道 1 位可以减少 2 倍的不确定性,要减少 4 倍的不确定性,我们需要两位。
从数学上讲,如果我们使用的代码中有 m 个符号,我们将需要 log₂M 位来编码信息。
我们用来发送信息的*均位数是多少?


*均值和期望值
什么是*均值?在概率的世界里,*均值是概率分布的期望值。

期望值也可以这样想:如果我们从盒子中随机挑选一个球 1000 次,记录对该消息进行编码所需的比特长度,并取所有这 1000 个条目的*均值,您将得到比特长度的期望值。
如果所有结果的可能性相等,P(x) = 1/N,其中 N 是可能结果的数量。在这种情况下,期望值变成了一个简单的*均值。


让我们稍微改变一下示例的设置。现在我们有 25 个蓝色球、50 个红色球、13 个绿色球和 12 个黄色球,而不是相同数量的彩色球。这个例子更好地解释了其余的概念,因为现在你知道概率分布的期望值是什么,我们可以遵循这个惯例。


期望值不会改变,因为无论选择哪个球,使用的位数仍然是 2。
但是,当前的编码方案是最佳的吗?这就是可变长度编码发挥作用的地方。让我们来看看三种不同的可变编码方案。

现在我们知道了如何计算位长的期望值,让我们来计算三种方案的期望值。比特长度最小的应该是最经济的吧?
编码方案 1:
我们对蓝色和红色使用 1 位,对绿色和黄色各使用 2 位。

编码方案二:
我们对蓝色使用 1 位,对红色使用 2 位,对绿色和黄色各使用 3 位。

编码方案 3:
我们对蓝色使用 2 位,对红色使用 1 位,对绿色和黄色各使用 3 位。

编码方案 1 是显而易见的选择,对吗?这就是变长编码变得棘手的地方。如果我们从盒子里拿起一个球,它是蓝色的。因此,我们将“0”作为消息发送到澳大利亚。在澳大利亚有机会阅读这个信息之前,我们选择了另一个球,它是绿色的。所以我们把“10”送到澳大利亚。现在,当澳大利亚查看消息队列时,他们会在那里看到“010”。如果是固定长度的代码,我们就会知道每隔 n 个符号就有一个断点。但是,如果没有这一点,“010”可以解释为蓝色,绿色或蓝色,红色,蓝色。这就是为什么一个代码应该是唯一可解码的。如果两个不同的符号串从未产生相同的编码位串,则称一个码是唯一可解码的。这导致了这样一种情况,即每添加一个额外的符号,就必须放弃一些代码。克里斯·奥拉有一个很棒的博客来解释这个概念。
这给我们留下了编码方案 2 和 3。两者都是唯一可解码的。它们之间的唯一区别是,在方案 2 中,我们对蓝色使用 1 位,对红色使用 2 位。方案 2 是相反的。我们知道从盒子里得到红球的可能性比蓝球大得多。因此,对红球使用较小的长度是有意义的,这就是为什么方案 3 的比特长度的期望值低于方案 2 的原因。
现在你可能想知道为什么我们如此关心比特的预期长度。最佳可能编码方案的这种预期比特长度被称为 香农熵 或简称为熵。只有一部分是不完整的。对于给定的问题,如何计算最佳位数?
简单的答案是-log₂p(x).
并将其扩展到整个概率分布 P ,我们取期望值:

在我们的例子中,结果是:

对于那些有兴趣知道我们是如何得出这个公式的人,请继续阅读。
数学
虽然直觉有助于获得想法,但你无法真正衡量它。每次遇到新问题,都不能拿着纸和笔坐下来,想出最佳编码方案再计算熵。这就是数学的用武之地。
唯一可解码码的特性之一是前缀特性。任何代码字都不应该是另一个代码字的前缀。这意味着,每当您选择一个长度较短的代码时,您就放弃了以该代码为前缀的所有可能的代码。如果我们把 01 作为一个代码,我们不能使用 011 或 01001 等。因此,选择每个代码会产生成本。引用克里斯·奥拉的博客:
买一个长度为 0 的码字的成本是 1,所有可能的码字——如果你想拥有一个长度为 0 的码字,你就不能拥有任何其他的码字。像“0”一样,长度为 1 的码字的成本是 1/2,因为一半可能的码字以“0”开始。像“01”一样,长度为 2 的码字的成本是 1/4,因为所有可能的码字的四分之一以“01”开始。一般来说,码字的成本随着码字的长度呈指数下降。
克里斯·奥拉的博客【2】
成本可以量化为

其中 L 是消息的长度。反过来,我们得到:

现在,成本是多少?我们的花费与需要编码的特定结果成正比。所以我们为一个特定的变量 x 花费 P(x),因此成本= P(x)。(为了更好地了解这一成本,请阅读克里斯·奥拉的博客文章 [2])

交叉熵
在我们的例子中,现在澳大利亚也有一个盒子,里面有同样的四个彩色球。但是球的分布是不同的,如下所示(用 q 表示)

现在澳大利亚想做和印度一样的实验,并发回他们选择的球的颜色。他们决定使用先前设置的相同编码方案来进行通信。
因为编码方案是从源分布中导出的,所以每个结果的比特长度与以前相同。例如。

但是不同信息的使用频率发生了变化。因此,现在澳大利亚抽出的球的颜色将有 50%的时间是绿色的,以此类推。我们为第一个用例(印度到澳大利亚)推导出的编码方案并未针对第二个用例(澳大利亚到印度)进行优化。


这就是交叉熵,它可以正式定义为:

其中 p(x)是用于提出编码方案的分布的概率,q(x)是使用它们的分布的概率。
交叉熵总是等于或大于熵。在最好的情况下,源和目的地分布完全相同,在这种情况下,交叉熵变成熵,因为我们可以用 p(x)代替 q(x)。用机器学习的术语来说,我们可以说预测分布是 p(x),地面真值分布是 q(x)。因此,预测分布和真实分布越相似,熵和交叉熵就越接*。
库尔贝克-莱布勒散度
既然我们已经理解了熵和交叉熵,我们就可以理解另一个名字很吓人的概念了。这个名字太吓人了,甚至从业者都称之为 KL 散度,而不是实际的 Kullback-Leibler 散度。这个来自信息论深处的怪物是一个非常简单易懂的概念。
KL 背离衡量一个分布与另一个分布的背离程度。在我们的例子中,我们使用用于从印度到澳大利亚的通信的编码方案来进行反向通信。在机器学习中,这可以被认为是试图用预测分布(q)来逼*真实分布(p)。但是这样做,我们花费了比发送消息所需更多的比特。或者,我们有一些损失,因为我们用 q 逼* p,这种信息的损失叫做 KL 散度。
KL 散度的两个关键性质值得注意:
- KL 散度是非负的。即它总是零或正数。
- KL 散度是非对称的。即从 p 到 q 的 KL 散度不等于 q 到 p 的 KL 散度。正因为如此,它不是严格意义上的距离。

KL(P||Q)可以用以下方式解释:
- 从 Q 到 P 的背离
- P 相对于 Q 的相对熵
- Q 有多接* P
数学
让我们看看我们是如何得出公式的,这将增强我们对 KL 散度的理解。
从直觉上我们知道 KL(P||Q)是用 Q 逼* P 时丢失的信息,那会是什么呢?
只是重述一下我们的示例与 ML 系统的类比,以帮助您更好地连接这些点。让我们利用澳大利亚向印度发送消息的情况,使用为从印度到澳大利亚的消息设计的相同编码方案。
- 带球盒子(在印度和澳大利亚)是概率分布
- 当我们准备一个机器学习模型(分类或回归)时,我们所做的是逼*一个概率分布,并且在大多数情况下输出概率分布的期望值。
- 基于概率分布设计编码方案就像准备一个模型来输出该分布。
- 在印度有球的盒子是预测的分布,因为这是我们在设计编码方案时假设的分布。
- 在澳大利亚有球的盒子是真正的发行版,因为这是使用编码方案的地方。
当我们在澳大利亚使用编码方案时,我们知道比特的期望值。就是 Q w.r.t. P 的交叉熵(其中 P 是预测分布,Q 是真实分布)。

现在,有一些低效率,因为我们使用的是为另一种概率分布设计的编码方案。这里的理想案例是什么?预测分布等于真实分布。这意味着如果我们使用为 Q 设计的编码方案来发送信息。这就是 q 的熵。

因为我们有实际的交叉熵和理想熵,所以由于编码方案而丢失的信息是





这也应该给你一些直觉,为什么这个指标是不对称的。
注意:我们已经讨论了整个博客,假设随机变量 X 是一个离散变量。如果它是一个连续变量,只需将∑替换为∫,公式就会再次生效。
深度学习的应用
损失函数是深度学习系统的核心。我们传播以调整权重的梯度源自这个损失函数。分类问题中最流行的损失函数来自信息论,特别是熵。
分类交叉熵损失
在 N 向分类问题中,神经网络通常有 N 个输出节点(二进制分类除外,它只有一个节点)。这些节点的输出也称为逻辑。逻辑是在我们应用激活之前神经网络的实值输出。如果我们通过 softmax 层传递这些逻辑,输出将被转换成类似于样本是该特定类的概率(统计学家现在会在坟墓里翻来翻去)。


本质上,softmax 将原始逻辑转换为概率。因为我们现在有了概率,我们可以像之前回顾的那样计算交叉熵。
用机器学习的术语来说,交叉熵公式是:

其中 N 是样本数,C 是类别数,y 是真实概率,y_hat 是预测概率。在典型的情况下,y 将是目标标签的独热码表示(到处都是零,一个表示正确的标签)。
交叉熵和对数似然
概率与可能性
在非技术术语中,可能性和概率可以互换使用。但在统计学中,以及通过扩展机器学习,它有不同的意义。简而言之,概率是指我们谈论结果的时候,而可能性是指假设。
让我们以正态分布为例,均值为 30,标准差为 2.5。我们可以从分布中找到抽取值为 32 的概率。

现在让我们颠倒一下情况,考虑我们不知道基本的分布。我们只有从分布中得到的观察值。在这种情况下,我们仍然可以像假设特定分布之前一样计算概率。

现在我们正在寻找一个特定的观察结果被假定的参数所描述的可能性。当我们最大化这种可能性时,我们会得到最适合抽取样本的参数。这是可能性。
总结一下:


在机器学习中,由于我们试图从数据中估计潜在的分布,我们总是试图最大化可能性,这被称为最大似然估计。在实践中,我们最大化对数似然,而不是似然。
数学

其中 N 是样本数,f 是一个函数,它给出了给定协变量 x 和参数时 y 的概率。
当我们处理上述乘积项时,有两个困难:
- 从数学的角度来看,当它是求和的时候,积分和导数更容易处理
- 从计算机科学的角度来看,将许多小数字相乘会产生非常小的数字,从而导致算术下溢
这就是对数可能性发挥作用的地方。如果我们应用对数函数,乘积就变成了总和。并且由于对数是单调变换,最大化对数似然性也将最大化似然性。因此,为了方便起见,我们几乎总是最大化对数似然,而不是纯似然。

交叉熵=对数似然
让我们将 q 视为真实分布,将 p 视为预测分布。 y 是样本的目标, x 是输入特征。
基本事实分布通常是可能标签上的一个热点表示。

对于 yᵢ的 xᵢ样本,交叉熵为:

其中 Y 是所有标签的集合
q(y|xᵢ项)对于 y 中除 yᵢ之外的所有元素都是 0,对于 yᵢ.是 1 所以这个术语简化为:

其中 yᵢ是样品的正确标签。
现在对所有 N 个样本求和,

也就是对数似然的负值。所以最大化对数似然相当于最小化交叉熵。
二元交叉熵损失
在二元分类中,神经网络只有一个输出,通常通过一个 sigmoid 层。如下所示的 sigmoid 图层将逻辑值压缩为 0 到 1 之间的值。

因此,s 形图层的输出相当于事件的概率。因此,如果我们有两个类,0 和 1,随着网络关于样本为“1”的置信度增加,sigmoid 层的输出也变得更接* 1,反之亦然。
二元交叉熵(BCE)是专门为二元分类定制的损失函数。让我们从公式开始,然后试着将它与我们目前所学的内容进行对比。

虽然这个公式乍一看可能不熟悉,但这只是我们前面提到的交叉熵的一个特例。与多类输出不同,我们只有一个介于 0 和 1 之间的输出。因此,为了应用交叉熵公式,我们综合创建两个输出节点,一个具有 y ,另一个具有 1-y (根据概率定律,我们知道在二元结果中,概率总和为 1),并对所有结果的交叉熵求和。

库尔巴克-莱布勒发散损失
我们知道 KL 散度是不对称的。如果 p 是预测分布, q 是真实分布,有两种方法可以计算 KL 散度。

项目 1

项目 2
第一个叫做 KL 向前发散。它给出了预测值偏离真实分布的程度。第二个叫做后向 KL 散度。它给出了真实分布与预测分布的偏离程度。
在监督学习中,我们使用前向 KL 散度,因为可以证明最大化前向 KL 散度相当于最大化交叉熵(我们将在数学部分详述),并且交叉熵更容易计算。由于这个原因,交叉熵在最简单的用例中比 KL 散度更可取。变分自动编码器和 GANs 是 KL 散度再次变得有用的几个领域。
当前向 KL 对均值做同样的事情时,后向 KL 散度用于强化学习并鼓励优化以找到分布的模式。关于 KL 前向和后向背离的更多细节,请阅读 Dibya Ghosh 的博客文章
数学
我们知道 KL 散度是交叉熵和熵的差。


因此,N 个样本的交叉熵损失为:

现在,优化目标是通过改变参数化预测分布 p 的参数来最小化这种损失。因为 H(q)是真实分布的熵,与参数无关,所以可以认为它是一个常数。优化时,我们知道常数是不重要的,可以忽略不计。所以损失变成了:

总之,我们从交叉熵损失开始,证明了最小化交叉熵等同于最小化 KL 散度。
在流行的深度学习框架中实现
这些损失在 PyTorch 和 Tensorflow 等流行的深度学习框架中的实现方式有点混乱。PyTorch 尤其如此。
PyTorch
- binary_cross_entropy —这要求在计算损失之前,逻辑值通过一个 sigmoid 层
- binary _ cross _ entropy _ with _ logits—这要求将原始输出或 logits 传递给 loss。损耗实现在内部应用一个 sigmoid
- cross_entropy —它期望 logits 作为输入,并在计算熵损失之前应用 softmax(技术上是 log softmax)
- nll_loss —这是简单的负对数似然损失。这要求在计算损失之前,logits 通过 softmax 层
- KL _ div-这期望在计算损失之前,逻辑通过 softmax 层

Tensorflow 2.0 / Keras
默认情况下,所有 Tensorflow 2.0 亏损都将概率作为输入,即 logits 在输入亏损之前要通过 Sigmoid 或 Softmax。但是它们提供了一个参数 from_logits ,该参数被设置为 True 将接受 logits 并转换为内部概率。
- 二元交叉熵 —计算 a y_true 和 y_pred 的 BCE 损失。 y_true 和 y_pred 是一维张量——每个样本一个值。
- CategoricalCrossentropy—计算 a y_true 和 y_pred 的交叉熵。 y_true 是标签的一个热点表示,而 y_pred 是一个多维张量——每个样本的类值数量
- SparseCategoricalCrossentropy—计算 a y_true 和 y_pred 的交叉熵。 y_true 是一维张量——每个样本的单个值——而 y_pred 是多维张量——每个样本的类值数量
- KLDivergence —计算从 y_pred 到 y_true 的 KL 散度。这是一个例外,因为它总是期望概率作为输入。
我们已经到了博客的结尾,我希望现在你对神奇的损失函数有了更好的理解和直觉,它使深度学习成为可能。
参考
- 香农,C.E. (1948),“通信的数学理论”,贝尔系统技术杂志,27,第 379–423 页&第 623–656 页,1948 年 7 月&10 月。
- 克里斯·奥拉赫,视觉信息,colah.github.io
- 迪比亚·戈什哈, KL 机器学习发散,【http://www.dibyaghosh.com】T2
原载于 2020 年 1 月 9 日 http://deep-and-shallow.com。
用 Python 分析膝关节磁共振成像🚑
学习使用 python 分析 MRI 扫描来检测严重的膝盖损伤
我总是对改变人们生活的有影响力的人工智能应用感到惊讶,我认为如今这种转变正在发生的领域之一是医疗保健。

人工智能和医疗保健是我直到最*才考虑的一个关联。所以我给自己设定了一个个人挑战:了解一个医疗应用程序,实现它,并分享它。
在我快乐地追求数据的过程中,我偶然发现了 MRNet :由斯坦福 ML 小组收集的用于研究膝盖损伤的膝盖 MRI 数据集。该数据集可通过书面请求获得,并附有该团队发表的一篇研究论文。简而言之,这项工作提出了一个神经网络结构,检测 3 种类型的膝关节损伤具有非常好的性能。
今天你将学到什么👨💻
- 关于膝关节功能障碍,你可能和我一样不熟悉。所以我会尽我所能来解释我们将要面对的膝盖损伤的类型
- 我将简要介绍磁共振成像,并解释它产生的数据类型:我们将看到深度学习有很大的潜力来处理它,用于医疗诊断自动化
- 我们将探索斯坦福大学提供的 MRNet 数据集
- 我将向您展示如何在没有 javascript 代码的情况下高效地构建交互式数据探索小部件。只有 Python 代码。
剧透警告 ⚠️ 这是它的样子

开始吧!😁
前十字韧带撕裂
在这个项目中,我们将特别关注前交叉韧带(ACL)撕裂,这是足球或篮球顶级运动员最常见的膝盖损伤。
当前交叉韧带被拉伸、部分撕裂或完全撕裂时,就会发生 ACL 撕裂。最常见的损伤是完全撕裂。
症状包括疼痛,受伤时发出爆裂声,膝盖不稳定和关节肿胀。
美国每年大约有 200,000 例前交叉韧带撕裂,每年有超过 100,000 例前交叉韧带重建手术。

为了诊断膝关节损伤,我们通常使用磁共振成像。
磁共振成像
磁共振成像(MRI)是一种用于放射学的医学成像技术,用于形成身体解剖和生理过程的图像。
核磁共振用于诊断您对治疗的反应,以及检测撕裂和结构问题,如心脏病发作、脑损伤、血管损伤等。
这是头部核磁共振成像的动画:

来源:维基百科
核磁共振扫描不是一个器官的单一图像。它是一组堆叠在一起的不同图像或切片(这就是为什么你会看到一个动画穿过 MRI 的每个切片)。
你可以把核磁共振成像想象成根据给定的*面,在不同的深度水*上检查器官的过程。
前交叉韧带撕裂诊断和自动化的高潜力
如上所述,膝关节 MRI 是诊断膝关节损伤的首选方法。然而,膝关节核磁共振成像的解释非常耗时,并且容易出现诊断错误和可变性。用于解释这种类型的图像数据的自动化系统可以优先考虑高风险患者,并帮助临床医生进行诊断。
此外,对放射科医师产生较少假阳性的系统是非常有利的,因为它消除了进行不必要的侵入性膝关节手术的风险。
在接下来的帖子中,我们将看到如何使用深度学习在 MRI 扫描上建立 ACL 撕裂分类器。但是我们先来看看这个帖子里的数据,了解一下。

MRNet 数据集
MRNet 是由吴恩达的斯坦福实验室提供的膝盖 MRI 数据集。
它分为训练集(1130 个案例)、验证集(120 个案例)和测试集(120 个案例),组织如下:

请注意,我们没有访问测试集的权限。
请注意,该病例也指患者。所以我们将互换使用这两个术语。
我们要用什么文件?
train-acl.csv 和 valid-acl.csv (我们暂时忽略其他文件)分别表示训练和验证数据上每个案例(正常或遭受 acl 撕裂)的标签。
在训练和有效文件夹中,每个病例都有 3 个从不同*面拍摄的 MRI 扫描:矢状面、冠状面和轴面。
为了对病例做出正确的决定,放射科医师通常从不同的*面查看 MRI 扫描,以获得全局视图。

给定患者的 3 次 MRI 扫描不一定具有相同数量的切片。
对于不同的病例(或患者)和给定的*面,MRI 扫描也不一定有相同数量的切片。这是一条需要记住的重要信息,因为它决定了我们稍后将用于分类的深度学习模型的架构。
用一些代码探索 MRNet 数据集💻
现在让我们来看看这些数据,并对其进行探究。
CSV 文件 train-acl.csv 和 valid-acl.csv 具有相同的两列结构:
- 案例:案例的 id
- 异常:二进制值(1/0)表示 ACL 断裂
print(train_acl.shape)
# (1130, 2)
前交叉韧带撕裂出现在不到 20%的训练集中。
train_acl.Abnormal.value_counts(normalize=True)# 0 0.815929
# 1 0.184071
# Name: Abnormal, dtype: float64
让我们从三个*面的角度来看一个给定的例子:
每一次核磁共振扫描都是 s 层的张量。每个切片都是大小为(256,256)的灰度图像。
让我们想象每个*面上的第一个:

绘制 MRI 扫描的切片并在三个不同的*面之间有一个全局视图不是很方便,特别是当每次 MRI 扫描有大量切片并需要检查每个切片时。
因此,下面是我们如何将一个静态的 matplolib 图转换成一个交互式小部件,它允许你:
- 选择一个案例
- 在每个*面的切片上滑动
- 看到图动态变化
让我们来看看如何做到这一点:
您首先需要将数据加载到一个方便的字典中,其中键是病例号,值是字典,键是*面,对应的值是表示 MRI 扫描的 NumPy 数组。
装完 100 箱后,让我们看看 0000 箱
print(cases['0000'].keys())
#dict_keys(['coronal', 'sagittal', 'axial'])
正如所料,它包含一个嵌套字典,将 plane 映射到 NumPy 数组对象。
让我们看看这个:
print(cases['0000']['axial'].shape)
print(cases['0000']['coronal'].shape)
print(cases['0000']['sagittal'].shape)# (44, 256, 256)
# (36, 256, 256)
# (36, 256, 256)
现在我们定义一个名为 KneePlot 的类,它从 cases 对象创建交互式绘图。
该类别定义了:
- 抽象方法 plot_slices 绘制给定案例的三个切片。每次在小部件上进行交互时,都会自动调用这个方法
- 一个 draw 方法,负责定义 dropdown 和 slider 小部件,这些小部件获取用户输入数据并将它们交互地传递给 plot_slices 。

关于数据的一些考虑🤔
- 从一个*面到另一个*面,切片是显著不同的:作为一个非专业人士,这是我注意到的第一件事
- 在给定的*面内,切片也可以显著不同。事实上,我们稍后会看到,一些切片可以更好地突出前交叉韧带撕裂
- 在下一篇文章中,我们将为每个*面建立一个 MRI 撕裂分类。接下来我们会看到,这三个模型的组合优于单个模型
- 根据给定*面进行的 MRI 扫描可以被认为是堆叠切片的体积。正如我们之前所说的,病例不一定共享相同的切片,磁共振成像不能批量放置。我们将看到如何有效地处理这个问题。
然后🔜:建立 ACL 撕裂分类模型
在下一篇文章中,我们将构建一个卷积神经网络,它将接收 MRI 扫描并预测 ACL 撕裂的概率。
了解如何使用 PyTorch 训练高精度的 MRI 扫描膝关节损伤分类器
towardsdatascience.com](/deep-learning-and-medical-imaging-how-to-provide-an-automatic-diagnosis-f0138ea824d)
我们将讨论这个网络的架构以及处理数据处理、数据扩充和迁移学习的不同组件。
我们将看到如何使用 PyTorch 将所有内容组合在一起。移至下一篇文章了解更多详情。
原载 此处 。
深度学习和社会科学的终结
意见
当计算机比自己更了解人的时候会发生什么?

数据真的更懂吗?弗兰基·查马基在 Unsplash 上拍摄的照片
科学是一种算法。迄今为止,它很可能是人类有史以来发明的最有效和最有用的算法——或算法家族。不断改进的建立世界运行模型的方法,然后对照证据测试这些模型,使得区分好主意和坏主意成为可能。人类对宇宙、世界和自身的理解一步步加深。
这种理解可能面临自加里利奥领导宗教裁判所以来最大的威胁。人工智能革命很可能颠覆好想法从坏想法中筛选出来的方式,并颠覆科学理解的最终目标。
声称人工智能可能破坏科学理解,甚至使其过时,这并不新鲜。与科学算法不同,深度学习算法一点也不关心理解。他们优化更接*和*庸的数量。十多年前,克里斯·安德森 认为数据洪流让科学方法过时了他预言了科学理论的终结。
海量数据的新可用性,以及处理这些数据的统计工具,提供了一种全新的理解世界的方式。相关性取代了因果关系,即使没有连贯的模型、统一的理论或任何真正的机械论解释,科学也能进步。
2017 年,大卫·温伯格 再次挑起事端 当他断言“我们的机器现在拥有我们永远不会理解的知识。”理论死亡的说法是否被夸大了,这仍然是一个激烈的,有时令人振奋的争论话题。彼得·斯威尼认为,深度学习产生的新的、令人费解的见解可能会为更深层次的解释提供一次复兴,他总结道:
应该庆祝深度学习,不是因为它揭示了知识的极限,而是因为它是一种强大的观察工具。
对人类的适当研究
大多数关于深度学习取代科学方法的讨论都围绕自然科学和医学展开。从天文学和粒子物理学到基因组学、生物信息学和疾病建模,不需要巨大的想象力就可以看出深度学习算法可能会挖掘大量可用数据。然而,这一采矿努力是展示了新的理解宝石,还是仅仅是一个有利可图的预测富矿,这很重要。然而,当这些主张被置于社会科学的土壤中时,问题就大得多了。
从民间传说、一厢情愿的想法和信仰的浑浊泥浆中提炼出关于人类行为和社会的知识,比理解物理世界更加困难。几千年来,对人类行为和社会的循证理解的进步受到了利己主义、道德直觉、宗教教义、政治教条和我们特殊教育的污染。进步也受到一种常见观点的影响,即科学在人类对自身的理解中没有一席之地。甚至声称使用科学方法的学术学科也倾向于聚集成部落,每个部落都被驱使去证明他们想法的正确性。
深度学习有望结束这些争论。这并不是说它将澄清黑暗,并最终向我们反映我们是谁,我们如何成为我们自己。相反,深度学习算法将从堆积如山的用户数据、点击、喜欢、关注、推文、消息、购买和运动中提取他们需要的一切,以便销售产品、赢得选票和形成观点。人工智能可能会取代人类的理解和所有许多相互竞争、不兼容和相互蔑视的“理论”形式。是的,甚至批判理论。
遗传与环境
最终,所有关于人性的冲突理论都始于先天和后天之间的分水岭。最终,它们都像迁徙的鲑鱼一样,回到这些出生的溪流中,再次延续错误的二分法,这种二分法在人们认真思考它们是如何成为现在的样子的时候就已经模糊了人类的理解。柏拉图和亚里士多德争论思想是天生的还是通过经验产生的,同样的问题比其他任何问题更困扰着哲学家。
在 20 世纪,事情变得特别敌对。先驱文化人类学家阿尔弗雷德·l·葛艺豪 在 1915 年断言“不能允许遗传在历史上扮演任何角色。”生物学/心理学的解释永远无法与社会/历史研究相一致。几代人类学家都相信克罗伯的话,公*地说,他们是有理由的。优生学和社会达尔文主义者已经展示了从他们对自然如何运作的狭隘和一厢情愿的观点中推断应该是什么的灾难。纳粹很快就证明了关于人类天生差异和种族优越性的想法是如何被滥用的。
今天,“进化心理学”这个术语可能会在其他有分寸的研究人员中引发唾沫和愤怒,他们相信任何对人类行为的生物学解释都不可避免地会形成下一个法西斯楔子的薄弱末端。反过来,这种接受在许多进化心理学家中引发了偏执,他们中的许多人确信,霸权的标准社会科学模型强加了天真但政治上可接受的想法,即人类从空白的石板开始生活,仅由社会构建或文化因素塑造。
类似的战斗在人类学内部激烈展开,在这种情况下,生物和文化人类学家的所谓“理论”对于另一个部落来说常常是相互难以理解的。对于任何想了解不*等、暴力和剥削从何而来的人来说,理解自然、养育以及它们相互作用的复杂方式是非常重要的。如果他们想做点什么就更是如此。社会学、心理学和经济学都在支持一个原因而贬低或忽视另一个原因的理论的重压下摇摇欲坠。
除非所有的社会科学超越它们巴别塔般的部落主义和自我隔离,否则它们将被人工智能变得无关紧要。对人类如何互动、消费和支出感兴趣的人和公司对行为在多大程度上是通过遗传或经验产生的兴趣不大。算法对解释毫无用处,更不用说许多研究人员希望称之为“理论”的华丽但琐碎的部分解释了。
结束了
儿童学习阅读的例子突出了一些问题。阅读需要重新规划进化来完成其他功能的神经通路。学习阅读的许多困难都有其生物学因素。尽管成为一名读者需要先天(神经系统)和后天(学习)的双重培养,但关于哪个最重要的古老幼稚的争论仍在继续。
最不体面的斗争——简称为“阅读战”——与先天-后天的断层线相切。它涉及两种不同的培养模式:系统语音法,教授字母和声音之间的联系,以及整体语言法,学生从图片、上下文和其他线索中推断或猜测他们不认识的书面形式的单词。尽管一些研究人员建议混合这些方法或寻找更好的方法,但许多人更喜欢坚持激烈的争吵,这肯定会让一年级学生被送到淘气的角落。或者现在“最佳实践”所说的任何事情。
研究如何最好地教孩子阅读确实很难。首先,你必须设计一项研究,为一些孩子提供语音教学,为另一些孩子提供全语言教学,以一种对两种方法都公*的方式。然后你需要招募很多孩子,并征得他们的监护人和老师的同意。然后,艰苦的工作开始了,看着孩子们学习,衡量相关的结果,最好是持续几年。即使你能做所有这些事情,如果开始看起来一种方法比另一种更有效,那么坚持下去是道德的吗?你能阻止父母和亲戚在家里使用另一种方法吗?
正确地、合乎道德地完成所有这些步骤需要数百万美元。那只是在一种文化和经济背景下的一种语言。除此之外,在科学家们看到他们的第一笔研究资助之前,他们还浪费了几个小时去申请和错过资助。
人工智能提供了一个诱人的选择。至少在理论上,人们可以构建软件,通过任何选择的方法教孩子阅读,测量他们的进步,并评估每种方法的成功。但是为什么就此打住呢?只需再多做一点工作,人们就可以开发出一款软件,在帮助孩子们学习阅读的同时,也能向他们学习。它可以产生新的策略,结合语音、整体语言和任何其他教学方法的优点。
这种尚待开发的软件可能会解决教条式的“自然发音法”和“整体语言”之争,并决定性地站在一边。然而,更有可能的是,它将集中在教孩子阅读的新策略上,而这些策略与这两种对立的理论都不一致。事实上,这一战略可能完全无法描述。孩子们可能会以他们更喜欢、更快、比以往任何一代学习者更少挫折的方式学习如何阅读,但没有人能够理解如何阅读。
如果大卫·温伯格写下的话是正确的,这就是我们可能期待的结果:
我们越来越依赖于从他们自己创建的模型中得出结论的机器,这些模型通常超出人类的理解,这些模型以不同于我们的方式“思考”世界。
…了解这个世界可能需要放弃对它的理解。
教育者或家长会接受这样的未来吗?即使孩子们变得比任何上一代人都更好,更热情的读者?首先,如果深度学习学会了如何最好地教孩子阅读,它就不会是某种改善人类知识储备的良性公益计划的产物。与*几十年来研究和教育资金的流向不同。相反,私营公司将开发软件,积累数据,并从它们的算法学习到的任何东西中受益。
富裕的父母将能够负担得起新技术能为他们的阅读年龄的孩子提供的最好的东西。其他家长不会。如果你认为关于如何教授阅读的意识形态之争是邪恶的,你可以通过研究席卷私立学校和公立学校的风暴来预测未来。
和你的部落离婚
可以让所有围绕人类行为和社会的困难的、充满意识形态色彩的问题变得过时的数据已经存在了。越积越多。然而,它们不一定能增进我们对彼此的了解,以及我们的行为方式。我认为,社会科学和人类自我认识的风险太高,无法跌入深度学习的不可知深渊。
如果社会科学要保持相关性,它就必须对“科学”部分有一个更新的、高度集中的关注。任何有兴趣了解人类在所有这些文化、社会化、遗传学、表观遗传学、特权、财富和权力之下到底是什么样的人,都需要脱离自己的部落,寻求整个科学界的公民身份。只有到那时,他们才有希望建立在那些有证据支持的少数观点之上,并拒绝那些没有证据的观点。
我们需要改进社会科学算法。要做到这一点,我们需要最终摆脱一厢情愿的彩色梦想外衣,找到无私的方式来筛选证据,并从大量可用的大数据中学习。一门新的社会科学可以像企业一样获得大量数据,并包含深度学习,有机会改善我们对自己和所有人类生活的了解。
如果社会科学家不能做这些困难的事情,那么机器和拥有它们的公司将会学习他们喜欢的关于我们的任何东西,知道我们但是仍然不理解一件事情。他们会大赚一笔。
孕育出亲密艺术形式的快感可以让技术深入我们的皮肤
towardsdatascience.com](/will-asmr-survive-machine-learning-490119a1c4d3)
加入我的邮件列表 进行每月更新。
用于动作识别的深度学习架构
2014 年至 2019 年的最新进展回顾
摘要
深度学习方法已经在经验上证明了在为诸如对象识别、图像字幕和语义分割等任务学习图像表示方面的显著成功。卷积神经网络通过参数共享卷积和局部不变性构建最大池神经元,使我们能够有效地捕捉图像中数据结构的空间局部性假设。在这篇文献综述中,我想探讨深度学习技术对视频任务的影响,特别是动作识别。
我想探索时空特征如何通过各种深层架构聚合,光流作为输入的作用,对实时能力的影响,以及所学特征的紧凑性和可解释性。
然后,我将提出未来研究的领域,我认为这些领域可以帮助我们以更好地捕捉现实世界的时间假设的方式偏向深度学习架构;自然流形。
在深度学习革命之前
在 2014 年之前,最先进的技术侧重于从稀疏或密集采样轨迹形成的手工特征。例如,一种流行的方法称为改进的密集轨迹(iDT) [1],提取一组密集的兴趣点的轨迹和特征,将它们编码在固定大小的视频描述中,然后像 SVM 这样的分类器在最终的“单词包”表示上进行训练。在这种方法中,需要对每一帧进行大量的预处理。必须在帧之间计算光流,还计算光流的梯度,并且为两者产生减去*均值的直方图。这些都被认为是编码到固定大小视频描述中的输入特征。在视频表示的深度学习方法中,我们将观察预处理如何对端到端可训练性和实时能力产生影响。
后深度学习
2014
2014 年后,深度学习架构在 UCF101、Sports-1M 和 HMDB51 等里程碑式的视频动作识别数据集上获得了最先进的性能。2014 年,两篇重要的突破性论文让深度学习在视频识别方面有了起步。Karpathy 等人利用卷积神经网络进行大规模视频分类。艾尔。Simonyan 和 Zisserman [3]的视频中用于动作识别的【2】和双流卷积网络导致了单流和双流网络T5 在动作识别中的流行。
卡帕西等人。艾尔。探索了如何融合时态数据与单流 2D 卷积神经网络。他们测试了图 1 中提出的架构。

图 1 —单流网络架构。红色、绿色和蓝色方框分别表示卷积层、归一化层和汇集层。在慢速融合模型中,所描绘的列共享参数。[2]
单帧网络本质上是一个没有时间特征的图像分类网络。后期融合使用两个相距很远的帧,并通过展*从这两个帧处理的特征,在紧密连接的层融合深层等级特征。早期的融合将帧堆叠为通道,并通过对整个帧堆叠进行 2D 卷积来学习视频描述符。慢速融合试图从一堆帧中以分层的方式连接特征,因此随着网络变得更深,更多的时间特征被学习。他们的结果总结在表 1 中。

表 1—Sports-1M 测试集的 200,000 个视频的结果。Hit@k 值表示在前 k 个预测中包含至少一个基本事实标签的测试样本的比例。[2]
单流策略的优势在于,我们可以从在大规模图像数据集上训练的模型中使用迁移学习。我们也不需要为光流预处理图像,因为我们在该架构中直接使用 RGB 图像数据。这使得单流网络成为实时处理的候选。在作者提出的融合架构中,参数的数量从深 2D CNN 显著增加。为了减轻这一点,作者建议使用多分辨率流。一种是将高分辨率视网膜中央凹流嵌入到视频的中央裁剪区域,并结合整个视频的低分辨率上下文流,如图 2 所示。

图 2 —多分辨率流有两个流,由交替的卷积(红色)、归一化(绿色)和汇集(蓝色)层组成。两条溪流汇聚成两个完全连接的图层(黄色)。[2]
根据经验,这大大减少了参数数量,与单帧架构相当。
从表 1 公布的结果中,我们看到,仅使用单个帧,所提出的架构未能有效提升性能。这些模型的弱点是它们不能很好地捕捉运动特征。然而,这篇论文确实揭示了迁移学习对于动作识别非常有用。与在 UCF101 [2]上从头开始训练的模型相比,在 Sports-1M 上预先训练然后在顶部 3 层进行微调的模型在 UCF101 数据集上的准确性提高了 20%以上。
在 2014 年,Simonyan 和 Zisserman 提出了一个两个流架构,分别处理空间特征和时间特征[3],如图 3 所示。

图 3 -双流网络[3]
视频的单个帧被传递到 2D 卷积网络,而预处理的多帧光流被传递到单独的 2D 卷积网络。每个流形成一个预测,类分数由它们的融合决定。这种架构的缺点是它不是端到端可训练的,因为光流需要单独计算,并且两个流都需要单独训练。空间流可以从大型图像数据集学习,而时间流必须在视频数据集上训练。这样,迁移学习就不完全适用于这种架构。此外,计算光流所需的预处理使得该算法难以具有实时能力。如下表 2 所示,这种方法的优势在于其能够与 IDT 等当时最先进的技术相匹配。

表 2—3 次分割的*均 ConvNet 精度[3]
这为视频分类的深度学习的进一步研究打开了大门。这项研究表明,卷积深度网络可以有效地捕捉一些运动特征,并将其与空间特征相结合,以形成对动作类别的准确预测。
在 2014 年至 2019 年之后的未来 5 年中开发的深度学习架构在很大程度上遵循了围绕下图 4 所示架构的变化。

图 4 —动作识别的各种架构。k 代表视频中的总帧数,N 代表视频中相邻帧的子集。[4]
前两种方法 a)和 b)分别使用 LSTM 和 3D ConvNet,具有端到端可训练和实时能力的优点。这是因为它们不依赖于光流,而是必须学习编码这些信息的特征。这允许网络在端到端训练中直接学习时空特征。方法 c)-e)不是实时的,也不是端到端可训练的,因为它们需要对原始数据进行光流计算。方法 b)、d)和 e)使用 3D 卷积。这从传统的 2D conv net 中创建了大量的参数。对于为 UCF101 数据集训练的单个 3D 卷积神经网络,可以有 33M +参数,相比之下,在 2D 的情况下只有 5M+参数[4]。这极大地影响了训练成本,因为在 Sports-1M 上训练 3D ConvNet 模型需要大约 2 个月的时间。这使得难以为视频数据搜索正确的架构。大量的参数也产生了过度拟合的风险。
Donahue 等人在 2014 年的论文用于视觉识别和描述的长期递归卷积网络中普及了视频的 LSTM 架构。铝[5]。这座建筑被称为 LRCN。它是编码器-解码器架构的直接扩展,但用于视频表示。LRCN 网络的优势在于它可以处理各种长度的序列。它还可以适用于其他视频任务,如图像字幕和视频描述。缺点是 LRCN 无法超越当时的技术水*,但它确实比单帧架构有所改进,如表 3 所示。

表 3 —活动识别:在 UCF101 [25]数据集上,使用 RGB 和 flow 输入,将单帧模型与 LRCN 网络进行活动识别比较。[5]
对于隐藏的递归图层来说,空间要素的时间建模很难掌握。根据经验,向 RGB 模型中添加更多的隐藏单元并不会改善过去的 256 个隐藏单元。然而,在使用流输入的同时添加更多的隐藏单元产生了 1.7%的精度提升,从 256 个单元增加到 1024 个单元。这表明 LRCN 在学习光流或运动的类似表达方面有一段艰难的时间。

表 4—ucf 101 上的动作识别结果。2015 年,C3D 与基线和最先进的方法进行了比较。[6]
2015
在 Du Tran 等人的 2015 年研究论文用 3D 卷积网络学习时空特征中,3D 卷积网络被确立为新的最先进技术。铝[6]。在这篇论文中,他们确定了具有 3x3x3 核的 3D 卷积网络(C3D)在学习时空特征方面是最有效的。有趣的是,解卷积揭示了网络正在学习片段的前几帧的空间外观,随后是后面几帧的显著运动。这种架构非常强大,因为许多视频可以实时处理,因为 C3D 的处理速度高达 313fps。由该网络生成的视频描述符也是紧凑的和有区别的,因为我们可以通过 PCA 将卷积生成的特征投影到 10 维,并且仍然在 UCF101 数据集上实现 52.8%的准确性。

图 5——两层融合架构(conv5 之后和 fc8 之后),其中保留了两个网络塔,一个作为混合时空网络,一个作为纯空间网络。[7]
2016
2016 年,重心转回二流网。在 Zisserman 等人的用于视频动作识别的卷积双流网络融合中。艾尔。[7],作者解决了如何有效地融合跨流的空间和时间数据,并创建可以处理长期时间依赖性的多级丢失。这里的激励思想是,为了区分图像不同部分的类似运动,如刷牙和刷牙,网络需要在一个像素位置结合空间特征和运动特征。理论上,在密集连接的层之前融合流的方法可以实现这一点。在提出的架构中,作者在两个位置融合了两个流,如图 5 所示。该网络能够更好地捕捉不同子网中的运动和空间特征,并击败了最先进的 IDT 和 C3D 方法。多级损失由最后融合层的时空损失和由时间网络的输出形成的单独时间损失形成。这使得研究人员能够创建时空特征,并对长期时间依赖性进行建模。这种方法仍然存在原始双流网络的缺点,但由于增强的架构更好地服务于我们的现实世界偏差,因此性能更好。
2017
2017 年,朱等人。艾尔。通过引入一个学习光流的隐藏流(称为 MotionNet [8]),two stream 网络向前迈进了一步。这种端到端的方法允许研究人员跳过明确计算光流。这意味着两个流方法现在可以是实时的,并且来自错误预测的误差也可以传播到 MotionNet 中,以获得更优化的光流特征。

图 6 — MotionNet 将连续的视频帧作为输入,并估计运动。然后时间流 CNN 学习把运动信息投射到动作标签上。[8]
研究人员发现,隐藏的双流 CNN 的性能与非隐藏方法类似,但现在每秒可以处理 10 倍以上的帧,如表 6 所示。这实现了双流方法的实时能力。

表 6-双流法及其在 UCF101 上的精度。[8]
MotionNet 子网是可扩展的,可以应用于其他需要计算光流的深度学习方法。这很重要,因为它允许我们实时地做其他的方法。
2017 年, Quo Vadis,动作识别?Zisserman 等人的新模型和动力学数据集。艾尔。通过将它与来自两个信息流网络的知识相结合,使 C3D 向前迈进了一步[4]。研究人员提出了一种新颖的双流膨胀 3D ConvNet (I3D)。2D ConvNets 的过滤器和池内核扩展到 3D,赋予它们额外的时间维度。这使得研究人员能够将 2D 分类的成功架构应用于 3D。研究人员还利用在 ImageNet 等海量图像数据集上训练的 2D ConvNet 模型的参数来引导这些 3D 过滤器。

表 7——在 UCF-101 和 HMDB-51 测试集(两个测试集的第一部分)上,以 ImageNet 预训练重量为起点和不含 ImageNet 预训练重量的架构的性能。原文:UCF-101 或 HMDB-51 上的火车;修正:来自动力学的特征,最后一层在 UCF-101 或 HMDB-51 上训练;全英尺:动力学预训练与端到端微调 UCF-101 或 HMDB-51。[4]
在双流架构中对顺序 RGB 帧和顺序光流帧使用 3D ConvNets 使研究人员能够在 UCF101 上击败最先进的技术。研究人员利用动力学数据集确立了迁移学习的明显重要性。不幸的是,他们使用的模型体系结构不是端到端可训练的,并且没有实时能力。
2018
在 2017 年至 2018 年,深度残差学习的许多进展导致了像 3DResNet 和伪残差 C3D (P3D)这样的新颖架构[9]。不幸的是,我不会在这篇文献综述中涵盖这些论文,但我确实恭敬地承认它们对现有技术的影响。
2019
最*一次是在 2019 年 6 月,杜川等人。艾尔。提出信道分离卷积网络(CSN)用于在视频分类中使用信道分离卷积网络进行动作识别【10】。研究人员基于在 Xception 和 MobileNet 模型中获得巨大成功的组卷积和深度卷积的思想。

图 7 — (a)传统卷积,只有一个组。(b)具有两个群的群卷积。c)深度方向卷积,其中组的数量与输入/输出滤波器的数量相匹配。
基本上,群卷积通过不完全连接引入了正则化和更少的计算。深度卷积是组卷积的极端情况,其中输入和输出通道等于组的数量,如图 7 所示。传统的卷积网络在其 3D 卷积中联合模拟信道相互作用和局部相互作用(空间或时空)。

图 8 — (a)标准 ResNet 瓶颈模块。(b)交互保留的瓶颈块。
研究人员提议将 3x3x3 卷积核分解为两个不同的层,其中第一层是用于局部通道交互的 1x1x1 卷积,第二层是用于局部时空交互的 3x3x3 深度卷积。通过使用这些模块,研究人员显著减少了网络中的参数数量,并引入了一种强有力的正则化形式。信道分离的块允许网络在不同的层中本地学习空间和时空特征。

表 8 —与 Sports-1M 上最先进架构的比较
如表 8 所示,CSN 改进了 Sports-1M 数据集上的最新 RGB 方法,如 R(2+1)D、C3D 和 P3D。在推理过程中,网络速度也提高了 2-4 倍。该模型也是从头开始训练的,其中表中的其余模型是在 ImageNet 或 Kinetics 数据集上预先训练的。这种新的架构改进了以前的因子分解网络,同时减少了过拟合,速度非常快,并在基准数据集上产生了最先进的精度。
结论
技术发展水*
动作识别的当前技术状态(2019 年 8 月)是通道分离网络。这个网络有效地在它们自己不同的层中捕获空间和时空特征。通道分离卷积块清楚地学习这些特征,但是在卷积的所有阶段局部地组合它们。这减轻了执行时间和空间两个流网络的缓慢融合的需要。网络也不需要像在 C3D 中那样在学习空间或时间特征之间做出决定,在那里网络可以决定学习两个维度之间混合的特征。该网络有效地捕获了 2D 空间切片应该形成自然图像的偏差,而时间方向上的 2D 切片具有不同的时间属性,并且不属于自然流形。这样,研究人员通过创建两个独立的不同层来处理每个方向来加强这种偏见。通道分离是动作识别中向前迈出的重要一步,即使从零开始训练,也已经取得了领先的结果。它还能够进行实时推理。由于这些原因,我相信 CSN 的是目前的艺术状态
摘要
我们已经了解到,深度学习已经彻底改变了我们处理动作识别视频的方式。深度学习文献已经从使用改进的密集轨迹走了很长的路。从图像分类的姐妹问题中获得的许多知识已经被用于推进用于动作识别的深度网络。具体而言,卷积图层、池化图层、批量归一化和残差连接的使用已从 2D 空间中借鉴过来,并成功应用于 3D 中。许多使用空间流的模型都是在大量影像数据集上进行预训练的。光流在早期深度视频架构(如双流网络和融合网络)中也在表示时间特征方面发挥了重要作用。光流是我们的数学定义,我们认为后续帧中的运动可以描述为所有像素的密集计算的流向量。最初,网络通过使用光流来提高性能。然而,这使得网络无法进行端到端训练,并限制了实时能力。在现代深度学习中,我们已经超越了光流,相反,我们构建了能够天生学习时间嵌入并且端到端可训练的网络。
我们还了解到,动作识别是一个真正独特的问题,有其自身的复杂性。摩擦的第一个来源是与 3D 卷积相关的高计算和存储成本。一些模型需要 2 个多月的时间来进行体育训练-在现代 GPU 上需要 100 万。摩擦的第二个来源是视频架构搜索没有标准的基准[11]。Sports-1M 和 UCF101 高度相关,当选择视频的一部分进行训练,但实际上可能不包含实际动作(因为它可能在视频的另一部分中)时,错误标签分配是常见的。摩擦的最后一个来源是,设计一个视频深度神经网络并非易事。层的选择、如何预处理输入以及如何对时间维度建模是一个未解决的问题。上述论文的作者试图以经验方式解决这些问题,并提出了解决视频中时间建模的新架构。
未来的研究
对于未来的研究,我建议研究如何在深度视频网络架构中包含更多我们对现实世界的偏见。一个有趣的垂直研究是深度建模如何与更好的视频分类相关联。当前的视频分类方法必须知道视频是在 3D 环境中拍摄的。深度是我们空间感知的重要组成部分。当前的方法可能需要学习如何在 2D 特征的时空模型中表达深度。也许使用单目深度估计网络可以帮助当前的视频网络更好地理解环境本身。一个重要的观察结果是,视频中的任何空间变化都来自两个来源:我们正在观察的外部对象的转换,或者观察者本身改变视角或位置。这两种运动源都必须被当前的网络所学习。研究如何使用深度场来模拟变化的来源将会很有趣。
引文
[1]王恒,亚历山大·克勒泽,科迪莉亚·施密德,.基于密集轨迹的动作识别。CVPR 2011 — IEEE 计算机视觉会议
[2] Karpathy,Andrej 等,“用卷积神经网络进行大规模视频分类”IEEE 计算机视觉和模式识别会议录。2014.
[3]西蒙扬、卡伦和安德鲁·齐泽曼。"用于视频中动作识别的双流卷积网络."神经信息处理系统进展。2014.
[4]卡雷拉、若昂和安德鲁·齐塞曼。“Quo vadis,动作识别?一个新的模型和动力学数据集。”IEEE 计算机视觉和模式识别会议录。2017.
[5] Donahue,Jeffrey 等,“用于视觉识别和描述的长期递归卷积网络”IEEE 计算机视觉和模式识别会议录。2015.
[6] Tran,Du 等,“用三维卷积网络学习时空特征”IEEE 计算机视觉国际会议论文集。2015.
[7] Feichtenhofer、Christoph、Axel Pinz 和 Andrew Zisserman。“视频动作识别的卷积双流网络融合。”IEEE 计算机视觉和模式识别会议录。2016.
[8]朱,易等.用于动作识别的隐双流卷积网络."计算机科学课堂讲稿(2019):363–378。交叉引用。网络。
[9]邱、、、。“用伪 3d 残差网络学习时空表示。”IEEE 计算机视觉国际会议论文集。2017.
[10] Tran,Du,等,“用信道分离卷积网络进行视频分类”arXiv 预印本 arXiv:1904.02811 (2019)。
[11] Tran,Du,等,“用于时空特征学习的 Convnet 架构搜索”arXiv 预印本 arXiv:1708.05038 (2017)。
深度学习:自动更正,短词拼写检查
使用最先进的神经网络纠正专有名词等生僻字的拼写。本文讨论网络的抽象概念、实现和结果。

由比斯瓦帕蒂·阿查里亚在 Unsplash 上拍摄
这是一张纽约市天际线的美丽图片,为什么我会把它放在一篇神经网络文章上?也许我现在更欣赏外在的美了,因为我从 2 月 15 日开始隔离自己(76 天,还在继续)。是的,已经两个多月了!!!在周五午夜 2:45 打出一篇文章会出什么问题。我们会找到答案的。
我已经在 Reorg 工作了一年多,这太不可思议了。Reorg 是在金融部门,提供破产相关的新闻和不良债务公司的分析。没错,当有人濒临破产时,我们会赚钱,这听起来很邪恶,但相信我,不是的。Reorg 有一个网站,用户可以通过这个网站获得对不良债务公司的最新分析。为了找到他们感兴趣的公司,我们为他们提供了一个搜索栏,搜索一个拥有超过一百万家公司的数据库。那么什么会出错呢?有一个问题,都是专有名词(公司名称),所以你必须在搜索栏中正确获取确切的名称。
不幸的是,我们人类生来就会犯错。解决方案?机器人来救援了。* 用机器人语言尖叫 *
视觉:
我在这里的愿景是实现类似于谷歌提供的东西,即在 下显示 或的结果,你的意思是。
我们为什么要这么做?让用户参与我们的网站。想象一下,如果每次你输入一个错误,谷歌从来没有显示任何结果,直到你真正输入正确的拼写。这个世界会有多糟糕?
以下是“深度学习”的搜索结果,其中有故意出现的错误。


资料来源:google.com
人们会注意到这两个结果有所不同。当它显示'显示'的结果时,Google 对您正在寻找的内容非常有信心,因此会向您显示预测关键字的搜索结果。另一方面,当它显示“你是指吗”的结果时,它的信心下降,并要求你(用户)帮助验证你实际上在找什么。尽管如此,他们仍然显示他们认为与搜索框中输入的词密切相关的网站链接。
如果您只对模型结果感兴趣,请一直向下滚动到 AI in action。

由 Samrat Khadka 在 Unsplash 上拍摄的照片
我的天啊,我是如此想念你!:(好了,我说够了莎士比亚。回到最酷的话题!
网络:
我们将使用一个序列对机器神经传输网络中常用的翻译器进行排序。这也会有一个注意机制和利用老师强迫学习。为此,你需要对 RNN 氏症和 GRU 氏症有基本的了解。我将简要描述这个网络,以及我如何使用我现有的数据库作为训练数据集。
总的来说,就是把源序列' X' 转换成某个目标序列 'Y' 其中, X = x₁ + x₂ + …。+ xᵣ,
Y = y₁ + y₂ + …+ yₐ
通常,这项工作是通过创建我们的源序列' X '的表示来完成的。我们将对目标序列' Y '中下一个目标单词/字符的条件概率进行建模。
为什么序列要序列模式?
抽象的思想是把一个给定的输入,即一个源序列转换成一个 N 维的上下文向量,它将体现输入的“意义”。这个向量然后被馈送到解码器,解码器将把输入“翻译”成所需的输出。
为什么有注意机制?等等,注意机制是什么?
分离编码器和解码器的上下文向量保存/总结了来自源序列的大部分输入信息。“预计”这将是输入的一个很好的总结,以便解码器开始产生良好的模型结果。注意力机制背后的思想是重新训练上下文向量,并发现哪些状态将被证明对解码器有用。如果没有注意机制,通常初始和中间状态不会被重视,很容易被遗忘,从而导致网络忘记序列的早期部分。为了更好地理解它,我建议阅读这些文章这里和这里。
输入:
问题定义是独特的,不同于其他定义。我们的数据库由超过 100 万个公司名称的列表组成,这些名称都是专有名词,即它们都是公司名称,任何用户都可以搜索。让我们采用数据科学的方法来减少这个数字,并朝着实现我们的目标迈出一小步。不是每个人都会搜索所有的公司,他们会对一些正在或即将成为趋势的公司感兴趣。此外,我们有搜索历史记录,这有助于我们分析人们关注的领域以及他们最感兴趣的行业。这将消除很多噪音,并大大减少我们的公司范围。
在其他时间,这是一个数据科学项目,但现在我们将使用一组特殊的公司,我们可以合理地假设人们对搜索感兴趣。这涵盖了 2500 多家公司,这将是我们的训练数据集。
训练数据:
魔术来了!从我们想要预测的单词列表中,我们创建自己的输入和输出。我们在列表中归纳拼写错误,不是任何随机的拼写错误,而是关键字彼此接*。例如,如果我们有一个名为“”Linkedin.com的公司,我们创建一个带有拼写错误“lonkwdin . com”的训练输入。那么这些错误有什么特别之处呢?我把字母 I 和 e 分别换成了 s 和 o。这些字母不是随意挑选的。看看你的键盘,最有可能拼错字母“I”的是“u”、“j”、“k”、“l”&“o”。我们选择这些字母中的任何一个,并在输入中替换它。字母 e 也是如此。现在我们引入一些变量,以便网络学习这些错误并预测输出。**

我在增强的输入中创建了 24 个错误,并将其映射到实际的预测输出。我还添加了一个没有错误的,这样网络应该知道,当有人输入完全正确,我们仍然显示他们预期的结果。请记住,网络的目标是以概括的方式学习这些错误,以便一旦有人在训练/测试集中犯了拼写错误,我们仍然能够预测它。
然后,这种增强/模拟在所有公司中运行,产生了 78,000 个数据点。这些数据被分成 60-20-20 份,用于训练、验证和测试数据集。
回到网络:
这里网络的目标是在给定增广值的情况下预测实际值。我们在这里必须随机应变如何使用神经机器翻译模型。这种模型广泛用于翻译语言,这些语言有大量的单词(专有名词除外),这些单词的频率足以让模型理解何时、何地以及如何使用它们。不幸的是,这个案例不一样。为什么?因为每当我们在数据集中介绍一家新公司时,我们的词汇量就会增加。这显然是不可扩展的,因为我们不能总是修改网络的输入来考虑这些单词并从头重新训练它。保持输入索引不变的一种方法是使用字符。这样,无论发生什么,我们的词汇长度都保持不变。我们总共取 52 个字符,包括字母、数字和特殊符号,将每个字符映射为‘a’->2、‘b’->3、‘c’->4 等等。通过这样做,不管有什么新公司进来,它都将在这个 52 个字符的词汇表中。这允许我们从先前离开的地方训练模型。另一方面,如果我们必须引入一个新单词,我们的初始映射索引将每次增加 1。这将要求网络每次从头开始重新学习一组新的数字,这是不可扩展的。
*"<>abcdefghijklmnopqrstuvwxyz &()+/.,;'?!-@0123456789"*
前两个字符''将在解码器中用作' SOS '(字符串开始)和' EOS '(字符串结束),以告诉解码器字符串何时开始和结束。为什么这是必要的?因为即使在抛出一个 EOS 标记后,它也会继续一个接一个地预测字符。这是一个提示,让我们知道预测到此结束。
很好,现在我们已经确定了我们的输入是什么样子,输出是实际的公司名称。我们开始训练网络,并在它过度适应之前停止。

结果:
该模型达到了 87.1%的准确率,与目前 89-90%的准确率相比,还算不错。准确性差异的原因仅仅是因为我的数据集是专有名词,即不会重复的单词。这大大增加了问题的复杂性,从而降低了准确性。
我认为改善这一点的一个方法是对数据集做更多的预处理,使模型更容易预测,从而提高准确性。
AI 在行动:
Reorg 最*一直在撰写关于冠状病毒影响的文章,所有相关文章都以“冠状病毒影响”为名。下面我用一些可能的错误组合创建了一个 gif。

当有人在我们搜索栏中搜索“冠状病毒影响”并点击回车时,可能会出现这些错误。这张 gif 显示了即使在诱发了许多错误之后,模型仍然做得很好。
橙色的字母是用户的输入,下面的输出是自动完成预测。
这是“Bharti Airtel”公司的另一个例子。在完全删除第二个单词并在第一个单词中引入 2 个错误后,它仍然预测正确的结果

另一件需要指出的事情是,这个模型是绝对疯狂的。模型训练时,输入长度和输出长度不必保持不变。对于任何其他数据点,它们可以不同。现在试着想一想其他能做到这一点的模型。想不出很多,是吧?心智成熟
基于深度学习的推荐系统

现代电影推荐人简介
传统上,推荐系统基于诸如聚类、最*邻和矩阵分解的方法。然而,*年来,深度学习在多个领域取得了巨大的成功,从图像识别到自然语言处理。推荐系统也受益于深度学习的成功。事实上,今天最先进的推荐系统,如 Youtube 和亚马逊的推荐系统,是由复杂的深度学习系统驱动的,而不是传统方法。
为什么是这个教程?
在阅读这里的许多有用的教程时,这些教程涵盖了使用传统方法(如矩阵分解)的推荐系统的基础,我注意到缺少涵盖基于深度学习的推荐系统的教程。在本笔记本中,我们将浏览以下内容:
- 如何使用 PyTorch Lightning 创建自己的基于深度学习的推荐系统
- 推荐系统中隐式和显式反馈的区别
- 如何在不引入偏差和数据泄漏的情况下训练-测试分割用于训练推荐系统的数据集
- 评估推荐系统的标准(提示:准确性或 RMSE 是不合适的!)
本教程的数据集
本教程使用 MovieLens 20M 数据集提供的电影评论,这是一个受欢迎的电影评级数据集,包含从 1995 年到 2015 年收集的 2000 万条电影评论。
如果你想跟随本教程中的代码,你可以查看我的 Kaggle 笔记本,在那里你可以运行代码,并在跟随本教程时看到输出。
使用隐式反馈构建推荐系统
在我们建立我们的模型之前,理解隐式和显式反馈之间的区别,以及为什么现代推荐系统建立在隐式反馈的基础上是很重要的。
明确的反馈
在推荐系统的背景下,显式反馈是从用户那里收集的直接和定量数据。例如,亚马逊允许用户在 1-10 的范围内给购买的商品打分。这些评级直接由用户提供,该量表允许亚马逊量化用户偏好。另一个显式反馈的例子包括 YouTube 上的拇指向上/向下按钮,该按钮捕捉用户对特定视频的显式偏好(即喜欢或不喜欢)。
然而,显式反馈的问题是它们很少。想想看,你上一次点击 YouTube 视频上的“喜欢”按钮,或者给你的网上购物打分是什么时候?很有可能,你在 YouTube 上观看的视频数量远远大于你明确评价的视频数量。
隐性反馈
另一方面,隐式反馈是从用户交互中间接收集的,它们充当用户偏好的代理。比如说。你在 YouTube 上观看的视频被用作隐性反馈,为你量身定制推荐,即使你没有明确地对这些视频进行评级。隐性反馈的另一个例子包括你在亚马逊上浏览过的商品,它被用来为你推荐其他类似的商品。
隐性反馈的好处是丰富。使用隐式反馈构建的推荐系统还允许我们通过每次点击和交互来实时定制推荐。今天,在线推荐系统是使用隐式反馈构建的,这允许系统在每次用户交互时实时调整其推荐。
数据预处理
在开始构建和训练我们的模型之前,让我们做一些预处理,以获得所需格式的 MovieLens 数据。
为了保持内存使用的可管理性,我们将只使用该数据集中 30%用户的数据。让我们随机选择 30%的用户,只使用所选用户的数据。
过滤数据集后,现在有来自 41,547 个用户的 6,027,314 行数据(这仍然是一个很大的数据!).数据帧中的每一行都对应于一个用户对一部电影的评论,如下所示。

列车测试分离
除了评级,还有一个时间戳列,显示提交评论的日期和时间。使用时间戳列,我们将使用留一法实现我们的训练测试分割策略。对于每个用户,最*的评论被用作测试集(即,省去一个),而其余的将被用作训练数据。
为了说明这一点,用户 39849 评论的电影如下所示。用户评论的最后一部电影是 2014 年的热门电影《银河护卫队》。我们将使用这部电影作为该用户的测试数据,并使用其余已审查的电影作为训练数据。

themoviedb.org 电影海报(免费使用)
这种训练-测试分离策略经常在训练和评估推荐系统时使用。进行随机分割是不公*的,因为我们可能会使用用户最*的评论进行训练,而使用早期的评论进行测试。这引入了带有前瞻偏差的数据泄漏,并且经过训练的模型的性能不能推广到真实世界的性能。
下面的代码将使用留一法将我们的评级数据集分成一个训练集和一个测试集。
将数据集转换成隐式反馈数据集
如前所述,我们将使用隐式反馈来训练一个推荐系统。然而,我们使用的 MovieLens 数据集是基于显式反馈的。要将该数据集转换为隐式反馈数据集,我们只需将评级二进制化,并将其转换为“1”(即正面类别)。值“1”表示用户已经与项目进行了交互。
值得注意的是,使用隐式反馈重新定义了我们的推荐器试图解决的问题。在使用显式反馈时,我们不是试图预测电影评级,而是试图预测用户是否会与每部电影进行交互(即点击/购买/观看),目的是向用户呈现交互可能性最高的电影。

不过,我们现在确实有一个问题。在二值化我们的数据集之后,我们看到数据集中的每个样本现在都属于正类。然而,我们还需要负样本来训练我们的模型,以指示用户没有交互的电影。我们假设这些电影是用户不感兴趣的——尽管这是一个笼统的假设,可能不是真的,但在实践中通常效果很好。
下面的代码为每行数据生成 4 个负样本。换句话说,阴性样本与阳性样本的比例为 4:1。这个比例是随意选择的,但我发现它在实践中工作得相当好(你可以自己找到最佳比例!).
太好了!我们现在有了模型所需格式的数据。在我们继续之前,让我们定义一个 PyTorch 数据集以便于训练。下面的类只是将我们上面写的代码封装到一个 PyTorch 数据集类中。
我们的模型——神经协同过滤(NCF)
虽然有许多基于深度学习的推荐系统架构,但我发现由 He 等人提出的框架是最简单的,它足够简单,可以在这样的教程中实现。
用户嵌入
在我们深入模型的架构之前,让我们熟悉一下嵌入的概念。嵌入是一个低维空间,它从高维空间中捕捉向量的关系。为了更好地理解这个概念,让我们仔细看看用户嵌入。
想象一下,我们希望根据用户对两种类型电影的偏好来代表他们——动作片和爱情片。让第一维度是用户有多喜欢动作片,第二维度是用户有多喜欢言情片。

现在,假设 Bob 是我们的第一个用户。鲍勃喜欢动作片,但不喜欢爱情片。为了将 Bob 表示为一个二维向量,我们根据他的偏好将他放在图中。

我们的下一个用户是乔。乔是动作片和爱情片的超级粉丝。我们用二维向量来表示 Joe,就像 Bob 一样。

这个二维空间被称为嵌入。从本质上说,嵌入减少了我们的用户,这样他们可以在一个低维空间中以一种有意义的方式被表示。在这种嵌入中,具有相似电影偏好的用户被放置在彼此附*,反之亦然。

当然,我们并不局限于仅仅使用二维来表示我们的用户。我们可以使用任意数量的维度来表示我们的用户。更多的维度可以让我们更准确地捕捉每个用户的特征,但代价是模型变得复杂。在我们的代码中,我们将使用 8 个维度(我们将在后面看到)。
习得嵌入
同样,我们将使用一个单独的项目嵌入层来表示低维空间中项目(即电影)的特征。
您可能想知道,我们如何学习嵌入层的权重,以便它提供用户和项目的准确表示?在我们之前的例子中,我们使用 Bob 和 Joe 对动作和爱情电影的偏好来手动创建我们的嵌入。有没有办法自动学习这样的嵌入?
答案是协同过滤——通过使用评分数据集,我们可以识别相似的用户和电影,从现有评分中创建用户和项目嵌入。
模型架构
现在我们对嵌入有了更好的理解,我们准备定义模型架构。正如您将看到的,用户和项目嵌入是模型的关键。
让我们使用以下培训示例来浏览模型架构:


对于 userId = 3 和 movieId = 1,模型的输入是一次性编码的用户和项目向量。因为这是一个正样本(用户实际评分的电影),真实标签(互动)为 1。
用户输入向量和项目输入向量分别被馈送到用户嵌入和项目嵌入,这导致更小、更密集的用户和项目向量。
嵌入的用户和项目向量在通过一系列完全连接的层之前被连接,这将连接的嵌入映射到预测向量作为输出。在输出层,我们应用 Sigmoid 函数来获得最可能的类。在上面的例子中,最可能的类是 1(正类),因为 0.8 > 0.2。
现在,让我们用 PyTorch Lightning 来定义这个 NCF 模型!
让我们使用 GPU 为我们的 NCF 模型训练 5 个时期。
注: PyTorch Lightning 相对于 vanilla PyTorch 的一个优势是,你不需要编写自己的锅炉板训练代码。注意训练师类如何让我们只用几行代码就能训练我们的模型。
评估我们的推荐系统
既然我们已经训练出了模型,我们就可以使用测试数据来评估它了。在传统的机器学习项目中,我们使用准确性(对于分类问题)和 RMSE(对于回归问题)等指标来评估我们的模型。然而,这样的度量对于评估推荐系统来说过于简单。
为了设计一个好的评估推荐系统的指标,我们需要首先了解现代推荐系统是如何使用的。
在网飞,我们可以看到如下建议列表:

类似地,亚马逊使用一个推荐列表:

这里的关键是,我们不需要用户与推荐列表中的每一个单项进行交互。相反,我们只需要用户与列表上的至少一个项目进行交互——只要用户这样做,推荐就有效。****
为了模拟这种情况,让我们运行下面的评估协议,为每个用户生成一个前 10 个推荐项目的列表。
- 对于每个用户,随机选择 99 个用户没有交互过的物品。
- 将这 99 个项目与测试项目(用户最后交互的实际项目)结合起来。我们现在有 100 个项目。
- 对这 100 个项目运行模型,并根据它们的预测概率对它们进行排序。
- 从 100 个项目列表中选择前 10 个项目。如果测试项目出现在前 10 个项目中,那么我们说这是成功的。
- 对所有用户重复该过程。命中率就是*均命中率。
这个评估协议被称为命中率@ 10 ,它通常用于评估推荐系统。
命中率@ 10
现在,让我们使用描述的协议来评估我们的模型。

我们有一个相当不错的命中率@ 10 分!从上下文来看,这意味着 86%的用户被推荐了他们最终与之互动的实际项目(在 10 个项目的列表中)。还不错!
下一步是什么?
我希望这对于创建基于深度学习的推荐系统是一个有用的介绍。要了解更多信息,我推荐以下资源。
来自 Neptune . ai——推荐系统:机器学习指标和商业指标。neptune.ai 的作者写了一份非常全面的推荐系统指南。如果你有兴趣,我鼓励你去看看。
其他资源
面向工业应用的基于深度学习的逆向图像搜索
理解大数据
从非结构化数据到基于内容的图像检索
有没有想过谷歌反向图片搜索是如何工作的,它接收一张图片,并在几分之一秒内返回给你最相似的图片?
对于人类来说,评估图像的内容相当简单,确定图像中是否包含汽车、猫或房子并不需要太多努力。然而,想象你有一个包含 100,000 张(或更多)图片的数据库,没有任何元数据或结构。在缺乏任何关于图像内容的相关元数据的情况下,您如何能够提取任何有用的信息而不必手动滚动所有图像呢?幸运的是,来自经典计算机视觉和深度学习的最新发展的技术来拯救我们。
基于内容的图像检索中的一个重要应用是所谓的“反向图像搜索”。这是计算机视觉技术在图像检索问题上的应用,即在大型数据库中搜索图像的问题。“基于内容”意味着搜索分析图像的内容,而不是元数据,例如与图像相关的关键字、标签或描述。
拥有一个没有可用元数据的大型图像数据库不是一个理想的起点,但不幸的是,这实际上是一个非常常见的场景。幸运的是,我们可以利用许多与前面提到的 Google 的“反向图像搜索”相同的技术来构建我们自己的自定义图像匹配应用程序。
深度学习和图像分类
你以前可能见过的例子可以是典型的“猫与狗”分类模型,在大量的博客和在线教程中讨论过。然而,这些例子中的大多数都是基于对大量带标签的图像的访问,在这些图像中,您拥有可用于训练您的模型的“基本事实”信息。在我们的情况下,这不是我们真正想要的,因为我们没有任何这样的信息。幸运的是,我们仍然可以利用在其他数据集上训练的公开可用的深度学习模型。
访问已经在大量数据上训练过的模型(例如,流行的 ImagNet 数据集,包含数百万张带注释的图像),是构建最先进的深度学习应用程序变得更加容易的原因之一。使用这种预先训练的模型作为基础,人们通常可以成功地利用迁移学习技术来使模型适应我们的特定需求,即使只有非常有限的数据量(或者根本没有数据)。
在我们的例子中,当谈到理解非结构化图像的数据库时,我们实际上可以获得许多有价值的见解,而根本不需要任何标记的训练图像。这是因为这些深度学习模型实际上是如何基于自动提取图像的相关“特征”来分析图像内容的。
在一大组标记图像上训练的深度学习模型基本上已经成为自动“特征提取器”。这意味着当分析我们的图像时,我们基本上得到一个包含图像内容相关信息的“特征向量”作为输出。即使我们没有训练我们的模型来将这个输出分类到一组不同的类别/类中,我们仍然可以提取许多有价值的信息。
神经网络作为特征提取器
- 神经网络图像分类器通过将图像(高维像素空间中的点)转换为低维“特征向量”来工作,低维“特征向量”表示网络学习的特有“特征”(如下图所示)
- 然后,我们可以采用一个经过训练的神经网络,删除其最初用于分类对象的最后一个高级层,并使用解剖模型将我们的图像转换为特征向量。

从图像到特征提取。卷积图层中的过滤器在网络的不同级别查找的要素示例。网络越深入(层次越高),特征就越复杂。资料来源:泽勒,马修 d。和罗布弗格斯。"可视化和理解卷积网络."计算机视觉-ECCV 2014。斯普林格国际出版公司,2014 年。818–833
图像的这种特征向量表示仍然包含一些“噪声”和冗余信息。为了过滤掉最重要的信息(同时加快图像检索和分析过程),我们基于主成分分析进一步压缩数据。为此,我们在这里将特征向量从 2048 维压缩到 256 维。(请注意,维度取决于您选择神经网络作为特征提取器)。

从输入图像到压缩特征向量
相似性度量:余弦相似性
将图像转换成特征向量后,我们需要某种相似性度量来比较它们。一个这样的候选,并且在这个例子中使用的,是“余弦相似度”。本质上,这度量了高维特征空间中图像之间的“角度”。这在下面针对二维特征空间的非常简化的版本中示出,比较输入图像和图像“A”/“B”之间的余弦相似性。我们在这里看到“A”包含与输入图像相似的对象(因此它们之间的“角度”更小),而“B”包含不同外观的对象(相应地具有更大的角度)。

余弦相似性作为比较特征向量的度量
图像聚类
通过我们的“特征提取模型”处理数据库中的图像,我们可以将所有图像转换为特征向量表示。这意味着我们现在有了图像内容的定量描述。有了这些信息,我们可以例如将这些向量通过聚类算法,该算法将基于图像的内容将图像分配到各个聚类。在这样做的时候,我们仍然不知道各个图像包含什么,但是我们知道各个群中的图像通常包含相似的对象/内容。

从特征向量到聚类。图片来源:使用 t-SNE 可视化数据,Laurens van der Maaten 和 Geoffrey Hinton 的研究论文
这种技术的一个应用可以是,例如,作为为监督图像分类模型定义训练集的初步步骤。通过对所有图像进行聚类,并检查每个聚类中的一些图像,我们可以为该聚类中的所有图像分配一个标签。在这样做的时候,我们已经有效地标记了我们所有的图像,仅仅通过查看来自每个集群的几个例子。与手动滚动和注释 100,000 幅图像相比,这显然是一个进步。也就是说,自动给每个聚类中的所有图像分配相同的标签可能会导致一些错误的标签。尽管如此,它仍然是更详细分析的良好起点。
面向工业应用的反向图像搜索
另一个关键应用是“反向图像搜索”,这是本文的主题。假设我们想要分析一个“目标图像”,然后在我们的数据库中搜索相似的内容。例如,这可以是来自制造/生产工厂中的先前维护工作或检查的图像数据库。然后,我们可能会对寻找类似物体的图像感兴趣,或者可能会对特定设备的所有历史检查图像感兴趣。
然后,我们可以做的是,首先通过我们的“特征提取器模型”处理我们的目标图像,将其转换为特征向量表示。完成这些后,我们可以在特征向量数据库中进行相似性搜索。
匹配图像:循序渐进
- 准备图像数据库:使用我们的神经网络模型将图像数据库转换为特征向量表示,然后进行主成分变换。
- 分析新的目标图像:使用与上述相同的流水线将图像转换成低维特征向量。
- 查找匹配图像:使用余弦相似度计算特征向量之间的相似度。使用相似性度量来匹配数据库中与目标图像最相似的图像。

从输入图像到最佳匹配识别
总结:
理想情况下,图像数据库当然应该已经构建了必要的元数据,以便首先执行这样的搜索。然而,实际上有许多现实世界的例子并非如此。幸运的是,正如上面的例子所说明的,所有的希望都没有破灭。即使从杂乱和非结构化的数据中,人们仍然可以提取有价值的见解。
本文并不打算从技术上深入研究在实践中实现这种解决方案的复杂性,但是我希望它至少能让您对这些技术能够提供的功能和可能性有一个基本的了解。
我认为,重要的是要强调,深度学习不仅适用于可以访问大量高质量标签数据的公司。如上例所示,即使根本没有标记数据,您仍然可以利用底层技术从数据中提取有价值的见解。
如果你有兴趣了解更多与人工智能/机器学习和数据科学相关的主题,你也可以看看我写的其他一些文章。你会发现它们都列在我的中型作者简介中,你可以在这里找到。
而且,如果你想成为一个媒体会员,免费访问*台上的所有资料,你也可以使用下面我的推荐链接。(注意:如果您使用此链接注册,我也会收到一部分会员费)
[## 通过我的推荐链接加入媒体- Vegard Flovik
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@vflovik/membership)
更多来自 Vegard Flovik 媒体:
- 蒙特卡洛方法简介
- 图论入门
- 用于图像分类的深度迁移学习
- 建造一个能读懂你思想的人工智能
- 人工智能和大数据的隐藏风险
- 如何使用机器学习进行异常检测和状态监控
- 如何(不)使用机器学习进行时间序列预测:避免陷阱
- 如何利用机器学习进行生产优化:利用数据提高绩效
- 如何给 AI 系统教物理?
- 我们能否利用纳米级磁铁构建人工大脑网络?
- 供应链管理中的人工智能:利用数据推动运营绩效
我还在下面的研讨会演示中讨论了与 AI/机器学习相关的各种主题:“从炒作到现实世界的应用”。我希望这些资源对您有所帮助!当然,欢迎在下面的评论中提出任何反馈和意见。
基于深度学习的 OpenCV 超分辨率
如何使用最新的算法,通过 OpenCV 库中一个简单易用的函数来提高图像的分辨率。

目录
- 超分辨率
- 在 OpenCV 中放大图像的步骤
- 不同的预训练模型
- 结果样本
- 注释和参考资料
OpenCV 中的超分辨率
OpenCV 是一个开源的计算机视觉库,有大量优秀的算法。自从最*的一次合并以来,OpenCV 包含了一个基于深度学习方法的易于使用的界面来实现超级分辨率(SR)。该界面包含经过预先训练的模型,可以非常容易和有效地用于推理。在这篇文章中,我将解释它能做什么,并逐步展示如何使用它。到目前为止,它与 C++和 Python 一起工作。
注意:使用此代码不需要任何关于 SR 的知识。我在一台 Ubuntu 16.04 机器上运行这个,但是它适用于任何其他发行版(它也适用于视窗)。
步骤
- 1.使用 contrib 模块(包含 dnn_superres)安装 OpenCV。
- 2.下载经过预先培训的模型。
- 3.放大图像。
- 与 contrib 模块一起安装 OpenCV。
我们的第一步是安装 OpenCV。有些功能会在以后发布,所以要小心版本:4.2.0 为 C++,4.3.0 添加 Python wrap,4.4.0 添加 GPU 推理。您可以按照 opencv 文档中的说明进行操作。非常重要的是你也要安装 contrib 模块,因为这是 SR 接口代码所在的地方。您可以选择安装所有 contrib 模块或只安装必要的 SR 模块。我们将使用的接口或模块称为 dnn_superres (dnn 代表深度神经网络;超级分辨率的超级图像)。
2.下载预先训练好的模型。
我们需要单独下载预训练的模型,因为 OpenCV 代码库不包含它们。原因是有些模型很大。因此,如果它们在标准代码库中,可能不需要它们的人仍然必须下载它们。有几个模型可供选择(参见本文中的模型一节)。都是流行 SR 论文的实现。就目前来说,还是选个小型号吧。你可以在这里下载。这个预先训练的模型可以将图像的分辨率提高 2 倍。更多模型及其解释,请参见本文中的模型部分。
3.放大图像。
现在我们准备升级我们自己的图像甚至视频。我将提供 C++和 Python 的示例代码。(如果要用 GPU 进行推理,也请参考本页底部的注释。)我们先来看 C++ :
我将解释代码的重要部分。
//Read the desired model
string path = "FSRCNN_x2.pb";
sr.readModel(path);
这将加载所选模型的所有变量,并为神经网络的推断做准备。参数是下载的预训练模型的路径。当您想要使用不同的模型时,只需下载它(参见本文的模型部分)并更新路径。
//Set the desired model and scale to get correct pre- and post-processing
sr.setModel("fsrcnn", 2);
这让模块知道您选择了哪个模型,因此它可以选择正确的预处理和后处理。您必须指定正确的模型,因为每个模型使用不同的处理。
第一个参数是模型的名称。可以在“edsr”、“fsrcnn”、“lapsrn”、“espcn”中选择。非常重要的一点是该型号是您在“sr.readModel()”中指定的型号的正确型号。请参见页面底部的型号部分,了解各型号的规格。
第二个参数是放大系数,即你将增加多少倍的分辨率。同样,这需要与您选择的型号相匹配。每个模型都有一个单独的放大系数文件。
//Upscale
Mat img_new;
sr.upsample(img, img_new);
cv::imwrite( "upscaled.png", img_new);
这是推理部分,它通过神经网络运行你的图像,并产生你的放大图像。
现在只需编译和运行您的文件来升级您的图像!
下面是用 Python 编写的代码:
它和 C++中的几乎完全一样,除了两件事。
- 您必须使用不同的构造函数:
# Create an SR object
sr = dnn_superres.DnnSuperResImpl_create()
2.放大时,您可以直接分配放大的图像,而不是创建占位符图像:
# Upscale the image
result = sr.upsample(image)
型号
该模块目前支持 4 种不同的 SR 型号。它们都可以按 2、3 和 4 的比例放大图像。LapSRN 甚至可以扩大到 8 倍。它们在准确性、大小和速度上有所不同。
- EDSR【1】。这是性能最好的型号。然而,它也是最大的模型,因此具有最大的文件大小和最慢的推理。你可以在这里下载。
- ESPCN【2】。这是一个小模型,推理又快又好。它可以进行实时视频放大(取决于图像大小)。你可以在这里下载。
- fsr CNN【3】。这也是推理快速准确的小模型。也可以做实时视频向上扩展。你可以在这里下载。
- LapSRN【4】。这是一个中等大小的模型,可以放大 8 倍。你可以在这里下载。
有关这些模型的更多信息和实现,请参见模块的 GitHub 自述文件。关于广泛的基准测试和比较,请点击。
样品
我们来看一些结果!(如果你在手机上,放大看区别更清楚。)

投入

通过双线性插值放大(系数为 3)。

由 FSRCNN 放大(系数为 3)。

由 ESDR 升级(系数为 3)。

输入。Randy Fath 在 Unsplash 上拍摄的照片

通过双线性插值放大(系数为 3)。

由 FSRCNN 放大(系数为 3)。

由 ESDR 升级(系数为 3)。

原图。
如您所见,这些模型产生了非常令人满意的结果,完全破坏了简单双线性插值的性能。特别是 EDSR 给出了惊人的结果,尽管它有点慢(几秒钟的推断)。自己试试吧!
实施注意事项:
- 如果它在使用。jpg 图片,试试。png 格式。
- 确保 setModel()参数与 readModel()中使用的模型相匹配。
- 尝试不同的模型,在速度和性能方面得到不同的结果。
- 如果你想使用你的 GPU 进行推理(标准是 CPU),你可以在读取模型后将后端和目标设置为 CUDA。根据你的 GPU,它会给你一个速度上的提升。这是新特性,所以需要 4.4.0 版本。参见相关的拉取请求。你还需要构建支持 CUDA 的 opencv,比如像这样:链接到 opencv 构建命令。
在 C++中设置后端/目标
在 Python 中设置后端/目标
参考
[1] Bee Lim,Sanghyun Son,Heewon Kim,Seungjun Nah,和 Kyoung Mu Lee,“用于单个图像超分辨率的增强深度残差网络”,第二届 NTIRE:图像恢复和增强研讨会的新趋势以及与 2017 年 CVPR 相关的图像超分辨率挑战。
[2] Shi,w .,Caballero,j .,Huszár,f .,Totz,j .,Aitken,a .,Bishop,r .,Rueckert,d .和 Wang,z .,“使用高效亚像素卷积神经网络的实时单幅图像和视频超分辨率”,IEEE 计算机视觉和模式识别会议论文集2016。
[3]赵东,陈变来,唐晓鸥。“加速超分辨率卷积神经网络”,2016 年 ECCV欧洲计算机视觉会议论文集。
[4]赖伟生,黄,J. B .,Ahuja,n .和杨,M. H .,“用于快速和精确超分辨率的深度拉普拉斯金字塔网络”,IEEE 计算机视觉和模式识别会议论文集,2017。
深度学习基础
深度强化学习讲解— 03
初学者的基本概念

这是“深度强化学习讲解”系列文章的第三篇。如果你以前有深度学习的知识,你可以跳过这篇文章,去读下一篇。
或者,如果您对深入学习的基础知识感兴趣,并希望在下一篇文章中继续使用 PyTorch,您可以阅读这篇文章。
在这篇文章中,我将回顾神经网络的主要概念,让读者理解深度学习的基础知识,以便用它在强化学习问题中编写代理程序。为了便于解释,我将把这篇文章放在一个有助于介绍理论概念的例子中。
访问第 3 页的自由介绍
medium.com](https://medium.com/aprendizaje-por-refuerzo/3-funciones-de-valor-y-la-ecuación-de-bellman-7b0ebfac2be1)
手写数字的分类
作为案例研究,我们将创建一个数学模型,允许我们识别手写数字,如下所示:

目标将是创建一个神经网络,给定一幅图像,该模型识别它所代表的数字。例如,如果我们向模型输入第一张图片,我们会期望它回答这是一张 5。下一个是 0,下一个是 4,以此类推。
不确定性分类问题
实际上,我们正在处理一个分类问题,给定一幅图像,模型将其分类在 0 到 9 之间。但有时,甚至我们会发现自己有某些疑问,例如,第一个图像代表 5 还是 3?

为此,我们将创建的神经网络返回一个具有 10 个位置的向量,指示 10 个可能数字中每一个的可能性:

数据格式和操作
在下一篇文章中,我们将解释如何使用 PyTorch 编写这个例子。目前,只需提到我们将使用 MNIST 数据集来训练模型,该数据集包含 60,000 张手工制作的数字图像。这个黑白图像(包含灰度级的图像)的数据集已经归一化为 28×28 像素。
为了便于将数据摄取到我们的基本神经网络中,我们将把输入(图像)从二维(2D)转换成一维(1D)的向量。也就是说,28×28 个数字的矩阵可以由 784 个数字(逐行连接)的向量(数组)表示,这种格式接受密集连接的神经网络作为输入,就像我们将在本文中看到的那样。
如前所述,我们需要用 10 个位置的向量来表示每个标签,其中对应于表示图像的数字的位置包含 1,其余的包含 0。这个将标签转换成与不同标签的数量一样多的零的向量,并将 1 放入对应于标签的索引中的过程被称为独热编码。例如,数字 7 将被编码为:

神经网络组件
现在我们准备开始解释基本神经网络概念的最小集合。
普通的人工神经元
为了展示基本神经元是怎样的,让我们假设一个简单的例子,其中我们在二维*面中有一组点,并且每个点已经被标记为“正方形”或“圆形”:

给定一个新的点“ × 【T3”),我们想知道它对应什么标号:

一种常见的方法是画一条线将两个组分开,并使用这条线作为分类器:

在这种情况下,输入数据将由( x1,x2 )形式的向量表示,这些向量表示它们在这个二维空间中的坐标,我们的函数将返回‘0’或‘1’(在线的上方或下方),以知道它应该被分类为“正方形”还是“圆形”。它可以定义为

更一般地说,我们可以将这条线表示为:

为了对输入元素 X(在我们的例子中是二维的)进行分类,我们必须学习一个与输入向量维数相同的权重向量 W,即向量( w1,w2 )和一个 b 偏差。
有了这些计算值,我们现在可以构建一个人工神经元来对新元素 X 进行分类。基本上,神经元在输入元素 X 的每个维度的值上应用计算权重的向量 W ,并在最后添加偏差 b. 其结果将通过非线性“激活”函数来产生结果“0”或“1”。我们刚刚定义的这种人工神经元的功能可以用更正式的方式来表达,例如

现在,我们将需要一个函数,它对变量 z 进行转换,使其变成‘0’或‘1’。虽然有几个函数(“激活函数”),但在本例中,我们将使用一个称为 sigmoid 函数的函数,该函数针对任何输入值返回 0 到 1 之间的实际输出值:

如果我们分析前面的公式,我们可以看到它总是倾向于给出接* 0 或 1 的值。如果输入 z 相当大且为正,则负 z处的“e”为零,因此, y 取值为 1。如果 z 具有大的负值,那么对于“e”的大正数,公式的分母将是一个大的数字,因此 y 的值将接* 0。从图形上看,sigmoid 函数呈现如下形式:

到目前为止,我们已经介绍了如何定义人工神经元,这是神经网络可以拥有的最简单的架构。特别是,这种架构在本主题的文献中被命名为感知器,由 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。在弱预测中,将有几个可能的标签,它们将具有或多或少相同的概率。
手写数字的神经网络模型
对于这个例子,我们将把一个非常简单的神经网络定义为两层序列。视觉上,我们可以用以下方式表示它:

在可视化表示中,我们明确表示我们有模型的 784 个输入特征(28×28)。具有 sigmoid 激活功能的第一层 10 个神经元“提取”输入数据,以获得所需的 10 个输出,作为下一层的输入。第二层将是由 10 个神经元组成的 softmax 层,这意味着它将返回代表 10 个可能数字的 10 个概率值的矩阵(如我们之前所述,其中每个值将是当前数字的图像属于其中每个数字的概率)。
学习过程
训练我们的神经网络,即学习我们的参数值(权重 W 和 b 偏差)是深度学习最真实的部分,我们可以将神经网络中的这一学习过程视为神经元层“往返”的迭代过程。“去”是信息的前向传播,“回”是信息的后向传播。
训练循环
第一阶段前向传播发生在网络暴露于训练数据时,这些数据穿过整个神经网络以计算它们的预测(标签)。也就是说,通过网络传递输入数据,使得所有神经元将它们的变换应用于它们从前一层神经元接收的信息,并将它发送到下一层神经元。当数据已经穿过所有层,并且其所有神经元已经进行了它们的计算时,将到达最后一层,具有那些输入示例的标签预测的结果。
接下来,我们将使用一个损失函数来估计损失(或误差),并比较和衡量我们的预测结果相对于正确结果的好坏程度(请记住,我们是在一个受监督的学习环境中,我们有一个标签来告诉我们期望值)。理想情况下,我们希望成本为零,也就是说,估计值和期望值之间没有偏差。因此,随着模型被训练,神经元互连的权重将被逐渐调整,直到获得良好的预测。
一旦计算出损失,该信息就被反向传播。因此,它的名字:反向传播。从输出层开始,损失信息传播到隐藏层中直接对输出做出贡献的所有神经元。然而,基于每个神经元对原始输出的相对贡献,隐藏层的神经元仅接收总损失信号的一部分。这个过程一层一层地重复,直到网络中的所有神经元都接收到描述它们对总损失的相对贡献的损失信号。现在我们已经将这些信息传播回来,我们可以调整神经元之间连接的权重。
视觉上,我们可以用这个阶段的视觉方案(基于我们的神经网络的先前视觉表示)来总结我们已经解释的内容:

我们正在做的是,在下次使用网络进行预测时,让损失尽可能接*于零。
一般而言,我们可以将学习过程视为一个全局优化问题,其中参数(权重和偏差)必须以最小化上述损失函数的方式进行调整。在大多数情况下,这些参数无法解析求解,但一般来说,它们可以通过优化器(迭代优化算法)很好地逼*,例如一种称为梯度下降的技术。这种技术在损失函数的导数(或梯度)的计算的帮助下以小增量改变权重,这允许我们看到朝着全局最小值“下降”的方向;这通常是在我们在每次迭代中传递给网络的所有数据集的连续迭代(历元)中的成批数据中完成的。
读者可以访问深度神经网络的学习过程一文,了解关于这个训练循环的更多细节,尽管就本节的目的而言,我不认为这是必要的。
交叉熵损失函数
我们可以为我们的神经网络模型选择范围广泛的损失函数。例如,确保读者知道通常用于回归的均方误差 (MSE)损失函数。对于本文中提出的分类,通常使用的损失函数是交叉熵,它允许测量两个概率分布之间的差异。
交叉熵损失,或对数损失,衡量分类模型的性能,其输出是 0 到 1 之间的概率值。根据上下文的不同,两者略有不同,但在深度学习中,当计算 0 和 1 之间的错误率时,它们会解决相同的问题。
交叉熵损失随着预测概率偏离实际标签而增加。完美的模型的对数损失为 0。在二进制分类中,类的数量是 2,交叉熵可以计算为:

在我们的多类分类示例中,我们为每个观察值的每个类标签计算单独的损失,并对结果求和:

在哪里
- C —类的数量(在我们的例子中是 10)
- 日志 —自然日志
- y—二进制指示器(0 或 1)如果分类标签 𝑐 是观察的正确分类 𝑜
- p —预测概率观测值 o 属于类 c
在这篇文章中,我回顾了神经网络的主要概念,以使读者理解深度学习的基础知识,以便在强化学习问题中使用它来编程代理。在下一篇文章中,我们将使用 PyTorch 编写这篇文章中的例子,我们将向读者介绍 PyTorch 的基本特性,这是我们将在这一系列文章中使用的框架。
下一篇在见!
深度强化学习讲解系列
由 UPC 巴塞罗那理工 和 巴塞罗那超级计算中心
一个轻松的介绍性系列以一种实用的方式逐渐向读者介绍这项令人兴奋的技术,它是人工智能领域最新突破性进展的真正推动者。
本系列的内容](https://torres.ai/deep-reinforcement-learning-explained-series/)
关于这个系列
我在五月份开始写这个系列,那是在巴塞罗那的封锁期。老实说,由于封锁,在业余时间写这些帖子帮助了我 #StayAtHome 。感谢您当年阅读这份刊物;它证明了我所做的努力。
免责声明 —这些帖子是在巴塞罗纳封锁期间写的,作为个人消遣和传播科学知识,以防它可能对某人有所帮助,但不是为了成为 DRL 地区的学术参考文献。如果读者需要更严谨的文档,本系列的最后一篇文章提供了大量的学术资源和书籍供读者参考。作者意识到这一系列的帖子可能包含一些错误,如果目的是一个学术文件,则需要对英文文本进行修订以改进它。但是,尽管作者想提高内容的数量和质量,他的职业承诺并没有留给他这样做的自由时间。然而,作者同意提炼所有那些读者可以尽快报告的错误。*
深度学习超越 2019
进步于 【缓慢】有意识任务解决 ?

这个图是由yo shua beng io(neur IPS 2019 talk)、Yann le Cun和Leon Bottou最*的谈话综合而成。缩略词【IID】在图中展开为独立同分布的随机变量;OOD展开为不分配
TL;速度三角形定位法(dead reckoning)
- 自我监督学习——通过预测输入进行学习
- 在分布式表示中利用组合的力量
- 降 IID (独立同分布随机变量)假设
- 自我监督表示学习方法
- 注意力的作用
- 多时间尺度的终身学习
- 架构先验
W 虽然深度学习 (DL) 模型在 2019 年继续创造新纪录,在各种各样的任务中表现出最先进的性能,特别是在自然语言处理方面,2019 年标志着不仅要审查问题 深度学习 1.0 之外是什么? 出现在公众话语中,对这个问题的研究也加快了步伐。
深度学习 1.0 —局限性的快速回顾
深度学习 1.0 ( 本吉奥教授称之为系统 1 深度学习 ) 在解决人类可以直观解决的任务方面取得了成功,通常是以快速无意识、非语言的方式。例子是直觉,一个特定的游戏走法是好的,或者一张图片包含一只狗——我们在不到一秒钟的时间内快速解决这些任务。我们习惯性解决的任务也属于这一类。
尽管 DL 1.0 模型的性能在某些任务基准中超越了人类,但即使在它们目前可以很好执行的任务中,也存在一些已知的缺陷
- DL 1.0 车型比美国需要更多的训练数据/时间。例如,一个模型必须经历 200 年的等效实时训练才能掌握一款名为星际争霸 2的策略游戏。我们*均 20 小时就能学会开车而不出事故。迄今为止,我们还没有能够完全自动驾驶的汽车,尽管在数小时的训练数据中暴露出比我们多几个订单。此外,对于许多任务,模型需要来自人类的标记数据来学习概念

图来自 Yann Lecun 最*的演讲(2019 年 11 月)“基于能量的自我监督学习”。加强了一些游戏的学习训练时间,在这些游戏中,模型的表现达到或超过了专业人类玩家。
- DL 1.0 车型会犯我们通常不会犯的错误。例如,改变图像中的几个像素(我们的眼睛甚至不会注意到)会导致模型将其错误分类。站在电话附*的人可能会使模型认为人正在打电话。这些错误似乎源于多种原因— (1)模型在某些情况下产生虚假关联(2)输入数据中的偏差导致模型输出被污染(3)模型对分布变化缺乏鲁棒性,或者在某些情况下无法处理属于训练分布一部分的罕见实例。

DL 1.0 模型所犯的不同类型的错误。 (a) 在左上角的图中,注入了我们甚至没有察觉到的噪声,导致了模型的误分类。图片来自 2015 年关于对抗性 e 例子的论文。 (b) 右图中的错误是因为该模型在很大程度上暴露给了在电话亭附*打电话的人——所以这是由于训练数据集中的选择偏差。图片来自 Leon Bottou 在 2019 年 10 月发表的关于使用因果不变性学习表示法 (c) 经常观察到的错误是模型无法将训练分布数据以外的数据推广到分布之外的数据,或者只是属于训练分布一部分的罕见事件。黑天鹅效应(下图)的一个具体例子是一辆无人驾驶汽车暴露在一个罕见的事件中(从训练数据分布的角度来看,这不太可能发生)。图片来自 Yoshua Bengio 的 NeurIPS 2019 演讲
我们如何更接*人类级别的 AI?
迄今为止,答案尚不明确。具体来说,我们如何解决 DL 1.0 现有的局限性,同时解决更困难的有意识的任务解决问题?一种看起来很有希望的方法是从人类那里获得灵感,这些人除了在无意识任务解决中没有 DL 1.0 (样本效率低下,无法归纳出不符合分布的数据)的限制之外,还擅长有意识任务解决 ( )系统 2 任务 ) 如逻辑推理、规划等。
下面列出了一些研究方向(合理的方法、假设和先验——其中一些已经在早期的小规模实施中实现),它们可能会让我们进入深度学习 2.0 (有意识的任务解决)。
- 自我监督学习——通过预测输入进行学习
- 在分布式表示中利用组合的力量
- 降 IID (独立同分布随机变量)假设
- 自我监督表示学习的两种方法
- 注意力的作用
- 多时间尺度的终身学习
- 架构优先
下面详细讨论的这些研究方向表明,考虑到正在考虑的方法的本质,有意识解决任务的途径很可能同时克服上述 DL 1.0 的缺陷。
- 自我监督学习——通过预测输入进行学习
自我监督学习本质上是通过对来自任何其他部分的输入数据的任何部分进行预测来进行学习。预测可以是关于输入数据序列(在时间或空间上)中的下一个是什么,或者一般来说是其中丢失了什么。输入数据可以是一种或多种类型——图像、音频、文本等。学习是通过重建输入中丢失的部分来进行的。
我们的大部分学习是自我监督的。几年前 Geoffrey Hinton 的《信封背面的推理》抓住了这一点(他称之为“无监督的”,尽管现在我们也称之为“自我监督的”,以表明我们通过重建输入数据来监督我们自己的学习)

自我监督学习的感觉数据流的价值,除了其绝对数量(就每秒训练数据而言)的价值之外,还有
- 与典型的监督学习(反馈是每个输入的类别值或几个数字)或强化学习(正如模型预测的那样,反馈是偶尔的标量奖励)相比,它向学习者提供了更多的反馈数据(如果不是全部,至少是部分输入数据)。
- 来自环境的感觉数据流不是静止的。这迫使学习者,或者更具体地,嵌入学习者中的编码器,学习在变化的环境中基本不变的对象和概念的稳定表示。环境固有的不稳定性也提供了了解变化原因的机会。分布外泛化(预测训练分布中未见的事件)学习因果对于学习者做出生存所必需的预测是必不可少的。从本质上讲,环境的非静态性质提供了一个通过评估和提炼概念的学习表示以及它们之间的因果关系来持续学习的机会。
- 感觉流包括在学习中起关键作用的主体(包括学习者)。代理是环境的一个组成部分,并负责通过干预来改变它。在 DL 1.0 中,代理只是强化学习的一部分。为了让 DL 2.0 模型达到它的目标,让代理参与自我监督学习可能是至关重要的。即使是一个被动的学习者(一个新生儿),在最初的几个月里,他很大程度上是在以最小的互动观察环境,从观察环境中其他代理的互动中学习。

图自最* Yann LeCun 的谈话。新生的孩子凭直觉学习物理——例如,在 9 个月左右,通过观察他们周围的世界来学习重力——我们不会教他们重力。我们知道他们凭直觉理解重力,因为一个简单的汽车从桌子上推下来而不倒的实验(因为我们用一根他们看不见的细线吊着它来欺骗他们)不会让大约 9 个月大的孩子感到惊讶。大约 9 个月后,他们感到惊讶——因为他们的观察与他们 9 个月大的内部世界模型的预测输出不匹配,该模型预测它必须倒下。
- 学习捕捉因果关系的概念的稳定表示,使学习者能够根据其计算能力,通过内部模拟似是而非的行动序列来预测未来的几个时间步骤,并计划未来的奖励行动,避免有害的行动(就像学习驾驶时避免驶下悬崖)。
DL 1.0 中的自我监督学习
在 DL 1.0 中,自我监督学习已经被证明对于自然语言处理(NLP)任务非常有用和成功。我们有通过预测句子中的下一个单词或预测已经从句子中删除的单词来学习单词表示的模型(伯特——这在 NLP 世界中被称为无监督预训练,但本质上是自我监督学习,其中模型通过重建输入的缺失部分进行学习)。然而,DL 1.0 语言建模方法仅从文本输入中学习,而不是在其他感觉流也与代理交互一起考虑的环境中进行基础学习 (有一篇 2018 年的论文试图做到这一点 )。基于感官环境的语言学习赋予单词更多的上下文和意义,而不仅仅是统计它们的句子上下文(句子中相对于其他单词的位置)。由于这个原因,语言学习被限制为仅从文本进行自我监督学习,不仅承受着需要大量文本的负担,而且还将模型的理解限制为仅仅是单词序列的统计特性,而这些统计特性永远无法与从多感觉环境中进行的学习相匹配(例如,模型永远不会获得空间理解——空间上适合于盒子,反之亦然, 当把“它”与句子中正确的物体联系起来时,需要理解的是:奖杯放不进盒子里,因为 它 太大了; 奖杯放不进盒子是因为太小了;“第一指奖杯,第二指盒子)。**
迄今为止,自我监督学习对于图像、视频和音频还没有像对于文本那样成功(在文本中,模型必须预测单词在词汇上的分布;对于视频中的下一帧预测,在所有可能的下一帧上的分布输出是不可行的),尽管在具有 GANs 的图像完成【修补】 、视频下一帧预测模型中有一些有希望的结果。然而,从有意识的任务解决角度来看,直接在像素、视频和音频的输入空间中预测可能不是正确的方法(我们不会有意识地在像素级别预测电影中接下来会发生什么——我们的预测是对象/概念的级别)。与原始输入空间(视频、音频等)相反,通过感觉模态的输入预测可能最好在抽象表示空间中完成。),尽管不同的感官输入对于理解世界有着重要的作用——语言理解是上面已经提到的许多原因之一(结尾的附加注释考察了语言的特殊性质及其在 DL 2.0 调试中的潜在作用)。
2。在分布式表示中利用组合的力量
组合性提供了从有限的元素集合中创建更大的(指数)元素组合的能力。
DL 1.0 已经在以下方面利用了组合性的指数力量
- 分布式表示 —分布式表示中的每个特征都可以参与表示所有的概念,考虑到指数组合性。组成制图表达的特征是自动学习的。将分布式表示可视化为实值向量(浮点数/双精度数)使其具体化。向量可以是密集的(大多数槽具有非零值)或稀疏的(在退化的情况下大多数槽为零是一个热码向量)。
- DL 模型中的每一层计算都允许额外的组合性——每一层的输出都是前一层输出的组合。这种组合性在 DL 1.0 模型中被利用来学习表示的层次(例如,NLP 模型学习跨不同的不同层捕获不同比例的句法和语义相似性)
- 语言支持更高层次的组合性,这在 DL 1.0 中还没有得到充分利用。例如,语言提供了从训练分布中永远不可能得出的原创句子的能力——这并不是说它在训练分布中的概率低——它在训练分布中的概率可能是零。这是一种系统概括的形式,它超越了不符合分布(OOD)的概括。最*的语言模型可以生成连贯的新颖段落,这些段落表现出很大程度的原创性,尽管它们缺乏对潜在概念的理解,特别是当这些段落是由例如工程概念组成时。这种缺陷可能部分是由于前面提到的缺乏基础语言理解,并且可能在 DL 2.0 中实现。
- 组合性不需要局限于仅仅创造新的句子,然而(尽管语言在某种程度上仍然可以用来描述任何概念) —它可以是来自先前概念的概念的原始组合,如下图所示。

从现有数据中组合出新的概念——DL 不能像我们这样成功地做到这一点
3。丢弃 IID (独立同分布随机变量)假设
大多数 DL 1.0 模型假设任何数据样本,无论它来自训练集还是测试集,都是相互独立的,并且来自同一个分布 (IID 假设训练和测试分布都可以用同一套分布参数来描述)
从代理交互的非静态环境中的自我监督学习,由于其从变化的环境中学习的本质,需要放弃 IID 假设。
然而,即使在使用监督学习的问题中(例如,自动驾驶汽车的图像/对象分类/识别),IID 假设也可能是一种负担,因为总会有模型在训练期间从未见过的真实生活场景,错误分类可能会被证明代价高昂(在自动驾驶汽车的早期版本中已经有一些这样的实例)。虽然为训练积累的大量驾驶时间可以减少错误,但在没有 IID 假设的情况下学习的模型比通过 IID 假设学习的模型更有可能更好地处理罕见和不符合分布的情况。
放弃 IID 假设的另一个原因是通过“通过混洗数据使训练和测试数据同质”为训练模型创建数据集时的选择偏差。为了实现 IID 目标,从不同来源(包含属性差异)获得的数据都被混洗,然后分成训练集和测试集。这破坏了信息并产生虚假的相关性。例如,考虑将一幅图像分类为一头牛或一头骆驼。奶牛的照片可能都在绿色的牧场上,骆驼在沙漠里。在训练模型之后,它可能无法将沙滩上的奶牛图片分类,因为它进行了虚假的关联——将绿色景观分类为奶牛,将米色景观分类为骆驼。我们可以通过让模型学习跨不同环境的不变特征来避免这种情况。例如,我们可以在不同的绿色牧场上标记奶牛的照片,其中一个是 90%的绿色,另一个是 80%的绿色。然后,该模型可以了解到牧场和奶牛之间有着强烈但不同的相关性,应该被拒绝。但是奶牛自己允许模型识别它们,不管它们在什么环境中。因此,通过利用不同的分布来识别不变属性,而不是将它们混在一起,可以防止虚假的相关性。虽然这只是一个例子,但是,广泛地利用分布变化中的信息,并学习它们之间的不变表示,可能有助于学习健壮的表示。顺便说一句,与直接确定因果关系变量相比,对分布变化不变的变量更容易确定,这可以用作识别因果变量的方法,尽管挑战在于找出那些不变变量是什么。
一个自然产生的问题是,如果我们放弃 IID 假设,我们如何在变化的环境中准确地学习表征?
4。两种自我监督表示学习方法
- 预测输入空间接下来会发生什么。
- 在抽象空间中预测接下来会发生什么。

自我监督学习的两种方法。在左边,表征学习通过预测输入空间的缺失部分来进行。例如,对于来自视频流的自监督学习,通过使用时间 t-1 的图像来预测时间 t 的输入。预测器将时间 t-1 处的帧和潜在变量作为输入,以预测时间 t 处的帧。该模型输出由潜在变量使之成为可能的多个预测-挑选最低能量的预测对(y,y’)(在基于能量的模型中)。右边的预测发生在学习表示 c 和 h 的抽象空间中。训练目标 V 试图以某种方式将当前的 h 与过去的 c 相匹配,使得一些过去的意识状态与当前的 h 相一致。参考资料部分有这种方法的更多细节。
这两种方法并不相互排斥。一个模型有可能使用这两种方法来学习表示。
- 预测输入空间接下来会发生什么。**这通常是通过一个潜在变量来完成的,该变量封装了所有关于环境的未知信息(包括代理和代理交互),并训练一个模型来预测未来,或者等效地重建未来,并使用重建误差作为学习表示的手段。基于能量的模型是学习这种表示的一种方式。它们可以用于学习表示,使得输入(x)和输入(y)的预测/重构部分通过标量值能量函数映射到能量表面,在该能量表面,输入数据点 x 和 y 具有较低的能量。这是通过两大类方法实现的(1)第一类方法降低输入数据点 (x 及其预测 y) 的能量,同时提升所有其他点的能量(例如,在基于 能量的 GAN 中,生成器选择对比数据点——远离输入点的点)和(2) 第二类方法将输入数据点的能量约束为低(通过架构或通过某种正则化)。 如前所述,环境中的未知因素通常由潜在变量(z)捕获,该潜在变量允许通过改变 z 并挑选具有最低能量的一个预测来对 y 进行多个预测。潜在变量的信息容量受到多种方法的限制,如使用正则化子使潜在变量稀疏,添加噪声等(潜在变量的信息容量有)。这些潜在变量通常在训练期间通过使用编码器来学习,该编码器被馈送输入(x)和被预测的实际数据(y’)。然后,解码器采用潜在变量和 x (它的转换版本,其中转换由某个神经网络完成)来进行预测。能量函数用作成本函数,其标量输出然后用于训练模型以学习正确的表示。仅通过利用接收输入数据和潜在变量的解码器(编码器在实践中可用于如下所述的终身训练循环中)来进行推断。 Yann LeCun 最*的演讲深入介绍了这种方法的更多细节,并展示了这种方法如何让汽车在模拟中学习驾驶(训练数据是真实世界场景中汽车的视频记录,模型通过预测下一帧来学习,下一帧包括它自己与其他汽车在车道中的位置;成本函数考虑汽车和其他汽车之间的距离以及汽车是否停留在其车道上)。这种方法本质上是将 DL 1.0 模型重新用于重建输入的自监督任务,其中反馈信号包含非常丰富的信息(视频、音频等中的下一个图像帧)。)相对于仅仅是标量(强化学习)或者标签(自我监督学习)。
- 预测抽象空间中接下来会发生什么。这种方法基于这样的假设,即环境的变化可以用几个因果变量(捕捉为稀疏表示)来解释,这些变量是从高维表示(类似于 DL 1.0 表示的感知空间)中获得的,这些高维表示是通过来自环境的感觉流输入来学习的。这些稀疏表示用于预测未来,不是在原始输入空间中,而是在与导出它们的感知空间一致的已学习稀疏表示的空间中。这类似于我们预测/计划我们下班回家的路程——我们在一个非常稀疏的(低维)水*上做这件事——而不是在开车旅行的实际感官体验的输入空间中。预测在远离感觉流的原始输入空间的抽象空间中发生的事情具有潜在的优势,不仅学习那些利用环境中的变化的输入流的更好的表示(类似于 DL 1.0 表示),而且学习导致输入感觉流中的那些变化的表示。本质上,我们正在根据分布和 OOD 性能的变化对这些模型进行训练(学习这些表示的训练目标仍未确定,如参考部分所述)用作学习良好的低维因果表示的训练信号。假设环境的变化可以用一个低维表示法(代表一个 稀疏因子图 ),几个变量之间的无向图;在实现中,这可能不是一个显式的图,而只是一个低维表示,在下面的参考章节中进一步检查)对编码器施加约束以学习这样的表示(可能还需要附加的约束)。一些早期工作使用 DL 方法寻找变量(有向图)之间的因果关系,该方法可用于在两个随机变量 A 和 B 的联合分布 P(A,B)的两个等价因子分解之间进行选择——P(A)P(B/A)和 P(B)P(A/B ),这两个因子分解最好地捕捉了 A 和 B 之间的因果关系。具有正确因果因子分解的模型,例如 P(A)P(B/A ),更快地适应分布的变化【T25Yoshua Bengio 最*的演讲深入探讨了这种方法的更多细节。
虽然这两种方法非常不同,但它们有潜在的联系。一个是两种方法的稀疏性约束,即使通过不同的方式实现。另一个是因子图和能量函数之间的联系。变量之间的联合分布(在右表示空间)是对世界的粗略*似,可以帮助代理进行计划、推理、想象等。通过将联合分布划分为随机变量(一个变量可以在多个子集中)的小子集的函数,可以使用因子图来表示联合分布。正确的划分会造成能量函数的下降——否则它们就不值得放入因子图中。
5。注意力的作用
虽然注意力本质上是一个加权和,但当权重本身在训练和推理过程中由内容驱动动态计算时,这个简单操作的威力就显而易见了。
- 重点在哪里?**标准前馈神经网络中任何节点的输出本质上是该节点输入的加权和的非线性函数,其中权重是在训练时间学习的。相比之下,注意力允许那些权重本身被动态地计算,即使是在基于输入内容的推断期间。这使得在训练和推理期间,连接计算层的边上的静态权重能够被由注意力计算的动态权重所取代。这些动态权重是基于内容计算的。变压器架构(如 BERT)使用这种方法。例如,单词的向量表示被计算为其邻居的加权和,其中权重确定每个邻居对于计算单词的向量表示有多重要(关注哪里)—关键是这些权重是由注意头(在 BERT 模型的每一层中有多个注意头)使用句子中的所有单词动态计算的。**

****重点在哪里?该图显示了模型层中使用关注度的动态边连接,并与模型中的层进行了比较,如推理期间层之间具有静态边权重的标准 FFN。左侧:节点 X 的输出是输入的加权和,其中权重 w1、w2、w3、w4、w5 在推理期间保持相同,而不管不同的输入(A1-A5、B1-B5)。右侧:注意力模型中节点 X 的输出也是输入的加权和,但是权重本身是作为输入的函数动态计算的(在训练和推断期间)。这使得权重本身在不同的输入(A1-A5,B1-B5)之间变化,如不同颜色的虚线边缘所示。
- 什么时候聚焦?**在翻译中,给定一组由编码器计算的隐藏状态,注意力基于翻译的阶段(解码器隐藏状态)在每个时间步长(何时聚焦)中挑选不同数量的这些隐藏向量,以产生如下所示的翻译。**

****什么时候聚焦?图改编自 Jay Alammar 关于神经机器翻译的文章。编码器的输出是三个隐藏状态向量,当翻译文本被输出时,在两个解码状态(时间步长 4 和 5)期间,使用注意力(A4 和 A5)来选择三个隐藏状态向量的不同比例。
注意力(特别是“何时聚焦”的用法)在前面描述的“抽象空间中的预测”方法中起着关键作用,以聚焦于一大组表征(构成无意识空间的表征)的选择方面,用于解决有意识的任务。因果推理、最优解的规划/图形搜索都可以被实现为时间上的顺序处理,其中在每个时间步,使用注意力挑选隐藏状态(从无意识状态集合)的正确子集。将噪声注入到图遍历中的下一步(使用注意力)的选择中为解决方案的搜索添加了探索性方面(类似于 RL 中使用的蒙特卡罗树搜索)。更重要的是,这种使用正确注意力屏蔽(作为感知空间表示的函数动态计算)的顺序处理可以像我们在 DL 1.0 中对翻译任务所做的那样进行学习。注意力不仅可以用于有意识的任务解决,还可能在任务过程中以自上而下的方式影响后续的感知。这种自上而下的影响从大脑中获得灵感,其中新皮层的每个功能单元(皮质柱)(意识处理主要在这里进行)都有传入的感觉连接和传出的连接,其中一些连接到运动区。一旦输入中的某些东西吸引了我们的注意力,这些运动神经连接就有意识地将感知引导到输入流的某些部分。例如,大脑皮层处理音频输入的感觉区域与我们头部的肌肉有运动连接,一旦一个不寻常的声音吸引了我们的注意力,它就会将我们的头转向它的来源。

图来自 Yoshua Bengio 的演讲幻灯片。有意识的思想是以自下而上的方式选择的更大的无意识状态的方面,这反过来导致自上而下的对感官输入的关注
6。多时间尺度的终身学习
多时间尺度的学习和迭代优化促进了面向对象的泛化。例如,代理可以在不同的环境中学习快速适应,同时执行较慢的迭代以在它们之间进行推广。这种多时间尺度的方法是一种学习的方式。DL 1.0 的实践者通过人类完成学习来学习部分来实现同样的效果——他们围绕失败的案例不断训练监督学习模型,通过使用失败案例来扩展训练集,人类专家识别更多这样的边缘案例,然后将训练好的模型部署到字段。特斯拉是这种方法在实践中的一个例子——他们在空中无缝更新汽车,不断提高其自动驾驶能力。这种缓慢但肯定会侵蚀罕见事件分布尾部的方法是否能最终将黑天鹅事件概率降低到可以忽略不计的水*,使其不再被视为所有实际用途的危险,还有待观察。
7。架构优先
“抽象空间中的预测”方法,除了依赖于上述注意力之外,可能还需要将模型从 DL 1.0 中的向量处理机器转换到对可被称为的向量集进行操作的机器(注意力中使用的关键字服务于这种间接功能,并且可被视为变量名)并且由动态重组的神经网络模块对其进行操作。
自我监督学习的输入空间方法中的预测似乎不需要新的架构-大量的现有模型可以大致分类为基于能量的模型 (例如像 BERT 这样的语言模型是基于能量的模型)。自我监督学习在很大程度上利用了这些现有的架构。
接*人类 AI 水*的替代方法
混合方法
到目前为止,有许多混合方法的实现将 DL 1.0 与传统的符号处理和算法相结合。这些混合方法使得应用程序能够利用 DL 1.0 进行部署。因此,不能低估混合方法的重要性。所有这些混合方法,当用于决策用例(判别模型;忽略生成用例,尽管它们也有应用——生成真实感图像等。 ) ,有一个共同的特性,它们对 DL 1.0 输出执行进一步的算法处理,通常是(例外情况是图形嵌入)将 DL 1.0 输出的分布式表示简化为符号,此时组合性(符号不像我们可以用向量进行组合,我们只能将它们与更多的符号组合在一起,例如像语法树)分布式表示中固有的相关性丢失。
如果一种混合方法将 DL 输出减少到符号,然后尝试 DL 2.0 任务,如对这些符号进行推理和规划,将使我们能够达到人类水*的人工智能,这仍有待观察。这些天来,所有关于混合方法达到人类人工智能水*的潜力与徒劳的公开辩论都归结为—DL 2.0 任务可以只用符号来完成吗?或者,鉴于分布式表示为 DL 1.0 提供的优势,DL 2.0 任务一定需要分布式表示吗,即它们可以被学习,它们可以捕获相关性,并且它们允许组合性
还有更多的先验来自自然智慧?
自然智能已经启发并继续以多种方式影响人工智能的创造,首先是智能的基本计算单元(从硬件角度)—神经元(尽管人工神经元仅实现生物神经元的一个很小的,即使是关键的功能)。深度学习继续从自然智能中汲取灵感,例如多层计算提供的组合性(类似于视觉皮层处理视觉)一直到有意识任务解决的先验(Yoshua beng io 的论文 ) 。
克里斯托斯·帕帕迪米特里奥 的 2019 年论文(尽管其核心计算原语牢牢植根于生物学家实验验证的大脑计算方法,但人们可能会很快将其视为大脑的另一种计算模型 ),但凸显了上述问题的重要性——在实现自然智能的过程中,我们至少还可以借鉴一些技巧(如果不是想法的话)?
以下面概述的机制为例,一只苍蝇(它的嗅觉系统硬件和功能是一般昆虫的代表)如何学习识别气味 ( )这在克里斯特斯的演讲 ) 中有描述,只有一两个样本。称这种学习为“样本效率”是一种保守的说法——“类固醇学习”可能更恰当。
苍蝇如何学会识别气味
大约 50 个神经元感知气味,这些神经元随机投射到 2000 个神经元上,形成一个随机图,即二分图。在向量术语中,由 50 维向量捕获的气味输入被随机投射到 2000 维向量,然后由抑制性神经元强制成为具有大约 10%非零值的稀疏向量(非零值表示从超过某个阈值的放电模式活动的正态分布的尾部挑选的神经元)。这个稀疏的 2000 维向量充当了苍蝇对特定气味的记忆。

图摘自克里斯特斯·帕迪米特里奥的演讲。这是一个代表苍蝇如何识别气味的模型。他们可以记住一两次接触的气味,也有能力超越他们学到的东西进行归纳,因为他们只有大约 50 种不同的嗅觉传感器(我们有大约 500 种;老鼠大约有 1500 只)
- 这个随机投影(在硬件中实现)后面跟着一个 cap (稀疏性的运行时实施)看起来是大脑计算的一个非常基本的功能原语,我们也使用 ( 克里斯特斯的大脑模型 很大程度上是基于在自然智能的这个基本计算原语之上构建一些简单的算法运算)
- 随机投影和 cap 保持相似性(给定一些超参数的正确选择)。气味之间的相似性在它们的记忆表征中被捕获(突触权重)。记忆回忆唤起与所学重量的强度相称的点火活动。一只苍蝇有大约 50 种不同类型的嗅觉传感器(我们有大约 500 个,老鼠有 1500 个)。将气味世界映射到捕捉相似性的分布式表示的能力对于苍蝇的生存至关重要。
- 本质上,非常高的采样效率(一两次尝试学习一种气味)和非分布学习(将新气味映射到现有气味)通过这个简单的生物网络成为可能。

图摘自克里斯特斯·帕迪米特里乌的讲话,说明随机项目和 cap 保持相似性。大自然似乎已经找到了最佳的稀疏度——足够数量的神经元激活以捕捉语义相似性,同时活跃神经元的数量有限,足以区分不同的气味
苍蝇嗅觉系统设计的一个关键方面是在信息处理的所有阶段实施的稀疏表示。与 DL 模型相比,DL 模型的每个输入都会照亮整个模型,就像圣诞树上的灯一样,以不同的亮度活动(当然这有点夸张,因为[1]我们的模型通常只解决一个任务[2]在培训期间,退出限制激活等。这样做也是有原因的——许多小而弱的特征加起来会在决策中变得重要。也许从输入开始一路实施稀疏性(类似于随机投影和 cap 等操作原语)将权重更新限制在部分启用 的几个参数内(2019 年发表的一篇论文解决了这个问题;参考章节有更多详情) ,快速学习。此外,简单的权重更新(学习)“一起触发的细胞连接在一起”规则具有固有的记忆效率,当与随机投影和 cap 结合时,有助于随时间增加的泛化。DL 模型中的学习依赖于随机梯度下降和反向传播——迄今为止 DL 中学习的主干。也许我们还将对 DL 模型学习的效率进行基本的改进,超越 DL 2.0 目标从自我监督学习中获得的效果。
最后的想法
一种全新的学习方法总有可能在未来出现,它更接*人类水*的人工智能,甚至比它更好。假设曾经发生过,深度学习的一些核心成功/想法很可能被新方法所包含/吸收——在正确的语义空间中捕获相关性(DL 1.0)和因果关系(DL 2.0 目标)的分布式表示。**
确认
如今,在机器学习社区中,我们几乎认为理所当然的一件事是以关于 arXiv 和 code 的论文的形式免费获取想法。这使得像我这样的从业者能够理解并跟踪进展。我对这个领域的理解归功于机器学习社区、其研究人员和教师的开放性。
参考/附加注释

用于计算意识和无意识表征的论文的逐字摘录

从的论文中逐字摘录了学习有意识和无意识表征的合理培训目标。我们可以通过学习映射将意识状态映射到语言,本质上是用语言调试意识状态。
- 语言在 DL 2.0 中对于“调试意识任务求解”的作用。语言(忽略感知的感官形态——文本、音频等。)的特殊之处在于“单词”——构成输入数据的单位(不考虑它们是通过哪种感官形式提取的,尽管这些感官形式赋予单词丰富的上下文)与用于操纵和表达有意识思维的单位非常接*(然而,儿童可以在获得语言之前很早就执行有意识的任务解决,这表明语言是不必要的,即使它对表达思想是有效的)。我们预测某人将要表达的内容,就像当前的机器学习语言模型预测序列中的下一个单词或序列中缺失的单词一样。从这个意义上说,语言可以成为有意识任务处理的一个很好的调试工具,因为单词序列是我们大脑中有意识处理的一个很好的代理,在那里我们直接用单词操纵和表达概念。由于这个原因,DL 2.0 有意识任务解决可能不会受到 DL 1.0 任务解决的不透明性的影响,因为我们可以通过模型读取有意识任务解决,读取实现为从思想到话语的学习映射,即我们可以使用语言调试思想,假设 DL 2.0 有意识任务解决与我们进行有意识任务解决的方式一致(这个假设的有效性很大程度上依赖于我们在上面检查的有意识任务解决方法)。**
- 用于学习解开因果机制的元传递对象
- 从未知干预中学习因果变量
- 递归独立机制钢圈论文
- 关于随机图的进化。鄂尔多斯和雷尼 1960 。n 边的随机图可以通过从 v₂,…v₁的标记顶点之间的所有可能边的集合中挑选边来构建。当我们不断给随机图添加一条又一条(下图)的边时,本文检查了随机图的性质,其中每条被选取的边都不会被再次选取。

图由来自的数据组成,随机图论文。当活跃突触连接的数量大于放电神经元数量的一半时,尚不清楚大自然是否利用了随机图结构中的突然变化(找不到这方面的任何工作)。
- 曼宁教授等人的一篇 2019 论文。使用学习分布式表示(来自图像输入)的方法,然后将其映射到概念的预定离散空间(对象和对象的属性)以及它们之间的关系,以执行任务(表示问题的文本输入也被学习为分布式表示,并映射到视觉场景上的概念的相同离散空间。CNN 变体( Mask R-CNN) 用于检测场景中的对象。一旦检测到对象,就基于对象邻*度创建它们之间的有向图。使用图形注意网络来确定边之间的关系类型。由图像构成的图形代表了世界的模型。Q & A 是通过遍历这个结构化的世界模型来执行的。问题的输入单词被表示为手套嵌入。这些嵌入表示输入到 LSTM 的单词,后者输出表示句子的隐藏状态。然后通过 softmax 从有限的预定词汇表中挑选单词向量。这个向量序列用作指令序列来遍历从图像中提取的场景图。遍历(模拟推理)在给定指令向量的情况下,在每一步使用注意力来挑选感兴趣的图节点。这种监督学习模型(纯粹基于 IID 假设的学习),使用分布式表示将推理空间限制在预先确定的有限概念集内的所有方式进行处理(论文* 的第 7 部分 有更多细节)。这部作品的灵感部分来自于 意识先验论文*

数字来自 al 的曼宁教授。2019 论文— 抽象学习—神经状态机。从图中逐字描述:NSM 推理过程的可视化:给定一幅图像和一个问题(左侧),该模型首先构建一个概率场景图(蓝色方框和右侧的图像),并将问题转化为一系列指令(绿色和紫色方框,其中对于每个指令,我们在向量空间中呈现其最接*的概念(或单词)(第 3.1 节)。然后,该模型在图形上执行顺序推理,在指令的引导下关注图像场景中的相关对象节点,以迭代地计算答案
- 解释和利用对立的例子
- StyleGANs 展示了在全球范围内控制图像生成的能力(姿势、身份等)。)使用一个潜在变量,并处于一个精细的层次(头发、胡须等)。)利用随机变异。这些方法是否可以用于自我监督学习,以预测不同抽象级别(像素级别和更高抽象级别)的输出,还有待观察。
- 掌握星际争霸 2 的实时战略
- 掌握雅达利等。通过使用学习模型进行规划
- 用于大脑计算的微积分
- 规划未来几个步骤的能力并不局限于人类。动物和鸟类为未来做计划——例如回去找食物的地方,记住种子储存了多长时间,以便确定它们是否变质。
- 生物学证据支持的意识功能观。
- 用注意力可视化模型
- 论文证明生物神经网络从一两个样本中学习,2019 年 12 月
- 大脑如何学会嗅觉
- 嗅觉输入的随机收敛… 本文提供了从苍蝇感觉神经元(50 维向量)到 2000 向量记忆层的投影的邻接矩阵是随机投影的证据。神经元的连接并不在基因中编码(考虑到这样做所需的信息量,一开始就在基因中编码连接是不可行的),到在发育过程中有一些机制充当神经元迁移的指导路径,特别是对于两个半球之间的主要连接纤维束等。其余的连接很大程度上是随机的。
- 哺乳动物在感觉神经元投射到的层中具有循环连接,这使得输入的后续投射能够用于进一步的下游处理。这种能力也许是达到哺乳动物智力水*的关键先决条件。苍蝇/昆虫似乎缺乏这种形式的多层加工,而这种加工是通过重复连接实现的。
- 由 Lex Fridman 撰写的关于 DL 1.0 迄今进展的综合概述—上传于 2020 年 1 月 10 日。他演讲的幻灯片
- Lex 的演讲中提到的一篇论文解决了当前 DL 模型中从输入到输出一直缺乏稀疏性的问题。

图[来自 Lex Fridman Jan 2020 年 1 月的演讲](http://Slides of his talk)
- 2020 年 2 月 9 日图灵奖讲座由杰夫·辛顿、扬·勒昆和约舒阿·本吉奥主讲,他们在讲座中讨论了他们的最新作品。
**这篇文章是从 Quora【https://qr.ae/TJg8ov】T21手动导入的
价值 2000 美元的深度学习课程笔记本现已开源
这些笔记本构成了 fast.ai 创始人 【杰瑞米·霍华德】新书的基础,并用于一个价值 2000 美元的深度学习课程。

fast . ai 2000 美元深度学习课程
前 Kaggle 首席科学家,fast.ai 创始人,ai 教育家, 杰瑞米·霍华德 将其 AI 课程笔记本开源。这些笔记本用于他从 2020 年 3 月开始在旧金山大学教授的一门课程。
课程笔记本代码现在可以在 GitHub 上免费获得。
fastai 的书现在在 Github 中是免费的
两周前,杰瑞米·霍华德在 Github 上发布了讲稿的草稿。他在短短两天内收获 2k 星,迅速登上日趋势榜榜首。
另外,这个项目也是杰瑞米·霍华德新书与 fastai & PyTorch 合作的《程序员深度学习》的草稿,目前还没有正式发布。这相当于为您节省了 60 美元。

来源于亚马逊
虽然这本书目前处于预购状态,但它被读者寄予厚望,长期以来一直位居亚马逊计算机科学图书排行榜的第一位。
书籍内容
该书初稿已出版 20 章(包括引言和结论)。内容从最著名的人工智能“Hello Word problem”,MNIST 图像分类开始,然后是 NLP,递归神经网络,卷积神经网络和可解释性。

fastai 图书草稿内容来自 Github
本课程不适合初学者,前提是具备 Python 和 PyTorch 知识。
要在 Jupyter Notebook 中运行代码,您需要安装:
fastai v2、Graphviz、ipywidgets、matplotlib、nbdev、pandas、scikit-learn、微软 Azure 认知服务图片搜索
它们都可以通过 PyPI 直接安装。
这个 fastbook 不仅仅是一本教材,更是一个 AI 社区资源。在最后的留言里,作者希望每一个完成这本书的人,和大家交流成功的经验。
版权
最后,提到版权是非常重要的。
从 2020 年开始,fastbook 项目中的所有内容都是杰瑞米·霍华德和西尔万·古格的版权。
笔记本和 python .py文件中的代码受 GPL v3 许可证的保护。其余部分(包括笔记本和其他散文中的所有减价单元格)未经许可不得进行任何形式或媒体的再分发或更改,除非复制笔记本或分叉此回购供您私人使用。禁止商业或广播使用。
这是来自杰瑞米·霍华德的关于开源和版权的信息
如果您看到有人在其他地方托管这些材料的副本,请让他们知道他们的行为是不允许的,并可能导致法律诉讼。此外,他们会伤害社区,因为如果人们忽视我们的版权,我们就不太可能以这种方式发布额外的材料。
杰瑞米·霍华德,来自 fastbook 自述
尽情享受吧!
以下是链接
- fastbook 项目:https://github.com/fastai/fastbook
- 课程:https://www . usfca . edu/data-institute/certificates/deep-learning-part-one
用 TensorFlow 建模,在 Google 云*台上服务
实用指南
在可扩展的云*台上服务 TensorFlow 模型

在本指南中,我们学习如何开发一个 TensorFlow 模型,并在谷歌云*台(GCP)上提供服务。我们考虑使用 TensorFlow 和 Keras APIs 实现的三层神经网络来预测产品收益的回归问题。
本指南的主要学习成果是
- 在 Tensorflow 中建立、编译和拟合模型
- 在 Google colab 中设置 tensorboard
- 保存、加载和预测看不见的数据
- 在 Google 云*台上部署 TensorFlow 模型
在本指南中,我们将使用 TensorFlow 2.1.0 和 Google colab 运行时环境。我们将使用 google colab 来训练使用 TensorFlow 和 Keras APIS 的模型。从 TensorFlow 2.0 开始,Keras 现在是 TensorFlow 包的一部分。Google colab 在免费的 GPU 和 TPU 上提供机器学习模型的训练。因此,建议环境获得在 GPU 和 TPU 上训练您的深度学习模型的实践经验。而且可以设置 tensorboard,更好的了解模型训练。本指南附带了一个 Google colab 的工作副本,可以帮助您快速入门。
# Install TensorFlow >2.0
!pip install tensorflow==2.1.0
导入必要的 python 库以及 TensorFlow 和 Keras 函数
# Import libraries
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
import os
import numpy as np
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model
from tensorflow.keras.models import Sequential, load_model
加载张量板扩展
# Load tensorboard
%load_ext tensorboard
为数据安装 Gdrive
要在 Google colab 环境中访问数据,有多种方法。我最喜欢的一个方法是将数据上传到你的 Google Drive,然后在 colab 中安装 Google Drive。
可以从 data_deep_learning 下载用于训练和测试的数据。可以尝试其他开源数据集试试。
我们需要安装 google drive 来读取存储在 google drive 中的数据。下面是最简单的安装方法。您将被要求输入访问过程生成的令牌。你可以参考文章《使用 Google Colab GPU VM + Drive 作为长期深度学习训练运行的持久存储》了解更多关于使用 Google drive 作为 Colab 的数据存储的信息。
我已经把数据上传到我的 google drive 上,以便于访问。你可以照着做。
from google.colab import drive
drive.mount('/content/drive')Go to this URL in a browser:
Enter your authorization code:
··········
Mounted at /content/drive
加载培训和验证数据
我已经将培训和验证数据上传到我的 google drive。出于练习的目的,您可以尝试任何其他开源数据。对于本教程,数据已经准备好进入训练集和测试集,但是在实际问题中,最有可能的是数据必须逐个任务地清理和准备。在我看来,机器学习科学家几乎 50%的工作是准备与机器学习模型兼容的数据
确保培训、有效和测试拆分中没有信息泄漏。
最*,杰森·布朗利在他的网站【https://machinelearningmastery.com/blog/. 发表了一系列关于数据准备的文章
# I have already uploaded the data to my google drive
data_path= '/content/drive/My Drive/data_deep_learning_tensorflow/'
output_dir = '/content/drive/My Drive/Deep_Learning_Course/Ex_Files_Building_Deep_Learning_Apps/'
阅读我们问题的训练和测试数据。目标是预测给定产品的总收入,给出下列特征。
# Reading the traing and test data
training_data_df = pd.read_csv(data_path + 'sales_data_training.csv')
test_data_df = pd.read_csv(data_path + 'sales_data_test.csv')training_data_df.head()

标准化要素数据
标准化是大多数机器学习模型的推荐做法,并已被证明是可行的。Scikit-learn 附带了一些业界信任的转换,用于预处理数据。
MinMaxScaler 是 Scikit-learn 转换模块中实现的常用转换之一。它在 0 和 1 之间缩放数据。在输入张量流模型训练之前,建议对训练和测试数据进行归一化。
scalar = MinMaxScaler(feature_range=(0,1))
scaled_training = scalar.fit_transform(training_data_df)
scaled_test = scalar.fit_transform(test_data_df)
scaled_training_df = pd.DataFrame(data = scaled_training, columns=training_data_df.columns)
scaled_test_df = pd.DataFrame(data = scaled_test, columns=training_data_df.columns)
让我们来看看缩放后的数据
scaled_training_df.head()

对于有监督的机器学习模型,我们将特征和目标分成X和y NumPy 数组。TensorFlow 模型也是如此,使用这种格式的数据。
# Splitting the feature and target columns. Using this dataset, we aim to predict total_earnings
X = scaled_training_df.drop('total_earnings', axis=1).values
Y = scaled_training_df['total_earnings'].values
用 Keras 顺序 API 定义张量流模型
为了定义深度学习模型,我们使用 TensorFlow 2.1.0 附带的 Keras API 模块。我们从一个具有两个中间 relu 层的基本模型开始。输入维度是 9,输出维度是 1。
# Define the Model
model = Sequential()
model.add(Dense(50, input_dim=9, activation = 'relu'))
model.add(Dense(100, activation = 'relu'))
model.add(Dense(50, activation = 'relu'))
model.add(Dense(1, activation = 'linear'))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
显示定义的模型摘要
model.summary()Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_4 (Dense) (None, 50) 500
_________________________________________________________________
dense_5 (Dense) (None, 100) 5100
_________________________________________________________________
dense_6 (Dense) (None, 50) 5050
_________________________________________________________________
dense_7 (Dense) (None, 1) 51
=================================================================
Total params: 10,701
Trainable params: 10,701
Non-trainable params: 0
_________________________________________________________________
准备类似于训练数据的测试特征和目标
X_test = scaled_test_df.drop('total_earnings', axis=1).values
Y_test = scaled_test_df['total_earnings'].values
为 tensorboard 安排复试
# Setup for tensorboard
from datetime import datetime
logdir="logs/scalars/" + datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=logdir)
用verbose=0和epochs=50训练模型,并将测试数据作为验证集。
# Train the network
training_history = model.fit(X, Y,
epochs = 50,
shuffle=True,
verbose=0,
validation_data=(X_test, Y_test),
callbacks=[tensorboard_callback])
print("Average test loss: ", np.average(training_history.history['loss']))Average test loss: 0.0003906410974522077
让我们在 tensorboard 中显示训练/验证错误
# Click on the view output full screen from dropdown cell menu if tensorboard does not show up itself
%tensorboard --logdir logs/scalars

验证结果
训练的验证是任何机器学习框架中非常重要的步骤之一。这里,我们互换使用验证/测试错误。
test_error_rate = model.evaluate(X_test,
Y_test,
verbose=0)
print('The mean squared error for test data is {}'.format(test_error_rate))The mean squared error for test data is 0.09696226567029953
对看不见的数据进行预测并保存模型
让我们读取样本输入数据并测试我们的模型,以预测并在本地保存模型供将来使用。
# Read the values of features for new product and test on our traioned model
df_new_products = pd.read_csv(data_path + 'proposed_new_product.csv').values# Use our trained moel to predict
predictions = model.predict(df_new_products)# Scaling up the earnings prediction using our Normalisation Parameters
predictions = predictions + 0.1159
predictions = predictions/0.0000036968
print('Earnings predictions for Proposed product - ${}'.format(predictions))Earnings predictions for Proposed product - $[[270639.12]]# Save the Model
model.save(output_dir + 'trained_model.h5')
print('Trained Model saved at {}'.format(output_dir))Trained Model saved at /content/drive/My Drive/Deep_Learning_Course/Ex_Files_Building_Deep_Learning_Apps/
检索已保存的预测模型
一旦我们对模型感到满意,我们就可以在本地保存这个模型,并且可以用来对看不见的数据进行预测。这个模型可以托管在云上,你可以发送输入数据来获得预测。
# Importing saved model
model_trained = load_model(output_dir + 'trained_model.h5')# Read the values of features for new product and test on our traioned model
df_new_products = pd.read_csv(data_path + 'proposed_new_product.csv').valuespredictions = model_trained.predict(df_new_products)
predictions = predictions + 0.1159
predictions = predictions/0.0000036968
print('Earnings predictions for Proposed product - ${}'.format(predictions))Earnings predictions for Proposed product - $[[270639.12]]
在 Google Cloud 上部署训练模型
一旦我们有了训练好的模型,下一个任务就是部署它来为客户服务。有各种可用的部署选项,但在这一节中,我们重点关注在谷歌云人工智能*台上部署它。
先决条件
在 google cloud 上部署 TensorFlow 模型的先决条件是
- 熟悉谷歌云项目
- 基本了解存储桶和 it
gsutils命令行工具 - 基本了解与谷歌云交互的
gcloud命令行工具 - 经过训练的 Tensorflow 2.1.0 模型
- 阅读下面的指南,了解如何部署机器学习模型的详细信息
通过 colab 验证您的 google 帐户
from google.colab import auth
auth.authenticate_user()
创建一个谷歌云项目,如果没有做之前和存储模型桶。
# GCP project name
CLOUD_PROJECT = 'gcpessentials-rz'
BUCKET = 'gs://' + CLOUD_PROJECT + '-tf2-models'
将所需的项目设置为在 colab 环境中使用的默认环境变量。
# Set the gcloud consol to $CLOUD_PROJECT 9Environment Variable for your Desired Project)
!gcloud config set project $CLOUD_PROJECTUpdated property [core/project].
使用gsutil命令行实用程序创建 Bucket。您可以使用 python API 来创建存储桶。现在让我们坚持使用命令行方法。
# Create the storage bucket for tf2 Models
!gsutil mb $BUCKET
print(BUCKET)Creating gs://gcpessentials-rz-tf2-models/...
gs://gcpessentials-rz-tf2-models
将 TensorFlow 模型保存到刚刚创建的存储桶中。您可以确认模型文件是从 google 控制台图形用户界面上传的。
MODEL = 'earnings-prediction'
model.save(BUCKET + f'/{MODEL}', save_format='tf')WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow_core/python/ops/resource_variable_ops.py:1786: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
INFO:tensorflow:Assets written to: gs://gcpessentials-rz-tf2-models/earnings-prediction/assets
服务于模型的配置
有两种方法可以设置在 google cloud 上服务的模型。第一个是使用 GCP 图形控制台,另一个是使用 gcloud 命令行工具,如如何在云 AI *台上部署 TensorFlow 2 模型中所述。我跟随 GCP 控制台进行了这次部署。一些关键点
- 确保您的模型数据上传到存储桶中
- 建议对您的模型和存储桶使用相同的区域(有时会产生问题)。
- 请耐心等待,创建模型/版本可能需要几分钟时间
- 第一次做的时候,仔细阅读所有的说明
!gcloud ai-platform versions create $VERSION \
--model $MODEL \
--origin $MODEL_DIR \
--runtime-version=2.1 \
--framework='tensorflow' \
--python-version=3.7
获取已部署模型的预测
一旦部署了模型,并且您可以看到绿色的勾号,就该测试模型的预测了。一些需要考虑的要点。
- 使用测试&测试模型预测使用您的版本或模型选项卡下的选项卡。
- 输入 JSON 数据取决于您如何定义您的模型
# [Reference](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/ml_engine/online_prediction/predict.py)
import googleapiclient.discovery
def predict_json(project, model, instances, version=None):
service = googleapiclient.discovery.build('ml', 'v1')
name = 'projects/{}/models/{}'.format(project, model)
if version is not None:
name += '/versions/{}'.format(version)
response = service.projects().predict(
name=name,
body={'instances': instances}
).execute()
if 'error' in response:
raise RuntimeError(response['error'])
return response['predictions']
加载看不见的数据进行预测
df_new_products = pd.read_csv(data_path + 'proposed_new_product.csv')df_new_products

将数据转换成 JSON 格式,以便与上面写的predict_json程序兼容。
tdata_instances = {'dense_input':df_new_products.values[0].tolist()}predictions_gcloud = predict_json(CLOUD_PROJECT, 'earnings_prediction', tdata_instances, version='v1')
predictions_gcloud = predictions_gcloud[0]['dense_3'][0] + 0.1159
predictions_gcloud = predictions_gcloud/0.0000036968
print('Earnings predictions for Proposed product - ${}'.format(predictions_gcloud))Earnings predictions for Proposed product - $261848.21778936993
谷歌 Colab 笔记本
按照下面的谷歌合作笔记本来复制和实践这个指南。
结论
在本指南中,我们学习了使用 TensorFlow 2.1.0 训练深度学习模型,并将训练好的模型部署在谷歌云*台上。以下是指南的重点。
- 安装 TensorFlow 2.1..google colab 中的 0
- 在 google colab 中设置 tensorboard
- 使用 TensorFlow 构建、编译和训练模型
- 评估并保存训练好的模型
- 加载已保存的模型以根据看不见的数据进行预测
- 在 Google Cloud 上部署模型
- 使用云中部署的模型进行预测
参考资料/阅读/链接
- https://blog . tensor flow . org/2020/04/how-to-deploy-tensor flow-2-models-on-cloud-ai-platform . html
- https://scikit-learn.org/stable/modules/preprocessing.html
- 【https://www.tensorflow.org/tutorials/keras/regression
- https://www.tensorflow.org/tutorials/keras/save_and_load
借助 Fluent Tensorflow Extended 简化深度学习端到端管道
快速 api 概述和 fluent-tfx 的自包含示例
如果这种生产 e2e ML 管道的事情对你来说似乎是新的,请先阅读 TFX 指南。
另一方面,如果你以前用过 TFX,或者计划部署一个机器学习模型,那你就找对地方了。

但是 Tensorflow Extended 已经完全有能力自己建设 e2e 管道,为什么还要麻烦使用另一个 API 呢?
- 冗长的代码定义。实际的预处理和训练代码可能与实际的管道组件定义一样长。
- 缺乏合理的违约。您必须手动指定所有东西的输入和输出。这一方面提供了最大的灵活性,但在其他 99%的情况下,大多数 io 都可以自动连接。例如,您的预处理组件可能会读取您的第一个输入组件的输入,并将输出传递给培训。
- 太多样板代码。通过 TFX CLI 搭建可在 4-5 个目录中生成 15-20 个文件。
更易于使用的 API 层的优势
- 流畅紧凑的管道定义和运行时配置。不再需要在构建管道的 300 多行庞大的函数中滚动
- 没有脚手架,很容易通过使用几行代码来设置
- 额外的有用的工具,以加快常见的任务,如数据输入,TFX 组件建设和布线
- 合理的默认值和 99% —合适的组件 IO 接线
声明:我是fluent-tfx的作者
通过示例进行 API 概述
这本质上是fluent-tfx/examples/usage _ guide/simple _ e2e . py,但是请继续读下去。
如果你已经了解 TFX 的基本情况,滚动到管道建设。
数据输入
文件data/data.csv实质上是 4 列:a, b, c, lbl。a和b是随机采样的浮点,c是二进制特征(0或1))lbl是二进制标签(值0或1)。那是个玩具问题,只是为了演示。
模型代码
工程师或“用户”提供预处理、模型构建、超参数搜索和保存带有正确签名的模型的功能。我们将展示如何在另一个文件中轻松定义这些函数(比如 model_code.py )
我们将利用 TFX 的所有优势来完成大部分工作。
keras Tuner和 TFX 调谐器——用于超参数搜索和建模的训练器:
管道建设
构建管道并不简单:提供一些带有 Tensorflow 模型分析的评估配置,只需使用fluent-tfx;
滑行装置
在 TFX 支持的不同管道上运行管道不需要额外的努力,也不需要额外的依赖:PipelineDef生产一个普通的 TFX 管道。
但是,如果您在管道函数中使用ftfx工具,请确保将这个包包含在 requirements.txt beam 参数中。
附录:自由度和限制
自定义组件在很大程度上受到支持,但是仍然会有一些边缘情况,这些情况只适用于冗长简单的旧 TFX api。
假设与组件 DAG 布线、路径和命名相关。
路径
PipelineDef需要一个pipeline_name和一个可选的bucket路径。- 二进制/临时/暂存工件存储在
{bucket}/{name}/staging下 - 除非另有说明,否则默认 ml 元数据 sqlite 路径设置为
{bucket}/{name}/metadata.db bucket默认为./bucket- 推进者的
relative_push_uri将模型发布到{bucket}/{name}/{relative_push_uri}
组件 IO 和名称
- 一个输入,或者一个
example_gen组件提供.tfrecord给下一个组件(可能是 gzipped 格式) - 流畅的 TFX 遵循 TFX 命名的默认组件的一切。当提供定制组件时,确保输入和输出与 TFX 相同。
- 例如,您的定制
example_gen组件应该有一个.outputs['examples']属性 - 当使用来自
input_builders的额外组件时,确保您提供的名称不会覆盖默认值,例如标准 tfx 组件名称snake_case和{name}_examples_provider、user_{x}_importer。
元件接线默认
- 如果提供了用户提供的模式 uri,它将用于数据验证、转换等。如果声明的话,生成的模式组件仍然会生成工件
- 如果用户没有提供模型评估步骤,它将不会被连线到推送器
- 默认训练输入源是转换输出。用户可以指定他是否想要原始 tf 记录
- 如果指定了超参数并声明了 tuner,tuner 仍将测试配置并生成超参数工件,但将使用提供的超参数
谢谢你一直读到最后!如果这种生产 ML 管道的事情对你来说似乎是新的,请阅读 TFX 指南。
使用深度学习的颅内出血检测
了解我们为脑出血分类而进行的一系列实验。

来源:https://swdic.com/radiology-services/mri-brain.php
本文由 Prajakta Phadke 合著
在过去十年中,深度学习在医疗应用中的使用增加了很多。无论是使用视网膜病变识别糖尿病,从胸部 x 光片中预测
肺炎还是使用图像分割计数细胞和测量器官,深度学习都在无处不在。从业者可以免费获得数据集来建立模型。
在本文中,您将了解我们在使用脑部核磁共振成像时进行的一系列实验。这些实验可以在 Github 上作为一系列笔记本获得。

以这种方式给笔记本编号的原因是为了让其他人能够系统地浏览它们,看看我们采取了哪些步骤,我们得到了哪些中间结果,以及我们在此过程中做出了哪些决定。我们不是提供一个最终的抛光笔记本,而是想展示一个项目中的所有工作,因为这才是真正的学习所在。
该库还包括有用的链接,链接到领域知识的博客、研究论文和所有我们训练过的模型。我建议每个人都使用这个库,自己运行每一个笔记本,理解每一点代码是做什么的,为什么要写,怎么写。
让我们来看看每一个笔记本。所有这些笔记本都是在 Kaggle 或谷歌联合实验室上运行的。
00_setup.ipynb
本笔记本包含在 Google colaboratory 上下载和解压缩数据的步骤。在 Kaggle 上,你可以直接访问数据。
01_data_cleaning.ipynb
对于这个项目,我们使用了杰瑞米·霍华德的干净数据集。他有一个笔记本,上面记录了他清理数据的步骤。我们在笔记本上复制了其中的一些步骤。一般来说,在深度学习中,快速清理数据以进行快速原型制作是一个好主意。
数据以 dicom 文件的形式提供,这是医疗数据的标准扩展。我们来看看其中一个的内容。

除了图像,它还包含一堆机器记录的元数据。我们可以使用这些元数据来深入了解我们的扫描。因此,我们将它们保存在数据帧中(因为 dicoms 访问和使用太慢)。

查看包含许多列的数据帧的头部的一个有用的技巧是转置它。
现在让我们来看一些图片。

我们看到我们有一个人从头顶到牙齿的大脑不同切片的图像。这就是大脑扫描是如何从上到下进行的。有时顶部或底部切片可以是完全黑色的(面部之前或之后的切片)。这样的切片对我们的模型没有用,应该被删除。
元数据中有一个称为img_pct_window的有用栏,它告诉我们大脑窗口中像素的百分比。如果我们绘制该列,我们会得到下图:

我们看到很多图像在大脑窗口几乎没有任何像素。因此,我们丢弃这样的图像。如果我们看一些我们丢弃的图像

我们看到它们是牙齿开始出现的较早或较晚的。
数据清理过程的第二步是修复RescaleIntercept列。关于这方面的更多信息,请参考杰里米的笔记本。最后,我们中心作物(以消除背景)和调整图像的大小为(256,256)。虽然高质量的图像会给出更好的精度,但这个尺寸对于原型来说已经足够了。
02 _ data _ exploration . ipynb
既然我们已经清理了数据,我们可以稍微研究一下。我们将分两个阶段进行建模。在第一阶段,我们只预测一个人是否有出血。
我们从检查空值开始。标签数据框没有空值,而元数据数据框有一些几乎完全为空的列。我们可以安全地删除这些列。
然后我们继续检查目标变量。

我们有一个非常*衡的数据集。医学数据集通常不是这种情况。它们通常是不*衡的,正类样本的数量远少于负类样本的数量。
接下来,我们检查每个子类别的数量。

硬膜下出血似乎是最常见的出血类型。元数据中一个有趣的列是“存储的位数”列,它表示用于存储数据的位数。它有两个不同的值:12 和 16。

这可能表明来自两个不同的组织。在深度学习中,通常建议使用来自相同分布的数据。最后,我们可以在不同的窗口中查看我们的图像。

然而,这只是针对人类的感知。神经网络可以处理浮点数据,并且不需要任何窗口。
03 _ data _ augmentation . ipynb
训练一个好的深度学习模型的第一步是获取足够的数据。然而,这并不总是可能的。然而有可能的是,对数据进行一些转换。
我们所做的是,不是每次都给模型提供相同的图片,而是做一些小的随机变换(一点旋转、缩放、*移等),这些变换不会改变图像内部的内容(对于人眼而言),但会改变其像素值。用数据扩充训练的模型将更好地概括。
在本笔记本中,我们在数据集上尝试了一些转换,看看它们是否有意义。还要注意,这些转换只应用于训练集。我们在验证集上应用非常简单的变换。
有点像空翻

或者轻微旋转

有意义,但是其他一些转换可能一点用都没有,因为它们不像实际的数据。

另请注意,我们已经裁剪和调整大小,所以我们不会这样做。
05_metadata.ipynb
最*的研究表明,元数据可以证明是有用的图像分类。我们可以通过*均预测来实现,或者将两个数据输入神经网络。
为了做到这一点,我们首先尝试仅使用元数据来对出血进行分类,以衡量其有用性。我们发现,即使使用像随机森林这样的健壮模型,我们也只能得到 50%的准确率。因此,我们决定放弃元数据,专注于图像本身。

04_baseline_model.ipynb
对于我们的基线模型,我们从一个 resnet18 作为主干开始,并在其上附加一个自定义头。迁移学习在图像分类方面表现出了良好的效果。它提供了更好的结果,更快的培训,并大大减少了资源消耗。
然而,对于像医学图像这样的东西,没有可用的预训练模型。因此我们用 resnet 来凑合。我们在这个笔记本中训练两个模型,一个有和没有预训练。在这两个模型中,我们能够在仅仅 5 个时期内达到大约 89%的准确度。

batch_size被设置为 256。我们使用 Leslie Smith 的学习率查找器,在训练中找到一个好的学习率。

简单地说,我们可以对我们的数据进行模拟训练,将我们的学习率从非常低的值变化到高达 10 的值。然后,我们计算损失,并将其与学习率进行对比。然后,我们选择具有最大下降斜率的学习速率。
在这种情况下,我们可以选择类似于3e-3的东西,因为1e-1和1e-2处于边缘,损耗很容易激增。我们也可以用一个切片来表示我们的学习率,例如1e-5 to 1e-3。在这种情况下,不同的学习率将适用于我们网络的不同群体。
对于训练,我们首先冻结模型的预训练部分,只训练新的头部。但是,我们确实更新了 resnet 的 batchnorm 层,以保持每层的*均值为 0,标准偏差为 1。
损失图如下所示。

然后我们可以展示一些结果。

红色的是我们的模型分类错误的。
暂时就这样了。在我结束这篇文章之前,我想给出一个非常重要的提示:“在训练模型时不要设置随机种子,每次都让它在不同的数据集上训练。这将有助于您了解您的模型有多稳健。”
这篇文章和项目是一项正在进行中的工作,在下一阶段,你会看到以下笔记本。在那之前,祝你快乐。
接下来…
06 _ multi label _ classification . ipynb
可视化您的模型在分类时关注的图像部分。继续对出血的子类进行分类。一幅图像可以有一种或多种出血类型。
07 _ 不同 _archs.ipynb
因为我们已经认识到元数据对我们的应用程序并没有真正的用处,所以我们尝试了各种架构,比如 resnet34、resnet50、alexnet、densenet 等等。
08 _ 混合 _ 精确 _ 训练. ipynb
我们也使用混合精度训练来降低训练时间。
09 _ 锦囊妙计. ipynb
我们使用了魔术袋研究论文中的一些技巧。像渐进的图像大小调整。我们还试验了批量大小,我们试图尽可能地增加它。批量越大,更新效果越好。
10 _ 测试 _ 和 _ 部署. ipynb
测试时间增加,用于测试的查询数据集和用于部署的简单网站。
计算机视觉的深度学习
理解 CNN 的卷积层、池层和全连接层
计算机视觉中的深度学习在短时间内取得了快速进展。深度学习在计算机视觉中的一些应用包括人脸识别系统、自动驾驶汽车等。
本文介绍了卷积神经网络,也称为 convnets ,这是一种广泛用于计算机视觉应用的深度学习模型。我们将深入了解它的组件、卷积层、池层和全连接层等层,以及如何应用它们来解决各种问题。
所以让我们开始吧。
有线电视新闻网的目标:

猫
上面是一只猫的图片,小时候我们被告知这种动物是猫。随着我们长大,学习和看到更多猫的图像,我们的大脑记录了它的各种特征,如眼睛、耳朵、面部结构、胡须等。下一次我们看到具有这些特征的动物图像时,我们能够预测它是一只猫,因为这是我们从经验中学到的。
现在我们需要在计算机上模拟同样的行为。这类问题在计算机视觉中被称为图像分类问题,我们试图识别图像中存在的对象。
给定一幅图像,首先计算机应该能够提取它的特征,然后根据这些特征,预测那个物体是什么。他们如何实现这一目标?嗯,简单的答案是通过 CNN。他们是如何做到这一点的,我们将深入探讨。
CNN 简介:
因此,CNN 的目标是执行两个任务:第一个是特征提取,第二个是聚集所有提取的特征并基于它进行预测。
在我们深入研究各个组件之前,让我们看看 CNN 是什么样子的。

描绘 Conv、池化和全连接层的 CNN 架构示例来源:https://www . learnopencv . com/WP-content/uploads/2017/11/CNN-schema 1 . jpg
从上图中,我们可以看到三种类型的层,分别是:卷积层、汇聚层和全连接层。(我们将在接下来的章节中讨论这些)
如果上面的图片没有完全理解,那也没关系。我们看到这一点的原因是为了在脑海中想象 CNN 是什么样子,这样一旦我们理解了它的各个层次,我们就可以很容易地将这些点联系起来。
卷积运算:
卷积是细胞神经网络的基本构件之一。卷积运算的主要目的是从输入图像中提取边缘、曲线、拐角、梯度方向等特征。我们将通过一个边缘检测示例来理解卷积运算。
给定一幅图像,我们想要提取该图像中所有的水*和垂直边缘。下图描述了同样的情况。

卷积运算的例子
假设我们有一个 6x6 的灰度图像。现在,为了检测图像中的边缘,我们构建了一个 3x3 的矩阵。在 CNN 的术语中,它被称为过滤器或内核。使用这两个矩阵,我们将执行卷积运算。结果矩阵,即卷积运算的输出将是大小为 4×4 的矩阵。下图描述了同样的情况。

卷积运算的例子
现在,我们如何计算得到的 4x4 矩阵的元素如下:
为了计算左上角的元素,我们将使用 3x3 滤镜并将其粘贴到原始输入图像的 3x3 区域的顶部。接下来,我们将做元素方面的乘积来给出我们想要的值。

接下来,为了计算第二个元素,我们将滤波器(即黄色方块)向右移动一步,进行相同的元素乘积,然后将它们相加。同样,我们可以填充该行的所有元素。

向右滑动过滤器一步以获得所需的值
现在,为了获得下一行中的元素,我们将把过滤器向下移动到下一行,重复相同的元素级乘积,并将它们相加。因此,我们可以同样地填充其余的元素。下面向我们展示了最终的结果。

卷积运算
这里有几点。当使用 3×3 矩阵进行卷积时,6×6 矩阵得到 4×4 矩阵。这些本质上是矩阵。但是左边的矩阵便于解释为输入图像,中间的一个解释为滤波器,右边的一个解释为输出特征。
输出特征尺寸的计算如下:
n x n input image f x f filter**output dimension = (n - f + 1)**Above example: 6 x 6 input image 3 x 3 filter
(6 - 3 + 1) x (6 - 3 + 1)
output dimensions = 4 x 4
注意:我们的过滤器的值通常被称为权重。我们如何决定重量值是在训练中学到的。它们用一些随机值初始化,并随着每个训练步骤不断调整。
填料
每次执行卷积运算时,我们都会丢失边界像素中的一些信息。此外,我们的形象缩小了一点。有时,我们会希望减少输出大小,以节省训练期间的资源消耗。然而,有时我们可能希望保持输出和输入的空间维度不变。为此,我们可以使用填充的概念。
填充只是在输入要素的每一侧添加适当数量的行和列。填充实质上使过滤器产生的特征图与原始图像的大小相同。

带填充的卷积,p = 1 来源:https://github.com/vdumoulin/conv_arithmetic
在图(左)中,一个尺寸为 5x5 的蓝色正方形代表我们的输入图像,它通过在每边添加几行零来填充。当使用 3×3 滤波器进行卷积时,输出维数与输入维数相同,即 5×5,如绿色方块所示。如果我们没有使用填充,输出尺寸将是 3x3。因此,填充 1 保持了输入和输出的空间维度相同。
有效且相同的填充
让我们根据是否添加填充来理解术语。
有效:当卷积期间没有添加填充,并且我们的结果输出是收缩尺寸时。示例:
Input size: 6 x 6 (i x i)
Filter size: 3 x 3 (f x f)
Output size: (i – f + 1)
(6 – 3 + 1) = 4
= 4 x 4
相同:添加填充,使输出尺寸与输入尺寸相同时。为了计算输出尺寸,我们对上面的公式进行了修改,以考虑填充参数。示例:
Input size: 6 x 6 (i x i)
Filter size: 3 x 3 (f x f)
Padding: 1 (p)
Output size: **(i + 2p - f +1)**
(6 + 2x1 – 3 + 1) = 6
= 6 x 6
注意:按照惯例,滤波器尺寸 f 通常是奇数,否则填充将是不对称的。一些最常用的过滤器尺寸为 3x3、5x5 和 1x1。
阔步
在我们的工作示例中,为了计算下一个元素,我们将过滤器向右移动一位。我们在输入图像上移动过滤器的行数是我们的步幅参数。
跨距定义了遍历图像时滤波器的步长。默认情况下,在任何框架中它都可能是 1。

步幅 s = 2 的卷积来源:https://github.com/vdumoulin/conv_arithmetic
在左图中,一个 5x5 的蓝色方块代表我们的输入图像。使用 3x3 滤波器进行卷积时,步长值为 2,我们得到了尺寸为 2x2 的下采样输出图。如果我们保持 stride 为 1,输出维度将是 3x3。
因此,我们可以在训练中增加步幅(步)长度以节省空间或减少计算时间。然而,当这样做时,我们将放弃一些信息,因此这是资源消耗(无论是 CPU 还是内存)和从输入中检索信息之间的权衡。
注意:一般来说,我们通常将步幅值保持为 1,并使用其他方法对我们的特征地图进行下采样,如使用池图层。
卷积运算概述:
卷积运算的主要目的是从输入图像中提取有意义的信息,如边缘、曲线等。下面的动画总结了卷积运算中元素的计算方式。

卷积运算概述
以下等式总结了输出要素地图的尺寸。

公式
使用上述等式的示例:
**6x6** input image, **3x3** filter | **7x7** input image, **3x3** filter
padding **p=1** & stride, **s=1** | padding **p=1** & stride, **s=2**
|
|
Output size: | Output size:
(6 + 2*1 – 3)/1 + 1 = 6 | (7 + 2*1 - 3)/2 = 4
**6 x 6** | **4 x 4**
体积卷积:
我们已经完成了矩阵的卷积运算。现在让我们了解如何对体积执行卷积运算,这将使它更加强大。以前我们有一个 6x6 的灰度图像。现在,让我们假设我们有一个 6x6 的 RGB 图像,因此它的尺寸将为 6x6x3,而不是 3x3 的滤镜,这次我们将使用 3x3x3 的滤镜。
输出大小仍为 4x4(与之前相同),但是,元素的计算方法是在每个通道中执行元素乘积,然后将它们相加,如下所示:

体积卷积:每个通道中的元素乘积,然后将它们相加。来源:https://indoml . com/2018/03/07/student-notes-convolutionary-neural-networks-CNN-introduction/
这里需要注意的一点是,输入和滤波器中的通道数必须相等。我们这样做的原因是,它允许我们在不同通道上使用不同的滤波器,比如在所有通道中使用边缘检测器,以提取更有意义的信息。所以想法是一样的。在输出要素地图中获取尽可能多的信息。
注意:过滤器中的通道数通常没有明确规定。假设它等于输入的深度。例如,如果我们有一个尺寸为 26x26x64 的输入,我们使用一个尺寸为 3x3 的滤波器进行卷积,这意味着滤波器中的通道数将为 64,因此其实际尺寸为 3x3x64。
使用多个过滤器的卷积:
现在我们知道如何对体积进行卷积,那么增加滤波器的数量怎么样?每个过滤器提取一些特征,像一个是提取垂直边缘,另一个是水*或 45 度线等。换句话说,扩展卷积以使用多个滤波器。
扩展我们的工作示例,我们仍然有一个 6x6x3 的输入。现在,我们有两个 3x3 维度的过滤器,而不是一个(深度为 3 是隐含的)。使用每个滤波器以类似的方式执行卷积操作。因此,我们将获得两个 4x4 输出特征地图。将一个堆叠在另一个之上,我们可以说输出尺寸为 4x4x2,如下所示:

使用 2 个滤波器的卷积。输出是两个 4x4 特征地图。每个过滤器一个来源:https://indoml . com/2018/03/07/student-notes-convolutionary-neural-networks-CNN-introduction/
因此,我们现在可以根据过滤器的数量来检测多个特征。卷积的真正力量得到了释放,因为现在我们可以从输入中提取大量的语义信息。
让我们考虑一个例子来理解多个过滤器中存在的值(权重)的数量:
Input Volume dimensions: **26x26x64**
filter Size: **3x3**(since input depth=64, filter depth will also be 64)
and we have **32** such filters being used for feature extraction**Hence, total number of weights in our filter will be:**
weights in one filter = **3 x 3 x 64 = 576**
Total filters = **32**
Total weights = **32 x 576 = 18,432**
这都是关于卷积运算的。现在让我们看看 CNN 中的典型卷积层是什么样子的:
卷积层:
在上面的例子中,我们得到了两个 4x4 的输出图。现在,我们将为每个输出图添加一个偏差。偏差是一个实数,我们将它添加到每个特征图的所有 16 个元素中。偏差就像线性方程中添加的截距,用于模拟真实世界的场景。然后,我们将通过应用激活函数来添加非线性。
没有激活函数的神经网络将简单地是线性回归模型,,其能力有限,并且在大多数时间不能很好地工作。如果没有激活功能,我们的神经网络将无法学习和模拟复杂类型的数据,如图像、视频等。
激活函数有多种选择,最流行的是 ReLU 激活函数。
ReLU 函数如果看到正整数,将返回相同的数字,如果看到负数,将返回零。
它纠正了消失梯度问题。此外,从 tanh 激活函数来看,它在收敛方面好了 6 倍。(关于激活功能的更多信息将在另一篇文章中介绍)。
下图描述了偏置加法,并将 ReLU 激活应用于我们的示例:

卷积层的整体计算
我们从 6x6x3 到 4x4x2 输出图的整个计算是 CNN 中的一个卷积层。卷积运算的目的是从输入图像中提取高级特征,例如边缘。 Convnets 不需要仅限于单个卷积层。
传统上,第一卷积层负责捕获低级特征,例如边缘、颜色、梯度方向等。随着图层的增加,该架构也适应了高级功能,为我们提供了一个对数据集中的图像有全面了解的网络,就像我们会做的那样。
池层:
除了卷积层, convnets 还使用池层来减少我们的表示大小,以加快计算速度。池化负责减小卷积要素的空间大小,从而降低处理数据所需的计算能力。
该操作的工作原理如下:

在图(左)中,以步幅 2 遍历输入图像上的 2×2 窗口,并且最大值保留在每个象限中。这被称为最大池操作。
最常见的形式是池图层,其大小为 2x2 的过滤器以 2 的步长应用,沿宽度和高度对输入中的每个深度切片进行 2 倍缩减采样。直觉是,如果在任何象限中存在一个特性,池将通过保持激活功能将启动的高数值来试图保留该特性
池化减少了要处理的要素地图系数的数量,并促使网络学习要素的空间等级,即,使连续的卷积层根据它们覆盖的原始输入的部分来查看越来越大的窗口。

两种类型的汇集操作
有两种类型的池:最大和*均池。最大池返回过滤器覆盖的图像部分的最大值。*均池返回内核覆盖的图像部分的所有值的*均值。
注意:在池化层的培训中没有需要学习的参数。具有较大感受野的池大小具有太大的破坏性。
完全连接层:
完全连接图层的目的是获取卷积/池化过程的结果,并使用它们将图像分类到标签中。这些层的作用与传统深度神经网络中的层相同。主要区别是输入将是由 CNN 的早期阶段(卷积层和池层)创建的形状和形式。

完全连接的层
展*是将数据转换为一维数组,以将其输入到完全连接的层。

展*,FC 输入层,FC 输出层
FC 输入层将展*的矢量作为输入,并应用权重和激活来预测正确的标签。FC 输出层给出了每个标签的最终概率。两层的区别在于激活功能。ReLU 输入,softmax 输出。(我们将在另一篇文章中对此进行更深入的讨论)
总结:
- CNN 主要有两个目标:特征提取和分类。
- CNN 有三层,即卷积层、汇集层和全连接层。CNN 的每一层都学习越来越复杂的过滤器。
- 第一层学习基本的特征检测过滤器:边缘、拐角等
- 中间层学习检测物体部分的过滤器。对于面部,他们可能会学会对眼睛、鼻子等做出反应
- 最后一层有更高的表现:他们学习识别不同形状和位置的完整物体。

CNN 架构示例
要实现一个示例 CNN,您可以在这里按照的指导实现。
用于在移动设备上检测图像中的对象的深度学习
使用 Expo、React-Native、TensorFlow.js 和 COCO-SSD 开发移动对象检测应用程序

作者照片
最*我发表了一篇文章【1】,演示如何使用Expo【2】、React【3】和React Native【4】开发一个多页面移动应用程序,该应用程序使用 tensor flow . js【5】和一个预先训练好的卷积神经网络模型 MobileNet 在移动设备上进行图像分类。
如[1]中所述,React【3】是一个用于构建 Web 用户界面的流行 JavaScript 框架。Reactive Native 继承和扩展了组件框架(如组件、道具、状态、 JSX 等)。)的 React,以支持使用预构建的原生组件(如视图、文本、触摸不透明、等)开发原生 Android 和 iOS 应用。特定于移动*台的语言(例如 Object-C、Swift、Java 等)中的本机代码。)通常使用 Xcode 或 Android Studio 开发。为了简化移动应用程序开发,Expo 为我们提供了一个围绕 React 原生和移动原生*台构建的框架和*台,允许我们使用 JavaScript/TypeScript 在 iOS、Android 和 web 应用程序上开发、构建和部署移动应用程序。因此,任何文本编辑器工具都可以用于编码。
关于机器学习移动应用,tensor flow . js for React Native是我们训练新的机器学习和深度学习模型和/或直接在移动设备上使用预训练模型进行预测和其他机器学习目的的强大使能器。
在本文中,与[1]类似,我开发了一个多页面移动应用程序来演示如何使用 TensorFlow.js [5]和一个预训练的卷积神经网络模型 COCO-SSD [6][7],一个新的 SSD(单次多盒检测器)[8],用于在移动设备上检测图像中的 COCO(上下文中的常见对象)[9]。
与[1]类似,这个移动应用在 Mac 上开发如下:
- 使用 Expo 生成多页面应用程序模板
- 安装库
- 在 React JSX 开发移动应用代码
- 编译和运行
假设最新的 node.js 已经安装在你的本地电脑/笔记本电脑上,比如 Mac。
1.正在生成项目模板
为了使用 Expo CLI 自动生成一个新的项目模板,首先需要安装 Expo CLI :
npm install *expo-cli*
然后可以生成一个新的 Expo 项目模板,如下所示:
expo init *coco-ssd
cd coco-ssd*
本文中的项目名称为 coco-ssd 。
如[1]中所述,我选择世博管理工作流的选项卡模板来自动生成几个示例屏幕和导航选项卡。TensorFlow logo 图像文件tfjs.jpg在本项目中使用,需要存储在生成的。/assets/images 目录。
2.安装库
为移动设备开发对象检测应用程序需要安装以下库:
- @tensorflow/tfjs ,即 TensorFlow.js,一个用于训练和部署机器学习模型的开源硬件加速 JavaScript 库。
- @ tensor flow/tfjs-react-native,TensorFlow.js 在移动设备上新的*台集成和后端。
- @ React-Native-community/async-storage,React Native 的异步、未加密、持久、键值存储系统。
- @ tensor flow-models/coco-SSD,预训练模型,可以将图像作为输入,并返回一组最可能的对象类预测、它们的置信度和位置(边界框)。
- expo-gl ,提供了一个视图,作为 OpenGL ES 渲染目标,用于渲染 2D 和 3D 图形。
- jpeg-js ,node.js 的纯 javascript JPEG 编码器和解码器
npm install [*@react*](http://twitter.com/react)*-native-community/async-storage* [*@tensorflow/tfjs*](http://twitter.com/tensorflow/tfjs)[*@tensorflow/tfjs-react-native*](http://twitter.com/tensorflow/tfjs-react-native) *expo-gl* [*@tensorflow*](http://twitter.com/tensorflow)*-models/coco-ssd jpeg-js*
此外,@ tensor flow/tfjs-react-native/dist/bundle _ resource _ io . js需要react-native-fs(react-native 的原生文件系统访问):
npm install *react-native-fs*
Expo-camera(为设备的前置或后置摄像头渲染预览的 React 组件)也是需要的,因为它在@ tensor flow/tfjs-React-native/dist/camera/camera _ stream . js中使用。
*expo install *expo-camera**
3.开发移动应用程序代码
如前所述,首先我使用 Expo CLI 自动生成示例屏幕和导航标签。然后,我修改了生成的屏幕,并添加了一个新的屏幕来检测图像中的对象。以下是生成的屏幕:
- 简介屏幕(参见图 2)
- 对象检测 COCO-SSD 屏幕(参见图 3 和图 4)
- 参考屏幕(参见图 5)
屏幕底部有三个相应的选项卡用于导航。
本文主要讨论 COCO-SSD 屏幕类(源代码见[10]),用于图像中的对象检测。本节的其余部分将讨论对象检测的实现细节。
3.1 准备 TensorFlow、COCO-SSD 模型和摄像机访问
生命周期方法componentidmount()用于初始化 TensorFlow.js,加载预先训练好的 COCO-SSD 模型,在 COCO-SSD 屏幕的用户界面准备就绪后,获取移动设备上访问摄像头的权限。
*async componentDidMount() {
await tf.ready(); // preparing TensorFlow
this.setState({ isTfReady: true});
this.model = await cocossd.load(); // preparing COCO-SSD model
this.setState({ isModelReady: true });
this.getPermissionAsync();
}getPermissionAsync = async () => {
if (Constants.platform.ios) {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL)
if (status !== 'granted') {
alert('Please grant camera roll permission for this project!')
}
}
}*
3.2 选择图像
一旦 TensorFlow 库和 COCO-SSD 模型准备就绪,就调用方法 selectImage ()来选择移动设备上的图像以进行对象检测。
*selectImage = async () => {
try {
let response = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3]
}) if (!response.cancelled) {
const source = { uri: response.uri }
this.setState({ image: source })
this.detectObjects()
}
} catch (error) {
console.log(error)
}
}*
3.3 检测图像中的对象
一旦在移动设备上选择了图像,就会调用 detectObjects ()方法来检测图像中的对象。
在该方法中,首先使用 TensorFlow React Native 的 fetch API 在移动设备上加载选定的图像。然后调用方法 imageToTensor ()将加载的原始图像数据转换为 3D 图像张量。最后,调用准备好的 COCO-SSD 模型,以将 3D 图像张量作为输入,并生成检测到的对象的列表及其类别、概率和位置(边界框)。
*detectObjects = async () => {
try {
const imageAssetPath = Image.resolveAssetSource(this.state.image)
const response = await fetch(imageAssetPath.uri, {}, { isBinary: true })
const rawImageData = await response.arrayBuffer()
const imageTensor = this.imageToTensor(rawImageData)
const predictions = await this.model.detect(imageTensor)
this.setState({ predictions: predictions })
} catch (error) {
console.log('Exception Error: ', error)
}
}imageToTensor(rawImageData) {
const TO_UINT8ARRAY = true
const { width, height, data } = jpeg.decode(rawImageData, TO_UINT8ARRAY)
// Drop the alpha channel info for COCO-SSD
const buffer = new Uint8Array(width * height * 3)
let offset = 0 // offset into original data
for (let i = 0; i < buffer.length; i += 3) {
buffer[i] = data[offset]
buffer[i + 1] = data[offset + 1]
buffer[i + 2] = data[offset + 2]
offset += 4
}
return tf.tensor3d(buffer, [height, width, 3])
}*
注意, fetch API 有两个版本,一个是 React fetch API,另一个是 TensorFlow React Native 的 fetch API。正确的是 TensorFlow React Native 的 fetch ,可以安装如下:
*import { fetch } from ‘[@tensorflow/tfjs-react-native](http://twitter.com/tensorflow/tfjs-react-native)’*
3.4 上报对象检测结果
一旦物体检测完成,调用方法 renderPrediction ()在移动设备的屏幕上显示物体检测结果。
*renderPrediction = (prediction, index) => {
const pclass = prediction.class;
const score = prediction.score;
const x = prediction.bbox[0];
const y = prediction.bbox[1];
const w = prediction.bbox[2];
const h = prediction.bbox[3]; return (
<View style={styles.welcomeContainer}>
<Text key={index} style={styles.text}>
Prediction: {pclass} {', '} Probability: {score} {', '} Bbox: {x} {', '} {y} {', '} {w} {', '} {h}
</Text>
</View>
)
}*
4.编译和运行移动应用程序
本文中的移动应用程序由一个 react 本地应用服务器和一个或多个移动客户端组成。移动客户端可以是 iOS 模拟器、Android 模拟器、iOS 设备(例如,iPhone 和 iPad)、Android 设备等。我验证了 Mac 上的移动应用服务器和 iPhone 6+和 iPad 上的移动客户端。
4.1 启动 React 本地应用服务器
如[1]中所述,在任何移动客户端可以开始运行之前,移动应用服务器需要启动。以下命令可用于编译和运行 react 本地应用服务器:
*npm install
npm start*
如果一切顺利,应该会出现如图 1 所示的 Web 界面。

图 1: React 原生应用服务器。
4.2 启动移动客户端
一旦移动应用服务器开始运行,我们就可以在移动设备上启动移动客户端。
因为我在本文中使用 Expo [2]进行开发,所以在移动设备上需要相应的 Expo 客户端/应用程序。iOS 移动设备的 Expo 客户端应用程序在苹果商店免费提供。
在 iOS 设备上安装 Expo 客户端应用后,我们可以使用移动设备上的摄像头扫描 react 本地应用服务器的条形码(见图 1),以使用 Expo 客户端应用运行移动应用。
图 2 显示了 iOS 设备(iPhone 和 iPad)上移动应用程序的简介屏幕。

图二:介绍画面。
图 3 和图 4 示出了检测图像中物体的两种不同场景。图 3 示出了在图像中检测汽车和卡车的屏幕。

图 3: 检测图像中的汽车和卡车。
以下是对象检测的输出:
*Array [
Object {
"bbox": Array [
61.6607666015625,
700.927734375,
230.8502197265625,
185.11962890625,
],
"class": "car",
"score": 0.8818359375,
},
Object {
"bbox": Array [
292.78564453125,
651.4892578125,
279.60205078125,
160.94970703125,
],
"class": "truck",
"score": 0.61669921875,
},
]*
图 4 示出了检测图像中的人的屏幕。

图 4: 检测图像中的人。
图 5 显示了参考屏幕。

图 5: 参考屏幕。
5.摘要
与[1]类似,在本文中,我使用 Expo [2]、、React JSX、[3]、React Native [4]、React Native 的 TensorFlow.js 和预训练的卷积神经网络模型 COCO-SSD [6]开发了一个多页面移动应用程序,用于在移动设备上检测图像中的对象。
我验证了 Mac 上的移动应用服务器和 iOS 移动设备(iPhone 和 iPad)上的移动应用客户端。
正如[1]和本文所展示的那样,这种移动应用程序有可能被用作开发其他机器学习和深度学习移动应用程序的模板。
本文的移动应用程序项目文件可以在 Github [10]中找到。
参考
- Y.张,面向移动设备的图像分类深度学习
- 世博会
- 反应过来
- 反应原生
- tensor flow . js for React Native
- COCO-SSD
- J.黄等,现代卷积目标检测器的速度/精度权衡
- W.刘等, SSD:单次多盒探测器
- 林廷烨等,微软 COCO:上下文中的公共对象
- Y.张, Github 中的手机 app 项目文件
用于移动设备上图像分类的深度学习
使用 Expo、React-Native、TensorFlow.js 和 MobileNet 开发移动影像分类应用程序

React 是一个流行的 JavaScript 框架,用于构建 Web 用户界面。 Reactive Native 继承和扩展了组件框架(如组件、道具、状态、等)。)来支持原生 Android 和 iOS 应用程序的开发,使用预先构建的原生组件,如视图、文本、触摸不透明、等。本机代码通常使用 Xcode 或 Android Studio 开发。
Expo 是一个围绕 React 原生和移动原生*台构建的框架和*台,允许我们从相同的 JavaScript/TypeScript 代码库开发、构建和部署 iOS、Android 和 web 应用上的移动应用。JavaScript/TypeScript 代码可以使用任何文本编辑器工具来开发。
随着tensor flow . js for React Native的发布,现在可以在移动设备上训练新的机器学习和深度学习模型和/或使用预训练的模型进行预测和其他机器学习目的。
在本文中,与[3]类似,我使用 Expo [4]和 React Native [5]开发了一个多页面移动应用程序,该应用程序使用 TensorFlow.js [1]和预训练的卷积神经网络模型 MobileNet [2]在移动设备上进行图像分类。
此移动应用程序在 Mac 上开发如下:
- 使用 Expo 生成多页面应用程序模板
- 安装库
- 在 React JSX 开发移动应用代码
- 编译和运行
1.使用 Expo 生成项目模板
为了使用 Expo CLI 自动生成新的项目模板,首先需要安装 Expo CLI :
npm install *expo-cli*
然后可以生成一个新的 Expo 项目模板,如下所示:
expo init *react-native-deeplearning
cd react-native-deeplearning*
本文中的项目名称为react-native-deep learning。
如下所示,我选择 Expo managed workflow 的选项卡模板来自动生成几个示例屏幕和导航选项卡。

TensorFlow logo 图像文件tfjs.jpg【3】在本项目中使用,需要存储在生成的。/assets/images 目录。
2.安装库
需要为移动设备上的影像分类应用程序安装以下库:
- @tensorflow/tfjs ,即 TensorFlow.js,一个用于训练和部署机器学习模型的开源硬件加速 JavaScript 库。
- @ tensor flow/tfjs-react-native,TensorFlow.js 在移动设备上新的*台集成和后端。
- @ React-Native-community/async-storage,React Native 的异步、未加密、持久、键值存储系统。
- @ tensor flow-models/mobilenet,预训练模型,可以将图像作为输入,并返回一组最有可能的预测及其置信度。
- expo-gl ,提供了一个充当 OpenGL ES 渲染目标的视图,用于渲染 2D 和 3D 图形。
- jpeg-js ,node.js 的纯 javascript JPEG 编码器和解码器
npm install [*@react*](http://twitter.com/react)*-native-community/async-storage* [*@tensorflow/tfjs*](http://twitter.com/tensorflow/tfjs)[*@tensorflow/tfjs-react-native*](http://twitter.com/tensorflow/tfjs-react-native) *expo-gl* [*@tensorflow*](http://twitter.com/tensorflow)*-models/mobilenet jpeg-js*
此外,react-native-fs(react-native 的本地文件系统访问)是@ tensor flow/tfjs-react-native/dist/bundle _ resource _ io . js所需要的:
npm install *react-native-fs*
由于在@ tensor flow/tfjs-React-native/dist/camera/camera _ stream . js中使用了Expo-camera(为设备的前置或后置摄像头渲染预览的 React 组件)。
*expo install *expo-camera**
3.开发移动应用程序代码
如前所述,首先,我使用 Expo CLI 自动生成示例屏幕和导航标签。然后,我修改了生成的屏幕,并添加了一个新的图像分类屏幕。因此(详见下一节),我创建了三个屏幕:
- 简介屏幕(参见图 3)
- 图像分类屏幕(见图 4)
- 参考屏幕(参见图 5)
屏幕底部有三个相应的选项卡用于导航。
本文重点介绍图像分类屏幕类(源代码见[7])。本节的其余部分将讨论实现细节。
3.1 准备 TensorFlow、MobileNet 模型和摄像机访问
生命周期方法componentidmount()用于初始化 TensorFlow.js,加载预先训练好的 MobileNet 模型,在图像分类屏幕的用户界面准备就绪后,获取在移动设备上访问相机的权限。
*async componentDidMount() {
await tf.ready(); // preparing TensorFlow
this.setState({ isTfReady: true,}); this.model = await mobilenet.load(); // preparing MobileNet model
this.setState({ isModelReady: true }); this.getPermissionAsync(); // get permission for accessing camera on mobile device
}getPermissionAsync = async () => {
if (Constants.platform.ios) {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL)
if (status !== 'granted') {
alert('Please grant camera roll permission for this project!')
}
}
}*
3.2 选择图像
一旦 TensorFlow 库和 MobileNet 模型准备就绪,就会调用方法 selectImage ()来选择移动设备上的图像以进行模型预测。
*selectImage = async () => {
try {
let response = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3]
}) if (!response.cancelled) {
const source = { uri: response.uri }
this.setState({ image: source })
this.classifyImage()
}
} catch (error) {
console.log(error)
}
}*
3.3 图像分类
与[3]类似,一旦在移动设备上选择了一幅图像,就会调用 classifyImage ()方法进行图像分类。
在该方法中,首先使用 TensorFlow React Native 的 fetch API 在移动设备上加载选定的图像。然后调用方法 imageToTensor ()将加载的原始图像数据转换为 3D 图像张量。最后,调用准备好的 MobileNet 模型以将 3D 图像张量作为输入,并生成具有概率/置信度的前 3 个预测。
*classifyImage = async () => {
try {
const imageAssetPath = Image.resolveAssetSource(this.state.image)
const response = await fetch(imageAssetPath.uri, {}, { isBinary: true })
const rawImageData = await response.arrayBuffer()
const imageTensor = this.imageToTensor(rawImageData)
const predictions = await this.model.classify(imageTensor)
this.setState({ predictions: predictions })
} catch (error) {
console.log('Exception Error: ', error)
}
}imageToTensor(rawImageData) {
const TO_UINT8ARRAY = true
const { width, height, data } = jpeg.decode(rawImageData, TO_UINT8ARRAY)
// Drop the alpha channel info for mobilenet
const buffer = new Uint8Array(width * height * 3)
let offset = 0 // offset into original data
for (let i = 0; i < buffer.length; i += 3) {
buffer[i] = data[offset]
buffer[i + 1] = data[offset + 1]
buffer[i + 2] = data[offset + 2] offset += 4
} return tf.tensor3d(buffer, [height, width, 3])
}*
注意 fetch API 有两个版本,一个是 React fetch API,另一个是 TensorFlow React Native 的 fetch API。
务必为 TensorFlow React Native 导入正确的 fetch API,如下所示,以避免类似“filereader.readasarraybuffer 未在 React Native 中实现”的错误:
*import { fetch } from ‘[@tensorflow/tfjs-react-native](http://twitter.com/tensorflow/tfjs-react-native)’*
3.4 报告图像分类结果
一旦图像分类完成,调用方法 renderPrediction ()在移动设备的屏幕上显示预测结果。
*renderPrediction = (prediction) => {
return (
<View style={styles.welcomeContainer}>
<Text key={prediction.className} style={styles.text}>
Prediction: {prediction.className} {', '} Probability: {prediction.probability}
</Text>
</View>
)
}*
4.编译和运行移动应用程序
本文中的移动应用程序由一个 react 本地应用服务器和一个或多个移动客户端组成。移动客户端可以是 iOS 模拟器、Android 模拟器、iOS 设备(例如,iPhone 和 iPad)、Android 设备等。我验证了 Mac 上的移动应用服务器和 iPhone 6+和 iPad 上的移动客户端。
4.1 启动 React 本地应用服务器
移动应用服务器需要在任何移动客户端开始运行之前启动。以下命令可用于编译和运行 react 本地应用服务器:
*npm install
npm start*
如果一切顺利,应该会出现如图 1 所示的 Web 界面。

4.2 启动移动客户端
一旦移动应用服务器开始运行,我们就可以在移动设备上启动移动客户端。
因为我在本文中使用 Expo [4]进行开发,所以在移动设备上需要相应的 Expo 客户端/应用程序。iOS 移动设备的 Expo 应用程序在 Apple Store 中提供。

图 2:Apple Store 中的 Expo 客户端 app。
在 iOS 设备上安装 Expo 客户端应用后,我们可以使用移动设备上的摄像头扫描 react 本地应用服务器的条形码(见图 1),以使用 Expo 客户端应用运行移动应用。
图 3、4、5 显示了移动应用程序在 iOS 设备(iPhone 和 iPad)上的结果屏幕。

图 3:iOS 设备上的介绍画面。

图 4:iOS 设备上的图片分类屏幕。

图 5:iOS 设备上的参考屏幕。
5.摘要
在本文中,我使用 Expo [4]、、React JSX、React Native [5]、TensorFlow.js [1]和预训练的卷积神经网络模型 MobileNet [2]开发了一个用于移动设备上图像分类的多页面移动应用程序。
我验证了 Mac 上的移动应用服务器和 iOS 移动设备(iPhone 和 iPad)上的移动应用客户端。
这款移动应用有可能被用作开发其他机器学习和深度学习移动应用的模板。
Github [7]中提供了移动应用程序项目文件。
参考
- tensor flow . js for React Native
- 移动互联网
- A.Mittal,使用 TensorFlow.js 和 MobileNet 在 React Native 上进行图像分类
- 世博会
- 反应原生
- 反应过来
- Y.张, Github 中的手机 app 项目文件
惯性导航的深度学习
基于深度学习的惯性导航前沿解决方案综述。

Or 等人 2020
介绍
在过去十年中,出现了许多视觉辅助导航方法,因为这些方法的应用范围很广(黄,2019)。换句话说,以低成本惯性传感器为唯一信息源的惯性导航经典领域已经开始受到所涉及的新颖深度学习方法的关注。惯性导航的主要问题是漂移,这是误差的一个重要来源。更多的问题包括错误的初始化、不正确的传感器建模和*似误差。
在这篇文章中,我们回顾了深度学习和惯性测量单元(IMU)在经典惯性导航系统(INS)中的集成,这些集成仅解决了上述部分问题。首先,我们介绍一些先进的架构来改进速度估计、降噪、零速度检测以及姿态和位置预测。其次,讨论了 KITTI 和 OxIOD 数据集。最后,给出了具有深度学习的行人惯性导航方案。
基于深度学习的尖端解决方案
导航领域的主要问题之一是速度估计。随着估计变得精确,它也将影响位置解。在 Cortes 等人 2018 年发表的工作中,提出了一种基于深度学习的速度估计方法。主要思想是在经典的惯性导航系统(INS)中加入速度约束。他们仅通过使用 CNN 来估计 IMU 的速度,然后通过这种预测来约束 INS 解。将这种估计公式化为回归深度学习任务,其中输入是 IMU 在几秒内的六通道,输出是速度,这将改善轨迹跟踪和运动模式分类。

科尔特斯等人,2018 年
我想展示的下一个作品是关于降噪的。由于许多低成本传感器会受到高幅度噪声的影响,并且噪声随时间变化,因此需要对其进行滤波。然而,由于这些噪声分布难以估计,使用基于深度学习的方法似乎可以解决这个问题。Chen 等人(2018)提出了一种新的深度学习方法来处理传感器信号中的许多误差源。通过这样做,传感器的信号可以被校正,然后才能用于导航方案。他们报告说,正确识别 IMU 信号的准确率为 80%。CNN 也用于这项工作,其中它包括 5 个卷积层和一个全连接层。

陈等,2018
瓦格斯塔夫和凯利(2018)的另一项工作涉及室内导航任务,其中提出了一种检测脚零速度的方案。通过这样做,提供了速度估计的精度,并且通过一般的 INS 提高了精度。检测是通过设计一个长短期记忆(LSTM)神经网络来完成的。通过评估超过 7.5 [km]的室内行人运动数据的设计,他们报告了定位误差的减少超过 34%。他们的架构包括 6 层 LSTM,每层 80 个单元,以及 LSTM 之后的单一全连接层。

瓦格斯塔夫和凯莉(2018)
我要讨论的最后一项工作与导航领域的一个主要问题有关:姿态和位置预测。实现精确的姿态状态估计对于多旋翼系统非常重要,因为微小的误差都可能导致不稳定并最终导致灾难。Al-Sharman 等人(2019)的一项工作提出了一种基于深度学习的状态估计增强,特别适用于姿态估计。他们通过降噪技术解决了精确姿态估计的问题,从而确定了测量噪声的特性。他们使用了一个简单的多层神经网络和一种退出技术,这种技术比传统的方法更优越。

阿尔-沙曼等人(2020 年)
公共数据集
有两个通用数据集可用于评估不同的建议方法,第一个是卡尔斯鲁厄理工学院的 KITTI 数据集,它包含大量数据:威力登、IMU、GPS、相机校准、灰度立体序列、3D 物体卡车标签等等。Geiger 等人(2013 年)的论文回顾了整个数据集。Alto KITTI 是该领域的主要数据集,我想提一下另一个全新的数据集,由牛津大学命名为“OxIOD”。它用于深度惯性里程计,完整信息见陈等人(2018)的论文。

盖格等人(2013 年)

陈等(2018)
行人惯性导航
最*,人们对将深度学习技术应用于行人的运动传感和位置估计越来越感兴趣。在 Chen 等人(2020)的工作中,审查了基于深度学习的行人 INS 方法、数据集和设备上的界面。在他们的工作中,他们提出了 L-IONet,一个从原始数据中学习惯性跟踪的框架。该架构主要包含 1d 扩展卷积层,受 WaveNet 启发,具有全连接层。
Klein 等人(2020)的另一项工作提出了 StepNet:一种用于步长估计的深度学习方法。作者通过一系列基于深度学习的方法来回归步长,从而解决了行人室内航位推算问题。建议的 StepNet 优于他们论文中描述的传统方法。

克莱因等人(2020 年)
总结
随着深度学习的热度不断上升,它似乎解决了惯性导航领域的许多经典问题。正如我们在这篇文章中所描述的,一些研究已经解决了深度学习和惯性导航的集成问题,并取得了可喜的成果。
参考
黄,。"目视惯性导航:简明综述." 2019 机器人与自动化国际会议(ICRA) 。IEEE,2019。
科尔特斯、圣地亚哥、阿诺·索林和胡奥·坎纳拉。"基于深度学习的速度估计,用于约束智能手机上的捷联惯性导航." 2018 IEEE 第 28 届信号处理机器学习国际研讨会(MLSP) 。IEEE,2018。
陈,华,等,“用深度学习方法减少误差改进惯性传感器” NAECON 2018-IEEE 全国航空航天与电子会议。IEEE,2018。
瓦格斯塔夫,布兰登和乔纳森·凯利。“用于鲁棒惯性导航的基于 LSTM 的零速度检测。” 2018 室内定位与室内导航国际会议(IPIN) 。IEEE,2018。
状态估计增强的基于深度学习的神经网络训练:应用于姿态估计。 IEEE 仪器仪表与测量汇刊69.1(2019):24–34。
视觉遇上机器人:kitti 数据集。国际机器人研究杂志 32.11(2013):1231–1237。
陈,常浩,等。“Oxiod:用于深度惯性里程计的数据集。” arXiv 预印本 arXiv:1809.07491 (2018)。
基于深度学习的行人惯性导航:方法、数据集和设备上的推断。 IEEE 物联网期刊7.5(2020):4431–4441。
克莱恩、伊茨克和奥姆里·阿斯拉夫。" Step net——用于步长估计的深度学习方法." IEEE 访问8(2020):85706–85713。
移动设备上自然语言处理的深度学习
使用 Expo、React-Native、TensorFlow.js 和 MobileBERT 进行阅读理解

作者照片
随着跨*台 Web 和移动开发语言、库以及 React [1]、React Native [2]和 Expo [3]等工具的进步,移动 app 在机器学习和其他领域找到了越来越多的应用。针对 React Native [4]和 TensorFlow Lite [5]发布的 TensorFlow.js 允许我们直接在跨*台移动设备上训练新的机器学习和深度学习模型和/或使用预训练模型进行预测和其他机器学习。
最*我发表了两篇文章【7】来演示如何使用Expo【3】、React【1】和React Native【2】来开发多页面移动应用程序,这些应用程序利用 TensorFlow.js 进行 React Native【4】和预训练的卷积神经网络模型 MobileNet 和 COCO-SSD 分别用于移动设备上的图像分类和对象检测。
如[6][7]所述,React【1】是一种流行的用于构建 Web 用户界面的 JavaScript 框架,而 Reactive Native 继承并扩展了组件框架(如组件、道具、状态、 JSX 等)。)的 React,使用预建的原生组件,如视图、文本、可触摸不透明、等,支持原生 Android 和 iOS 应用的开发。
特定于移动*台的语言(例如 Object-C、Swift、Java 等)中的本机代码。)通常使用 Xcode 或 Android Studio 开发。为了简化移动应用开发,Expo [3]为我们提供了一个围绕 React 原生和移动原生*台构建的框架和*台,允许我们使用 JavaScript/TypeScript 在 iOS、Android 和 web 应用上开发、构建和部署移动应用。因此,任何文本编辑器工具都可以用于编码。
在本文中,与[6][7]类似,我开发了一个多页面移动应用程序,以演示如何使用 TensorFlow.js [5]和一个预先训练好的深度自然语言处理模型 MobileBERT [8][9][10]在移动设备上进行阅读理解。
类似于[6][7],这个移动应用在 Mac 上开发如下:
- 使用 Expo 生成多页面应用程序模板
- 安装库
- 在 React JSX 开发移动应用代码
- 编译和运行
假设最新的 node.js 已经安装在你的本地电脑/笔记本电脑上,比如 Mac。
1.正在生成项目模板
为了使用 Expo CLI 自动生成新的项目模板,首先需要安装 Expo CLI :
npm install *expo-cli*
然后可以生成一个新的 Expo 项目模板,如下所示:
expo init *qna
cd qna*
本文中的项目名称为 qna (即问答)。
如[6][7]所述,我选择世博管理工作流的标签模板来自动生成几个示例屏幕和导航标签。TensorFlow logo 图像文件tfjs.jpg在本项目中使用,需要存储在生成的。/assets/images 目录。
2.安装库
开发阅读理解移动应用程序需要安装以下库:
- @tensorflow/tfjs ,即 TensorFlow.js,一个用于训练和部署机器学习模型的开源硬件加速 JavaScript 库。
- @ tensor flow/tfjs-react-native,TensorFlow.js 在移动设备上新的*台集成和后端。
- @ React-Native-community/async-storage,React Native 的异步、未加密、持久、键值存储系统。
- expo-gl ,提供了一个视图,作为 OpenGL ES 渲染目标,用于渲染 2D 和 3D 图形。
- @tensorflow-models/qna ,预训练的自然语言处理模型 MobileBERT [9][10],它可以将问题和相关段落作为输入,并返回该问题最可能的答案、它们的置信度以及答案在段落中的位置(答案在段落中的开始和结束索引)的数组。
npm install [*@react*](http://twitter.com/react)*-native-community/async-storage* [*@tensorflow/tfjs*](http://twitter.com/tensorflow/tfjs)[*@tensorflow/tfjs-react-native*](http://twitter.com/tensorflow/tfjs-react-native) *expo-gl* [*@tensorflow*](http://twitter.com/tensorflow)*-models/qna*
另外,@ tensor flow/tfjs-react-native/dist/bundle _ resource _ io . js需要react-native-fs(react-native 的一个原生文件系统访问):
npm install *react-native-fs*
由于在@ tensor flow/tfjs-React-native/dist/camera/camera _ stream . js中使用了Expo-camera(一个为设备的前置或后置摄像头渲染预览的 React 组件)也是需要的。
*expo install *expo-camera**
3.开发阅读理解移动应用程序代码
如前所述,首先我使用 Expo CLI 自动生成示例屏幕和导航标签。然后我修改了生成的屏幕,增加了一个新的 Qna (问答)屏幕,用于阅读理解。以下是生成的屏幕:
- 简介屏幕(参见图 2)
- 阅读理解( Qna )屏幕(见图 3)
- 参考屏幕(参见图 4)
屏幕底部有三个相应的选项卡用于导航。
本文重点介绍用于自然语言阅读理解的 Qna screen 类(源代码见【11】)。本节的其余部分将讨论实现细节。
3.1 准备 TensorFlow 和 MobileBERT 模型
生命周期方法componentidmount()用于初始化 TensorFlow.js,并在 Qna 屏幕的用户界面准备就绪后加载预先训练好的 mobile Bert【9】【10】模型。
*async componentDidMount() {
await tf.ready(); // preparing TensorFlow
this.setState({ isTfReady: true});
this.model = await qna.load();
this.setState({ isModelReady: true });
}*
3.2 选择文章和问题
一旦 TensorFlow 库和 MobileBERT 模型准备就绪,移动应用程序用户就可以键入一篇文章和一个与这篇文章相关的问题。
为了方便起见,[10]中的段落和问题在本文中作为默认段落和问题重复使用。
默认段落:
*Google LLC is an American multinational technology company that specializes in Internet-related services and products, which include online advertising technologies, search engine, cloud computing, software, and hardware. It is considered one of the Big Four technology companies, alongside Amazon, Apple, and Facebook. Google was founded in September 1998 by Larry Page and Sergey Brin while they were Ph.D. students at Stanford University in California. Together they own about 14 percent of its shares and control 56 percent of the stockholder voting power through supervoting stock. They incorporated Google as a California privately held company on September 4, 1998, in California. Google was then reincorporated in Delaware on October 22, 2002\. An initial public offering (IPO) took place on August 19, 2004, and Google moved to its headquarters in Mountain View, California, nicknamed the Googleplex. In August 2015, Google announced plans to reorganize its various interests as a conglomerate called Alphabet Inc. Google is Alphabet's leading subsidiary and will continue to be the umbrella company for Alphabet's Internet interests. Sundar Pichai was appointed CEO of Google, replacing Larry Page who became the CEO of Alphabet."*
默认问题:
*Who is the CEO of Google?*
3.3 寻找问题的答案
一旦在移动设备上提供了一篇文章和一个问题,用户可以点击“查找答案”按钮来调用方法 findAnswers ()来查找文章中给定问题的可能答案。
在这种方法中,调用准备好的 MobileBERT 模型,以将提供的段落和问题作为输入,并生成问题的可能答案列表及其概率和位置(段落中答案的开始和结束索引)。
*findAnswers = async () => {
try {
const question = this.state.default_question;
const passage = this.state.default_passage;
const answers = await this.model.findAnswers(question, passage);console.log('answers: ');
console.log(answers);return answers;} catch (error) {
console.log('Exception Error: ', error)
}
}*
3.4 报告答案
阅读理解完成后,调用方法 renderAnswer ()在移动设备的屏幕上显示答案。
*renderAnswer = (answer, index) => {
const text = answer.text;
const score = answer.score;
const startIndex = answer.startIndex;
const endIndex = answer.endIndex;return (
<View style={styles.welcomeContainer}>
<Text key={answer.text} style={styles.text}>
Answer: {text} {', '} Probability: {score} {', '} start: {startIndex} {', '} end: {endIndex}
</Text>
</View>
)
}*
4.编译和运行移动应用程序
本文中的移动应用程序由一个 react 本地应用服务器和一个或多个移动客户端组成。移动客户端可以是 iOS 模拟器、Android 模拟器、iOS 设备(例如,iPhone 和 iPad)、Android 设备等。我验证了 Mac 上的移动应用服务器和 iPhone 6+和 iPad 上的移动客户端。
4.1 启动 React 本地应用服务器
如[6][7]中所述,在任何移动客户端可以开始运行之前,移动应用服务器需要启动。以下命令可用于编译和运行 react 本地应用服务器:
*npm install
npm start*
如果一切顺利,应该会出现如图 1 所示的 Web 界面。

图 1: 反应式应用服务器。
4.2 启动移动客户端
一旦移动应用服务器开始运行,我们就可以在移动设备上启动移动客户端。
由于我在本文中使用 Expo [3]进行开发,因此在移动设备上需要相应的 Expo 客户端应用程序。iOS 移动设备的 Expo 客户端应用程序在苹果商店免费提供。
在 iOS 设备上安装 Expo 客户端应用后,我们可以使用移动设备上的摄像头扫描 react 本地应用服务器的条形码(见图 1),以使用 Expo 客户端应用运行移动应用。
图 2 显示了 iOS 设备(iPhone 和 iPad)上移动应用程序的简介屏幕。

图 2:iOS 设备上的介绍画面。
图 3 显示了阅读理解的屏幕(段落、问题、“查找答案”按钮和答案)。

图 3:iOS 设备上的 Qna 屏幕。
以下是 findAnswers ()方法调用的输出:
*Array [
Object {
"endIndex": 1206,
"score": 12.2890625,
"startIndex": 1186,
"text": "replacing Larry Page",
},
Object {
"endIndex": 1206,
"score": 10.87109375,
"startIndex": 1150,
"text": "Pichai was appointed CEO of Google, replacing Larry Page",
},
Object {
"endIndex": 1206,
"score": 9.658203125,
"startIndex": 1196,
"text": "Larry Page",
},
Object {
"endIndex": 1156,
"score": 5.2802734375,
"startIndex": 1150,
"text": "Pichai",
},
]*
图 4 显示了参考屏幕。

图 4:iOS 设备上的参考屏幕。
5.摘要
与[6][7]类似,在本文中,我使用 Expo [3]、React JSX、React Native [2]、React Native 的 TensorFlow.js 和预先训练好的深度自然语言处理模型 MobileBERT [9][10]开发了一个用于移动设备上阅读理解(问答)的多页移动应用。
我验证了 Mac 上的移动应用服务器和 iOS 移动设备(iPhone 和 iPad)上的移动应用客户端。
正如[6][7]和本文所展示的那样,这种移动应用程序有可能被用作开发其他机器学习和深度学习移动应用程序的模板。
本文的移动应用程序项目文件可以在 Github [11]中找到。
参考
- 反应
- 反应土著
- 世博会
- tensor flow . js for React Native
- TensorFlow Lite
- Y.张,面向移动设备的图像分类深度学习
- Y.张,深度学习在移动设备上检测图像中的物体
- J.Devlin,M.W. Chang 等人, BERT:用于语言理解的深度双向转换器的预训练
- Z.孙,于,等, MobileBERT:一个面向资源受限设备的任务无关的精简 BERT
- tensor flow . js 预训 MobileBERT 问答
- Y.张, Github 中的手机 app 项目文件
用 PyTorch 和 Torchtext 实现自然语言处理的深度学习
PyTorch 和 Torchtext 教程
Torchtext 的预训练单词嵌入,数据集 API,迭代器 API,以及带有 Torchtext 和 PyTorch 的训练模型

PyTorch 是我一直在使用的一个非常棒的深度学习框架。然而,说到 NLP,不知何故我找不到像 torchvision 那样好的实用程序库。原来 PyTorch 有这个 torchtext ,在我看来,缺少如何使用它的例子,文档[6]可以改进。此外,有一些很好的教程,如[1]和[2],但是,我们仍然需要更多的例子。
本文的目的是向读者提供关于如何使用 torchtext 的示例代码,特别是使用预先训练的单词嵌入、使用数据集 API、使用迭代器 API 进行小批量,以及最后如何结合使用这些来训练模型。
使用 Torchtext 预训练单词嵌入
在预训练的单词嵌入中有一些替代方法,如 Spacy [3],Stanza (Stanford NLP)[4],Gensim [5],但在本文中,我想重点介绍使用 torchtext 进行单词嵌入。
可用单词嵌入
你可以在 torchtext 看到预训练单词嵌入列表。在撰写本文时,支持 3 个预先训练好的单词嵌入类:GloVe、FastText 和 CharNGram,没有关于如何加载的更多细节。这里的列出了详尽的列表,但我有时会花时间去阅读,所以我会在这里列出列表。
**charngram.100d
fasttext.en.300d
fasttext.simple.300d
glove.42B.300d
glove.840B.300d
glove.twitter.27B.25d
glove.twitter.27B.50d
glove.twitter.27B.100d
glove.twitter.27B.200d
glove.6B.50d
glove.6B.100d
glove.6B.200d
glove.6B.300d**
有两种方法可以加载预训练的单词嵌入:启动单词嵌入对象或使用Field实例。
使用现场实例
你需要一些玩具数据集来使用它,所以让我们设置一个。
df = pd.DataFrame([
['my name is Jack', 'Y'],
['Hi I am Jack', 'Y'],
['Hello There!', 'Y'],
['Hi I am cooking', 'N'],
['Hello are you there?', 'N'],
['There is a bird there', 'N'],
], columns=['text', 'label'])
然后我们可以构造Field 对象来保存特性列和标签列的元数据。
from torchtext.data import Fieldtext_field = Field(
tokenize='basic_english',
lower=True
)label_field = Field(sequential=False, use_vocab=False)# sadly have to apply preprocess manually
preprocessed_text = df['text'].apply(lambda x: text_field.preprocess(x))# load fastext simple embedding with 300d
text_field.build_vocab(
preprocessed_text,
vectors='fasttext.simple.300d'
)# get the vocab instance
vocab = text_field.vocab
要获得预训练单词嵌入的真实实例,可以使用
vocab.vectors
启动 Word 嵌入对象
对于这些代码中的每一个,它将下载大量的单词嵌入,所以你必须有耐心,不要一次执行下面所有的代码。
快速文本
FastText 对象有一个参数:language,它可以是“simple”或“en”。目前他们只支持 300 个嵌入维度,如上面的嵌入列表中所提到的。
from torchtext.vocab import FastText
embedding = FastText('simple')
查恩格拉姆
from torchtext.vocab import CharNGram
embedding_charngram = CharNGram()
手套
手套对象有两个参数:名称和尺寸。您可以查看每个参数支持的可用嵌入列表。
from torchtext.vocab import GloVe
embedding_glove = GloVe(name='6B', dim=100)
使用单词嵌入
使用 torchtext API 使用单词嵌入超级简单!假设您已经将嵌入存储在变量embedding中,那么您可以像使用 python 的dict一样使用它。
# known token, in my case print 12
print(vocab['are'])
# unknown token, will print 0
print(vocab['crazy'])
正如你所看到的,它已经处理了未知的令牌,没有抛出错误!如果您尝试将单词编码成整数,您会注意到,默认情况下,unknown token 将被编码为0,而 pad token 将被编码为1。
使用数据集 API
假设变量df已经如上定义,我们现在通过为特征和标签构建Field来准备数据。
from torchtext.data import Fieldtext_field = Field(
sequential=True,
tokenize='basic_english',
fix_length=5,
lower=True
)label_field = Field(sequential=False, use_vocab=False)# sadly have to apply preprocess manually
preprocessed_text = df['text'].apply(
lambda x: text_field.preprocess(x)
)# load fastext simple embedding with 300d
text_field.build_vocab(
preprocessed_text,
vectors='fasttext.simple.300d'
)# get the vocab instance
vocab = text_field.vocab
这里有一点警告,
Dataset.split可能返回 3 个数据集( train,val,test ),而不是定义的 2 个值
使用迭代器类进行小型批处理
我没有找到任何现成的Dataset API 来加载 pandas DataFrame到 torchtext 数据集,但是创建一个还是很容易的。
from torchtext.data import Dataset, Example ltoi = {l: i for i, l in enumerate(df['label'].unique())}
df['label'] = df['label'].apply(lambda y: ltoi[y])class DataFrameDataset(Dataset):
def __init__(self, df: pd.DataFrame, fields: list):
super(DataFrameDataset, self).__init__(
[
Example.fromlist(list(r), fields)
for i, r in df.iterrows()
],
fields
)
我们现在可以构建DataFrameDataset并用熊猫数据帧初始化它。
train_dataset, test_dataset = DataFrameDataset(
df=df,
fields=(
('text', text_field),
('label', label_field)
)
).split()
然后我们使用BucketIterator类来轻松地构造迷你批处理迭代器。
from torchtext.data import BucketIteratortrain_iter, test_iter = BucketIterator.splits(
datasets=(train_dataset, test_dataset),
batch_sizes=(2, 2),
sort=False
)
记住使用 sort=False 否则当你试图迭代test_iter时会导致错误,因为我们还没有定义 sort 函数,然而不知何故,默认情况下test_iter被定义为排序。
小提示:虽然我同意我们应该使用
DataLoaderAPI 来处理迷你批处理,但是目前我还没有探索过如何使用DataLoader和 torchtext。
培训 PyTorch 模型的示例
让我们使用 1 个嵌入层和 1 个线性层定义一个任意 PyTorch 模型。在当前的例子中,我没有使用预训练的单词嵌入,而是使用新的未训练的单词嵌入。
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import Adamclass ModelParam(object):
def __init__(self, param_dict: dict = dict()):
self.input_size = param_dict.get('input_size', 0)
self.vocab_size = param_dict.get('vocab_size')
self.embedding_dim = param_dict.get('embedding_dim', 300)
self.target_dim = param_dict.get('target_dim', 2)
class MyModel(nn.Module):
def __init__(self, model_param: ModelParam):
super().__init__()
self.embedding = nn.Embedding(
model_param.vocab_size,
model_param.embedding_dim
)
self.lin = nn.Linear(
model_param.input_size * model_param.embedding_dim,
model_param.target_dim
)
def forward(self, x):
features = self.embedding(x).view(x.size()[0], -1)
features = F.relu(features)
features = self.lin(features)
return features
然后,我可以很容易地重复如下的训练(和测试)例程。
重用预先训练的单词嵌入
很容易将当前定义的模型修改为使用预训练嵌入的模型。
class MyModelWithPretrainedEmbedding(nn.Module):
def __init__(self, model_param: ModelParam, embedding):
super().__init__()
self.embedding = embedding
self.lin = nn.Linear(
model_param.input_size * model_param.embedding_dim,
model_param.target_dim
)
def forward(self, x):
features = self.embedding[x].reshape(x.size()[0], -1)
features = F.relu(features)
features = self.lin(features)
return features
我做了 3 行修改。您应该注意到,我已经更改了构造函数输入以接受嵌入。此外,我还将view方法改为reshape ,并使用 get 操作符[] 而不是 call 操作符() 来访问嵌入。
model = MyModelWithPretrainedEmbedding(model_param, vocab.vectors)
结论
我已经完成了使用 torchtext 在 PyTorch 中处理文本数据的探索。我开始写这篇文章是因为我在使用互联网上现有的教程时遇到了困难。我希望这篇文章也能减少其他人的开销。
写这段代码需要帮助吗?这里有一个谷歌 Colab 的链接。
参考
[1]聂,A . torch text 教程。2017.http://anie.me/On-Torchtext/
[2]用 TorchText 教程进行文本分类。https://py torch . org/tutorials/初学者/text _ 情操 _ngrams_tutorial.html
[3]节文档。https://stanfordnlp.github.io/stanza/
[4] Gensim 文档。https://radimrehurek.com/gensim/
[5]空间文件。https://spacy.io/
[6] Tor chtext 文档。https://pytorch.org/text/
自然语言处理的深度学习:单词嵌入

简单直观的单词嵌入
介绍
单词嵌入 已经成为最常用的工具之一,也是需要处理语音或文本等自然语言的人工智能任务取得惊人成就的主要驱动力。
在本帖中,我们将揭开它们背后的神奇,看看它们是什么,为什么它们成为了自然语言处理 (NLP 下文)世界中的标准,它们是如何构建的,并探索一些最常用的单词嵌入算法。
一切都将以简单直观的方式进行解释,避免复杂的数学运算,并尽量使帖子的内容易于理解。
这将在以下小节中进行分解:
- 什么是单词嵌入?
- 为什么要使用单词嵌入?
- 单词嵌入是如何构建的?
- 最流行的单词嵌入有哪些?
一旦你准备好了,让我们开始看看什么是单词嵌入。
1)什么是单词嵌入?
计算机把一切都分解成数字。更确切地说是比特(零和一)。当计算机内部的软件(例如机器学习算法)必须操作或处理一个单词时会发生什么?很简单,这个单词需要作为交给计算机,作为它唯一能理解的:数字。
在 NLP 中,最简单的方法是通过创建一个包含大量单词的词汇表(比如说 100,000 个单词),并为词汇表中的每个单词分配一个数字。
我们词汇中的第一个词(苹果也许)将是数字 0。第二个字(香蕉’)将是数字 1,依此类推直到数字 99.998,前一个到最后一个字(国王’)和 999.999 被分配给最后一个字(王后’)。
然后我们将每个单词表示为一个长度为 100.000 的向量,其中每个单项除了其中一项都是零,对应于该单词所关联的数字的索引。

前面段落中一些例子的矢量表示。
这被称为单词的一键编码。
one-hot 编码有各种不同的与效率和上下文相关的问题,我们马上就会看到。
单词嵌入只是另一种形式通过向量表示单词,它通过某种方式抽象每个单词的上下文或高级含义成功地解决了使用一键编码带来的许多问题。
这里的主要要点是,单词嵌入是表示单词的向量,所以意思相似的单词有相似的向量。
2)为什么要使用单词嵌入?
考虑前面的例子,但是我们的词汇中只有三个词:‘苹果’,【香蕉】,和‘国王’。这些单词的一个热编码向量表示如下。

我们词汇的一个热门向量表示
如果我们在三维空间中绘制这些单词向量,我们将得到如下图所示的表示,其中每个轴代表我们拥有的一个维度,图标代表每个单词向量的末端。

三维空间中我们的一个热编码字向量的表示。
正如我们所看到的,从任何一个向量(图标的位置)到所有其他向量的距离都是相同的:两个大小为 1 的步长在不同的方向。如果我们将问题扩展到 100.000 维,采取更多的步骤,但在所有单词向量之间保持相同的距离,这将是相同的。
理想情况下,我们希望具有相似含义或代表相似项目的词的向量靠*在一起,远离那些具有完全不同含义的词:我们希望苹果靠*香蕉但远离国王。
此外,一个热编码非常低效。仔细想想,它们是巨大的空向量,只有一项的值不为零。它们非常稀疏,会大大降低我们的计算速度。
总之:一种热编码不考虑单词的上下文或含义,所有单词向量之间的距离相同,效率非常低。
单词嵌入通过用一个相当小的(150、300、500 维)固定大小的向量表示词汇表中的每个单词来解决这些问题,这个向量被称为嵌入,它是在训练期间学习的。
这些向量是以这样一种方式创建的,即出现在相似上下文中或者具有相似含义的单词靠得很*,并且它们不像从一键嵌入中导出的那些向量那样是稀疏向量。
如果我们有一个二维单词嵌入表示我们之前的 4 个单词,并将其绘制在 2D 网格上,它看起来会像下图一样。

我们的示例单词的二维单词嵌入表示
从上图中我们可以清楚地看到,单词' apple '和' banana '之间的单词嵌入表示比单词' king '和' queen '之间的单词嵌入表示更接*,这适用于相反的情况:当我们使用单词嵌入时,具有相似含义的单词更接*。
这个事实也让我们可以做一些非常非常酷的事情。我们可以操作单词嵌入,使用单词的表示从一个已知单词到另一个单词。
下图显示了如果我们从单词 ' king ' 的嵌入中减去单词 ' royal ' 的嵌入,我们将到达单词 ' man ' 的嵌入附*。以类似的方式,如果我们从皇后的嵌入中减去' royal' 的嵌入,我们到达单词 ' woman ' 的嵌入附*的某处。爽吧?

单词嵌入操作。国王、王后、男人、女人的例子非常流行来说明这一点。
最后,正如我们在单词嵌入向量中看到的,它们通常具有较小的尺寸(在我们的例子中是 2,但是大多数时候它们具有 150、200、300 或 500 维)并且不是稀疏的,使得使用它们进行计算比使用单热点向量更有效。
3)单词嵌入是如何构建的?
你可能已经猜到了,像机器学习生态系统中的许多元素一样,单词嵌入是通过学习建立的。从数据中学习。
有许多算法可以学习单词嵌入,我们将很快看到它们,但总的目标是构建一个矩阵 E ,它可以将表示单词的一个热点向量转换为固定大小的向量,即该单词的嵌入。
让我们来看一个非常高级的例子。
想想这句话我喜欢喝苹果冰沙’。如果我去掉这个词’苹果’我们就剩下下面这个不完整的句子:‘我喜欢喝 __ 思慕雪’。如果我接下来给你这个不完整的句子,并让你猜缺失的单词,你可能会说像' 香蕉 '、 ' 草莓'、或' 苹果 '这样的单词,它们都有相似的意思,并且通常出现在相似的上下文中。
学习单词嵌入的主要方法之一是通过与此非常相似的过程:算法通过在巨大的文本句子语料库中猜测缺失单词来学习在相似上下文中多次出现的单词的相似单词嵌入。
嵌入矩阵 E (将一个热嵌入转换成单词嵌入向量的矩阵)通过训练类似于语言模型(试图预测句子中缺失单词的模型)的东西来计算,使用人工神经网络来预测该缺失单词,其方式类似于如何计算网络的权重和偏差。
在实践中,你可以避免训练你自己的单词嵌入,因为有从各种语料库构建的公开可用的单词嵌入(像维基百科或 Twitter GloVe 单词嵌入),节省你的时间和精力。
最后,让我们简单看看一些最流行的单词嵌入算法。
4)最流行的单词嵌入有哪些?
最常用的两种单词嵌入算法是 Word2Vec 和 GloVe。让我们看看它们是如何工作的。
- word 2 vec:word 2 vec是一组相关的模型,它们通过使用两层、浅层的人工神经网络来产生单词嵌入,这些人工神经网络试图使用单词的上下文来预测单词( 连续的单词包 — CBOW),或者仅使用一个单词来预测上下文( Skip-gram 模型)。这是上一节描述的过程。

CBOW 和 Skipgram Word2Vec 型号。在 CBOW 中,我们试图使用上下文来预测单词 apple,而在 Skip-gram 模型中,我们试图预测单词 apple 的上下文。
- GloVe: 是全局向量的缩写,GloVe 算法通过在单词之间使用共现矩阵来计算单词嵌入。这个矩阵是通过阅读一个巨大的句子语料库并为它找到的每个独特的单词创建一列和一行而构建的。对于每个单词,它使用特定的窗口大小记录它与其他单词在同一个句子中出现的次数,因此它也可以测量两个单词在一个句子中的接*程度。

窗口大小为 2 的句子“我喜欢喝苹果冰沙”的同现矩阵
结论和额外资源
就是这样!一如既往,我希望你喜欢这篇文章,并且我设法帮助你理解了什么是单词嵌入,它们是如何工作的,以及它们为什么如此强大。
如果您想了解有关该主题的更多信息,您可以在这里找到一些附加资源:
- 一种神经概率模型。 本吉奥等。
- 吴恩达教授关于学习单词嵌入的讲座。
- 机器学习掌握单词嵌入的帖子。
- 单词嵌入及其在语义模型中的应用概述。
如果你喜欢这篇文章,那么请随时关注我的推特@jaimezorno 。还有,你可以看看我其他关于数据科学和机器学习的帖子 这里 。好好读!
如果你想了解更多关于机器学习和人工智能的知识 在 Medium 上关注我 ,敬请关注我的下一篇帖子!另外,你可以查看 这个资源库 获取更多关于机器学习和人工智能的资源!
最后,看看我关于 NLP 深度学习的其他帖子:
** [## NLP 的深度学习:ann,RNNs 和 LSTMs 解释!
了解人工神经网络,深度学习,循环神经网络和 LSTMs 前所未有地使用…
towardsdatascience.com](/deep-learning-for-nlp-anns-rnns-and-lstms-explained-95866c1db2e4) [## NLP 的深度学习:用 Keras 创建聊天机器人!
了解如何使用 Keras 构建递归神经网络并创建聊天机器人!谁不喜欢友好的机器人…
towardsdatascience.com](/deep-learning-for-nlp-creating-a-chatbot-with-keras-da5ca051e051)
- 封面图片来自。
- 图标来自 *面图标 。
- 所有其他图像都是自己制作的。**


浙公网安备 33010602011771号