TowardsDataScience-博客中文翻译-2020-七十六-

TowardsDataScience 博客中文翻译 2020(七十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

延迟支付行为:这是英国经济的定时炸弹吗?

原文:https://towardsdatascience.com/late-payment-practices-is-this-the-ticking-time-bomb-of-the-uk-economy-5b958e4dd109?source=collection_archive---------38-----------------------

英国大企业支付实践数据分析

Jurica koleti 在 Unsplash 上拍摄的照片

对许多中小企业来说,延迟付款仍然是一个有争议的问题。大企业经常强加延长的条款或延迟付款,因为这使他们能够获得廉价的流动资金信贷。虽然这是常见的做法,但未能及时向供应商付款会对供应商的现金流和交易能力产生不利影响。在严重的情况下,延迟付款会危及企业的偿付能力。据估计,仅在英国,就有 260 亿英镑被拖欠中小企业的供应商逾期付款所套牢。及时付款每年可以避免 50,000 家企业死亡,这给英国经济造成了 25 亿英镑的损失。

为打击逾期付款行为,英国政府于 2017 年 4 月出台立法,要求英国大公司和有限责任合伙企业(LLP)每年发布两次关于其付款表现和政策的报告。不遵守这些规则是一种刑事犯罪,可能会导致巨额罚款。

延期付款是否会让企业感到羞愧,从而做出更好的行为?

丢人!丢人!

要回答这个问题,让我们看看商业能源部&产业战略(BEIS)发布的截至 2020 年 1 月 28 日的支付实践报告。

数据概述

迄今为止,7,887 家公司提交了 25,800 份报告。数据质量不高,数据准确性也值得怀疑。在这些报告中:

  • 2632 份不完整,几乎没有任何有用的信息。
  • 一些公司提交了相同的付款信息,一些公司在同一时期提交了几份文件,但包含不同的条目。
  • 并非所有报告期都是六个月。例如,时间段的范围从 29 天到一整年。
  • 公司报告的平均支付时间为 0 天和 1,000 天。

数据清理后,我们剩下一组来自 7287 家公司的23028 份报告。并非所有这些公司都一贯提交报告。

提交的报告不一致

一些公司在首次提交报告后,没有按照要求提交报告。或许对公司来说,未报告的罚款还不够大?

一个公司的平均支付时间是多少?

公司向供应商付款的平均天数分布

  • 平均而言,一家英国公司向供应商付款需要 37 天
  • 64%的公司平均支付时间超过 30 天
  • 9%的公司给出的平均支付时间超过 60 天

发票延迟支付的比例是多少?

所有报表中延迟支付发票的百分比分布

  • 平均而言,30%的款项比约定的期限晚支付
  • 21%的公司报告延迟支付 50%或更多的发票
  • 2%的公司报告延迟支付 90%或更多的发票

那些签了即时支付码的公司怎么样?

即时支付代码(PPC)为支付实践设定了标准。它由 CICM 特许信用管理协会代表 BEIS 管理。守则要求在 60 天内支付至少 95%的发票。

  • 只有 9%的公司称自己是 PPC 成员
  • PPC 的参与者报告平均支付时间为 34 天,25%的发票被延迟支付
  • 相比之下,非参与者报告的平均支付时间为 37 天,30%的发票被延迟支付

PPC 签署方的合规性

上图显示,尽管他们是成员,但只有 47%的 PPC 参与者遵守《守则》的要求。

提供金融解决方案的公司表现更好吗?

在他们的报告中,公司被要求公布他们是否提供电子发票或供应链融资。这些是什么?为什么它们会对支付实践产生影响?

一张 e(电子)发票 包含来自供应商的数据,其格式可以无缝接入买方的应付账款系统。这减少了手动处理时间和错误。

供应链融资 涉及三方:买方、卖方和金融机构。工作原理:

  1. 供应商向买方开具发票
  2. 买方向金融机构确认发票已被批准支付
  3. 供应商直接获得价值(减去少量费用)
  4. 付款到期时,买方向贷方付款。

因此,供应商很快得到付款,买方可以利用延长的付款条件。这有助于买家和供应商稳定和管理他们的日常现金流。

电子发票

******

按电子发票可用性划分的主要支付行为分布**

  • 24%的公司报告提供电子发票
  • 那些不提供电子发票的公司报告平均支付时间为 36 天,并且延迟支付 30%的发票
  • 对于提供电子发票的公司,虽然平均支付时间更长(40 天),但他们更有可能按时支付,28%的发票被延迟支付。

供应链融资:

******

按供应链融资的可用性划分的主要支付行为分布**

  • 供应链融资的使用率很低,只有 7%的公司报告说他们提供供应链融资。
  • 那些不提供供应链融资的公司报告平均支付时间为 36 天,30%的发票被延迟支付
  • 对于提供供应链融资的公司,平均付款时间更长(49 天),但延迟付款的比例仍保持在 30%

随着时间的推移,我们会看到任何改进吗?

要求大型企业公布其支付方式的规定生效还不到三年。在这段时间内,没有证据表明大企业已经做了 180 度大转弯,但数据显示情况正在改善。

  • 2017 年,公司支付的平均时间是 44 天。这一数字下降了一周多,公司报告 2019 年的平均时间为 36 天。
  • 迟缴率的改善并不明显。发票延迟支付的比例从 2017 年的 30%降至 2019 年的 28%。

过去 3 年的付款等待时间

上图揭示了这一趋势。它表明,对于没有逾期的发票,付款时间有了较大的改善,但对于逾期的发票,变化较小。

我们学到了什么?

尽管大型企业被要求提交其支付行为的报告,但这种做法似乎是不完整和不一致的。剔除异常报告后,我们分析了 2017 年 4 月至 2020 年 1 月期间收到的来自 7,287 家公司的 23,028 份完整的支付实践报告。

  • 一家公司支付发票的平均时间是 37 天,30%的付款晚于商定的条款。
  • PPC 的参与者支付发票的速度更快(34 天),并且更及时地支付(25%)。然而,这些公司中不到一半符合 PPC 的要求,PPC 规定至少 95%的款项必须在发票开具后 60 天内支付。
  • 提供电子发票的公司需要更长的时间来支付(40 天),但更善于在商定的期限内支付(28%)
  • 提供供应链融资的公司比平均支付时间(49 天)多花了 12 天,在及时支付方面也不比普通人强。

有证据表明支付表现略有改善,但这需要注意,因为 2019 年的数据尚未完全成熟。在撰写本报告时,公司还有几天时间提交截至 2019 年的财务报告。

显而易见的是,这种被公开点名羞辱的特殊威胁并不是大企业推动支付条款限制的灵丹妙药。也许 2019 年 9 月出台的即时支付政策会让天平倾斜?也许 PPC 的签约国会被吓得顺从,因为去年 CICM 开始暂停会员资格。或者,我们能否接触到足够数量的用脚走路的中小企业,让表现不佳的企业表现良好?

谁知道呢?但这确实值得一看。

点击这里,查看我的工作笔记链接。要查看底层数据,点击这里

除非另有说明,本支付实务报告数据受 开放政府许可 v3.0 许可。

主题建模的潜在狄利克雷分配解释:算法和 Python Scikit-Learn 实现

原文:https://towardsdatascience.com/latent-dirichlet-allocation-for-topic-modelling-explained-algorithm-and-python-scikit-learn-c65a82e7304d?source=collection_archive---------17-----------------------

用于主题建模的潜在狄利克雷分配算法和 Python Scikit-Learn 实现。

潜在狄利克雷分配是一种无监督的机器学*形式,通常用于自然语言处理任务中的主题建模。对于这些类型的任务,它是一个非常受欢迎的模型,其背后的算法非常容易理解和使用。此外,Scikit-Learn 库有一个非常好的算法实现,所以在本文中,我们将关注使用潜在 Dirichlet 分配的主题建模。

拉斐尔·沙勒在 Unsplash 上拍摄的照片

潜在狄利克雷分配概述

  • 什么是主题建模
  • 什么是无监督机器学*
  • 潜在的狄利克雷分配应用
  • 潜在狄利克雷分配算法
  • 构建潜在的狄利克雷分配数据集
  • 使用 Scikit-Learn 实现潜在的狄利克雷分配

什么是主题建模

主题建模是一项无监督的机器学*任务,我们试图发现能够描述一组文档的“抽象主题”。这意味着我们有一个文本集,我们试图找到单词和短语的模式,这些模式可以帮助我们对文档进行聚类,并按照“主题”对它们进行分组。

我把主题放在引号中,我称它们为抽象主题,因为这些不是显而易见的主题,我们不需要它们。我们假设相似的文档会有相似的单词和短语模式。

例如,假设我们有 100 个文本的集合。我们浏览了每一篇文章,发现其中有 10 篇包含“机器学*”、“训练”、“有监督的”、“无监督的”、“数据集”等词汇。我们可能不知道这些词是什么意思,也不在乎。

我们在这里只看到一种模式,即 10%的文章包含这些词,我们得出结论,它们应该包含在同一主题中。我们实际上不能命名主题,同样,这是不必要的。我们可以把这 10 篇文章归纳成同一个主题。当我们得到一个我们从未见过的新文本时,我们查看它,我们发现它包含这些单词中的一些,然后我们将能够说"嘿,这与其他 10 篇文章属于同一类别!

什么是无监督机器学*

无监督机器学*是一种机器学*模型,在这种模型中,我们试图在没有任何先验知识,也不知道我们是否正确的情况下推断数据模式。使用这种类型的模型,我们试图在数据中找到模式,然后我们可以使用它们来聚类、分类或描述我们的数据。

潜在狄利克雷分配是一种无监督的机器学*。我们在开始之前并不知道文档的主题,只能指定要找多少个主题。在解析的最后,我们可以查看结果并判断它们是否有帮助。

潜在的狄利克雷分配应用

潜在狄利克雷分配主要用于主题建模。现在我们可以考虑为什么我们需要主题建模。

通过主题建模,我们可以对一组文档进行聚类,从而将更多相似的文档分组在一起,将更少相似的文档放入不同的类别中。这可以用来分析和理解数据集。

我们还可以根据这种算法自动组织我们的文档,然后,当一个新文档出现在数据集中时,我们可以自动将其放入正确的类别中。

此外,这可以用于改进处理文本文档的应用程序中的文本搜索和文本相似性特征。

潜在狄利克雷分配算法

潜在狄利克雷分配算法只需几个简单的步骤就能工作。我们需要做的唯一预处理是我们在几乎所有的文本处理任务中所做的:从我们所有的文档中删除停用词(很可能在大多数文档中出现并且不会带来任何价值的词)。

  1. 建立将由 LDA 算法识别的多个 n 主题。怎样才能找到完美的题目数量?嗯,这不是很容易,通常是一个反复试验的过程:我们尝试不同的值,直到我们对结果满意。或者,也许我们很幸运,我们有关于数据集的其他信息,允许我们建立完美的主题数量。
  2. 将每个文档中的每个单词分配给一个临时主题。这个临时话题一开始会是随机的,但是下一步会更新。
  3. 对于这一步,我们将遍历每个文档,然后遍历文档中的每个单词,并计算 2 个值
  • 该文档属于某个主题的概率;这基于该文档中有多少单词(除了当前单词)属于当前单词的主题
  • 因为当前单词而被分配给当前单词的主题的文档的比例。

我们将运行步骤 3 一定次数(在开始运行算法之前建立)。最后,我们将查看每个文档,根据单词找到最流行的主题,并将该文档分配给该主题。

构建潜在的狄利克雷分配数据集

有时,当我了解一个新概念时,我喜欢建立自己的小数据集,以便更快地学*。我喜欢这样有两个原因:

  • 没有浪费时间清理数据。我知道这对于一个机器学*工程师或者数据科学家来说是非常重要的技能,但是这个话题不是这里的重点。如果我想学*一个算法,我会建立我自己的小而干净的数据集,让我可以玩它。
  • 更快的试错过程:建立我自己的数据集将允许我使它足够大以提供结果,但又足够小以快速运行。

对于 LDA 算法,我将获得 6 个维基百科页面的摘要部分(2 个关于城市,2 个关于技术,2 个关于书籍),并将它们用作 LDA 算法要聚类的文档。然后,我将提供另一页的第 7 个摘要,并观察它是否被放在正确的类别中。

为了从维基百科中提取文本,我将使用维基百科 python 包。

pip3 install wikipedia

我将使用一个小类来下载摘要。

import wikipedia

class TextFetcher:

    def __init__(self, title):
        self.title = title
        page = wikipedia.page(title)
        self.text = page.summary

    def getText(self):
        return self.text

然后我可以用这个类提取数据。正如我前面提到的,唯一需要做的预处理是删除停用词。为此,我将使用 nltk 包。

def preprocessor(text):
    nltk.download('stopwords')
    tokens = word_tokenize(text)
    return (" ").join([word for word in tokens if word not in stopwords.words()])

if __name__ == "__main__":

    textFetcher = TextFetcher("London")
    text1 = preprocessor(textFetcher.getText())
    textFetcher = TextFetcher("Natural Language Processing")
    text2 = preprocessor(textFetcher.getText())
    textFetcher = TextFetcher("The Great Gatsby")
    text3 = preprocessor(textFetcher.getText())
    textFetcher = TextFetcher("Machine Learning")
    text4 = preprocessor(textFetcher.getText())
    textFetcher = TextFetcher("Berlin")
    text5 = preprocessor(textFetcher.getText())
    textFetcher = TextFetcher("For Whom the Bell Tolls")
    text6 = preprocessor(textFetcher.getText())

    docs = [text1, text2, text3, text4, text5, text6]

既然我们已经准备好了数据集,我们就可以继续算法实现了。

使用 Scikit-Learn 实现潜在的狄利克雷分配

scikit-learn 包很好地实现了 LDA 算法。我们今天要用这个。

pip3 install scikit-learn

单词矢量化

第一步是把我们的单词转换成数字。虽然我们正在与文字打交道,但许多文本处理任务都是用数字来完成的,因为它们对计算机来说更容易理解。

scikit-learn 包中的 CountVectorizer 类可以将一个单词转换成实数向量。让我们用我们的数据集来做这件事。

countVectorizer = CountVectorizer(stop_words='english')
    termFrequency = countVectorizer.fit_transform(docs)
    featureNames = countVectorizer.get_feature_names()

现在,让我们将潜在的狄利克雷分配算法应用于我们的单词向量,并打印出我们的结果。对于每个主题,我们将打印前 10 个单词。

lda = LatentDirichletAllocation(n_components=3)
    lda.fit(termFrequency) for idx, topic in enumerate(lda.components_):
        print ("Topic ", idx, " ".join(featureNames[i] for i in topic.argsort()[:-10 - 1:-1]))

结果是这样的:

Topic  0 berlin city capital german learning machine natural germany world data
Topic  1 novel fitzgerald gatsby great american published war book following considered
Topic  2 london city largest world europe populous area college westminster square

正如我们之前所讨论的,这些信息可能不会告诉你太多,但它足以让我们正确地分类一个关于巴黎的新文本(在我们再次矢量化这个文本之后)。

text7 = preprocessor(TextFetcher("Paris").getText())
    print (lda.transform(countVectorizer.transform([text7])))

结果是这样的:

[[0.17424998 0.10191793 0.72383209]]

这 3 个是我们的文本属于 LDA 算法生成的 3 个主题之一的概率。我们可以看到,最高概率(72%)告诉我们,这段文字也应该属于第 3 个题目,所以在同一个讲城市的题目里。我们可以看到,这是一个从非常小的数据集获得的非常好的结果。

结束语

在本文中,我们讨论了潜在的狄利克雷分配算法的一般概述。然后,我们建立了一个自己的小数据集,并测试了算法。我对这个结果非常满意,希望你也是。

本文原载于 程序员背包博客 。如果你想阅读更多这类的故事,一定要访问这个博客。

非常感谢您阅读本文!对更多这样的故事感兴趣?在 Twitter 上关注我,地址是@ b _ dmarius,我会在那里发布每一篇新文章。

潜在的狄利克雷分配:直觉,数学,实施和可视化与 pyLDAvis

原文:https://towardsdatascience.com/latent-dirichlet-allocation-intuition-math-implementation-and-visualisation-63ccb616e094?source=collection_archive---------11-----------------------

TL;DR — 潜在狄利克雷分配 (LDA,有时 LDirA/LDiA)是在文本数据中寻找主题的最流行和可解释的生成模型之一。我已经提供了一个基于网络搜集的职位描述数据的示例笔记本。虽然在像 20Newsgroups 这样的规范数据集上运行 LDA 会提供更清晰的主题,但重要的是要见证主题识别在“野外”有多么困难,以及你可能如何实际上找不到清晰的主题——使用无监督学*,你永远无法保证找到答案!

  • 致谢:对我理解最有帮助的是路易斯·塞拉诺在 LDA (2020)上的两个视频。很多直觉部分都是基于他的解释,我强烈建议你访问他的视频进行更深入的剖析。

1.0 —生成文档的 LDA“机器”

内容:

直觉

数学

实施和可视化

直觉

假设您有一个不同新闻文章的集合(您的文档语料库,并且您怀疑在所述语料库中有几个经常出现的主题——您的目标是找出它们是什么!为了达到这个目标,你需要做一些关键的假设

  • d分布假设 : 频繁出现在一起的词,很可能意义相*;
  • 每个题目都是不同单词的混合(图 1.1);
  • 每个文档都是不同主题的混合体(图 1.2)。

1.1 —混合单词的主题

在图 1.1 中,你会注意到主题“健康和医学”有各种各样的与之相关的词,其关联程度(“癌症”比“血管”或“锻炼”更紧密)。请注意,不同的单词可以与不同的主题相关联,例如单词“cardio”。

1.2 —混合主题的文档

在图 1.2 中,你会看到一个单独的文档可能涉及多个主题(如左边的颜色代码所示)。像“受伤”和“恢复”这样的词也可能属于多个主题(因此我用了不止一种颜色)。

现在 LDA 是一个生成模型——它试图确定生成文章和话题的潜在机制。想象一下,如果有一台具有特定设置的机器可以输出文章,但我们看不到机器的设置,只能看到它产生的内容。LDA 创建一组具有不同设置的机器,并选择给出最佳拟合结果的机器(Serrano,2020)。一旦找到最好的一个,我们看一看它的“设置”,并从中推断出主题。

那么这些设置是什么呢?

首先,我们有一个叫做狄利克雷(发音像迪-里什-雷)的东西,先于主题。这是一个表明我们的话题有多稀疏或者有多混杂的数字。在 L Serrano 的视频里(我强烈推荐!)他阐述了如何在视觉上将其视为一个三角形(图 1.3),其中点代表文档,它们相对于角的位置(即主题)代表它们与每个主题的关系(2020)。所以一个非常接*“运动”顶点的点将几乎完全是关于运动的。

1.3 —主题的狄利克雷分布

在左边的三角形中,文档被很好地分开,大部分文档被整齐地塞到角落里(这对应于一个低的 Dirichlet 先验,alpha <1); on the right they are in the middle and represent a more even mix of topics (a higher Dirichlet prior, alpha> 1)。查看图 1.2 中的文档,考虑一下主题的组合,想想你认为它应该放在右边三角形的什么位置(我的答案是它应该是最靠*体育角的上方的点)。**

第二,我们有(我们词汇表中的所有单词)的狄利克雷先验。这个数字(它的名字是贝塔)*与阿尔法的功能几乎完全相同——除了它决定了主题如何在术语 中分配。*

1.4 各项的狄利克雷分布;这些数字与每个单词与每个主题的关联程度成正比

正如我们之前所说的,主题被假设为不同术语的混合(更准确地说是分布)。在图 1.4 中,“运动”主要是指“伤害”。“健康&医学”在“心脏”和“损伤”之间徘徊,与“祈祷”一词毫无关联。

**但是等等,我们的词汇不仅仅由三个单词组成!你说得对!我们可以有一个由 4 个单词组成的词汇表(如图 1.5 所示)!麻烦在于,可视化一个典型的由 N 个单词组成的词汇表(其中 N 可能是 10000)需要一个广义版本的三角形,但是是在N-1维度中(这个术语是 n-1 单形)。这就是视觉效果停止的地方,我们相信更高维度的数学将会像预期的那样发挥作用。这也适用于主题——我们经常会发现自己有 3 个以上的主题。

1.5-根据术语的分布,哪个主题是红色的?

一个重要的澄清:在 LDA 中,我们从α和β的值开始作为超参数,但是这些数字仅仅告诉我们我们的点(文档/主题)是否通常集中在它们三角形的中间或者更靠*角落。三角形(单纯形)内的实际位置由机器猜测——猜测不是随机的,它被狄利克雷先验加权。

因此,机器创建了两个狄利克雷分布,将文档和主题分配给,然后基于这些分布生成文档(图 1.6)。那么,最后一步是如何发生的,即部分?

1.6 —生成文档的 LDA“机器”

还记得在开始时我们说过主题被看作是单词的混合/分布,文档被看作是主题的混合/分布吗?在图 1.7 中从左到右,我们从一个文档开始,在三角形的某个地方,在我们的 3 个主题之间撕裂。如果它在“体育”角附*,这意味着文档将主要是关于体育的,也会提到一些“宗教”和“健康医学”。所以我们知道文档的主题构成→因此我们可以估计会出现什么单词。我们将主要从体育中抽取(即随机抽取)单词,一些来自健康&医学,极少量来自宗教(图 1.7)。有个问题问你:看图 1.7 底部的三角形,你觉得2* 会不会上来?*

1.7 —两种狄利克雷分布如何影响我们的文档生成

答案是它可能:记住主题是单词的混合。你可能会想,单词 2* 与黄色(宗教)主题有很强的相关性,由于这个主题在本文档中很少出现,单词 2 不会出现太多。但是要记住 a. 单词 2 也与蓝色、体育话题和 b .单词是概率上的样本,所以每个单词都有一些非零的出现几率。*

我们最终生成的文档中的单词(在图 1.7 的右端)将与原始文档中的单词进行比较。我们不会得到相同的文档,但是当我们将一系列不同的 LDA“机器”与一系列不同的发行版进行比较时,我们发现其中一个比其他的更接*于生成文档,这就是我们选择的 LDA 模型。

数学

正常的统计语言模型假设您可以通过从单词的概率分布中进行采样来生成文档,即对于我们词汇表中的每个单词,都有一个该单词出现的关联概率。

LDA 给这种安排增加了一层复杂性。它假设了一个主题列表。每个文档 m 是这些 k 主题的概率分布,每个主题是我们词汇表 V 中所有不同术语的概率分布。也就是说每个词在每个题目中出现的概率是各种各样的。

生成文档的全概率公式如下图 2.0 所示。如果我们将它分解,在右边我们会得到三个乘积和:

  • 主题随词条的狄利克雷分布:(对应图 1.4 和 1.5)对于每个主题 iK 个主题中, i. 的词的概率分布是什么
  • 文档在主题上的狄利克雷分布:(对应图 1.3)对于我们规模为 M、的语料库中的每个文档 j、的主题概率分布是什么
  • 给定文档中某个主题出现的概率 X 给定主题中某个单词出现的概率:(对应图 1.7 中的两个矩形)某个主题、出现在该文档中的可能性有多大,然后给定那些主题,某个单词、出现的可能性有多大。

2.0 — LDA 公式

前两个和包含对称狄利克雷分布,这是我们的文档和主题的先验概率分布(图 2.1 显示了一组一般的狄利克雷分布,包括对称分布)。

2.1-由 emperistor-Own 工作,CC BY-SA 4.0,https://commons.wikimedia.org/w/index.php?curid=49908662

第三个和包含两个多项式分布,一个针对主题,一个针对单词,即我们从主题的概率分布中抽取主题,然后对于每个主题实例,我们从该特定主题的单词的概率分布中抽取单词。

正如在直觉部分末尾提到的,使用最终概率,我们试图生成与原始文档中相同的单词分布。实现这一点的概率非常非常低,但是对于α和β的某些值,概率会更低。

解读 LDA 模型及其主题

我们用什么标准来发现我们的潜在主题?正如雪莉和西维尔所说:

“为了解释一个主题,人们通常检查该主题中最可能出现的术语的排序列表,[……]。以这种方式解释主题的问题是,语料库中的常用术语经常出现在多个主题的列表顶部附*,这使得很难区分这些主题的含义。”(2014)

这正是我们在下一节实现中遇到的问题。因此,我们使用另一种衡量标准来解释我们的主题— 相关性 (Shirley 和 Sievert,2014)。

关联

这是一个可调整的指标,它可以平衡某个术语在特定主题中的出现频率与该术语在整个文档语料库中的出现频率。

换句话说,如果我们有一个在某个主题中非常流行的术语,相关性允许我们衡量它的流行程度有多少是因为它非常特定于该主题,有多少是因为它只是一个到处出现的作品。后者的一个例子是工作描述数据中的“学*”。当我们用一个较低的 lambda 调整相关性时(即惩罚那些碰巧在所有主题中频繁出现的术语),我们看到“学*”并不是一个特别的术语,它之所以频繁出现只是因为它在语料库中普遍存在。

相关性的数学定义是:

  • 相关度
  • ⍵——我们词汇中的一个术语
  • k — 我们的 LDA 制作的主题之一
  • λ — 可调权重参数
  • 𝝓kw —某个术语出现在特定主题中的概率
  • pw—一个词在整个语料库中出现的概率

除了λ, λ,所有项都是从 LDA 数据和模型中导出的。我们将在下一节中调整 lambda,以帮助我们获得更有用的见解。原论文作者将 lambda 保持在 0.3 到 0.6 的范围内(Shirley 和 Sievert,2014)。

实现和可视化

sklearn 的 LatentDirichletAllocation 模型的实现遵循大多数 sklearn 模型的模式。在我的笔记本中,我:

  1. 预处理我的文本数据,
  2. 将其矢量化(产生文档术语矩阵),
  3. Fit _ 使用 LDA 转换它,然后
  4. 检查结果,看看是否有任何紧急的,可识别的主题。

最后一部分是高度主观的(记住这是无监督学*),并不能保证揭示任何真正有趣的东西。此外,识别主题(如聚类)的能力取决于您对数据的领域知识。我还建议修改 alpha 和 beta 参数,以符合您对文本数据的期望。

我使用的数据是来自 indeed.co.uk 的职位描述数据。除了文本,dataframe 还有许多其他属性,包括我是否使用了搜索术语“数据科学家”、“数据分析师”或“机器学*工程师”。我们可以在 LDA 主题中找到一些原始搜索类别吗?

在下面的要点中,你会看到我已经将我的数据矢量化,并将其传递给 LDA 模型(这发生在 data_to_lda 函数下)。

运行这段代码和 print_topics 函数将产生如下结果:

*Topics found via LDA on Count Vectorised data for ALL categories:

Topic #1:
software; experience; amazon; learning; opportunity; team; application; business; work; product; engineer; problem; development; technical; make; personal; process; skill; working; science

Topic #2:
learning; research; experience; science; team; role; work; working; model; skill; deep; please; language; python; nlp; quantitative; technique; candidate; algorithm; researcherTopic #3:
learning; work; team; time; company; causalens; business; high; platform; exciting; award; day; development; approach; best; holiday; fund; mission; opportunity; problem

Topic #4:
client; business; team; work; people; opportunity; service; financial; role; value; investment; experience; firm; market; skill; management; make; global; working; support...*

“print_topics”功能按概率降序给出每个主题的术语,其中可以提供信息。正是在这个阶段,我们可以开始尝试从我们的模型中标记出新出现的、潜在的主题。例如,主题 1 似乎与 ML 工程师的技能和需求关系不大(提到“amazon”与使用 AWS 有关——这是我在另一个笔记本中从项目的 EDA 阶段发现的);与此同时,鉴于“市场”、“金融”、“全球”等术语,主题 4 显然更面向客户或面向业务。

现在这两个类别对你来说可能有点牵强,这是一个公平的批评。你可能已经注意到,使用这种方法来确定主题是很难的。所以,让我们转向 pyLDAvis!

皮尔戴维斯

使用 pyLDAvis,LDA 数据(在我们的例子中是 10 维的)已经通过 PCA(主成分分析)被分解为仅 2 维的。因此,为了可视化的目的,它被展平了。我们有十个圆,每个圆的中心代表我们的主题在潜在特征空间中的位置;主题之间的距离说明了主题相似(不相似)的程度,圆圈的面积与每个主题对应的文档数量成正比。

下面我展示了如何在 pyLDAvis 中插入一个已经训练好的 sklearn LDA 模型。令人欣慰的是,负责将最初的 LDAvis (是 R 模型)改编成 python 的人让它与 sklearn 有效地通信。

在图 3.0 中是我们生成的图:

图 3.0 — pyLDAvis 交互图

解读皮尔戴维斯地块

LDAvis 图分为两部分——一部分是我们的 n 维 LDA 数据的二维“扁平”重绘图,另一部分是交互式的、变化的术语分布水平条形图。图 A1.0 显示了这两种情况。需要注意的一个重要特征是,右边的条形图以相关性递减顺序显示了主题中的术语,但条形显示了术语的频率。红色部分代表纯粹在特定主题内的术语频率;红色和蓝色表示文档语料库中的总术语频率。**

调整λ(λ)**

如果我们设置λ等于 1,那么我们的相关性完全由该词与该主题的概率给出。将它设置为 0 将导致我们的相关性由该词对主题的特异性决定-这是因为右边的词将某个词在特定主题中出现的概率除以该词一般出现的概率-因此,当我们使用较低的 λ 值时,高频词(如“团队”、“技能”、“业务”)的相关性将大大降低。

图 3.1-将λ设置为 1

在图 3.1λ 被设置为 1,你可以看到这些术语通常与占主导地位的术语相匹配(例如,在我们打印出的每个主题的最流行术语中)。这只针对主题 1,但是当我改变主题时,前 30 个最相关的术语的分布几乎没有变化!

现在,在图 3.2λ 被设置为 0,术语完全改变了!

图 3.2-λ设置为 0

现在我们有了非常具体的术语,但是请注意顶部的刻度——最相关的词出现了大约 60 次。超过 6000 英镑后,下降幅度相当大!还有,这些话不一定会告诉我们什么有趣的东西。如果你用这个 lambda 值选择一个不同的主题,你将继续得到不一定那么重要的垃圾术语。

在图 3.3 中,我将 lambda 设置为 0.6,我正在探索主题 2。马上就有一个围绕工程师工作的重要主题,比如“aws”、“云”和“平台”。

图 3.3-λ= 0.6

用 pyLDAvis 可以做的另一件大事是直观地检查给定单词的条件主题分布,只需将鼠标悬停在单词上即可(图 3.4)。下面我们可以看到有多少“NLP”被分成几个主题——不是很多!这让我更有理由相信主题 6 关注的是 NLP 和基于文本的工作(像“语音”、“语言”、“文本”这样的术语在这方面也有帮助)。对我来说,一个有趣的发现是“研究”和“博士”在这个话题中如此强烈地同时出现。

图 3.4——“自然语言处理”的条件主题分布

这是否意味着行业中 NLP 为重点的角色比其他角色需要更高的教育程度?他们是否比其他职位更需要以前的研究经验?NLP 的角色可能更专注于实验技术,因此需要具有前沿知识的人吗?

虽然生成的交互图不能提供具体的答案,但它可以为我们提供一个进一步研究的起点。如果你在一个可以运行主题建模的组织中,你可以使用 LDA 的潜在主题为调查设计、A/B 测试提供信息,甚至将其与其他可用数据相关联,以找到有趣的相关性!

祝你在话题建模上好运。如果你喜欢这篇冗长的文章,请给我你认为合适的掌声。如果你对 LDA 有所了解,并且认为我做了一些甚至是部分错误的的事情,请给我留言(反馈是一份礼物,诸如此类)!

参考文献

  1. Serrano L. (2020)。在线访问:潜在狄利克雷分配(第 1 部分,共 2 部分)
  2. 希沃特 c .和雪莉 K (2014)。LDAvis:一种可视化和解释主题的方法。在线访问:交互式语言学*、可视化和界面研讨会会议录

潜在狄利克雷分配(LDA):主题发现的概率建模方法指南

原文:https://towardsdatascience.com/latent-dirichlet-allocation-lda-a-guide-to-probabilistic-modeling-approach-for-topic-discovery-8cb97c08da3c?source=collection_archive---------29-----------------------

潜在狄利克雷分配在 python 中的实现

来源

潜在狄利克雷分配(LDA)是主题建模中最常用的算法之一。LDA 由 J. K. Pritchard、M. Stephens 和 P. Donnelly 于 2000 年提出,并由 David M. Blei、Andrew Y. Ng 和 Michael I. Jordan 于 2003 年重新发现。在这篇文章中,我将试着给你一个什么是主题建模的概念。我们将学* LDA 如何工作,最后,我们将尝试实现我们的 LDA 模型。

什么是主题建模?

主题建模是机器学*和自然语言处理中最有趣的领域之一。主题建模意味着从文档集合中提取抽象的“主题”。自然语言处理的主要应用之一是在大量的文本文档中了解人们在谈论什么。通读所有这些文档并提取或编辑主题真的很难。在这些情况下,主题建模用于提取文档信息。为了理解主题建模的概念,让我们看一个例子。

假设你正在读报纸上的一些文章,在这些文章中,“气候”这个词出现得最多。所以,从正常意义上来说,你可以说这些文章更有可能是关于气候的。主题建模以统计的方式做同样的事情。它通过聚集相似的单词来产生话题。这里有两个术语:一个是“主题建模”,另一个是“主题分类”。虽然它们看起来相似,但它们是完全不同的过程。第一种是非监督机器学*技术,第二种是监督技术。
让我们详细阐述一下这个概念。

主题分类通常涉及互斥的类别。这意味着每个文档都标有特定的类别。另一方面,主题建模并不相互排斥。同一份文件可能涉及许多主题。由于主题建模是基于概率分布工作的,所以同一文档可能具有跨越许多主题的概率分布。

对于主题建模,您可以使用几种现有的算法。非负矩阵分解(NMF)潜在语义分析或潜在语义索引(LSA 或 LSI)潜在狄利克雷分配(LDA) 是这些算法中的一些。在本文中,我们将讨论潜在的狄利克雷分配,这是主题建模中最常见的算法之一。

潜在狄利克雷分配(LDA)

"潜在狄利克雷分配(LDA)是一个生成统计模型,它允许观察集由未观察到的组来解释,这解释了为什么数据的某些部分是相似的。例如,如果观察是收集到文档中的单词,它假设每个文档都是少量主题的混合物,并且每个单词的出现都归因于文档的一个主题。—维基百科

好吧,让我们试着理解这个定义。

L atent Dirichlet 分配(LDA)的基本思想是,文档被认为是各种主题的随机混合,主题被认为是不同单词的混合。现在,假设你需要一些与动物有关的文章,你面前有成千上万的文章,但你真的不知道这些文章是关于什么的。看完所有这些文章,要找出与动物相关的文章,真的很繁琐。让我们看一个例子。

作为一个例子,让我们考虑我们有四篇文章。第 1 条涉及动物,第 2 条涉及遗传类型,第 3 条涉及计算机类型,第 4 条是动物和遗传类型的组合。作为一个人类,你可以很容易地根据它包含的单词来区分这些主题。但是如果有几千条,每条有几千行,你会怎么做?答案会是这样的——“如果我们能在计算机的帮助下做到这一点,那么我们应该这样做”。是的,借助于潜在的狄利克雷分配,计算机可以这样做。现在我们将试着理解 LDA 是如何工作的。首先,我们将看到 LDA 的图形表示,然后我们将看到概率计算公式。**

上图是 LDA 的图示。在上图中,我们可以看到有六个参数-

α(α)和η*(η)——代表狄利克雷分布。高 alpha 值表示每个文档包含大多数主题,相反,较低的 alpha 值表示文档可能包含较少数量的主题。与 alpha 相同,较高的η值表示主题可能覆盖大多数单词,相反,较低的 eta 值表示主题可能包含较少数量的单词。*

β(β)和θ*(θ)——代表多项式分布。*

z —代表一堆话题

w —代表一串单词

公式的左边表示文档的概率。在公式的右边,有四个术语。公式的第一项和第三项将帮助我们找到主题。第二个和第四个将帮助我们找到文章中的单词。公式右侧的前两项表示狄利克雷分布,右侧的其余部分是多项式分布。

我们假设,在上图中,左边的三角形中,蓝色的圆圈表示不同的文章。现在,如果我们将文章分布在不同的主题上,它将如直角三角形所示分布。蓝色圆圈将移动到三角形的角上,这取决于它在该主题中所占的百分比。这个过程是由公式右边的第一项完成的。现在,我们使用多项式分布根据第一个词的百分比生成主题。

现在,在得到主题后,我们会发现哪些单词与这些主题更相关。这是通过另一个狄利克雷分布来实现的。主题根据单词分布,如下所示。

现在,我们将使用另一个多项式分布来查找与这些主题更相关的单词,并使用该狄利克雷分布生成具有概率的单词。这个过程进行多次。

因此,我们将找到与主题更相关的词,并基于这些主题分发文章。

实施 LDA

你可以在 GitHub 中找到代码。要实现 LDA,您可以使用 gensim 或 sklearn。这里,我们将使用 gensim。

加载数据

为了实现的目的,我使用了 Kaggle 数据集。该数据集由 15 列 2150 个数据集信息组成:

*dataset = pd.read_csv('/content/drive/My Drive/topic modelling/voted-kaggle-dataset.csv')*

数据预处理

为了处理数据,首先,我们选择对这个过程有意义的列。然后删除包含任何缺失值的行。

*modified_dataset = modified_dataset.dropna()*

然后,我们将计算标签列中唯一标签的数量,因为我们会将此视为模型的主题数量。

*unique_tag = []
**for** i **in** range(len(tag_dataset)):
  tag_string = str(tag_dataset[i])
  **if** tag_string != "nan" :
    tag_word=convert(tag_string)
    **for** j **in** range(len(tag_word)):
      **if** tag_word[j] **not** **in** unique_tag:
        unique_tag.append(tag_word[j])
print(len(unique_tag))*

删除标点符号并转换小写的整个文本使训练任务更容易,并提高了模型的效率。

*remove_digits = str.maketrans('', '', string.digits)
exclude = '[!"#$%&**\'**()*+,-./:;<=>?@[**\\**]^_`{|}~]'
**for** column **in** ['Title','Subtitle','Description']:
  modified_dataset[column] = modified_dataset[column].map(**lambda** x : x.translate(remove_digits))
  modified_dataset[column] = modified_dataset[column].map(**lambda** x : re.sub(str(exclude), '', x))*

我们需要标记数据集并执行词干操作。

***import** **nltk**
nltk.download('punkt')
tokenized_dataframe =  modified_dataset.apply(**lambda** row: nltk.word_tokenize(row['Description']), axis=1)
print(type(tokenized_dataframe))**def** lemmatize_text(text):
    **return** [ps.stem(w)  **for** w **in** text **if** len(w)>5]ps = PorterStemmer() 
stemmed_dataset = tokenized_dataframe.apply(lemmatize_text)*

探索性数据分析

通过使用 WordCloud ,我们可以验证我们的预处理是否正确完成。单词云是由单词组合而成的图像,看起来像一个云状。它向我们展示了一个词在文本中出现的频率——它的频率。

***from** **wordcloud** **import** WordCloud
**import** **matplotlib.pyplot** **as** **plt**
*#dataset_words=''*
*#for column in ['Title','Subtitle','Description']:*
dataset_words=''.join(list(str(stemmed_dataset.values)))
print(type(dataset_words))
wordcloud = WordCloud(width = 800, height = 500, 
                background_color ='white',  
                min_font_size = 10).generate(dataset_words) 

plt.figure(figsize = (5, 5), facecolor = **None**) 
plt.imshow(wordcloud) 
plt.axis("off") 
plt.tight_layout(pad = 0) 

plt.show()*

建立模型

对于 LDA 模型,我们首先需要构建一个单词字典,其中每个单词都有一个唯一的 id。然后需要创建一个包含 word_frequency — ->(word_id,word_frequency)的单词 id 映射的语料库。

*dictionary_of_words = gensim.corpora.Dictionary(stemmed_dataset)word_corpus = [dictionary_of_words.doc2bow(word) **for** word **in** stemmed_dataset]*

最后,训练模型。

*lda_model = gensim.models.ldamodel.LdaModel(corpus=word_corpus,
                                                   id2word=dictionary_of_words,
num_topics=329, 
random_state=101,
update_every=1,
chunksize=300,
passes=50,
alpha='auto',
per_word_topics=**True**)*

连贯性衡量一个主题中单词之间的相对距离。

*coherence_val = CoherenceModel(model=lda_model, texts=stemmed_dataset, dictionary=dictionary_of_words, coherence='c_v').get_coherence()

print('Coherence Score: ', coherence_val)*

一致性值:0.4

估价

***for**  index,score **in** sorted(lda_model[word_corpus[2]][0], key=**lambda** tup: -1*tup[1]):
    print("**\n**Score: **{}\t** **\n**Topic: **{}**".format(score, lda_model.print_topic(index, 10)))*

顶部的主题获得了最高的概率,并且它与类似经济的东西相关。

你可以在 GITHUB 上找到所有代码。

参考文献:

  1. 潜伏的狄利克雷分配 作者大卫·m·布雷,安德鲁·y·Ng&迈克尔·乔丹。
  2. 潜伏的狄利克雷分配路易斯·塞拉诺。
  3. 潜在狄利克雷分配(算法)由 ML 论文讲解— A.I .苏格拉底圈— AISC。

最后,感谢您的阅读。感谢任何反馈。

潜在语义分析—从文档中推断出隐藏的主题

原文:https://towardsdatascience.com/latent-semantic-analysis-deduce-the-hidden-topic-from-the-document-f360e8c0614b?source=collection_archive---------4-----------------------

让计算机学*和理解人类语言仍然是最困难的任务。语言包含巨大的词汇,每部作品根据上下文有不同的含义,让计算机学*上下文是一个悬而未决的问题。在此,我们将尝试推导出文本所代表的隐藏主题,并将这些知识用于文档聚类。

主题模型

分析 vidhya —主题建模

主题模型是一种无监督的方式来推断隐藏的主题所代表的文本或文件。这个主题不是诸如体育、新闻或商业之类的实际主题,而是可以用来以最佳方式表示文本的词语。

这种技术非常强大,可以在无人监督的情况下用于文档聚类。如果你使用过谷歌新闻,那么你会看到不同来源的新闻聚集在一起,如果这些新闻代表相似的主题。这是主题建模的应用之一。

潜在语义分析

潜在语义分析是一种通过理解文本的上下文来分析文本和发现隐藏主题的有效方法。

潜在语义分析(LSA)用于发现由文档或文本表示的隐藏主题。这个隐藏的主题然后被用于将相似的文档聚集在一起。LSA 是一种无监督的算法,因此我们不知道文档的实际主题。

为什么是 LSA?

查找相似文档的最简单方法是使用文本的向量表示和余弦相似度。向量表示以向量的形式表示每个文档。这个向量被称为文档术语矩阵。

例如:

a1 = "the petrol in this car is low"
a2 = "the vehicle is short on fuel"

考虑以上两个字符串并形成上下文,我们可以理解这两个字符串是相似的。我们将尝试使用向量表示来找出这些字符串有多相似。

上述示例的文档术语矩阵为:

文档术语矩阵

文档-术语矩阵的大小是(文档数量)*(词汇大小)。词汇量是所有文档中出现的唯一单词的总数。这里的词汇量是 11,文档数是 2

文档之间的相似性是使用文档之间的余弦相似性矩阵来找出的。文档a1a2之间的相似度是 0.3086067,这太低了,因为文档在上下文中大多相似。这是文档术语矩阵的缺点,因此也是向量表示技术的缺点。另一个缺点是词汇量大,因为该语言具有巨大的词汇量,导致矩阵更大且计算成本高。

向量表示法的这一缺点导致了寻找文档间相似性和隐藏主题的新技术的需求。该技术可以解决同义词的问题,并且计算上也不昂贵。建议的技术是潜在语义分析。

LSA 的工作

术语共现矩阵

这个矩阵的维数是(词汇大小)*(词汇大小)。它表示单词在数据集中出现的频率。矩阵帮助我们理解属于一起的单词。

对于上面的例子,术语共生矩阵是:

术语共现矩阵

正如我们所看到的,单词theis是最常见的,但在句子的意思中不是很有用。我们将在本博客的后面看到如何使用这个矩阵及其好处。

概念

LSA 返回代表给定文档的概念而不是主题。概念是以最佳方式表示文档的单词列表。

例如,在体育文档的数据集中,概念可以是

概念 1:球、鞋、目标、胜利

概念 2:球,球棒,得分,裁判

我们可以看到两个概念——概念 1 代表足球,概念 2 代表板球。但是我们可以看到,这些概念可以有重叠的词,因此,整个词集共同代表一个概念,而不是单个的词。LSA 试图使用术语共现矩阵来找到被称为概念的最佳单词集来表示文档。

概念也是通过降维来表示文档的一种方式。

奇异值分解

我们可以看到文档-术语矩阵非常稀疏并且大小很大。在如此大的矩阵上的计算是昂贵的,并且没有非常显著的结果,并且矩阵中的许多值是零。为了降低计算复杂度并获得更相关和有用的结果,使用了 SVD。

SVD 将矩阵分解成三个不同的矩阵:正交列矩阵、正交行矩阵和一个奇异矩阵。

研究之门

奇异值分解的主要优点是我们可以将矩阵的规模从数百万减少到 100 或 1000。上图中的K是矩阵的秩。类似地,如果我们仅使用 k 列和 k 行,那么我们也可以*似地计算矩阵 A,而没有任何大的损失。

在 SVD 计算期间,我们计算代表项共生矩阵的A*(A'T)。这意味着上面矩阵中带有索引(i,j)的值表示术语(I)和术语(j)在文档数据集中同时存在的次数。点击了解 SVD 更多信息

履行

实现是理解概念的最佳方式。我们将使用一个小例子来实现 LSA,这将有助于我们理解 LSA 的工作和输出。

我们将使用的文档是

a1 = "He is a good dog."
a2 = "The dog is too lazy."
a3 = "That is a brown cat."
a4 = "The cat is very active."
a5 = "I have brown cat and dog."

这里我们可以看到,必须生成两个概念,一个代表猫,另一个代表狗。

将此文档列表转换为数据帧:

import pandas as pd
df = pd.DataFrame()
df["documents"] = [a1,a2,a3,a4,a5]
df

df应该是这样的:

文档数据框架

预处理

任何机器学*算法最重要的部分就是数据预处理。数据中存在的噪声越多,模型的准确性越低。

我们将对数据执行四种类型的处理:

  1. 删除文本中的所有特殊字符。
  2. 删除所有少于 3 个字母的单词。
  3. 小写所有字符。
  4. 删除停用词。
#remove special characters
df['clean_documents'] = df['documents'].str.replace("[^a-zA-Z#]", " ")#remove words have letters less than 3
df['clean_documents'] = df['clean_documents'].fillna('').apply(lambda x: ' '.join([w for w in x.split() if len(w)>2]))#lowercase all characters
df['clean_documents'] = df['clean_documents'].fillna('').apply(lambda x: x.lower())

为了移除停用词,我们将对字符串进行标记,然后再次追加所有不是停用词的词。

import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
stop_words = stopwords.words('english')# tokenization
tokenized_doc = df['clean_documents'].fillna('').apply(lambda x: x.split())# remove stop-words
tokenized_doc = tokenized_doc.apply(lambda x: [item for item in x if item not in stop_words])# de-tokenization
detokenized_doc = []
for i in range(len(df)):
    t = ' '.join(tokenized_doc[i])
    detokenized_doc.append(t)df['clean_documents'] = detokenized_doc

经过预处理后,我们的数据将如下所示:

清洗完文件后

文档术语矩阵

我们将使用sklearn来生成文档术语矩阵。

from sklearn.feature_extraction.text import TfidfVectorizervectorizer = TfidfVectorizer(stop_words='english', smooth_idf=True)X = vectorizer.fit_transform(df['clean_documents'])

我们用TfidfVectorizer代替CountVectorizer,因为 tf-idf 是更有效的矢量器。你可以在这里了解传递给TfidfVectorizer 的各种参数,要了解 tf-idf 你可以查看这个链接

X的形状将是(5,6),其中行代表文档数 5,列代表术语数 6。

要查看条款

dictionary = vectorizer.get_feature_names()
dictionary

这将给出一组单词

['active', 'brown', 'cat', 'dog', 'good', 'lazy']

奇异值分解

from sklearn.decomposition import TruncatedSVD# SVD represent documents and terms in vectors 
svd_model = TruncatedSVD(n_components=2, algorithm='randomized', n_iter=100, random_state=122)lsa = svd_model.fit_transform(X)

TruncatedSVD对文档-术语矩阵执行 SVD 函数,并给出降维后的向量。如果你想要矩阵不降维,你应该使用fit而不是fit_transform

n_components是输出数据的维度。n_components的值代表不同主题的数量。可以在这里了解更多 sklearn SVD。

现在,我们将检查分配给文档的主题

pd.options.display.float_format = '{:,.16f}'.format
topic_encoded_df = pd.DataFrame(lsa, columns = ["topic_1", "topic_2"])
topic_encoded_df["documents"] = df['clean_documents']
display(topic_encoded_df[["documents", "topic_1", "topic_2"]])

输出如下所示

电平移动放大器(Level Shift Amplifier)

我们可以看到分配给每个文档的主题。关于狗的文档由 topic_2 表示,关于猫的文档由 topic_1 表示。最后一个既有猫又有狗的文档更多地由 topic_1 表示,但也属于 topic_2。这与 topic_1 更相似,因为文档包含单词browncat,这两个单词在 topic_1 中的权重更高。

我们还可以看到每个主题中术语的权重。

encoding_matrix = pd.DataFrame(svd_model.components_, index = ["topic_1","topic_2"], columns = (dictionary)).T
encoding_matrix

术语-主题矩阵

从上面我们可以看到,术语browncat在 topic_1 中的权重都高于 topic_2

我们已经看到了 LSA 的实施和运作。

应用程序

LSA 是 LSI 和降维算法的先驱。

  1. LSA 用于降维。我们可以在不丢失任何上下文的情况下,将向量的大小从数百万急剧减少到数千。这将有助于我们减少计算能力和执行计算所需的时间。
  2. LSA 用于搜索引擎。潜在语义索引(LSI)是在 LSA 上开发的算法。使用从 LSA 开发的向量来找到匹配搜索查询的文档。
  3. LSA 也可以用于文档聚类。正如我们看到的,LSA 为每个文档分配主题,基于分配的主题,我们可以对文档进行聚类。

潜在语义分析:直觉、数学、实现

原文:https://towardsdatascience.com/latent-semantic-analysis-intuition-math-implementation-a194aff870f8?source=collection_archive---------4-----------------------

我们如何使用无监督学*从文本中提取主题和话题

TL;DR —文本数据深受高维度之苦。潜在语义分析(LSA)是一种流行的降维技术,遵循与奇异值分解相同的方法。LSA 最终根据 r 潜在T5(即隐藏)特征来重构文本数据,其中 r 小于数据中的项数 m 。我将解释概念上的数学上的直觉上的,并使用 20 个新闻组数据集在 Scikit-Learn 中运行一个基本的实现*。*

语言不仅仅是你面前单词的集合。当你阅读一篇文章时,你的脑海中会浮现出一些图像和概念。当你阅读许多文本时,主题开始浮现,即使它们从未被明确地表达出来。我们理解和处理语言的天生能力挑战了算法表达式(目前)。LSA 是最流行的自然语言处理(NLP)技术之一,它试图用数学方法确定文本中的主题。LSA 是一种无监督的学*技术,它基于两个支柱:

  • 分布假说,即意思相*的词频繁出现在一起。JR Firth 的名言“你应该从一个人交往的朋友那里知道一个词”很好地概括了这一点
  • 奇异值分解(SVD——图 1)是一种数学技术,我们将更深入地研究它。

请注意,LSA 是一种无人监督的学*技术——没有基础真理。潜在的概念可能存在,也可能不存在!在我们稍后将使用的数据集中,我们知道有 20 个新闻类别,我们可以对它们进行分类,但这只是出于说明的目的。通常情况下,我们会在非结构化、无标签的数据上使用 LSA。

像所有的机器学*概念一样,LSA 可以分为 3 个部分:直觉、数学和代码。请随意使用目录中的链接,跳到与您最相关的部分。完整的代码可以在这个 Github repo 中找到。

术语注释:通常,当对文本数据进行这种分解时,术语 SVD 和 LSA(或 LSI)可以互换使用。为了简单起见,从现在开始我将使用 LSA。

本文假设对基本的自然语言处理预处理和单词矢量化有一些了解(特别是 tf-idf 矢量化 )。

内容:

  1. 直觉:用政治新闻话题解释
  2. 数学 : SVD 作为矩阵的加权有序和作为一组 3 个线性变换
  3. 代码实现:python 3 中的 Scikit-Learn 和 20 个新闻组数据
  4. 参考文献

1.直觉

(返回目录)

简单来说:LSA 把有意义的文本文件放在不同的地方重新创作,每一部分都表达了看待文本意义的不同方式。如果你把文本数据想象成一个想法,那么对于这个想法会有 n 种不同的方式看待,或者有 n 种不同的方式概念化整个文本。LSA 将我们的数据表简化为一个潜在的概念表。

1:奇异值分解的公式和矩阵维数

假设我们有一些数据表,在本例中是文本数据,其中每行是一个文档,每列代表一个术语(可以是一个单词或一组单词,如“baker's 十二”或“Downing Street”)。这是表示文本数据的标准方式(在文档术语矩阵中,如图 2 所示)。表格中的数字反映了该单词在文档中的重要性。如果数字是零,那么这个单词就不会出现在文档中。

2:文档术语矩阵,在应用了某种矢量化之后,在我们的例子中是 TF-IDF(但是单词包也可以)

不同的文档将涉及不同的主题。假设所有文件都是政治文章,有 3 个主题:外交政策(F.P .)、选举和改革

图 3:文档-主题矩阵(或者文档- 潜在的-概念,如果你喜欢的话)

假设有些文章属于每一个类别,有些属于两个类别,有些属于所有三个类别。我们可以绘制一个表格,其中每行是一个不同的文档(一篇新闻文章),每列是一个不同的主题。在单元格中,我们将使用不同的数字来表示该文档属于特定主题的程度(参见图 3)。

现在,如果我们从概念上将注意力转移到主题本身,我们应该问自己以下问题:我们是否期望某些 单词 在这些主题中更频繁地出现?

如果我们看外交政策,我们可能会看到像“中东”、“欧盟”、“大使馆”这样的术语。对于选举,可能是“选票”、“候选人”、“政党”;对于改革,我们可能会看到“法案”、“修正案”或“腐败”。因此,如果我们在不同的表中绘制这些主题和这些术语,其中的行是术语,我们会看到根据哪个主题最强烈地属于每个术语绘制的分数。自然会有在所有三个文档中出现的术语(“总理”、“议会”、“决定”),这些术语会在所有三列中有分数,反映它们属于任一类别的程度-数字越高,其与该主题的关联越大。因此,我们的第二个表(图 4)由术语和主题组成。

图 4:术语-主题矩阵

现在,最后一个组件作为一个表来解释有点棘手。它实际上是一组数字,一个数字代表一个话题。这些数字代表什么?它们代表了每个主题解释了我们的数据的程度。

他们如何“解释”这些数据?好吧,假设实际上,“改革”并不是贯穿我们文章的突出主题,大多数文章更适合“外交政策”和“选举”。因此,“改革”在这一组中会得到一个很低的数字,低于其他两个。另一种选择是,也许所有三个数字实际上都很低,我们实际上应该有四个或更多的主题——我们后来发现我们的许多文章实际上都与经济学有关!由于只坚持三个主题,我们已经剥夺了自己获得更详细和精确的数据的机会。这个数组的技术名称是“奇异值”。

图 5:奇异值——我们的主题在文本中的相对重要性是什么?

这就是目前为止的直觉。您会注意到我们的两个表有一个共同点(文档/文章),这三个表都有一个共同点——主题,或者它们的某种表示。

现在让我们解释一下这是一种怎样的降维技术。如果我们指定一些文档和主题,就更容易看到优点。假设我们有 100 篇文章和 10,000 个不同的术语(想想所有这些文章会有多少独特的词,从“修正”到“热心的”!).在我们最初的文档术语矩阵中,有 100 行和 10,000 列。当我们开始将数据分解为 3 个部分时,我们实际上可以选择主题的数量——我们可以选择 10,000 个不同的主题,如果我们真的认为这是合理的。然而,我们也许可以用更少的主题来表示数据,比如我们最初谈到的 3 个主题。这意味着在我们的文档主题表中,我们将削减大约 99,997 列,在我们的术语主题表中,我们将做同样的事情。我们从表中丢弃的列和行在图 6 中显示为散列矩形。M 是原始文档-术语表; U 是文档主题表,𝚺 (sigma)是奇异值的数组,而 V-transpose (上标 t 表示原始矩阵 t 已沿其对角线翻转)是文档主题表,但沿其对角线翻转(我将在数学部分解释原因)。

图 6 —我们丢弃了哪些散列

至于表示主题重要性的一组数字,从一组 10,000 个数字中,每个数字越来越小,因为它对应于一个不太重要的主题,我们削减到只有 3 个数字,用于我们剩余的 3 个主题。这就是为什么 LSA 的 Python 实现被称为截断的 SVD:顺便说一下,我们截掉了表的一部分,但是我们稍后会看到代码。同样值得注意的是,我们事先不知道 3 个主题是什么,我们只是假设会有 3 个,一旦我们得到了组件,我们就可以探索它们,看看术语是什么。

当然,我们不只是想回到原始数据集:我们现在有 3 个可以使用的低维组件。在代码和数学部分,我们将讨论我们实际上前进了哪一步。简而言之,一旦我们截断了表(矩阵),我们将得到的产品是文档主题表( U ) 乘以奇异值(𝚺).这可以解释为文档(我们所有的新闻文章)以及它们属于每个主题的程度,然后根据每个主题的相对重要性进行加权。你会注意到,在这种情况下,这个最终表格中遗漏了一些东西,即单词。是的,我们已经超越了文字,我们丢弃了它们,但保留了主题,这是一种表达我们文本的更简洁的方式。

2.数学

(返回目录)

对于数学,我将对 SVD 进行两种不同的解释:首先是可以用于实方阵 M 的一般几何分解,其次是与我们的例子更相关的可分离模型分解。SVD 也用于基于模型的推荐系统。它非常类似于主成分分析(PCA),但是它在稀疏数据上比 PCA 操作得更好(并且文本数据几乎总是稀疏的)。PCA 对数据集的相关性矩阵进行分解,而 SVD/LSA 直接对数据集进行分解。

我们将把这个矩阵分解成组成矩阵。我所说的因式分解本质上与我们用一个数来表示它的因子是一样的,当这些因子相乘时,我们就得到了原始数,例如 A = B * C * D。

这也是为什么它被称为奇异值分解——我们将分解成它的组成部分。

一般几何分解

我们在原始矩阵中无法获得的额外维度,即 r 维度,是潜在概念的数量。一般来说,我们试图把我们的矩阵表示成其他矩阵,它们的一个轴是这组分量。您还会注意到,基于维度,3 个矩阵的乘法(当 V 被转置时)将使我们回到原始矩阵的形状,维度 r 实际上消失了。

在理解数学的过程中,重要的不是确定 u、v 和𝚺中每个数字的代数算法,而是这些乘积的数学性质以及它们之间的关系。

首先,重要的是首先考虑矩阵实际上是什么,它可以被认为是向量空间的变换。在图 7 的左上角,我们有两个垂直的向量。如果我们只有两个变量开始,那么特征空间(我们正在查看的数据)可以在这个空间的任何地方绘制,这个空间由这两个向量描述。现在移到我们图的右边,矩阵 M 被应用到这个向量空间,这就把它转换成新的,在右上角的转换空间。在下图中,M 的几何效应被称为“剪切”向量空间;两个向量 𝝈1𝝈2 实际上是我们在这个空间中绘制的奇异值。

图 7:来源:维基百科;奇异值分解链接;作者:格奥尔格-约翰

现在,就像你们在学校可能记得的点的几何变换一样,我们可以把这个变换 M 看作三个独立的变换:

  1. V引起的旋转(或反射)。注意V * = V-转置*由于 V 是实酉矩阵,所以 V 的复共轭与其转置相同。在矢量项中,V 或 V* 的变换保持基矢量的长度不变;
  2. 𝚺具有沿其奇异值拉伸或压缩所有坐标点的效果。想象一下我们在左下角的圆盘,我们朝着 𝝈2 的方向垂直向下挤压它,然后沿着 𝝈1 的方向水平拉伸它。这两个奇异值现在可以被描绘成椭圆的长半轴和短半轴。你当然可以将此推广到 n 维度。
  3. 最后,应用 U 旋转(或反射)我们的特征空间。我们已经得到了与直接从 M 转换相同的输出。

我还推荐关于 SVD 的优秀的 Wikipedia 条目,因为它对这个过程有特别好的解释和 GIF。

所以,换句话说,其中 x 是任意列向量:

M 对 x 的变换与右边矩阵对 x 的三次变换相同

矩阵 UV* 的性质之一是它们是酉矩阵,因此我们可以说这两个矩阵的列形成了两组正交基向量。换句话说,你可以从 U 得到的列向量会形成它们自己的坐标空间,这样如果有两列 U1U2,你就可以写出空间的所有坐标,作为 U1U2 的组合。这同样适用于 VV1V2的列,并且这将推广到n-尺寸(你将有n-列)。

可分离模型分解

如果我们想象我们的矩阵 M 可以被分解成可分离矩阵的加权和,我们可以得到对 PCA 的相同理解,如下所示。

将我们的数据 M 分解成可分离矩阵的加权和, Ai

矩阵𝐴𝑖据说是可分的,因为它们可以分解成两个向量的外积,用奇异值𝝈I加权。计算形状为( m,)和( n,)的两个向量的外积将给出形状为(m,n)的矩阵。换句话说,计算两个向量中任意两个数的每个可能乘积,并放入新矩阵中。奇异值不仅对和进行加权,而且对和进行排序,因为值是按降序排列的,所以第一个奇异值总是最高的一个。

图 8:我们的可分离矩阵。请注意,≅符号代表这样一个事实,即只有 3 个乘积的分解集*似于我们的原始矩阵,它并不完全等于它。

在图 8 中,你可以看到如何将它可视化。以前我们有高的 U ,正方形σ和长的𝑉- 转置矩阵。现在你可以想象从 U 中取出第一个垂直切片,用第一个奇异值对其所有值进行加权(相乘),然后通过与𝑉 的第一个水平切片进行外积-转置,用这些切片的维度创建一个新矩阵。然后我们把这些乘积加在一起,得到 M。或者,如果我们不做完全求和,而只是部分完成,我们得到的是截断的版本。

因此,对于我们的数据:

  • 其中 M 是我们原来的( m,n )数据矩阵——M 行,n 列; m 个文档,n 个术语
  • u 是一个( m,r )矩阵— m 个文档和 r 个概念
  • σ是一个对角线 ( r,r )矩阵——除了对角线上的值以外,所有值都为零。(但是非零值代表什么呢?
  • v 是一个( n,r )矩阵— n 项,r 个概念

𝚺的值代表了每个潜在概念在多大程度上解释了我们数据中的差异。当这些乘以该潜在概念的 u 列向量时,它将有效地加权该向量。

如果我们将它分解成 5 个组件,它看起来会像这样:

加权文档概念向量和术语概念向量的外积之和

这里原本会有 ru 个向量;5 个奇异值和 n 个𝑣-转置向量。

3.代码实现

(返回内容)

在最后一节中,我们将看到如何使用 Scikit-Learn 实现基本的 LSA。

提取、转换和加载我们的文本数据

from sklearn.datasets import fetch_20newsgroups
X_train, y_train = fetch_20newsgroups(subset='train', return_X_y=True)
X_test, y_test = fetch_20newsgroups(subset='test', return_X_y=True)

清洗和预处理

文本数据的清理通常与数字数据的清理截然不同。您经常会发现自己已经准备好了矢量器、模型,并准备好进行网格搜索,然后提取特征,却发现 cluster x 中最重要的特征是字符串“_ _”…因此您需要返回并做更多的清理工作。下面的代码块是我意识到需要从数据集中删除网站 URL、号码和电子邮件的结果。

from nltk.corpus import stopwords
from nltk.tokenize import RegexpTokenizer
import re
tokenizer = RegexpTokenizer(r'\b\w{3,}\b')
stop_words = list(set(stopwords.words("english")))
stop_words += list(string.punctuation)
stop_words += ['__', '___']# Uncomment and run the 3 lines below if you haven't got these packages already
# nltk.download('stopwords')
# nltk.download('punkt')
# nltk.download('wordnet')def rmv_emails_websites(string):
    """Function removes emails, websites and numbers""" new_str = re.sub(r"\S+@\S+", '', string)
    new_str = re.sub(r"\S+.co\S+", '', new_str)
    new_str = re.sub(r"\S+.ed\S+", '', new_str)
    new_str = re.sub(r"[0-9]+", '', new_str)
    return new_strX_train = list(map(rmv_emails_websites, X_train))
X_test  = list(map(rmv_emails_websites, X_test))

文本数据的符号化和矢量化

我们的模型处理数字,而不是字符串!因此,我们将文本标记化(将所有文档转化为更小的观察实体——在本例中为单词),然后使用 Sklearn 的 TF-IDF 矢量器将它们转化为数字。我建议任何转换过程(尤其是那些需要时间运行的过程)都在数据的前 10 行进行,并检查结果:它们是您期望看到的吗?数据框的形状是你所希望的吗?一旦你对你的代码有信心了,就输入整个语料库。

tfidf = TfidfVectorizer(lowercase=True, 
                        stop_words=stop_words, 
                        tokenizer=tokenizer.tokenize, 
                        max_df=0.2,
                        min_df=0.02
                       )
tfidf_train_sparse = tfidf.fit_transform(X_train)
tfidf_train_df = pd.DataFrame(tfidf_train_sparse.toarray(), 
                        columns=tfidf.get_feature_names())
tfidf_train_df.head()

这将为您提供矢量化的文本数据——文档术语矩阵。对测试集也重复上面的步骤,但是使用 transform, fit_transform。

探索性数据分析 LSA

仅仅为了我们的分解数据的可视化和 EDA 的目的,让我们将我们的 LSA 对象(在 Sklearn 中是 TruncatedSVD 类)适合我们的训练数据,并且只指定 20 个组件。

from sklearn.decomposition import TruncatedSVDlsa_obj = TruncatedSVD(n_components=20, n_iter=100, random_state=42)tfidf_lsa_data = lsa_obj.fit_transform(tfidf_train_df)
Sigma = lsa_obj.singular_values_
V_T = lsa_obj.components_.T

现在让我们想象奇异值——下面的柱状图是否显示了我们对它们的预期?

sns.barplot(x=list(range(len(Sigma))), y = Sigma)

图 9 —我们的奇异值,代表每个潜在概念在多大程度上解释了数据中的差异

让我们通过术语-主题矩阵,V-trans pose 来探索我们减少的数据。 TruncatedSVD 将把它作为形状的 numpy 数组(num_documents,num_components)返回,所以我们将把它变成一个 Pandas dataframe 以便于操作。

term_topic_matrix = pd.DataFrame(data=lsa_term_topic, 
                                 index = eda_train.columns, 
                                 columns = [f'Latent_concept_{r}' for r in range(0,V_T.shape[1])])

让我们将术语-主题矩阵分割成 Pandas 系列(单列数据框),按值排序并绘制它们。下面的代码为我们的第二个潜在组件绘制了这个图(回想一下,在 python 中我们从 0 开始计数),并返回图 10 中的图:

data = term_topic_matrix[f'Latent_concept_1']
data = data.sort_values(ascending=False)
top_10 = data[:10]
plt.title('Top terms along the axis of Latent concept 1')
fig = sns.barplot(x= top_10.values, y=top_10.index)

图 10:尽管看起来很嘈杂,但这里至少有三个术语有一个很强的主题

这些词在我们的第二个潜在成分中排名很高。这个轴的另一端的单词呢(见图 11)?

图 11:在这个时候,作者意识到了旅鼠/词干是多么有用

你可以自己决定这种语义分歧意味着什么。添加更多的预处理步骤将有助于我们摆脱像“说”和“说”这样的词产生的噪音,但我们现在将继续努力。让我们为第六个潜在概念再做一对想象(图 12 和 13)。

图 12

图 13:我们再一次看到技术术语在这些数据中非常突出

在这一点上,由我们来从这些情节中推断出一些意义。概念 5 的轴的负端似乎与技术和科学主题有很强的关联(“空间”、“科学”、“计算机”),但正端也是如此,尽管更侧重于计算机相关的术语(“硬盘”、“驱动器”、“系统”)。

现在澄清一下,确定正确的组件数量需要调优,所以我没有将参数设置为 20,而是将其改为 100。您可能认为这仍然是一个很大的维数,但是我们最初的维数是 220(这是对我们最小文档频率的限制!),所以我们减少了相当大的一部分数据。我将在另一篇文章中探讨如何选择奇异值的最佳数量。现在,我们将继续我们所拥有的。

在我们的建模任务中使用我们的潜在组件

虽然 LSA 是一种无监督的技术,通常用于在未标记的数据中发现模式,但我们在这里使用它来降低标记数据的维度,然后再将其输入模型。我们将比较 LSA 数据和标准 TF-IDF 数据的准确性,以衡量 LSA 从原始数据集中获取了多少有用信息。我们现在有一个形状的训练数据集(11314,100)。文档的数量保持不变,我们已经创建了 100 个潜在的概念。现在,让我们在这一点上和我们的标准 TF-IDF 数据上运行一个模型。下面的实现的目的不是得到一个好的模型,而是比较两个非常不同的数据集。我通过 GridSearchCV 加入了基本的交叉验证,并对 tolerance 超参数进行了少量的调整。如果你这样做是为了建立一个实际的模型,你会比下面写的走得更远。这只是为了帮助您进行基本的实现:

logreg_lsa = LogisticRegression()
logreg     = LogisticRegression()
logreg_param_grid = [{'penalty':['l1', 'l2']},
                 {'tol':[0.0001, 0.0005, 0.001]}]grid_lsa_log = GridSearchCV(estimator=logreg_lsa,
                        param_grid=logreg_param_grid, 
                        scoring='accuracy', cv=5,
                        n_jobs=-1)grid_log = GridSearchCV(estimator=logreg,
                        param_grid=logreg_param_grid, 
                        scoring='accuracy', cv=5,
                        n_jobs=-1)best_lsa_logreg = grid_lsa_log.fit(tfidf_lsa_data, y_train).best_estimator_
best_reg_logreg = grid_log.fit(tfidf_train_df, y_train).best_estimator_print("Accuracy of Logistic Regression on LSA train data is :", best_lsa_logreg.score(tfidf_lsa_data, y_train))
print("Accuracy of Logistic Regression with standard train data is :", best_reg_logreg.score(tfidf_train_df, y_train))

它返回:

Accuracy of Logistic Regression on LSA train data is : 0.45
Accuracy of Logistic Regression with standard train data is : 0.52

性能的下降是显著的,但是您可以将这一点纳入优化流程,并调整潜在组件的数量。这在我们的测试数据(7532 个文档)上表现如何呢?

Accuracy of Logistic Regression on LSA test data is : 0.35
Accuracy of Logistic Regression on standard test data is : 0.37

两者的精确度都大大下降了,但是请注意模型之间的差距有多小!我们的 LSA 模型能够从我们的测试数据中获取与我们的标准模型一样多的信息,而尺寸却不到一半!由于这是一个多标签分类,最好用混淆矩阵来显示(图 14)。当你考虑给定 20 个新闻类别的随机分类概率时,我们的结果看起来明显更好。如果你不熟悉混淆矩阵,作为一个经验法则,我们想最大化对角线上的数字,最小化其他地方的数字。

图 14— 我们测试数据的混淆矩阵(7532 个文档)。y 轴代表实际新闻类别,x 轴代表预测新闻类别。对角线值是所有正确分类的文档。

这就结束了我们在 Scikit-Learn 中对 LSA 的实现。我们已经讨论了这项技术的直觉、数学和编码。

我希望你喜欢这篇文章,并会感谢任何数量的掌声。请在评论中留下任何反馈(积极的或建设性的),尤其是关于数学部分,因为我发现这是最难表达的。

4.参考

(返回目录)

参考资料:

1 L. Hobson,H. Cole,H. Hapke,自然语言处理在行动 (2019),https://www . manning . com/books/Natural-Language-Processing-in-Action

[2] Pedregosa 等著,sci kit-learn:Python 中的机器学* (2011),JMLR 12,第 2825–2830 页。

3 哈姆达维 Y, TF(词频)-IDF(逆文档频)从 python 中的无到有 (2019),走向数据科学

4维基贡献者,奇异值分解https://en.wikipedia.org/wiki/Singular_value_decomposition

潜在随机微分方程

原文:https://towardsdatascience.com/latent-stochastic-differential-equations-a0bac74ada00?source=collection_archive---------30-----------------------

活动讲座

大卫·杜文瑙德| TMLS2019

来自多伦多机器学*峰会的演讲:【https://torontomachinelearning.com/

关于演讲者:

David Duvenaud 是多伦多大学计算机科学和统计学的助理教授。他是加拿大研究生成模型的主席。他的博士后研究是在哈佛大学完成的,在那里他从事超参数优化、变分推理和化学设计。他在剑桥大学获得博士学位,与邹斌·格拉马尼和卡尔·拉斯姆森一起研究贝叶斯非参数。大卫在谷歌研究院的机器视觉团队呆了两个夏天,还联合创立了能源预测和交易公司 Invenia。David 是 Vector Institute 的创始成员,也是 ElementAI 的研究员。

关于演讲:

许多真实世界的数据是不定期采样的,但是大多数时间序列模型需要定期采样的数据。连续时间潜变量模型可以解决这个问题,但直到现在,只有确定性模型,如潜在常微分方程,是有效的反向传播训练。我们将伴随灵敏度方法推广到随机微分方程,构造了一个 SDE,它在时间上向后运行并计算所有必要的梯度,以及一个通用算法,该算法允许随机微分方程通过具有恒定存储成本的反向传播来训练。我们还给出了函数空间中基于梯度的随机变分推理的有效算法,所有算法都使用了自适应黑盒 SDE 解算器。最后,我们将展示对时间序列数据应用潜在随机微分方程的初步结果,并讨论无限深度贝叶斯神经网络的原型。

潜在随机微分方程

潜在变量&期望最大化算法

原文:https://towardsdatascience.com/latent-variables-expectation-maximization-algorithm-fb15c4e0f32c?source=collection_archive---------7-----------------------

机器学*的贝叶斯方法

潜伏的‘烟雾’:(图片来源:作者)

“潜伏”一词源于拉丁语,意思是隐藏起来。大概你们都知道潜热,是相变保持温度不变所需的热能。因此,我们观察到一种变化,但其背后的原因显然是隐藏的。潜在变量模型(LVM)的动机是用一些潜在的隐藏变量来解释数据的表层结构。在这篇文章中,我们将通过一个例子来理解 LVMs 和非常著名的处理这类模型的算法,即期望最大化(EM)算法。我个人认为这个主题是贝叶斯机器学*的核心之一,它将涉及大量的数学知识。但是,相信我,会很容易的。此外,了解 EM 算法的核心概念将有助于您真正理解变分自动编码器和最终 GAN 的基础。你可以从这篇文章中学到什么:

  1. 为什么是潜变量模型(LVM)?
  2. 高斯混合模型(GMM)。
  3. 期望值最大化算法。
  4. 变分推理和 EM 算法。
  5. 用 EM 算法训练 GMM 的例子。

潜在变量和 LVM:

为什么是隐藏变量?潜在变量可能是一些理论概念,或者是无法观察到的真实物理变量。我们用几个现实的例子来阐述吧。在文本文档中,提取的“单词”可以被视为特征。通过分解这些特征,我们可以找到文档的“主题”。因此,观察到的特征(“单词”——树枝、根、叶子、花、果实)会分解为潜在特征(“主题”——树、花园)。每当我们有大规模、高维度的噪声特征时,在潜在特征上建立分类器是有意义的。在对象识别任务的情况下,每个数据点(像素强度矩阵)对应于一个对象的图像。在这种情况下,潜在变量可以解释为对象的位置方向。正如克里斯·毕晓普在他的模式识别书中提到的—

潜在变量的主要作用是允许观察到的变量上的复杂分布根据从较简单的(通常是指数族)条件分布构建的模型来表示。

通常一个 LVM p ,是 2 组变量 x,z 的概率分布; p(x,z)。x 是数据集 D 中学*时的观察变量,而 z 从未观察到。模型的联合概率分布可以写成 p(x,z) = p(x|z) p(z)

您将会看到,开发 LVMs 的拟合算法相当困难,但是研究这一点并没有什么好处

  1. LVM 通常比原始模型具有更少的参数,这些参数直接表示可见空间中的相关性。
  2. LVMs 中的 LV 主要充当数据的压缩表示,这也称为“瓶颈”。这是无监督学*的基础。如果你想到一个形象(例如。人脸)作为观察变量 x 那么,潜在变量 z 可以编码人脸的特征(在训练期间看不到),就像它可以编码人脸是快乐还是悲伤,男性还是女性等等。
  3. LVMs 还可以帮助我们处理缺失数据。前一点和这一点是相关的。如果我们可以对潜在变量进行后验推断,即给定一幅图像 x 潜在因子 z 是什么,那么一旦我们发现某些图像有缺失部分,潜在因子就可以用于重建。

为了讨论和发展一个现实的 LVM,我们将根据离散的潜变量来公式化高斯混合模型(GMM)。由于获取 LVMs 中最大似然估计量的最通用技术是 EM 算法,我们将在接下来的章节中详细讨论。

概率聚类和 GMM;

在我之前的 DBSCAN 算法文章中,我已经讨论了 K-Means 算法的缺点,特别是在处理不同密度、大小和数据点的空间聚类时,包括噪声和异常值。K-Means 的另一个问题是它执行硬聚类。让我们看一个使用简单的[make_blobs](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html)数据集的例子。在下面的图 1 中,我们看到了包含 3 个带标签和不带标签的聚类的数据集。一旦我们应用 K-Means 算法,它将识别 3 个聚类,但是不可能将任何概率分配给聚类边界处的数据点。如果我们想知道每个数据点属于这三个聚类的概率或可能性(对于聚类边界上的点尤其重要),该怎么办?

1:创建 Blobs 数据集(左)和包含标签的相同数据集(右)。来源:作者

在图 2 中,我们展示了一个将高斯混合模型(GMM)聚类应用于数据集的示例,每个数据点的大小与 GMM 预测的确定性成比例。这与 K-Means 结果进行比较,您可以清楚地看到差异,尤其是对于边界处的点。

2:使用 GMM 的软聚类(右)的比较通过给每个数据点分配预测的确定性来描述。这与硬聚类-K-Means(左)相比较。来源:作者

将这种软聚类作为一种动机,让我们使用潜在变量建立 GMM,但在此之前,让我们回忆一下多元正态分布。这里使用的符号很常见。

实验一:多元正态分布。

我们将使用混合正态分布来开发一个概率聚类(软聚类)模型。认为 GMM 是高斯分量的线性叠加的天真想法。每个分量将具有与其相关联的某种概率来表示特定的数据点。

实验 2:高斯分布的混合。

π在 Exp 中称为混合系数。2.对于单个数据点,总和超过聚类数 K 。变量 xz (潜伏)的联合概率分布为: p(x,z) = p(x|z) p(z) 。因此数据点 x 上的边际分布将由下式给出: p(x) = ∑ p(x|z) p(z) dz (通过对变量 z 求和/积分获得)。考虑这个 p(x) 的一种方式是混合分布 p(x|z) ,用 p(z) 加权。对于 GMM 上下文,我们可以把 z 看作是一个二进制随机变量,具有 1K 表示(你可以把这看作是分类表示),其中一个特定元素等于 1,其他所有元素都是 0。

实验 3:潜在变量的边际分布。

现在,混合系数和潜在变量 z ,当我们考虑 z 上的边际分布是按照上面表达式中定义的混合系数来指定时,都落入一个位置。混合系数所满足的条件是必要的,以便它们可以有效地解释为概率。我们认为第 k 个混合系数(π_k)是 z_k 等于 1 的先验概率。由于潜在变量使用 1/K 的表示法(把这看作是分类表示法),我们可以用另一种方式写出 p(z)和相应的条件分布如下—

实验 4:边际和条件分布

因此,结合多元正态分布和潜在变量分布,我们可以重写 GMM 模型如下。

实验 5:混合系数和多元正态分布的 GMM。

上述表达式对单个数据点有效。对于几个数据点,我们将有一个对应的潜在变量与每个观察到的数据点相关联。我们现在可以处理联合分布 p(x,z),而不是只处理边际分布。我们让事情变得更复杂了吗?为了回答这个问题,我们必须在可能性估计的数学中稍微深入一点。下一节将揭示潜在变量将如何帮助我们解决最大似然估计(MLE)容易。

期望值最大化算法(动机):

我们对 GMM 的主要刺激是进行数据点的软聚类。获得每个聚类的最佳参数(混合系数、聚类均值、协变矩阵)的一般直觉是执行通常的 MLE 任务。在上面的表达式 4 中,我们已经为单个数据点写了 GMM 模型。让我们考虑一个具有 N 个点的数据集,这样该观察集将是{x1,x2,x3,…,xN}。对于 N 个数据点,似然函数如下—

实验 6:对数似然函数包括所有 N 个数据点。

这个表达式的最大问题是对数并不直接作用于高斯,而是作用于高斯混合的和。因此,相对于对数对指数的作用,我们没有优势。所以确实这个表情很难还原。意识到这不是单个高斯函数的问题。除了前面的问题,另一个可能出现的问题是当 GMM 的一个组成部分只解释了一个点。这意味着其中一个μ等于数据点 x_n,在方差趋于 0 的极限内,似然项的行为类似于δ函数。所以最大化可能性在这个问题中不是一个好主意。与单个高斯分布问题相比,考虑高斯混合问题的另一种方式是,虽然单个高斯模型属于具有凹对数似然(对于足够简单的族来说是易处理的)的指数族,但是分量的混合不会具有这种性质。因此,所有这些原因都需要一种新的方法来确定参数,并且是时候深入研究期望值最大化(EM)算法了,该算法确实是基于贝叶斯更新规则的。

EM 算法:

在学* EM 算法之前,我们需要先推导一些重要的表达式。首先,我们将利用贝叶斯定理从条件分布 p(x|z) 中得到给定 xz 的后验分布表达式,如下所示

实验 7:潜在变量的后验分布

γ 项被称为责任,它代表潜在变量 z 的第 k 个分量为解释观察值 x 所承担的责任。顾名思义,EM 算法依赖于两个简单的步骤:期望(E 步)和最大化(M 步)

a)。E-step:期望步骤是我们计算后验分布的地方,即基于当前参数的责任(exp: 5)。这更多的是解决推断问题,即哪个高斯负责哪个数据点?

b)。M-Step:从 E-step 获得的概率然后用于计算更新的参数(μ、σ和π)。

在几次迭代之后,该过程将收敛,并且我们获得参数的最佳拟合值。让我们更一般地回顾一下 EM 算法的步骤——

实验 8:EM 算法的一般步骤

在这里,重要的是要提到,一旦我们知道了集群分配,就可以获得最佳参数(这是我们在 E-step 上尝试的一部分)。还要意识到,由于从 E-step 中获得了后验概率,我们可以使用期望的定义,然后我们需要最大化完整数据可能性的期望而不是数据可能性。我们如何进入这种期望的表达,在接下来的部分将会更加清楚,但是现在记住在责任(在实验中定义)方面。7) 我们可以计算出 1参数(μ,σ,π),表达式如下—

实验 8:从 MLE 获得的参数。

变分下界和 EM 算法;

这是刚才提到的,直到收敛重复 EM 算法的步骤。你可能会想怎么保证算法收敛?我们来深入挖掘一下!我们从 GMM 开始说,对于每个数据点 x_n 都有一个潜在变量 z_n 。完整数据集的对数似然采用如下形式—

实验 9:包含潜在变量的完全可能性

如前所述,这个表达式的问题是对数是作用于高斯混合的和。我们将耍些小花招来解决这个问题。让我们在潜在变量上引入任意概率分布(没有任何特殊性质)— q(z) 现在我们可以修改上面的表达式——

实验 10:数据似然性的微小变化

使用期望值的定义,这个表达式可以进一步简化为—

实验 11:使用期望的定义

期望项可以理解为从分布 q_i 中提取的 z_i 的期望值。我们可以将这个表达式与 Exp 进行比较。为了理解对潜在变量求和是如何给出期望值的。在 Exp 中。11、日志正在对期望值进行操作。鉴于 Log 是一个凹函数,让我们应用 詹森不等式 来进一步简化表达式——

实验 12:用詹森不等式修改实验 11。

上面的表达式表示完整数据集的对数似然大于或等于上面的期望值。期望项被称为证据下限(ELBO) ,通过对数展开和应用贝叶斯定理,我们可以得出更有意义的结论

实验 13:证据下限

使用 KL 散度的定义,上述表达式变成—

实验 14: ELBO 和 KL 背离

当 KL 散度≥ 0 时,这意味着 ELBO ≤ log p(x) 。现在我们知道它为什么被称为下界了。我们的目标是最大化我们的数据可能性 log p(X) ,相反,我们最大化 ELBO。基于这个表达式(Exp。14)让我们再回顾一遍 EM 算法的步骤—

  1. 通过随机初始化参数来启动算法。
  2. e 步骤:最大化 ELBO w.r.t q(z) 并保持参数 (π,μ,σ)不变。由于 log p(X) 独立于q(z)这个步骤本质上只是计算 KL 散度,并且在 GMM 的情况下 q(z) 被设置为等于后验概率。这是可能的,因为在 GMM 中可以计算每个数据点的后验概率。
  3. m 步:ELBO 相对于参数最大化,而 q(z) 保持固定,这与 MLE 估计非常相似。在这个步骤中,参数被更新。

为什么趋同:

我们以一个问题开始这一节——为什么 EM 算法能保证收敛?EM 算法是一个迭代过程,因此 E 和 M 步骤循环进行。重要的是要记住,在 EM 算法的每一步中,首先将分布 q(z) 设置为等于后验 p(z|x) (E 步),并且从最大化开始在 M 步中更新参数。随着更新的参数,下限增加(除非算法已经达到局部最大值)。这又增加了对数似然性,但是 log p(x) 比下限增加得更多,因为虽然 q(z) 是针对旧参数获得的,但是现在在 E 步骤中,当我们再次计算后验 p(z|x) 时,并且这次使用来自 M 步骤的新参数,产生非零 KL 发散项。因此,下限以及数据似然性单调增加。为了确保算法不会陷入局部最大值,我们对不同的参数初始值运行算法。数据似然性的这种单调递增的性质正是我们想要展示的收敛的代理。如果我们看到可能性在每一步都没有增加,这有时对调试代码非常有帮助。为了运行该算法,我们将给出迭代次数作为参数,并且还为损失函数的分数增加设置容差。现在,是时候将所有的理论付诸实践了,让我们来编码吧!!请查看笔记本,了解详细的代码以及参考资料部分的其他参考资料。

用 Python 实现 EM 算法;

让我们从定义 E-step 开始。这里,我们的主要目标是定义后验分布,在我们把它定义为 Exp 中的责任之前。7.下面是代码块—

EM 算法的 e 步(适用于 GMM)

接下来,我们实施 M 步,这是关于最大化的期望,对于 GMM,我们已经知道最好的参数,一旦我们从 E 步得到后验。最大似然估计的参数在实验中给出。8,我们将使用它们来定义 M-step,如下所示—

GMM 的 M-step

Exp。15: ELBO 的可能性和后验概率

一旦我们定义了 E 和 M 步骤,现在我们将实现证据下限作为损失函数。我们从 Exp 修改下界表达式。12 至如实验所示。15.对于潜在变量的分布 q(z),我们将使用从 E-step 计算出来的后验。考虑到这些,让我们将 ELBO 定义如下—

现在,我们已经准备好定义训练循环,我们设置迭代次数和容差,并确保算法以随机初始化的参数启动几次,以免陷入局部最大值。在训练期间,我们需要指定集群的数量,对于复杂的问题,这可能是一个问题。由于 EM 算法很耗时,通常建议运行 K-Means 算法来确定聚类数,然后对 GMM 运行 EM。另外,确定这一点的另一种方式是使用 Akaike 信息标准。在我的博士研究中,我确实用 AIC 来分离天体物理模型,但这与我们目前的目的不同。训练循环的代码如下—

最后,在训练之后,我们可以画出轮廓—

图:左:2D 数据集,聚类成 3 个高斯混合(右)。来源:作者

使用 Scikit-Learn:

使用 sklearn 的 GaussianMixture 类,用 3 行代码就可以实现 GMM EM 算法的所有这些理解和相应的长代码。但是当你知道基本知识的时候,生活总是更好!下面是代码块—

使用 scikit-learn 实现 GMM 很容易!

结论:

我们已经完成了这项工作,在这个过程中,我们学*了贝叶斯方法在无监督学*中的几个重要概念。在许多重要的概念中,我希望你们至少能回忆起最重要的一些——

  1. 通过 EM 算法的迭代步骤更新基于先验知识的概率分布。这是贝叶斯推断的基础——一旦我们更新了数据(证据),我们的信念会如何改变。
  2. 为什么引入潜在变量有助于我们更好地理解数据,并最终帮助计算最大似然?
  3. KL 散度和 ELBO 通过数据的可能性的关系。这一点你会在生成模型的概念中反复遇到(GMM 是生成模型的一个简单例子)。
  4. 对于 GMM,单个数据点的后验概率可以通过分析计算得出,但在复杂模型中可能不是这种情况(大多数情况下后验概率是难以处理的),因此,它不能作为潜在变量分布的代理( q(z) = p(z|x) )。在这种情况下,我们试图从尽可能接*后验分布的分布族 Q 中选择 q 。这是变分贝叶斯和最终变分自动编码器(VAE)和生成对抗网络(GAN)的基础。

感谢阅读,希望这能对你有所帮助。干杯!!!

页(page 的缩写)s:我在另一篇文章中讨论了贝叶斯机器学*中的另一个重要概念,称为共轭先验

参考文献:

1 EM 算法: Andrew NG 笔记来自斯坦福知识库。

[2] 变分推论:大卫·布雷的评论。

3克里斯·毕晓普的模式识别书:第 9 章。

4笔记本链接: GitHub

Matplotlib 的最新酷功能

原文:https://towardsdatascience.com/latest-cool-features-of-matplotlib-c7a1e2c060c1?source=collection_archive---------24-----------------------

照片由 Paola GalimbertiUnsplash 上拍摄

立即将您的 Matplotlib 升级至最新版本 3.3

日前,Matplotlib 发布了 3.3 版本— 其家族第三代中最新的。它引入了一些非常令人兴奋的特性,我强烈建议您今天就升级 Matplotlib。这篇文章将通过一些例子来引导你。

我使用以下命令在我的虚拟环境中更新到最新版本。对于新的安装,请参考官方安装指南。

pip install matplotlib --upgrade

下面我们来看看 Matplotlib 3.3 的最新 亮点功能。

1)生成复杂子情节网格的语义方式

通过subplot_mosaic()介绍了一种不太冗长的方式来生成支线剧情,这种方式允许你以一种 语义方式 可视化地布局你的坐标轴。早先,你不得不使用相对更冗长的方法subplots()GridSpec。此外,您可以随意命名您的轴。

例如,要生成如下所示的网格,现在可以以列表的形式传递布局。缺失的支线剧情被标示为'.'。要将一个支线剧情跨越两列,重复名字,就像我对'bar'做的那样。若要跨行(垂直),请在第二个列表中垂直下方使用相同的名称。名字'bar''hist''scatter'也可以用来控制/修改相应支线剧情的属性。

这个功能挺酷很宽泛的,关于这个 复杂语义图构图 这里你要详细阅读。这个超链接还向您展示了其他简写的 ASCII 符号,以重新创建下图。

axes = plt.figure(constrained_layout=True).subplot_mosaic(
                [['.', 'bar', 'bar'], # Note repitition of 'bar'
                 ['hist', '.', 'scatter']])for k, ax in axes.items():
    ax.text(0.5, 0.5, k, ha='center', va='center', 
            fontsize=36, color='magenta')

使用 subplot_mosaic()生成的支线剧情。请注意跨越两列的扩展“条”。

创建后共享 x 轴和 y 轴

你现在也可以在不同的支线剧情中共享轴线,就像这里举例的。

2)设置轴框的纵横比

轴框 的 纵横比是轴的高度除以其物理单位的宽度。所以如果你需要一个正方形的盒子,盒子的长宽比为 1。现在,您可以通过如下所示的set_box_aspect()方法直接设置该比率。此处提供了该功能的几个使用案例。在下面的代码中,注释掉最后两行,以查看轴框纵横比的变化。

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)ax1.plot(np.random.randint(0, 100, 1000), 'go')
ax2.plot([300, 900], [20, 55], 'g')ax1.set_box_aspect(1)
ax2.set_box_aspect(1)

盒子长宽比为 1 的支线剧情。

3)图例中的彩色标签

使用关键字参数labelcolor调用图例时,可以指定图例文本标签的颜色。默认情况下,它总是黑色的。

参见下面的示例,我将标签的颜色设置为标记面的颜色:

fig = plt.figure()x = np.linspace(0, 2*np.pi, 500)plt.plot(x, np.sin(x**2), '-o', c='orangered', mfc='b',
         lw=3, markevery=4, label=r'sin($x^2$)')plt.legend(fontsize=20, labelcolor='markerfacecolor',
           handlelength=1)

使用参数“labelcolor”将图例设置为标记颜色的图形。

Matplotlib 3.3 现在还提供了 Google AI 团队的 turbo colormap。

Matplotlib 3.3 中的 Turbo 颜色映射。

4)记号和标签

轴和颜色条标签的新对齐方式

现在,您可以在三个位置对齐 xy 轴标签。x-标签可以对准 x 轴的左侧、中间或右侧。类似地, y 标签可以在 y 轴的顶部、中心或底部对齐。这可以使用参数loc来完成。下面的例子说明了这一点:

plt.xlabel(r"$x$ (radians)", loc='right', fontsize=18)
plt.ylabel(r"sin($x^2$)", loc='bottom', fontsize=18)

一种图形,其各自的轴的右边标有 x,底部标有 y。

使用字符串和 lambda 函数设置刻度格式化程序

现在,在轴上设置刻度格式要简单得多。例如,您现在可以直接使用字符串函数作为字符串格式化程序的输入。下面的代码片段比较了使用字符串格式化的最新方式和旧方式。你可以清楚地看到最新的方法是多么简单。参见这个例子,了解 lambda 函数的类似用法。

import matplotlib.ticker as mticker# Plot the sinusoidal function# In latest version 3.3 
ax.xaxis.set_major_formatter('{x:.0f} rad')# Before version 3.3
ax.xaxis.set_major_formatter(mticker.StrMethodFormatter('{x:.0f} 
                             rad'))

x 轴上新字符串格式的演示。

5) rcParams 可以作为 Decorators 传递

这是一个真** 特色。现在你可以用定制的装饰器包装你的函数来控制你的绘图的参数。在下面的例子中,我用自定义的rcParams设置来装饰函数以绘制正弦曲线。**

from matplotlib import rc_context@rc_context({"lines.linewidth": 6, 
             'figure.facecolor': 'lightgreen',
             'legend.fontsize': 18})
def plot_sin(x):
    fig, ax = plt.subplots(figsize=(6, 4))
    ax.plot(x, np.sin(x**2), label=r'sin($x^2$)')
    ax.legend()
    returnplot_sin(x)

使用 rcParams 设置作为装饰器生成的图。

6) 3D 绘图现在支持次要刻度

到目前为止,还没有直接的方法在 3D 轴上启用次要刻度。现在你可以简单地使用关键字minor=True打开它们。改编官方示例,我在下面展示应用于 z 轴的该功能。

from mpl_toolkits.mplot3d import Axes3Dfig = plt.figure()
ax = fig.add_subplot(projection='3d')ax.scatter([0, 1, 2], [1, 3, 5], [30, 50, 70])ax.set_zticks([35, 45, 55, 65], minor=True)
ax.set_zticklabels([r'$\alpha$', r'$\beta$', r'$\delta$',
                    r'$\gamma$'], minor=True)ax.tick_params(which='major', color='r', labelcolor='r', width=5)
ax.tick_params(which='minor', color='b', labelcolor='b', width=3)

z 轴上带有次要刻度的 3D 绘图。

7)保存图形时指定后端

现在,您不需要在 Jupyter 笔记本的开头明确指定后端。您可以简单地将所需的后端作为参数 传递,同时使用后端关键字保存图形 。例如,如果您想用 pgf 后端保存 pdf 图形,您可以执行以下操作**

plt.savefig('/Users/Henry/Downloads/sinusoidal.pdf', backend="pgf")

你可以在 matplotlib 这里阅读更多关于后端的内容。

8)通过两点的无限长直线

现在你可以使用新引入的axline方法直接画出通过两点的无限长的线。有两种选择:要么明确指定两点并让系统计算斜率,要么指定一点和直线的斜率。以下示例显示了这两个选项的用法。

记住:关键字slope应该只能用于线性秤。对于所有的非线性刻度,你必须明确的通过两点

**fig, ax = plt.subplots(figsize=(6, 4))ax.axline((.4, .4), slope=5, color='r', label='using slope')
ax.axline((.3, .4), (.5, .6), color='b', label='using points')ax.legend(fontsize=18, frameon=False)**

在 Matplotlib 3.3 中使用 axline()方法绘制无限长的线

尽管最新版本 3.3 中引入了其他几个有趣的特性,但我会保持这篇文章的简短,并建议您参考阅读官方页面此处了解引入的变化的完整列表。

如果你有兴趣了解之前的 Matplotlib 版本 3.0、3.1 和 3.3 中的新功能,请阅读我之前的帖子Matplotlib 3 的新功能

人工智能视频流的最新技术进步

原文:https://towardsdatascience.com/latest-technological-advancements-in-video-streaming-with-ai-293d3b8b2a7e?source=collection_archive---------29-----------------------

回顾网飞等视频流媒体公司使用的最新技术。

照片由耶稣爱奥斯汀Unsplash

互联网上 85%的数据是通过视频消费的。大约 2.8 艾字节的数据通过流媒体视频在互联网上传输。这种增长是由网飞等视频点播平台、Zoom 等视频通信平台、Tiktok、电子竞技、直播等社交平台的出现推动的。

图片作者来自 Vadoo

Covid19 疫情加速了视频消费,并一直是公司从离线模式转向在线直播模式的驱动力。随着日常视频消费的爆炸式增长,我们需要为即将到来的需求做好准备。

在本文中,我们将讨论视频流技术的最新进展,以及它们如何帮助改善流体验。

超分辨率

人工智能已经颠覆了各种行业,视频流也不例外。AI 模型可以通过从大量图像中学*,学*如何从低分辨率图像生成高分辨率图像。这种从低分辨率图像生成高分辨率图像的方法称为超分辨率

来自 Kaggle创作者的图片

超分辨率属于生成算法领域,该算法能够生成以前没有的信息。从上图中可以看出,网络可以从左侧获取图像,并想象更精细的细节来重新创建右侧的图像。这是可能的,因为人工智能模型已经在大量图像数据上接受了训练,现在它知道如何在提供新图像时放大图像。

同样的概念可以扩展到稍加修改的视频。在视频的情况下,过去的多个生成的高分辨率帧和当前的低分辨率帧一起用于生成当前的高分辨率帧,但是概念是相同的。这项技术提供了以 480p 发送视频,但在客户端设备上以 1080p 观看的能力。

图片来自论文作者作者

由于深度学*的最新进展和客户端设备巨大计算能力的可用性,这项技术是可能的。最*的一篇论文 TecoGAN 产生了高分辨率的结果,与现实世界的图像惊人地相似,如上图所示。使用这项技术可以节省高达 30%的带宽消耗,从而改善整体用户体验。

P2P 流媒体

视频流遵循客户端-服务器模型。内容从称为 CDN 的边缘位置传送,CDN 缓存来自服务器的内容。客户端设备,即手机/笔记本电脑/电视,从这些 CDN 获取内容,开始播放您的视频。通过 CDN 的视频流有一些限制,如下所述

  1. 使用 CDN 的视频流是昂贵的
  2. 收视率高峰导致高缓冲
  3. 由于 CDN 覆盖不佳,向远程位置交付内容

由于这些原因,视频流公司很难有效地扩展其服务并提供良好的用户体验。所有这些问题都可以通过使用 P2P 流媒体扩展 CDN(即混合 CDN)来解决

图片作者来自论文

在传统 CDN 上添加对等层,通过分发来自相邻对等体的内容来减少主 CDN 的负载,这些对等体本身就像一个 CDN,从而使边缘更接*用户。由于 CDN 上的负载减少,费用现在将减少 40%,同时用户体验也由于较低的重新缓冲而得到改善,因为内容是从附*的对等点而不是远处的 CDN 获取的。关于这项技术如何工作的更多信息可以在这里找到。

使用 Vadoo 缩放您的视频流

多 CDN

我们已经看到,内容通过 CDN 传送到客户端设备,CDN 缓存来自服务器的内容。CDN 由位于多个位置的数据中心组成,提供内容服务。这些位置被称为接入点(POP)。理想情况下,我们希望有尽可能多的 POP。但并不是所有的 CDN 在全球范围内都有同等的影响力。例如,一些最受欢迎的 CDN 在中国甚至没有一个 POP。

另外,每个 CDN 的性能都是随时间变化的,不一致。根据墨菲定律,CDN 可能会在任何时间点发生故障。为了应对所有这些风险,理想的选择是同时接入多个 CDN。这可以通过联系多个 CDN 并单独与它们中的每一个达成交易来实现,也可以通过联系为您管理所有这一切的多 CDN 提供商来实现。

使用多 CDN 为您的视频流服务提供支持,为您提供有助于改善整体用户体验的优势。

  1. 通过切换到工作的 CDN 来防止服务突然停止
  2. 使用实时用户监控(RUM)指标从当时性能最高的 CDN 获取内容,以提高服务质量(QOS)
  3. 中游交换有助于降低 CDN 成本

CMAF

直播体育比赛会比电视广播延迟 25-30 秒,从而影响用户体验。这是由于视频流技术的设计方式。流式传输视频的最主要方式是基于 HTTP 的流式传输,其中视频内容通过以下步骤传送

  1. 视频使用编解码器(如 h264)进行编码,以减小视频文件的大小
  2. 然后,视频被转换成可流式传输的格式,如 HLS 或 MPEG-DASH
  3. 来自服务器的内容现在通过 CDN 分发
  4. 视频播放器在开始播放之前会缓冲一些视频片段

HLS 或 MPEG-DASH 允许分段发送视频,由视频播放器顺序下载。一个片段通常包含大约 10 秒钟的视频。编码器必须等待对视频的整个片段进行编码,然后才能将其用于 CDN。CDN 必须等待接收完整的视频片段,然后才能将其传递给视频播放器。视频播放器必须在开始播放之前缓冲至少几段视频,以保持用户体验。

整个过程会导致 25-30 秒的延迟。此外,由于存在多种格式,即 MPEG-DASH 的 ts fr HLS 和. mp4,因此需要双倍的存储、双倍的编码和双倍的 CDN。CMAF 试图解决上述两个问题。

CMAF 提供了 HLS 和 MPEG-DASH 都支持的一致格式的片段 mp4(fmp4)。它还具有进行分块传输编码的能力。这意味着,编码器在传输之前不会等待整个视频片段。该段被进一步分成更小的块,并且这些块在被编码时被发送,该编码由 CDN 以不特定的顺序传递给编码器。视频播放器负责组织数据块并播放视频片段。

因此,CMAF 有助于减少编码和存储成本,以及减少使用分块传输编码的延迟。

按标题编码

视频编码是使用 H.264 等编解码器压缩视频的过程,这些编解码器利用连续帧中存在的公共信息,因此只在帧中存储新添加的信息。为了应对各种网络条件和多变的互联网连接,视频内容以多种分辨率进行编码,并进行智能切换。这种技术被称为自适应比特率(ABR)。

图片来自网站

下图描述了多种分辨率和相应的比特率分配。这里要注意的关键因素是,相同分辨率的内容可以以多种比特率编码,即 1920 x 1080 的视频可以以 5800 mbps 或 6800 mbps 甚至 4800 mbps 的速率编码。这是因为视频压缩是有损压缩,因此选择的比特率越小,压缩视频中可用的信息就越少。这可以在编码伪像中观察到,类似于您在流媒体平台上观看视频时观察到的上图。

图片来自网飞博客的作者

既然我们知道可以使用不同的比特率对特定分辨率的视频进行编码,那么在现实世界中,可以选择理想的通用比特率,以便在不消耗大量带宽的情况下减少伪像。上图显示了为所有视频选择的通用带宽模式。但是这种一刀切的方法有一个问题。诸如高辛烷值动作电影的一些视频可能具有丰富的信息,因此可能需要更高的比特率来编码,而简单的卡通视频甚至可以用更低的比特率来执行。

因此,网飞建议以多种比特率对特定的视频分辨率进行编码,然后选择最佳比特率来呈现没有伪像的视频。这是使用称为 VMAF 的度量来完成的,VMAF 是识别渲染视频质量的视觉分数。在此帮助下,可以为每个视频设计定制的比特率阶梯。因此,如果我们正在流式传输卡通视频,它可以以较低的比特率发布,同时仍然具有类似的质量,而动作电影可以以较高的比特率发布,没有任何伪像,从而改善用户体验。

摘要

总而言之,我们已经看到了多种有助于扩展、改善用户体验和减少视频流延迟的技术。5G 和虚拟现实(VR)和增强现实(AR)世界的到来以及电子竞技的兴起将使视频带宽消耗飙升。因此,是时候采用最新技术来跟上并服务于这种增长了。

面向数据科学家的乳胶,不到 6 分钟

原文:https://towardsdatascience.com/latex-for-data-scientists-in-under-6-minutes-3815d973c05c?source=collection_archive---------25-----------------------

背景图片:不飞溅

任何数据科学简历的必备技能

作为一名数据科学家,你与数据打交道。数据本质上是数学的——你必须能够清楚地表达这些想法。即使您没有开发算法,表达常见数据科学技术的能力——可能是多项式回归或 box-cox 变换的结果——也是必不可少的。

也就是说,LaTeX,这种最流行的数学排版语言,有很多很多多余的东西。本教程将只展示 LaTeX 中与数据科学相关的最重要的部分,到最后,您将对 LaTeX 有足够的了解,可以将它结合到您的项目中。

这是乳胶,在 6 分钟或更短的时间内。最后是 5 道练*题。

显示数学

要在文本中显示数学,表达式必须在美元符号之间。

In physics, the mass-energy equivalence is stated  by the equation $E=mc^2$, discovered in 1905 by Albert Einstein.

或者,可以使用打开和关闭\[\]

The mass-energy equivalence is described by the famous equation\[E=mc²\]

这将自动使数学居中并显示在新的一行上。

下标和上标

下标用 _,上标用^.$a^2$将输出。上标也可以通过连续调用与下标组合:

\[ a_1^2 + a_2^2 = a_3^2 \]

对于更长的上标和下标,将上标和下标放在括号中可以清理代码:

\[ x^{2 \alpha} - 1 = y_{ij} + y_{ij}  \]

注意——LaTeX 有许多符号可以用\name来调用。在上面的例子中,使用了\alpha。其他的还有\infty,是无穷大的符号。

上标和下标也可以以多种方式嵌套和组合,只要用括号明确指定范围:

\[ (a^n)^{r+s} = a^{nr+ns}  \]

许多数学运算符需要下标或/和上标。在这些情况下,运算符被视为具有正常上标和下标属性的对象。以 sigma/summation 操作符为例,这个操作符由\sum调用。

\[ \sum_{i=1}^{\infty} \frac{1}{n^s}  
= \prod_p \frac{1}{1 - p^{-s}} \]

即使使用 sigma 操作符对常规对象调用上标和下标,它也会自动对齐。

另外需要注意的是——当使用[ and ]开始和结束指示符时,所有内容都放在一行中,所以放在几行中的代码不会影响最终结果。

对上标和下标进行操作的其他运算符包括:

  • \int对于积分
  • \cup用于联合(朝上 u)
  • \cap对于交叉点(朝下 u 形)
  • \oint对于曲线积分
  • \coprod为联产品

经营者

三角函数、对数和其他数学函数可以取消斜体,并通过在前面加一个\来格式化。

\[ 
\sin(a + b ) = \sin(a)\cos(b) + \cos(a)\sin(b) 
\]

有些运算符可以通过下标接受参数,比如 limit 运算符。

\[ 
\lim_{h \rightarrow 0 } \frac{f(x+h)-f(x)}{h} 
\]

注意一个极限声明是如何包含一个下标和一个符号\rightarrow的调用的。\frac{a}{b}是一种创建分数的方法a/b

分数和二项式

为了让本节中的一些命令生效,您必须首先在文件的开头包含amsmath包。

\usepackage{amsmath}

分数和二项式系数非常简单。它们被称为\name{parameter1}{parameter2}

\[     
\binom{n}{k} = \frac{n!}{k!(n-k)!} 
\]

当分数被内联使用时,它们的显示方式会有所不同。

Fractions can be used alongside the text, for  example $frac{1}{2}$, and in a mathematical  display style like the one below:\[\frac{1}{2}\]

通过使用分数作为参数,可以很容易地嵌套分数。

\[   
a_0+\cfrac{1}{a_1+\cfrac{1}{a_2+\cfrac{1}{a_3+\cdots}}} 
\]

上面的命令使用了来自amsmath包的\cfrac{}{},它保持片段的大小不变,即使它们是嵌套的。这可以用\frac{}{}来代替,这会让嵌套的分数变小。

括号和圆括号

LaTeX 支持多种类型的支架:

  • (x+y)渲染( x + y )
  • [x+y]渲染[ x + y ]
  • \{ x+y \}渲染{ x + y }
  • \langle x+y \rangle渲染⟨ x + y
  • |x+y|渲染| x + y |
  • \| x+y \|渲染∩x+y

有时,括号和圆括号对于表达式来说太小,例如,如果它有分数。

动态圆括号和括号由\left[object]\right[object]命令操作,表示开始和结束。

\[  
F = G \left( \frac{m_1 m_2}{r^2} \right) 
\]

在这种情况下,[object]是一个括号,所以表达式被包含在\left(\right)中。[object]也可以用括号代替(\left[\right])。

矩阵

这个amsmath包包含了许多排版矩阵的命令。

一个矩阵由几个值定义,每行由&分隔,每行由一个\\分隔。它包含在标准的\begin{object}\end{object}中。

对于没有侧括号的简单矩阵:

\begin{matrix}
1 & 2 & 3\\
a & b & c
\end{matrix}

{pmatrix}替换\begin{matrix}\end{matrix}中的{matrix},将括号括在矩阵周围:

{bmatrix}用括号括起来:

…然后{Bmatrix}用花括号把它括起来。

实践

现在,你有了乳胶的基本技能。找到将创建给定输出的代码。

解决方法

1(损失):

\[
Loss = Bias^2 + Variance^2 + Noise
\]

2(卡方检验):

\[
Chi 
= \frac{(\hat(y)-y)^2}{\sqrt{y}}
= \frac{\delta^2}{\sqrt{y}}
\]

第三名(KNN):

\[
\hat(f)(x)
\leftarrow \frac{\sum f(x)}{k}
\]
\[
DE(x_i,x_j) = \sqrt{(x_i-x_j)^2 + (y_{xi}-y_{xj})^2}
\]

4(乙状结肠):

\[
\frac{1}{1+e^{-(wx+b)}}
\]

5 (R):

\[
R^2 = \frac{n \sum xy - \sum x. \sum y}{\sqrt{(n \sum x^2 - (\sum x)^2). (n \sum y^2 - (\sum y)^2)}}
\]

结论

在本教程中,您学*了…

  • 如何内联和单独格式化数学
  • 如何使用上标和下标,以及运算符
  • 如何呼叫特定的接线员
  • 如何使用圆括号和方括号,包括动态的
  • 如何创建带有各种侧括号样式的矩阵

现在你可以漂亮地格式化数学了!从现在开始学* LaTeX 的大部分内容是记忆某些对象的代码(\object),因为你现在已经知道 LaTeX 的基本结构。

如果您喜欢这篇文章,您可能也会对本系列的其他文章感兴趣:

继续并点击“添加”。

使用 GitHub 页面,通过 5 个简单的步骤免费创建一个网站

原文:https://towardsdatascience.com/launch-a-website-for-free-in-5-simple-steps-with-github-pages-e9680bcd94aa?source=collection_archive---------23-----------------------

不到 10 分钟就能在网上建立你的个人投资组合网站。

尼古拉斯·皮卡德在 Unsplash 上拍摄的照片

拥有自己的网站可以让你向世界展示你是谁,以及你热爱什么。

许多人认为,对于普通人来说,建立一个网站成本太高,或者技术难度太大。实际上,它根本不需要花费任何成本,任何人都可以完成——不管经验水平如何——并且可以在 10 分钟内启动并运行!(可以查看我的这里)

GitHub Pages 是 GitHub 的一个特性,它允许用户直接从存储库中托管静态网页。这是托管个人投资组合网站、展示项目或为小型组织托管其页面的理想选择。在这篇文章中,我将展示对于任何人来说,通过 GitHub 页面建立一个网站是多么简单。

步骤 1 —创建 GitHub 帐户

如果您已经有一个 GitHub 帐户,可以跳过这一步。如果没有,可以 报名这里

在整篇文章中,我尽量不假设您已经掌握了相关知识,但是如果您以前从未使用过 Git,我建议您熟悉 Git 概念。本文从完整的基础知识开始,对 Git 和 GitHub 进行了很好的介绍:

[## Git 和 GitHub 入门:完全初学者指南

Git 和 GitHub 基础知识,供好奇和完全困惑的人使用(加上最简单的方法来为您的第一次公开…

towardsdatascience.com](/getting-started-with-git-and-github-6fcd0f2d4ac6)

步骤 2-为你的网站创建一个存储库

资源库是存储项目所有代码的地方,或者如 GitHub 的帮助页面所解释的:

“存储库就像是项目的文件夹。项目的存储库包含项目的所有文件,并存储每个文件的修订历史。您还可以在存储库中讨论和管理您的项目工作。” GitHub 帮助

因此,要开始我们的项目,我们需要做的第一件事是为我们网站的代码创建一个存储库。现在我们有了一个 GitHub 帐户,这很容易做到。只需导航到 GitHub 主页的右上方,在“+”菜单下,选择“ New Repository ”。

添加新的存储库

这将打开“创建新存储库”页面,我们可以在其中选择存储库名称,并选择我们的存储库是“公共”还是“私有”。重要的是,我们给这个存储库一个特定的名称,这样 GitHub 就知道这个存储库应该通过 GitHub 页面托管。这个应该是[your_username].github.io。例如,因为我的 GitHub 用户名是 emilegill743,所以我的存储库名称——我们稍后将看到我的网站 URL——将是 emilegill743.github.io 。我们还希望将我们的存储库设置为“Public”,因为如果我们升级到 GitHub Pro,GitHub Pages 只允许托管“ Private ”存储库。

为我们的 GitHub 页面网站创建一个存储库

一旦我们完成了这些,GitHub 将带我们到我们新创建的存储库,并解释我们可以开始使用存储库的本地副本的几种方法。如果您不熟悉在命令行上使用 Git,将这个空存储库"克隆到您的本地系统的最简单的方法是使用在桌面中设置的""选项。这将打开 GitHub Desktop——可以在这里安装——在您选择的位置创建一个存储库的本地副本。现在,在您的本地文件系统上将会有一个以您的存储库命名的空文件夹,它将会跟踪我们所做的任何更改。然后,这些更改可以被“提交”和“推送”到我们在 GitHub 上的远程存储库。**

第三步——选择你的网站设计

https://html5up.net/上提供的模板

现在,如果你是铁杆,你可能想从头开始设计你的网站。理论上,你可以这样做;我们所需要的只是我们的远程存储库中的一个index.html文件,GitHub 将继续渲染我们的网站。然而,由于这篇文章的目的是让我们的网站尽快建立并运行,我们将使用一个模板来开始。这将使我们能够以最少的工作量创建一个时尚、响应迅速、专业的网站。

有许多网站提供网站设计的模板,有些可以花很少的钱购买,但许多是免费的。我特别喜欢的是 HTML5 UP ,它提供了一系列漂亮的设计,非常适合个人作品集网站。在知识共享署名 3.0 许可下,所有的设计都是免费的,这意味着我们可以随心所欲地使用它,只要我们为设计归功于 HTML5。

随意自己做研究,找到最适合自己的设计;为了演示,这里我用 HTML5 UP 的地层主题

Strata by HTML5 UP!

第 4 步—推送至 GitHub

既然我们已经选择了我们的设计,我们可以下载它的相关文件,并将它们转移到我们的本地存储库中。然后,我们可以提交我们的更改,并将其推送到我们的远程存储库。同样,如果你*惯使用 Git,可以通过命令行来操作,但是如果你是新手,你可以使用 GitHub Desktop。

推送至 GitHub

这就是奇迹发生的地方。打开网络浏览器并导航至 URL [your_username].github.io

我们的网站上线了!现在让我们看看如何添加最后的润色和个性化,现在它只是一个模板。

第五步——定制你的网站

对于这最后一步,我们需要一个文本编辑器。如果你是一个编程专家,你可能已经有了一个文本编辑器。任何都可以,但我个人推荐 Visual Studio 代码,你可以在这里安装。

在我们的文本编辑器中打开包含我们的存储库的文件夹,我们将看到所有有助于我们网站设计的文件。其中最重要的是我们的index.html文件,它表示我们网站主页的结构。可能还会有一些.css文件,也可能有一些.js。如果你不熟悉这些,不要太担心,当我创建我的第一个网站时,我并不熟悉!一个基本的总结是,HTML(超文本标记语言)构成了网页结构的构建模块,CSS(层叠样式表)描述了网页的样式,Javascript 定义了网页的交互行为。

我建议的第一件事是你下载 Visual Studio 代码的‘Live Server扩展,这将使我们能够在编辑网站时预览它,当我们保存更改时会自动刷新。或者,您可以在 web 浏览器中打开index.html页面,手动刷新以检查更改。

VS 代码的实时服务器

关于如何编写 HTML,我不会讲太多细节,否则,这很快就会变成一个教程。基本语法由构成 HTML 元素的'标签组成,HTML 元素是 HTML 网页的构建块。这些标签通常由开始标签、标签的任何属性、一些内容和结束标签组成。

*<tag attribute="value">Some content</tag>*

你想在多大程度上定制你的网站取决于你自己。在最基本的层面上,你需要改变网页中 HTML 元素的内容来反映你的个人信息。您可能还想更改网页中的图像。要做到这一点,你需要做的就是把你想要使用的图像复制到你的存储库中(如果你使用的是 HTML5 UP 模板,它可能已经有一个为图像指定的文件夹),然后修改图像元素的src属性来反映你的新图像<img src="path_to_image.jpg"/>的路径。这里值得注意的是,图像元素由包含其属性的单个标签组成,而不是像许多其他 HTML 元素那样由开始和结束标签组成。

如果你有兴趣学*更多关于 HTML、CSS 和 JavaScript 的知识,这样你就可以让你的网站个性化更上一层楼,我强烈推荐哈佛的 CS50W : 用 Python 和 Javascript 进行 Web 编程 。这是一门关于 edX 的完全免费的课程,它的前几章主要关注 Git、HTML 和 CSS,之后会继续关注 Javascript。它很好地介绍了让网站真正成为我们自己的网站所需的技巧。

要获得更多灵感,请随时查看我的网站 emilegill743.github.io 和下面链接的相应 github 库。

* [## Emile gill 743/Emile gill 743 . github . io

我的个人作品集网站,通过 GitHub 页面托管,基于 HTML5 UP 的 Strata 主题。…

github.com](https://github.com/emilegill743/emilegill743.github.io)

感谢阅读!*

如果你喜欢这篇文章,可以看看我的其他文章:

* [## 聪明的方法是找到一个杂货递送点

使用 Python、Heroku 和 Twilio 从一个杂货网站的 API 中抓取数据,并在出现插槽时获得文本通知…

towardsdatascience.com](/finding-a-grocery-delivery-slot-the-smart-way-f4f0800c4afe) [## PostgreSQL 入门实用指南🐘

Python 的 PostgreSQL、pgAdmin 和 SQLAlchemy 入门。将 SQL 融入 Python 的核心…

towardsdatascience.com](/a-practical-guide-to-getting-set-up-with-postgresql-a1bf37a0cfd7)*

在几分钟内,在浏览器中启动您自己的人脸识别应用程序(实时)

原文:https://towardsdatascience.com/launch-your-own-real-time-face-recognition-algorithm-in-your-browser-in-minutes-beginner-guide-a8f2e6fd505c?source=collection_archive---------24-----------------------

用 Face API 和 Docker 实现基于 JavaScript 的人脸识别

三二一…发射!

如果您想自己实现它,请跳到下面的实现部分。

如果你只是想玩一个没有任何编码的实时人脸识别算法,可以运行下面这个 Dockerized web app:

docker run -p 8080:8080 billyfong2007/node-face-recognition:latest

这个 Docker 命令将从 Docker Hub 运行 Docker 映像,并将容器的网络端口 8080 绑定到您的计算机。您可以在浏览器中访问面部识别算法,方法是:

localhost:8080

该网页将访问你的笔记本电脑的摄像头,并开始实时分析你的表情!

不要担心,这完全脱机工作,你将是唯一一个可以查看视频流的人…假设你的计算机没有受到损害。

无论如何,你可能会开始像一个傻瓜一样在电脑前做各种有趣的表情(或者悲伤/愤怒等)!

履行

这个算法消耗了建立在 tensorflow.js 核心 API 之上的 Face API 。你也可以训练这个算法来识别不同的人脸。

对于那些还在阅读的人来说,也许您想知道如何构建自己的节点应用程序来使用 Face API?好了,我们开始吧:

你可以在我的 GitHub Repo 里找到所有的源文件。

首先,你需要安装 NPM 的实时服务器来服务你的 HTML:

npm install -g live-server

构建一个名为 index.html: 的准系统 HTML 页面

这个 HTML 包含一个视频元素,我们将使用它来传输您笔记本电脑的网络摄像头。

然后用以下内容创建 script.js :

该脚本做了几件事:

  1. 从目录异步加载所有模型
  2. 请求访问您的网络摄像机的权限
  3. 一旦视频开始流,创建一个画布,并调用 Face API 每 100ms 在画布上绘制一次。

需要的机器学*模型可以从我的 GitHub Repo 下载:

一旦你准备好了 index.html、script.js 和模型,你就可以开始了。您仍然需要包含 face-api.min.js,您的应用程序才能开始工作:

现在你准备好了!开始使用 live-server 服务您的 HTML 页面:

cd /directory-to-your-project
live-server

这个简单的 JavaScript 项目让我体验了 ML,我希望我能做更多,但我不确定这个算法在现实生活中会有什么实际用途。你怎么想呢?

页(page 的缩写)s:这是我的第一篇媒体文章,如果你认为这篇文章需要进一步澄清,请告诉我!😃

使用 Flask & Python 在 7 分钟内启动您自己的 REST API

原文:https://towardsdatascience.com/launch-your-own-rest-api-using-flask-python-in-7-minutes-c4373eb34239?source=collection_archive---------19-----------------------

下面的文章介绍了使用 Python、Flask 和 Sqlite3 开发 REST API

1.简介:

应用程序编程接口(API)被定义为处理两个或更多中介(通常是用户和数据库之间)之间的交互的接口。更常见的是,大多数被访问的网站、被玩的视频游戏、甚至是被流式传输的视频都涉及到被利用的某种级别的 API。作为数据科学家,我们经常使用 API 来检索信息,如股票价格、文章或其他类型的信息。数据科学家通常会发出 HTTP 请求,这通常会导致数据以 JSON 文件的格式返回。

表述性状态转移(REST)类型的 API 是一种架构风格,它使用 HTTP 请求来获取、上传、发布和删除数据(图 1)。作为用户,当使用诸如 Postman 之类的软件或者诸如 Requests 之类的普通 Python 库来发出 HTTP 请求时,我们经常会体验到 API 的客户端。然而,对于大多数 Python 开发者来说,API 函数的底层框架仍然是一个“黑箱”。本文的目的是通过使用 Flask 框架从头开发一个 API 来探索这一领域。

1:REST API 的主框架,其中 API 的客户端允许使用 GET、POST、DELETE 和 PUT 方法添加和删除数据。

2.REST API 的基础:

REST API 背后的主要结构由三个关键项目组成:(url 和端点,(2)方法,以及(3)数据。当客户机针对 API 发出 HTTP 请求以检索数据时,必须设计的第一项是 URL。URL 通常包含站点域、一系列目录层次结构,最后是端点,通常遵循图 2 所示的结构。

图 HTTP 请求 URL 的一般结构。

使用 REST API 发出请求时,通常使用四种主要方法:GET、POST、PUT 和 DELETE。虽然这些方法大多是不言自明的,但主要的好处是可以使用这些方法从任何给定的数据库中检索、添加或删除数据。GET 请求是最常见的请求类型,主要用于从服务器或数据库中检索数据。POST 请求用于向 API 发送数据,以便创建或更新条目。与 POST 类似,PUT 请求用于向 API 发送数据,以便创建或更新条目,但是,PUT 请求是等幂的,这意味着可以多次应用该方法,而不会改变最终结果。最后,删除请求用于删除数据库中的某些条目。下面的图 3 总结了 REST API 背后的主要方法,使用了一个关于每个请求的示例解释命令。

图 3:REST API 背后的四个主要方法,以及一个以职位发布为例总结功能的示例语句。*请注意,PUT 方法类似于 POST 方法,但是它们是等幂的,多次调用相同的请求将产生相同的结果。另一方面,POST 请求是非等幂的,发出相同的请求可能会导致意外的结果。

最后,构成 API 的最后一项是要查询的实际数据,可以是从小的 CSV 文件到大的关系数据库。出于本文的目的,我通过转换一个示例 CSV 文件,使用 Python 的 sqlite3 库创建了一个数据库。

3.准备数据库:

出于本文的目的,我们将使用一个关于 CS 和数据科学职位的职位发布数据集来创建一个 API。现在让我们继续使用 sqlite3 库创建一个数据库。出于本文的目的,为了简单起见,我们将坚持使用 s qlite3 库,然而,生产级数据库应该利用 MySQLPostgreSQL 来获得最大效率,这两者在 AWS 等云服务器上都很容易获得。我们从 sqlite3 开始,创建一个允许我们创建新的 sqlite3 连接的函数。这里的主要目标是准备一个函数,通过创建一个连接来创建一个新的数据库文件。

def createSqliteConnection(database):
    """ 
    Function that creates a connection to a sqlite3 database file.[@param](http://twitter.com/param) database -- The path and name of the database file to connect to.
    """
    conn = None
    try:
        print("----------Attempting to connect to database using Sqlite3 version {version} ...".format(version = sqlite3.version))
        conn = sqlite3.connect(database)
        print("----------Successfully to connected to {database}".format(database = database))except Error as e:
        print(e)
    finally:
        if conn:
            conn.close()

创建数据库后,现在可以直接从 CSV 导入数据。

def pandasToDatabase(csvDocument, database, tableName):
    conn = sqlite3.connect(database) 
    df = pd.read_csv(csvDocument)
    df.to_sql(tableName, conn, if_exists = "append", index = False)

两个函数都完成后,我们现在可以继续执行这些函数:

if __name__ == '__main__':
    createSqliteConnection("data/datasciencejobs_database.db")
    pandasToDatabase("data/datasciencejobs_database.csv", "data/datasciencejobs_database.db", "tblJobs", )

这将导致创建一个名为:

data/datasciencejobs_database.db

现在创建了主数据库文件,我们现在能够使用 API 直接从数据库中查询数据,从而避免了 CSV 的使用。这允许更快和更干净的连接。

4.创建 Flask 应用程序:

针对 API 的 Flask 应用程序的后端开发不同于大多数用户熟悉的标准的基于 GUI 的 web 应用程序。从高层次的角度来看,主要的区别可以总结在图 4 中。两者之间的主要区别在于,由于必须考虑图形用户界面,标准 web 应用程序的重点转向了 HTML 和布局功能。另一方面,API 的主要关注点是信息的路由和流动。

图 flask 应用程序用于 API 时相对于标准 web 应用程序的一般高层次比较。

我们通过在 app.py 文件中定义我们的“app”并创建一个 Flask 应用程序来开始这个过程。

app = flask.Flask(__name__)
app.config["DEBUG"] = True

然后,我们必须创建几个函数,当在 URL 中采用某些路线时,这些函数会显示数据。让我们从一个简单的' view all' 函数开始,它显示数据库中的所有条目。请注意,我们使用的是上面指定的 GET 方法。

@app.route('/api/v1/jobs/datascience/all', methods=['GET'])def apiViewAll():
    conn = sqlite3.connect('data/datasciencejobs_database.db')
    conn.row_factory = dictFactory
    cur = conn.cursor()
    all_books = cur.execute('SELECT * FROM tblJobs;').fetchall()
    return jsonify(all_books)

启用此功能后,最终用户现在能够查询我们数据库中的所有数据。目前,这还不是问题,因为数据库包含的条目不超过 1000 个,但是,随着数据库的增长,最终用户需要等待很长时间才能访问整个数据库,这将成为更大的问题。也就是说,任何 REST API 的高效设计的一部分是基于预定的文件服务器查询数据的能力,以便查询数据库的某些部分。假设数据库由列' id '、 datetime '、 country '和' content '组成,一个“最佳设计”的 API 将允许用户使用前三个参数来查询数据。必须开发一个函数,允许通过指定' id '、日期时间'或'国家'来使用多个端点过滤数据。请注意,如果没有指定任何条目,将发出错误 404 页面未找到。

@app.route('/api/v1/jobs/datascience', methods=['GET'])def apiViewByFilter():
    '''
    Function that allows users to filter the results in the API     based on specified input.
    '''
    query_parameters = request.args
    id = query_parameters.get('id')
    dateTime = query_parameters.get('dateTime')
    cleanContent = query_parameters.get('cleanContent')
    country = query_parameters.get('country')
    query = "SELECT * FROM tblJobs WHERE" to_filter = []
    if id:
        query += ' id=? AND'
        to_filter.append(id) if dateTime:
        query += ' dateTime=? AND'
        to_filter.append(dateTime) if cleanContent:
        query += ' cleanContent=? AND'
        to_filter.append(cleanContent) if country:
        query += ' country=? AND'
        to_filter.append(country) if not (id or dateTime or cleanContent or country):
       return pageNotFound(404) query = query[:-4] + ';'
    conn = sqlite3.connect('data/datasciencejobs_database.db')
    conn.row_factory = dictFactory
    cur = conn.cursor() results = cur.execute(query, to_filter).fetchall() return jsonify(results)

最后,现在完成了 API 的所有部分,可以使用 Flask 的运行功能运行应用程序。

app.run()

API 中指定的三个主要端点允许用户查询所有数据,或者基于“id”、“国家”和“日期时间”。

例如,用户可以使用以下方式查询所有数据:

‘127.0.0.1:5000/api/v1/jobs/datascience/all’

用户还可以使用其中一个端点来查询数据:

‘127.0.0.1:5000/api/v1/jobs/datascience?country=United%20States’
‘127.0.0.1:5000/api/v1/jobs/datascience?id=81953194’

5.部署 Flask 应用程序:

API 完成并按预期运行后,下一个逻辑步骤是将应用程序部署到服务器。出于本教程的目的,API 是使用本地端口在本地“部署”的。部署基于 Flask 的应用程序的一些最佳选项包括: AWSHerokuPythonAnywhere 。在探索了这三个版本之后,我个人发现www.pythonanywhere.com是这三个版本中最用户友好和最便宜的,拥有关于部署过程的全面的文档

结论:

总之,为了理解管理这个功能的主要框架,我们对 REST APIs 进行了概述。为了存储我们感兴趣的数据,创建了一个 SQL 数据库。最后,使用 Flask 使用 REST APIs 的最佳实践开发了一个 API,允许用户通过多个端点查询数据。

欲了解更多信息和访问代码,请访问 my GitHub

我们如何利用 AWS 在 60 天内推出数据产品

原文:https://towardsdatascience.com/launching-beta-data-product-within-two-month-with-aws-6ac6b55a9b5d?source=collection_archive---------11-----------------------

新闻捕手

两个人的团队在不到两个月的时间里为 200 名用户计划并发布了一个测试版,并且没有放弃他们的全职工作。

测试版 newscatcherapi.com 解决方案架构

60 天内,我们:

  • 迭代我们的架构设计 3 次
  • 发布的 Python 包在 GitHub 上获得了 800 多颗星
  • 收到了 200 多个测试版的注册
  • 交付了我们的最小可行产品

这篇文章中我将要谈到的产品的官方网站

在本文中:

  • 第一部分产品
  • 第二部分。计划&要求
  • 第三部分。解决方案架构
  • 第四部分。发布测试版

我们是由两名数据工程师组成的团队。在 2020 年 2 月和 3 月,我们将大部分空闲时间用于构建一个 API,让你可以搜索新闻文章的数据。

这就像用一行代码查询谷歌新闻档案。

我们之前几乎没有使用 AWS 或交付成功的端到端解决方案的经验。尽管如此,正确的规划、寻求帮助和投入一些时间来寻找正确的工具使之成为可能。

尽管这是一个测试版。

我们遵循的原则

在业务方面:

  1. 尽可能多地使用外部工具
  2. 尽可能快地交付,以便尽快获得用户的反馈
  3. 用户至上。他们应该决定什么重要,什么不重要

在技术方面:

  1. 尽量减少使用您必须自己运行的服务器
  2. 如果已经编写了代码,就不要再编写了
  3. 只有当客户无法使用您的解决方案时,性能才是重要的
  4. 请求帮助

第一部分.产品

何塞·马丁·拉米雷斯 C 在 Unsplash 上拍摄的照片

问题

我们大多数人阅读新闻。当我们为了个人兴趣消费新闻时,很容易跟随我们感兴趣的事情。

许多企业还必须不断了解全球的最新动态。典型的例子是金融机构。他们使用替代数据来识别非金融活动产生的风险。

政治、文化和社会事件可能引发另一系列事件,重塑某些金融市场。

当然,你可以谷歌任何关键词或话题,找到最相关的新闻结果。但是,假设你是一个交易者,想要了解投资组合中每家公司的最新消息。每小时一次。

https://www.gifbay.com/gif/newspaper_press-130154/

或者,你必须分析一个人/公司/事件在过去的一个月中被提及了多少次。

或者,您希望向服务的用户显示特定主题的最新新闻。

从某种意义上来说,手工劳动要么变得不可能,要么变得过于昂贵。成千上万的新闻文章需要分析。如果你想扩大规模,你必须自动化这个过程。

解决办法

Newscatcher AP I 是一个 JSON API,可以让你搜索新闻数据。例如,您想获得在过去一天发表的关于苹果公司的所有文章的列表。

对于每个数据记录,您将获得:

  • 相关性分数(文章与搜索标准的匹配程度)
  • 统一资源定位器
  • 发布日期和时间
  • 标题
  • 摘要
  • 文章语言
  • 网站的全球排名

我们从数以千计的新闻网站收集新闻文章数据,更重要的是,将这些数据标准化。

是数据即服务吗?

Auren Hoffman 的《数据即服务圣经》是任何想要了解什么是数据业务的人的必读之作。

根据 Auren 的愿景,数据业务有 3 大支柱:

  1. 数据采集 —我们必须从数千家不同的在线新闻发布商那里收集新闻
  2. 数据转换 —我们必须规范化我们的数据并存储它,以便它可以被数据交付流程使用
  3. 数据交付 —我们必须让客户能够消费我们的数据(例如,API)

DaaS 卖给你的是材料,而不是解决方案本身。你必须根据自己的需求调整数据以提取价值。因此,潜在客户池减少到那些拥有数据团队作为资源的人。但是,那些拥有开发人员的客户可以根据需要精确地调整数据产品。

DaaS 对 SaaS

当你饿的时候,你有两个主要的选择。

第一个是从餐馆点一些食物/去餐馆。例如,你订了 20 美元的比萨饼。

另一个选择是去杂货店,花 8 美元买下所有的食材,然后自己做饭。

自己做披萨的缺点就是要花时间。另外,你需要掌握一些技能。但是,它更便宜(如果你不为你的时间收费的话),而且你可以随心所欲地定制

餐馆的比萨饼通常不能定制。

比萨饼店是 SaaS 的一个例子,因为它给你的是最终产品。杂货店是 DaaS 的一个例子,因为它给你资源来烘烤你自己的比萨饼。

什么是贝塔?

贝塔是你如何能:

  • 验证你的想法,
  • 揭示主要技术问题
  • 收集关于用户需要的最重要功能的反馈

你不收费,所以它不需要完美。

为什么发布测试版而不是最终版?

嗯,你必须非常擅长你正在做的事情,并且完全了解你的受众,这样才能在第一次尝试时就发布“有价值的东西”。所以多花一点时间最终会有回报。

对我们来说,这也是为了验证我们的架构。我们必须看到不同的部件是如何粘在一起的。

β=最小可行产品

我不确定这是否总是正确的,但在大多数情况下应该是这样。你只留下产品无法生存的功能。

所有不必要的都放在 MVP 后的第一栏。

第二部分。计划和要求

伦纳特·约翰逊Unsplash 上拍摄的照片

测试版要求

用户传递单词/短语,API 返回一堆关于搜索主题的文章。就这么简单。

从 API 收到响应应该不会超过 3-5 秒。

我们还添加了一些过滤器,因为这很容易做到。

任何需要一个多小时开发的功能都被抛弃了。

我们的文档页面很好地展示了我们所取得的成就。

如何构建新闻 API?

简单来说,我们必须从新闻网站获取文章,比如 nytimes.com 的和 theverge.com 的等。最终目标是从任何现有的新闻网站上获取。

然后,数据规范化&重复数据删除——最重要的部分。每篇文章都是一个数据点——它有一组变量,如标题、出版日期、作者等。

例如,一篇文章发表的日期和时间应该是我们最终数据源中的一个时区。否则按时间查询数据就没有任何意义了。

最后,在我们收集和标准化之后,我们应该将数据存储在某个地方。更重要的是,检索数据应该很容易。在我们的例子中,我们很大程度上依赖于搜索功能。

去拿文章。数据收集

在我开始解释架构设计之前,我应该解释一下我们将如何收集新闻文章的数据。

第一个想法可能是为每个网站设置网页抓取器。Web 抓取已经很发达了——有很多开源库使得 web 抓取变得很容易。

但是,每个网站都有自己的结构。即使有一些令人惊奇的库可以帮助你从新闻文章中构建数据(比如报纸),它也不能 100%适用于这些来源。

制作成千上万个可以避免被禁的网络爬虫既昂贵又耗时

在理想的情况下,我应该有一个 API 来从每个新闻数据提供者那里检索最新的新闻。另外,每个 API 都是相同的设计。

但是没有这样的 API。然而,另一种获取新闻数据的方法是存在的。并且,它已经被规范化了。它被称为 RSS。

根据维基百科RSS 是一种网络提要,允许用户和应用程序以标准化的、计算机可读的格式访问网站的更新。

对于新闻网站来说,网站更新是新的新闻文章。几乎每个新闻网站都有。

RSS 已经标准化了。算是吧。您需要做一些额外的工作来从中提取主要字段。

nytimes.com 的主要 RSS

第三部分。解决方案架构

newscatcherapi.com AWS 架构图测试版

将收集到的标准化数据传送到我们的最终数据存储需要 7 个步骤——弹性搜索:

  1. CloudWatch 事件触发λ
  2. Lambda 从 DynamoDB 获取 RSS 提要 URL
  3. 同一个 Lambda 将所有这些 RSS URLs 发送到 SQS
  4. Lambda 获取来自 SQS 的每个 RSS 端点,并读取和规范化提要
  5. 新闻文章数据被插入 DynamoDB
  6. DDB 流收集多达 X 条新插入的记录,并将其发送给 Lambda
  7. Lambda 在 Elasticseearch 中插入新记录

第一步。 CloudWatch 事件触发了“编排”lambda

AWS Lambda 是一个无服务器的功能即服务工具,它运行您的代码来响应事件。您不必维护服务器。您只需为执行该功能的时间付费。

CloudWatch 事件是一个 cron 作业的 AWS 实现。

你可以设置 CloudWatch 事件,每隔 X 分钟、小时、天等触发你的 Lambda。

第二步。“编排”lambda 从 DynamoDB 获取 RSS 提要 URL

DynamoDB 表包含了我们用来更新新闻数据库的所有 RSS 提要

DynamoDB 是 AWS 的一个完全托管的非 SQL 数据库。与 AWS Lambda 一样,您不必管理其背后的硬件或软件。您可以将它作为存储数据的现成解决方案。

第三步。“编排”lambda 将所有这些 RSS URLs 发送到 SQS

现在您有了一个必须处理的所有 RSS 提要的列表。

它们有数千个,所以循环处理每一个不是一个选项。

让我们假设我们有另一个 Lambda 函数可以读取和规范化 RSS。AWS Lambda 允许您进行数百个并行调用。因此,你可以考虑从你当前的 Lambda 调用许多其他的 Lambda。

这种方法应该是可行的,但是,它会使您的过程变得复杂并且容易失败。

所以你需要中间的东西。

简单队列服务是由 AWS 完全管理的队列服务。

我们将把所有的 RSS 端点作为消息发送给 SQS,而不是从我们的“编排”Lambda 中触发 RSS 处理。然后,来自 SQS 的新消息可以触发 RSS 处理 Lambda。

通过添加 SQS 层,我们使得检查每个 RSS 端点处理的成功变得更加容易。如果其中一个 lambda 失败,它不会中断处理其他 RSS 提要的任何其他 lambda。

第四步。Lambda 从 SQS 获取每个 RSS 端点,并读取和规范化提要

我最喜欢的 AWS Lambda 特性是,你不用为同时执行多个 Lambda 而多花钱。当您不知道未来的工作负载,或者想要确保系统在接收更多负载时不会崩溃时,它使 Lambda 成为一个有用的工具。

这个 Lambda 是一个 Python 函数,它将 RSS URL 作为输入,并返回结构化数据(标题、发布日期、作者、文章 URL 等。)

现在,当我们从每个 RSS 提要中提取并规范化新闻文章的数据时,必须存储这些数据。

第五步。新闻文章数据被插入 DynamoDB

在将数据发送到 Elasticsearch 集群之前,我们将其放入 DynamoDB。主要原因是 Elasticsearch 确实失败了。Elasticsearch 在很多方面都很棒(我们将在后面讨论),但是 Elasticsearch 不能成为你的主要数据存储

重复数据删除。每个 RSS 提要偶尔会更新一次。它向提要添加了更多的文章。例如,新闻网站 X 的 RSS 提要总是包含 100 篇文章。提要每小时更新一次。如果在这一小时内有 10 篇新文章,那么它们将出现在顶部。而最早的 10 篇文章将被删除。其他 90 篇文章会和一个小时前一样。因此,所有这 90 篇文章在我们的数据库中都是重复的。

我们有成千上万的这样的反馈。

因此,如果我们能够验证每个 ID(不管它是什么)是否已经存在于我们的数据库中,那就太好了。

我从 Reddit 上得到了很好的建议:

感谢来自 AWS 的 Vladimir Budilov 的帮助

诀窍是确保我们对每篇新闻文章都有一个一致的 ID 键。我们是每篇文章的标题+网址。然后,当我们将这些数据插入 DynamoDB 时,只允许新的 id(检查 DynamoDB 的 attribute_not_exists 设置)。

因此,我们不必自己消除重复数据。

第六步。 DDB 流收集多达 X 条新插入的记录,并将其发送给 Lambda

现在,我们必须从 DynamoDB 向 Elascticsearch 集群发送新数据。

我们在 DynamoDB 插件上做了一个触发器。每次任何数据被插入 DynamoDB 时,它都会被 Lambda 拾取,然后将这些新数据发送到 Elasticsearch 集群。

将数据加载到 DynamoDB 中我们显著降低了 ES 的负载,因为它将接收更少的新数据。另外,DynamoDB 是我们的主要数据来源。

第七步。 Lambda 在 Elasticsearch 中插入新记录

DynamoDB 承担了确保数据库中没有重复项的所有繁重工作。只有新插入的记录才会进入 Elasticsearch 集群。

您可以将 Lambda 设置为等待新的 X 记录或 Y 分钟,然后一次获取多个记录。这样你的交易会更少,而且你可以利用 Elasticsearch 批量插入。

为什么选择 Elasticsearch?

因为这是使用全文搜索的最佳方式。

Elasticsearch 很复杂,你几乎可以调整任何东西。充分了解数据的用途和用途可以让您优化集群以获得最佳性能。

然而,出于测试目的,我们几乎在所有地方都使用默认设置。

数据交付/API

到目前为止,我们确保我们的 Elasticsearch 集群得到了新数据的更新。现在,我们必须为用户提供一个工具来与我们的数据进行交互。我们选择让它成为一个 RESTful API。

我最喜欢的组合是用 API Gateway + Lambda 来做。

来自 AWS 页面:

API Gateway 处理接受和处理多达数十万个并发 API 调用所涉及的所有任务,包括流量管理、CORS 支持、授权和访问控制、节流、监控和 API 版本管理。

因此 API 网关负责管理 API 请求。我们还是要实现逻辑层。Lambda 函数将处理每个 API 调用。

Lambda 本身是用一个叫 Flask 的微型 web 框架编写的。

这个 Lambda 的任务是解析用户传递的参数(比如他们想要查找文章的短语)。然后,它查询我们的 Elasticsearch 集群。最后,它组成一个干净的 JSON 响应对象,发送给用户。

除了 Flask,我们还使用了elasticsearch-DSL-py包来帮助编写和运行针对 elastic search 的查询。

我建议使用 Zappa 部署 API Lambdas:

Zappa 使得在 AWS Lambda + API Gateway 上构建和部署无服务器、事件驱动的 Python 应用程序(包括但不限于 WSGI web 应用程序)变得非常容易。可以把它想象成 Python 应用程序的“无服务器”网络托管。这意味着无限扩展、零停机、零维护,而成本只是您当前部署的一小部分!

当你不确定你要服务多少个调用时,用 Lambda 部署你的 API 是最方便的。

更重要的是,如果你有 0 个电话,你支付 0。

第四部分。后期测试

照片由蓝屋滑雪板Unsplash 上拍摄

初始(beta 后)发布计划

除了我们在测试版中取得的所有成就之外:

  • 按语言过滤
  • 适用于 6-10 种最常见语言的正确文本分析器
  • 精确匹配搜索
  • 必须包含/排除一个短语
  • 按国家过滤
  • 每个国家/地区端点的头条新闻
  • 按主题过滤(体育、商业、娱乐等。)
  • 页码

我们将有大量的工作来优化我们的弹性搜索集群。最大的变化是正确的根据语言分析文本字段。

重点是让搜索知道用户想要的语言。例如,默认的 Elasticsearch 文本分析器不知道“got”是“go”的基本形式。而英语分析器使用词干来跟踪这些东西。

因此,知道你希望你的文章被搜索到哪种语言将极大地提高找到的文章的相关性分数。

日志记录是我们想要实现的另一件重要的事情。最有可能的是,我们将使用 Elasticsearch 进行日志记录。

还应实施弹性搜索恢复计划。至少,我们应该知道集群何时关闭(目前情况并非如此)。

结论

它只是工作。你还需要从测试版中得到什么?

帮助我们进行测试的两个主要因素是:

  1. 请 Reddit 帮助我们设计建筑
  2. 投资一些时间来发布我们的 Python 包 →获得 beta 注册

https://www.youtube.com/watch?v=r13riaRKGo0

感谢你一路阅读到这里。

支持我们的最好方式是参加我们的封闭测试

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.

走向不确定性——让您的 ML 模型经得起未来考验的 6 个明智步骤

原文:https://towardsdatascience.com/launching-into-uncertainty-6-smart-steps-to-future-proof-your-ml-models-bdebbccc6c43?source=collection_archive---------71-----------------------

新冠肺炎版:

你的机器学*模型在疫情会失败。以下是减轻损害的方法。

来自 Unsplash 的照片 Anastasia Patrova

有许多文章关注机器学*如何能够并且正在疫情期间提供帮助。韩国和台湾政府成功展示了他们如何利用人工智能来减缓新冠肺炎病毒的传播。法国科技公司发现没有戴口罩的热点地区,建议政府将重点放在教育上。数据和医学专家合作索引新冠肺炎医学期刊论文

来自数据科学界的参与令人振奋,结果也很突出。

但是这个帖子讲的恰恰相反。我在这里不是要吹捧机器学*的成功。我在这里对它所有的荣耀和奇迹产生一点怀疑。我是来问这个问题的:

在这段不确定的时间里,你在观察你的机器学*模型吗?

为什么不呢?

照片由斯蒂芬·道森Unsplash 拍摄

现实生活中的数据经常与训练数据相背离。从您将准确、稳定的模型发布到产品中的那一天起,随着客户的发展,它的性能每天都在下降。对于新冠肺炎来说,这就好像是将模型从安全的培养皿中释放出来,放入狂野的西部。

随着政策变化、利率下降和支付假期,突然的数据转移会对您的模型产生深远的影响。模型精度下降没问题,但是对变化一无所知就不行了。

模型精度下降是可以的,但是对变化一无所知是不行的

在过去的几周里,我一直在参与这些机器学*模型的影响评估。最初这是压倒性的,所以我收集了一些实际的步骤,希望其他团队可以带着更多的信心和更少的恐慌来处理这个过程:

作者制作的信息图。由 Eucarlp 从www.flaticon.com创作的图标

为了避免就这个主题写一整本书,本文使用了相当多的术语。如果您不确定术语的含义,请单击超链接。

步骤 1:识别受影响的用例以及涉众

图标来自桉树,作者改编。

不是所有的用例都会受到疫情的影响,就像不是所有的模型都会遭受数据数据或概念漂移

任何软件评估的第一步都和任何软件开发的第一步一样:提出问题。

问一堆问题。

如果您有许多正在进行的用例,并且不确定先处理哪一个,请从以下问题开始:

❓:我在模拟人类行为吗?(即复活节期间购买的物品、房屋贷款首付款)

❓Did:我对政府或企业在危机期间改变的政策(如旅行禁令、银行支付假期)有任何固有的假设

一旦你确定了用例,然后指出受这些用例影响的涉众。涉众通常是该领域的主题专家,因此他们可以在下面的步骤 2 中帮助您。

给自己画一个决策树。

如果您的系统涉及到人员或策略,请继续执行步骤 2

否则,继续前进。

第二步:评估事情出错时的风险和暴露程度

图标来自桉树,作者改编。

这个疫情是黑天鹅事件的经典案例。这是一次罕见的意外病毒爆发,后果严重。

所以很有可能事情会出错,但是会错到什么程度呢?

事情将会出错,但到底会错到什么程度呢?

情景分析 可以帮助我们驾驭这些极端情况。

在这一步中,与业务部门的 SME(主题专家)交谈非常有价值。他们通常有许多问题想要答案,数据科学家将分析数据以生成这些问题的洞察包。这时候这些问题可以帮助你审问你的模型。

举个例子,

"如果房地产销售大幅下降,我们的底线会怎么样?"

好了,现在是检验它的时候了。如果您正在对房屋贷款产生的收入进行建模,那么在房屋贷款销售额较低时(夏季度假城镇的冬季月份)检查数据。然后,根据 SME 的建议进行调整,生成一个假的输入数据集,并在您的模型中运行。这可以帮助您评估模型面临风险的区域。

给出一个量化的数字可以帮助企业做出艰难的决定。即使我们觉得我们没有足够的信息来提供预测,但仍然要做出决定。贷款仍然需要发放,卫生纸仍然需要运输。我们不应该把责任推得更远,而应该专注于尽力而为。

给出一个附有所有星号的预测。

如果影响很大,请继续第 3 步进行彻底检查。

否则,继续前进。

步骤 3:检查整个解决方案的漏洞

图标来自桉树,作者改编。

机器学*解决方案不仅仅是模型本身。有数据工程管道、推理和模型再训练。端到端地扫描整个解决方案以发现漏洞非常重要。

机器学*解决方案不仅仅是模型

以下是您可以关注的一些领域:

⏩大量购买会破坏你的销售渠道吗?一些供应商的预测算法被订单数量的突然变化破坏。另一方面,一些欺诈检测系统被误报淹没了。

⏩您的基础架构上的基本负载是否发生了变化?有些模型不太相关,有些甚至更重要,转移您的计算资源可以平衡成本。

⏩调查模型的全局和局部特征重要性。你的主要特征对疫情敏感吗?他们应该吗?有很多关于可解释 AI 的文章,在未知的时间里,推理可解释性可以给人们需要的透明度。

在整个管道中定义检查。

到第 3 步时,您已经确定您的解决方案受到了危机的影响。所以继续第 4 步。

从这一点开始,没有前进,只有前进。

步骤 4:设置自动警报和修复

图标来自桉树,作者改编。

如果你正在阅读这篇文章,你可能还没有监控系统。否则,你将设置 500 吉拉门票,并在您的下一步顶部。

部署机器学*模型就像驾驶飞机一样

想象你是一名飞行员:

☑️:没有伐木就像没有黑匣子的飞行。任何恐怖分子都可以劫持飞机而不承担任何后果。

🖥️:没有监控就像在新的空域盲目飞行。飞行员不知道他要去哪里,你也不知道。

🌪没有弹性基础设施的️️:就像一架无人维护的飞机。机票很便宜,但飞机随时可能坠毁。

来自 UnsplashKaotaru 摄影, melio.ai 编辑

你不会带着一个失明的飞行员和一个坏掉的引擎登机,为什么你要部署一个没有日志记录、监控和弹性基础设施的模型呢?

先不说监控,治愈呢?

许多成熟的机器学*解决方案都在系统中内置了自动化的再培训。但在这些极端事件中,或许值得看一看刷新的车型。他们使用最新的数据进行预测吗?他们应该吗?

面对未知情况时,自动重新部署刷新的模型可能会有风险。人在回路的方法可以是临时的,也可以是战略性的解决方案。

1️⃣设置了自动再培训和报告(使用业务 KPI 以及步骤 3 中定义的抽查)。

在疫情时期,2️⃣用更严格的警告标准警告人们要得到认可。

3️⃣:如果步骤 1-3 被严格执行,并且风险和暴露被承认,那么我们可能准备好重新部署模型。

监控数据和模型漂移,并在必要时重新部署。

如果您仍然不确定,设置 金丝雀部署 并将您的一小部分流量重定向到新模式。然后等新车型稳定了再慢慢淘汰旧的。

第五步:打开包装,交流未来的挑战

图标来自桉树,作者改编。

新冠肺炎的影响从卫生纸短缺到全球经济崩溃不等。即使不是所有行业,也是大多数行业受到了正面或负面的影响。

这种反常可能会成为新的常态

远程工作、破产激增、结构性失业以及旅行限制等长期影响尚不明朗。当历史数据在这种前所未有的情况下不适用时,“异常”就可能成为新的常态。这迫使我们回过头来解开基本的商业问题,并重新思考许多假设。

⏩我们在未来的模型训练中包括疫情的数据吗?

⏩我们是否包含了更好地反映当前现实的新特性?

⏩当发生重大中断时,我们应该调整模型的敏感性吗?

⏩我们需要重新评估疫情之前选择的模型指标吗?

⏩当事情“恢复正常”时,我们会恢复上述所有情况吗?

在这个阶段,问题比答案多。盲目推荐“最佳实践”为时尚早。

唯一的办法是保持好奇,保持沟通畅通,承认风险,一步一步来。

步骤 6:建立后备系统以减轻影响

图标来自桉树,作者改编。

你想过为什么蜣螂不会迷路吗?

这些微小的昆虫使用一系列的导向系统来帮助它们达到尽可能高的精确度。当一个系统不可靠时,他们切换到使用另一个

当你没有任何数据的时候,你就得用理智~理查德·费曼

著名物理学家、诺贝尔奖获得者劳蕾特·理查德·费曼在调查美国宇航局挑战者计划灾难时说:“当你没有任何数据时,你必须使用理性。”(摘自戴维·爱泼斯坦的系列,第 9 章)。

当机器学*依赖于历史模式时,这一点尤其正确。当历史模式不可靠时,需要调用替代策略:

无监督 或半监督方法可以帮助重新定义问题空间。基于现有用户的新行为为其创建新的细分。一个过去的户外迷可能是现在正念的瑜伽士。

压力测试:第二步建立的场景分析框架可用于加载输入数据的各种极端情况。

⏩集成或选择:集成很受欢迎,因为它能够通过组合多个弱学*者来创建强学*者。有时,这可能是不必要的。一个用例可能有多个模型。工程管道可以检测变更或属性,并使用最合适的模型进行推断。

或者以上都有,以人为中心。

这就是为什么女士们先生们——AutoML 不会取代数据科学家。成为理性的声音。与中小企业交流。保持冷静,坚持下去。

来自 UnsplashTonik 拍摄的照片

在这个不确定的时期避免变化是一项挑战。没有人能确定任何事情,做一个预测是令人畏惧的。遵循以下步骤可以指导您解决无法预见的问题:

  1. 回到基本面,这个用例是关于什么的?
  2. 问题&解释你的模型
  3. 抽查您的整个解决方案
  4. 建立测井&监控框架
  5. 再培训和重新部署
  6. 保持好奇心,为未来做准备
  7. 做一只屎壳郎

如果你喜欢这篇文章,我以前也发表过类似的主题:

感谢阅读 ⭐在媒体LinkedIn 上关注我,或者访问我的网站。此外,如果你想评估你的机器学*部署框架,在 Melio Consulting 给我们发电子邮件

用 Python 实现金融中的大数定律

原文:https://towardsdatascience.com/law-of-large-numbers-in-finance-using-python-86945eaee444?source=collection_archive---------44-----------------------

大数定律:

你有没有想过赌场是怎么赚钱的?大数定律从统计学的早期阶段开始就是一个众所周知的概念。但是,我们不仅仅在统计学中发现它的用途。它的重要性体现在生活的各个领域,从赌博到汽车保险定价,甚至是猜测谁会赢得选举。

鸣谢:图片来自 Unsplash

大数定律指出,随着试验或观察次数的增加,观察到的或实际的概率接*预期的均值或理论值。这意味着随着样本量的增加,样本的平均值越来越接*总人口的平均值。

大数定律在从金融到商业到统计的各种分析领域都有应用。例如,在商业环境中,增长率往往是大数法则的代表。这表现为增长率或多或少地与经济增长率趋同。类似的情况也出现在金融领域,市值巨大的公司或多或少变得停滞不前,看不到之前观察到的增长。

理解这个概念的一个非常有力且被广泛引用的例子是观察硬币的翻转。最初的几次投掷不一定有一半的机会是正面或反面。对于一个结果可能有更高的累积概率。因此,相对频率可能与预期的 50%相差很远,比如说 10、20、50、100 次翻转。但另一方面,假设我们像掷硬币 a 一样掷 1000 次或 100000 次,那么得到正面的累积概率就更接* 50%的期望值。

我试图通过用 python 写代码来模拟这种情况。

在观察不同翻转次数的累积概率时,我们看到当整体翻转随着分布接*正态分布而开始变高时,概率收敛到期望值 50.0%。

仅仅 10 次翻转,我们就能看到以下内容:

抛 10 次硬币正面朝上的概率

对于 1000 次翻转,我们会看到以下内容:

投掷硬币 1000 次,正面集中到 50%的概率

因此,大数定律有助于我们理解为什么不能只相信一个结果。这就是为什么我们需要对从样本人群中得到的观察结果持怀疑态度,尤其是那些低数量的人群。

平均法则:

有时人们倾向于把大数定律和平均数定律互换。他们不一样。大数定律是一个数学定理,随着试验次数的增加(大型试验),理论上结果必然会收敛到预期的平均值,而平均定律或多或少是一个门外汉术语,认为试验的结果会在一个小样本内达到平衡。这不是数学原理,而是一厢情愿的想法。而这个非常糟糕的统计数据导致了‘赌徒谬误’的概念。

赌徒的谬误:

这种谬误是一种信念,认为某个结果可能会发生,因为错误地理解了平均法则的基本原理。这导致“赌徒”相信,由于特定的结果最*没有发生,所以它现在有可能发生,从而达到平均。人们需要理解,各种结果的发生之间没有关系,它们是相互独立的。

虽然大数定律将有助于赌场在大量旋转中获得收益,即使它在轮盘赌的单次或几次旋转中失败,但是平均定律将不会帮助赌徒,因为假设轮盘现在将落在黑色上,就像它以前几次落在红色上一样。因此它纯粹是随机的,没有真正的平均律概念。

大数定律在交易和金融中的应用:

大数定律在贸易和金融领域也有应用。它表明,大量具有较高夏普比率(回报风险比)的交易往往比少量交易更有效。

正如乔治索罗斯(George Soros)所言,重要的不是你是对是错,而是正确时你会赚多少,错误时你会亏多少,这让你的策略更有针对性。这归结为有效风险管理的原因。在这种情况下,根据大数定律,一个交易者可能大部分时间都是错的,但仍然是盈利的。

在很多这样的场景中,最大的挑战是理解一段时间实际上有多长。经验告诉我们,尽可能长时间的回溯测试会让我们更接*平均年化回报。让我们以低频交易策略为例。让我们试着去理解实现一个更真实的夏普战略和它的方差需要多长时间。

让我们假设一个经过回溯测试的策略的真实夏普比率为 2(假设这是低频交易的平均值)。让我们在大约 2 个月的 40 天交易期内试着认识到这一点。假设正态分布的平均回报率为 0.1%,让我们模拟一下,看看夏普比率随着交易(或试验)次数的增加而变化。

它的 python 代码如下。

只做了 15 笔交易,我们看到以下夏普比率:

进行了 15 次交易

上面的直方图告诉我们,只要有几笔交易,就会得到比回溯测试更低的夏普比率。

通过 500 笔交易,我们观察到以下情况:

500 笔交易

在 2500 笔交易中,我们看到了以下情况:

2500 笔交易

从上面的图表中,我们可以清楚地看到,随着轨迹的减少,我们可能会观察到更多的损失。但是最终,随着试验的不断增加,夏普比率趋向于回溯测试的数字(通过趋向于正态分布)。这里的诀窍是尽可能多地参与大量的试验。

行为心理学对 LLN 的入侵:

大数定律的关键在于,首先,一次又一次地交易,其次,不要因为一次又一次地改变潜在的假设而中断交易。交易者确实倾向于改变策略,希望战胜市场,因此很难保持自我控制。在不气馁的情况下尽可能多的交易是一个非常困难的任务。因此,“耐心和财务”这个概念变得比以往任何时候都重要。这个信息超载的时代是一把双刃剑。它一方面帮助长期投资者做出明智的选择,但同时也干扰了另一个不耐烦的投资者对策略进行定期评估。这使投资者倾向于选择正确的股票,但在错误的时机退出交易策略,甚至在很早的时候退出交易游戏。

离别的思念:

无论从回溯测试中得出的交易策略听起来有多好,它都取决于你无数次的执行和实践。交易是一份需要正确的技术和技能,经验和更重要的不断尝试的工作。

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

走向一个特定法律领域的伯特?

原文:https://towardsdatascience.com/lawbert-towards-a-legal-domain-specific-bert-716886522b49?source=collection_archive---------21-----------------------

法律行业的特定领域 BERT

来源:大英图书馆

谷歌来自变形金刚的双向编码器表示(BERT)是 2018 年开发的大规模预训练自动编码语言模型。它的发展被描述为 NLP 社区的“ImageNet 时刻”,主要是因为 BERT 在执行下游 NLP 语言理解任务时非常熟练,只需要很少的反向传播和微调(通常只有 2-4 个时期)。

来源:德夫林等人(2019 年)

对于上下文,传统的单词嵌入(例如 word2vec 和 GloVe)是非上下文的。they用单个静态向量表示每个单词令牌,通过单词共现而不是单词的顺序上下文来学*。当一词多义时(即同一个词有多个不同的意思),这可能会有问题,这在法律中是很常见的。

来源:谷歌开发者

例如,单个静态上下文无关向量将用于表示句子“柠檬是酸的”和“那辆车是柠檬”中的单词“柠檬”(即,对柠檬法则的有趣引用,该法则在新车被证明有缺陷时保护消费者)。

来源: Ethayarajh (2019)

相比之下,BERT 是一个上下文模型,它基于每个单词周围的单词生成特定于上下文的表示。有趣的是,Ethayarajh (2019)表明,BERT 不会为每个词义创建一个“柠檬”的表示(左选项),而是会创建无限多个“柠檬”的表示,每个表示都高度特定于其上下文(右选项)。这意味着不是生成单个密集向量来表示令牌“lemon”,而是将令牌动态地表示为“______ 是酸的”和“那辆车是 _____”。

伯特捕捉语言多义性的能力尤其适用于多义性大量存在的法律领域。例如,法律中的“对价”一词代表契约关系中的互惠理念,与该词通常的含义“考虑周到”有着不同的含义。此外,同一术语在成文法和判例法中可以有多种定义。例如,“工人”一词在欧盟法律中有四种不同的定义,甚至在同一份文件中也可以用来指不同种类的工人。因此,语境语言模型的发展对法律人工智能领域具有重要意义。

BERT 体系结构的技术细节超出了本文的范围(已经有大量文章讨论过)。然而,值得注意的是,BERT 的关键创新之一是它的双向性,即它克服了顺序文本解析的传统问题。值得注意的是,这个上下文中的双向并不意味着在顺序意义上的双向(即同时从左到右和从右到左进行解析),而是在同时意义上的双向(即它同时从所有层中的令牌的左右上下文中学*信息)。这是通过使用像掩蔽 LMs (MLMs)和下一句预测(NSP)这样的方法来实现的,以获得更好的上下文单词嵌入结果。

特定领域的优势

来源:大英百科全书

虽然 BERT 在执行一般语言表示任务方面非常有效,但问题是——在未标记的通用维基百科和开源文章上接受训练——它缺乏特定领域的知识。这是一个重要的警告,因为语言模型只能和它的语料库一样好。打个比方,将一个普通的伯特模型应用于特定法律领域的问题,可能相当于让一个文科生去解决一个法律问题,而不是让一个学了多年法律知识的法律学生去解决。这是有问题的,因为在一般开源语料库(例如维基百科和新闻文章)中发现的语言和法律语言之间有很多脱节,这些语言可能是深奥的和基于拉丁语的。

虽然在撰写本文时尚未开发出法律领域特定的 BERT 模型,但已经开发的其他领域特定的 BERT 的示例包括 BioBERT(生物医学科学)、SciBERT(科学出版物)、FinBERT(金融通讯)和 ClinicalBERT(临床笔记)。尽管它们都具有特定于领域的 BERTs 的相似性,但是它们的体系结构表现出许多关键的不同。

培训特定法律领域的专家

我将探索一些培训特定领域业务技术人员的方法:

完全预先训练伯特

这包括用大规模未标记的法律语料库(例如,法令、判例)完全重做 BERT 的预训练过程。从这个意义上说,特定领域的知识将在预培训过程中注入。这是 SCIVOCAB SciBERT 采用的方法。

虽然这确实大大提高了 BERT 在特定领域任务上的性能,但关键问题是完成重新训练所需的时间、成本和数据量可能太大而不可行。BERT-Base 本身是一个具有 12 个堆叠层和大约 1.1 亿个权重/参数的神经网络,其预训练语料库需要 33 亿个令牌。重新训练特定领域的 BERT 将需要类似数量的训练数据(例如,SciBERT 使用了 31.7 亿个令牌)。训练该模型需要一周或更长时间(例如,SCIVOCAB SciBERTs 在 v3 TPU 上训练需要一周时间),并且成本极高,这对于一般企业来说根本不可行。

进一步预培训 BERT

因此,一种折衷方案可能是不完全重新训练 BERT,而是从 BERT 初始化权重,并用合法的特定领域数据进一步对其进行预训练。这已被证明可以提高 BERT 的性能,Sun (2019)表明,经过进一步预训练的模型在所有七个数据集上的表现都优于原始的 BERT-Base 模型。

这似乎是最受欢迎的方法,用于 BioBERT、BASEVOCAB SciBERT 和 FinBERT。研究人员没有完全从头开始重新训练,而是用从 BERT-Base 学*到的权重初始化新的 BERT 模型,然后在特定领域的文本上训练它(例如 PubMed abstracts 和 BioBERT 的 PMC 全文文章)。Lee 等人(2020)报告说,BioBERT 在所有数据集上取得了比 BERT 更高的 F1、精度和召回分数。同样,Beltagy 等人(2019)报告称,SciBert 在生物医学、计算机科学和多领域任务上表现出色。

来源:李等人(2019)

微调伯特

另一个更简单的选择是使用预先训练的 BERT,但在下游 NLP 任务中使用特定于法律领域的语料库对其进行微调。微调的概念来自迁移学*的领域,简单地说,这意味着采用一个旨在解决任务 x 的模型,并将其重新用于解决任务 y 。在实践中,它通常意味着采用预训练的 BERT 模型,并在最后添加一个未训练神经元的额外输出层,然后使用带标签的法律语料库进行训练(微调通常是一项监督任务)。在对特定于领域的数据进行微调之后,得到的模型将具有更新的权重,更接*于目标领域的特征和词汇

这种方法的优点是,它需要的数据少得多,而且训练起来明显更快、更便宜。鉴于 BERT-Base 的预训练已经编码了一般领域中大多数单词的知识,它只需要一些调整就可以适应法律上下文的功能。微调通常只需要 2-4 个时期(几分钟的事情),而不是几周的时间跨度。这种方法还需要更少的数据(尽管它通常需要带标签的数据),这使它更可行。

此外,如果需要,微调可以结合特定领域的预训练来完成,即它们不是互斥的方法。例如,BioBERT 首先接受生物医学领域特定语料库的预训练,然后在生物医学文本挖掘任务上进行微调,如命名实体识别、关系提取和 QA。

结论

随着最*对像 OpenAI 的 GPT-3 这样的超大规模模型的大肆宣传,最初围绕 BERT 的兴奋似乎有些消退。然而,值得记住的是,BERT 仍然是一个非常强大和敏捷的模型,可以说它有更多的实际应用。从特定领域的 BERT(如 SciBERT 和 BioBERT)的经验来看,在特定领域的语料库上微调和/或预训练 BERT 可能会提高法律 NLP 任务的性能。为此,根据研究人员的时间和金钱资源,有各种方法来改善和调整伯特的表现。

分层标签传播算法

原文:https://towardsdatascience.com/layered-label-propagation-algorithm-1b181b982e80?source=collection_archive---------46-----------------------

一种社区发现算法

在运行分层标签传播算法之后,具有可变混合参数(μ)和固定节点数以及平均节点度的 lanchi netti-Fortunato-radic chi 基准合成网络。

分层标签传播算法(LLP) 1的发展强烈地基于旧的标签传播(LP) [2]。后者从给网络中的每个节点分配不同的社区开始。然后,在每一轮的开始,节点的顺序被随机化。在每一轮中,每个节点将被分配在直接邻居中更有代表性的社区。只要社区没有发生变化,或者达到给定的迭代次数,LP 就结束。它不依赖于任何目标函数的优化,并且不需要关于网络中存在的社区的先验信息(无监督的)。虽然,可以用*似集输入(半监督)。根据定义,该算法本质上是局部的,在边的数量上是(*似)线性的,并且在图中需要很少的通道。这些是允许对真实网络进行分析的基本特征。寻找最优划分的问题已经被证明等价于寻找动力学 Potts 模型1的哈密顿量的局部最小值。虽然这个问题有一个平凡的全局最优解,将整个网络视为一个集群,但这不是我们感兴趣的。LP 避免了这样的解决方案,因为本地搜索的固有动态性。虽然这通常被认为是一个缺点,但在这种情况下,它是 LP 算法工作的一个基本特征。

尽管使用了类似的方法,LLP 不仅考虑了邻居中的节点,还考虑了剩余网络中的节点。迭代过程是一样的,区别在于它优化的值。在这种情况下,分配的社区将最大化:

𝑘𝑖是在给定节点的邻域中带有标签𝜆𝑖的节点的数量,而𝑣𝑖是整个图中以相同方式标记的总数。𝛾是分辨率参数,通过其在整个网络中的通常存在来缓冲属于邻域中给定社区的节点的数量。每当接* 0 时,LLP 就减少到 LP。预计对于较低的𝛾值,该算法将突出显示较少、较大和稀疏的聚类。对于更高的值,簇变得更小、更密集并增加它们的数量。可以说,没有一个先验的度量来说明哪个值对被分析的网络更好。算法 1 中 LLP 的伪代码。

与 LLP 类似,已经提出了其他算法,它们执行相同的步骤序列,但最大化不同的值,如模块化。

利用多个处理器的并行实现可以显著地加速该算法在我们的机器上的执行。

参考

1 P. Boldi,M. Rosa,M. Santini 和 S. Vigna,“分层标签传播:用于压缩社交网络的多分辨率无坐标排序”,载于 WWW '11 第 20 届国际万维网会议论文集,2011 年;

[2] N. Raghavan,R. Albert 和 s .鸠摩罗王,“检测大规模网络中社区结构的*线性时间算法”,物理评论 E 25 周年里程碑,第 76 卷第 3 期,2007 年。

数据层:背景如何帮助做出更好的决策

原文:https://towardsdatascience.com/layers-of-data-how-context-helps-make-better-decisions-4432b855573c?source=collection_archive---------47-----------------------

2012 年,《哈佛商业评论》宣布数据科学家的角色是“21 世纪最性感的工作”。Glassdoor 在 2016 年将数据科学家列为他们年度最佳工作名单的第一位,这更是火上浇油。他们 2019 年的头号工作?你猜对了:数据科学家。那么,这些“受过培训、有好奇心在大数据世界中做出发现的高级专业人员”到底有什么特别性感的地方呢?首先,现在的数据比以往任何时候都多,而且大多数数据都是最*才创建的。2017 年,数据管理平台 Domo 估计,所有数据中有 90%是在前两年内创建的——每天有 2.5 万亿字节的数据。难怪公司对如何最好地利用这些前所未有的数据感兴趣。然而,大量的数据不一定是相关的数据。这种不一致导致公司在过去十年中争相实施程序来解释这些数据并产生可操作的见解。正如杜克大学经济学家丹·艾瑞里在 2013 年所说:

“大数据就像青少年性行为:每个人都在谈论它,没有人真正知道如何去做,每个人都认为其他人都在做,所以每个人都声称自己在做……”

因此,数据科学家对这些海量信息的理解能力变得非常有价值。通过绘制不同数据点之间的联系,并评估这些数据为何重要的更大图景,数据科学家能够帮助公司获得有意义的见解,从而做出更好的决策。

为什么没有上下文数据毫无意义

从表面上看,数据只是数字、单词等的集合。只有当数据与上下文一起呈现时,它才变得有意义。以谷歌趋势图为例:

没有任何语境,完全没有意义。这个频率肯定有周期性的东西,但是还不完全清楚这个频率是什么或者为什么会发生,或者它为什么重要。现在,如果我告诉你趋势图是关于搜索词“馅饼”的,你可以开始对数据得出有意义的结论:也就是说,每年都有一些东西导致搜索词“馅饼”的搜索量激增。如果我继续提供上下文线索,数据会变得越来越相关。例如,请允许我进一步澄清,搜索仅限于美国,峰值似乎集中在一个主要峰值和一个次要峰值上:

知道了在美国对“馅饼”的搜索在每年的 11 月达到高峰,我们就可以开始推断这些数据意味着什么。在这一点上,你可能会对自己说“很明显,在感恩节前后搜索馅饼的次数会激增。”然而,这正是上下文变得至关重要的地方。如果你在美国出生和长大,你很可能知道感恩节在 11 月,而且馅饼经常在感恩节供应,因此馅饼搜索的激增与人们计划感恩节庆祝活动直接相关。然而,如果你不是在美国长大的,你可能缺乏上下文参考来理解为什么馅饼搜索在美国的 11 月达到高峰。

那么三月份的小高峰是怎么回事呢?在这一点上,你可能已经猜到了,3 月份的峰值很可能是每年 3 月 14 日(3.14…明白吗?).同样,这些数据只对那些拥有提供相关性的适当上下文的人有洞察力。如果你从未听说过圆周率日,3 月份的数据峰值可能不会给你提供太多的见解。

有了适当的上下文,可以根据数据做出决策,也可以根据数据的含义做出决策。在我们的 pie 示例中,假设的 pie 制造商的 CMO 将配备有关于流量*惯的信息(数据),以及与这些*惯相关的热门话题(上下文)。总之,这可以支持广告活动,其中数据通知何时以及如何到达消费者,并且上下文通知他们可能发现相关和有趣的内容。

值得一提的是,这个例子过于简化,可能需要通过定量和定性手段获得额外的数据和背景。无论如何,希望这些性感的数据科学家能够通过研究趋势和背景线索来帮助改善决策,这一点变得越来越清楚。可能不太清楚的是,他们如何可能开始用 2.5 万亿字节的日常数据做到这一点。这就是技术进入等式的地方。

计算机如何帮助导航上下文线索

在我们进入芯片和算法之前,让我们花点时间想想是什么让数据科学家能够如此出色地完成他们的工作。广义地说,他们都可以使用现存的最强大的计算机:人脑。神经科学家 Bobby Kasthuri 博士致力于“以前所未有的规模绘制大脑地图”,他估计一个人的大脑有大约 1000 亿个连接连接超过 1000 亿个神经元。正是这种极端的复杂性导致了意识和认知。实际上,这种复杂性和力量是人类之所以为人的原因。生物过程和它们影响的高级行为特征之间的这种分离最终是神经科学和认知科学之间的差异。这一切都回避了一个问题:如果我们能制造一台像人脑一样复杂的计算机,它能“思考”吗?

截至这篇论文发表时,人类大脑的复杂程度比我们可用的最强大的计算机还要高几个数量级,因此,真正的计算机认知距离现实还有很长的路要走。如果我们看看神经科学/认知科学的关系,电气工程和计算机科学之间有明显的相似之处。计算机行为背后的理论(计算机科学)受限于硬件的实际约束(电子工程)。因此,计算机需要人类的输入和指令才能以某种方式运行。换句话说,它们需要数据(输入)和上下文(指令)来生成一些有价值的输出。数据科学家可以利用他们的经验、洞察力、研究和批判性思维来帮助计算机“学*”与给定数据集相关的上下文。反过来,计算机可以在给定的上下文中快速独立地处理这些数据。这就是机器学*的有效工作方式。一旦经过训练,计算机可以接受新的输入,并确定该输入是否与已建立的上下文匹配,并相应地采取行动,提供根据已建立的上下文理解进行判断的新输出。这个循环本质上就是我们所说的人工智能。

尽管有了这些基本的工具,计算机离思考还有很长的路要走。正如柳文欢·埃齐奥尼在《T4》中所说的,如何知道人工智能是否会毁灭文明:

机器只拥有人类丰富多样的学*能力的一小部分。说机器学*就像说小企鹅知道如何捕鱼。事实是,成年企鹅会游泳,捕捉鱼,消化鱼,吐出到它们的嘴里,然后把食物放进它们孩子的嘴里。人工智能同样被人类科学家和工程师填鸭式喂养。

与机器学*相反,人类学*将个人动机(“我想独立于父母开车”)映射到战略学*计划(“参加驾驶培训,周末练*”)。一个人制定具体的学*目标(“在平行停车方面变得更好”),收集并标记数据(“这次角度错了”),并融入外部反馈和背景知识(“讲师解释了如何使用侧镜”)。人类识别、框定和塑造学*问题。这些人类的能力没有一项是机器可以远程复制的。机器可以执行超人的统计计算,但这仅仅是学*的最后一英里。"

我们如何利用人工智能做出更好的决策

显然,技术“思考”的能力与我们自己的能力还相差甚远。然而,当我们将人工智能视为改善我们决策方式的几个可用工具之一时,它仍然提供了显著的好处。

如果计算机缺乏真正“思考”和生成战略决策的能力,我们还应该使用人工“智能”这个术语吗?如果我们按照以下定义来考虑人工智能,我会说是的:人工智能是一个依赖人类输入的计算机系统,以便在给定的数据环境下处理可能的输出。没有人类的智能,人工智能是没有意义的。

想想人工智能的这个定义,很明显,任何输出的价值都将受到数据准确性和上下文相关性的限制。此外,上下文的范围将是“影响”任何结果的最大驱动因素。如果我们要接受人工智能的功能至少类似于人类智能,尽管功能远不如人类智能,那么我们应该首先考虑如何利用我们自己的智能来为决策提供信息,这是有道理的。考虑一下机器学*公司 OnCorps 的创始人兼首席执行官、埃森哲前首席技术策略师 Bob Suh 的话:

情商高的人优势明显。他们学*其他人的模式,知道如何传达同理心,并根据他们对他人反应的预期,仔细权衡回应,选择最佳回应。情商帮助领导者做出更好的决策,产生更好的结果。

考虑到情商的这一定义,模式是从经过仔细权衡(上下文)的响应(数据)中得出的。所有这些都符合我们之前对机器学*的定义。主要的补充是在 Suh 的描述中,高情商的人知道“如何传达同理心”这是人类的理解和人工智能的输出可以一起行动,以更好地做出决策的地方。

最普遍接受的同理心定义(也是 Suh 提到的与高情商个体相关的定义)是“对他人态度的心理认同或替代体验。”较少讨论的是移情的第二个定义,它是“赋予一个物体,如一个自然物体或艺术品,自身存在的情感或态度的想象力。”如果我们认为“要做的决定”是一个我们可以归因于自己的感觉或态度的对象,那么我们就可以看到决策是一系列的行动,在这些行动中,我们将自己的情感背景用于最终结果。这就是人脑的复杂性取代计算机能力的地方,并允许我们做出比计算机本身更复杂的决定。

避免语境偏见的危险

在我们上面提到的例子中,正是个人情绪和经历的可变性最终允许了复杂的决策。每个人都会对输入指导和输出评估做出不同的、略有细微差别的解释。因此,考虑用于训练 AI 的上下文如何导致有偏见的结果是至关重要的。虽然个人可能会对如何解释和使用任何人工智能输出产生明显的偏见,但本节将特别关注输入偏见如何导致重大但往往隐藏的问题。为什么?因为如果你的任务是仅仅基于输出做出决策,你可能会缺乏任何关于是什么形成了输入的背景,这可能会导致你对数据的完全不正确的解释。

历史偏见是有偏见的最明显的例子之一。当由于文化、法律和/或系统原因,数据集被限制在一个小的上下文子集内,可能不再有效时,就会出现这种情况。举个例子,广泛报道的问题与亚马逊试图创建一个人工智能算法来审查新员工并为公司的发展职位找到最佳候选人有关。一旦实施,结果明显倾向于推荐男性候选人而不是女性候选人。原因?亚马逊使用十年的应用程序作为成功/失败的背景来建立这个系统。问题是绝大多数技术职位的候选人和雇员都是男性。虽然众所周知,历史上(以及现在)技术行业的工作都是由男性主导的,但任何数据模型都必须考虑这一历史背景,以防止有偏见的招聘决策。

偏置结果的另一个例子涉及先前关于人类经验和视角的讨论,用于向数据集提供上下文。有一种现象与人类所说的他们的感受/想法和他们的大脑实际反应之间的差异有关。正如我们之前讨论的,我们可以将处理(神经科学)与输出(认知)分开。在许多情况下,我们的生活经历导致我们(通常是下意识地)改变我们的输出,以满足我们认为可以接受的东西(社会的、情境的或其他的)。情感本质上是主观的。这当然会影响我们训练数据模型的方式,这会给任何人工智能输出增加偏见。

如果我们认识到背景主观性会固有地偏向数据训练,那么我们必须检查这对基于这些主观模型的现实世界决策有什么潜在影响。2016 年 5 月,ProPublica 对语境偏见的影响进行了最早和最彻底的调查。他们对美国各地法庭使用的“风险评估”算法进行了彻底的分析,以确定通过司法系统的个人再犯的风险。最终,他们发现这些算法明显更有可能将黑人被告识别为比白人被告具有更高的再犯风险,这导致这些人的刑期明显更高。问题是这与实际的再犯率没有关联。白人被告与其实际比率相比长期得分较低,而黑人被告与其实际比率相比长期得分较高。事实上,种族间的再犯率比分数显示的要接*得多。虽然正在讨论的算法的具体设计是专有的,因此我们无法最终确定其失败的确切原因,但它揭示了当我们“出错”时可能发生的可怕后果。人们失去了多年的生命,因为没有考虑到背景偏见可能会不正确地扭曲输出。

如果有空间对影响人工智能输出的背景偏见产生如此重大的、潜在的改变生活的后果,它回避了问题:我们到底应该使用人工智能吗?与人类大脑相比,它是否仍然过于初级,无法为我们提供任何有意义的东西?简而言之,不,我们不应该放弃人工智能带来的潜在好处。然而,我们必须时刻注意技术如何将上下文应用于数据,上下文如何增加偏差,以及这对未来的任何输出意味着什么。如果我们认识到人工智能有什么好处:也就是说,它只是我们可以用来补充决策过程的许多工具之一,那么我们就可以开始利用我们个人和商业生活中的潜在重大利益。

如何通过自动化变得更棒并节省时间

原文:https://towardsdatascience.com/laziness-saved-my-friends-sanity-6683dcec2383?source=collection_archive---------56-----------------------

我写 Python 字数统计脚本时的一个实际用例

埃维·卡莱米Unsplash 上拍摄的照片

和很多开发者一样,我很懒。我珍惜自己的时间,也珍惜亲人的时间。

当我看到一个朋友一遍又一遍地重复一项乏味的任务时,我感到沮丧,就好像这是我的负担一样。因为我讨厌重复的任务,所以我想找到一种自动化它们的方法。

拥抱懒惰

自动化包括给机器一套指令,让它替你做所有的重活。都是关于效率。我跟你说实话:我是一名专门从事移动开发的程序员。我对脚本语言没有特别的了解。

不久前,我看到一篇文章,这篇文章启发了我如何以及为什么我们可以让生活变得更轻松。

[## 用 Python 自动化枯燥的东西

“编程最好的部分是看到机器做一些有用的事情的胜利。用…自动化枯燥的工作

automatetheboringstuff.com](https://automatetheboringstuff.com/)

这值得痛苦吗?

记住,大多数开发人员都很懒。写剧本对我来说听起来很痛苦。对你来说也一样。问自己这些问题:你介意重复同样的任务吗?你觉得手工做有价值吗?如果你在这些问题上犹豫不决,考虑投资一些时间在自动化上。

我想和你分享一个故事,这个故事让我为我的朋友写了一个小剧本。我决定选择 Python,因为这是一个发现这种语言的绝佳机会。

字数问题

有一天,女朋友带着任务来找我。她是一名专业内容作家。有时,她碰巧做翻译工作。有一次,一家公司给她发了一个剧本来翻译。以下是一个示例:

Joey and Phoebe meets in a bar
Joey(smiling): [<How're you doing?>]
Phoebe welcomes him with open arms
Phoebe(cheerful): [<Oh! I'm feeling great!>]

注意到文本中的分隔符了吗?该公司突出显示了要翻译的区域。其余的作为额外的信息——对从上下文中选择正确的语气至关重要。工作完成后,她需要将发票寄给公司。因为我的朋友是按单词收费的,她需要计算她翻译了多少单词。

任何文字处理软件都可以帮你统计字数。然而,她不能对整篇文章收费——并不是说她不介意账单。她必须首先排除括号外的内容。可惜公司没有给她提供这样的工具。

当她开始用手数单词时——我们谈论的是 50000 个单词!——我必须在她失去理智之前进行干预。

分析需求

任务很明确:在一个定义的分隔符内计算所有单词。我开始把它分解成更小的步骤:

  1. 对于所有输入行,提取[<>]之间的文本。
  2. 将所有带格式的行合并成一个文本块。
  3. 把这个模块分成一个单词列表
  4. 计算列表的长度

考虑到这一点,我准备开始下一阶段。

用脚本自动化

我最终写了这个剧本:

word_counter.py

仅此而已!我承认我花了两个小时才把它放下。但这两个小时花得很值。我很自豪地看到几行代码可以为我的朋友节省这么多时间!她的理智也是!

她只需要将文本插入到inputString变量中,然后运行脚本来获得字数。

$ python word_counter.py
7 // there are seven words in the example above

对于没有入门的 Python 开发人员,我们来分解一下这段代码。

提取分隔符中的文本

第一步要求我使用正则表达式(Regex)。它们允许我提取符合特定模式的所有行。我以这个结尾:

import relist = re.findall(r'\[\<(.+?)\>\]', inputString)
// ['How're you doing?', 'Oh! I'm feeling great!']

首先,我们必须导入 Regex 库。然后,我们通过从inputString中找到所有以[<开头、以>]结尾的句子来创建一个list。最后,括号声明我们想要排除分隔符。作为注释,我展示了从本文开头的示例中获得的结果。

从提取的文本创建一个句子

我们要把list展平成一句话。我们需要将前面的列表加入到一个空字符串中。

subString = " ".join(list).replace('\xc2\xa0', ' ')
// "How're you doing?, Oh! I'm feeling great!"

注意到replace方法了吗?由于 UTF-8 编码,当复制粘贴你的文本时,一些不间断空格会出现。我们可以用一个规则的空格代替它们来计算两个单词而不是一个。当我的朋友要开发票时,省略单词不会让她高兴!

将句子拆分成单词

对于这一步,一个简单的split就可以了。

words = subString.split()
// ['How're', 'you', 'doing?', 'Oh!', 'I'm', 'feeling', 'great!']

在继续之前,我必须检查结果是否正确。例如,你可能会惊讶于“怎么样”也算一个单词。我也很好奇。然而,任何在线工具都会证实这一点。

计数和打印

最后,计算并打印我们的words列表的大小。

count = len(subStr.split())
print count
// 7

如何理解它?

我知道这个剧本一点也不特别。有改进的余地。例如,我可以提取分隔符或输入文本等参数。

但它完成了任务。这就是我所关心的!

痛苦吗?不完全是。在不了解 Python 的情况下,我设法在几个小时内编写了一个小脚本。我甚至觉得写它很有趣!

值得吗?问我女朋友。到目前为止,她似乎很感谢有这个工具。

高血压药物综述的 LDA 主题建模

原文:https://towardsdatascience.com/lda-topic-modeling-for-high-blood-pressure-drugs-reviews-ff40af2ee319?source=collection_archive---------34-----------------------

图片由作者“联合国新冠肺炎对策”提供

主题建模是一种利用无监督机器学*算法的文本分析技术。主题建模的最终目标是在大量文本文档中发现主题,并发现隐藏的主题。语料库中的每个文档将由至少一个主题组成,如果不是多个主题的话。主题建模对于文档聚类和非结构化文本的信息检索非常有用。

潜在狄利克雷分配 (LDA)是一种用于主题建模的算法,用于将文档中的文本聚类成主题列表。

这里我们将把 LDA 应用于一组高血压药物综述文档,并把它们分成主题。

动机

目标是通过对这些分组主题的分析,从这些评论中获得深刻见解:

  • 从综述中探索所有高血压药物共有的潜在主题。
  • 预测给定评论文本的评分。

我们开始吧!

数据集

该分析中使用的数据集是从 WebMD 药物评论数据集(可从 Kaggle 下载)中提取的约 18,000 份患者对用于治疗高血压的药物的评论列表。数据提供者通过抓取 WebMD 站点获取数据集。原始数据集中约有 36 万行独特的评论,更新到 2020 年 3 月。

import pandas as pd# Read data into papers
drug_df = pd.read_csv('C:/Users/Johnny Phua/Metis/Project4/Drug Review/webmd.csv')hbp_drug_df = drug_df[drug_df["Condition"] == 'High Blood Pressure']

看一眼数据。

print(len(hbp_drug_df))
hbp_drug_df.head()

1:药品评论数据集的前 5 行。

数据预处理

执行了以下步骤:

  • 小写单词并删除非字母字符。
  • <三字去掉
  • 分词:将文本拆分成单词。
  • 所有停用字都被移除。
  • 单词被词条化:第三人称的单词被改为第一人称,过去时态和将来时态的动词被改为现在时态。
  • 单词被词干化:单词被还原成它们的词根形式。

以下功能用于小写单词、删除非字母字符以及删除少于 3 个字符的单词:

import redef clean_non_alpha(text):
    return re.sub('[^a-zA-Z]',' ', str(text))def remove_short_word(text):
    return  re.sub(r'\b\w{1,3}\b', '', str(text))def convert_to_lower(text):
    return re.sub(r'([A-Z])', lambda m: m.group(1).lower(),  
    str(text))

标记化

标记化就是将一个字符串拆分成一系列标记的过程。标记是整体的一部分,所以在我们的上下文中,单词是句子中的标记。

from nltk.tokenize import RegexpTokenizerdef get_tokenize(text):
    """
    function to tokenize text to list of words.
    """
    tokenizer = RegexpTokenizer(r'\w+')
    return tokenizer.tokenize(str(text))

2:标记化后列表中的单词

删除停用词、词汇化、词干

下面的函数做的工作是去除停止字,词汇化和词干化。

from nltk.stem import WordNetLemmatizer
lemma = WordNetLemmatizer()
from nltk.stem import PorterStemmer
stemmer = PorterStemmer()
from nltk.corpus import stopwords
stop_words = stopwords.words('english')def remove_stopwords(token):
    """
    function to remove stopwords
    """
    return [item for item in token if item not in stop_words]def clean_lemmatization(token):
    #from nltk.stem import WordNetLemmatizer
    #lemma = WordNetLemmatizer()
    return [lemma.lemmatize(word=w,pos='v') for w in token]def clean_stem(token):
    #from nltk.stem import PorterStemmer
    #stemmer = PorterStemmer()
    return [stemmer.stem(i) for i in token]

图 3:去除停用词、词汇化和词干后的标记。

数据集现在是干净的,并且格式正确。它现在可以用于 LDA 建模。

然而,在我们开始训练模型之前,我们将如何决定使主题可解释性的最佳主题数量。

1)主题建模中主题数(k)的确定方法是什么?

确定主题模型的最佳主题数(k)的方法之一是通过比较 C_V 一致性分数。最佳的话题数量会产生最高的 C_V 连贯分数。Coherence 查看每个生成的主题中最频繁出现的单词,对它们之间的语义相似性进行评级(使用 UCI 或 Umass 进行成对计算),然后找到模型中所有主题的平均一致性分数。(http://qp ple . com/topic-coherence-to-evaluate-topic-models/)

我们如何评估和提高模型结果的可解释性?

一旦我们选择了主题的最佳数量,接下来要问的问题是如何最好地评估和提高这些主题的可解释性。一种方法是可视化我们的主题模型的结果,以确保它们对我们的场景有意义。我们可以使用 pyLDAvis 工具来可视化您的 LDA 模型对主题及其热门词的拟合。

一袋单词

从“reviews_docs”创建一个字典,包含一个单词在训练集中出现的次数。

from gensim import corpora
dictionary = corpora.Dictionary(reviews) 

使用 Gensim.filter_extremes 内置函数过滤出出现在,

  • 少于 15 份文件(绝对数量)或
  • 超过 0.5 个文档(总语料库大小的一部分,而不是绝对数量)。
  • 在上述两个步骤之后,只保留那些出现次数为 11 及以上的标记,换句话说,只保留前 2130 个最频繁的标记。

通过检查整个单词字典的频率分布(按频率降序排列),我们可以知道前 2130 个单词/记号对于每个记号具有 11 个及以上的出现次数。

# first get a list of all words
all_words = [word for item in      list(hbp_drug_df['reviews_text_processed']) for word in item]# use nltk FreqDist to get a frequency distribution of all words
fdist = FreqDist(all_words) # choose k and visually inspect the bottom 10 words of the top k
k = 2130
top_k_words = fdist.most_common(k)
top_k_words[-10:]

图 5:语料库的词频分布。

将上述过滤器应用于 gensim 字典:

dictionary.filter_extremes(no_below=15, no_above=0.5, keep_n=2130)

然后,我们为每个文档创建一个文档单词矩阵,报告有多少单词以及这些单词出现了多少次。将此保存到‘doc _ term _ matrix’。

from gensim import corpora
doc_term_matrix = [dictionary.doc2bow(rev) for rev in reviews]

使用单词包运行 LDA

准备好字典和 doc_term_matrix 后,现在我们可以使用gensim . models . LDA model . LDA model来训练 LDA 模型。

然而,此时,我们需要问的下一个问题是,我们应该使用多少个主题(k)来训练我们的模型?我们可以利用 c_v coherence score 和 pyLDAvis 可视化工具来决定我们的模型的最佳主题数量。

计算 c_v 一致性分数:

#Calculate the c_v Coherence Score for different k from 1 to 10.
from tqdm import tqdm
from gensim.models import LdaModel

coherenceList_cv = []
num_topics_list = np.arange(1,10)for num_topics in tqdm(num_topics_list):

    lda_model =  LdaModel(corpus=doc_term_matrix,id2word=dictionary,num_topics=num_topics,random_state=100, update_every=1, chunksize=1000, passes=50, alpha='auto', per_word_topics=True)

    cm_cv = CoherenceModel(model=lda_model, corpus=doc_term_matrix, texts=reviews, dictionary=dictionary, coherence='c_v')

    coherenceList_cv.append(cm_cv.get_coherence())

绘制 pyLDAvis:

# Plotting tools
import pyLDAvis
import pyLDAvis.gensim# Visualize the topics
pyLDAvis.enable_notebook()
vis = pyLDAvis.gensim.prepare(lda_model, doc_term_matrix, dictionary)
vis

什么是话题连贯?

连贯性测量在每个生成的主题中最频繁出现的单词,评定它们之间的语义相似性;利用 UCI 或 Umass 来执行成对计算;然后为该模型计算所有主题的平均一致性分数

从下面我们的模型中不同 k 个主题的 c_v 一致性分数分布可以看出,主题数 k=3 和 k=5 给出了同样高的分数。

图 6:k 个主题的 c_v 连贯分数

然而,如果我们绘制 pyLDAvis 图,很明显,k=3 将比 k=5 给出更有希望的结果。可以注意到,对于 k=5,主题 12 和 3 彼此高度重叠。而对于 k=3,主题在不同的象限中被很好地分开。

图 7:k 从 1 到 10 的 pyLDAvis 图

t-SNE 图也清楚地表明,k=3 比 k=5 好得多,因为可以注意到,当 k=5 时,有 3 个主题相互重叠。

图 8:k = 3 和 k=5 时的 t-SNE 图

现在,我们可以使用 k=3 来生成 LDA 模型。让α和β超参数自动生成。

import gensim# Creating the object for LDA model using gensim library
LDA = gensim.models.ldamodel.LdaModel# Build LDA model
lda_model = LDA(corpus=doc_term_matrix, id2word=dictionary, num_topics=3, random_state=100, chunksize=1000, passes=50, update_every=1, alpha='auto', eta='auto', per_word_topics=True)

您可以使用 lda_model.show_topic(): 查看每个主题的前 10 个关键词以及每个关键词的权重(重要性)

0 [('天',0.043550313),('感觉',0.03116778),('时间',0.030068435),('得到',0.0252915),('喜欢',0.020811914),('迪子',0.017624224),('使',0.017559748),('胎',0.01706512

1 [('压',0.046297483),('效',0.045646794),('血',0.044705234),('方',0.041772064),('功',0.027191896),('年',0.026943726),('医',0.024851086),('下',0.0203996)。

2 [('咳嗽',0.038522985),('疼痛',0.021691399),('药物',0.02127608),(' caus ',0.017660549),(' sever ',0.01583576),('走',0.01558094),('医生',0.01529741),('停',0.015242598

词云

我们来看看模型的词云分布。

图 9:单词云

通过参考高血压药物的一些常见副作用的列表,可以注意到主题 0 和主题 2 显示了下面提到的列表中的一些副作用。

高血压药物的一些常见副作用包括:

咳嗽

腹泻或便秘

头晕或头晕

剧烈而突然的脚部疼痛

感到紧张

感觉疲倦、虚弱、困倦或缺乏能量

头痛

恶心或呕吐

皮疹

无需尝试就能减肥或增重

  • 腿肿

获得洞察力

通过从数据集中随机读取耐心的评论,可以注意到,主题 0 和主题 2 的评论显示耐心对于这两个主题经历了不同类型的副作用。而专题 2 的综述表明,这类患者的耐心比专题 0 经历了更严重的副作用,因为专题 2 的患者采取了诸如停止服用该药物并改用另一种药物的行动。然而,对于以主题 1 为主导主题的耐心的评论显示,该药物对他们有效,并且仅经历轻微的副作用症状。

现在我们可以给这个主题贴上如下标签:

主题 0:副作用类型 I —“头晕”、“疲倦”、“头痛”

话题 1:药物有效

主题 2:第二类副作用——“咳嗽”、“肿胀”、“疼痛”

图 10:各主题满意率统计

从上述三幅图中可以看出,在主题 1 中聚集了评论的患者对等级为 3 及以上的药物最满意。而主题 0 和主题 2 的患者对 2 级及以下的评分大多不满意。

图 11:每个主题的文档数。

从上面的图表可以看出,大约 55%服用高血压药物的患者会出现某种副作用症状。

基于 Tweets 的 LDA 主题建模

原文:https://towardsdatascience.com/lda-topic-modeling-with-tweets-deff37c0e131?source=collection_archive---------13-----------------------

理解非结构化文本

凯文在 Unsplash悲伤的照片

问题和目的

有了一些为文本分类构建 NLP 模型的经验,我一直在进一步思考如何处理完全非结构化的文本数据。每天大约有 5 亿条推文在 Twitter 上发布,Twitter 是文本数据的巨大来源。人们在推特上谈论什么?这些推文可以通过编程组织成主题吗?人们对你的产品或公司有什么看法?可以发现对进一步分析/建模有用的模式吗?嗯——我想我们会找到答案的。

对于这个项目,我决定使用 GetOldTweets3 python 库从 twitters API 中提取的 tweets。用于这个项目的任何笔记本都可以在我的 GitHub 上找到。

GetOldTweets3

import GetOldTweets3 as got
  • 使用“got”别名导入 GetOldTweets3 库,以便于使用
  • 有很多参数可以玩,即用户名,位置,日期。我选择使用“通过查询搜索获取 tweets ”,这样我就可以指定一个特定的主题。
tweetCriteria =    got.manager.TweetCriteria().setQuerySearch('anxiety')\
                           .setSince("2018-06-30")\
                           .setUntil("2020-06-30")\
                           .setNear('New York')\
                           .setMaxTweets(10000)tweet_object = got.manager.TweetManager.getTweets(tweetCriteria)

我选择查看纽约地区两年时间内包含“焦虑”一词的推文,希望了解人们可能在推文中表达他们的焦虑。是什么引起的?人有自残的风险吗?我们能找到任何有价值的特定主题来潜在地执行进一步的建模吗?

在进行 API 调用后,我用下面的代码片段构建了一个数据帧:

这里感兴趣的主要值只是文本。我不会对用户名、日期等感兴趣。此刻。

预处理文本

在我真正对文本数据做任何有用的事情之前,它必须被预处理成机器可读的数字输入。我已经在之前的博客中介绍了下面的步骤,但是我将在这里列出一般的步骤。

  1. 删除 URL
  2. 标记每条推文
  3. 删除停用词、标点符号和小写所有单词
  4. 删除任何剩余的特殊字符
  5. 将文本词条化

一旦文本被处理,它应该像这样:

[‘feel’, ‘like’, ‘cheer’, ‘slowly’, ‘morphed’, ‘scream’]

我可以检查我的推特语料库的全部词汇:

共 99716 字,词汇量为 13633
最大推文长度为 32

电子设计自动化(Electronic Design Automation)

然后,我可以使用 seaborn 和 matplotlib 的 countplot 检查每条 tweet 的长度:

语料库中推文的长度

考虑到这种分布是右偏的,每条包含少于 5 个单词(令牌)的 tweets(文档)高度集中,我将删除少于 4 个单词的额外文档,假设这些文档不会提供任何有意义的上下文。

让我们来看看排名前 30 的单词。有了 nltk.probability 的 FreqDist 类和 WordCloud 库,实际上相当容易。

首先,我从每条 tweet 创建了一个包含所有令牌的平面列表。然后将所有标记的列表传递给 FreqDist(),它将计算每个标记的出现次数,并为每个标记创建一个包含(单词,频率)的元组。

输出:

[('time', 854),  ('people', 774),  ('depression', 608),  ('much', 548),  ('know', 501),  ('stress', 469),  ('really', 449),  ('thing', 438),  ('need', 437),  ('attack', 428),  ('make', 407),  ('social', 396),  ('today', 389),  ('work', 354), ...]

一旦我有了词频,我就可以构建一个字典来创建单词云。

然后,该字典可以与。WordCloud 的 generate _ from _ frequencies 方法。

单词云:

人、时间、压力、抑郁是出现频率最高的 10 个词。考虑到被查询的推文都包含“焦虑”一词,这并不奇怪。

创造一个单词包

我将使用 Gensim 的字典构造器给 tweet 语料库中的每个单词一个唯一的整数标识符。

构造的字典应该包含 13633 个标记(语料库 vocab 的大小)。

{'applies': 0,  'exist': 1,  'go': 2,  'japanese': 3,  'learning': 4,  'list': 5,  'mean': 6,  'okay': 7,  'open': 8,  'people': 9, ....}

袋字 什么是袋字?简单的解释是,它是一个单词 token(或 term) 在一个文档中出现的次数的计数(在这个例子中是一条 tweet )。下面的代码利用了 gensim 的 doc2bow 方法,将上面的字典作为输入。

输出将包含每个 tweet 的向量,形式为(单词 id,单词在文档中出现的频率)。

[[(0, 1),
  (1, 1),
  (2, 1),
  (3, 1),
  (4, 1),
  (5, 1),
  (6, 1),
  (7, 1),
  (8, 1),
  (9, 1),
  (10, 1),
  (11, 1),
  (12, 1),
  (13, 1),
  (14, 1)],
      ...]

考虑到 tweet 通常非常短,平均大约 33 个字符,我们可以看到这条 tweet 包含 14 个独特的单词,每个单词只出现一次。有了这袋单词,建模就可以开始了!

拟合 LDA 模型

那么,LDA 到底是什么?

LDA,或潜在目录分配,是围绕最流行的主题建模算法之一。 LDA 是一个生成统计模型,它允许观察值由未观察到的组来解释,从而解释为什么部分数据是相似的。LDA 将文档集作为输入,假设每个文档是少量主题的混合,并且每个单词可归属于文档主题之一。如果想深入了解,可以去看看戴夫·布雷的讲座,以及这个博客

根西姆

在 Gensim 中拟合 LDA 模型非常简单。作为起点,我已经建立了一个包含 5 个主题和 10 个通道的模型。这在这个阶段有些武断。我想看看是否会出现一些关于人们为什么在推特上谈论焦虑的一般性话题,并发现一个可观察到的模式。

以下是输出结果:

[(0,
  '0.019*"work" + 0.015*"take" + 0.014*"stress" + 0.014*"need" + 0.014*"time" + 0.013*"much" + 0.011*"today" + 0.010*"sleep" + 0.009*"next" + 0.009*"watch"'),
 (1,
  '0.034*"know" + 0.027*"people" + 0.025*"depression" + 0.017*"nice" + 0.016*"social" + 0.016*"family" + 0.015*"please" + 0.015*"really" + 0.015*"fucking" + 0.015*"think"'),
 (2,
  '0.022*"attack" + 0.019*"much" + 0.018*"give" + 0.017*"really" + 0.014*"make" + 0.014*"know" + 0.014*"never" + 0.013*"would" + 0.013*"something" + 0.013*"people"'),
 (3,
  '0.018*"news" + 0.014*"respond" + 0.013*"good" + 0.013*"disorder" + 0.012*"fear" + 0.012*"hard" + 0.011*"trying" + 0.011*"still" + 0.010*"love" + 0.010*"literally"'),
 (4,
  '0.030*"people" + 0.020*"real" + 0.019*"body" + 0.019*"social" + 0.018*"find" + 0.018*"good" + 0.018*"depression" + 0.018*"want" + 0.016*"next" + 0.016*"actually"')]

估价

在我寻求评估的过程中,我发现了一些有用的资源,这才刚刚开始。特别是 Matti Lyra 在 PyData Berlin 2017 关于评估主题模型的演讲。我不打算在这篇博客中深入讨论评估或优化,因为这会变得太长。但是这里有一些可视化主题模型的基本策略。

目测

输出代表 5 个主题,包括热门关键词和对主题的相关权重贡献。

虽然我可以从每个主题中推断出一定程度的情感,但主题分配并没有明确的划分或可识别的模式。和常用词也有不少交叉。

  • 主题 0 似乎是关于在家工作的挣扎。虽然如果是这样的话,我很惊讶“covid”、“新冠肺炎”、“冠状病毒”等。不包括在这里。
  • 话题 1 可能是关于社会孤立?
  • 话题二?
  • 主题 3 似乎是关于媒体,以及对媒体的反应
  • 主题 4 与主题 1 没有太大的不同

皮尔戴维斯

PyLDAvis 库是可视化主题模型中的主题的好方法。我不打算详细解释它,但这里有图书馆的文件以及原创研究论文,该论文于 2014 年 6 月 27 日在巴尔的摩的 2014 年关于交互式语言学*、可视化和界面的 ACL 研讨会上发表。

用 PyLDAvis 可视化主题模型非常简单。传入模型、单词包和 id2word 映射,就完成了。

输出:

在左边,主题被绘制在表示每个主题之间的距离的二维平面上。而右边的水平条形图代表与每个主题最相关的单词。该图表是交互式的,允许您选择特定的主题,并查看每个主题的相关单词,希望从每个主题中推断出含义。

结论和未来步骤

虽然我目前对这个 tweet 主题模型的迭代没有明确地以一种我认为对外部任务有价值的方式分离或聚集 tweet,但我将继续研究一些优化策略。

  • 使用 n-grams 连接通常一起出现的单词,如“精神”和“健康”。一个双字母组合将保留“心理健康”,这样模型就可以把它作为一个标记来读取。
  • 对不提供任何有意义上下文的常见单词进行额外过滤。
  • 计算一致性分数,并找到 k 个主题、通过次数等的最佳参数。
  • 收集更大的推特语料库,并尝试更多样化的数据集。

祝贺你坚持到了最后。如果你想联系@https://www.linkedin.com/in/rob-zifchak-82a551197/,请随时在 LinkedIn 上联系我

用愿景而不是指标来领导:OKR 如何成为一个危险的工具

原文:https://towardsdatascience.com/lead-with-vision-not-metrics-how-okrs-can-be-a-dangerous-tool-29e0ee2a2012?source=collection_archive---------45-----------------------

照片由 iStock Photo 编舞提供

如果使用得当,数据是任何组织成功的关键。没有帮助我们理解性能和设定基线的度量标准,就不可能改进。大多数组织一开始都有良好的意图——使用数据来提高效率、推动问责制和改进关键指标——但很快就陷入了官僚主义、“给自己的作业打分”的偏差状态。这导致利用数据来转移人们对美国真实状况的注意力,或者更糟糕的是,直接撒谎并掩盖真相。

20 世纪 90 年代,NYPD 实施了 CompStat,这是一个全市范围的数据库系统,使用比较统计数据来更有效地跟踪和减少犯罪。该法案要求警察对其管辖区域内的犯罪负责,并因将犯罪率降低了 75%而受到称赞。然而,在过去的几十年里,这实际上导致了官员们不太关心履行他们的职责,而更关心在被跟踪的指标上显示改进。在极端情况下,有报道称警察降低了举报犯罪的严重程度只是为了提高指标。

按指标管理:用良好的意图铺路

科技行业多年来一直使用 OKR(目标和关键结果)来跟踪业绩,但我们都看到它们随着时间的推移变得越来越没有意义。经过几个季度甚至几年的时间,人们不可避免地将 OKR 氏症作为获得晋升的一种方法,而不是一种跟踪什么是对的,以及——可能更重要的是——什么是错的方法。这意味着,被跟踪的关键结果最终成为相同的顶级指标,只是稍作调整,以显示对组织其余部分的微小改进:比如“我们的数据将扩展 10%”或“我们将增加 5 个新客户”

这种类型的问题在一个行业中并不孤立,但当我们为成功设定错误的标准时,这种问题就会经常发生。例如,学校通常是根据学生的毕业率来评判的。作为回应,老师们感到有压力让可能没有取得学业成功的学生通过考试。这种做法非但没有让学生为未来做好准备,反而危及学生接受的教育质量。

设定只跟踪顶级指标的目标是糟糕领导的表现。我可以在没有外界知识的情况下进入任何一家公司,并通过说“我们的组织需要多销售 X%的产品”或“增加 Y%的利润”来负责一个好的船长不仅会规定船需要到达哪里,还会提供一个愿景,让船员们能够沿途做出自己的航行决定。

哪里出问题了?

CompStat,沿着我们在教育和技术领域看到的路线,开始得很好。作为一个集中跟踪数据库的所有逮捕,传票,以及整个地区的其他犯罪活动,它有巨大的能力,揭示主要趋势。如果使用得当,它可以帮助领导者更有效地打击犯罪,例如,通过了解犯罪是如何联系在一起的,或者在什么时间哪个区域需要更多的警察关注。

然而,任何像这样的系统被滥用的两个因素是:

  1. 给自己的作业评分
  2. 与晋升和降级的相关性

不幸的是,这两个概念是相互矛盾的。我们都希望在报告自己的成功时能够做到客观,但当业绩与个人职业发展或成就相关时,即使是道德狂热分子也会有意或无意地将衡量标准偏向那些对他们更有利的方面。

如何对抗度量的阴暗面

无论你怎么分析,这都是一个极其困难的问题。很难激励你的组织去创建和恰当地度量那些不可游戏的客观指标。也很难确保员工对愿景有足够清晰和简明的理解,以便他们在任何时候都能为组织做出正确的决定。

有几个因素可能有助于组织实现这些目标。

1——作为领导者,为公司设定正确的愿景。

一个组织的愿景不应该由顶级的业务成果组成。相反,愿景应该是员工在决策过程中使用的工具,以理解和直观地了解他们应该做出的决策类型。亚马逊取得了令人难以置信的成功,部分原因是杰夫·贝索斯让非常清楚顶级指标并不是亚马逊努力的方向。他正在建设“世界上最大的商店”,员工们知道他们可以牺牲短期收入来实现这个目标。

2 —创建与个人绩效无关的组织绩效客观指标。

有一个清晰定义的愿景会让一切变得更容易,并有助于确保员工跟踪真正重要的指标。出于客观性,指标不应与个人晋升相关联,以确保对公司的成功有一个清晰的看法,不受政治的影响。

3——推动个人绩效评估中的问责制。

给自己的作业评分是决定成绩的良好基础,但任何好的制度都有制衡机制。个人需要责任感,这可以通过管理层、同事和最终消费者来实现。

它在实践中是如何工作的?

让我们试着把这个过程应用到 NYPD。

1——NYPD 运用杰夫·贝索斯原则的新愿景。

我们不应该设定像“连续 20 年降低犯罪率”这样的最高目标,而是应该思考警察为什么存在,并以此来定义我们的愿景。

寻找愿景应该很简单:“在执法的同时确保公民的安全、健康和财产。”

最终,这意味着警察是公务员,其任务是帮助公民更加安全。不应优先考虑不符合这一愿景的指标。

2 —定义客观的绩效指标。

虽然客观性通常很难实现,但我们的工作变得容易多了,因为我们都设定了一个愿景,并将衡量与推广脱钩。因此,在报告犯罪时,我们不应该担心坏数据。犯罪将是我们的第一个衡量标准,因为它达到了理解我们公民的安全、健康和财产的最高水平。

犯罪显然是衡量愿景的一个标准,因为犯罪是衡量违反法律的频率的外在标准,但它并不能严格衡量公民的安全和健康。我们可以从外部数据中添加这方面的直接测量,并将其与犯罪联系起来,以确保它们得到准确报告。我们也可以通过这种方法来衡量警察自己是否造成了伤害。

3 —推动对个人绩效的问责。

个人绩效报告是一个良好的开端,但让官员承担责任也意味着从同事、经理和外部信息中收集信息。

为了确保警察对公民的安全和健康起到促进作用,我们必须衡量警察本身的行为。警队的不良行为记录需要像保存给市民一样保存给警察。

最后,我们应该增加从我们的公民中提取警方表现数据的方法,如民意测验或匿名举报热线。从多个来源和角度收集反馈对于推动绩效评估的问责制至关重要。

底线

自从引入 CompStat 以来,已经过去了将* 30 年。虽然指标可能在改善,但公民和警察之间的关系比以往任何时候都紧张。当然,在讨论美国的治安状况时,有一个更大的社会背景需要考虑。然而,由于专注于错误的指标,他们不再致力于确保公民安全和健康的目标。

我们能从中学到什么?虽然大多数人本质上是好的,并希望在他们的组织中做到最好,但很少有领导层能够将他们公司的愿景提炼为一套指导原则。员工非常擅长对他们获得的成功指标进行局部优化,并且倾向于推动短期指标而不是长期愿景,除非组织明确规定了优先事项。

在许多组织中,缺乏领导远见会导致对员工的误导。OKR 的是一个危险的目标设定框架,没有一个明确定义的愿景和客观跟踪和分级表现的结构。不用说,我们都应该努力确保愿景和目标跟踪在我们的组织中被视为一等公民,否则我们将面临与警察机构相同的挑战。

领导软件开发团队

原文:https://towardsdatascience.com/leading-a-software-development-team-be13b3f6b0f?source=collection_archive---------26-----------------------

5+5 关于如何成为伟大的技术领导者的独特视角

软件开发是团队的努力,但是一群没有技术带头人的工程师就像一群没有牧羊人的羊。技术领导的角色不仅仅是设计和编写代码,还是软件质量的守护者;它还包括指导和代表技术团队,并需要采用一套新的非技术技能。在我的职业生涯中,我发现下面列出的原则为成为一名有效的领导者提供了一个坚实的基础——一个不断取得巨大成就的领导者!

因此在本文中,我们将深入探讨这个问题:

什么是伟大的技术领先?

向技术领导过渡

新任命的技术主管(TL)可能会很快陷入许多陷阱,这些陷阱通常是由他们作为开发人员时养成的*惯造成的。为了克服这些缺陷,他们必须找到在技术和领导责任之间取得平衡的方法。

让我们来探究其中的一些错误:

➊:反思生产力

作为一名开发人员,你可能至少花了 80%的时间写代码。每天结束时,你可以回顾并看到进展:无论是代码、设计规范、同行评审还是修复 bug,你都可以说:这是我今天做的事情

但是,作为一个领导角色,量化你的日常成就变得非常困难,因为你是通过你的团队的生产力和效率来衡量的。准确地说,困难来自内部;虽然别人可以清楚地看到你的成就,但你内心的声音一直在想:我今天到底做了什么?在无数的会议、计划会议、整理积压工作、状态报告、技术讨论和各种各样的干扰之后,你带着一种交付不足的感觉结束了一天。

这当然不是真的。作为一名 TL,你应该使用关注团队成果的方法,而不是你个人的产出。

➋:在编码方面找到了正确的平衡

当我第一次担任 TL 角色时,我犯的最明显的错误是继续像以前一样编写代码。在不停地编码几年后,我的自然倾向是以同样的方式操作,没有意识到尽管我作为一个个体贡献者最大化了我的生产力,但我这样做是以我团队的生产力为代价的(抱歉伙计们)。当你认为自己的技术能力是成为一名技术人员的首要原因时,停止把自己视为一名制作人是非常棘手的。

新 TLs 经常犯的另一个错误是不再做足够的编码。当你不动手时,你将逐渐变得不太能够设计正确的架构,评估你的团队建议的解决方案,或者帮助调试在生产中不断出现的讨厌的多线程错误。冒援引“象牙塔领导”反模式的风险,即领导技术决策而不理解其真正含义,会给团队带来可怕的后果,他们最终会对你这个领导者失去信心。

根据我的经验,这个问题没有正确的答案。最佳状态是将 30%-40%的时间用于编码,剩下的时间留给剩下的工作。

➌:关注大局

新 TLs 发现的角色挑战的另一个方面是如何调整他们的“关注水平”。作为一名开发人员,你曾经一次专注于一项任务。显然,了解你的特性/模块/服务如何与整个系统相适应是很重要的,你可能会迷失在实现的细节中。但是作为一个 TL,这种情况会改变:你需要对软件生态系统有一个鸟瞰图,并且对代码设计有一个更广泛的理解。

想象一下相机上的变焦镜头:它允许操作者向后拉并看到大画面,但也允许他们放大细节。类似地,一个有效的目标语可以不断地从大局转移到细节,转换视角和语境。

➍:忍住了微观管理的冲动

新成立的团队有着积极管理团队的冲动,因为他们相信领导力包括做出所有决定的谬论,无论这些决定是大是小。他们成为看门人:他们在发布之前审查所有的代码变更,他们是唯一可以访问关键服务的人,他们处理所有的任务管理和评估,他们代表团队与业务部门进行对话,等等。这些情况中的每一种都会导致团队感到无能为力,并对他们的士气、动机和表现产生不良影响。

一个有能力的领导者和一个微观管理者之间的界限可能很窄,虽然这条界限对你来说似乎很模糊,但你的团队很可能很容易就能识别出来。一定要放手!相信你的团队,尽量不要支配一切,在早上的讨论中获得你的每日更新,不要做一个令人窒息的老板!

➎:代表

在希腊神话中,阿特拉斯是掌管大地和天空的神。在更小的范围内,作为一名 TL,你可以尝试扮演这个角色,独自完成所有的关键工作。显然,有些任务需要你的经验和知识,但你不想成为解决问题的瓶颈,所以你需要找到一种方法来委派任务,并且仍然参与其中。

只有当领导者认为某人有足够的技能和动力来完成一项任务时,授权才是可能的,这不仅鼓励解决问题的创造力,也是赋予团队权力并看到他们成长的机会。一个从来没有被要求拥有他们的工作,转换环境,或者解决他们舒适区之外的事情的团队将永远不会前进。

试图为阿特拉斯这个角色服务,从长远来看,是一种不值得承受的负荷。和团队分享会好很多。

作为技术领导者的卓越表现

虽然扎实的技术知识对 TLs 至关重要,但一个有效的领导者最重要的技能是社交技能。但坏消息是:

非技术能力没有明显的“你好世界”!

这些技能是在你的领导之旅中逐渐形成的。你的最终目标不应该是擅长你的新角色,而是要出彩!成就卓越就是对出色完成的工作有一种成就感——这是本文的主旨!

正如亚里士多德所说:“我们就是我们反复做的事情。因此,优秀不是一种行为,而是一种*惯。

让我们看看成为一名优秀的 TL 需要什么!

➊:是一个仆人式的领导者

服务型领导颠覆了传统的等级领导方式。它通过关注他人的支持和成长来采取利他主义的领导方式。

保持服务第一的心态意味着你专注于授权和提升那些为你工作的人。你是在服务而不是命令,表现谦逊而不是展示权威,倾听理解而不是决定你的反应,并且总是希望以释放潜力和提高绩效的方式促进团队成员的发展。

当你认为你比你的团队成员更优秀的时候,你是不可能去服务的——对你来说,从来没有一份工作是太小的!仆人式领导不是让人你下面;它是关于携带人你,去建立比你自己更好的东西!这本身就是一种很棒的感觉!

➋:放弃胜利和自己的失败

每当有成功的时候,人们都想得到荣誉(有时他们甚至想为他们没有做过的事情得到荣誉)。如果你想出类拔萃,把你团队的任何成功故事的功劳都给别人,因为它会给你十倍的回报:表扬,不仅会给团队更大的主人翁感,还会给他们工作的成功(以及后来的失败)带来更大的责任感!

在失败中,当大多数人开始指指点点时,那就是承担责任的时候了!即使你可能不相信这是你的错,你也必须拥有你的团队生产的一切。如果他们觉得你会把责任推给他们,他们会怨恨你的领导。向他们反馈他们的缺点,但总是向高级管理层掩盖你的团队。

➌:培养信任文化

强大的团队文化是完成使命的基础。

你应该努力营造一种信任的氛围,即营造一种敢于冒险的环境,在这种环境中,你周围的人感到安全并有动力发挥他们的创造力,交流想法并毫不犹豫地为重大决策提供意见。给予信任是激励回报的强烈信号。

信任和谦逊是相辅相成的。不知道是谁创造了这句话:“当我和经理们交谈时,我觉得他们很重要。当我与领导交谈时,我感觉自己很重要,但这是谦逊领导的最佳例子。团队中的每个人都应该在与你交谈后感到被授权、被重视和被欣赏,然后离开。

当一个好的领导者的工作完成了,他的目标实现了,人们都会说,“这是我们自己做的。”——老子

强化团队精神的一个同样重要的方面是问他们“我做得怎么样?“—提出这样的问题需要谦虚,考虑答案更需要谦虚!

在我的领导风格中,将团队放在首位极大地影响了我的职业道路和我的个人品牌。我希望你在职业生涯的早期就认识到团队导向的重要性!

➍:从过去中吸取教训

你的领导哲学应该由你早期作为开发人员的经历来定义。我记得年轻时的自己在会议上发言时感到不自在。现在我通过询问那些安静的人是否有什么要补充的来确保每个人的声音都被听到。解决您作为开发人员遇到的一些问题,包括技术和社会问题,是一个很好的起点。你的团队会喜欢你的!

同样,我也曾为令人沮丧的 TLs 和绝对英雄工作过。我试图避免成为我真正不喜欢的 TL,并注意到那些我钦佩的人的强烈特征,并将它们融入到我的管理风格中。

➎:打造新领袖

寻求取代你自己,除非你想在你的职业生涯中继续做同样的工作!你需要通过承担更多的责任,偶尔让他们领导团队,给你的团队发光的机会。在指导他们并帮助他们发现自己的优点和缺点后,请他们在你度假时扮演你的角色。然后,您可以评估他们可能需要额外培训和发展的地方。逐渐地将更多的任务委派给他们,直到你尝试新领域的时候!

考虑你的继任计划意味着你需要培养你周围的人。当他们知道下一个角色在等着他们时,他们的自尊和自尊会得到提升,这增强了他们作为团队成员的效能和价值。这是双赢的局面!

推荐资源

这里有几个资源对我以前的 TL 角色影响最大。

结论

技术领导将无与伦比的技术专长与社交技能相结合。如果你做到了这一步,你可能足够关心做好 TL 这个角色,并且你有成为 TL 的天赋。

成为最好的是关于不断改善你是谁,并保持进化…这是你的旅程。拿着!

感谢阅读!

我经常在媒体上写关于领导力、技术&的数据——如果你想阅读我未来的帖子,请‘关注’我

英雄联盟获胜条件

原文:https://towardsdatascience.com/league-of-legends-win-conditions-db139f1ed6ca?source=collection_archive---------25-----------------------

用 Python 编码来理解赢得英雄联盟游戏的最重要因素

Mateo Vrbnjak 在 Unsplash 上拍摄的照片

介绍

在过去的几年里,电子竞技社区一直在快速发展,曾经是一种休闲娱乐的东西已经演变成一个产业,预计到 2022 年将产生 18 亿美元的收入。虽然这个生态系统中有许多视频游戏,但很少有像英雄联盟这样成为社区的主要内容,该游戏在 2019 年世界锦标赛期间聚集了超过 1 亿名独立观众。

《英雄联盟》于 2009 年底发布,是一款免费的 MOBA(多人在线对战竞技场)视频游戏,由 Riot Games 创建,早期曾产生广泛的竞争场景,2011 年的第一届世界锦标赛产生了约 160 万观众。从那以后,这款游戏在受欢迎程度和游戏性方面都有所增长,因为 Riot 开始明白如何改变才能使游戏更具竞争性和趣味性。

游戏目前的状态相当复杂,如果你是一个完全的新手,你应该看看这个视频。总的来说,一场英雄联盟比赛由两队五名球员组成,每队控制一个独特的角色或“冠军”,当一队位于该队基地深处的 Nexus 被摧毁时,比赛结束。一路上,一个团队可以实现许多目标,例如摧毁炮塔,杀死中立的怪物,如龙和男爵,为整个团队的爱好者,等等。一些目标,比如摧毁至少五个炮塔和一个抑制剂,是赢得游戏的必要条件,而其他的,比如获得第一滴血,是有帮助的,但不是必要的。通过这个项目,我想更好地了解这些目标中哪些是赢得一场英雄联盟比赛最重要的。就此而言,我提出的问题如下:

《英雄联盟》一款游戏最重要的胜利条件是什么目标?

收集数据

跳进来,我首先用 Riot 开发者门户申请了一个应用,在我的应用被接受后,我浏览了一下API 标签以了解我可以请求的数据类型。不幸的是,没有直接的方法让我从一个区域中找出最后 X 个排名匹配,所以我必须找到一种方法来解决这个问题。

我的解决方案是使用一个召唤师名字(用户名)列表来为每个玩家生成一个最*比赛的列表。通过使用 Python 包 Riot-Watcher 对 Riot API 的一系列调用,我在一个略低于 10,000 行的 Pandas 数据帧中填充了最*排名的英雄联盟游戏,这些游戏是由五个地区的前 100 名玩家玩的,这五个地区构成了最大数量的英雄联盟玩家群乍看之下,数据帧如下所示:

匹配数据帧的前十行

在前七列中,0 表示“假”,1 表示“真”,而在后面的列中,单元中编码的数据表示该事件发生的次数。每一行都包含了英雄联盟排名赛中一支球队的数据。例如,在第一行中,没有首先获得任何目标的队输掉了整场比赛。

利用热图和主成分分析进行探索性数据分析

我首先发现,大约 91%的获胜团队摧毁了第一个抑制剂,80%杀死了第一个男爵,70%摧毁了第一个塔,63%杀死了第一条龙,59%的获胜团队以第一滴血开始游戏。看起来最重要的胜利条件是摧毁第一个抑制剂,这是有道理的,因为摧毁一个团队的抑制剂会给他们的基地带来压力,并让对手有更多的地图控制权。

接下来,我可视化了数据集中各列之间的相关性:

数据间的热图关联

我还为我的数据中代表的每个区域绘制了相同的相关性热图,以比较不同区域之间的相关性,希望注意到游戏风格的一些差异。不过一般来说,相关矩阵看起来非常相似。一个可能的原因是,我的数据包括了每个地区最好的球员参加的比赛,其中许多人都是职业水平的。因此,由于良好的游戏实践在竞争社区中是一致的,所以我的数据中所表示的比赛涉及到的玩家相对于每个地区排名较低的玩家来说,在每个游戏中的导航是相似的。

我现在很好奇,想看看用比我用来预测游戏结果的 10 个特征更少的特征能在多大程度上解释数据中的差异。在这种情况下,我进行了主成分分析,以了解我可以将数据简化成多少个特征,并仍然保留大部分差异:

每个新组成部分解释的差异比率

十个预测值列中超过 80%的方差可以用一半的特征量来解释。这肯定很有趣,通过将每个组件与原始数据集的列相关联,我希望了解哪些特性在解释数据的方差方面最重要,这可以帮助我找出哪些列对团队是否会获胜最关键。

数据集的列和主成分之间的关系

用于生成上述热图的组件来自一个包含六个组件的 PCA 对象,因为我希望这些组件能够解释数据中 90%以上的差异。看起来,杀死塔的数量、杀死抑制剂的数量以及团队是否摧毁了第一个抑制剂是决定数据方差的最重要的特征,因为第一个成分解释了方差的 40%,并且前面提到的三列在该成分中权重最大。

重申我在这一点上收集的见解:

  • 从我的关联热图来看,一个团队是否摧毁了第一个抑制剂,一个团队有多少塔杀,一个团队摧毁了多少抑制剂,都与获胜有最高的关联。
  • 根据我的 PCA 分析,一个团队是否摧毁了第一个抑制剂,一个团队有多少塔杀,以及一个团队摧毁了多少抑制剂在解释数据的差异方面起了最大的作用。

使用逻辑回归的数据建模

我用了一个逻辑回归模型来理解一场《英雄联盟》排名赛的获胜条件。我的过程是首先将我的数据分成一组特征和一组目标,其中我的特征是除“win”和“region”列之外的所有列,我的目标是“win”列。然后,我将我的数据分为训练集和测试集,通过逻辑回归模型运行它们,并检查分类报告和混淆矩阵,以确保相对较强的预测能力。当逻辑回归模型在整个数据集上运行时,模型的精度和召回率分别为. 86 和. 85。

在这里,我对只包含一个地区的数据子集进行了逻辑回归,比如只在北美、北美等地进行的比赛。,并将模型的系数记录在熊猫数据框中。然后这个数据框架被可视化,这样我就可以比较不同的区域:

跨区域和整体的对数回归系数

回归系数描述了预测变量和目标变量之间的关系。例如,当观察上面的第一滴血预测变量时,获得第一滴血的团队是游戏结果的中度预测者,因为获得第一滴血的团队更有可能获胜。另一方面,裂缝传令官杀死实际上是反方向相关的(除了 EUNE),获得更多裂缝传令官杀死的团队更有可能失败。

使用这个分析过程,我了解了哪些列更能预测胜利,帮助我回答了关于英雄联盟游戏中胜利条件的问题。

结论

作为我项目的结果,以下是我得出的结论:

  • 根据我的逻辑回归模型,按照从大到小的顺序,第一个抑制剂,第一个塔,和塔杀是整个数据集中最重要的获胜条件。
  • 根据我的关联热图,按照从大到小的顺序,塔击杀、第一个抑制剂和抑制剂击杀是整个数据集中最重要的获胜条件。
  • 虽然拿了第一个男爵的北美和 EUW 队更有可能获胜,但是随着杀死男爵数量的增加,这些地区的队更有可能失败。
  • 与其他地区相比,北美地区的团队更有可能赢得第一条龙,这一事实可能表明北美地区的游戏更容易受到龙迷的影响,并围绕龙展开战斗。
  • KR 游戏受一个特性的影响并不均衡。这可能表明 KR 球员比其他地区的球员更了解如何在背后比赛,这促使一支球队比其他地区更经常地赢得目标的组合。

如果你认为我错过了任何其他有趣的观察,请在评论中告诉我们!

包含我的代码的 GitHub 存储库和我为这次分析整理的数据集可以在这里找到。

在 Web 应用程序中泄露秘密

原文:https://towardsdatascience.com/leaking-secrets-in-web-applications-46357831b8ed?source=collection_archive---------33-----------------------

环境变量失控:数据泄露结果

利用错误配置的中间件中的漏洞

“秘密应该是安全的”——授权给杰森·奥斯特罗姆

信息泄露是一种漏洞,在这种漏洞中,系统会无意中暴露机密信息。这篇文章通过观察环境变量在 web 应用程序中如何被误解和误用,展示了这个缺陷的一个例子。这篇文章将重新审视最佳实践,并以对开发者的可行建议作为结束。

L eaking Secrets 描述了一种信息泄露缺陷,在这种缺陷中,应用程序将敏感凭证或 API 密钥暴露给对手。OWASP 2017 十大漏洞将此漏洞归类为“ 敏感数据曝光 ”。这篇文章将讨论如何通过一个在 rails 应用程序上运行的易受攻击和错误配置的中间件 gem 的案例研究来利用这一点。这些类型的问题可能会导致企业的数据泄露,从而导致重大的财务和声誉损失。这些问题是经常观察到的,因为基础设施即代码(IaC)和云速度使 DevOps 人员能够快速启动新的 web 应用程序和环境而不受检查。如果您是使用 Rails 的开发人员,您需要了解这些问题。如果你是一个使用 web 应用程序的初学者,你会发现这些信息很有用,并且(我希望)能够更好地保护你的客户。

在你的 web 应用程序中通过公共互联网暴露秘密正是你 永远 不想做的事情。对于阅读本文的 Rails 开发人员来说,这是对 Rack-mini-profiler 的致敬。

机架式迷你剖面仪:好的,坏的,丑陋的

Rack-mini-profiler是一个中间件 gem,被 Rack 开发人员用作性能工具,以提高基于 Rack 的 web 应用程序的可见性和速度。该工具对开发者社区有价值,并受到高度重视,正如这位爱好者所展示的:

*rack-mini-profiler*是一个用于机架应用的性能工具,由天才的 @samsaffron 维护。 rack-mini-profiler 提供了一整套工具来测量支持 rack 的 web 应用程序的性能,包括详细的 SQL 查询、服务器响应时间(对每个模板和部分模板都有细分),令人难以置信的详细的毫秒级执行时间细分(具有不可思议的*flamegraph*功能),甚至可以通过其出色的垃圾收集功能帮助您跟踪内存泄漏。我会毫不犹豫地说 ***rack-mini-profiler*** 是我最喜欢也是最重要的开发快速 Ruby webapps 的工具。

我最*在野外发现了一个使用 Rack-mini-profiler 的 Rails 应用程序的部署,看到其中的安全问题令人大开眼界。我想澄清的是,我并不是说创业板有内在的脆弱性;相反,如果没有适当的安全保护,如何使用或配置中间件 gem 是一个问题。所以我开始更好地理解这是如何发生的,以及观察到的实际漏洞。这一努力的高潮是一个开源项目,“锤子”。Hammer 是一个易受攻击的 Rails 应用程序部署的例子,它使用 Rack-mini-profiler 来泄漏 API 密钥和敏感信息。它与在野外观察到的真实世界的应用程序一样容易受到攻击。这也是一个骨架应用程序,可以用来以安全的方式分叉和试验敏感变量。在构建这个工具的过程中,我学到了一些东西,希望与开发人员和 InfoSec 社区分享这些经验。

锤子图像,归杰森·奥斯特罗姆所有

锤子 Github 站点这里是这里是

这里的是的一个轻锤介绍。

让我们快速浏览一下中间件的功能,它为开发人员提供了如此多的好处,但同时也使它成为一个有吸引力的攻击目标。你可以跟随锤子的演示应用:https://preprod.rtcfingroup.com

在左上角,通过安装这个性能中间件 gem 呈现了一个“HTML 速度徽章”。安装该工具后,HTML speed badge 可用于分析 Rails 应用程序提供的任何给定页面。

HTML 速度徽章

https://preprod.rtcfingroup.com/users/.】T2 让我们浏览敏感用户可以公开访问的 URL—注意,这些不是真正的用户。它们是从模拟用户的工具中包含的脚本中随机生成的。看一下左上角的 HTML 速度标记,看看它是如何渲染页面渲染时间的。

用户页面

Ex 在 /users/ 展开速度徽章,显示渲染每个页面所花费的时间,以毫秒为单位。请注意用于呈现 用户/索引 的有趣的 SQL 查询。Rack-mini-profiler 创建了一个链接,您可以单击该链接获取更多信息。让我们来看看。

用户的 SQL 查询

B 下面,您可以看到 Rack-mini profiler 显示了详细的调用堆栈查询信息。您可以看到呈现给用户的 SQL 查询、文件和精确行。对于试图提高性能和识别应用程序瓶颈的开发人员来说,这是非常好的信息。但是从攻击者的角度来看,这收集了诸如 SQL 查询之类的有价值的信息,这些信息可能使其他漏洞被利用。从不公开 SQL 查询客户端被认为是一种标准的安全实践。当我第一次在野外看到这个的时候,我简直不敢相信我所看到的。Rack-mini-profiler 的网站声明,该工具可用于分析开发和生产中的应用程序。这就是为什么确保公开 SQL 调用堆栈查询与应用程序开发的组织安全策略保持一致如此重要。当我第一次看到这个的时候,我不知道会有更有趣的东西。阅读下文。

调用堆栈查询

R ack-mini-profiler gem 使用了“Pretty Print”Ruby 类( pp ),可以通过追加 在默认 URL 找到?pp =求助 。对于开发者来说,它有很多不错的特性,比如内存分析和垃圾收集。从安全角度来看最有趣的是漂亮的印花 env

精美的印刷(pp)菜单

№1:转储“环境”

T 他的 env pretty print 特性转储所有传递给 Rails 应用程序的环境变量。这包括如下所示的 机架环境

env 的漂亮印刷

T 看一下profiler . Rb的 Rack-mini profiler 源代码,代码显示它首先通过迭代并打印存储在 env 中的局部变量来转储 env 这与上面以“ 机架环境 ”开头的输出相关

№2:转储“环境”

其次,它通过迭代并打印这个散列的内容来转储 ENV 常量。

用于转储环境和环境的 RackMiniProfiler 源

T 下面的截图显示了从易受攻击的示例应用程序开始转储 ENV 常量哈希,与从ENV.each do开始的第二部分代码相关。

转储环境

在这个例子中,亚马逊 S3 API 密钥被存储在 ENV 中,并向公众公开。这显示了在存储于 ENV 常量散列中的环境变量中存储 API 秘密和其他敏感凭证是多么危险。我们将在下面详细讨论这是如何发生的。

转储更敏感的环境

更进一步,示例应用程序泄露了各种不同的云 API 和秘密,包括脸书、Twitter、LinkedIn 和 Google。

转储 API 密钥

Ruby 中的 env 和 ENV 是什么?

NV 是一个类似哈希的类,Ruby 用它向我们的应用程序公开环境变量。例如,我们的 rails 应用程序可以使用 PATH 或 HOME。Rack-mini-profiler 不需要做太多的事情来转储 ENV,因为该常量在应用程序启动时公开。开发人员有责任正确地存储、加载和保护 ENV。传统上,ENV 与环境变量相关,并且比 env 更加全局。这些变量中的每一个都被列为键/值对,它们通常用于共享配置。

像 Rails 这样的 ll Rack 应用程序只接受一个参数,这个参数是一个名为 env 的散列。env 被传递给 Rails 应用程序,并存储诸如 HTTP 头、请求和服务器配置等信息。与 ENV 相比, env 更适合 Rails。

漏洞

环境变量不应该用来存储敏感的配置信息,比如凭证和 API 密钥。如果必须使用它们,您的安全程序应该接受这种风险,将其记录在您的风险登记簿中,并提供适当的安全控制来降低风险。

关于环境变量及其正确使用已经说了很多。十二因素应用宣言声明环境变量应该被用来存储配置元素,比如亚马逊 S3 或 Twitter 等外部服务的凭证。

十二要素应用宣言

我不同意这个。遵循这种做法会增加您公司的商业风险。

这个示例应用程序展示了开发人员犯错误和无意中暴露敏感的 API 键(如 AWS)是多么容易,这些 API 键会导致数据泄露。创建此应用程序是为了模拟在列举上述问题后得到保护的野外生产环境。Rails 开发人员可以使用不同的环境,比如生产、QA 或开发。Rack-mini profiler 设计用于这些环境中的任何一种。暴露的环境变量,如果包含在开发环境中运行的敏感机密,会给攻击者提供凭证,允许未经授权的数据访问、信息泄漏和特权升级到生产。环境变量有一个存储配置元素的好地方。它们不应该被用于敏感的秘密。

T 这个示例应用程序使用 Dotenv rails gem 从.env加载环境变量。这个示例应用程序使用.env.local将文件中包含的所有填充的环境变量加载到由 Rack-mini-profiler 转储的 env 常量中。看看锤子的 Github 回购中也能看到的配置:

Hammer 附带的“. env.local”

除了通过中间件暴露敏感环境变量的风险之外,还有其他一些充分的理由说明为什么开发人员应该意识到这种实践中固有的风险。下面的列表总结了来自迪奥戈莫尼卡的一些风险:

  1. 由于没有正确使用 而将未加密的环境变量文件如.env.local复制到中央 Git 存储库中的风险。gitignore 文件。部落知识的风险,当没有设置系统的新开发人员没有适当注意保护这些包含环境变量的文件时。秘密被复制到不同的系统并被暴露。
  2. 应用程序可以获取整个环境,并打印出来用于调试或错误报告。如果在离开您的环境之前没有进行适当的清理,机密可能会泄露。
  3. 环境变量被传递给子进程,这可能导致意外的访问(例如,第三方工具可以访问您的环境)。
  4. 当应用程序崩溃时,通常将环境变量存储在日志文件中以供调试。这增加了磁盘上明文秘密的风险。

试验 ENV 和 Bash 环境

在我们开始玩一些 ENV 和环境变量的例子之前,让我们回顾一下 Ruby 环境变量的一些规律。 Honeybadger.io 就此给出了一个精彩的教程,我来总结一下:

  1. 每个进程都有自己的一组环境变量。
  2. 环境变量随着它们的过程而消亡。
  3. 一个进程从它的父进程继承它的环境变量。
  4. 对环境的更改不会在进程间同步。
  5. 您的 shell 只是环境变量系统的一个 UI。

这个例子遍历了 Rails 应用程序主目录中的 Hammer 环境。

转到 Rails Hammer 应用程序的工作主目录:

$ cd /home/<username>/hammer

Grep for SECRET 中的 .env.local 来看一些我们想玩的环境变量。

$ grep SECRET .env.local

你会看到几个皇冠宝石的 API 键。现在用env打印 Bash shell 环境变量。您将看到所有的标准环境变量,比如\(HOME 和\)PATH。用env | grep SECRET验证那些敏感变量当前没有加载到您的 Bash 环境中。

验证“env”命令不显示机密

运行交互式 Ruby 工具( irb ),我们看看会发生什么。默认情况下, irb 不会看到 ENV 公开的任何敏感环境变量。这是因为我们需要使用 Rails 'dotenv' gem 从.env文件中加载变量。这表明,默认情况下,当实例化 Ruby 应用程序时,Rails 应用程序会将父进程(Bash shell)的环境变量继承到 ENV 常量中。但是我们需要以特殊的方式将额外的环境变量加载到 ENV hash constant 中,因为这些变量在默认情况下是不可用的。您将能够看到 \(PATH*** 和 ***\)HOME ,但看不到其他任何内容。

$ irb
> ENV
> ENV['PATH']
> ENV['S3_SECRET_ACCESS_KEY']

启动 irb

获取一些环境变量

指示 irb 使用 dotenv gem 从 .env.local 文件中加载环境变量。这个命令将把环境变量加载到 ENV 中,使它们对我们的 irb ruby 环境可用。

> require 'dotenv';Dotenv.load('.env.local')

注意,所有漂亮的东西现在都有了,敏感的皇冠宝石 API 键!

使用 dotenv 加载. env.local 文件

验证您可以在 irb 终端中访问这些漂亮、敏感的 ENV 程序!

> ENV['S3_ACCESS_KEY_ID']
> ENV['S3_SECRET_ACCESS_KEY']

验证敏感的环境变量

接下来,打开一个新的外壳。启动 irb 并尝试列出 ENV 中存储的敏感环境变量。

默认情况下,ENV 不会在单独的进程之间共享或同步

注意,在第二个 shell 的 irb 会话中,没有列出敏感的环境变量。这是因为环境变量的工作方式。每个进程都有自己的一组环境变量,这些变量不会在进程之间自动同步。

现在尝试导出这些变量。如果你把export放在.env.local中命名的变量的语法前面,并源文件, 神奇地发生了 。这将本地 shell 变量转换为 ENV 可用的环境变量。然后任何从 bash shell 实例化的 Rails 子进程都可以使用它。锤子应用程序包括一个导出的变量文件样本,目的是以安全的方式处理敏感变量- .env.local.exported。让我们试一试。

在第二个 shell 中,退出 irb 会话并键入 source 命令。然后运行 env 列出 bash shell 中的环境变量:

$ source .env.local.exported
$ env | grep SECRET

获取. env.local.exported 文件

现在在第二个 shell 中,重新启动 irb 并获取敏感的 ENV 变量。

$ irb
> ENV['S3_ACCESS_KEY_ID']
> ENV['S3_SECRET_ACCESS_KEY']

显示秘密被加载到 ENV 中

太神奇了!你不必调用 Dotenv gem 来自动加载到 env 中。这向您展示了 Dotenv gem 正在做什么——本质上是从 中获取变量。env 文件当环境被引导并加载到 env。然后通过 Rack-mini-profiler Pretty Printer(PP)ruby 类转储 ENV。

在本例中,我们最终将导出的变量提供给了 bash shell。一旦我们退出 shell,环境变量对于下一个启动的 bash shell 就不可用了。如果开发人员将命令添加到 shell init 脚本,如 。bashrc 这是应该避免这种做法的另一个原因。

存储机密的方法概述

  • 明文存储秘密:使用 Rails gem 方法如 DotenvFigaro 在环境中存储秘密,通过加载 env 访问。其他方法包括 rbenv-vars 插件和 direnv 。这些是流行的方法,但是开发者应该考虑更好的安全性。
  • SaaS 秘密管理服务:使用诸如金库AWS 秘密管理器和许多其他服务在你的应用程序内同步和管理秘密。这是一种比明文存储秘密更好的方法,但是请记住,您必须保护一个超级机密的 SaaS API 密钥,它会保护您的所有秘密。
  • Rails 加密的秘密:从 Rails 5.1 开始,您可以使用加密的秘密来为您的应用凭证提供更好的保护。可以使用除 ENV 键/值散列之外的特殊变量来访问它们。这里有一个很好的概述,从 Rails 6 开始,可以做多环境凭证管理。这是比第一种方法更安全的方法,与第二种方法相似。这应该将主加密密钥保存在您的 Rails 系统上,而不是与云 SaaS 同步。

推荐

以下是一些降低风险的建议。这些旨在提供想法,并应与您的开发运维流程保持一致。

  • 卸下连接到公共互联网的所有系统上的 rack-mini-profiler gem。
  • 在需要可访问公共互联网的 Rack-mini profiler 系统上:通过白名单/防火墙 IP 地址实施强访问控制,仅允许开发人员工作站访问 web 应用程序。
  • 使用 RackMiniProfiler 访问控制来授权请求并将其列入白名单。RackMiniProfiler 有一个authorization _ mode在生产中加入白名单。参考自述文件非开发环境下的访问控制 章节。
  • 使用加密的机密并避免使用 ENV 的环境变量来存储敏感的凭证。在本地执行此操作的最佳方法是 Rails 加密机密。这将避免将敏感变量加载到 ENV 中,因为这会增加它们被无意中暴露的风险。

结论

像 Rack-mini-profiler 这样的中间件为开发人员提高 Rails 应用程序的速度提供了优秀的特性;但是,必须应用安全控制来确保机密在您的应用程序中得到适当的保护,不会泄露给对手。

一位睿智的网络安全专家发表了这个简单而有力的声明:

我们都需要一起努力。任何弱点都是需要修正的弱点,让我们一起来修正它。

参考

https://github.com/MiniProfiler/rack-mini-profiler

https://www . speed shop . co/2015/08/05/rack-mini-profiler-the-secret-weapon . html

https://stack ify . com/rack-mini-profiler-a-complete-guide-on-rails-performance/

https://12factor.net/config

https://www . honey badger . io/blog/ruby-guide-environment-variables/

https://www . honey badger . io/blog/securing-environment-variables/

https://www . ruby guides . com/2019/01/ruby-environment-variables/

https://diogomonica . com/2017/03/27/why-you-should-use-env-variables-for-secret-data/

https://stack overflow . com/questions/61821207/rails-environment-variables-with-rack-mini-profiler

https://medium . com/craft-academy/encrypted-credentials-in-ruby-on-rails-9db 1 f 36d 8570

https://medium . com/@ kirill _ shevch/encrypted-secrets-credentials-in-rails-6-rails-5-1-5-2-f 470 accd 62 fc

https://medium . com/poka-tech blog/the-best-way-to-store-secrets-in-your-app-308 a 6807 D3 ed

今日学*人工智能 Pytorch 入门

原文:https://towardsdatascience.com/learn-ai-today-01-getting-started-with-pytorch-2e3ba25a518?source=collection_archive---------31-----------------------

今天学 AI

定义和训练 Pytorch 模型并动态可视化结果

Jukan TateisiUnsplash 上拍摄的照片。

这是今天我创作的 学艾 系列中的第一个故事!这些故事,或者至少是前几个,是基于我在研究/学* PyTorch深度学*时创作的一系列 Jupyter 笔记本。我希望你和我一样觉得它们很有用!

你将从这个故事中学到什么

  • 如何创建 PyTorch 模型
  • 如何训练你的模型
  • 动态可视化培训进度
  • 学*速度如何影响训练

1.PyTorch 中的线性回归

线性回归是一个你可能很熟悉的问题。最基本的形式就是用一条线来拟合一组点。

1.1 介绍概念

考虑一条线的数学表达式:

wb是该线性模型的两个参数权重。在机器学*中,通常使用w重量b偏差参数。

在机器学*中,当我们训练一个模型时,我们基本上是在为一组给定的输入/目标(x,y)对寻找最佳参数 wb。在模型被训练之后,我们可以计算模型估计。该表达式现在将看起来

这里我把y的名字改成ye (y 估计),因为这个解不精确。

均方差(MSE) 就是mean((ye-y)²)——目标值和估计值之间的均方差。对于一个回归问题,你确实可以最小化 MSE 以便找到最好的wb

线性回归的思想可以用代数矩阵符号来概括,以允许多个输入和目标。如果你想了解更多关于回归问题的数学精确解,你可以搜索正规方程

1.2 定义模型

PyTorch nn.Linear类是定义具有任意数量输入和输出的线性模型所需要的全部。对于将直线拟合到一组点的基本示例,考虑以下模型:

注: 我使用的 Module 来自fastai库,因为它使代码更干净。如果你想使用纯 PyTorch,你应该使用 nn.Module 来代替,你需要在 __init__ 方法中添加 super().__init__() 。fastai Module 为你做到了。

如果你熟悉 Python 类,代码是不言自明的。如果没有,考虑在深入 PyTorch 之前做一些研究。有许多在线教程和课程涵盖了这一主题。

回到代码。在__init__方法中,您定义了模型的层。在这种情况下,它只是一个线性层。然后,forward方法就是当你调用模型时被调用的方法。类似于普通 Python 类中的__call__方法。

现在,您可以将 LinearRegression 模型的一个实例定义为model = LinearRegression(1, 1),表示输入和输出的数量。

也许你现在在问为什么我不简单地做model = nn.Linear(1, 1)你是绝对正确的。我在定义LinearRegression类时遇到这么多麻烦的原因只是为了给以后的改进提供一个模板,稍后你会发现。

1.3 如何训练你的模型

训练过程基于一系列 4 个步骤,反复重复:

  • 正向传递:将输入数据提供给模型,并获得模型输出— outputs = model(inputs)
  • 计算损失函数:对于线性回归问题,我们使用的损失函数是均方误差(MSE)。我们经常把这个函数称为标准— loss = criterion(outputs, targets)
  • 反向传递:计算损失函数相对于每个可学*参数的梯度。记住,我们要减少损失函数,使输出接*目标。梯度告诉我们,如果你增加或减少每个参数,损耗会如何变化— loss.backwards()
  • 更新参数:在减少损失的方向少量更新参数值。更新参数的方法可以简单到减去乘以一个小数值的梯度值。这个数字被称为学*率,我刚刚描述的优化器随机梯度下降(SGD)optimizer.step()

我还没有确切地定义criterionoptimizer,但我会在一分钟。这只是给你一个训练迭代步骤的总体概述和理解,或者通常称为训练时期

让我们定义我们的fit函数,它将完成所有需要的步骤。

请注意,在 — optimizer.zero_grad()之前,还有一个额外的步骤我没有提到。这是因为默认情况下,在 PyTorch 中,当您调用loss.backwards()时,优化器会将梯度值相加。如果你不在每个时期将它们设置为零,那么它们将会一直累加,这是不可取的。除非你在做梯度积累——但那是一个更高级的话题。除此之外,正如你在上面的代码中看到的,我保存了每个时期的损失值。我们应该预计它会稳步下降——这意味着该模型在预测目标方面变得越来越好。

正如我上面提到的,对于线性回归,通常使用的标准是 MSE 。至于优化器,现在我总是把 Adam 作为首选。它速度很快,应该可以很好地解决大多数问题。我不会详细说明 Adam 现在是如何工作的,但我们的想法总是在最短的时间内找到最佳解决方案。

现在让我们继续创建我们的线性回归模型的实例,定义我们的标准和我们的优化器:

model.parameters()是向优化器提供可训练参数列表的方式,而lr是学*率。

现在让我们创建一些数据并训练模型!

数据只是一组遵循模型y = 2x + 1 + noise的点。为了让它更有趣一点,我让 x 的值越大噪声越大。第 4 行和第 5 行中的unsqueeze(-1)只是在末尾给张量增加了一个额外的维度(从[10000][10000,1])。数据是相同的,但张量需要有这样的形状,这意味着我们有 10000 个样本,每个样本有一个特征。

绘制数据,结果就是下图,可以看到真实的模型和输入数据+噪声。

线性回归模型的输入数据。图片由作者提供。

现在为了训练模型我们只需运行我们的 **fit** 函数!

经过训练后,我们可以绘制 100 个时期内损失的演变。正如您在下图中看到的,最初的损失约为 2.0,然后急剧下降到接*零。这是意料之中的,因为当我们开始时,模型参数是随机初始化的,并且随着训练的进行,它们收敛到解决方案。

100 个训练时期的损失演变(MSE)。图片由作者提供。

注:试试玩学*率值,看看对训练有什么影响!

要检查训练好的模型的参数,可以在训练完模型后运行list(model.parameters())。您将会看到,在这个示例中,它们非常接* 2.0 和 1.0,因为真正的模型是y = 2x + 1

您现在可以计算模型估计值— ye = model(x_train)。(请注意,在计算评估之前,您应该始终运行model.eval()来将模型设置为评估模式。这对于这个简单的模型来说不会有什么不同,但是当我们开始使用批处理规范化和删除时,就会有所不同。)

绘制预测图,您可以看到它几乎完美地匹配了真实数据,尽管事实上模型只能看到有噪声的数据。

可视化模型评估。图片由作者提供。

2.逐步走向多项式回归

既然我们已经使它适用于简单的情况,那么转移到更复杂的线性模型就非常简单了。第一步当然是生成这样的输入数据。对于这个例子,我认为模型y = 3x² + 2x + 1 + noise如下:

多项式模型的输入数据。图片由作者提供。

请注意,这次输入形状是[1000, 2],因为我们有两个对应于x的特征。这就是使用线性回归拟合多项式的方法!

与前面的例子相比,现在唯一的区别是模型需要两个输入— model = LinearRegression(2,1)。就是这样!现在,您可以按照完全相同的步骤来训练模型。

然而,让我们用一些动态的可视化来让事情变得更有趣一点吧!

2.1 动态可视化培训进度

为了动画化训练的发展,我们需要更新拟合函数,以便也存储每一步的模型估计值。

你可能注意到了一个‘新词’——detach()(代码第 17 行)。这是告诉 PyTorch 从梯度计算图中分离变量(它将不再计算分离变量的梯度)。如果在分离之前尝试将张量转换为 NumPy,将会出现错误。

继续,您可以像以前一样重复相同的过程来训练模型。唯一的区别是fit2函数也将返回每个训练时期的模型估计值。

要创建培训的视频/gif,请看下面的代码:

%%capture告诉 Jupyter 抑制单元格的输出,因为我们将在下一个单元格中显示视频。然后,从第 3 行到第 10 行,我照常设置情节。不同之处在于模型预测。我将其初始化为空,然后使用matplotlib.animation迭代更新图形以生成动画。最后,可以使用来自IPython.displayHTML渲染视频。看看下面的结果!

在训练期间可视化模型预测。作者的动画。

有趣的是,蓝线最初非常快地弯曲成正确的形状,然后为了最终的解决方案收敛得更慢!

注:尝试使用学*率、不同的优化器以及任何您能想到的东西,看看对优化的影响。这是一个直观了解优化工作原理的好方法!

3.神经网络模型

上面的例子对于学*和实验来说很有趣。然而,在实践中,你的数据通常不是由多项式生成的,或者至少你不知道多项式的项是什么。关于神经网络的一个好处是你不需要担心它!

让我们从定义我命名为GeneralFit的模型开始:

在这个模型中有一些新的方面需要考虑。有 3 个线性层,正如你在正向方法中看到的,在前两个线性层之后,使用了一个 ReLU 激活函数F.relu() —。 ReLU 代表整流线性单元,简单来说就是将所有负值归零。然而,这个看似琐碎的操作足以使模型非线性。

注意,线性层只是矩阵乘法。如果你有一个接一个的 100 个线性图层,线性代数会告诉你有一个线性图层执行相同的操作。这个线性层是 100 个矩阵的简单乘积。然而,当你引入非线性激活函数时,这就完全改变了。现在,您可以继续添加更多的线性层与非线性激活交错,如 ReLU(在最*的模型中最常见)。

一个深度神经网络只不过是一个具有几个“隐藏”层的神经网络。回头看看上面的代码,例如,你可以尝试添加更多的“隐藏”层并训练模型。事实上,你可以称之为深度学*。(请注意,隐藏层只是输入层和输出层之间任何层的传统名称。)

使用上述模型和一组新生成的数据,我获得了以下训练动画:

以 0.01 的学*率在训练期间可视化 GeneralFit 模型的模型预测。作者的动画。

对于这个例子,我训练了 200 个纪元,学*率为 0.01。让我们试着将学*率设置为 1

在学*率为 1 的训练期间可视化 GeneralFit 模型的模型预测。作者的动画。

显然这样不好!学*率过高时,模型可能无法正确收敛到一个好的解,甚至可能发散。如果你把学*率设定为 10 或 100,它不会有任何进展。

家庭作业

我可以给你看一千个例子,但如果你能自己做一两个实验,你会学到更多!我给你们展示的这些实验的完整代码可以在这个笔记本上找到。

  • 试着玩一下学*率,历元数,隐藏层数,隐藏层数的大小;
  • 也试试 SGD optimizer,玩玩学*率,也许还玩玩动量(我在这个故事中没有涉及到,但现在你知道了,你可以做一些研究);

如果你通过实验创造了有趣的动画笔记本,那就在 GitHub、Kaggle 上分享吧,或者写一个关于它的故事!

结束语

今日学 AI系列第一个故事到此结束!

欢迎在评论中给我一些反馈。你觉得什么最有用,或者什么可以解释得更好?让我知道!

本系列的下一个故事:

** [## 今日学*人工智能:02 —使用 PyTorch 解决分类问题简介

用神经网络对花卉进行分类,可视化决策边界和理解过度拟合。

towardsdatascience.com](/learn-ai-today-02-introduction-to-classification-problems-using-pytorch-b710918cba63)

你可以在下面的故事中了解更多关于我的旅程!

[## 我的 3 年历程:从零 Python 到深度学*竞赛高手

自从 2017 年开始学* Python 以来,我一直遵循的道路是成为一名独自参加 Kaggle 比赛的大师…

towardsdatascience.com](/my-3-year-journey-from-zero-python-to-deep-learning-competition-master-6605c188eec7) [## 我在 Kaggle 上的两年旅程:我如何成为竞赛大师

描述我的旅程和策略,我遵循成为一个竞赛大师与个人金牌

towardsdatascience.com](/my-2-year-journey-on-kaggle-how-i-became-a-competition-master-ef0f0955c35d)

感谢阅读!祝您愉快!**

今天学*人工智能 02:使用 PyTorch 的分类问题介绍

原文:https://towardsdatascience.com/learn-ai-today-02-introduction-to-classification-problems-using-pytorch-b710918cba63?source=collection_archive---------69-----------------------

今天学 AI

用神经网络对花卉进行分类,可视化决策边界和理解过度拟合。

改编自凯莉·西克玛Unsplash 上的照片。

这是我创作的 今日 AI系列的第二个故事!这些故事,或者至少是前几个,是基于我在研究/学* PyTorch深度学*时创作的一系列 Jupyter 笔记本。我希望你和我一样觉得它们很有用!

如果你还没有,一定要检查以前的故事!

** [## 今日学*人工智能:Pytorch 入门

定义和训练 Pytorch 模型并动态可视化结果

towardsdatascience.com](/learn-ai-today-01-getting-started-with-pytorch-2e3ba25a518)

你将从这个故事中学到什么:

  • 验证的重要性
  • 如何为分类问题训练模型
  • 动态可视化决策边界
  • 如何避免过度拟合**

1.鸢尾花数据集

让我们从介绍数据集开始。我将使用非常著名的 鸢尾花数据集 ,它包含以下 3 种花的 4 种不同测量值(萼片长度、萼片宽度、花瓣长度、花瓣宽度)。

图片改编自维基百科

****目标是使用每朵花的 4 个测量值准确识别物种。注意,现在使用直接从图像中学*的模型(卷积神经网络)相对容易,但我将把这个话题留到下一课。如下面的代码所示,鸢尾花数据集可以很容易地从 sklearn 数据集中下载。

为了快速显示数据,我们绘制每对要素的散点图和每个要素的直方图。为了实现这个表示,我使用了pandas . plotting . scatter _ matrix函数(和往常一样,你可以在最后找到完整代码的链接)。

鸢尾花数据的可视化(蓝点——鸢尾;蓝绿色的点——杂色鸢尾;黄点——海滨鸢尾)。图片由作者提供。

正如你在上面的散点图中看到的,对于大多数样品来说,区分物种应该很容易。例如,在大多数地块中,刚毛鸢尾点与其他两个物种非常接*。对于这样一个简单的例子,你可以通过画几条线来创建一个基于规则的算法。然而,为了简单起见,也是一个用神经网络介绍分类的好例子!****

2.验证集

在直接进入模型和训练之前,创建一个验证集非常重要。为了避免一次引入太多概念,我在第一课中跳过了这一步。

****验证集的想法很简单。不是用你所有的数据训练一个模型,而是把一小部分数据(通常是 20% — 30%)储存起来,你将使用这些数据来评估训练好的模型是否能很好地推广到看不见的数据。这对于确保您的模型可以安全地投入生产以准确评估新数据非常重要。

在上面的代码中,我使用了train_test_split函数来随机分割数据,我选择了一个test_size=0.5。设置random_state总是一个好主意,以确保当您重新运行代码时,将使用相同的分割。

请注意,这是一个常见且良好的实践,两个不是 2 个而是 3 个数据分割:训练、验证和测试。在这种情况下,当你尝试几个模型、想法和超参数(如学*率)时,你使用验证集来检查进度,当你对结果满意时,才在最后使用测试集。这就是在卡格尔比赛中发生的事情,那里通常有一个隐藏测试装置

3.为分类训练模型

我将在这个例子中使用的模型与我在上一课中用于回归问题的模型完全相同!

那么有什么区别呢?不同之处在于损失函数。对于多类分类问题,通常的选择是交叉熵损失 (nn。PyTorch 中的 CrossEntropyLoss)。对于二元分类的问题,你通常会用二元交叉熵 损失 (nn。BCEWithLogitsLoss)。因此,用于定义模型、标准和优化器的代码与我在上一课中用于回归的代码非常相似!

要考虑的另一个区别是最后一个激活函数。对于回归问题,模型的输出是一个数字,可以是任何实数值。对于二进制分类,您需要使用一个 Sigmoid 激活函数将输出映射到 0–1 范围。对于多级分类,您需要 Softmax 激活功能(除非您想要允许多项选择,在这种情况下使用 Sigmoid 激活)。Softmax 输出可以解释为分配给每个类的概率。

现在不要太担心激活函数。我只是在这里提一下,让你意识到他们的存在。目前,值得一提的是。CrossEntropyLoss 包括为您激活的 Softmax 和 nn。BCEWithLogitsLoss 为您提供乙状结肠。这样你就不需要在模型的末尾添加任何激活函数。PyTorch 会帮你搞定的!

在训练模型之前,我还修改了上一课的fit函数(你可以在 Kaggle 笔记本上查看,最后有完整的代码),以考虑到traintest/validation数据。(当只处理两个数据集时,术语验证测试经常互换使用。)

绘制 1000 次训练中的训练和测试损失图,你可以看到有些奇怪的事情正在发生

训练和测试损失。图片由作者提供。

虽然列车损失随着时间的推移不断改善,但测试损失最初稳步改善,但随后开始增加。也许最重要的是,你可以通过绘制模型在 1000 个时期的精确度来看到同样的效果。

训练和测试准确性。图片由作者提供。

你现在看到的是我们所说的过拟合——在的某个点,模型开始“记忆”训练数据,而的泛化性能(用测试集评估)下降。这就是为什么你需要一个验证/测试集。在这种情况下,你可以看到,如果你在 200 个时期停止训练,结果可能会更好。这种方法称为提前停止,是一种减少过拟合的简单方法。然而,还有其他的方法,比如使用重量衰减,我马上会谈到。让我们首先做一些有趣的可视化来更好地理解正在发生的事情。

4.可视化决策边界并减少过度拟合

为了可视化训练边界并更好地理解过度拟合,我仅使用 2 个(而不是 4 个)特征来重新训练模型,以便容易地在 2D 图形中绘制结果。在下面的动画中,您可以看到在 1000 个训练时期中,训练(左)和测试(右)的决策界限不断演变。****

在 1000 个训练时期可视化模型决策边界。作者的动画。

看看最初模型如何快速学*划分区域的 2 条直线边界。然后,红黄边界开始向上弯曲,更好地适应列车组。然而,观察测试集,这导致了性能的轻微下降,因为更多的黄色点移动到中间区域,而蓝绿色点移动到顶部区域。而这正是过度拟合的样子。对于更复杂的问题,你可以在多维度中想象这一点——当你有很多维度时,更容易过度拟合。****

如果你很难想象任何超过 3 维的东西,只要遵循 Geoffrey Hinton 的建议:“要处理 14 维空间中的超平面,想象一个 3 维空间,并大声对自己说‘14’。大家都这么干。”****

为了减少这个例子中的过度拟合,可以使用两个简单的“技巧”:

  • ****提前停止:用更少的时期训练模型
  • ****权重衰减:通过在每次迭代中少量减少模型权重,使其变小

4.1 提前停止

提前停止的想法非常简单,正如我之前提到的,如果模型在大约 200 个历元时具有最佳验证精度,那么如果你只训练 200 个历元,你将得到一个概括得更好的模型——根据验证精度。问题是,您可能会在视觉上过度适应验证集——特别是当您根据验证分数调整许多超参数时。这就是为什么在完成所有实验后,获得一组额外的数据来评估模型是非常重要的。

4.2 重量衰减

****体重衰减的思路也很简单。当拟合一个神经网络时,一般来说,不存在最优解,而是存在多个可能的相似解。权重衰减,通过迫使权重保持较小,将迫使优化过程达到更简单的解决方案。

让我们给我们的模型添加一个weight_decay=0.01,并像以前一样在训练 1000 个时期后可视化结果。在 PyTorch 中,您只需要将这个参数作为optimizer = optim.Adam(model.parameters, lr=0.001, weight_decay=0.01)添加到优化器中。生成的动画如下。

在权重衰减为 0.01 的 1000 个训练时期期间可视化模型决策边界。作者的动画。

如您所见,现在红黄边界不会像以前那样向上弯曲,因为这需要大幅增加权重,而且精度不会有太大变化。

用具有重量衰减的 4 个输入特征来训练模型,得到了下面的训练和测试损失图。看,现在测试损失没有像以前一样开始增加!****

用重量衰减训练的模型的训练和测试损失。图片由作者提供。

同样重要的是要提到当你开始一个新项目时,过度适应是你应该瞄准的目标。从一个可以过度拟合数据的模型开始,这样你就知道你的模型有足够的“灵活性”来学*数据中的模式。然后增加正则化,像权重衰减,避免过拟合!****

家庭作业

我可以给你看一千个例子,但如果你能自己做一两个实验,你会学到更多!这些实验的完整代码可以在 这本笔记本 上找到。

  • 和上一课一样,试着玩学*率、时期数、重量衰减和模型大小。
  • 做些实验,看看结果是否如你所愿,如果不是,看看视觉效果,试着理解为什么。

和往常一样,如果你通过实验创作出了有趣的动画笔记本,那就在 GitHub、Kaggle 上分享吧,或者写一个中型故事!

结束语

Learn AI Today 系列第二个故事到此结束!

欢迎在评论中给我一些反馈。你觉得什么最有用,或者什么可以解释得更好?让我知道!

你可以在下面的故事中了解更多关于我的旅程!

**** [## 我的 3 年历程:从零 Python 到深度学*竞赛高手

自从 2017 年开始学* Python 以来,我一直遵循的道路是成为一名独自参加 Kaggle 比赛的大师…

towardsdatascience.com](/my-3-year-journey-from-zero-python-to-deep-learning-competition-master-6605c188eec7) [## 我在 Kaggle 上的两年旅程:我如何成为竞赛大师

描述我的旅程和策略,我遵循成为一个竞赛大师与个人金牌

towardsdatascience.com](/my-2-year-journey-on-kaggle-how-i-became-a-competition-master-ef0f0955c35d)

感谢阅读!祝您愉快!****

学*人工智能今天 03:马铃薯分类使用卷积神经网络

原文:https://towardsdatascience.com/learn-ai-today-03-potato-classification-using-convolutional-neural-networks-4481222f2806?source=collection_archive---------40-----------------------

今天学 AI

在 PyTorch 中创建一个 CNN 模型,并使用 fastai2 训练它识别土豆的类型,以简化代码

JESHOOTS.COM 在 Unsplash的照片。

这是 学艾今日 系列的第 3 个故事!这些故事,或者至少是前几个,是基于我在研究/学* PyTorch深度学*时创作的一系列 Jupyter 笔记本。我希望你和我一样觉得它们很有用!

如果你还没有,一定要检查以前的故事!

[## 今日学*人工智能:02 —使用 PyTorch 解决分类问题简介

用神经网络对花卉进行分类,可视化决策边界和理解过度拟合。

towardsdatascience.com](/learn-ai-today-02-introduction-to-classification-problems-using-pytorch-b710918cba63)

你将从这个故事中学到什么:

  • 土豆并不都一样
  • 使用 Kaggle 数据集
  • 卷积神经网络如何工作
  • 使用 fastai2 让您的生活更轻松

1.Kaggle 数据集

如果你想找到一个公共数据集,Kaggle 数据集页面是一个很好的起点。Kaggle 上有* 5 万个数据集,随着用户创建和上传新的数据集与世界分享,这个数字每天都在增长。

有了为这节课创建一个土豆分类器的想法后,我很快找到了这个数据集,它包含了 4 类土豆以及许多其他水果和蔬菜。

来自水果 360 数据集的图像样本。

2.卷积神经网络

计算机视觉的构建模块是卷积神经网络。这些网络通常结合了几层核卷积运算和缩减。

下面的动画是对内核卷积操作的可视化展示。内核是一个小矩阵,通常是 3x3,在整个图像上移动。让我们称它为输入特征图,而不是图像,这样更通用。

来自 Theano 文档的卷积示例。

在每一步中,内核 3x3 矩阵的值按元素乘以输入特征映射的相应值(上面动画中的蓝色矩阵),这 9 个乘积之和就是输出值,从而得到动画中的绿色矩阵。内核中的数字是待学*模型的参数。通过这种方式,模型可以学*识别作为计算机视觉基础的空间模式。通过拥有多层并逐渐缩小图像,每个卷积层学*到的模式越来越复杂。为了更深入地了解 CNN,我推荐 Irhum Shafkat 的这个故事。****

CNN 的想法从 80 年代就有了,但它在 2012 年开始获得动力,当时 ImageNet 竞赛的获胜者使用了这种方法并“击败”了竞争对手。他们的论文描述了解决方案,摘要如下:

“我们训练了一个大型深度卷积神经网络,将 ImageNet LSVRC-2010 大赛中的 120 万幅高分辨率图像分类为 1000 个不同的类别。在测试数据上,我们实现了 37.5%和 17.0%的前 1 名和前 5 名错误率,这大大优于以前的最先进水平。具有 6000 万个参数和 650,000 个神经元的神经网络由五个卷积层组成,其中一些卷积层后面是 max-pooling 层,以及三个完全连接的层,最后是 1000 路 softmax。为了加快训练速度,我们使用了非饱和神经元和卷积运算的高效 GPU 实现。为了减少全连接层中的过拟合,我们采用了最*开发的正则化方法“dropout ”,该方法被证明非常有效。我们还在 ILSVRC-2012 竞赛中加入了该模型的一个变体,并获得了 15.3%的前五名测试错误率,而第二名的错误率为 26.2%。”

前五名的错误率为 15.3%,而第二名的错误率为 26.2%,这是一个巨大的突破。快进到今天, 当前前 5 名结果 准确率为 98.7%(错误率 1.3%)。

现在让我们用两个卷积层编码一个非常简单的 CNN,并用它来创建一个土豆分类器!

  • 第一卷积层nn.Conv2d具有 3 个输入通道32 个输出通道,其内核大小为 3×3。输入通道的数量 3 对应于 RGB 图像通道。输出通道数只是一个选择。
  • 第二卷积层具有 32 个输入通道和 64 个输出通道,以匹配前一层的输出通道数量。
  • 注意第 9 行和第 10 行,在卷积层之后,我应用了一个F.max_pool2d和一个F.relumax-pooling 操作将通过选择每个 2x2 像素的最大值来缩小图像。这样得到的图像只有一半大小。 ReLU 是一个非线性激活函数,正如我在本系列的1 课中提到的。
  • 在大小为 2 的两次卷积和最大池化之后,得到的特征图的大小是原始图像的 1/4。我将使用 64x64 的图像,因此这将产生一个 16x16 的特征地图。我可以添加更多的卷积层,但在某些情况下,当特征图已经很小时,通常,下一步是使用平均池,通过计算平均值将特征图减少到 1x1。注意,因为我们有 64 个通道,结果张量将有一个(batch-size, 64, 1, 1)的形状,然后在应用最后的线性层之前,它将被整形为(batch-size, 64)
  • 最终线性层的输入大小为 64,输出大小等于要预测的类别数。在这种情况下,将是 4 种类型的土豆。

注意:理解一切工作原理的一个好方法是使用 Python 调试器。您可以将import pdbpdb.set_trace()包含在 forward 方法中。然后你可以一步一步地移动,检查每一层的形状,给你一个更好的直觉或者帮助调试问题。

3.使用 fastai2 让您的生活更轻松

当有工具可以让你的生活更轻松时,不值得浪费时间为深度学*管道的每一步编码。这就是为什么在这个故事中我将使用 fastai2 库 来完成大部分工作。然而,我将使用前一节中定义的基本 CNN 模型。请注意,fastai2 使用 PyTorch,并使每个步骤的定制变得容易,这使它对初学者和高级深度学*实践者和研究人员都有用。

下面 12 行代码就是 fastai2 中的整个深度学*流水线,使用的是上一节定义的 BasicCNN !你可以在这里找到本课所有代码的笔记本。

  • 1-6 行:定义了 fastai 数据块。我在这个这个故事中谈到了 fastai 数据块的话题。图像块类别块表示数据加载器将有一个图像类型的输入和一个类别类型的目标。
  • 2 行和第 3 行:get_xget_y是给出处理输入和目标的函数的参数。在这种情况下,我将从 pandas dataframe 中读取列“file”(每个图像文件的路径)和“id”(马铃薯的类型)。
  • 第 4 行:splitter是一个参数,可以告诉你如何将数据分成训练集和验证集。这里我使用了RandomSplitter,默认情况下随机选择 20%的数据来创建验证集。
  • 第 5 行:添加了一个变换,将图像的大小调整为 64x64。
  • 第 6 行:包括标准化和图像放大。请注意,我使用的是默认的扩充。fastai 的一个优点是,大多数情况下,您可以使用默认设置,而且它很有效。这对学*非常有好处,因为在开始做有趣的工作之前,你不需要了解所有的细节。
  • 第 8 行:data loaders 对象被创建。(train_df是带有fileid列的数据帧,查看完整代码此处)。
  • 第 9 行:创建一个类数为 4 的 BasicCNN 模型的实例(注意dls.c自动指示类数)。
  • 第 10 行:定义了 fastai Learner 对象。这是您指出模型、损失函数、优化器和验证指标的地方。我将使用的损失函数是nn.CrossEntropyLoss,正如在上一课中所述,它是超过两个类别的分类问题的首选。
  • 第 12 行:使用一次循环学*率时间表(学*率快速增加到lr_max,然后逐渐减少)和 0.01 的权重衰减来训练模型 30 个时期。

经过 30 个时期的训练,我用这个简单的 CNN 模型获得了 100%的验证准确率!这是训练和验证损失看起来像一个训练过程:

培训和验证损失在培训过程中的演变。图片由作者提供。

就是这样!如果你按照代码操作,你现在可以非常准确地识别 4 种土豆。最重要的是,这个例子中没有任何东西是关于土豆的!您可以对几乎任何想要分类的东西应用类似的方法!

家庭作业

我可以给你看一千个例子,但如果你能自己做一两个实验,你会学到最多!这个故事的完整代码可以在这个笔记本上找到。

  • 和上一课一样,试着玩学*率、时期数、重量衰减和模型大小。
  • 不使用 BasicCNN 模型,尝试使用在 ImageNet 上预训练的 Resnet34(看看 fastai cnn_learner)结果如何比较?可以尝试更大的图像尺寸,激活 Kaggle 内核上的 GPU,让训练更快!(Kaggle 免费为您提供 30h/周的 GPU 使用量)
  • 现在,使用数据集中的所有水果和蔬菜训练模型,并查看结果。该数据集还包括一个测试集,您可以使用它来进一步测试训练好的模型!

和往常一样,如果你通过实验创作出了有趣的动画笔记本,那就在 GitHub、Kaggle 上分享吧,或者写一个中型故事!

结束语

Learn AI Today 系列第三个故事到此结束!

欢迎在评论中给我一些反馈。你觉得什么最有用,或者什么可以解释得更好?让我知道!

你可以在下面的故事中了解更多关于我的深度学*之旅!

[## 我的 3 年历程:从零 Python 到深度学*竞赛高手

自从 2017 年开始学* Python 以来,我一直遵循的道路是成为一名独自参加 Kaggle 比赛的大师…

towardsdatascience.com](/my-3-year-journey-from-zero-python-to-deep-learning-competition-master-6605c188eec7) [## 我在 Kaggle 上的两年旅程:我如何成为竞赛大师

描述我的旅程和策略,我遵循成为一个竞赛大师与个人金牌

towardsdatascience.com](/my-2-year-journey-on-kaggle-how-i-became-a-competition-master-ef0f0955c35d)

感谢阅读!祝您愉快!

今日学*人工智能 04:时间序列多步预测

原文:https://towardsdatascience.com/learn-ai-today-04-time-series-multi-step-forecasting-6eb48bbcc724?source=collection_archive---------21-----------------------

今天学 AI

创建和训练 1D 卷积神经网络,以预测用 Mackey-Glass 方程生成的混沌时间序列的多个未来时间步长

Unsplash 上绘制的 Beamer 照片。

这是 学艾今日 系列的第 4 个故事!如果你还没有,一定要检查以前的故事。

[## 今天学*人工智能:03 —使用卷积神经网络的马铃薯分类

在 PyTorch 中创建一个 CNN 模型,并使用 fastai2 训练它识别土豆的类型,以简化代码

towardsdatascience.com](/learn-ai-today-03-potato-classification-using-convolutional-neural-networks-4481222f2806)

你将从这个故事中学到什么:

  • 创建一个混乱的时间序列
  • 按顺序拆分系列以提供给模型
  • 定义和训练用于时间序列预测的 1d 卷积神经网络
  • 使用 fastai2 数据集学*器

1.创建一个混乱的时间序列

在一个混沌系统中,初始条件的一个非常小的变化就可能导致完全不同的结果。在这样的系统中,即使你知道描述未来的确定性方程,你也无法准确预测未来。为什么?因为你需要一台无限精确的计算机和无限精确的初始条件。事实上,这根本不可能。这就是为什么天气预报只在短期内准确。随着时间的推移,随着动态和统计模型的改进以及计算能力的提高,它们也在不断改进。然而,不可能长期准确地预测每天的天气,因为它是一个混沌系统。

为了生成一个混沌时间序列,我将使用 Mackey-Glass 方程,参数在这里描述。Python 代码如下所示:

前 500 个样本的结果如下:

麦基-格拉斯时间序列。图片由作者提供。

请注意,时间序列中有一个模式,但有很多变化,无法在很长一段时间内可靠地预测。

2.按顺序拆分系列以提供给模型

用上面的代码生成的数据是一个很长的序列。为了训练一个模型,我将把数据分成 500 个元素的较小序列。输入数据将是前 100 个元素,而目标数据(未来预测)将是剩余的 400 个元素。此外,数据的前 2/3 将用作训练数据,而后 1/3 用作验证数据

注意:处理时间序列时,选择序列的最后一部分进行验证通常是个好主意,特别是当您想要预测未来时。否则,该模型可能会学*自相关,并产生误导性的好结果,这将在应用于未来时“打破”实践。

上面的代码简单地运行长序列,并创建如上所述的输入和目标序列,按照模型所需的格式重新整形。对于图像数据和通常的 2D 卷积神经网络,张量以形状[批量大小,通道,行,列]组织。这里对于 1D 卷积神经网络,也是一样的,但是去掉了最后一个维度。并且实际上有可能具有多个时间序列的输入(表示为几个通道)。

3。定义和训练模型

我为这个实验定义的模型是一个 1D 卷积神经网络,它有 3 个卷积层,然后是 ReLU 激活和批量归一化,最后是平均池和两个线性层。基本原理类似于 2D 卷积层。每个连续的层都可以捕获越来越复杂的数据模式。批量标准化有助于使训练更快、更稳定,即使在非常深的神经网络中。你可以看这个 10 分钟的视频,吴恩达解释了为什么 Batch Norm 有效。

还注意到,在最后一个线性层之前,我使用了一个下降(第 26 行)。漏失(在第 10 行中定义,概率为 0.5)通常是一种成功的正则化方法。它只是随机删除特征图中的一些元素,使数据每次都略有不同。以一幅图像为例。丢弃就像删除图像的一些像素。最有可能的是,您仍然可以识别图像中的对象,因此模型必须学*它,从而产生更健壮的模型。

注意:在推断时间内,辍学是不活跃的。这也是你需要在运行推理之前调用model.eval()的原因之一,否则会应用 dropout。

使用 fastai Datasets类很容易创建数据加载器,然后使用 fastai Learner将数据加载器与模型结合起来。学*者类处理训练和预测。

  • 在上面的代码中,数据集是通过给出一个项目列表和一个函数来定义输入和其他目标而创建的(第 1 行)。我之前将序列和目标定义为张量xy(这里是完整代码),因此我只需要从这些张量中选择元素。你可以在文档中阅读更多关于 fastai Datasets的信息。
  • 如您所见,在第 5 行中,我使用一个周期学*率时间表训练模型 20 个时期(学*率上升,直到达到max_lr,然后逐渐衰减)。fastai 提供的又一个好特性!

在训练过程中,下表打印了结果,您可以看到随着训练的进行,训练和验证损失逐渐下降。

训练进展表。图片由作者提供。

如上表所示,列车损失高于验证损失有几个原因。在这种情况下,一个可能的原因是仅用于培训的辍学本身的使用。你可以试着运行没有脱落的代码,检查一下是不是这样!

现在模型已经定型,让我们计算验证的预测。Learnerget_preds方法可以如下使用:ye_valid, y_valid = learn.get_preds().注意,我不需要调用model.eval(),因为 fastai get_preds已经处理了这些细节。然而有一点需要记住。

有了结果,是时候可视化预测了!这是最好玩的部分。下面的代码创建了一个包含 12 个验证序列的可视化图像。

结果的可视化。绿线代表真实数据,红线代表预测。输入数据显示在垂直黑条上。图片由作者提供。

如上图所示,模型预测(红色)从紧跟目标(绿色)开始,但随着时间的推移,性能开始下降。事实上,如果我沿着时间轴绘制均方差(MSE ),结果如下:

MSE 超过 400 的预测序列。图片由作者提供。

由于数据的混乱性质,这是意料之中的。这个结果还能进一步提高吗?可能是的,我在准备这个故事时尝试了几种不同的选择,真正的学*是查看代码并进行自己的观察和实验。

家庭作业

我可以给你看一千个例子,但如果你能自己做一两个实验,你会学到最多!这个故事的完整代码可以在 这个笔记本 上找到。

  • 尝试改变模型、超参数、优化函数、输入和输出序列的大小,看看它如何影响结果。
  • 将该模型应用于你可能感兴趣的某个问题的另一个时间序列。成绩如何?

和往常一样,如果你通过实验创作出了有趣的动画笔记本,那就在 GitHub、Kaggle 上分享吧,或者写一个中型故事!

结束语

今日学 AI系列第四个故事到此结束!

欢迎在评论中给我一些反馈。你觉得什么最有用,或者什么可以解释得更好?让我知道!

你可以在下面的故事中了解更多关于我的深度学*之旅!

[## 我的 3 年历程:从零 Python 到深度学*竞赛高手

自从 2017 年开始学* Python 以来,我一直遵循的道路是成为一名独自参加 Kaggle 比赛的大师…

towardsdatascience.com](/my-3-year-journey-from-zero-python-to-deep-learning-competition-master-6605c188eec7) [## 我在 Kaggle 上的两年旅程:我如何成为竞赛大师

描述我的旅程和策略,我遵循成为一个竞赛大师与个人金牌

towardsdatascience.com](/my-2-year-journey-on-kaggle-how-i-became-a-competition-master-ef0f0955c35d)

感谢阅读!祝您愉快!

Git 和 GitHub 入门:初学者完全教程

原文:https://towardsdatascience.com/learn-basic-git-commands-for-your-data-science-works-2a75396d530d?source=collection_archive---------26-----------------------

照片由扬西·敏Unsplash 上拍摄

动手教程

关于如何在 15 分钟内使用 GitHub 的完整教程

Git 作为一个版本控制系统

G 它是全球开发者普遍使用的开源版本控制系统。版本控制系统帮助开发人员对开源项目做出贡献,并检查代码的版本。git 是由 Linux 创始人 Linus Torvald 开发的,作为帮助 Linux 开发人员开发和维护代码的工具。所以,git 是 Linus Torvald 支持主项目 Linux 的第二个项目。

git 作为版本控制工具的图示(图片由作者提供)

上图清楚地向我们解释了 git 作为版本控制工具的功能。它让我们可以处理单个文件,而不是有各自版本的多个文件。使用基本版本(许多文件)往往是不可跟踪和非结构化的。我们也无法跟踪我们的修订。但是,使用 git,任何修订或更改都将被记录在 git 系统上,作为用户,我们可以根据需要返回到文件的某个版本。从 git 日志中,我们可以从头开始跟踪我们工作中的修订。

作为协作工具,git 将电子邮件、短信、聊天等基本协作方式移植到协作系统中。对于一个有很多人参与的大项目来说,基本的协作往往是不完整的、误解的、糟糕的日志,并且效率低下。

Git 是为基于文本的数据设计的,例如代码、书籍、论文、文章等

许多公司和开源项目都在使用版本控制系统来管理他们的项目,比如谷歌、脸书、微软、推特、LinkedIn 等等。所以,这就是为什么我们需要学*基本的 git 命令,为我们未来在科技公司的工作和职业生涯服务。

如何安装 Git

在你的电脑上安装 git 似乎很容易。但是这也取决于你的操作系统。对于 Windows 用户,你可能需要去 git 官方网站下载它。幸运的是,对于 Linux 用户,只需打开我们最喜欢的终端并运行如下脚本:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git

安装完成后,一切都会好的。用下面的命令检查我们的 git 版本。

**# Check our git version**
git --version

Git 版本 2.17.1(图片由作者提供)

配置

第一步,在深入讨论 git 及其环境之前,我们需要配置我们的 git。我们向它提供一个用户名电子邮件

**# Setup the git configuration**
git config --global user.name "your-username"
git config --global user.email "your-email"

设置 git 配置(图片由作者提供)

查看我们的 git 全局配置(图片由作者提供)

Git 作为版本控制工具

对于我们第一次接触 git,让我们创建一个目录,例如,在我的例子中是 git-stk ,然后移动到那个目录中。然后,从**git init**开始我们的练*。重要的是注意到**git status**将打印我们的作品的状态,如目录或文件有任何变化。只要我们没有做任何修改,命令**git status**打印出来还没有提交

git 的初始化(图片由作者提供)

那么,**git init**是什么意思呢?简单来说,这个命令将创建一个包含几个文件夹和文件的**.git**文件夹,比如**hooks****info****objects****refs****config****description****HEAD**,以便跟踪我们的工作。我们的更改日志将被记录在那里。

中的目录。git 初始化后的 git 文件夹(图片由作者提供)

为了与 git 命令进行交互,让我们创建一个新的 markdown 文件,即 README.md ,其中填充了句子“readme . MD 文件的第一行”

创建一个新文件与 git 交互(图片由作者提供)

让我们用**git status**命令检查当前状态。它打印出红色标记,表明我们对 git-stk 中的文件夹或文件做了任何更改。这也意味着我们的改变还没有被标记出来。我们处于 git 生命周期中的修改状态。

README.md 在修改状态下的状态(图片由作者提供)

要在文件 README.md 中标记我们的更改,请运行**git add**命令。要查找修改状态和暂存状态之间的状态差异,只需再次运行**git status**。绿色标记表示我们的更改已被标记,现在我们处于暂存状态。

README.md 运行**git add**命令后的状态(图片由作者提供)

我们的 README.md 文件已被标记,但尚未录制。记录我们的更改,就像我们在使用 Microsoft Word 或其他带有**git commit**的工具时一样,然后是提交消息。

README.md 已提交(图片由作者提供)

Git 生命周期

到目前为止,我们已经在 git 环境中进行了实验,并分配了 git 命令。但是现在,我们将深入探讨 git 的生命周期。我们之前所做的就是我们在 git 生命周期中看到的。git 生命周期分为四个状态,即:

  • 已修改:尚未标记任何更改。我们可以在这里做任何事情,操作文件,创建或删除一个新的文件夹,以及其他事情
  • Staged :我们的变更已经被标记但还没有被记录的状态
  • 提交:成功的文件夹或文件被记录到我们的中。git 文件夹

Git 生命周期(图片由作者提供)

继续追踪我们的日志

你能想象如果我们在文件夹中犯了一些错误吗?我们可以倒退回上一次提交或两次提交吗?答案是我们当然可以。Git 保存我们的更改(提交),如果我们的工作需要,我们可以去任何地方。好了,下面是你必须知道的新 git 命令:**git log**。我们将记录我们的整个提交,所以我们可以很容易地跟踪我们的工作或提交。

在之前的提交中,我们创建了一个名为 README.md 的文件。现在,我们将使用 git logs 命令修改该文件并检查其日志。首先用句子“readme . MD 文件第二行”添加我们的 README.md 文件然后提交。只需遵循并运行基于下图的脚本。

修改我们的 README.md 文件并提交它(图片由作者提供)

检查状态,直到它打印出“Nothing to commit”。这意味着我们已经提交了所有的更改。好了,为了跟踪我们的工作(提交),我们只需运行**git log**,它将打印作者(用户名和电子邮件)、修改的日期和时间、消息和 SHA。

  • **git log --oneline** :打印一行日志
  • **git log --graph** :用作者的线漂亮的展示日志
  • **git log --author=<username>** :显示某个作者的日志(如果我们和很多用户一起工作)
  • **git log <filename>** :显示某个文件的日志

我们必须尽可能清晰简单地添加提交消息,因为这将有助于我们跟踪我们的工作

在 git 中提交日志(图片由作者提供)

git 上必须知道的命令之一是**git diff**。它帮助我们比较分支、特定文件或整个目录上的提交。例如,我们将比较两次提交。

图案是**git diff <SHA-before> <SHA-after>**。用我们提交的 SHA 输入**<SHA-before>****<SHA-after>**

使用**git diff**比较 git 中的两个条件(图片由作者提供)

根据输出,我们在 README.md 文件中获得了关于第一次提交和第二次提交之间差异的信息。有用吧?

向后移动到以前的状态

作为人类,我们并不完美,对吗?有时我们会犯一些影响其他事情的错误。这也适用于科技公司,例如作为一个数据科学团队,我们正在为我们的机器学*流程开发新功能。但是发现了一个 bug。我们必须从作品的开始追溯,逐行检查代码。Git 通过向后移动特性简化了我们的工作。我们可以根据发现 bug 之前的提交来跟踪,而不是从作品的开头开始。

在 git 上有三个命令可以向后移动。它是用来满足我们的需要的。

  • **git checkout**:它就像一台时光机,我们可以将项目文件的状态还原到指定的时间。然而,这是暂时的。这些不存储在 git 数据库中
  • **git reset**:这个命令让我们无法回到未来。我们将丢失我们的提交。重置 git 日志后,我们需要编写一个新的提交
  • **git revert**:将采用过去已有的文件条件,然后将它们与上次提交合并

我们可以调用 git checkout 命令在每次提交时检查文件条件。使用命令***git checkout master***从过去返回

git 中**git reset**命令的实现(图片由作者提供)

当我们决定使用 git reset 时,有三个选项可供选择。这取决于我们的问题和我们想去的州。让我们来看看它们,并在您的计算机上试用它们!

  • **git reset --soft**:将文件恢复到暂存状态
  • **git reset --mixed**:将文件恢复到修改状态
  • **git reset --hard**:将文件恢复到提交状态

Git 重置命令(图片由作者提供)

**git reflog**用于恢复项目历史。我们可能熟悉显示提交列表的**git log**命令。**git reflog**与此类似,但显示的是**HEAD**改变的时间列表。

执行**git reflog**来恢复项目历史(图片由作者提供)

让我们再次修改我们的 README.md 文件来显示**git checkout**命令。我们只是用“readme . MD 文件的第三行”添加一个新行。之后,像上一步一样,将其添加到提交状态。

在 git 中提交日志(图片由作者提供)

请记住,我们已经用**git reset**恢复了我们的文件,它删除了我们的最后一次提交。然后,使用 git checkout,我们将在每次提交时检查文件条件。

记住:直到这一步,我们只有三次提交

在 git 中提交日志(图片由作者提供)

为了检查我们的第一次提交,我们使用了指针。按照说明理解**git checkout HEAD**是什么意思。它帮助我们跟踪 README.md 文件中的内容,每次提交时,是否有任何更改?什么样的变化?

使用**git checkout**命令检查提交(图片由作者提供)

要了解标题上 波浪号(~)脱字符(^) 的功能,请看下图。它让我们可以执行工作中每个分支上的每个提交。

标题上的代字号和插入符号(图片由作者提供)

Git 作为协作工具—分支

当谈到 git 作为一个版本控制工具时,我们只是谈论 git 如何帮助我们保持文件的版本。但是,现在我们将 git 作为一个协作工具来讨论。

Git 中默认的分支名称为**master**

在我们的代码上开发新特性时,建议创建一个新的分支。让主分支作为我们的主要代码。如果我们的功能已经完成,并且没有发现错误,就与主分支合并。

在这种情况下,我们将创建一个名为 new_branch 的新分支,向 README.md 文件添加两行新行。

***git checkout***命令也用于移动和创建分支

README.md 文件中新建一个分支并添加一行(图片由作者提供)

new_branch 分支上添加对提交状态的修改,并返回到主分支。查看 README.md 文件。我们在 new_branch 上的修改没有应用到主文件,因为我们在不同的分支上工作。它保持我们的主要代码干净和安全。

签出到主文件,并在 README.md 文件中添加新的一行(图片由作者提供)

查看 git 日志,现在您会在红色标记处发现一个新分支。是的,这表明在另一个分支上有任何提交。

使用 git 中的新分支提交日志(图片由作者提供)

我们刚刚创建了一个新的分支并提交给它。现在,我们必须将该分支合并到主分支,并清除所有冲突。

Git 作为协作工具—合并

当我们和一个团队一起工作时,我们必须有许多分支和它的特性。我们的下一个任务是合并这些分支,并管理其中的冲突。它是由**git merge**指挥的。当主文件上的文件被选为主文件或代码时,我们必须将另一个分支合并到主文件中。所以我们要去找师父!如果我们的代码冲突,作为主要开发人员或项目负责人,我们的任务是选择是删除代码还是添加到主代码中。

两个分支代码由**======**分开

将 new_branch 合并到主服务器并管理冲突(图片由作者提供)

在我们的合并正确完成后,只需查看 git 日志。瞧啊。我们已经将 new_branch 合并到 master。我们的主人现在干净了!这是在 git 上合并的简单任务。

在 git 中提交日志(图片由作者提供)

显示文件的每一行是什么版本和作者最后修改的,我们可以使用**git blame**命令。

**git blame L <start><end>**

README.md 文件中的最后修改版本和作者(图片由作者提供)

Git 作为协作工具—远程存储库

在谈论了很多关于 git 作为版本控制工具之后,接下来我们讨论 git 作为通过远程存储库的协作工具。有许多平台提供服务,让我们的脚本与人们或我们的团队协作,例如 GitHub、GitLab、Bitbucket 等。对于本教程,我们使用 GitHub。因此,您可能需要注册您的帐户,并按照说明操作!

请登录 GitHub 页面并创建一个新的存储库。选择您自己的回购名称,然后单击 创建存储库 创建新的存储库。

在 GitHub 中创建一个新的资源库(图片由作者提供)

我们的目标是将本地存储库上传到 GitHub 上的远程存储库。因此,在创建了新的存储库之后,我们可以将我们的远程存储库链接(通过 SSHHTTPS )复制到终端并运行**git remote add**命令。它将创建一个到远程存储库的新连接。

运行**git push**将我们的本地存储库上传到远程存储库。这个命令需要两个参数***<remote-name>******<branch-name>***

  • ***<remote-name>*** : 一个远程名字,比如,**origin**
  • ***<brach-name>*** :分支名称,例如**master**(默认)

管理远程存储库并上传到其中(图片由作者提供)

摘要

我们现在就在这里,编码员!总结一下我们的教程,友好的开发者只是创建了一个简单的备忘单来帮助我们理解我们已经学过的基本 git 命令。了解更多关于 git 备忘单的信息!

笔记

你可能想要得到这个基础 git 教程的简历,只需访问我的 GitHub 页面https://audhiaprilliant . GitHub . io/git-version-control-system/。如果能和世界各地的人一起分享和学*,那该多好啊!谢谢!

参考

1阿诺姆,吉特 (2020),https://docs.github.com/

通过检测垃圾邮件学*贝叶斯定理

原文:https://towardsdatascience.com/learn-bayes-theorem-by-detecting-spam-df092cd68d6a?source=collection_archive---------16-----------------------

应用贝叶斯定理预测 SMS 消息是垃圾消息的概率的教程。

本教程有 2 个部分:
1。从条件概率推导贝叶斯定理
2。预测短信是否是垃圾短信

第一部分:从条件概率推导贝叶斯定理

条件概率

我在这里更深入地讨论了条件概率

条件概率告诉我们,给定另一个事件,一个事件发生的概率。

P(A|B) = P(A ∩ B) / P(B)是发生A的概率,在我们知道B发生的情况下。计算方法是AB都发生的概率除以B发生的概率。

但是如果我们想找到相反的情况,在发生A的情况下B的概率,会怎么样呢?

有时条件概率在这方面很有用。但是有时候用贝叶斯定理更简单。

贝叶斯定理

维基百科说,

概率论统计学贝叶斯定理(或者贝叶斯定律或者贝叶斯法则)描述了事件概率,基于可能与该事件相关的条件的先验知识。

推导贝叶斯定理

我们从条件概率的公式开始,它可以写成“A 给定 B”或“B 给定 A”。

注意,直观上,P(A∩B)P(B∩A)是一样的(见下文)。这意味着我们可以互换使用它们。以后请记住这一点。

我们从第一个公式开始,P(A|B)= P(A∩B) / P(B)

多两边乘P(B)。这将抵消右边的P(B)分母,留给我们下面的。

我们现在能看到的(如果我们交换左右两边,会更容易)是P(A∩B)= P(A|B) * P(B)。我们将把它插回到我们的第二个原始配方中(原始配方如下)。

得到这个公式(修改如下)。

也就是贝叶斯定理。

我们现在将使用贝叶斯定理来尝试和预测 SMS 消息中的垃圾邮件。

2 部分:预测 SMS 消息是否是垃圾消息

贝叶斯推理在垃圾邮件检测中有着悠久的历史。我们将在这里用一些真实的数据进入基础。

在我们的例子中,probability an SMS is spam, given some word,等于probability of the word, given it is in a spam SMS,乘以probability of spam,再除以probability of the word

Kaggle 下载数据集,并在数据帧中检查。

import pandas as pd
df = pd.read_csv('sms-spam.csv', encoding='ISO-8859-1')
df.head(3)

原始 CSV 中的列没有意义。因此,我们将把有用的信息移到两个新列中,其中一列是布尔值,表示该短信是否是垃圾短信。

仅供参考,“火腿”的意思是“不是垃圾邮件”。

import numpy as npdf['sms'] = df['v2']
df['spam'] = np.where(df['v1'] == 'spam', 1, 0)df.head(3)

现在删除旧列。

df = df[['sms','spam']]
df.head()

好多了。

检查记录的数量。

len(df)
#=> 5572

那太多了。让我们使用 25%的原始数据样本。

sample_df = df.sample(frac=0.25)
len(sample_df)
#=> 1393

那更好。

现在将数据分成两个独立的数据帧,一个是垃圾邮件数据帧,一个是火腿数据帧。

spam_df = sample_df.loc[df['spam'] == 1]
ham_df = sample_df.loc[df['spam'] == 0]print(len(spam_df))
print(len(ham_df))#=> 180
#=> 1213

我们将使用 sklearn 的 TFIDF 矢量器来观察垃圾邮件中的一些重要单词,并选择一个插入我们的公式中。

from sklearn.feature_extraction.text import TfidfVectorizervectorizer_spam = TfidfVectorizer(stop_words='english', max_features=30)vectorizer_spam.fit(spam_df['sms'])
vectorizer_spam.vocabulary_

我们需要在公式中选择一个单词,所以我将选择单词“win ”,尽管尝试使用其他单词也很有趣。

现在我们需要计算公式的不同部分。

P(W|S) =单词“win”出现在垃圾消息中的概率
P(S) =垃圾消息整体的概率
P(W) =单词“win”出现在消息整体中的概率

说出我们的话。

word = 'win'

计算P(W|S)

word = 'win'spam_count = 0
spam_with_word_count = 0for idx,row in spam_df.iterrows():
    spam_count += 1

    if word in row.sms:
        spam_with_word_count += 1probability_of_word_given_spam = spam_count / spam_with_word_count
print(probability_of_word_given_spam)#=> 10.0

计算P(S)

probability_of_spam = len(spam_df) / (len(sample_df))
print(probability_of_spam)#=> 0.12921751615218952

计算P(W)

sms_count = 0
word_in_sms_count = 0for idx,row in sample_df.iterrows():
    sms_count += 1

    if word in row.sms:
        word_in_sms_count += 1probability_of_word = word_in_sms_count / sms_count
print(probability_of_word)#=> 0.022254127781765973

现在把所有这些放在一起。

(probability_of_word_given_spam * probability_of_spam) / probability_of_word#=> 58.064516129032256

嘣。这告诉我们,如果一条短信包含“赢”这个词,那么这条短信有 58%的概率是垃圾短信。

结论和下一步措施

在生产垃圾邮件检测系统中,我们需要对语料库中的每个单词进行上述计算,然后组合概率。

我们可能还想包括其他功能,如单词组合,消息长度,标点符号等。

这会让这篇文章变得很长。

如果你感兴趣,这里有一篇 PDF 文章,解释了组合多个单词结果的几种方法。

我希望这给了你一些使用贝叶斯定理的洞察力和实践经验,即使我们只是触及了表面。

5 分钟 5 步学会初学 SQL!

原文:https://towardsdatascience.com/learn-beginner-sql-in-5-steps-in-5-minutes-c44c47fa39a1?source=collection_archive---------11-----------------------

学*科技行业最受欢迎的技能!

图片来自 Pixabay图米苏

介绍

所以你想学 SQL?太好了,你应该!

你知道数据分析师数据工程师 和数据科学家最想要的第三个技能是什么吗?**

在本文中,我将向您解释如何以最简单的方式使用 SQL 进行查询。但首先,让我定义几个术语…

如果这是你喜欢的那种东西,成为第一批订阅 我的新 YouTube 频道在这里 !虽然还没有任何视频,但我会以视频的形式分享很多像这样的精彩内容。感谢大家的支持:)

定义

****行,也称为记录,是代表单个实体的属性(变量)的集合。例如,一行可能代表一个住院病人,可能有年龄、体重、身高等属性/变量…

一个是具有相同属性(相同变量)的行的集合。对我帮助最大的是把一个表格想象成一个 Excel 表格。

表格示例

****查询是对数据库表或表组合中的数据的请求。使用上面的表格,如果我想找到所有年龄大于 23 岁的患者,我将编写一个查询

如何编写 SQL

因为这是给初学者的教程,如果你想从一个表中提取数据,我将向你展示如何编写一个查询。

一个基本查询有五个组件:

  1. 选择(必填)
  2. 从(必填)
  3. 其中(可选)
  4. 分组依据(可选)
  5. 排序依据(可选)

其结构如下:

****SELECT**
   [column_name_1],
   [column_name_2],
   [column_name_n]
**FROM**
   [table_name]
**WHERE**
   [condition 1]
**GROUP BY** [column_name] 
**ORDER BY** [column_name]**

让我们带回我的例子作为参考:

1.选择(必填)

****SELECT 确定要从给定的表中提取哪些列。例如,如果我想提取名称,那么我的代码应该是这样的:

**SELECT Name**

一个巧妙的技巧是,如果你想拉所有的列的,你可以使用星号——见下文:****

**SELECT ***

2.从(必填)

****FROM 确定您要从哪个表中提取信息。例如,如果您想要获取患者的姓名,您可能想要从名为 patient_info 的表中获取数据(见上文)。代码看起来会像这样:

**SELECT
   Name
FROM
   patient_info**

这是您的第一个函数查询!让我们来完成另外 3 个可选步骤。

3.其中(可选)

如果您想选择年龄超过 23 岁的患者的姓名,该怎么办?这就是我们的用武之地。 WHERE 是用来过滤您的表的语句,就像您在 Excel 中使用过滤工具一样!

获取 23 岁以上患者姓名的代码在左边。右侧显示了一个可视化表示:

如果想要满足两个子句的患者姓名,可以使用。例如,查找年龄超过 23 岁且体重超过 130 磅的患者的姓名。

**SELECT
   Name
FROM
   patient_info
WHERE
   Age > 23
   AND
   Weight_lbs > 130**

如果您想要满足两个子句之一的的患者姓名,您可以使用。*例如,查找小于 22 岁或大于 23 岁的患者的姓名。*****

**SELECT
   Name
FROM
   patient_info
WHERE
   Age < 22
   OR
   Age > 23**

4.分组依据(可选)

GROUP BY 正如它所说的那样— 它将具有相同值的行分组到汇总行中。它通常与计数、最小值、最大值、总和、AVG 等聚合函数一起使用。

让我们用下面的例子:

如果我们想得到每个病人去医院的次数,我们可以使用下面的代码并得到下面的结果:

5.排序依据(可选)

ORDER BY 允许您根据特定属性或多个属性按升序或降序对结果进行排序。我们来举个例子。

**SELECT
   *
FROM
   patient_info
ORDER BY
   Age asc**

“ORDER BY Age asc”意味着您的结果集将按年龄以升序对行进行排序(参见上图中的左表)。如果你想按降序排列(上图的右边表格),你可以用 desc 代替 asc

结论

这就是如何构造一个查询!你刚刚学到了科技界最受欢迎的技能之一。我将在下面提供一些链接,在那里你可以练*你的 SQL 技能。尽情享受吧!

感谢阅读!

如果你喜欢我的工作,想支持我…

  • 成为第一批订阅我的新 YouTube 频道这里的人之一!虽然还没有任何视频,但我会以视频的形式分享很多像这样的精彩内容。
  • 也是这里第一批关注我的 Twitter 的人之一。
  • LinkedIn 上关注我这里
  • 在我的邮箱列表** 这里报名。**
  • 看看我的网站,terenceshin.com

** [## 解决 SQL 代码挑战

加入 700 多万开发人员在 HackerRank 上解决代码挑战的行列,这是为…

www.hackerrank.com](https://www.hackerrank.com/domains/sql) [## SQL 练*、练*、解答-w3 资源

SQL 代表结构化查询语言,它是一种 ANSI 标准的计算机语言,用于访问和操作…

www.w3resource.com](https://www.w3resource.com/sql-exercises/)**

免费从顶尖大学学*数据科学

原文:https://towardsdatascience.com/learn-data-science-from-top-universities-for-free-ee3387ad88ac?source=collection_archive---------22-----------------------

在哪里可以找到麻省理工学院、斯坦福大学和哈佛大学的免费讲座、研讨会和完整课程

瓦西里·科洛达在 Unsplash 上拍摄的照片

我最*在读一本名为《超学*》的书。加速您的职业生涯,掌握硬技能并智胜竞争对手。这本书讲述了一种学*技巧,可以让你在看似不可能的时间框架内学*新的技能,甚至全新的科目。根据这本书,超学*是“获取技能和知识的一种策略,这种策略是自我导向的和强烈的”。

这本书的作者斯科特·H·杨利用超级学*完成了一项著名的个人挑战。他给自己设定的挑战是在 12 个月内学*完麻省理工学院(T2 麻省理工学院)的计算机科学课程。他在 2012 年成功完成了挑战,并录制了一个关于他经历的 ted 演讲,名为“你能用 2000 美元获得麻省理工学院的教育吗?”。

你能花 2000 美元得到斯科特·H·杨的麻省理工教育吗

斯科特·H·杨只用了 2000 美元就完成了他的挑战,因为麻省理工学院通过一个在线门户网站免费提供他们的大部分课程材料和讲座。

麻省理工学院并不是唯一一所这样做的大学。许多排名靠前的美国大学免费提供课程、讲座和其他学*材料。在这其中,有大量的材料高度且经常直接适用于学*数据科学、机器学*和人工智能。

许多排名靠前的美国大学免费提供课程、讲座和其他学*材料。

我之前写过一篇名为如何免费学*数据科学的文章,与更传统的大学学位课程相比,它提供了一种替代的、免费的学*途径。然而,如果你是通过更传统的基于讲座的课程学得更好的人,或者想通过更深入地钻研相关主题来补充本课程,以下免费资源可以提供帮助。**

麻省理工学院,开放式课程

麻省理工学院是现代计算机领域教学和研究的领先机构之一。2001 年,该大学推出了自己的开放式课件平台。它的目标是让绝大多数课程的课堂笔记、*题集、考试和视频讲座都可以在网上免费获得。

这里有大量数据科学相关主题的资料。我个人最喜欢的包括:

数据、模型和决策——课程大纲,麻省理工学院开放式课程

哥伦比亚大学,应用机器学*

Andreas C. Muller 是流行的 Python 机器学*库 Scikit-learn 的核心开发人员之一,也是哥伦比亚大学的研究科学家和讲师。

每年他都在网上发布他的‘应用机器学*’课程的所有材料。本课程的所有幻灯片、课堂讲稿和家庭作业都可以在这个 Github repo 中获得。

回购中的材料实际上是我见过的最好的,涵盖了在现实世界中实际应用机器学*的领域。除了涵盖从数据探索和清理到模型评估和调优的机器学*过程的所有方面,还涵盖了 Github、单元测试和持续集成。当你在现实世界中应用机器学*时,这些都是非常重要的方面。

哥伦比亚大学“应用机器学*课程”的时间表快照

斯坦福大学,研讨会

斯坦福工程学院定期在网上免费提供一些精选的研讨会。有一些精选的数据科学相关研讨会,包括“人机交互”和“机器人和自主系统”。你可以通过这个链接找到它们。

此外,斯坦福大学将许多研讨会和讲座上传到它的 Youtube 频道——你可以在这里找到。频道上有大量涵盖数据科学、机器学*和深度学*的视频。

斯坦福大学免费研讨会

哈佛免费在线课程

哈佛大学在其网站上发布了一系列完全免费的在线课程。这些课程大部分是由 edX 主办的,所以你也可以选择支付少量费用来获得每门课程的认证。

这里有一些非常优秀的学*数据科学的课程。这些包括以下几个最佳选择,尽管还有很多其他的:

哈佛大学免费在线课程

伯克利,MOOCs

加州大学柏克莱分校也出版了一系列关于 edX.org 课程。有一些优秀的数据科学相关课程,包括:

网上有如此丰富的学*数据科学的免费资料。本文涵盖了一些来自高排名大学的更传统的基于讲座的方法。为了获得更多的替代资源,我之前在这里发布了我的前 5 个。

感谢阅读!

我每月发一份时事通讯,如果你想加入,请通过此链接注册。期待成为您学*旅程的一部分!

以正确的方式学*数据科学

原文:https://towardsdatascience.com/learn-data-science-the-right-way-92fc9437e64e?source=collection_archive---------23-----------------------

发痒的地图集,直接跳进去😉

来源:弗拉巴哈拉unsplash (CC0)

要错过数据科学的迷人歌曲,你必须生活在岩石下。作为“21 世纪最性感的工作”,数据科学激起了人工智能、机器学*、魔法等的想象,正在彻底改变我们与信息互动的方式。对于临时技术人员、经验丰富的数据专业人员或任何介于两者之间的人来说,将数据科学技能添加到你的技能清单中会非常有利可图。但是你应该从哪里开始呢?

如果你像我一样,问谷歌“如何学*数据科学”会让你陷入混乱。在“ 8 个简单步骤”中吹嘘掌握数据科学的文章与致力于艺术的整个博士项目相矛盾。Python 爱好者和 R 狂热分子争夺“数据科学的最佳计算语言”,而 Julia 进行了一次突袭。数据库技术吹捧高效的存储和检索方法,如 MySQL、Postgres、MongoDB 和 Cassandra,以与位/字节进行交互,但因应用程序而异。Tableau 最*被 SalesForce 以将*160 亿美元收购,然而嵌入式绘图库和前端框架使得数据可视化变得免费容易。

因为有这么多固执己见、见解深刻的声音回荡在数据科学领域,所以我不会因为给乐队增加一件乐器而感到内疚。我的建议?无论何时何地,只要你能,就加入进来。在这个旅程中没有完美的地图,只有你的。通过分析把自己从麻痹中解放出来,把自己的手弄脏,宝贝!

来源:经由狮门辣身舞 g

不,不是那种肮脏的🕺.

在本文中,我将分享我的建议,告诉你如何抛弃 atlas,进入数据科学的奇妙世界。我将讨论我最喜欢的开源资源、平台和框架(天哪!)它可以启动你的旅程,或者让余烬继续燃烧。如果这次在新冠肺炎的隔离让我们学到了什么,那就是在线教育和电子学*工具在提升普通技术人员方面有着无限的潜力。没有比这更好的时间来学*新技能或磨练你的爱好了。

在开始之前,让我们快速定义一下“数据科学”到底是什么:

数据科学家(名词):比任何软件工程师更擅长统计学,比任何统计学家更擅长软件工程的人。— 乔希·威尔斯通过推特

不管你对这个定义的感觉如何,它说明了围绕数据科学的模糊光环。一般的软件工程师真正了解多少统计学?一般的统计学家做过多少工程项目?我个人觉得无所谓。该领域不断变化,包括新技术,淘汰过时的技术,并鼓励新兴领域的加入。所以,只要你致力于追求学*和建设,我相信你会走得很好。

还是不相信我?看一看数据科学的招聘信息,你会发现基本要求从高级算法设计博士到任何拥有 HS 文凭和相关经验的人都有。10 年使用特定技术的基于项目的工作与另一个初级职位——拥有数学学位的大学毕业生——的竞争。熟练掌握 Python、R、Scala、COBOL 等。与任何有使用代码模糊性经验的人相比。

我最*参加了一个会议,会上才华横溢的 Dick De Veaux 用这张图(或类似的图)传达了他对数据科学的定义。

来源:数据科学维恩图经由德鲁·康威 (CC0)

De Veaux 教授交替使用“预测分析”、“机器学*”、“数据科学”和“人工智能”等术语,并用有趣的例子证明他的松散命名法是正确的,这些例子证明了这门学科是多么模糊。我喜欢这个图表,因为它为灵活性和灵活性留下了空间:如果你对一个主题感到舒适,只需深入另一个主题。

我绝对不是想抹杀那些拥有高等学位和相关经验的数据科学家的惊人成就。然而,我确实想激励越来越多好奇的数据专业人员建立他们的信心,并向一些伟大的资源学*。我们来看看吧!👇

我没有💰来推广这些资源,我希望您在使用我的建议来提升您的数据科学技能时发现真正的价值!

免费在线资源

有大量的资源可供任何对启动或维持数据科学职业感兴趣的人使用。在众多的在线课程、游戏化课程、GitHub 知识库和媒体文章中,有一些是我最喜欢的:

Hackr.io

这个出色的平台查询他们的用户社区,以众包和聚合各种主题的课程,包括数据科学机器学*,以提供免费的在线学*。根据您的技能水平和对特定主题的兴趣,您可以定制搜索查询和/或加入他们的社区以接收新产品的更新。

互联网档案馆

互联网档案馆提供免费书籍、电影、软件、音乐、网站以及几乎所有主题的更多内容。我的一个同事最*建议互联网档案馆填补一些隔离时间,我没有回头!你可以下载和/或查阅高质量的人工智能/人工智能教材,以继续你的研究或进入新的主题。

Python 课程

Python 是迄今为止我最喜欢的编程语言,由于它的简单性和无限的社区支持,我总是对免费提供的高质量 Python 资源感到惊讶。如果您是这个领域的新手,Python 是介绍编程概念的一种很好的语言;如果你是个老手,学*或更新 Python 基础知识只会提高你的市场竞争力。

虽然我还没有完成下面列出的所有免费课程的(你也不应该!),这些是一些最受欢迎和评价最高的资源,值得您关注📚。

十大免费 Python 编程书籍

我一直随身带着一个 1TB 的外置硬盘,里面装满了编程教科书、PDF、备忘单等等。虽然它已经过时了,特别是在如此容易访问云的情况下,我还是喜欢把一切都组织在一个物理驱动器上。无法解释。无论如何,许多📖 👇在我的💾。

*** [## 十大免费 Python 编程书籍——下载 PDF 或在线阅读

每个程序员都喜欢免费的电子书和免费的课程,如果它们来自著名的技术书籍出版商,比如…

www.java67.com](https://www.java67.com/2017/05/top-7-free-python-programming-books-pdf-online-download.html)

R 的漩涡

如果你曾经上过在线编程课程,你可能会对基于浏览器的代码和实际开发环境之间的脱节感到沮丧。 Swirl 在 R 控制台上,按照您自己的节奏,以交互方式教您 R 编程和数据科学。你只需要下载 R,设置 RStudio,安装漩涡,就可以开始了!作为一个对 Python 无比熟悉的人,这个工具真的帮助我扩展了我的视野与 R studio(R 开发人员的首选 IDE)的舒适性。

Git & GitHub

如果之前没用过 GitHub, git 启动😉!对于那些正在构建很酷的自动化脚本/ ML 项目的独立数据科学家来说,GitHub 提供了一个存储和共享代码的好地方。如果你在一个团队中工作,你很可能使用过类似的工具来协作和管理产品代码。 GitHub 是一个在线平台(虽然桌面应用程序可以下载),用于创建存储库和共享代码;git 生活在你的终端里,与 GitHub 的沟通要高效得多。

对于新手,我推荐 Git Started with GitHub 作为入门速成班,包括安装。如果您熟悉 GitHub,但想更好地了解终端,请查看这个 Bash Shell 教程以了解更有效的命令行要点。对于侧重于版本控制的基于浏览器的场景,请尝试 katacoda 。如果您想跳过教程,直接进入脚本,请查看参考指南:

[## 我离不开的 4 个 Git 脚本

2005 年,Linus Torvalds 创建了 Git 来取代他开发的专有分布式源代码控制管理解决方案

opensource.com](https://opensource.com/article/20/4/git-extras)

如果所有这些看起来有点初级,而你只是在寻找一个复*/备忘单供你使用,那么克隆这个库。

发展环境和集装箱化

如果你曾经看过 MTV 婴儿床,那么这个参考就是给你的:一个 IDE(集成开发环境),很像主卧室,是魔法发生的地方。无论您选择哪种语言,您的 IDE 确实为任何专业或个人代码开发设定了基调,并且应该进行定制以满足您独特的编码需求。数据科学项目依赖于多种语言、框架和平台无缝协作;我推荐 Visual Studio 代码来简化你的操作。他们为有效的数据科学设置提供了极好的操作指南👇。

[## Visual Studio 代码中的 Python 和数据科学教程

本教程演示了如何在公共数据科学中使用 Visual Studio 代码和 Microsoft Python 扩展…

code.visualstudio.com](https://code.visualstudio.com/docs/python/data-science-tutorial)

您可能也会对容器化开发环境的 Docker 感兴趣。如果你计划构建和共享代码,但 Docker 不是你想要的,我强烈推荐像 KubernetesAnaconda Cloud 这样的软件。

建议:如果你有几分钟空闲,花 12 分钟学* Docker 基础知识,提升你的下一个项目。

(舞台上由人扮的)静态画面

数据可视化是任何数据科学部署的关键组成部分,负责将数据洞察转化为可消费的观察。一个糟糕的可视化可能会浪费你所有的辛苦工作来提取、清理和建模数据;相反,一个伟大的 viz 可以催化可操作的见解,建立信任,激发好奇心,激励项目,等等。

Tableau 可以很容易地安排美丽的指标,只受你的想象力。很难感受到灵感?看看他们的“今日之见”。如果你是 Tableau 的新手,他们有一些很棒的资源可以让你在他们的平台上快速提升。

截至 2020 年 4 月,Tableau Desktop(付费版)提供 90 天的试用期,以增强你的技能。Tableau Desktop 和 Tableau Prep(也包括在内)提供了更广泛的数据连接、嵌入、流水线等。

[## Tableau 电子教学

培训获得 90 天免费使用访问代码 2020 电子学*开始学*随着全球经济复苏,数据技能将…

www.tableau.com](https://www.tableau.com/learn/training/elearning)

如果你已经是一个 Tableau 的狂热用户,看看禅宗大师(显然是同卵双胞胎兄弟)并准备好让你的袜子被打掉。

LeetCode

寻找相关的资源来帮助你通过技术面试?LeetCode 为提高技能和拓展专业领域提供实践培训。无所不知的“在线法官”会对您的算法的强度和效率提供即时反馈,以促进定制体验。我用 LeetCode 准备那些需要现场编码或者伪代码的数据科学面试。他们有一个高级版,UX 稍好,面试问题更有针对性,由公司组织。

几乎免费的在线资源和书籍

如果你能摆动它,这些资源是廉价的和沉浸式的。这是我做过的一些投资,在接触新项目和/或与学生合作时,我会经常提到它们。

简陋的包裹

Humble Bundle 是一家数字店面,提供不同的游戏、软件、电子书等。为了便宜。他们的目标是使发展收益民主化,并为慈善事业做出贡献,同时“以优惠的价格向客户提供精彩的内容”。他们通常会有价值数千美元的机器学*/人工智能教科书,价格不到 20 美元。是的,你没听错。基本上,你可以选择支付多少钱给开发商,慈善机构等等。查看他们当前的产品:

[## 简陋的书籍捆绑:人工智能与机器学*

更多精彩的电子书给你。我们与摩根&克莱普尔联手推出了我们的最新产品包!获得像必需品一样的电子书…

www.humblebundle.com](https://www.humblebundle.com/books/artificial-intelligence-machine-learning-morgan-claypool-books)

数据营

从您舒适的浏览器中学*数据科学!DataCamp 是可扩展的,并不断向其课程中添加新的课程/技能。你可以选择不同的职业轨迹根植于 Python、R 和 SQL,跟随行业专家完成不同规模的项目。当你完成免费试用时,你通常可以通过让他们在购买前流点汗来获得一笔特殊的再营销交易——我通过电子邮件获得了 60%的折扣,只需等待几天就可以购买年度套餐。此外,一旦你完成职业轨迹,你将获得一个徽章,可以添加到你的 LinkedIn 个人资料中🙌。

专业提示:看一下 DataCamp 免费的备忘单——它们组织得很好,值得在技术面试和编码挑战中密切关注。

用 Python 自动化枯燥的东西

这本书不仅仅为初学者提供了 Python 技巧,它还改善了你与逻辑的关系。使用 Python 基础知识,用逻辑学家的眼光重新想象平凡的任务并开始处理“东西”。我毫不夸张地向每一位与我共事的非技术经理/主管/副总裁推荐这本书,以获得立竿见影的效果。

[## 用 Python 自动化枯燥的东西

“编程最好的部分是看到机器做一些有用的事情的胜利。用…自动化枯燥的工作

automatetheboringstuff.com](https://automatetheboringstuff.com/)

ACM —资源和专业网络

一旦你对展示你的数据科学肌肉感到更舒服了,你可能会想与其他志同道合的技术专家交流和分享。GitHub、Medium、StackOverflow 和其他网站是开始与人联系的绝佳场所,但可能会让你渴望更专业、更有针对性的内容。加入 ACM,或计算机械协会,向“世界上最大的教育和科学计算协会”提供会员资格。这就像数据科学的演讲会。

你也可以访问他们的数字图书馆,它包含在会员费用中,以搜索任何计算主题的相关资源。

奥莱利学*— Safari 在线访问

这是付费资源的最高端,所以如果你是数据科学的新手,或者可以忙于我提到的其他课程和教科书,那么推迟可能对你最有利。也就是说,如果你是一名学者或者迫切需要前沿参考资料,这绝对适合你!

[## 奥莱利在线学*-奥莱利媒体

你可以找到来自美国前首席数据科学家 DJ Patil、通用电气前副主席 Beth Comstock 的内容…

www.oreilly.com](https://www.oreilly.com/online-learning/individuals.html)

专业提示: Safari 在线学*是 ACM 会员的额外福利!所以,如果你想让你的钱最大化,ACM 会员是一个不错的选择。

训练营

号称课程饱和的速成编程训练营正在席卷全球。如果你一直在研究数据科学和阅读在线课程,你可能会遇到一两个训练营,它们可以快速提升你的数据科学地位,从零到英雄。但是训练营值这个价钱吗?

我认为旅程比目的地更重要,但我有偏见。我在明尼苏达州明尼阿波利斯的一个著名的数据分析/数据科学训练营担任助教,致力于为学生提供尖端的技术技能。这绝对是一种“一英里宽,一米厚”的方法,可以进入数据科学的多面世界。我们一路上涵盖了如此多的相关主题(6 个月的周期),这迫使每个学生接受模糊性,并专注于他们解决问题的方法,而不是找到“完美”的解决方案。这是因为对于不断变化的问题,没有完美的解决方案,只有高效、美观、可持续且有发展空间的解决方案。

这并不适合所有人。但是,如果你付出努力并致力于学*,你将获得无价的技能、专门的项目组合、解决任何问题的开源工具以及自信。在我看来这是非常棒的东西。

我会走下讲台,推荐三部曲教育:他们提供了一系列可以兼职或全职完成的训练营选项。在你花钱之前——要求旁听一堂课,检查全部课程,和以前的学生和/或教授交谈,等等。为了更好地了解你可以期待的投资回报率。

[## 课程|明尼苏达大学数据可视化和分析训练营

在过去的十年里,数据爆炸几乎改变了每个行业。无论是在制造业,医疗保健…

bootcamp.umn.edu](https://bootcamp.umn.edu/data/curriculum/)

重复一下:这些训练营赚钱,因为我们大多数人没有资源来建立和审查我们自己的沉浸式课程。如果你想要一个快速的旅程,充满补充资源和支持来保持你的动力,那么训练营可能是正确的选择。

社区

中等

既然你正在读这篇文章,你已经对媒体很熟悉了。给自己一个鼓励!我偶然发现了 Medium,并对出版物的广度和深度感到震惊。如果您还没有,请成为会员并更新您的首选项,以便 Medium 可以为您提供出色的自定义内容。

我最喜欢的媒体出版物是面向数据科学的。在@here 上发表文章是我的个人目标,所以我很自豪能够通过他们出版团队的审核并获得批准。如果你有一些有趣的事情要说,或者只是你有太多的时间,那就把笔写在纸上,或者把手指放在键盘上?在我鼓起勇气将我的内容公之于世之前,我只是一个长期的鉴赏家,而且我没有回头。

以下是我喜欢的几个相关出版物:

专业提示:如果你对自己的在线状态感到满意,但又想保持经常更新、低维护量的内容,那么读一读 Nat Torkington 每日收集的 4 个短链接

公共数据集

不接触数据,就当不了数据科学家。如果你足够幸运,可以获得公司数据并得到批准,那就去做吧!否则,在使用安全的私有数据移动之前,分析清理过的公共数据并不可耻。

建立工作关系网

我在科技行业担任数据科学顾问。我真诚地相信,没有比从私营部门的专家那里学*新技术、方法和策略更好的环境了。就我个人而言,我尽可能多的与招聘方/公司沟通和面试,强化自己的软技能,拓展自己的人脉。

如果您有兴趣与我联系讨论,请在 LinkedIn 上给我留言。我很乐意连接!

结论

数据科学太模糊了,无法构建成功的完美路线图。随着需求的发展,你也将拥抱新兴的技术、方法、策略和定义行业的个性。总是有探索和进步的机会,推动你的边界,将另一种工具纳入众所周知的工具带。

概述的资源足以启动您的数据科学之旅。如果你走得更远,它们应该有助于激励你或者给你指明一个新的方向。

这篇文章中的所有内容都深受我的学生和其他教学人员的影响。非常感谢他们激励我继续学*,尤其是现在!

如果你对我想要添加的资源有任何建议,我很乐意在下面的评论中听到你的意见。感谢阅读!***

边听边学数据科学

原文:https://towardsdatascience.com/learn-data-science-while-listening-a555811b0950?source=collection_archive---------44-----------------------

不知道从哪里开始播客?这是三个吸引你的播客片段。

Unsplash 上由 Mohammad Metri 拍摄的照片

播客是一种有趣的方式来学*你喜欢的话题的新东西。播客主持人必须想办法用简单的术语解释复杂的想法,否则没人会理解🙂在这篇文章中,我展示了几个小插曲来让你开始。

这里有几个你可能会感兴趣的链接:

- [Labeling and Data Engineering for Conversational AI and Analytics](https://www.humanfirst.ai/)- [Data Science for Business Leaders](https://imp.i115008.net/c/2402645/880006/11298) [Course]- [Intro to Machine Learning with PyTorch](https://imp.i115008.net/c/2402645/788201/11298) [Course]- [Become a Growth Product Manager](https://imp.i115008.net/c/2402645/803127/11298) [Course]- [Deep Learning (Adaptive Computation and ML series)](https://amzn.to/3ncTG7D) [Ebook]- [Free skill tests for Data Scientists & Machine Learning Engineers](https://aigents.co/skills)

上面的一些链接是附属链接,如果你通过它们进行购买,我会赚取佣金。请记住,我链接课程是因为它们的质量,而不是因为我从你的购买中获得的佣金。

如果你错过了我之前关于播客的文章:

[## 数据科学家的五大应用

我如何跟上最新的研究?我如何记住领域中的复杂概念?在…的帮助下

towardsdatascience.com](/top-5-apps-for-data-scientists-dc8b66886560)

你应该通过偏导数获得博士学位吗

部分衍生自 Twitter 的标志

偏导数由数据科学超级极客主持。他们谈论我们周围世界的日常数据。

这一集对于正在考虑攻读博士学位的学生来说可能会很有趣,在这一集里,克里斯从他个人的角度谈到了获得博士学位。他谈到他年轻时对数学不感兴趣,但对历史更感兴趣。大学毕业后,他受够了学校教育,不打算继续攻读博士学位。他向加州大学戴维斯分校递交了申请,面临着一项挑战。喜欢听他的冒险。

Tim 是一名两届博士退学者,现居北卡罗来纳州,是一名数据科学家,他有一个专门讨论这个话题的网站:我应该获得博士学位吗?

让冒险开始吧…

基于线性离题的核技巧和支持向量机

线性离题标志来自 SoundCloud

凯蒂和本通过有趣的(通常非常不寻常的)应用程序探索机器学*和数据科学。

在这一集,凯蒂和本解释什么是支持向量机(SVM)的核心技巧。我真的很喜欢 SVM 背后的重型机械的简单解释。不知道最大边距分类器是什么?然后先听支持集最大间隔分类器

最大边缘分类器试图在左侧和右侧之间找到一条线(决策边界),以便最大化边缘。这条线被称为超平面,因为它通常包含更多的二维。决策边界在支持向量之间。

基于支持向量的二元分类问题

内核绝招是什么?

当二维空间中有 3 个点时,可以用一种方式排列这些点,使它们不能被一条线分开。你总是可以通过把它们放在三维空间中来把它们分开。引入新尺寸的一种方法是计算离原点的距离:

z = x^2 + y^2

这将推动离原点更远的点,而不是更靠*原点的点。下面我们来看一个视频。这也使得线性分类器成为非线性的,因为它将边界映射到更低维度的空间。

来自 giphy 的具有多项式内核可视化的 SVM

当维度多于样本时,我们总是可以用一个超平面来分隔这些点——这是 SVM 背后的主要思想。多项式核是 SVM 常用的核之一(最常见的是径向基函数)。二次多项式核寻找两个特征之间的所有交叉项,这在我们想要对交互进行建模时非常有用。

内核招数是什么?爆米花加入了军队,他们让他成为了核心

数据怀疑论者的人工智能决策

来自 https://dataskeptic.com/的数据怀疑论者标志

数据怀疑论播客的特色是采访和讨论与数据科学、统计学和机器学*相关的话题。

在本集的中,Dongho Kim 讨论了他和他在 Prowler 的团队如何建立一个基于概率建模、强化学*和博弈论的自主决策平台。目的是让人工智能系统能像人类一样做出好的决策。

我们对贝叶斯过程最感兴趣,而不是深度学*

在你走之前

Twitter 上关注我,在那里我定期发布关于数据科学和机器学*的消息。

Unsplash 上由Courtney hedge拍摄的照片

在实践社交距离的同时学*数据科学

原文:https://towardsdatascience.com/learn-data-science-while-practicing-social-distancing-9c335006ceb9?source=collection_archive---------19-----------------------

在保持社交距离的同时学*数据科学

我是如何帮助我的朋友充分利用在家的时间的

和我的朋友一起研究数据科学

更多在家的自由时间

在全球疫情时期,适应新的生活常态是一项挑战。在澳大利亚,我们的情况比许多其他国家好得多,至少目前是这样。然而,孤立仍然会让你沮丧。坚持“呆在他妈的家里”运动,我们都有更多的空闲时间。许多人试图通过学*新技能来明智地利用他们的独处时间。

学*数据科学的想法

为了这篇文章的目的,我把我朋友的名字改成了化名,以保护无辜的人。任何一起阅读的父母可能会认出我从流行的儿童电视节目 Bluey 中使用的名字😜

Bluey 别名来自两集:

1.布鲁伊的爸爸决定将布鲁伊和她的妹妹宾果重新命名为“丹尼斯”和“沙拉兰达”,这一集叫做“戏弄”。

2.布鲁和宾戈在《老奶奶》一集中扮演老奶奶“珍妮特”和“丽塔”。

我的一个朋友沙拉兰达是一名会计师,她告诉我她正考虑在疫情期间做一些研究。我问她在想什么学*?她不是很确定,但数据科学是她清单上的事情之一。我告诉她,如果她真的想学*,我很乐意帮助她。至少我可以教她足够多的东西,让她知道这是不是她想进一步追求的东西。

其他人加入进来

当我提出这个建议后,另一个朋友珍妮特也加入了进来。她是一名化学家和数据分析师。这些年来,她一直对学*数据科学感兴趣,并开始学*几次 python 编程。然而,生活阻碍了她,她没有继续下去。所以她问她是否可以和沙拉兰达一起学*。我说她当然可以,人越多越好。

因此,我向更多的朋友发出了做一些数据科学研究的邀请,并有更多的人接受了邀请。

我的朋友丹尼斯是一名律师,在她的工作中经常涉及技术。她想更多地了解数据科学到底是什么。对她来说,这个想法更多的是为了更好地理解数据科学,以便她在与数据科学家和技术合同互动时能够更轻松地完成工作。

另一个说愿意加入我们小学*小组的人是丽塔。她是一名研究科学家,刚刚完成生理学博士学位。我们以前在数据科学项目上合作过,并参加了政府举办的开放数据黑客马拉松 GovHack。

Rita 已经开始自学数据科学的某些方面,但是她有三个孩子,还有许多其他事情要做。所以她很难保持学*的动力。

小组学*

网上有很多自学的数据科学课程。然而,我从未发现我对一门客观的在线课程负有责任。你也不能总是在网络课程中提问。当我开始学*数据科学时,我希望有一群朋友一起学*。

和一群朋友一起学*数据科学似乎是完美的解决方案。我们可以互相问责。我总是发现,如果别人依赖我,保持对一个项目的热情会更容易。和朋友一起学*也比独自学*有趣得多。因此,即使我们目前不能面对面地见面,我们也可以分享这个项目来提高我们的技能。

我发现在过去,当我和朋友一起做活动时,比如学*一项新技能,我会比平时更多地看到他们。这项活动为接触和保持联系提供了动力。希望一起学*能让我们在这个几乎不可能面对面交流的困难时期保持理智和联系。

在学*复杂的概念时,有不同的观点也会很有帮助。来自不同人的问题可能会引发其他人的理解。因此,希望我们能够帮助彼此获得数据科学方面的新技能。

小组想从学*数据科学中获得什么

  • 更好地理解什么是数据科学。
  • 工作中使用的编程技巧。
  • 通向新事业的可能途径。

我的数据科学背景

我已经做了几年的数据科学家。我的背景是神经科学,我通过免费的在线课程过渡到了数据科学。你可以在我之前的故事“我如何在 6 个月内从零编码技能成为数据科学家”中了解我是如何进入数据科学的。我的旅程证明,如果你真的想学*数据科学,并全身心投入,你可以不读特定的大学学位。

数据科学有点像艺术,有许多方法可以达到预期的结果,对于如何解决问题也有不同的思想流派。我绝不是数据科学各个方面的专家。我不认为有人真的是。我期待在我们的旅程中学*一些新的数据科学技能。

在我们进行的过程中开发课程将会响应我的朋友们想要学*的数据科学方面。所以,任何读到这些帖子的人请不要把它们当成福音,这只是我们尽最大努力一起学*新东西。我将尽我所能提供我的专业知识,但也将根据需要利用其他资源。

我们将从哪里开始

虽然我的朋友不一定要在数据科学领域寻找职业,但我仍然很高兴能帮助他们学*并实现他们的目标。

为了让我们走上正轨,我想我会在媒体上记录我们的进展。我们已经建立了一个私人的 facebook 聊天平台,在那里我发布了包含这些课程的我的媒体文章的草稿链接。然后,我的朋友们在一个共享的谷歌文档中写下他们对问题和练*的答案。这样我可以看到他们在解决问题时的进展。然后在周末我会出版这个故事。

学数据科学的朋友背景千差万别。我不希望任何人在我们学*课程的过程中掉队,所以我们将从头开始。第一课假设没有编程或统计知识。

首先,我们将着手学* SQL。这样,我们将知道如何从数据库中访问数据。所以请继续关注第一课,在 SQL 中创建一个表并用数据填充它。

时机

作为一个小组,我们决定每周完成一节课。这似乎是一个时间框架,既能让我们保持势头,又不会给家庭生活带来不必要的压力。当我们学*更复杂的课程时,我们可能需要修改时间框架。尽管有目标是好事。

如果你喜欢,就跟着去吧

如果你想加入我们,试着在这段强制的时间里提高自己的技能,请随时关注我帖子里的练*。希望我们都能玩得开心,学到新东西:)

除了数据,我的另一个爱好是绘画。你可以在 www.katemarielewis.com 找到我的野生动物艺术

社交距离学*数据科学的所有课程(LDSWSD)

[## Ldswsd -走向数据科学

阅读《走向数据科学》中关于 Ldswsd 的文章。共享概念、想法和代码的媒体出版物。

towardsdatascience.com](https://towardsdatascience.com/tagged/ldswsd)

如何使用 SQL 创建数据表

原文:https://towardsdatascience.com/learn-data-science-while-practicing-social-distancing-lesson-1-making-a-table-using-sql-13fb9678282b?source=collection_archive---------13-----------------------

在保持社交距离的同时学*数据科学

使用儿童节目 Bluey 中的一个例子,演示了如何使用 SQL 制作一个表格并用数据填充它

本·怀特Unsplash 上拍摄

介绍

在我之前的故事中,我谈到了我和我的朋友们如何以及为什么决定在这次全球疫情期间学*数据科学,同时保持社交距离。我们都喜欢能够利用我们的时间做一些建设性的事情的想法。我很高兴能够通过这个项目与我的朋友保持联系,并帮助他们提高数据科学技能。

自从我们一周前开始以来,这个团队已经发生了微小的变化。一个人不得不退出,因为她有了一个全新的婴儿。这是一个在每天洗澡和学*数据科学之间的决定,洗澡理所当然地赢了😃

另一方面,自从我发表了本系列的第一篇文章介绍我们将如何以及为什么在自我隔离的同时学*数据科学,我得到了人们的惊人回应。我的几个朋友问他们是否可以加入。所以现在我们是一个 8 人小组,所有女性一起学*技术技能。

我甚至有几个朋友的朋友问他们是否可以加入,但我决定只限于我亲自认识的人。主要是因为我不想让我的其他任务影响到团队的规模。然而,我欢迎任何人和每个人跟随我发布的课程,并尝试学*数据科学。

也许如果你是那些喜欢学*的人之一,你可以和你的一些朋友成立自己的学*小组。然后,如果你们在任何一个概念上陷入困境,你们将能够互相帮助,并且你们将获得让彼此保持在正确轨道上的好处。我建议在你的社交媒体上打个电话,看看有没有你认识的其他人有兴趣和你一起学*。你永远不知道,你可能会对你得到的回应感到惊讶。我知道我是😊

我要教小组的第一件事是 SQL。在第一课中,我们将练*制作表格并用数据填充它们。我们将使用 CREATE TABLE 和 INSERT INTO 关键字来实现这一点。如果这还不完全有意义,不要担心,在整个课程中它会变得很清楚。

如果你和我们一起学*,这是一个很好的起点。我的目标是在我们完成课程后每周发布一次。敬请关注!

什么是 SQL?

SQL 是一种在数据库中访问、存储和操作数据的语言。它代表结构化查询语言,因为你用它来查询数据库。每种基于 SQL 的语言都有自己的细微差别,但有相同的基本命令。每种语言的细节及其排列方式被称为语法

当学*编程时,我想我能给人们的主要建议是在代码中寻找模式。然后尝试如何修改这些模式,使代码按照您的要求运行。

为什么要学 SQL?

当人们想到数据科学家时,他们往往会专注于机器学*的激动人心的工作。然而,数据科学家花费大部分时间将他们需要的数据转换成他们需要的格式。因此,我认为在学*数据科学时,从头开始并学*如何从数据库中访问数据是很重要的。

许多数据科学课程为学生提供了包含他们需要的数据集的文件。在我看来,这种做法对学生有害无益。如果不知道如何从数据库中检索您想要的数据,您将不得不依靠数据工程师来为您完成,或者希望数据集已经以您需要的格式可用。根据我的经验,这种情况很少发生,尤其是当你试图使用一个大数据集的子集时。

背景

什么是数据库?

数据库通常包含一个或多个表。我们给每个表起了一个名字,这样当我们想要查看表中的数据时,就可以访问我们想要的那个表。如果您愿意,可以阅读更多关于数据库的内容,但是为了学* SQL,我们将把它们看作是表的集合。

什么是桌子?

表格包含数据。它用于组织数据,以便于使用。表格中的数据被进一步组织成行和列。描绘表格的一种方式是像电子表格一样。

什么是行?

每行代表一个记录(或条目)。例如,一条记录将包含数据集中每一列的值,这将构成表的行。您可以在下面的示例表中看到一条高亮显示的记录。

什么是专栏?

数据集的要素存储在单独的列中。例如,对于表中的每条记录,一列将包含一个特性值。您可以在下表中看到一个突出显示的列。还需要注意的是,每一列都包含一致数据类型的数据。

什么是数据类型?

数据类型顾名思义就是一种数据。有许多不同的数据类型可以在 SQL 中使用,但最常见的是 varchar、integer 和 float。

varchar —一个长度可变的字符串。字符串是字符的集合,这些字符串在一起构成文本。字符串可以包含字母字符、数字字符和空格。例如,“这是一个包含 33 个字符的字符串”

整数 —整数是没有小数位的整数。因此,此数据类型中不允许有分数。例 6

float —浮点数。因此,数字的分数可以以小数点的形式包含在内。例如 6.45

制作表格时,您需要在每一列中指定数据类型。希望当你看到一些例子时,这将是有意义的。您可以查找 SQL 中使用的所有数据类型,但在本课中我们将只使用 varchar 和 integers。

什么是查询?

SQL 中的查询是对表进行某种操作的语句。它询问一个表的问题,因此命名为查询。它可以用来从表中读取记录、向表中插入记录、过滤表、修改表中的记录、从表中删除记录以及许多其他操作。我们的目标是学*如何编写查询。

在 SQL 中,每个查询通常以分号结尾。这将一个查询与下一个查询分开。

重要说明

SQL 不区分大小写。我将对 SQL 关键字使用大写字母,使它们更加明显。这在许多 SQL 风格指南中是相当标准的做法。

公司或组织内部经常使用风格指南来指定他们希望在所有计算机代码中使用的风格。每种编程语言都有自己的风格指南,因此在组织内部,代码看起来都很相似。团队中的其他人也能够很容易地理解它。

创建表的语法

下面是一个使用 SQL 创建表的查询语法示例。

CREATE TABLE name_of_table(
    first_column_name datatype,
    second_column_name datatype,
    third_column_name datatype,
    fourth_column_name datatype,
    fifth_column_name datatype
);

首先,我们有 CREATE TABLE 语句。CREATE TABLE 是用于创建新表 SQL 关键字。

然后,将该表的结构放在 CREATE TABLE 语句后面的括号中。在括号中,我们用逗号分隔每个列的名称和数据类型。然后,查询以分号结束。

问题 1 :上例创建的表中有多少列?

向表中插入数据的语法

下面是一个使用 SQL 向表中插入数据的查询语法示例。

INSERT INTO name_of_table (
     first_column_name, 
     second_column_name, 
     third_column_name, 
     fourth_column_name, 
     fifth_column_name)
VALUES
    ('column1_value1', 'column2_value1', 'column3_value1', 'column4_value1', 'column5_value1'),
    ('column1_value2', 'column2_value2', 'column3_value2', 'column4_value2', 'column5_value2'),
    ('column1_value3', 'column2_value3', 'column3_value3', 'column4_value3', 'column5_value3')
;

首先我们有 INSERT INTO 语句。INSERT INTO 是一个 SQL 关键字,用于将数据插入到指定的表中。命名表的列名的逗号分隔列表包含在第一组括号中。

然后,我们将值插入到关键字值后面的括号中。每个记录都是一个逗号分隔的列表,在它自己的一组括号内。

然后,查询以分号结束。

问题 2 :使用上面的查询在表中插入了多少行或记录?

现在让我们试一试:

  1. http://sqlfiddle.com/的(或者你可以用 https://www.db-fiddle.com/的,因为我发现 SQL fiddle 最*停机了)
  2. 在左边的框中放入创建表并插入到下面的查询中
CREATE TABLE bluey_nerds (
    name varchar(255),
    occupation varchar(255),
    number_of_children int(255)
);INSERT INTO bluey_nerds (name, occupation, number_of_children)
VALUES
    ('Sharalanda', 'accountant', 1),
    ('Dennis', 'lawyer', 1),
    ('Janet', 'analytical chemist', 0),
    ('Rita', 'scientist', 3)
;

关于数据类型的说明:回到黑暗时代,计算机内存和磁盘空间是昂贵的,所以优化每一位的使用是很重要的(哈哈)。数据类型后面括号中的 255 是关于指定字符限制的,为了节省空间,可以把它变小。我们现在不会担心太多,除了记住你需要为 varchar 和 integer 数据类型包括它,而不是为 floats,255 是最大显示大小。如果你想了解更多,你可以查看 SQL 中关于数据类型的有用资源。

关于数据的说明:这个表包含了我的四个朋友的数据,他们启发我写下了这些关于学*数据科学的帖子。为了保护他们的身份,他们的名字被改了。它们已经根据流行儿童节目《蓝调》中的角色名字重新命名。

Bluey 别名来自两集:

布鲁伊的爸爸决定将布鲁伊和她的妹妹宾果重新命名为“丹尼斯”和“沙拉兰达”,这一集叫做“戏弄”。

布鲁和宾戈在《老奶奶》一集中扮演老奶奶“珍妮特”和“丽塔”。

以防你想知道😜妈妈的生活!

3.单击“构建模式”按钮

4.在右边的框中输入下面的查询

SELECT * 
FROM bluey_nerds;

SELECT 和 FROM 都是不言自明的 SQL 关键字。*用于表示您想要所选表格中的所有内容。

5.您应该会看到一个包含您插入的所有数据的表格:

练* 1 :制作一个包含 5 列 3 行的表格,其中至少有一列是整数数据类型。

练* 2: 制作自己的表,包含 2 列 7 行,其中一列为浮点数据类型,另一列为 varchar 数据类型。

我们是如何学*这一课的

我所有的朋友都很容易地掌握了这一课的概念。他们在一周内第一次就正确地完成了所有的练*和问题。他们中的一些人甚至问了我几个问题,要求我去寻找答案。我认为这是一个很好的迹象!

和我一起工作的小组报告说,他们花了 45 分钟到 1.5 小时完成了这一课。谢天谢地,这正是我想要的时间。我会在学*的过程中不断重新评估课程,以确保我没有让它们变得太难或太容易。我想让他们保持金发,刚刚好。

看到我的朋友们制作的有趣的桌子是一件非常有趣的事情。有关于酒的桌子,关于食物的桌子和关于锻炼的桌子。我认为这是对人们在自我孤立时所做的事情的一个很好的反思。这只是表明我们周围到处都有数据😃

我很高兴我的朋友们对这一课如此投入,并期待着和他们一起进入第二课。如果你和我们一起学*,我希望你喜欢这第一课,并渴望开始下一课。

下一课

2 课将讲述如何使用 SQL 从表中选择数据。我们将练*从表中选择所有数据,根据列名进行选择,以及选择特定数量的记录。此外,我们还将学*如何使用 SELECT DISTINCT,这样我们就不会得到重复的值。

除了数据,我的另一个爱好是绘画。你可以在 www.katemarielewis.com 的找到我的野生动物艺术

社交距离学*数据科学的所有课程(LDSWSD)

[## Ldswsd -走向数据科学

阅读《走向数据科学》中关于 Ldswsd 的文章。共享概念、想法和代码的媒体出版物。

towardsdatascience.com](https://towardsdatascience.com/tagged/ldswsd)

学*梯度下降(带代码)

原文:https://towardsdatascience.com/learn-gradient-descent-with-code-f84eb9a14703?source=collection_archive---------56-----------------------

大量的统计和机器学*涉及将一堆数据转化为新的数字,以做出好的决策。例如,数据科学家可能会使用您过去对 Google 搜索项的出价和结果,来计算新出价的预期投资回报(ROI)。有了这些知识,你就可以对未来出价多少做出明智的决定。酷,但是如果那些 ROI 是错的呢?真的错了吗?

灾难!

幸运的是,数据科学家不只是猜测这些数字!他们使用数据为自己生成一个合理的数字。有很多方法可以做到这一点,一个常见的是梯度下降。根据我们的朋友维基百科,“梯度下降是一种一阶迭代优化算法,用于寻找可微函数的局部最小值。”这没有错,但是你被这个弄糊涂了也是情有可原的。我们来学*一下什么是梯度下降,它是如何工作的(用代码)。

设置和代码

想跟着去吗?本文中复制了基本代码。如果你想完全遵循,从这个 github repo 下载代码。我将对以下包使用 R:

library(tidyverse)
library(broom)
library(glue)

渐变?血统?

在“如何”之前,让我们先了解一下梯度下降是关于什么的。

我们将从两个变量的超级简单数据集开始,xy。这些可以是bidROI的值。我们有兴趣使用这些数据来猜测我们从未见过的x值的y会是多少。

d <- tibble(x = c(0, 1, 2),
            y = c(1, 3, 10))

好吧。为了使用该数据对y进行新的预测,典型的方法是使用普通最小二乘(OLS)回归。听起来不错吧?别担心。这只是一种快速获得下图所示最佳拟合线的方法。

我们是怎么得到这条线的?使用此代码:

model <- lm(y ~ x, d) %>% tidy()
model#> # A tibble: 2 x 5
#>   term        estimate std.error statistic p.value
#>   <chr>          <dbl>     <dbl>     <dbl>   <dbl>
#> 1 (Intercept)    0.167      1.86    0.0894   0.943
#> 2 x              4.5        1.44    3.12     0.198

记住,直线有等式:y = intercept + slope * x。上面的代码告诉我们estimate列中的截距和斜率:intercept = 0.167slope = 4.5。我们会把这些留到以后。

ols_intercept <- model$estimate[1]
ols_slope     <- model$estimate[2]

OLS 回归是一个超级标准的算法。尽管如此,我还是会用它来演示梯度下降是如何工作的,因为你可以将你在这里学到的东西应用到更多的东西上!

想象一下,有人告诉你截距值(0.167),但让你算出斜率。除了认为这很粗鲁,你还会怎么做?我们就试试一堆随机的斜坡吧!

从视觉上看,斜率 5 是这一组中最好的(我们知道它非常接*真实的斜率 4.5)。但是如果我们看不出来呢?斜率为 4 看起来也不错。

这就是所谓损失函数的用武之地。这是一个奇特的术语,表示有一种方法可以用数字来表示你的线与数据的匹配程度。有很多方法可以做到这一点,但我们将使用一个非常标准的方法来处理回归问题:误差平方和。

哇,更多的行话?!这些数据人员让事情变得不容易。别担心。我会解释的。这条线显示了在给定每个x值的情况下,我们对y的预测。这意味着从直线到每个数据点的垂直距离就是我们的错误程度。这个距离称为“误差”(或“残差”)。这些是下图中的红线。

侧面宣传:想进入这样的可视化领域?看看我的博客, [“可视化残差”](http://Visualising Residuals)

把这些红色的部分加起来,我们就能对我们的曲线与数据的吻合程度有一个总体的了解。如果总数很少,我们的产品一定很好。如果总数很大,我们一定做得不好。还有一个额外的细节需要了解。距离计算为y - predicted y。在上面的图中,这些都是正值(因为线在点的下面)。然而,如果线在它们上面,它们将是负的。这很烦人,因为如果我们有很多正面和负面,它们可能会互相抵消。所以解决方法是首先求每个误差值的平方,这样它们都是正的,然后把所有的都加起来。因此,“误差平方和!”

# Calculating the squared errors for a slope of 1
slope_guess <-  1d %>%
  mutate(predicted_y = ols_intercept + slope_guess * x) %>% 
  mutate(error = y - predicted_y) %>% 
  mutate(squared_error = error^2)#> # A tibble: 3 x 5
#>       x     y predicted_y error squared_error
#>   <dbl> <dbl>       <dbl> <dbl>         <dbl>
#> 1     0     1       0.167 0.833         0.694
#> 2     1     3       1.17  1.83          3.36 
#> 3     2    10       2.17  7.83         61.4

这些平方误差的总和就是0.694 + 3.36 + 61.4 = 65.42

现在,我们可以对之前尝试的五行代码重复这一过程:

# Function to add predicted y to data with x and y
add_predicted_y <- function(df, intercept, slope) {
  mutate(df, predicted_y = intercept + slope * x)
}# Function to get sum of squared errors (sse) from the data
sse <- function(y, predicted_y) {
  squared_errors <- (y - predicted_y)^2
  sum(squared_errors)
}# Compute Sum of Squared Errors (sse) for each slope
slope_tests <- tibble(slope_guess = c(1, 3, 5, 7, 10)) %>%
  mutate(sse = map_dbl(
    slope_guess, 
    ~ add_predicted_y(d, ols_intercept, .) %>% 
      summarise(sse = sse(y, predicted_y)) %>% 
      pull(sse)
  ))slope_tests#> # A tibble: 5 x 2
#>   slope_guess    sse
#>         <dbl>  <dbl>
#> 1           1  65.4 
#> 2           3  15.4 
#> 3           5   5.42
#> 4           7  35.4 
#> 5          10 155.

看起来像这样:

我们不用再猜了。5°的斜率绝对是这一组中最好的,因为它的误差平方和最低。

你注意到这个情节了吗?我们只有 5 分,但他们已经有一个 U 型。这不是巧合。存在一个误差最小的“最佳”斜率。当我们选择更远的斜率时,误差会增加。我们的目标是找到最低点!这就像在山谷中迷路,但知道你最有可能在底部找到水,所以走下坡路。

走下山。下山。降梯度!
渐变下降!

梯度下降

是时候认真对待了。如果我们想努力达到最低点,我们该怎么做呢?一种选择是尝试很多很多的斜坡,直到我们有信心到达那里。当然,但这可能会变得非常烦人和耗时。

梯度下降是一种算法,巧妙地为我们找到了最低点。它从斜率的初始值开始。假设我们从斜率 1 开始。然后,它以一系列合理的步骤调整斜率,直到它认为找到了最低点。让我们来看看这是如何发生的。

寻找梯度

尝试一个斜率后,我们希望下一个斜率更接*曲线的底部。方便的是,我们可以利用曲线在当前位置的梯度知道向哪个方向移动。

我们分两步解决这个问题。首先,定义上图所示曲线的方程式。这并不太难。记住,曲线上的一点代表误差平方和。所以曲线的整个方程看起来像这样(其中yx是我们数据中值的向量):

sum((d$y - (intercept + slope * d$y))^2)

我们也知道截距,所以实际上是:

sum((d$y - (0.167 + slope * d$x))^2)

旁注:这是指误差的总组合,称为损失。方程也可以叫做函数。这是我们的损失函数!

其次,我们使用链式法则对这条曲线进行求导(它告诉我们梯度)。如果你不熟悉导数,我会偷偷摸摸地让你弄清楚这是怎么回事,但答案是:

sum( -2 * d$x * (d$y - ( 0.167 + slope * d$x) ) )

代入斜率 1,我们得到:

# Derivative where slope = 1
sum( -2 * d$x * (d$y - ( 0.167 + 1 * d$x) ) )#> [1] -34.998

好,我们有一个很大的负值。这意味着我们在曲线上的一点,向下向右倾斜。为了下降到一个更合适的斜坡,我们需要向右移动!为了直观地理解它,您可以在下图中看到一条紫色的倾斜线:

为了比较,对 9°的斜率重复,我们得到了45.002的正导数。这意味着我们在一个向右上方倾斜的点上,必须向左移动来降低坡度。下图证实了这一点:

好吧,我们已经搞定了一个大挑战。需要休息吗?喝一杯,吃点点心,或者做点瑜伽。当你准备好了,回来开机!

穿越梯度

我们现在知道如何使用导数来告诉我们更高或更低的斜率会更好。现在是行动的时候了。

照片由尼古拉斯·I .Unsplash ( CC0 )拍摄

假设我们需要将正在测试的斜率向右移动(一个更高的斜率)。我们应该走多远?太小的一步,我们会浪费时间。太大的一步,我们可能会在另一边以比以前更大的误差结束。

方便的是,衍生品可以再次帮助我们!当导数真的很大(远离 0)时,意味着我们离一个好的解还很远,可以迈出一大步。随着导数越来越接*零,这意味着我们越来越接*解决方案,可以开始采取更小的步骤。

梯度下降如何使用这个俏皮的想法?它可以从当前斜率移动到current slope — derivative。如果导数是负的,那么从当前斜率中减去它将向上移动(右)。如果导数为正,那么我们向下移动(向左)。离零更远的导数也会导致更大的步长。有道理。然而,仅仅减去导数最终有点疯狂。当我告诉你这不是个好主意时,你必须相信我。为了处理这种情况并更好地控制步骤,梯度下降将导数乘以一个称为学*率的数字。例如,0.1 的学*率意味着下一个测试点将在:current position — 0.1 * derivative

让我们来看看实际情况。我们将使用 1 的初始斜率,0.08 的学*率,并采取 5 个步骤(所有这些都是我挑选出来做一个很好的演示)。

# Setup
initial_slope <- 1
learning_rate <- .08
steps_df <- tibble(step = seq_len(5), slope = NA)
current_slope <- initial_slope# For each step...
**for** (step **in** steps_df$step) {
  # Store the current slope value
  steps_df$slope[step] <- current_slope # Calculate the derivative of the loss
  derivative <- sum(-2*d$x*(d$y - (0.167 + current_slope * d$x))) # Update the slope value based on the derivative and learning rate
  current_slope <- current_slope - learning_rate * derivative
}

steps_df#> # A tibble: 5 x 2
#>    step slope
#>   <int> <dbl>
#> 1     1  1   
#> 2     2  3.80
#> 3     3  4.36
#> 4     4  4.47
#> 5     5  4.49

当绘制误差曲线时,看起来像这样:

注意从第一步到第二步的变化有多大,但是它很快变得越来越小。5 步之后,算法落在一个4.49的斜坡上。难道你不知道吗,这和 OLS 一开始给我们的答案差不多!

知道何时停止

到目前为止还不错,但是走 5 步就能找到正确答案有多幸运呢?!好吧,这不是运气。不幸的是,你不知道现实世界中的正确答案,需要告诉算法什么时候停止。

Unsplash ( CC0 )上由贝琳达·费因斯拍摄的照片

我们想要停止有两个原因,每个原因都有不同的处理方式:

  1. 我们认为我们已经找到了一个很好的答案。
  2. 我们的耐心到期了。

为了停止,因为我们认为我们已经得到了一个好的答案,我们可以设置一个最小的步长。也就是说,一旦算法试图采取一个小于这个最小值的步骤,我们就停止。

为了不考验我们的耐心,我们可以设定我们愿意等待的最大步数。如果算法不停地运行这个数量的步骤,那么就停下来,把计算机还给我们。

这里不多解释了。让我们在下一节看看代码。

将碎片拼在一起

是时候用一个新的稍微大一点的数据集把这些碎片放在一起了:

*# Simulate a larger data set*
more_d <- tibble(x = rnorm(100),
                 y = .6 * x + rnorm(100) + 5)

我得到了 OLS 对这个新数据的估计:

more_d_model <- lm(y ~ x, more_d) %>% tidy()
more_d_ols_intercept <- more_d_model$estimate[1]
more_d_ols_slope     <- more_d_model$estimate[2]

并且如下运行梯度下降:

# Hyperparameters
initial_slope   <- 1
learning_rate   <- .001
minimum_step    <- .0001
maximimum_steps <- 1000# Values to track
slope <- initial_slope
step  <- Inf
steps <- 0# Run Gradient Descent until stopping criterion reached
while((steps < maximimum_steps) && (abs(step) > minimum_step)) {     derivative <- sum(-2 * more_d$x * (more_d$y - (more_d_ols_intercept + slope * more_d$x))) step  <- learning_rate * derivative
  steps <- steps + 1
  slope <- slope - step
}

注意到我在代码中的注释“超参数”了吗?你可能听说过这个,因为 超参数 是所有酷的机器学*孩子都使用的一个词。现在你知道梯度下降是如何工作的,你可以看到它只是指我们可以改变的值,以使我们的算法按照我们想要的方式运行。

结果呢?

glue("OLS slope: {round(more_d_ols_slope, 3)}",
     "Gradient Descent slope: {round(slope, 3)}",
     "Number of steps: {steps}",
     .sep = "\n")#> OLS slope: 0.624
#> Gradient Descent slope: 0.625
#> Number of steps: 26

如果你问我,我会觉得这很酷!

注意。我调整了超参数(再次),所以这个演示工作。事实上,许多学*率并没有导致找到解决方案。这是因为梯度下降对学*速率非常敏感。如果你想进入这个兔子洞,那么你的下一站应该是学*不同的学*率公式,以确保事情顺利进行。我会从搜索“适应性学*率”开始。

如果你愿意,这是另一个快速休息的好时机。准备好了吗?向前!

不止一个参数?

我们已经走了很长一段路,但你还记得吗,我们一直在使用 OLS 拦截器作弊。这是我的错,但这是为了帮助你学*,我发誓!

为了解决这个问题,我们必须回到我们的损失函数(误差曲线)。这里有一个提醒:

sum((y - (intercept + slope * y))^2)

既然我们正在处理两个参数(截距和斜率),我们的损失函数就不像我们看到的图那样是 2D 曲线。它更像一个三维平面。如果这是令人困惑的,不要担心。相反,假设我们现在有两条误差曲线,一条是截距,一条是斜率。我们将在其中的每一个上设置一个点,并尝试同时移动它们。这意味着算法必须计算导数,并为每个步骤!

我们知道斜率的导数是什么样的:

# Derivative of the slope
sum( -2 * x * (y - ( intercept + slope * x) ) )

截距是相似的,但不完全相同:

# Derivative of the intercept
sum( -2 * (y - ( intercept + slope * x) ) )

为了方便起见,我编写了一些函数来计算这些:

*# Functions to compute derivatives*
get_slope_derivative <- **function**(x, y, intercept, slope) {
  sum( -2 * x * (y - ( intercept + slope * x) ) )
}

get_intercept_derivative <- **function**(x, y, intercept, slope) {
  sum( -2 * (y - ( intercept + slope * x) ) )
}

我们所做的大部分与之前相同,但同时针对两个参数。这意味着我们需要:

  • 为每个参数(截距和斜率)创建一个初始值
  • 使用各自的导数对每个参数进行阶跃变化。
  • 改变最小步长停止准则以考虑所有参数。

让我们来看看它的实际应用:

*# Hyperparameters*
initial_intercept <- 0
initial_slope     <- 1
learning_rate     <- .001
minimum_step      <- .0001
maximimum_steps   <- 1000

*# Values to track*
intercept      <- initial_intercept
slope          <- initial_slope
intercept_step <- Inf
slope_step     <- Inf
steps          <- 0

*# Run Gradient Descent until stopping criterion reached*
**while**((steps < maximimum_steps) && (max(abs(intercept_step), abs(slope_step)) > minimum_step)) {

  *# Handle intercept*
  intercept_derivative <- get_intercept_derivative(
    more_d$x,
    more_d$y,
    intercept,
    slope
  )
  intercept_step <- learning_rate * intercept_derivative
  intercept <- intercept - intercept_step

  *# Handle slope*
  slope_derivative <- get_slope_derivative(
    more_d$x,
    more_d$y,
    intercept,
    slope
  )
  slope_step <- learning_rate * slope_derivative
  slope <- slope - slope_step

  *# Increment step*
  steps <- steps + 1
}

最后的结果呢?

glue("OLS intercept: {round(more_d_ols_intercept, 3)}",
     "OLS slope: {round(more_d_ols_slope, 3)}",
     "Gradient Descent intercept: {round(intercept, 3)}",
     "Gradient Descent slope: {round(slope, 3)}",
     "Number of steps: {steps}",
     .sep = "\n")#> OLS intercept: 5.187
#> OLS slope: 0.624
#> Gradient Descent intercept: 5.186
#> Gradient Descent slope: 0.624
#> Number of steps: 44

完美!(给或拿一些四舍五入,让我一个人呆着,好吗)

祝贺和告别

如果你做到了这一步,并且理解了正在发生的一切,那么恭喜你!这并不完全是让人放松的材料,你可能需要一些时间来理解。

这是我要结束的地方。我的最后一个请求是,如果你在此基础上有所发展,请回来分享一些东西。例如,也许你测试适应性学*率。在这里分享你的作品意味着未来的读者可以从你的作品中受益并直接阅读:)

感谢您的阅读,希望您觉得这有用,再见!

了解如何自动化数据分析的基本步骤

原文:https://towardsdatascience.com/learn-how-to-automate-the-basic-steps-of-data-analysis-45e118048172?source=collection_archive---------33-----------------------

你是不是也厌倦了一遍又一遍的写 df.shape,df.info()。

马库斯·斯皮斯克在 Unsplash 上的照片

介绍

df.shape,df.info(),plt.plot(kind='bar '),df['column_name'],你也烦吗?nunique() ,以及其他许多基本函数一次又一次地从任何数据中获得基本的洞察力。我相信你们一定也开始觉得这个过程很单调。阅读完本文后,您将看到如何通过在几分钟内开发自己的 Python 包,在五个基本步骤中实现这些基本功能的自动化。

试映

作者提供的视频

我们开始吧

要开始开发您自己的定制 Python 包,我们需要执行以下步骤:

步骤 1-创建 Python 脚本文件

该文件将包含运行基本数据分析所需的 Python 代码。为了演示,让我们自动执行以下步骤,例如计算-

  • 数据集的维度
  • 所有列的数据类型
  • 唯一值的数量
  • NA 值的百分比
  • 绘制所有分类列的条形图
  • 绘制所有数字列的直方图,以查看数据的分布
  • 制作一个热图来显示空值

以下是我写的代码片段:

作者图片

文件的名字应该是你想要的包的名字,比如 Pandas,Numpy 等等,并且应该是唯一的。在我们的例子中,我将其命名为“Mrinal”。

步骤 2 创建一个 Setup.py 文件

这个文件是安装包所必需的,包含了包名、作者名等信息。该文件位于包含步骤 1 中的 Python 脚本文件和稍后讨论的其他文件的文件夹之外。

作者图片

上面的图像显示了要在 Setup.py 中编写的代码。这里需要注意的一些事情是,您的包的名称应该是唯一的,如果您希望稍后发布到 pypi.org,那么您不能使用网站中已经存在的任何匹配的名称。例如,您不能创建名为“Pandas”或“Numpy”的包,因为它们已经在库中。

步骤 3 创建一个 init。py 文件

这个文件告诉 Python 这个文件夹包含一个包。它应该与步骤 1 中创建的 Python 脚本文件位于同一文件夹中。

作者图片

上面的代码引用了我们在 Python 脚本中创建的类的名称“Insights ”,以及包的名称“Mrinal”。“.”在 Python3 和更高版本中是强制的。

将文件放在正确的文件夹中

对于这一步:

  • 创建一个文件夹,你可以随意命名,因为它不会以任何方式影响安装。让我们把它命名为“我的第一个 Python 包”作为参考
  • 将 Setup.py 文件存储在该文件夹中
  • 在其中创建另一个文件夹,并将其命名为与您给定的包名相同的名称,在我们的例子中,它是“Mrinal ”,每当您想要导入包时,您将编写“From Mrinal import Insights”。
  • 存储名为“Mrinal.py”的 Python 脚本文件和“init”。新创建的文件夹中的“py”文件

第五步 Pip 安装

  • 打开命令提示符
  • 使用“cd”命令导航到“我的第一个 Python 包”文件夹
  • 键入“Pip 安装”
  • 这将安装您的软件包
  • 然后打开任何 IDE,如 Jupyter Notebook,并键入:“来自 Mrinal import Insights”
  • 创建一个类对象,例如 insight_1 = Insights()。也可以看看预告视频。
  • 然后像视频中一样调用' automate_analysis()'函数。你会看到那些重复的步骤现在是如何自动化的,现在你只需要调用这个函数就可以完成所有的工作。

恭喜你!

您自己构建了您的第一个 python 包,并且通过不再一次又一次地编写那些函数,将会在将来节省大量时间。类似地,您可以添加更多的函数和类来为您的包添加更多的内容,并使您的数据分析过程更加顺畅。

资源

  • 你也可以从我的 GitHub 页面下载所有的代码文件
  • 如果你想上传你的包裹到 pypi.org,你可以点击这个链接

如果你喜欢这篇文章,那么请阅读我的另一篇关于如何开发为强大的机器学*模型执行特征工程所需的关键技能的文章。

了解如何用 Python 创建动画图形

原文:https://towardsdatascience.com/learn-how-to-create-animated-graphs-in-python-fce780421afe?source=collection_archive---------1-----------------------

动画数据可视化的基础

随着数据以前所未有的速度不断膨胀,数据科学家需要对其进行分析和理解。一旦发生这种情况,就需要有效地交流结果。

然而,交流数据分析的结果常常是棘手的。为了有效地沟通,一个流行的和非常有效的技术是讲故事。

让世界上所有的信息触手可及并不会让交流变得更容易:反而会让交流变得更难。―科尔·努斯鲍默·克纳弗里克

为了帮助讲故事和交流,数据可视化是至关重要的。动画数据可视化让事情更上一层楼,增加了令人惊叹的因素。

在这篇博客中,我们将探讨如何让你的图表生动起来。我们将学*如何给折线图、条形图和饼图添加新的维度。这个博客将让你开始,但可能性是无限的。

双摆

动画是如何工作的

在典型的时尚中,正如你对 Python 的期望,有一个非常易用的包,它使我们能够为我们的数据可视化增加一个额外的维度。

正在讨论的包是 FuncAnimation 扩展方法,是 Python 的 matplotlib 库中动画类的一部分。我们将通过多个例子来看看如何使用它,但是现在,你可以把这个函数想象成一个 while 循环,它不断地在画布上重新绘制我们的图形。

如何使用图书馆

帮助我理解如何制作图表动画的是从结尾开始。这个动画魔术将从下面两行开始发生:

import matplotlib.animation as anianimator = ani.FuncAnimation(fig, chartfunc, interval = 100)

让我们看看 FuncAnimation 的上述输入:

  1. fig 是我们将用来“绘制我们的图形”的图形对象
  2. chartfunc 是一个接受数字输入的函数,它表示时间序列上的时间(随着数字的增加,我们沿着时间轴移动)
  3. 间隔是帧之间的延迟,单位为毫秒。默认为 200。

如需更多可选输入,请查看文档

进一步研究以上内容,我们需要做的就是将他们的图表参数化为一个函数,该函数将时间序列中的点作为输入,游戏就开始了!

入门指南

为了确保我们涵盖了所有基础,我们将基于之前的数据可视化示例,我们已经在:

[## Python 数据可视化基础

不到 5 分钟的逐步介绍

towardsdatascience.com](/the-basics-of-data-visualisation-with-python-23188aa9fc1a)

换句话说,我们将使用来自疫情(每天死亡人数)的数据,并且我们将使用下面代码中给出的最终数据集。如果你想了解更多关于下面的数据转换和如何开始简单的数据可视化,先简单地阅读上面的帖子。

import matplotlib.animation as ani
import matplotlib.pyplot as plt
import numpy as np
import pandas as pdurl = '[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
df = pd.read_csv(url, delimiter=',', header='infer')df_interest = df.loc[
    df['Country/Region'].isin(['United Kingdom', 'US', 'Italy', 'Germany'])
    & df['Province/State'].isna()]df_interest.rename(
    index=lambda x: df_interest.at[x, 'Country/Region'], inplace=True)
df1 = df_interest.transpose()df1 = df1.drop(['Province/State', 'Country/Region', 'Lat', 'Long'])
df1 = df1.loc[(df1 != 0).any(1)]
df1.index = pd.to_datetime(df1.index)

动画线条图

我们需要做的第一件事是定义图表中的项目,这些项目将保持不变。也就是说,创建图形对象、x 和 y 标签,设置线条颜色和图形边距。

import numpy as np
import matplotlib.pyplot as pltcolor = ['red', 'green', 'blue', 'orange']
fig = plt.figure()
plt.xticks(rotation=45, ha="right", rotation_mode="anchor") #rotate the x-axis values
plt.subplots_adjust(bottom = 0.2, top = 0.9) #ensuring the dates (on the x-axis) fit in the screen
plt.ylabel('No of Deaths')
plt.xlabel('Dates')

然后,我们必须设置我们的曲线功能,然后动画它:

def buildmebarchart(i=int):
    plt.legend(df1.columns)
    p = plt.plot(df1[:i].index, df1[:i].values) #note it only returns the dataset, up to the point i
    for i in range(0,4):
        p[i].set_color(color[i]) #set the colour of each curveimport matplotlib.animation as ani
animator = ani.FuncAnimation(fig, buildmebarchart, interval = 100)
plt.show()

动画饼图

代码结构看起来与折线图相同。然而,有一些差异,我们将通过。

import numpy as np
import matplotlib.pyplot as pltfig,ax = plt.subplots()
explode=[0.01,0.01,0.01,0.01] #pop out each slice from the piedef getmepie(i):
    def absolute_value(val): #turn % back to a number
        a  = np.round(val/100.*df1.head(i).max().sum(), 0)
        return int(a)
    ax.clear()
    plot = df1.head(i).max().plot.pie(y=df1.columns,autopct=absolute_value, label='',explode = explode, shadow = True)
    plot.set_title('Total Number of Deaths\n' + str(df1.index[min( i, len(df1.index)-1 )].strftime('%y-%m-%d')), fontsize=12)import matplotlib.animation as ani
animator = ani.FuncAnimation(fig, getmepie, interval = 200)
plt.show()

一个主要的区别是,在上面的代码中,我们每次都返回一组值。在线图中,我们将整个时间序列返回到我们所在的点。我们通过使用

df1.head(i).max()

df1.head(i)返回一个时间序列,但是。max()确保我们只获得最新的记录(因为死亡总数要么保持不变,要么上升)。

动画条形图

构建条形图就像我们到目前为止看到的例子一样简单。对于这个例子,我包括了水平和垂直条形图。取决于你想看哪一个,你只需要定义变量 bar

fig = plt.figure()
bar = ''def buildmebarchart(i=int):
    iv = min(i, len(df1.index)-1) #the loop iterates an extra one time, which causes the dataframes to go out of bounds. This was the easiest (most lazy) way to solve this :)
    objects = df1.max().index
    y_pos = np.arange(len(objects))
    performance = df1.iloc[[iv]].values.tolist()[0]
    if bar == 'vertical':
        plt.bar(y_pos, performance, align='center', color=['red', 'green', 'blue', 'orange'])
        plt.xticks(y_pos, objects)
        plt.ylabel('Deaths')
        plt.xlabel('Countries')
        plt.title('Deaths per Country \n' + str(df1.index[iv].strftime('%y-%m-%d')))
    else:
        plt.barh(y_pos, performance, align='center', color=['red', 'green', 'blue', 'orange'])
        plt.yticks(y_pos, objects)
        plt.xlabel('Deaths')
        plt.ylabel('Countries')animator = ani.FuncAnimation(fig, buildmebarchart, interval=100)plt.show()

如何保存动画图形

所以你已经创建了你的第一个动画图表,你想分享它们。你如何拯救他们?

幸运的是,只需要一行代码:

animator.save(r'C:\temp\myfirstAnimation.gif')

更多信息,查看文档

如果你喜欢这篇博文,你可能也会喜欢:

[## 如何用 Python 为 Excel 增压

如何用 xlwings 集成 Python 和 Excel

towardsdatascience.com](/how-to-supercharge-excel-with-python-726b0f8e22c2) [## 正则表达式简介

使用 Python 逐步介绍正则表达式

medium.com](https://medium.com/better-programming/introduction-to-regex-8c18abdd4f70) [## 用 Python 中的 PyAutoGUI 实现自动化 UI 测试

回归测试你的用户界面的一个快速简单的方法

towardsdatascience.com](/automate-ui-testing-with-pyautogui-in-python-4a3762121973)

了解如何用 Python 创建 Web 数据应用程序

原文:https://towardsdatascience.com/learn-how-to-create-web-data-apps-in-python-b50b624f4a0e?source=collection_archive---------21-----------------------

最后,你可以在 5 分钟内找到一个图书馆

学* python 的美妙之处在于它的简单性和直观的表达结构。一旦你学会了这些基础知识,你就可以很好地构建有用且功能强大的应用程序了。加速整个过程并使 python 领先于竞争对手的是大量的免费库。

时不时会出现一个新的库,这改变了游戏!我认为这可能是构建 web 数据应用程序的一个例子。

用于构建 web(数据)应用程序的 Python 库

最流行的 web 开发 Python 框架有 Django、Tornado 和 Flask。都很厉害,但多少有点技术含量。它们需要你投入大量的时间来学*使用它们。在某种程度上,他们不是真正的生活方式!

这就是 streamlit 拯救世界的地方。一家谷歌支持的公司,其使命包括提供机器学*爱好者应得的工具:极快、有趣和互动!

“在生产可共享工件的同时编写生产级代码。”—谷歌 X,尼尔·特里克

事不宜迟,让我们开始探索这个令人印象深刻的图书馆。

疫情数据探索

使用我上一篇文章 中的数据和技术,如何用 Python 创建交互式可视化 我们可以用 Streamlit 非常快速地构建一个数据仪表板。

下面是我用几行代码构建的!

加载仪表板

加载仪表板非常快速简单。首先,以典型的方式安装库:

pip install streamlit

然后,创建一个 python 脚本:

import streamlit as stst.title('Hello there')

然后通过命令行运行它:

streamlit run yourScriptsFileName.py

这将返回您需要在浏览器中使用的地址,以查看您的 web 数据应用程序。

内置函数介绍

显示文本

有几种方法可以在 web 应用程序上显示文本:

import streamlit as st
st.title('This is a title')
st.header('A header...')
st.subheader('A subheader...')
st.markdown('Or a markdown.')

多重选择

你可以很容易地添加一个下拉多选控件。

x = st.multiselect('Text to display', List of Available Options, List of default options)
#where x will end up being a list of options

选择框

或者你可以有一个选择框,你只能从下拉菜单中选择一个值。

dailytotal = st.selectbox('Toggle between Daily and Total number of deaths', ('Daily', 'Total'))

滑块

引入滑块可以允许用户在不同的值之间拖动滑块。

slide = st.slider('Slide across to explore infection spread', minimumslide, maxslide, defaultslidevalue)

图表

使用 plotly express 时,您很大程度上遵循了典型的模式,但是您没有使用 fig.show(),而是将其替换为:

st.plotly_chart(fig, use_container_width=True)

交互式地图

一个直接的控件,要求您传入经度和纬度。

st.map(dfmap[['lat','lon']])

缓存以更快获得结果

没有任何形式的缓存,数据仪表板就不完整。令人欣慰的是,streamlit 允许您非常快速、轻松地缓存数据,因此您不必每次都读取它们。简单地在你的函数上添加下面一行。

@st.cache(persist=True)

我的仪表板的完整代码

import streamlit as st
import pandas as pd
import plotly.express as px
import pydeck as pdk
import numpy as np#Load and Cache the data
[@st](http://twitter.com/st).cache(persist=True)
def getmedata():
    url = '[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
    df = pd.read_csv(url, delimiter=',', header='infer')
    df.rename(index=lambda x: df.at[x, 'Country/Region'], inplace=True)
    dft = df.loc[df['Province/State'].isnull()]
    dft = dft.transpose()
    dft = dft.drop(['Province/State', 'Country/Region', 'Lat', 'Long'])
    dft.index = pd.to_datetime(dft.index)
    return(dft, df)df1 = getmedata()[0]st.title('Building a Data Dashboard with Streamlit')
st.subheader('while exploring COVID-19 data')#####In Scope Countries
countrylist = df1.columns.tolist()
countrylist1 = ['United Kingdom', 'US', 'Italy']
x = st.multiselect('Choose in scope countries', countrylist, countrylist1)
df1_inscope = df1[x]dailytotal = st.selectbox('Toggle between Daily and Total number of deaths', ('Daily', 'Total'))
if dailytotal == 'Daily':
    plotdata = df1_inscope.diff() #day on day changes
else:
    plotdata = df1_inscope#Build Pie Chart
df1 = plotdata.tail(1).transpose()
fig = px.pie(df1, values = str(df1.columns[0]), names = df1.index)
fig.update_traces(textposition='inside', textinfo = 'percent+label')
ddate = str(df1.columns[0])[:10] #chop timestampif dailytotal == 'Daily':
    st.header('Number of deaths on ' + ddate)
else:
    st.header('Total number of deaths up until ' + ddate)fig.update_layout(
    #title = f'Deaths on {ddate} due to COVID-19',
    xaxis_title = 'Dates'
    ,yaxis_title = 'Number of Deaths'
    ,font = dict(size = 25)
    ,template = 'seaborn' #"plotly", "plotly_white", "plotly_dark", "ggplot2", "seaborn", "simple_white", "none"
)
st.plotly_chart(fig)piechart = st.sidebar.checkbox('Show Pie Chart data')
if piechart == True:
    st.dataframe(df1)
    st.write()
else:
    st.write()#Move to Line graph
if dailytotal == 'Daily':
    st.header('Timeseries of daily number of deaths')
else:
    st.header('Timeseries total Number of deaths')fig = px.line()
for i,n in enumerate(plotdata.columns):
    fig.add_scatter(x=plotdata.index, y= plotdata[plotdata.columns[i]], name= plotdata.columns[i])
fig.update_layout(
     xaxis_title = 'Dates'
    ,yaxis_title = 'Number of Deaths'
    ,template = 'seaborn' #"plotly", "plotly_white", "plotly_dark", "ggplot2", "seaborn", "simple_white", "none"
    ,legend=dict(orientation="h", yanchor = 'top', y = 1.2)
)
fig.update_xaxes(
    rangeslider_visible=True,
    rangeselector=dict(
        buttons=list([
            dict(count=7, label="1w", step="day", stepmode="backward"),
            dict(count=1, label="1m", step="month", stepmode="backward"),
            dict(count=2, label="2m", step="month", stepmode="backward"),
            dict(step="all")
        ]),
        font = dict( color='#008000', size = 11),
    )
)st.plotly_chart(fig, use_container_width=True)##Show underlying data?
showdata = st.sidebar.checkbox('Show Line graph timeseries data')
if showdata == True:
    st.dataframe(plotdata)
else:
    st.write()###Plot a streamlit map
st.header('Explore the infection spreading with a map')
df2 = getmedata()[1]
df2.rename(columns={'Lat': 'lat', 'Long': 'lon', 'Province/State': 'Province', 'Country/Region': 'Country'}, inplace=True)maxslide = len(df2.columns) - 5
slide = st.slider('Slide across to explore infection spread', 0, maxslide, 10)datecolumn = df2.columns[slide + 4]
datecolumnlist = [datecolumn]st.subheader('Infections Recorded on ' + datecolumn)dfmap = df2[['Country','Province', 'lat', 'lon', datecolumn]]
dfmap = dfmap.replace(0,np.nan).dropna(subset = [datecolumn, 'lat', 'lon'])st.map(dfmap[['lat','lon']])mapgraph = st.sidebar.checkbox('Show map data')
if mapgraph == True:
    st.dataframe(dfmap)
    st.write()
else:
    st.write()

离别的思绪

Streamlit 是一个非常漂亮的数据 web 仪表板,可以单独用 python 编写。它允许你毫不费力地分享你的工作,并且有许多有用的控件。

只使用了这个仪表板的基本功能,我可以看到它的许多应用。它上传文件的新控件 st.file_uploader()肯定会支持更大的项目。

我相信 streamlit 是这样一个库,随着它的成熟,它会变得越来越好,并在定制和控制方面提供越来越多的功能!

如果你喜欢这个博客,你可能也会喜欢:

[## 时间管理和优先级排序的三种技巧

学*如何有效管理你的时间以获得职业成功

medium.com](https://medium.com/better-programming/three-techniques-for-time-management-and-prioritization-9df6dffe2ff1) [## 学*使用 Python 中的进度条

4 个不同库的介绍(命令行和用户界面)

towardsdatascience.com](/learning-to-use-progress-bars-in-python-2dc436de81e5) [## 识别投资股票的入门指南

想在股市一试身手却不知道从何下手?

medium.com](https://medium.com/financeexplained/beginners-guide-to-identifying-stocks-to-invest-in-4cf10fa5dcff)

了解如何以正确的方式进行特征选择

原文:https://towardsdatascience.com/learn-how-to-do-feature-selection-the-right-way-61bca8557bef?source=collection_archive---------11-----------------------

来源: Pixabay

x 真的是 y 的预测因子吗?

努力为您的模型找到合适的功能?我指的是增值功能。假设您正在处理来自物联网传感器或医疗保健的高维数据,这些数据具有成百上千个特征,很难找出哪些特征子集将带来良好的可持续模型。本文是关于在汽车数据集上使用 scikit-learn 的特性选择和技术实现的。我已经尽了最大努力把复杂的计算放在一边,但是对统计学的一些基本理解会让你的旅程更容易。😃

“原始”数据集通常带有许多不相关的特征,这些特征对预测模型的准确性没有太大贡献。使用音乐类比来理解这一点——音乐工程师经常使用各种技术来调整他们的音乐,这样就没有多余的噪音,声音也清晰明了。类似地,即使是数据集也会遇到噪声,为了更好地优化模型,去除噪声是至关重要的。这就是特性选择的由来!

现在,撇开模型精度不谈,理论上,特征选择

  • 减少过度拟合‘维数灾难’—如果数据集的特征/列多于样本 (X) ,模型将容易过度拟合。通过移除不相关的数据/噪声,该模型可以专注于基本特征,从而实现更高的泛化能力。
  • 简化模型 —维度给模型增加了许多层,使其变得不必要的复杂。过度工程很有趣,但他们可能不会比简单的同行更好。更简单的模型更容易解释和调试。
  • 减少训练时间 —较少的特征/尺寸降低了计算速度,加快了模型训练。

请记住,所有这些好处在很大程度上取决于问题。但可以肯定的是,它会产生一个更好的模型。

这是降维吗?

不完全是!

通常,特征选择和降维可以互换使用,因为它们的相似目标是减少数据集中的特征数量。然而,它们之间有一个重要的区别。特征选择从原始特征集中产生特征子集,这是数据的最佳代表。而降维是引入新的特征空间,在该空间中表示原始特征。它基本上将特征空间转换到一个较低的维度,保持原始特征不变。这是通过组合或排除一些特征来实现的。总之,你可以把特征选择看作是维度教育的一部分。

数据集在运行

我们将使用来自 UCI 机器学*知识库的自动汽车数据集。该数据集包含有关汽车规格、保险风险评级以及与其他汽车相比的正常使用损失的信息。该模型的目标是预测“价格”。一个回归问题,它由连续变量和分类变量组成,如下所示:

属性描述(图片由作者提供)

在对大约 200 个样本(每个样本有 26 个属性)进行了大量的预处理后,我设法将 R 的平方的值设为 0.85。因为我们的重点是评估特性选择技术,所以我不会深入建模过程。要获得完整的回归代码,请查看下面 Github 链接上的 jupyter 笔记本

[## ayushijain 09/特征选择技术

查看此链接,了解完整的多元线性回归代码以及汽车数据集的特征技术。

github.com](https://github.com/Ayushijain09/Feature-Selection-Techniques/blob/master/_Automobile_Multiple_LinearRegression_Feature_Selection.ipynb)

现在,让我们尝试通过特征选择来改进模型!

技术

简而言之,特征选择方法可以分为三大类,过滤、包装和嵌入。

一.过滤方法

使用过滤方法,我们主要应用适合我们的数据的统计测量来分配每个特征列一个计算的分数。基于该分数,将决定该特征将被保留还是从我们的预测模型中移除。这些方法计算成本低,最适合消除冗余的不相关特征。然而,一个缺点是它们没有考虑到特性的相关性,因为它们独立地处理每个特性。

此外,我们有对单个特征进行排序的 单变量过滤方法 ,以及评估整个特征空间的 多变量过滤方法 。让我们探索一下最著名的特征选择过滤方法:

1。)缺失值比率

缺少太多值的数据列没有多大价值。理论上,25–30%是缺失值的可接受阈值,超过该阈值,我们应该从分析中删除这些特征。如果你有领域知识,最好能做出一个有根据的猜测,这个特性是否对模型至关重要。在这种情况下,尝试使用此处列出的各种技术输入缺失值。要获得每个特性的缺失值百分比,请尝试下面的一行代码!为每种技术添加一个 jupyter 笔记本很麻烦,所以我使用 Github gist 并排添加了输出,考虑到了相同的汽车数据集。

nlargest()返回缺省值最多的 5 个要素

2。)差异阈值

其中相同值占据大多数样本的特征被称为具有零方差。这种携带少量信息的特征不会影响目标变量,并且可以被丢弃。您可以调整阈值,默认值为 0,即移除所有样本中具有相同值的特征。对于一个非常大的子集具有相同值的准常数特征,使用阈值 0.01。换句话说,删除 99%的值相似的列。

丢弃零方差要素(可自定义阈值)

3。)相关系数

如果两个独立的特征(X)彼此之间有很强的关系并且向相似的方向移动,则它们是高度相关的。在这种情况下,如果一个特性就足够了,那么就不需要将两个相似的特性添加到模型中。它主要考虑拟合线、拟合线的斜率和拟合质量。计算相关系数有多种方法,如果一对列超过某个阈值,则显示与目标变量(y)高度相关的一列将被保留,而另一列将被丢弃。

皮尔逊相关 (针对连续数据)是度量两个变量之间相似性的参数统计检验。被参数项搞糊涂了?这意味着该测试假设观察到的数据遵循某种分布模式(例如,正态、高斯)。其系数值' r' 的范围在 -1( 负相关)到 1( 正相关)之间,表示数据与模型的拟合程度。它还返回' p 值,通过与显著性水平' alpha' (α)进行比较,确定变量之间的相关性是否显著。如果 p 值小于α,则意味着样本包含足够的证据来拒绝零假设,并得出相关系数不等于零的结论。

来源:多组( xy )点,每组相关系数为 xy 。请注意,相关性反映了线性关系的强度和方向(顶行),但不是该关系的斜率(中间),也不是非线性关系的许多方面(底部)。

Spearman 秩相关系数 (针对连续+有序数据)是一种非参数统计检验,工作原理类似于 Pearson,但是,它不对数据做任何假设。用符号 rho(-1<ρ<1)表示,这种检验可以应用于未通过皮尔逊相关假设的有序和连续数据。对于新手来说,有序数据是分类数据,但在排名/排序上有细微差别(例如,低、中、高)。这里要注意的一个重要假设是,变量之间应该存在单调关系,即变量的值一起增加,或者如果一个增加,另一个减少。

肯德尔相关系数 (针对离散/有序数据)——**类似于 Spearman 相关,这个系数比较的是一致和不一致数据对的数量。

*假设我们有一对观测值(xᵢ,yᵢ),(xⱼ,yⱼ),i < j,它们是:
*** 和谐 if 任一(xᵢ > xⱼ和 yᵢ > yⱼ)或(x\u\u<x \u\u 和 y\u\u<y\u\u
**不和谐if 任一(x \u

用希腊字母 tau ( τ )表示,该系数在-11 之间变化,并且基于相对于 x-y 对数量的一致和不一致对的计数差异。

Pearson、Spearman、Kendall 使用 Scipy & Pandas 的相关系数

在上面的回归 jupyter 笔记本中,我使用了 Pearson 相关性,因为 Spearman 和 Kendall 只对顺序变量有效,而我们有 60%的连续变量。

4。)独立性卡方检验 (针对分类数据)

在深入研究卡方之前,我们先了解一个重要的概念:假设检验!想象一下,XYZ 提出一个主张,一个公认的事实,你称之为无效假设。现在你提出了一个替代假设,一个你认为能更好地解释这种现象的假设,然后努力拒绝零假设。
在我们的例子中:
零假设:两个变量是独立的。
备择假设:两个变量是相依的。

因此,卡方检验有两种变化——一种是评估拟合优度,另一种是独立性检验。首先,它将观察到的数据与根据变量独立的期望分布数据的模型进行比较。然后,你基本上需要检查观察到的数据哪里不符合模型。如果数据点/异常值太多,那么变量存在相依性的可能性极大,证明零假设不正确!

它主要返回一个测试统计量“p 值”来帮助我们决定!在高水平上,如果 p 值小于某个临界值- ' 显著性水平'(通常为 0.05),我们拒绝零假设,认为变量是相关的!

卡方检验不适用于汽车数据集,因为它需要分类变量和非负值!出于这个原因,我们可以使用互信息&方差分析。

5。) 互信息( 为双方回归&分类)

互信息衡量一个变量对另一个变量的贡献。换句话说,如果我们删除或添加特性,目标变量会受到多大的影响?如果两个变量都是独立的,则 MI 为 0,如果 X 是 y 的确定性变量,则 MI 在 0-1 之间。MI 主要是 X 的熵,它测量或量化通过一个随机变量获得的关于另一个随机变量的信息量。

关于 MI 最好的事情是它允许人们检测非线性关系,并且对回归和分类都有效。酷!不是吗😃

6。)方差分析

好吧,老实说,这有点棘手,但让我们一步一步地理解它。首先,这里我们处理的不是特性,而是组/级别。组是同一独立(分类)变量中的不同组。方差分析主要是 t 检验的一种 T2 扩展。用 t 检验,你可以只研究两组,但用方差分析,你至少需要三组来观察均值是否有差异,并确定他们是否来自同一人群。

它假定假设为
H0:所有群体的手段都是平等的。
H1:至少有一组的均值不同。

假设从我们的汽车数据集中,我们使用一个“燃料类型”特征,它有两个组/级别——“柴油”和“汽油”。因此,我们的目标是通过计算两组的平均值是否不同于独立变量(即“燃料类型”)的总体平均值,来确定这两组在统计上是否不同。ANOVA 使用 F-Test 进行统计显著性检验,F-Test 是组之间的方差与组内的**方差之比,该数字越大,组的均值越有可能真正不同,您应该拒绝零假设。***

回归任务的方差分析特征选择

选择特征选择方法(图片由作者提供)

二。包装方法

在包装方法中,我们主要选择特征的子集,并使用机器学*算法来训练它们。基于来自该模型的推论,我们采用搜索策略来查看可能的特征子集的空间,并决定为下一个模型开发添加或移除哪个特征。该循环继续,直到模型性能不再随所需的特征数 (k_features) 而变化。

缺点是,随着要素的增加,计算量会变得很大,但好的一面是,它会处理要素之间的交互,最终为您的模型找到具有最低可能误差的最佳要素子集。

1.)顺序特征选择

一种贪婪的搜索算法,它有两种变体- 顺序向前选择 (SFS)和顺序向后选择 (SBS)。它基本上从一组空集特征开始,然后寻找一个特征,使最小化成本函数。一旦找到特征,它就被添加到特征子集中,并以同样的方式一个接一个地找到正确的特征集来构建最佳模型。这就是 SFS 的工作方式。对于顺序向后特征选择,它采取完全相反的路线。它从所有特征开始,并根据性能迭代地逐个去除特征。两种算法的目标都是获得最低成本的模型。

SFS 的主要限制是不能删除添加其他功能后变得无用的功能。SBS 的主要限制是它不能在一个特性被丢弃后重新评估其有用性。

SFS(对于顺序向后选择,将向前参数改为 假)

2.)递归特征消除(RFE)

考虑到您有一组初始特征,这种贪婪算法的作用是通过每次考虑更小的特征子集来重复执行模型构建。它是怎么做到的?在对估计器进行特征训练之后,它基于模型的 coef_feature_importances_ 属性返回等级值,传达每个特征的重要性。对于下一步,从当前特征集中删除最不重要的特征。这个过程被递归地重复,直到获得指定数量的特征。

RFE 回归

三。嵌入式方法

这些方法结合了过滤器和包装器方法的功能。好处是它们在训练过程中执行特征选择,这就是它们被称为嵌入式的原因!计算速度和过滤方法一样快,当然精确度更高,这是一个双赢的模式!

1.)L1(拉索)正则化

在深入 L1 之前,让我们先了解一下正规化。首先,它是一种用于减少对高度复杂模型过度拟合的技术。我们在成本函数中增加了一个惩罚项,这样随着模型复杂度的增加,成本函数会增加一个巨大的值。回到 LASSO(最小绝对收缩和选择算子)正则化,这里你需要明白的是,它带有一个参数,‘alpha’并且 alpha 越高,最不重要特征的特征系数越收缩到零。最终,我们得到一个更简单的模型,具有相同或更好的精度!

然而,在某个特征很重要的情况下,您可以尝试岭正则化(L2)或弹性网(L1 和 L2 的组合),其中不是完全放弃它,而是减少特征权重。

套索回归

2.)树模型(用于回归和分类)

随机森林是最流行和最准确的机器学*算法之一,它是随机决策树的集合。一个单独的树不会包含所有的特征和样本。我们使用这些进行特征选择的原因是决策树的构造方式!我们的意思是,在树构建的过程中,它使用内置的几种特征选择方法。从根开始,用于创建树的函数通过在每一步进行条件比较来尝试所有可能的分割,并选择将数据分割成最同质组(最纯)的一个。每个特征的重要性由每个集合的“纯净”程度得出。

使用基尼系数进行分类,使用方差进行回归,我们可以识别出能够产生最优模型的特征。同样的概念也可以应用于 CART(分类和回归树)和 boosting 树算法。

使用决策树的特征重要性

结束注释

仅此而已!希望你对这些统计测试作为特征选择技术是如何工作的有一个很好的直觉。这里要考虑的一件重要事情是,应用特征选择算法并不总是保证更好的准确性,但肯定会导致比以前更简单的模型!

如果你有任何问题/想法,请在下面的评论区留下你的反馈,或者你可以通过 Linkedin 联系我。

敬请关注更多内容!😃

参考

* [## NumPy、SciPy 和 Pandas:与 Python 的相关性-真正的 Python

在本教程中,您将了解什么是相关性,以及如何使用 Python 计算相关性。你会用 SciPy,NumPy…

realpython.com](https://realpython.com/numpy-scipy-pandas-correlation-python/#pearson-correlation-coefficient) [## 特征选择技术实践:嵌入式方法

第 4 部分:正则化和基于树的嵌入方法

heartbeat.fritz.ai](https://heartbeat.fritz.ai/hands-on-with-feature-selection-techniques-embedded-methods-84747e814dab)*

学*如何(轻松!!)用 Python 做 3 个高级 Excel 任务

原文:https://towardsdatascience.com/learn-how-to-easily-do-3-advanced-excel-tasks-in-python-925a6b7dd081?source=collection_archive---------4-----------------------

面向 Excel 高级用户的熊猫介绍

对峙开始了!(来源:Nik Piepenbreier)

Excel 是无处不在的数据分析工具——它很容易上手,大多数情况下每个人都有一份,一旦你掌握了它,它就非常强大!与此同时,Python 通常被认为是比较难学的,但是却有无限的潜力。在这篇文章中,我们将探索在 Python 中可以轻松完成的三件事,这三件事你通常在 Excel 中都能做到!

我们将从导入 pandas 开始,并根据工作簿中的工作表加载两个数据帧。我们称它们为销售状态

将我们的数据集导入熊猫数据框架。

假设我们运行了。head()方法,如下所示:

print(sales.head())

我们可以将其与 Excel 中的数据进行比较:

比较数据在 Excel 和 Pandas 中的显示方式(来源:Nik Piepenbreier)

我们可以看到显示的数据与 Excel 显示数据的方式相对相似,但也有一些关键的区别:

  • Excel 从第 1 行开始,而 Pandas 从第 0 行(' index ')开始,
  • Excel 用以 A 开头的字母标记列,而 Pandas 用变量名标记列

让我们开始深入研究如何与熊猫一起完成 Excel 任务。

Python 中的 IF 函数

在 Excel 中使用 IF 函数非常方便,它允许我们根据另一个单元格中的条件应用某个标签。假设我们想要创建一个新列,让我们知道 B 列的单元格中的值是否大于 500。在 Excel 中,我们将 E 列标记为大于 500,我们将进入单元格 E2 并写入:

=IF([@Sales]>500, "Yes", "No")

在 Excel 中应用 IF 函数(来源:Nik Piepenbreier)

如果我们想在 Pandas 中这样做,我们可以使用列表理解来轻松应用相同的 If 语句:

sales['MoreThan500'] = ['Yes' if x > 500 else 'No' for x in sales['Sales']]

解释的理解列表(资料来源:Nik Piepenbreier)

列表理解是这类工作的好工具,它减少了编写复杂 if/else 语句的需要。您可以用 if/else 语句完成同样的事情,但是这样可以节省时间,并使代码更加简洁。你可以通过查看这篇文章来了解更多关于列表理解的细节。

想了解更多关于列表理解的知识吗?看看我的视频!

Python 中的列表理解。资料来源:Nik Piepenbreier

熊猫视频

在我们的数据集中,城市在一张表上,州/省在另一张表上。这并不理想,但是我们可以在 Excel 中使用 VLOOKUP 来链接数据。VLOOKUP 的工作方式类似于左连接,左数据集中的每个记录都被保留。我们告诉 Excel 在查找表中垂直上下查找某一列中的特定值,然后返回位于该列右侧特定列数的值。

让我们添加一个名为“State”的列,并使用 VLOOKUP 从 states 表中返回相应的状态。

使用 VLOOKUP 添加州/省信息(来源:Nik Piepenbreier)

在 Python 中,我们可以使用 Pandas merge 函数来完成同样的事情。Merge 获取两个数据帧并将其合并。为此,我们将编写以下代码:

sales = pd.merge(sales, states, how='left', on='City')

让我们一个论点一个论点地来分析:

  1. 第一个参数是原始数据帧
  2. 第二个参数是我们要查找值的数据帧
  3. 如何指定我们要进行的连接类型
  4. On 指定我们想要合并的变量(如果变量在每个数据帧中被称为不同的东西,还有 left_on 和 right_on)。

熊猫的数据透视表

数据透视表是 Excel 最强大的功能之一,它允许我们以令人难以置信的速度从大型数据集提取有意义的数据。让我们创建一个关于每个城市销售额的数据透视表。

在 Excel 中生成数据透视表(来源:Nik Piepenbreier)

为此,我们只需将 City 字段拖到 Rows 部分,将 Sales 字段拖到 Values 部分。Excel 会自动合计数据集中每个城市的销售额。

为了在 Pandas 中生成相同的数据透视表,我们将编写以下代码:

sales.pivot_table(index = 'City', values = 'Sales', aggfunc = 'sum')

让我们再来分解一下:

  1. 我们使用 sales.pivot_table 让 Pandas 知道我们想要基于销售数据框架创建一个数据透视表
  2. Index 指定了我们想要聚合的值
  3. Values 指定我们要聚合的值
  4. Aggfunc 指定了我们想要使用的函数(我们也可以使用 mean,max,min 等)。)

包扎

在本文中,我们学*了如何将 Excel 数据导入 Pandas,如何完成 IF 和 VLOOKUP 函数,以及如何生成数据透视表。但是你可能会问自己,如果你可以在 Excel 中做这里列出的所有事情,为什么还要用熊猫呢?这里没有一个明确的答案。Python 让我们能够生成可重用、可追踪的代码,让我们能够轻松地复制我们的分析设计。对于较小的分析,Excel 可能就足够了。我鼓励你给熊猫打一针,看看你是否会喜欢上它。

学*如何(轻松!!)用 Python 做 3 个更高级的 Excel 任务

原文:https://towardsdatascience.com/learn-how-to-easily-do-3-more-advanced-excel-tasks-in-python-36449e425c9d?source=collection_archive---------15-----------------------

Excel 高级用户对熊猫的更多介绍

让我们用 Python 来承担一些更高级的 Excel 任务吧!资料来源:Nik Piepenbreier

在另一篇文章中,我们学会了如何(轻松!!)用 Python 做 3 个高级 Excel 任务。在这里,我们将继续这项任务,并学*另外 3 项你可以轻松掌握的高级技能!我希望这篇文章让 Python 变得更加平易*人,同时在这两个伟大的工具之间提供一些有趣的比较。

我们将从导入 pandas 开始,并根据工作簿中的工作表加载两个数据帧。我们使用与上一篇文章相同的数据集。

如果你想继续的话,我已经为这篇文章上传了一个完整的笔记本。在可以找到这个链接。遗憾的是,颜色格式没有遵循,但是您可以很容易地从那里复制并粘贴代码。同样,如果你想在 Excel 中跟进,你可以通过这个链接下载文件。

让我们开始吧!

Pandas 中的彩色地图格式

条件格式是 Excel 中非常棒的工具之一,它可以让我们快速挑出数据中的异常值,例如最高值或最低值。让我们先在我们的 Excel 文件中这样做!

在 Excel 中应用色彩映射表很容易!资料来源:Nik Piepenbreier

选择要格式化的列。

在“主页”选项卡下,选择条件格式、色标和

选择您想要使用的比例。我们用了绿-黄-红。

在熊猫身上,我们想应用。背景 _ 渐变样式方法。我们可以通过输入:

sales.style.background_gradient(subset=[‘Sales’], cmap = ‘YlGnBu’)

这将返回:

在熊猫身上应用色阶的结果。资料来源:Nik Piepenbreier

让我们稍微分解一下这个语法:

  • 子集:识别您想要应用这个的列。如果您想要多个,请将它们嵌套在列表中。
  • cmap:Matplotlib 中的颜色映射。这确定了我们想要应用的色阶类型。更多细节可以在这里找到

Python 中的数据栏

与色标类似,数据条使我们能够轻松地识别单元格中值的大小。

在 Excel 中添加数据栏。资料来源:Nik Piepenbreier

要在 Excel 中添加数据栏:

选择要格式化的列。

在主页选项卡上,转到条件格式→数据栏。

为此,我们选择了纯蓝。

为了用 Python 和 Pandas 实现这一点,我们可以编写以下代码:

sales.style.bar(subset=['Sales'], color = '#50C878')

在 Python 中用熊猫应用数据栏。资料来源:Nik Piepenbreier

让我们再细分一下:

  • 子集再次引用我们想要应用格式的列,而
  • 颜色是指我们要应用的颜色的十六进制代码!

熊猫中的 SUMIFs

最后,我们将探索如何用 Python 完成 SUMIFs。SUMIF 函数允许我们根据条件将值相加(该条件是否出现在另一列取决于我们)。

在 Excel 中计算 SUMIFs。资料来源:Nik Piepenbreier

在左边的例子中,我们计算所有香蕉销售的总销售额。我们通过使用以下公式实现了这一点:

=SUMIF(sales[Product], "Bananas", sales[Sales])

我们可以通过编写以下代码在 Python 中完成同样的事情:

sales.loc[sales["Product"] == "Bananas", "Sales"].sum()

就像在 Excel 中一样,这将返回 5843。让我们来看看这里发生了什么:

如何承担熊猫的 SUMIF 功能?资料来源:Nik Piepenbreier

结论:学会如何(轻松!!)用 Python 做 3 个更高级的 Excel 任务

在这篇文章中,我们学*了如何在 Excel 和 Pandas 中承担三个额外的高级任务。我们学*了如何在熊猫身上应用色标、色带和 SUMIF 函数。

如果你还没有,请通过点击此链接查看这篇文章的第一部分。

感谢阅读!

现在学*如何掌握 Python 中的 groupby 函数

原文:https://towardsdatascience.com/learn-how-to-master-groupby-function-in-python-now-4620dd463224?source=collection_archive---------31-----------------------

Pandas 中的 GroupBy 比 SQL 中的 groupby 更加复杂和强大。

麦克斯韦·尼尔森在 T2 的照片

熊猫套餐中一个受欢迎的功能是分组功能。相信之前用熊猫的几乎都一定也用过 groupby 功能。它之所以如此受欢迎,是因为它有效地提供了概括而详细的结果。如熊猫包装文件所述,

“分组依据”指的是涉及一个或多个以下步骤的过程:

根据某些标准将数据分组

功能独立应用于每组。

结果组合成一个数据结构。1

SQL 中还有一个 groupby 函数。因此对于有 SQL 经验的人来说,学* Python 中的 groupby 函数并不是一件困难的事情。但问题是 Pandas 中的 groupby 可以执行比 SQL 更多的分析,这使得 Pandas 中的 groupby 成为一个常见但重要的函数。

熊猫里的 groupby 之所以更厉害,是因为第二步“申请”。在 SQL 中,“应用”步骤中的大多数操作都是统计相关的,比如 min、max、count 等。然而,在熊猫身上,“应用”可以表现得更多。

从熊猫的文档中,

在应用步骤中,我们可能希望执行以下操作之一:

聚合:计算每个组的汇总统计数据。

转换:执行一些特定于组的计算,并返回一个相似索引的对象。

过滤:根据评估真或假的分组计算,丢弃一些分组。1

在本文中,我将介绍一些 groupby 应用程序。这些应用程序不仅向我展示了数据的洞察力,还帮助我确定了分析数据的下一步行动。

我们开始吧。

本文使用的数据是来自 Kaggle 的《学生饮酒》中的“student-por.csv”。你可以从这个链接下载数据。

**# Input**
import pandas as pd 
data = pd.read_csv('student-por.csv')
data.info()**# Output** <class 'pandas.core.frame.DataFrame'>
RangeIndex: 649 entries, 0 to 648
Data columns (total 33 columns):
school        649 non-null object
sex           649 non-null object
age           649 non-null int64
address       649 non-null object
famsize       649 non-null object
Pstatus       649 non-null object
Medu          649 non-null int64
Fedu          649 non-null int64
Mjob          649 non-null object
Fjob          649 non-null object
reason        649 non-null object
guardian      649 non-null object
traveltime    649 non-null int64
studytime     649 non-null int64
failures      649 non-null int64
schoolsup     649 non-null object
famsup        649 non-null object
paid          649 non-null object
activities    649 non-null object
nursery       649 non-null object
higher        649 non-null object
internet      649 non-null object
romantic      649 non-null object
famrel        649 non-null int64
freetime      649 non-null int64
goout         649 non-null int64
Dalc          649 non-null int64
Walc          649 non-null int64
health        649 non-null int64
absences      649 non-null int64
G1            649 non-null int64
G2            649 non-null int64
G3            649 non-null int64
dtypes: int64(16), object(17)
memory usage: 167.4+ KB

第一步:拆分数据

第一步相当简单,根据一列或多列中的值对数据进行分组。您只需要指定如何执行分组。大多数人都知道一个列名或一组列名可以用于分组。但是,您也可以为分组传递一个函数。该函数将使用索引值作为参数并执行分组。欲了解更多信息,[2]

groupby 函数返回的对象是“DataFrameGroupBy 对象”。分组后,您可以使用group来查看分组。

**#Groupby one column****# Input**
data.groupby('school')
**# Output** <pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000024D28C9DF98>**# Input** data.groupby('school').groups
**# Output** {'GP': Int64Index([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
...413, 414, 415, 416, 417, 418, 419, 420, 421, 422],
dtype='int64', length=423),
 'MS': Int64Index([423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
...639, 640, 641, 642, 643, 644, 645, 646, 647, 648],
dtype='int64', length=226)}**# Groupby a function** **# Input**
def grouping(int):
    if int%10==0:
        return 'Group1'
    if int%5==0:
        return 'Group2'
    return 'Group3'
data.groupby(grouping).groups
**# Output** {'Group1': Int64Index([  0,  10,  20,  30,  40,  50,  60,  70,  80,  90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 640], dtype='int64'),
 'Group2': Int64Index([  5,  15,  25,  35,  45,  55,  65,  75,  85,  95, 105, 115, 125,135, 145, 155, 165, 175, 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295, 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 405, 415, 425, 435, 445, 455, 465, 475, 485, 495, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 605, 615, 625, 635, 645], dtype='int64'),
 'Group3': Int64Index([  1,   2,   3,   4,   6,   7,   8,   9,  11,  12,... 637, 638, 639, 641, 642, 643, 644, 646, 647, 648],dtype='int64', length=519)}

在上面使用函数进行分组的例子中,数据帧中的索引是行号。因此,根据行号将一行分配给三个组之一。然后 groupby 函数将这三组分组。

要获得每个组的数据,您可以使用get_group()函数并输入组名。

**#Input** data.groupby(grouping).get_group('Group1')

data.groupby(分组)。get_group('Group1 ')

此外,如果要按非索引列对数据进行分组,可以同时使用 apply 和 lambda 函数进行分组。

**# Input** data.groupby(data['famsize'].apply(lambda x: x.startswith('GT'))).get_group(False)

data.groupby(data['famsize']。apply(lambda x: x.startswith('GT '))。get_group(False)

分组后,您已经可以应用许多计算或统计函数。例如,size()可以给你每组的行数;sum()返回每组所有数字列的总和。要知道更多适用的函数,3

**#Input** data.groupby(data['famsize'].apply(lambda x: x.startswith('GT'))).size()**#Output** famsize
False    192
True     457
dtype: int64

步骤 2:应用函数并组合结果

是时候报道 groupby 的重要部分了。Pandas 中的 Groupby 函数比 SQL 中的功能更强大,因为你不仅可以使用常见的统计函数,如min(), max(), mean(),...,还可以使用许多更复杂的函数。您也可以应用您定义的函数。在下面的部分,我将分别解释这三个动作。

聚合(agg)

关于聚合的一个简单解释是根据以前分组的数据执行计算。聚合应用于每个组,并返回其各自的结果。

一些常见的计算如summinmax、…您可以对所有数值列执行计算,也可以指定一列来执行计算。

**#Input** mjob_gp = data.groupby('Mjob')
mjob_gp.agg('mean')

mjob_gp.agg('mean ')

**#Input** mjob_gp['age'].agg('mean')**#Output** Mjob
at_home     16.955556
health      16.312500
other       16.802326
services    16.661765
teacher     16.583333
Name: age, dtype: float64

关于聚合,一个不太为人所知的情况是,您可以在一个或多个列上同时执行多个计算。如果您想研究一个列的统计数据,这个选项很有用。

**#Input** mjob_gp.agg({'age':['mean','max']})

mjob_gp.agg({'age':['mean ',' max']})

然而,一个问题是这些列是多索引的,这对于进一步的处理不是很好(我个人不喜欢多索引)。因此,我们可以更进一步,将pd.NamedAgg(熊猫 0.25.0 版本新增)包含到agg功能中。关于pd.NamedAgg的更多信息,4

**#Input** mjob_gp.agg(avg_age=pd.NamedAgg(column='age', aggfunc='mean'),
            min_age=pd.NamedAgg(column='age', aggfunc='min'),
            max_age=pd.NamedAgg(column='age', aggfunc='max'))

mjob_gp.agg(avg_age=pd。NamedAgg(column='age ',aggfunc='mean '),
min_age=pd。NamedAgg(column='age ',aggfunc='min '),
max_age=pd。NamedAgg(column='age ',aggfunc='max '))

使用pd.NamedAgg有两个好处。当然,第一个优点是列上没有多索引。第二个优点是您可以自定义列名。

毫不奇怪,您也可以在聚合中使用自定义函数。

**#Input** def range_function(x):
    return max(x) - min(x)mjob_gp.agg(max_age = pd.NamedAgg(column='age',aggfunc='max'),
            min_age = pd.NamedAgg(column='age',aggfunc='min'),
            range_age = pd.NamedAgg(column='age',aggfunc=range_function),)

mjob_gp.agg(max_age = pd。NamedAgg(column='age ',aggfunc='max '),
min_age = pd。NamedAgg(column='age ',aggfunc='min '),
range_age = pd。NamedAgg(column='age ',aggfunc=range_function),)

变换(transform)

回到变形的描述,

T 转换:执行一些特定于组的计算,并返回一个相似索引的对象。

关键部分是“特定于组的计算”。不同组的计算是不同的。例如,max将为每个组提供一列的最大值,但不是跨整个数据集。

转换的另一个特征是,计算应用于每一行,并返回每个组长度相同的结果,而不像长度减少的聚合。如果您熟悉 SQL 中的窗口函数,Pandas 中的转换与此类似。(PS:你还不知道 SQL 中的窗口函数?!?!查看我以前的一篇文章,这篇文章帮助您理解为什么 SQL 中的窗口函数如此重要)

[## 为什么 SQL 中的窗口函数如此重要,以至于你现在就应该学*它?

如果我告诉你这个问题会在每次数据分析职位的面试中被问到,你会怎么想?

towardsdatascience.com](/why-window-function-in-sql-is-so-important-that-you-should-learn-it-right-now-1274b6096a86)

**#Input** mjob_gp['G1','G2','G3'].transform(lambda x: (x-x.mean())/x.std())

mjob_gp['G1 ',' G2 ',' G3']。transform(λx:(x-x . mean())/x . STD())

在上面的例子中,对于每个组,G1 到 G3 的值基于相应组的平均值和标准偏差被归一化。

过滤器

从《熊猫》中的描述来看,

R 返回数据帧的副本,排除不满足 func 指定的布尔标准的组中的元素。【5】

您可以使用filter功能过滤掉任何不符合标准的组。

**#Input** mjob_gp.filter(lambda x: x['G1'].mean() > 12)

mjob_gp.filter(lambda x: x['G1']。平均值()> 12)

在上面的示例中,只返回“健康”和“教师”下的 Mjob,因为它们的“G1”的平均值大于 12。

**#Input** mjob_gp['G1'].mean()**#Output** Mjob
at_home     10.451852
health      12.395833
other       11.275194
services    11.610294
teacher     12.555556
Name: G1, dtype: float64

关闭

Pandas 中的 Groupby 函数是执行大量分析和数据转换的便捷工具。我希望这篇文章能帮助你理解熊猫中 groupby 的威力和用处。我相信您现在已经更加了解如何在日常数据分析中使用 groupby 了。和熊猫玩得开心,下次再见。

我的另一篇文章

如果您是 Python 新手(尤其是自学 Python 的话),请将此加入书签

(第二部分)如果你是 Python 新手(尤其是自学 Python 的话)请将此加入书签

如何用熊猫来分析数值型数据?

Web Scrape Twitter by Python Selenium(第 1 部分)

Web Scrape Twitter by Python Selenium(第二部分)

引用/参考

2】:熊猫。DataFrame.groupby

[5]:pandas . core . group by . data frame group by . filter

学*如何在 5 分钟内将数据读入熊猫数据框

原文:https://towardsdatascience.com/learn-how-to-read-data-into-a-pandas-dataframe-in-5-minutes-122af8e0b9db?source=collection_archive---------18-----------------------

从不同来源提取数据

来源

概观

据说数据科学家花费 80%的时间对数据进行预处理,所以让我们深入研究数据预处理管道,也称为 ETL 管道,让我们找出哪个阶段花费的时间最多。在这篇博文中,我们将学*如何从不同的数据源中提取数据。让我们来看一个真实的数据集,这样更容易理解。

本课使用了世界银行的数据。数据来自两个来源:

  1. 世界银行指标数据 —该数据包含世界各国的社会经济指标。一些示例指标包括人口、可耕地和中央政府债务。
  2. 世界银行项目数据 —该数据集包含 1947 年以来世界银行项目贷款的相关信息。

数据文件的类型

  1. CSV — CSV 代表逗号分隔值。这是文件的外观
id,regionname,countryname,prodline,lendinginstr
P162228,Other,World;World,RE,Investment Project Financing
P163962,Africa,Democratic Republic of the Congo;Democratic Republic of the Congo,PE,Investment Projec

让我们用 pandas 加载这个文件。

import pandas as pd
df_projects = pd.read_csv('../data/projects_data.csv')#ERROR:
#/opt/conda/lib/python3.6/site-packages/IPython/core/interactiveshell.py:2785: DtypeWarning: Columns (44) have mixed types. Specify dtype option on import or set low_memory=False.interactivity=interactivity, compiler=compiler, result=result)

我们将得到一个 DType 警告错误。基本上,pandas 会计算出我们文件的数据类型,并适当地读取它们,但是我们的一个列有多种数据类型,因此会出现警告错误。我们可以在读取时传递字符串的数据类型。请参考熊猫 文档 阅读更多。

df_projects = pd.read_csv('../data/projects_data.csv',dtype=str)

输出:

让我们阅读另一个 CSV 文件:

df_population = pd.read_csv("../data/population_data.csv")
# ParserError: Error tokenizing data. C error: Expected 3 fields in line 5, saw 63

看起来这个 CSV 文件有问题。让我们检查一下里面的东西。这里,如果文件很小,您可以使用记事本/excel 直接打开 CSV 文件,也可以使用下面的 python 代码:

with open("../data/population_data.csv") as f:
    lis = [line.split() for line in f]        # create a list of lists
    #print(lis)
    for i, x in enumerate(lis):              #print the list items 
        print ("line{0} = {1}".format(i, x))#Output:line0 = ['\ufeff"Data', 'Source","World', 'Development', 'Indicators",']
line1 = []
line2 = ['"Last', 'Updated', 'Date","2018-06-28",']
line3 = []
line4 = ['"Country', 'Name","Country', 'Code","Indicator', 'Name","Indicator', 'Code","1960","1961","1962","1963","1964","1965","1966","1967","1968","1969","1970","1971","1972","1973","1974","1975","1976","1977","1978","1979","1980","1981","1982","1983","1984","1985","1986","1987","1988","1989","1990","1991","1992","1993","1994","1995","1996","1997","1998","1999","2000","2001","2002","2003","2004","2005","2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017",']

看起来 CSV 文件的前 4 行已损坏。因此,我们可以通过使用skip prows参数跳过前 4 行。

df_population = pd.read_csv("../data/population_data.csv",skiprows=4)

输出:

2。JSON —它是一种带有键/值对的文件格式。

[{"id":"P162228","regionname":"Other","countryname":"World;World","prodline":"RE","lendinginstr":"Investment Project Financing"},{"id":"P163962","regionname":"Africa","countryname":"Democratic Republic of the Congo;Democratic Republic of the Congo","prodline":"PE","lendinginstr":"Investment Project Financing"},{"id":"P167672","regionname":"South Asia","countryname":"People\'s Republic of Bangladesh;People\'s Republic of Bangladesh","prodline":"PE","lendinginstr":"Investment Project Financing"}]

谢天谢地,熊猫有直接读取 JSON 的功能。

import pandas as pd
df_json = pd.read_json('population_data.json',orient='records')

其他方法:

import json# read in the JSON file
with open('population_data.json') as f:
    json_data = json.load(f)# print the first record in the JSON file
print(json_data[0])
  1. XML —另一种数据格式叫做 XML(可扩展标记语言)。至少在格式方面,XML 和 HTML 非常相似。
<ENTRY>
  <ID>P162228</ID>
  <REGIONNAME>Other</REGIONNAME>
  <COUNTRYNAME>World;World</COUNTRYNAME>
  <PRODLINE>RE</PRODLINE>
  <LENDINGINSTR>Investment Project Financing</LENDINGINSTR>
</ENTRY>
<ENTRY>
  <ID>P163962</ID>
  <REGIONNAME>Africa</REGIONNAME>
  <COUNTRYNAME>Democratic Republic of the Congo;Democratic Republic of the Congo</COUNTRYNAME>
  <PRODLINE>PE</PRODLINE>
  <LENDINGINSTR>Investment Project Financing</LENDINGINSTR>
</ENTRY>

有一个名为 BeautifulSoup 的 Python 库,它使得读入和解析 XML 数据变得更加容易。以下是文档链接:美汤文档

# import the BeautifulSoup library
from bs4 import BeautifulSoup# open the population_data.xml file and load into Beautiful Soup
with open("population_data.xml") as fp:
    soup = BeautifulSoup(fp, "lxml") # lxml is the Parser type

让我们看看汤是什么样子的:

<html><body><p><?xml version="1.0" encoding="utf-8"?>
<root xmlns:wb="http://www.worldbank.org">
<data>
<record>
<field key="ABW" name="Country or Area">Aruba</field>
<field key="SP.POP.TOTL" name="Item">Population, total</field>
<field name="Year">1960</field>
<field name="Value">54211</field>
</record>
<record>
<field key="ABW" name="Country or Area">Aruba</field>
<field key="SP.POP.TOTL" name="Item">Population, total</field>
<field name="Year">1961</field>
<field name="Value">55438</field>
</record>

如何将 XML 作为数据帧读取?

data_dictionary = {'Country or Area':[], 'Year':[], 'Item':[], 'Value':[]}for record in soup.find_all('record'):
    for record in record.find_all('field'):
        data_dictionary[record['name']].append(record.text)df = pd.DataFrame.from_dict(data_dictionary)
df = df.pivot(index='Country or Area', columns='Year', values='Value')df.reset_index(level=0, inplace=True)

基本上,我们需要为每一列或每一行创建一个字典,然后将字典转换为 dataframe。

输出:

  1. SQL — SQL 数据库使用主键和外键在表中存储数据

要从 SQL 数据库中读取数据,您需要将数据存储在数据库中。要了解如何将 CSV 转换为 SQL DB,请阅读这篇 博客

SQLite3 对熊猫

import sqlite3
import pandas as pd# connect to the database
conn = sqlite3.connect('population_data.db')# run a query
pd.read_sql('SELECT * FROM population_data', conn)

对熊猫的 SQLAlchemy

import pandas as pd
from sqlalchemy import create_engineengine=create_engine('sqlite:////home/workspace/3_sql_exercise/population_data.db')
pd.read_sql("SELECT * FROM population_data", engine)

5.从网络中提取数据是一个非常累人的过程。但是很多公司已经通过 API 公开了他们的数据。API 通常以 JSON 或 XML 格式提供数据。有些 API 是公共的,您不需要登录,而有些是私有的,用户需要生成一个 API 密钥。

import requests
import pandas as pdurl = '[http://api.worldbank.org/v2/countries/br;cn;us;de/indicators/SP.POP.TOTL/?format=json&per_page=1000'](http://api.worldbank.org/v2/countries/br;cn;us;de/indicators/SP.POP.TOTL/?format=json&per_page=1000')
r = requests.get(url)
r.json()

不同网站的 API 调用是不同的,这里我们使用请求库来获取 JSON 格式的数据。在这里 阅读更多关于不同 API 结构的信息

了解如何使用熊猫在地方参数一劳永逸

原文:https://towardsdatascience.com/learn-how-to-use-pandas-inplace-parameter-once-and-for-all-5a29bb8bf338?source=collection_archive---------14-----------------------

对流行的 pandas 函数何时使用、何时不使用 inplace 参数的快速解释。

图片由 995645 来自 Pixabay

简介

我注意到初学者,有时甚至是更高级的数据科学家在操作数据帧时,对如何在 pandas 中使用 inplace 参数感到困惑。

更有趣的是,我没有看到太多解释这个概念的文章或教程。不知何故,它似乎是假定的知识或不言自明的概念。不幸的是,这并不是对每个人都如此简单,因此本文试图解释什么是 inplace 参数以及如何正确使用它。

使用现场参数的功能

让我们来看一些使用代替的函数的例子:

  • 菲尔娜
  • 德罗普纳()
  • 排序值()
  • 重置索引()
  • 排序索引()
  • 重命名()

我已经从头开始创建了这个列表,可能有更多的函数使用代替作为参数。我并不记得所有的函数,但是几乎所有将作为参数的 pandas DataFrame 函数都会以类似的方式运行。这意味着在处理这些问题时,你将能够运用你将在本文中学到的同样的逻辑。

创建一个样本数据框

为了说明位置的用法,我们将创建一个样本数据框。

import pandas as pd
import numpy as np
client_dictionary = {'name': ['Michael', 'Ana', 'Sean', 'Carl', 'Bob'], 
                     'second name': [None, 'Angel', 'Ben', 'Frank', 'Daniel'],
                     'birth place': ['New York', 'New York', 'Los Angeles', 'New York', 'New York'],
                     'age': [10, 35, 56, None, 28],
                     'number of children': [0, None, 2, 1, 1]}
df = pd.DataFrame(client_dictionary)
df.head()

我们创建了一个具有五行的数据框,其中包含以下各列:姓名、第二个名字、出生地、子女数量。注意年龄、姓氏、子女列(NaNs)有部分数值缺失。

我们现在将演示 dropna()函数如何与 inplace 参数一起工作。因为我们想要检查两种不同的变体,所以我们将创建原始数据框的两个副本。

df_1 = df.copy()
df_2 = df.copy()

dropna()with in place = True

让我们从 inplace=True 的变体开始。下面的代码删除所有缺少值的行。

df_1.dropna(inplace=True)

如果你在 Jupyter 笔记本上运行这个,你会看到这个单元没有输出。这是因为 inplace=True 的函数不会返回任何内容。它使用所需的操作修改现有的数据帧,并在原始数据帧上“就地”执行。

如果您在数据框上运行 head()函数,您应该会看到两行被删除。

df_1.head()

dropna() with inplace = False(默认)

现在让我们用 inplace = False 运行相同的代码。注意,这次我们将使用 df_2 版本的数据帧。

df_2.dropna(inplace=False)

如果你在 Jupyter notebook 中运行这段代码,你会看到有一个输出(上面的截图)。inplace = False 的函数返回删除了行的数据框。

记得当在位被设置为时,没有返回任何东西,但是原始数据帧被修改。

那么这次原始数据帧会发生什么情况呢?让我们调用 head()函数来检查。

df_2.head()

原数据框不变!发生了什么事?

使用 inplace=False 时,将创建并更改新对象,而不是原始数据框。如果想要更新原始数据框以反映被删除的行,则必须将结果重新分配给原始数据框,如下面的代码所示。

df_2 = df_2.dropna(inplace=False)

但是等等!这正是我们在使用 inplace=True 时所做的事情。是的,这最后一行代码相当于下面一行:

df_2.dropna(inplace=True)

后一种方法更优雅,它不会创建一个中间对象,然后将这个中间对象重新分配给原始变量。它直接更改原始数据框,因此,如果您打算更改原始数据框,则首选它。

简单,不是吗?

那么,为什么会有这么多的错误呢?我不确定,可能是因为有些人还不明白如何正确使用这个参数。让我们来看看一些常见的错误。

图片来自pix abaySyaibatul Hamdi

常见错误

  • 对数据帧的一部分使用 in place = True

我已经注意到好几次了。让我们回到本文开头的数据框示例。有些自由列没有值:ssecond name、agenumber of children

如果我们只想从第二个姓名和年龄列中删除 None,并保持孩子数量列不变,我们该怎么办?

我见过有人尝试做以下事情:

df[['second name', 'age']].dropna(inplace=True)

这可能是你不想做的事情!

事实上,这应该抛出以下警告。

显示这个警告是因为熊猫设计师很好,他们实际上试图警告你不要做你可能不想做的事情。代码正在更改只有两列的数据帧切片,而不是原始数据帧。这是因为您选择了数据帧的一个切片,并将 dropna()应用于这个切片,而不是原始数据帧。

为了纠正它,在带有子集参数的整个数据帧上使用 dropna()。

df.dropna(inplace=True, subset=['second name', 'age'])
df.head()

这将导致在的第二个名字的年龄列中有空值的行从数据框中被删除。

  • 将变量值赋给 inplace = True 的结果

这个我也看过好几次了。

df = df.dropna(inplace=True)

这也是你永远不应该做的事情!你只是把 None 重新分配给 df 的值。请记住,当您使用 inplace=True 时,不会返回任何内容。因此,该代码的结果将不会给 df 赋值。

总结

我希望这篇文章为你揭开了参数的神秘面纱,你将能够在你的代码中正确地使用它。快乐的数据框操作!

原载于 aboutdatablog.com: 学*如何一劳永逸地使用熊猫原地参数2020 年 7 月 15 日。

PS:我正在 Medium 和上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的* 邮件列表 在我每次写新文章的时候得到通知。如果你还不是中等会员,你可以在这里加入。***

下面还有一些你可能喜欢的帖子

** [## Pandas 数据操作函数:apply()、map()和 applymap()

以及如何在熊猫身上正确使用它们…

towardsdatascience.com](/pandas-data-manipulation-functions-7b3519fc1370) [## 9 熊猫有效数据分析的可视化技术

学*如何使用折线图、散点图、直方图、箱线图和其他一些可视化技术

towardsdatascience.com](/9-pandas-visualizations-techniques-for-effective-data-analysis-fc17feb651db) [## Jupyter 笔记本自动完成

数据科学家的最佳生产力工具,如果您还没有使用它,您应该使用它…

towardsdatascience.com](/jupyter-notebook-autocompletion-f291008c66c) [## 9 大 Jupyter 笔记本扩展

改进笔记本电脑功能,提高您的工作效率

towardsdatascience.com](/top-9-jupyter-notebook-extensions-7a5d30269bc8)**

学*线性代数的机器学*从最好的

原文:https://towardsdatascience.com/learn-linear-algebra-for-machine-learning-from-the-best-ae95ab92c6f9?source=collection_archive---------6-----------------------

ML 和 DS 学*线性代数的顶级免费资源

图像由像素生成

介绍

大约 4、5 年前,我坐在一堂数学课上,老师第一次介绍向量的话题。

"矢量是既有方向又有大小的线段."

这时候我以为我已经永远不再学数学了。在学校,每当老师介绍一些大的数学话题时,他们总是说这个概念在现实生活中非常重要,我应该学*它。我从不问为什么,只是顺其自然。原因是我真的很喜欢数学,擅长数字。我甚至参加了一些数学竞赛,赢了一些。

但是当涉及到向量时,我就是不明白尖尖的线怎么会在现实生活中有应用(我不会责怪任何人不解释)。那时候,学这样的东西似乎很荒唐,我对数学失去了兴趣。

直到今年,我从未见过我的数学知识在现实生活中的应用。然而,当我决定学*计算机科学并发现数学是我感兴趣领域的基石——机器学*时,事情发生了变化。

机器学*应该什么时候学线性代数?

机器学*由几种适合不同现实生活问题的算法组成。任何一个有扎实编程基础的人都可以利用现成的工具、库和模型成为一名优秀的机器学*工程师。但是如果你想成为这个领域的真正专家,你就不能逃避学*线性代数的一些概念。

任何机器学*算法,尤其是深度学*的掩盖下发生的所有魔法,大多是线性代数数学。所以,在我开始学* ML 之前,很多人都坚信线性代数是一个很大的先决条件。不只是线性代数,我也碰到很多帖子说多元微积分和 PCA 也很重要,不容忽视。我想成为一名“专业人士”,所以我认真考虑了这些建议,并在 Coursera 上找到了一门教授上述所有内容的课程。还有…大错特错!

我读到的所有东西都说数学很重要,但它们从没说过什么时候。事实证明,在你开始研究复杂的算法和解决实际问题之前,ML 有太多的东西要学。谢天谢地,在我学完一些线性代数并准备转向多元微积分的时候,我发现了这个真理。

所以,我的建议是这样的:刚开始不用数学就进入学*机器学*或者数据科学。无论何时开始学*算法,都要尽可能地学*每一个算法。如果你不理解背后的数学,那就开始学*数学课程,填补你的知识空白。这就是你进步的方式,边做边学。不要犯这样的错误,在你还不知道它有什么用之前就去学*。否则,在你开始应用它们之前,你会被烧坏几次,忘记你的大部分知识。

现在,正如承诺的那样,让我们继续学*线性代数的实际资源。

3 蓝色 1 棕色,线性代数播放列表

我们名单上的第一位是 YouTube 传奇人物格兰特·桑德森,他是 YouTube 频道 3Blue1Brown 的创始人。他用 Python 写的一个将数学概念形象化,如此美丽,你会爱上他的视频。

他的线性代数 播放列表只包含了线性代数的 15 个章节,然而,却在 YouTube 上获得了* 2000 万的浏览量。他的所有视频都旨在给出每个数学概念背后的完整直觉,不会让你对复杂的计算细节感到厌烦。

他使用 2D 和 3D 动画的解释是最高质量和难忘的。这对于线性代数案例特别有用,因为你将会处理大量的向量和线性变换,这些都是不能也不应该用纸笔来教授的主题。要掌握线性代数,你需要每个题目的几何直觉,然后,它的代数表示。

总而言之,格兰特·桑德斯给了数学界它所需要的视觉元素,此外,我喜欢他的视频和 pi 学生的配乐。😃

特雷福·巴泽特,线性代数全教程

接下来是特雷福·巴泽特教授的线性代数完整 YouTube 课程。他是辛辛那提大学的数学教授。他在 YouTube 上关于线性代数的课程是视觉解释和通过定义明确的例子进行教学的完美结合。

他首先用视觉动画教授每个主题,并展示一般公式和计算方法。然后通过解题进一步强化知识,不用复杂的字母和符号,而是用实际的矩阵和向量。你可能会惊讶,有多少教师没有超越我们都讨厌的混乱公式。

可汗学院,线性代数播放列表

最后但同样重要的是,我们还有另一位著名的教育家和在线导师萨尔·汗——汗学院的创始人。他在 YouTube 或他的网站上的线性代数 播放列表可以被认为是对线性代数的深入钻研。

有超过 140 个视频,几乎所有的视频都至少持续 15 分钟。他通过理论和例子很好地解释了每个主题。他还为线性代数中的许多主题提供了证明。我不建议观看他的所有视频,因为并非所有视频都与机器学*有关。

但是如果你想要一个系统的学*线性代数的方法,并完全掌握它的基础知识,这是一个学*的好地方。

我应该选择哪一个?

我的建议是不要选择一个,而是结合使用这三个。其中任何一个都不能涵盖你需要的所有主题。我所做的是观看 3B1B 中的一个章节,并观看其他两个章节中相应的主题视频。这样我就有了我所需要的视觉直觉,以及所有缺少的计算信息和它们在例子中的应用。

使用 scikit-learn 和 NBA 数据学*线性回归:体育数据科学

原文:https://towardsdatascience.com/learn-linear-regression-using-scikit-learn-and-nba-data-data-science-with-sports-9908b0f6a031?source=collection_archive---------14-----------------------

使用 Python 对 NBA 球员的真实数据进行实际线性回归,可视化结果和学*(包括数据和代码)

用 Python 构建 NBA 球员表现模型(图片由作者提供)

数据科学为其从业者实现了许多非常惊人的任务,并在许多方面从小到大改变了我们的生活。当企业预测产品需求时,当公司发现在线欺诈交易时,或当流媒体服务推荐观看内容时,数据科学通常是实现这些创新的润滑油。

这些类型的数据科学创新基于回归分析,也就是说,它们是关于理解输入变量和输出变量之间的关系。

与分类分析一样,回归是两种基本类型的数据问题之一,了解它如何工作以及如何执行它们是数据分析和数据科学的重要组成部分。

因此,我想在这篇文章中展示如何使用回归分析来识别数据中的模式并用于预测目的。首先,让我们从简单的线性回归技术开始,看看它们能教会我们什么。

我们将构建一个简单的模型来预测 NBA 球员的描述性统计数据,称为 Box-Plus-Minus (BPM)

来自关于 BPM —图片:Basketball-Reference.com

BPM 旨在衡量球员的贡献,它基于球员的统计数据、位置和球队的表现。

在这种情况下,我们将仅基于每个玩家的个人统计数据来构建该模型。因此,该模型不仅要估计 BPM 如何与个人统计数据相关,还要估计个人统计数据如何与集体团队绩效相关,此处未包括。

最后,在我们建立了一个模型之后,我们将查看哪些数据点形成了异常值/高误差点,并讨论这在该模型的上下文中可能意味着什么。

准备

接下来,安装几个软件包— numpypandassklearn (scikit-learn),还有plotlystreamlit。用一个简单的pip install [PACKAGE_NAME]安装每个(在您的虚拟环境中)。

这篇文章的代码在我的 GitHub repo here (作为data_predict_bpm.py)上,所以你可以下载/复制/叉走你喜欢的内容。

哦,这是我写的关于使用 NBA 数据的一系列数据科学/数据分析文章的一部分。所有的钱都会去回购,所以你要睁大眼睛!(这是我之前写的一篇关于可视化数据集进行数据探索的文章

如果您正在跟进,请使用以下内容导入密钥库:

import numpy as np
import pandas as pd
import sklearn
import plotly.express as px
import streamlit as st

我们准备好出发了。

构建玩家模型——从汤到坚果

数据预处理

大多数数据科学项目都是从乏味的任务开始的,比如项目范围、数据收集和数据清理。幸运的是,我们正在使用的数据集将让我们绕过这一切。

尽管如此,它并没有完全减轻我们对预处理的所有责任。

在预处理中,就像在每一步一样,我们需要记住我们要达到的目标。在这种情况下,我们正在构建一个使用玩家统计数据来预测 BPM 的模型。

因为 BPM 是一个“比率”统计,所以使用与每场比赛相关的统计是有意义的。因此,让我们加载每场比赛的统计数据集(player_per_game.csv)并检查它。(有关使用交互式 web 应用程序探索该数据集的文章,请在此处查看我的文章。)

查看数据,我们看到一些玩家有异常数据。这里有一个例子,绘制球员在两分球和三分球上的命中率。

请注意由于样本量小而导致的数据失真(图片由作者提供)

你会注意到在这张图表中的直的垂直线或水平线中的点群。这些都是小样本的伪影,导致像 0%、60%或 100%这样的百分比。)精度。一名球员 3 投 100 中,整体命中率 80%。这些数据点不太可能代表玩家的实际能力,并且可能会污染我们构建的任何模型。

所以让我们过滤掉这些玩家。我们应该怎样做呢?很明显,我们可以过滤掉具有一定准确度的球员,但这不是根本问题——这是症状,不是原因。原因是某些球员的样本量很小。

考虑到这一点,让我们用一个统计数据来代表每个球员产生这些统计数据的机会,也就是总的上场时间。

上场时间的分布如下所示:

分钟直方图(图片由作者提供)

因此,让我们按照至少 500 分钟的播放时间来过滤数据帧。

df = df[df["mp"] > 500]

数据现在应该看起来“干净”多了。你自己看看吧。

因为我们正在构建一个线性回归模型,所以让我们保持一些连续的变量来简化事情。

cont_var_cols = ['g', 'mp_per_g', 'fg_per_g', 'fga_per_g', 'fg3_per_g', 'fg3a_per_g', 'fg2_per_g', 'fg2a_per_g', 'efg_pct', 'ft_per_g', 'fta_per_g', 'orb_per_g', 'drb_per_g', 'trb_per_g', 'ast_per_g', 'stl_per_g', 'blk_per_g', 'tov_per_g', 'pf_per_g', 'pts_per_g', 'mp']
cont_df = df[cont_var_cols]

将所有最新的数据放在一起(为了实时可视化,添加了一点 Streamlit),我们得到:

数据探索

让我们暂停一下,检查各种输入变量和目标变量(BPM)之间的相关性。

首先,场均得分和 BPM 之间:

场均得分和 BPM 之间的相关性——非常非常好!(图片由作者提供)

场均助攻呢?

场均助攻与 BPM 的相关性——还不错!(图片由作者提供)

现在,并不是所有的统计数据都与目标相关联—请看下一个统计数据:

场均助攻和 BPM 之间的相关性——可能接*于零(图片由作者提供)

这看起来像是典型的非相关关系!不要相信我的话,看看这个教科书上的例子:

相关性示例表——中上图是否让你想起了什么?(图片:维基百科)

这很直观,对吗?为什么一个球员的平均个人犯规次数与他们的能力有任何关系,除了他们在球场上花了多少时间?即便如此,我认为这种相关性还是很弱。

接下来,我们将看看单个特征的规模。我们可以将数据列的最小、平均、最大和标准偏差可视化,如下所示:

feat_desc = cont_df.describe()[cont_var_cols].transpose().reset_index().rename({'index': "var"}, axis=1)
feat_fig = px.bar(feat_desc[['var', 'mean', 'std']].melt(id_vars=['var']), x="var", y="value", color="variable", barmode="group")

各种特征的统计描述符—范围由一个统计数据决定!(图片由作者提供)

即使在对数标度中,它们也是极其易变的!(图片由作者提供)

这里有一个相当大的范围。这可能会导致一些变量对模型的影响超过其他变量,因此调整每个输入变量通常是一种好的做法。

所以让我们将数据标准化。Scikit-learn 有一个模块preprocessing.StandardScaler(),它基本上使这个过程一步完成。像这样实例化一个scaler:

from sklearn import preprocessing
scaler = preprocessing.StandardScaler().fit(cont_df)

数据可以缩放为:

X = scaler.transform(cont_df)

为了确保缩放有效,我们可以再次绘制缩放后的变量,从而得到这个极其无聊的图!

成功的攀登,还是一堵墙的轮廓?(图片由作者提供)

现在我们(终于)准备好开始构建一些模型了。

给我做个模型

作为第一步,我们将数据分成两组—一组训练集和一组测试集。让我们保持简单,现在使用 80/20 规则。输入变量可以这样分割:

X_train, X_test = model_selection.train_test_split(X, train_size=0.8, random_state=42, shuffle=True)

目标变量是这样的:

Y = df["bpm"].values
Y_train, Y_test = model_selection.train_test_split(Y, train_size=0.8, random_state=42, shuffle=True)

现在我们在这里,scikit-learn 的神奇之处在于,实际应用一个特定的算法非常简单。

对于随机梯度下降回归器,建立如下模型:

mdl = linear_model.SGDRegressor(loss="squared_loss", penalty="l2", max_iter=1000)
mdl.fit(X_train, Y_train)

然后用以下公式进行预测:

Y_test_hat = mdl.predict(X_test)

我们可以将预测与基本事实(实际 Y 值)进行比较,如下所示:

test_out = pd.DataFrame([Y_test_hat, Y_test], index=["Prediction", "Actual"]).transpose()
val_fig = px.scatter(test_out, x="Prediction", y="Actual", title="Stochastic Gradient Descent model prediction of BPM vs ground truths")

SDG 模型预测与实际值(图片由作者提供)

这是个不错的结果。我们犯了什么错误?让我们以 MSE(均方误差)来计算它,这又是用 sklearn 的一行计算:

from sklearn import metrics
mse = metrics.mean_squared_error(Y_test, Y_test_hat)

使用随机梯度下降回归器,MSE 值为:1.19。

那是我们能做的最好的吗?有可能,但也可能没有。有很多很多算法可以尝试。Scikit-learn 文档为提供了这份线性模型指南,这份指南可能值得一读,或者至少提供了一份方便的参考。他们还提供这个地图来帮助选择一个估计器(不仅仅是线性模型,但是它们在那里)

现在,让我们尝试几个不同的回归变量,看看它们的表现如何:

试一个岭回归模型:

mdl = linear_model.Ridge(alpha=.5)
mdl.fit(X_train, Y_train)

岭回归模型预测值与实际值(图片由作者提供)

支持向量回归模型:

mdl = svm.SVR(kernel='rbf', degree=3)
mdl.fit(X_train, Y_train)

支持向量回归模型预测值与实际值(图片由作者提供)

你可以看到他们的行为都略有不同。

MSE 值为:

  • 随机梯度下降:1.19
  • 岭回归:1.17
  • 支持向量回归:0.9

组合在一起的代码如下所示:

在我们的简单测试中,支持向量回归对这组数据表现最好。这当然没有多大意义——我没有做过任何超参数调优,只使用了相对较小的数据集,并且使用了一个测试/训练集分割。但希望这足以让你大致了解。

这就是用 Python 构建线性回归模型的基础——如果你对机器学*相对陌生,并且认为它比你想象的要简单——我同意。如今,实现机器学*算法很容易。

对于深度学*等更复杂的方法也是如此,我们将在后面看到。对我来说,就像在其他技术领域一样,关键在于问题的表述。所以我鼓励你投入进去,看看你还能做些什么。

额外讨论——这里的错误意味着什么吗?

通常,基础事实和模型之间的误差并不意味着什么,除了——这是模型和现实生活样本之间的差异。但有时,误差可能是系统性的,甚至表明模型或输出变量的某些固有特性。

在我们的例子中,回想一下 BPM 是一个与团队绩效相关的统计数据,而模型仅仅来自个人绩效。

所以,我想知道预测(仅基于个人数据)和实际的 BPM 数据之间的差异是否会识别出对球队有额外价值,但没有显示在数据上的球员。

这就是结果。在这里,我只显示了排名靠前的球员(BPM 值为 6 或更高),并根据球员的位置和时代进一步细分了结果。

杰出的玩家,比较预测和实际表现(图片由作者提供)

通过查找 BPM 表现超出模型的最佳季节有:

超额表现者(与我们的模型相比)(图片由作者提供)

相反,这些玩家的实际 BPM 远低于预测。

和…表现不佳者(对比模型)(图片由作者提供)

我的假设是,具有较高“相对价值”统计数据的球员往往是那些让队友变得更好的球员(例如斯蒂芬·库里,因为他的重力,或者迈克尔·乔丹,因为他是迈克尔·乔丹),但另一种解释可能是,这表明那些幸运地拥有伟大队友的球员(例如 2012 年的马努)。

有趣的是,勒布朗·詹姆斯三次出现在名单上,因为他的表现低于他预测的 BPM 数据——随你怎么想。我会注意到,2017 年的骑士队在某种程度上只是一个疲软的东部联盟的 2 号种子,2011 年的热火队是热火队真正团结起来之前的第一年,而 2019 年的湖人队或多或少是勒布朗周围一支球队的一个小垃圾箱。

无论如何,关于篮球方面的事情已经说得够多了——我可能下次再写。我只是想强调错误不仅仅意味着模型和事实之间的差异。

今天到此为止。我希望那是有趣的。我将跟进一些其他机器学*的例子,一些还有深度学*/神经网络模型,这对我来说真的很令人兴奋。

ICYMI,这是我之前写的一篇关于用 Plotly 和 Streamlit 探索数据集的文章:

[## 使用定制的交互式 web 应用程序探索任何数据:体育数据科学

了解如何使用领先的数据可视化工具构建交互式、可重复使用的 web 应用程序进行探索性数据分析…

towardsdatascience.com](/explore-any-data-with-a-custom-interactive-web-app-data-science-with-sports-410644ac742)

在你离开之前——如果你喜欢这个,在推特上打个招呼/关注,或者点击这里更新。

您可能还会对以下内容感兴趣:

[## Plotly Dash 与 Streamlit——哪个是构建数据仪表板 web 应用程序的最佳库?

用于共享数据科学/可视化项目的两个顶级 Python 数据仪表板库的比较——

towardsdatascience.com](/plotly-dash-vs-streamlit-which-is-the-best-library-for-building-data-dashboard-web-apps-97d7c98b938c)

交互式学*机器学*概念

原文:https://towardsdatascience.com/learn-machine-learning-concepts-interactively-6c3f64518da2?source=collection_archive---------30-----------------------

五个免费可用的工具,直观地分解了复杂的机器学*概念

罗斯·斯奈登在 Unsplash 上的照片

机器学*算法如何在引擎盖下工作是许多人不理解的一个方面。一层 CNN 看到了什么?反向传播是如何工作的?层中的权重究竟是如何更新的?这些是我们脑海中反复出现的一些问题。这些概念对于那些想要在将数学方程与理论联系起来的过程中度过一段艰难的时间的初学者来说可能是特别难以理解的。好消息是,一些人理解这种痛苦,并希望提供替代形式的学*。本文汇集了五个这样的工具,它们超越了理论,而是直观地解释了标准的机器学*概念。

1.MLaddict.com

来源:https://www.mladdict.com/

mladdict.com如果你想理解以下四种算法的基本数学概念,这是一个极好的工具:

  • 线性回归
  • 神经网络
  • 循环网络
  • q 学*代理

它会在您的浏览器中打开一个模拟器,然后演示算法的每个阶段会发生什么。下面是一个模拟器的演示,展示了如何使用梯度下降算法进行线性回归。

作者视频|内容来自mladdict.com

2.直观解释

来源:mladdict.com

直观解释(EV) 是一个旨在将挑战性的想法直观化的实验。它的灵感来自 Bret Victor 的作品探索性解释。这个网站上最后一篇更新的文章可以追溯到 2017 年,所以你不会找到任何最新的材料,但那里的那些简直太棒了。我在我的一些博客中借用了一些他们的视觉解释,因为他们创作得非常漂亮。下面先睹为快 EV 如何解释主成分分析(PCA)的概念。查看他们网站上其他令人兴奋的作品。

作者视频。来自的内容进行了直观解释(EV)

3.视觉理论

来源:https://seeing-theory.brown.edu/

见理论 是一个提供概率和统计直观介绍的网站。该网站的目标是通过交互式可视化使统计数据更容易获取。该书为以下六个统计概念提供了直观的解释。

  • 基本概率
  • 复合概率
  • 概率分布
  • 频繁推理
  • 贝叶斯推理
  • 回归分析

我们来看看看见论是如何介绍概率论的基本概念的。

作者视频。内容来自 见论

4.R2D3:统计和数据可视化

来源: R2D3:统计和数据可视化

R2D3 是用交互设计表达统计思维的实验。它以结构化的方式提供了机器学*概念的可视化介绍。目前,网站上提供了以下主题:

下面是你如何可视化决策树如何进行分类

作者视频|内容来自 R2D3

5.CNN 解说者

来源:https://poloclub.github.io/cnn-explainer/

CNN 讲解人 是一个交互式可视化系统,旨在帮助非专家了解卷积神经网络(CNN)。CNN Explainer 是一个结合了 CNN 的模型概述和动态可视化解释的工具,可以帮助用户理解 CNN 的底层组件。 通过跨抽象层次的平滑过渡,我们的工具使用户能够检查低级数学运算和高级模型结构之间的相互作用。

欲了解更多信息,请查看我们的手稿 CNN 解释者:用交互式可视化学*卷积神经网络或尝试使用现场演示这里。下面是如何使用该工具的快速演示。

演示视频“CNN 讲解者:用交互式可视化学*卷积神经网络”

结论

最后,我们看了五个有用的工具,它们让机器学*和统计概念变得更有趣。一幅画胜过千言万语,这是正确的说法。当复杂的术语以互动的形式呈现时,它们会变得更容易理解。这也有助于降低初学者进入机器学*领域的门槛。

以有趣的方式学*机器

原文:https://towardsdatascience.com/learn-machine-learning-the-fun-way-554833891b73?source=collection_archive---------7-----------------------

严格的课程让你享受学*。

最*,我收到了一些读者的回复,他们让我写一些关于如何从机器学*/数据科学开始,以及从哪些资源开始是正确的。我犹豫了一下,因为已经有很多关于这个主题的“初学者指南”文章了。

然而,我也注意到,那里的许多文章更像是无穷无尽的在线课程列表的集合。而 乐趣 学*的成分很大程度上被忽略了。此外,来自非技术背景(我第一个学位学的是经济学),我知道放弃有多容易。学*的道路需要大量的 努力 ,大量的 奉献好奇心 。没有捷径可走,但你肯定可以让它变得更有趣、更令人兴奋。在这篇文章中,我试图向你展示一幅最清晰的机器学*(ML)的画面,以及你应该如何从它开始而不被淹没。这是我们的计划:

  • 了解机器学*的构建模块;
  • 必修基础;
  • 学*策略+如何娱乐自己的技巧;
  • 如何让知识成为你的?

让我们开始吧。

1.机器学*的基石

机器学*的构建模块可以总结如下:

机器学*的基石。

这肯定不是一个详尽的列表,但你得到的想法。你遇到的所有模型和算法背后都有一些支配性的理论。这是因为机器学*可以从很多角度来看:统计的角度,计算复杂度的角度等等。当你看到一些主要介绍数学定理和证明的 ML 书籍时,不要感到困惑,而其他一些书籍则更注重数据和编程语言的实用性。他们只是从不同的角度看 ML。

来源:https://anacuder.com/o-que-significa-in-a-nutshell/

从这些不同的理论中,我们得出了不同类型的学*模型(线性、决策树、神经网络等。).

然而,为了使模型能够在真实数据集上很好地概括,我们需要采用一些额外的技术(例如,正则化以避免过度拟合,集成方法以减少学*模型中的偏差/方差)。这就是同一款车型的各种变种的来源。例如,添加了一些正则化项的线性回归创建了新类型的模型(例如套索、山脊或弹性网)。决策树也是如此:使用不同的集成方法,我们提出了随机森林、AdaBoost 等。

最后,根据您如何在真实数据集上应用模型,模型可以分为不同的范例。例如,当在标记数据集上训练时,神经网络是监督学*算法。然而,当它被训练来重建自己(例如自动编码器)时,它就变成了一种无监督的算法。还有其他混合范式,如半监督学*,但一旦你掌握了基本知识,你会在一眨眼的功夫就明白了。因此,很好地了解核心,事情将开始步入正轨。

2.必需的基础知识

来源:https://www . bouvet . no/bouvet-deler/6-机器学*入门提示

你可能已经意识到,我们显然需要温*我们的数学统计学才能征服机器学*。

其实你还需要一些计算机科学知识和编程技巧。但是,在将机器学*应用于您的问题时,您将通过实践自然地获得这些技能。

3.学*策略

还没睡吗?现在,让我们看看我们应该如何征服机器学*的这个广阔领域。

首先,做好基础工作

当你还没有很好的基础时,从一个在线课程转到另一个是很诱人的。许多在线课程就其核心内容而言基本上是相同的,尽管它们可能以不同的方式交付或使用不同的编程语言。所以明智地利用你的时间吧!你需要的是彻底完成一门课程,这门课程会给你所有你需要的基础知识。避免编程语言特定的课程,比如“Python 中的机器学*”,因为它们会让你失去对基础知识的关注。

我得到了这个教训。我发现自己甚至在完成了相当多的 ML 课程后,还在思考一些非常基本的概念,如最大似然估计或单值分解。无论你为你的 ML 项目写了多少次 model.fit(X_train,y_train)model.predict(X_test) ,这些差距都是很难弥补的。因此,把基础知识做好你就可以在将来不断扩展你在“扩展”方面的知识,比如图像处理和自然语言处理。请记住,你的目标是成为一名有能力的数据科学家/机器学*者,而不是只知道在数据集上应用 Sklearn 的人。

ML 入门推荐:

  1. Coursera 的机器学*——吴恩达(对 ML 最好的直观介绍。编程练*在 Matlab 中,但是如果你不熟悉 Matlab,现在可以跳过这些练*)。
  2. CS540 机器学*作者 Nando de Freitas (几乎所有 ML 概念和算法的综合数学基础)。

我们大多数人的学*曲线是这样的。来源:https://medium . com/@ pwalukagga/learning-curve-experience-at-SLC-boot camp-day 3-9f8f 34458959(改编)

如何让自己开心的小贴士:

  • Youtube 是你最好的朋友。每当事情变得太抽象或者你被某样东西卡住了,就去 Youtube 上找找看!一些有用的 Youtube 频道(仅举几个)是:
  1. 3 蓝色 1 棕色通道
  2. 亚历山大·伊勒频道
  3. JB 统计
  4. 可汗学院
  • 使用视觉工具进行学*,正如我在另一篇帖子中所描述的。
  • 什么时候开始觉得无聊?这里有一些真正有趣的书,会让你在学*数学和统计学时充满乐趣:
  1. 如何用统计数据撒谎(达雷尔·赫夫著)
  2. 如何不犯错:数学思维的力量(乔丹·艾伦伯格)

二、基础编程

Coursera、Udemy、DataCamp 上有很多不错的学* R/ Python 的在线课程,这里就不赘述了。最好的学*方法,至少对我来说,是练*,大量的练*。下载一个玩具数据集,做一些操作,看看你能走多远。

如何让自己开心的小贴士:

  • 你可以收集你自己的数据集(关于你自己的)。保存一个你日常生活用品的数据集,获取你每月支出的银行对账单,浏览你最喜欢的网站。然后你可以用它们做大量有趣的分析。
  • 找一个社区,和他们互动。如果你被卡住了,你可以在 Stackoverflow 上发布你的问题。回答别人的问题也是一种非常好的学*方式。此外,在许多在线课程中,你可以找到比你知道得更多或更少的同学。在任何情况下,这种互动都会让你感到与他人有联系,并在过程中给你带来些许快乐。

当你第一次开始时,你想做的每一件事情都很简单。你编程越多,你就越不需要谷歌,你开始学*成为一个高效和干净的程序员。你基本上可以像写诗一样写代码(嗯,我想你比我更擅长写诗)。

4.让知识成为你的

在某些时候,你可能会觉得自己对所学的知识仍然没有信心。你可以这样做:

教导他人

内化你的知识的最有效的方法是别人。写一篇关于你所学到的东西的博文。给一个朋友解释,一个不了解这个概念的同事。做一个关于这个话题的报告。尽你所能解释清楚,穿过浅层,把它修剪到核心。使用图形、图表、图画或任何方式来传达你的信息。

在工作/学*中应用编程

如果你有一份工作,试着应用编程来自动化一些工作任务,无论是操作仪表板的数据,还是操作 Excel 文件!这将帮助您快速熟悉和熟练编程。

如果您正在学* Python,以下是您可以尝试的内容:

  1. 用 Python 自动化枯燥的东西

辅助项目(与朋友一起)

就你关心的话题找一个 ML 挑战,和一个朋友一起做。通过从一些流行的内核派生代码,你总是可以在 Kaggle 竞争中“生存”,你可能还会学到一些新东西,但这并不真正有趣。和朋友在一起,你会比别人更有动力保持忠诚,变得更好。

祝你机器学*之旅一帆风顺。享受学*!

以斯坦福的方式学* NLP 第 1

原文:https://towardsdatascience.com/learn-nlp-the-stanford-way-lesson-1-3f1844265760?source=collection_archive---------28-----------------------

给你的邀请,介绍自然语言处理和词向量

Unsplash 上由伊尼基·德尔·奥尔莫拍摄的照片

自然语言处理(NLP)的人工智能领域,通过其庞大的语言模型——是的,GPT 3 号,我在看着你——展示了它被视为机器执行最独特语言任务能力的一场革命。

由于这一点,公众对整体的看法是分裂的:一些人认为这些新的语言模型将为天网类型的技术铺平道路,而另一些人则认为它们是炒作推动的技术,将在很短时间内或根本不会存在于尘土飞扬的架子或硬盘驱动器中。

邀请

受此激励,我创作了这一系列故事,以一种友好的方式从头开始接* NLP。

我也邀请你和我一起参加这个系列来学* NLP,并且精通人工智能语言模型塑造的未来。

要加入我,你需要有一点 Python 和 Jupyter 笔记本的经验,在大多数情况下,我甚至不会要求你在你的机器上安装任何东西。

这个系列将在统计学和微积分的深度上与斯坦福课程有显著的不同。我将尽力避免涉及细节,因为在大多数情况下,我们将使用已经实现了我们将需要的大部分结构的 Python 库。但是,如果你想了解更多关于这些主题的知识,我强烈建议你学*课程笔记。

我们将使用 Deepnote 创建我们的 Python 笔记本,并使用云开发整个课程。

为什么选择 Deepnote?Deepnote 通过实时协作扩展了 Jupyter 笔记本的体验,并提供无预装的免费计算。你可以在这里复制我的 Deepnote 笔记本,并跟随我完成这个项目以获得最佳体验。

对于这门课程,我们将使用斯坦福大学 2020 年冬季 CS224N 材料的指南,因为它有一个全面的方法,一个包含课程的 Youtube 播放列表,以及斯坦福大学学生提供的其他资源。如果你想了解更多的课程,你可以访问它的网站

我们将首先从自然语言处理的基础开始,然后学*它的关键方法:RNN、注意力、变形金刚等等。本课程结束时,我们将能够创建以下一些应用程序:

  • 字义
  • 依存句法分析
  • 机器翻译
  • 问题回答

自然语言处理简介

“自然语言处理 ( NLP )是语言学计算机科学人工智能的一个分支,涉及计算机和人类语言之间的交互,特别是如何给计算机编程,以处理和分析大量的自然语言数据。”—维基百科

根据这个定义,除了看到 NLP 是一个广阔的多学科领域,它还将我们引向一个问题:我们如何让计算机程序分析自然语言数据?

第一步是学*我们如何在计算环境中表示单词及其含义。

词语的含义

几年来,NLP 的工作主要是基于对单词同义词和上位词的建模。找出这些集合的一个方法是查看字典中的单词定义。

我们可以通过使用 Python 和一个名为 NLTK 的库来做到这一点。

试用 NLTK

“NLTK 是构建 Python 程序来处理人类语言数据的领先平台。它为超过 50 个语料库和词汇资源如 WordNet 提供了易于使用的接口,以及一套用于分类、标记化、词干化、标记、解析和语义推理的文本处理库,工业级自然语言处理库的包装器,以及一个活跃的论坛—Nltk.org

有了 NLTK,我们可以使用一个名为 WordNet 的内置词汇数据库来搜索一个单词的意思。WordNet 将名词、动词、形容词和副词分组为认知同义词集— 同义词集— ,每个同义词集代表一个不同的概念。

首先,让我们在 Deepnote 上登录创建一个“新项目”。打开笔记本,让我们通过在单元格中键入并使用 Shift+Enter 运行来安装 NLTK 库——对于那些使用不同 Python 笔记本平台的人来说,您知道的快捷方式应该可以正常工作。

之后,我们需要导入 NLTK 库并下载 WordNet 数据库。

有了这个,我们就都准备好了。为了从像 'language,这样的单词中获取 synsets 对象,我们必须导入 WordNet 数据库并使用方法。*synsets()*

看起来结果对象并没有给我们所有需要的关于这个单词的信息,只是一些关于每个*synset* 的类似加密的信息。为了更好地查看,我们可以循环查看结果,并使用*pos()* *lemmas()* 格式化 synset 对象,借助一个自定义的对象列表来“漂亮地打印”单词表示。

关于 NLTK 中 WordNet 包的更多信息,您可以查看这个链接

NLTK 陷阱

您可以看到它作为字典工作正常,但是在开发 NLP 应用程序时有一些问题。

这很主观。它需要大量的人力,所以实际上不可能维持语料库。它也不会有效地计算单词相似度,而这对于我们的应用程序来说是非常重要的。那会导致我们编写不可靠或容易过时的人工智能软件。

离散表示

另一种方法是使用离散向量(包含 0 和 1 的向量)来表示不同的单词,但是这种方法也有一些缺陷。例如,它主要依赖 WordNet 的同义词列表,这会给我们带来一些问题。

由于这个原因,该领域转向另一种方法,即使用单词向量来表示单词。

根据上下文来表示单词

从一个人交的朋友身上,你就可以知道这个人是什么样的人。

单词向量的概念使我们能够处理单词和中心单词的上下文(附*的单词)。这使我们能够研究不同语境中单词之间的相似性。

单词向量(也称为嵌入或表示)

单词向量由包含非零值的 n 维向量表示,通过单词与其他单词的关系来表示单词。为每个单词构建一个密集向量,如下所示:

由 100 维单词向量表示的单词“medium”

如果你想扩展你在单词向量方面的知识,我推荐这本由艾莉森·帕里什写的超棒的笔记本

可以用不同的方法创建单词向量。在斯坦福的 CS224N 课程中,呈现了 word 2 vec(miko lov et al . 2013)12框架:

Word2Vec 概述:

  • 收集大量的文本
  • 用 n 维向量表示固定词汇表中的每个单词
  • 对于文本中的每个位置,定义一个中心词和上下文词。
  • 使用向量的相似度来计算给定中心词的上下文的概率。
  • 重复单词向量以最大化这个概率

这个过程主要是通过使用神经网络学*单词之间的关联来实现的。我们不会实现 Word2Vec 框架来训练一个模型;相反,我们将使用 Python 库 gensim 中的 Word2Vec 模型。

“Gensim 是一个 Python 库,用于大型语料库的主题建模文档索引相似性检索。目标受众是 T21 的自然语言处理(NLP)和信息检索(IR)社区— Gensim 网站

探索单词向量与 gensim 库的关系

这个例子将使用 gensim 的嵌入式apiWord2Vec模块下载一个文本语料库,并创建一个 Word2Vec 模型来可视化一些有趣的单词向量特征。首先,我们需要安装 gensim 包。

现在我们需要获得用于创建 Word2Vec 模型的语料库。为此,我们可以使用api模块。我们将下载从维基百科中提取的文本创建的 text8 语料库。之后,我们需要使用语料库来创建我们的 Word2Vec 模型,我们通过导入 Word2Vec 模型并实例化它,将语料库作为构造函数参数传递来完成。

这可能需要一些时间:)

我们已经可以通过执行诸如查找相似单词和选择不属于一个组的单词这样的任务来处理单词向量。你可以阅读 gensim 的文档了解更多关于可用的词向量运算。

还记得 NLTK 最大的缺陷可能是无法计算两个单词之间的相似度吗?通过使用单词向量,我们可以使用这个特性来执行更复杂的任务。例如,我们可以找到几组单词之间的相似之处。

我们可以用单词和模型表达式进行数学运算,比如:“国王—男人+女人=?”

摘自第一讲的视频

为了使用 gensim、对表达式求值,我们可以使用most_similar()方法,将正值‘woman’‘king’以及负值‘man’作为参数传递。

我们还可以创建一个analogy函数来简化这个操作:

单词向量为现代分布式单词表示奠定了基础,从而为 NLP 的发展铺平了道路。

对于第 2 课,您可以访问以下链接:

[## 以斯坦福的方式学* NLP 第 2

深入了解单词 2vec、手套和词义

thiago-gcandido.medium.com](https://thiago-gcandido.medium.com/learn-nlp-the-stanford-way-lesson-2-7447f2c12b36)

结论

在下一篇文章中,我们将讨论单词向量和词义,这是斯坦福课程第二讲的主题。我希望你喜欢阅读这篇文章。

如果你有,考虑在 推特 上关注我。

谢谢你的时间。保重,继续编码!

参考

软件和库

学* R 中的主成分分析

原文:https://towardsdatascience.com/learn-principle-component-analysis-in-r-ddba7c9b1064?source=collection_archive---------26-----------------------

图片来自 PixabayPavlofox

使用 PCA 改进您的特征选择过程

PCA 是一种降维技术;这意味着您在建模过程中包含的每个额外变量都代表一个维度。

它是做什么的?:

就 PCA 实际做的事情而言,它采用高维度的数据集,并将其缩减为少数不相关的成分。需要考虑的是不相关组件的概念。如果我使用客户的收入(如果我碰巧有)&来预测他们的收入,那么我会添加一个额外的变量来表示他们的邮政编码中值收入,这两个变量很可能是相关的,下一个变量不太可能对我的模型准确预测收入的能力产生积极影响。

我刚才解释的想法是多重共线性。给定变量的一个预测因子可以由其他预测因子预测的想法。或者回到我刚才举的例子,实际收入可以通过他们所在地区的收入中值来预测;这两者可能是共线的。

入门:

组件 是如何确定的?

确定每个分量是因为它占了最大的方差,并且根据所占方差的下一个最大部分来选择每个后续分量。因此,组件 1 将占最大的差异,组件 2 将占第二大的差异,以此类推。

步骤:

  • 缩放数据集
  • 创建 pca 对象— prcomp
  • 打印特征值

首先,加载 R 数据集,mtcars

data(mtcars)

接下来,PCA 最适合处理数值数据,所以您需要过滤掉任何非数值的变量。在我们的例子中,我们将使用 dplyr select 函数删除变量vs & am

mtcars <- mtcars %>% select(- c(vs, am))

让我们将更新的、只有数字数据的数据集放入 pca 函数中,prcomp.

pca <- prcomp(mtcars, center = TRUE,scale. = TRUE)

这里需要记住的是缩放。缩放的目的是标准化变量间的方差。为什么有人会关心你问?因为每个组成部分背后的想法是,它们尽可能多地解释了差异。没有这种缩放,您的高方差变量将在您的组件中被过度表示。

现在,我们应该保留多少组件??:

在我们开始这一节之前,要记住的是,我们正试图减少我们的尺寸,因此最大限度地减少不必要的组件是理想的。

在决定保留多少组件时,我将给出三个主要考虑事项。

对于第一个跟随!

summary(pca)

我们在这里寻找的是proportion of variance。正如我们一直在谈论的,这个想法是围绕着解释变异;如果你继续下去,你会看到第一个组成部分,PC1占变异的 62.8%,PC2占 23%,以此类推。

有了这些信息,你就可以考虑用最少数量的组件来解释你需要多少差异。这可能是您决定第一个组件的 63%就足够了,它可能是 86%的前两个,或 91%的三个。

考虑这类问题的一个有用工具是碎石图。

你会看到在碎石图上,我在 x 轴上画出了分量,在 y 轴上画出了分量的重要性。我们在上面看到的是,在第二个组件之后,每个附加组件的增量影响会显著下降。虽然有人可能会认为第三个组件的影响非常重要,足以得出值得包含第三个组件的结论,但不太可能有人会认为应该添加更多组件。

你可能会做的下一个评估是所谓的凯泽-古特曼准则。这里的规则很简单;仅保留特征值大于 1 的组件。

如果你不知道如何立即得到特征值;跟我来一次快速旅行吧。要获得每个组件的特征值,您只需要从 pca 对象中找到每个组件的方差或标准差的平方——如下所示。

pca$sdev ^ 2

如前所述,您将消除任何特征值不大于 1 的变量。这背后的想法是,如果特征值小于 1,那么该组件比单个变量贡献的方差更小。

基于我们所使用的方法,很明显我们在这里的路线是只使用前两个组件

了解您的组件:

知道你的组件是由什么组成的很重要。换句话说,哪些变量对任何给定的分量有贡献?geom_hline(yintercept=20)了解组件由什么组成很重要。换句话说,哪些变量对任何给定的分量有贡献。

print(pca$rotation)

看着第一个组成部分的各种贡献,我可能会努力建议第一个组成部分在很大程度上代表了汽车的动力或性能,如汽缸、马力、重量和显示为最高。

另一个可以很容易看到不同变量分组的方法是双标图。

pca %>% biplot(cex = .5)

正如我之前提到的,你可以看到气缸、马力、显示和重量都分组在一起。

使用线性回归将您的组件与原始变量进行比较:

为了确定使用常规变量与主成分的潜在预测影响,让我们使用每组进行回归,并比较每个模型的 r 平方。

对于每次回归,我们将尝试使用mtcars数据集中的其他变量来预测 MPG。

我们现在将创建第一个模型,按原样预测所有变量。

fit_1 <- lm(mpg ~ ., data = mtcars)

现在让我们创建包含 mpg 和前两个组件的下一个数据集。

components <- cbind(mpg = mtcars[, "mpg"], pca$x[, 1:2]) %>% as.data.frame()

现在,我们将使用这些组件训练第二个模型

fit_2 <- lm(mpg ~ ., data = components)

现在到了关键时刻,让我们比较一下每个模型的 r 平方!

summary(fit_1)$adj.r.squared

summary(fit_2)$adj.r.squared

正如你在上面看到的,当只使用两个组件时,模型的 r 平方有一个不那么小的变化。

结论

我希望这有所帮助!这里要记住的最后一点是,这里的唯一目的是在不损失太多预测能力的情况下进行简化。请随意查看我在 datasciencelessons.com 的其他帖子&祝数据科学快乐!

从头开始学* Python Lambda

原文:https://towardsdatascience.com/learn-python-lambda-from-scratch-f4a9c07e4b34?source=collection_archive---------33-----------------------

Python 中 lambda 函数的注意事项

照片由本在上写下un splash

当处理元素列表时,Python 程序员通常有三种选择:常规的 for 循环列表理解lambda 函数。对于 Python 初学者来说,lambda 函数通常被认为是“一个很酷的特性”,因为它的语法很短,而且与函数式编程很相似。但是对于初学者来说,这通常不是很简单。另一方面,即使对于长期使用 Python 的人来说,也不是每个人都一定熟悉 lambda,因为他们总能找到简单的替代方法。

相对于 lambda 函数,我个人更喜欢list/dictcomprehension。在本文中,我们将一起从头开始学* Python Lambda 及其注意事项,无论您是初级还是高级 Python 程序员。我们开始吧!

什么是 Lambda 函数?

Python 中的 Lambda 函数是一个小型匿名函数。它不同于其他函数式编程语言,在其他函数式编程语言中,lambda 函数增加了功能。根据 Python 设计 Q & A :

如果你懒得定义一个函数,Python lambdas 只是一种速记符号。

我们都喜欢做懒惰的程序员,但仅此而已吗?

创建 Lambda 函数

lambda 函数是用一个表达式定义的,而不是我们通常在 Python 中使用的def。任何 lambda 函数都遵循相同的规则:

lambda arguments: expression

它由三部分组成:

  • lambda:任意 lambda 函数的关键字
  • arguments:输入函数的参数。该函数允许多个输入参数。
  • expression:函数在单个表达式中将做什么。Lambda 只接受一个表达式,但可以生成多个输出。

论据

Python lambda 函数支持各种输入参数,就像一个def函数一样。

lambda-arguments.py

表情

Lambda 函数只接受单个表达式。因为它是一个表达式,所以可能会也可能不会被赋予名称。在下面的例子中,第二个 lambda 函数被赋予值sum_lambda。但是第三个 lambda 函数没有名字。正如你所看到的,它仍然工作,但是代码第一眼很难读懂。

λfunction . py

需要记住的一点是, lambda 函数不能包含任何语句。区分表达式和语句的一个简单的技巧是,如果你可以打印它或者给它赋值,那么它就是一个表达式。否则就是声明。

在 Python 中,语句包括returntryassertifforraise等。如果 lambda 函数包含一个语句,程序将引发SyntaxError异常。

检查 Lambda 函数

那么,lambda 函数和常规函数有什么不同呢?让我们检查功能!

我们将使用上一个例子中的函数。让我们首先检查两个函数的类型。好吧,他们属于function类这就说得通了。

>> print(type(sum))
>> <class 'function'>
>> print(type(sum_lambda))
>> <class 'function'>

然后,让我们检查一下表示法。sum_lambda的名字是<lambda>而不是“函数名”。即使我们给 lambda 函数赋值,它仍然是一个匿名函数。这种行为将导致一个我们将在最后讨论的限制。(先想想)

>> sum
>> <function sum at 0x10d2f30e0>
>> sum_lambda
>> <function <lambda> at 0x10d390200>

将 Lambda 函数与 Python 高阶函数一起使用

Lambda 函数通常与 Python 高阶函数结合使用。根据维基百科,

高阶函数是至少执行下列操作之一的函数:a)将一个或多个函数作为参数。b)返回一个函数作为结果。

在 Python 中,有几个内置的高阶函数,如mapfilterreducesortedsumanyall。其中,mapfilterreduce最常与 lambda 函数一起使用。

地图

函数有两个参数:一个输入映射函数和一个 iterable。映射函数将应用于 iterable 中的每个元素。map()函数返回包含映射元素的迭代器。

映射函数可以用简洁的λ函数来表示。

map-lambda.py

滤镜

filter()函数采用与map()相同的参数:一个输入过滤函数和一个 iterable。过滤函数将应用于每个元素,filter()函数返回一个包含过滤元素的迭代器。

下面是一个使用def函数和 lambda 函数过滤偶数的例子。

减少

reduce()函数来自 Python 内置模块functools。它实际上是将一个函数累积应用于 iterable 中的所有元素,并生成一个值。函数有 3 个参数:一个输入函数,一个可迭代函数和一个可选的初始化函数。

第三个例子定义了一个初始值设定项 0,每次都将 dictionary 元素中的值添加到初始值设定项中。如果初始化器没有被定义,那么默认情况下程序将把第一个元素作为初始化器,这将引发一个TypeError异常。

减少-λpy

在 pytest 中使用 Lambda 函数

您可能有一个函数generate生成一个随机值列表,这些值依赖于一个外部系统。当你进行单元测试时,你不希望generate函数与外部系统通信。此外,您需要来自generate函数的可重复结果,而不是每次的随机值。

在 Pytest 中,您可以使用 monkeypatch fixture 来修补生成这些随机值的部分。另外,使用 lambda 函数作为补丁函数使得代码更加简洁。

下面是示例代码。它使用 lambda 函数lambda _: 0来修补random.randint()。lambda 函数总是生成 0,它不关心输入参数,所以输入参数可以用_来表示。

pytest-lambda.py

列表理解与λ函数

lambda 函数的一个很好的选择是列表理解。对于map()filter()reduce(),都可以用列表理解来完成。列表理解是一种介于常规 for 循环和 lambda 函数之间的解决方案。在我看来,这是一个简洁而直观的解决方案。

list-comprehension.py

很好奇大家对列表理解和 lambda 函数的看法。你更喜欢哪一个,为什么?

性能比较

了解 lambda 函数的性能并与常规的def函数进行比较也很有趣。Lambda 函数需要的代码少,会对性能有影响吗?

比较内容包括:

  1. 创建函数(v.s .常规函数)的时间
  2. 调用函数的时间(v.s .常规函数)
  3. 是时候调用高阶函数了,比如map() (v.s. for-loop 和 list comprehension)

我使用 Python 内置函数[timeit](https://docs.python.org/3.8/library/timeit.html)对代码片段计时。首先,我使用def和 lambda 函数创建一个函数来计算一个数的平方。结果发现创建一个函数的时间几乎是一样的。

然后我调用这两个函数。它们比创建一个函数花费更长的时间,但是 lambda 函数在这里没有赢得任何时间。

最后一个是比较 for-loop list comprehension 和 lambda 函数的性能。由于从映射对象到列表的转换,Lambda 函数花费的时间最长。在这种情况下,列表理解表现最好。

lambda-compare-map.py

速度性能可以帮助我们决定选择哪种代码风格,但不应该是唯一的因素。我们还需要考虑代码的可读性和可维护性。

使用 Lambda 函数的限制

到目前为止,我们已经讨论了 lambda 函数的一些用例。它的简写符号使代码更加优雅和简洁。然而,总是有得有失。Python 开发者要理解 lambda 函数的局限性,避免“不必要的优化”。

  1. 在追溯中丢失信息

Lambda 函数是匿名函数,所以没有真正的函数名。当引发异常时,这可能会丢失信息。回溯只显示<lambda>而不是有意义的函数名。

λ-exception . py

2.调试麻烦

在 IDE 中调试print(list(map(lambda x: x ** 2, [1, 2, 3])))这样的语句并不容易。一种解决方法是给 lambda 函数添加一个“装饰器”。通常,我们会给一个def函数添加一个像@debug这样的装饰器,但是对于 lambda 函数来说这是不可能的。但实际上,decorator 是一个函数的 wapper,所以它可以将 lambda 函数作为输入参数。

下面是一个将debug装饰器应用到def函数和 lambda 函数的例子。修饰 lambda 函数有助于理解 lambda 函数在高阶函数中的行为。

lambda-debug.py

3.不符合 PEP8

如果您将 Flake8 这样的 linter 应用到您的程序中,您将会得到一个警告:

不要分配 lambda 表达式,使用 def (E731)

Flake8 给出了一个非常合理的解释,这与我之前的观点相联系:

这样做的主要原因是调试。Lambdas 在回溯中显示为<lambda>,其中函数将显示函数名。

4.不支持注释

根据 PEP 3107 ,lambda 的语法不支持注释。一种解决方法是使用代表函数的typing.Callable。例如,Callable[[int, int], str]表示一个带有两个类型为int的输入参数的函数,返回值的类型为str。我们可以用它来暗示 lambda 函数的类型。

下面是我们如何在高阶函数中提示 lambda 函数的类型。

λ-hint . py

我希望你喜欢这篇文章,并且理解 Python lambda 函数的一些注意事项!如果你有任何想法,请在下面留下你的评论。

参考

[## 如何使用 Python Lambda 函数——真正的 Python

参加测验“Python 和其他编程语言中的 lambda 表达式源于 Lambda 演算,是一种……

realpython.com](https://realpython.com/python-lambda) [## Python 的 reduce():从函数式到 Python 式——真正的 Python

在本教程中,您将学*到:函数式编程是一种编程范式,它基于将一个问题分解成…

realpython.com](https://realpython.com/python-reduce-function/)

了解如何在 5 分钟内用模块和包组织您的 Python 代码

原文:https://towardsdatascience.com/learn-python-modules-and-packages-in-5-minutes-bbdfbf16484e?source=collection_archive---------3-----------------------

用通俗易懂的例子!

扎克·卡道夫在 Unsplash 上的照片

当您的 Python 代码变大时,随着时间的推移,它很可能变得杂乱无章。随着代码的增长,将代码保存在同一个文件中会使代码难以维护。此时,Python 模块帮助你通过使用文件和文件夹来组织和分组你的内容。

  • 模块是带有的文件。py" 包含 Python 代码的扩展。它们有助于在同一个文件中组织相关的函数、类或任何代码块。
  • 将大型 Python 代码块分割成包含多达 300–400 行代码的模块被认为是最佳实践。
  • 将相似的模块放在一个单独的目录中。它们是包含相关模块和一个 init 的文件夹。py 文件,用于可选的包级初始化。
  • 根据您的 Python 应用程序,您可以考虑将您的模块分组到子包中,例如 doc、core、utils、data、examples、test。

让我们编写一个示例 Python3 代码来进一步理解模块和包:

**""" cvs_get_module.py
This module displays the summary of the tabular data contained in a CSV file 
"""**import pandas as pdprint("cvs_get_module is loaded")*def* **display_file_location(*path, file_name*)**:
 print("File Location: {}".format(path+filename))*class* **CSVGetInfo:**
 *def* __init__(*self*, *path*, *file_name*):
  self.path = path
  self.file_name = file_name

 *def* **display_summary(*self*):**
  data = pd.read_csv(self.path + self.file_name)
  print(self.file_name)
  print(data.info())

丹尼尔在 Unsplash 上的照片

导入模块

为了在外部 Python 代码块中使用一个模块,我们需要将那个特定的模块导入到我们的代码结构中。为此,使用带有"import<module _ name>"语法的 import 语句。这里的模块名是指不带的 Python 文件名。py" 扩展名。一旦我们导入模块,我们使用点符号,.”,访问模块内部的元素。

# **ModulesExample.py
# Importing 'csv_get_module' and accessing its elements**import **csv_get_module****data_by_genres** = **csv_get_module.CSVGetInfo**("/Users/erdemisbilen/
Lessons/", "data_by_genres.csv")**csv_get_module.display_file_location**(data_by_genres.**path**, data_by_genres.**file_name**)data_by_genres.**display_summary()****Output:** cvs_get_module is loaded
File Location: /Users/erdemisbilen/Lessons/data_by_genres.csv
data_by_genres.csv
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2617 entries, 0 to 2616
Data columns (total 14 columns):

通过重命名导入模块

我们可以用‘导入< 模块 _ 名称 >作为< 替代 _ 名称>’语法在导入的同时重命名模块。这可能有助于缩短长模块名。

# **ModulesExample.py
# Importing 'csv_get_module' and accessing its elements**import **csv_get_module** as **cg****data_by_genres** = **cg.CSVGetInfo**("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")**cg.display_file_location**(data_by_genres.path, data_by_genres.file_name)data_by_genres.display_summary()**Output:** cvs_get_module is loaded
File Location: /Users/erdemisbilen/Lessons/data_by_genres.csv
data_by_genres.csv
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2617 entries, 0 to 2616
Data columns (total 14 columns):

照片由亚历克斯·布洛克Unsplash 上拍摄

从模块导入特定名称

我们可以导入模块的特定名称,而不是加载模块中包含的所有元素。此外,我们可以通过用逗号分隔名称来导入多个元素。

注意,这里我们不需要使用点符号,因为我们直接从<module _ name>import<element _ name>’语法中导入带有的名称。

from **csv_get_module** import **display_file_location** as **dfl****dfl**("/User/Python/","ModulesExample.py")**Output:** File Location: /UserModulesExample.py

导入模块内的所有名称

我们也可以使用星号(*)直接导入模块的所有名称,尽管这不是一个好的做法。如果导入多个包含同名元素的模块,这可能会导致名称冲突。

from **csv_get_module** import *****

隐藏模块的元素

如果我们想要隐藏模块的一些元素,我们可以用下划线 "_" 开始命名元素。这种元素不能导入到外部文件中,因为这种命名约定使该元素成为模块本身的私有元素。

区分独立脚本运行和模块加载

包含 Python 代码的文件可以作为独立脚本运行,也可以作为模块加载到另一个代码结构中。

有时,考虑到这些用途,需要将 Python 文件中的代码分开。Python 有内置的 name 属性,当文件作为模块加载时,该属性为我们提供了模块名称。当文件作为独立脚本运行时,这次它返回 main 字符串。

**""" cvs_get_module.py
This module displays the summary of the tabular data contained in a CSV file 
"""**import pandas as pdprint("cvs_get_module is loaded")*def* **display_file_location(*path, file_name*)**:
 print("File Location: {}".format(path+filename))*class* **CSVGetInfo:**
 *def* __init__(*self*, *path*, *file_name*):
  self.path = path
  self.file_name = file_name

 *def* **display_summary(*self*):**
  data = pd.read_csv(self.path + self.file_name)
  print(self.file_name)
  print(data.info())if **__name__ == '__main__'**: **data_by_genres** = **CSVGetInfo**("/Users/erdemisbilen/Lessons/", 
 "data_by_genres.csv") **display_file_location**(data_by_genres.path, 
 data_by_genres.file_name) data_by_genres.display_summary()

只有当脚本作为独立脚本运行时,上述 if 语句中的代码才会运行。

Python 中的包

将相似的模块放在一个单独的目录中。它们是包含相关模块和一个 init 的文件夹。py 文件,用于可选的包级初始化。

init。py 在引用包内模块时执行一次。这个文件可以保留为空,或者可以选择实现包级初始化代码。

根据您的 Python 应用程序,您可以考虑将您的模块分组到子包中,例如 doc、core、utils、data、examples、test。由于相似的模块保存在不同的文件夹中,这使得你的整体结构得到很好的组织和维护。

Lynn Kintziger 在 Unsplash 上拍摄的照片

从包中导入模块

我们可以使用包名(文件夹名)和点“.”来导入包内的模块接线员。

from **utils.csv_get_module** import **display_file_location** as **dfl****dfl**("/User/Python/","ModulesExample.py")**Output:** File Location: /UserModulesExample.py

关键要点

  • 在 Python 中,组织大型代码块由模块包管理。
  • 这简化了代码结构,增加了代码的可重用性,并简化了维护和测试工作。

结论

在这篇文章中,我解释了 Python 中模块和包的基础知识。

这篇文章中的代码可以在我的 GitHub 库中找到。

我希望这篇文章对你有用。

感谢您的阅读!

同时学* SQL 和 MongoDB 简单的方法(第 1 部分)

原文:https://towardsdatascience.com/learn-sql-mongodb-simultaneously-the-easy-way-part-1-2d4ee20aa083?source=collection_archive---------14-----------------------

学*一切,简单的方法。

礼貌: Pixabay

读了这个标题,你可能会想,究竟谁会在学* SQL 的同时学* MongoDB 呢?让我给你一个小蛋糕,同时学*一门关系和非关系数据库管理语言超级容易。你也可以称它们为脚本语言。

哦,你是在告诉我们它们在一起学的时候超级容易学吗?是的,它是。只要在整个系列中跟随我,你就会意识到我没有错。

但是,你为什么想要学*这些呢?嗯,知道一些可以帮助你在数据库上交互和执行操作的语言总是很棒的。另一个大问题是,如果你对数据科学、数据分析、业务分析、web 开发、应用程序开发和开发运营感兴趣,那么你必须学*这些。偶尔你将不得不接触和使用这样的数据库,如果事先没有这方面的知识,我担心你会因为没有学*它而感到内疚。

基本概述:

SQL : SQL 是一种数据库计算机语言,设计用于关系数据库中数据的检索和管理。SQL 代表结构化查询语言。本教程将让您快速入门 SQL。它涵盖了基本理解 SQL 所需的大部分主题。SQL 数据库包含:

  • 数据存储在称为表的数据库对象中。
  • 每个表都被分解成更小的实体,称为字段。
  • 一条记录也称为表中每个条目中数据的
  • 是表格中的垂直实体,包含与表格中特定字段相关的所有信息。

MongoDB :使用 MongoDB 查询语言 (MQL)查询 MongoDB 数据库。作为一个 NoSQL 数据库,MongoDB 确实没有使用 SQL 作为它的查询语言。相反,MongoDB 依赖于几个驱动程序,这些驱动程序允许其引擎与多种语言进行交互。非 SQL 数据库包含:

  • 数据存储在被称为集合的数据库对象中。
  • 一个文档是一组键值对。文档具有动态模式。这可以称为行。
  • _id :这是每个 MongoDB 文档都需要的字段。
  • 字段是文档中的名称-值对。一个文档有零个或多个字段。这可以称为列。

数据类型概述:

SQL:

  • 整数
  • Smallint
  • Numeric(p,s)——其中 p 是精度值; s 是一个刻度值。例如,numeric(6,2)是一个小数点前有 4 位、小数点后有 2 位的数字。
  • Decimal(p,s)其中 p 为精度值; s 是一个刻度值。
  • 实数单精度浮点数。
  • 双精度——双精度浮点数。
  • Float(p)其中 p 为精度值。
  • Char(x)其中 x 是要存储的字符数。它用空格填充,以填充指定的字符数。
  • Varchar(x)其中 x 是要存储的字符数。它没有空间垫。
  • Bit(x)其中 x 是要存储的位数。
  • 位变化(x)其中 x 是要存储的位数。长度最大为 x。
  • 日期-存储年、月和日的值。
  • 时间-存储小时、分钟和秒的值。
  • 时间戳-存储年、月、日、小时、分钟和秒的值。
  • 带时区的时间-与 Time 相同,但也存储指定时间相对于 UTC 的偏移量。
  • 带时区的时间戳——与时间戳相同,但也存储指定时间相对于 UTC 的偏移量。
  • 年-月间隔-包含年值、月值或两者。
  • 日-时间间隔-包含日值、小时值、分钟值和/或秒值。

MongoDB:

  • 字符串——这是存储数据最常用的数据类型。MongoDB 中的字符串必须是 UTF-8 有效。
  • 整数——用于存储数值。整数可以是 32 位或 64 位,具体取决于您的服务器。
  • boolean——用于存储布尔值(真/假)。
  • double——用于存储浮点值。
  • 最小/最大键——用于将数值与最低和最高 BSON 元素进行比较。
  • arrays——它用于将数组或列表或多个值存储到一个键中。
  • 时间戳 ctimestamp。当文档被修改或添加时,这对于记录非常方便。
  • 对象-它用于嵌入的文档。
  • Null——用于存储空值。
  • 符号——它的用法与字符串相同;然而,它通常是为使用特定符号类型的语言保留的。
  • 日期—用于以 UNIX 时间格式存储当前日期或时间。您可以通过创建日期对象并向其中传递日、月、年来指定您自己的日期时间。
  • 对象 ID——它用于存储文档的 ID。
  • 二进制数据——用于存储二进制数据。
  • code——它用于将 JavaScript 代码存储到文档中。
  • 正则表达式——它用于存储正则表达式。

我不打算在一个部分中用所有的信息轰炸你,因为即使对我来说处理这么多信息是困难的,我知道那是什么感觉。我们将一步一步、非常流畅地学* SQL & MongoDB。我将在第 1 部分介绍大约 4 个州。

创建表格/集合并插入记录:

表/集合的创建非常简单,如果您更专注于提取和分析数据,就不需要经常这样做。顺便说一下,SQL 是区分大小写的。

SQL:

# Syntax to create a table
> **create** **table** "tablename" ("columnName" "datatype", "columnName" "datatype");# Create a table:
> **create** **table** winner ( Id INT, name VARCHAR(15))# Insert a row:
> **insert** **into** winner (Id) **values** (1)
(or)
> **insert** **into** winner **values** (1)

MongoDB:

# Syntax to create a collection
> db.createCollection(name, options)# Create a collection:
> db.createCollection("winner")# Syntax to insert a record> db.collectionName.insert({"key":"value"})# Inserting a record:
> db.winner.insert({"name" : "Kunal"})

查询数据库:

查询数据库的一般定义是从集合或表中获取数据。查询数据库的基本过程非常简单。在 SQL 中,通过使用 select 来完成,在 MongoDB 中,通过使用 findaggregate 来完成。以下是从数据库中获取数据的方法:

SQL:

# Syntax to query a table
> **select** column **from** tables# Query all the records
> **select** * **from** winner# Query the DB, select all rows from the Id column
> **select** Id **from** winner

MongoDB:

# Syntax to query a collection, to select all the documents
> db.COLLECTION_NAME.find({})# Get all the records using **find**
> db.winner.find({})# Fetch data using **aggregate** > db.winner.aggregate(
[{
        $group: { 
            '_id':null,
            'max':{'$first':"$$ROOT"}
        }
    }])

对于初学者,我建议您熟悉 find 函数,因为直接切换到 aggregate 函数会有点困难。原因是在后面的阶段你必须学*聚合,发现函数有各种限制,为了实现这一点,你必须使用聚合函数。

对查询数据进行排序:

当您希望数据按特定顺序排列时,排序非常重要。您之前可能运行过的查询会以随机顺序给出结果。排序在 SQL 中称为订单,在 MongoDB 中称为排序。我们可以根据列、升序、降序和限制对数据进行排序。让我告诉你怎么做。

SQL:

# Syntax for ordering the data
> select * from tablename order by asc/desc/column/limit# Fetch all records and sort by ascending
> **select** * **from** winners **order** **by** asc# Fetch all records and sort by descending
> **select** * **from** winners **order** **by** desc# Fetch all records and sort by column
> **select** * **from** winners **order** **by** Id# Fetch all records and sort by multiple columns
> **select** * **from** winners **order** **by** Id, name

MongoDB:

# Syntax to sort the data - find()
> db.collectionName.find({}).sort({**KEY**:1})# Sort the data in descending order using find()
> db.winners.find({}).sort({"_id":-1})# Sort the data in ascending order using find()
> db.winners.find({}).sort({"_id":1})# Sort the data in ascending order using aggregate()
> db.users.aggregate(
   [
     { **$sort** : { name: 1 } }
   ]
)# Sort the data in descending order using aggregate()
> db.users.aggregate(
   [
     { **$sort** : { name: -1 } }
   ]
)

_id 是为插入集合中的每条记录捕获的 objectID,它是必需的。如果您解码 ObjectID,您将从中获得一个时间戳。对于聚合管道中的函数,必须加上前缀 $。

基于条件查询数据库:

一次获取所有的记录总是很简单的,但有时可能会耗费你大量的时间,有时你甚至不需要查看全部数据。您还可以根据特定条件过滤数据。过滤的作用是,它从你的显示中去掉其余的数据,你只能看到需要的数据。在 SQL 中使用 where 完成,在 MongoDB 中使用$ matchaggregate 中完成,只是一些简单的赋值find 中完成。让我告诉你怎么做。

SQL:

# Syntax to query data based on condition
> **select** * **from** table **where** *condition*# Fetch data based on a condition
> **select** Id **from** winners **where** name="Kunal" **and** Id>4# Another condition
> **select** name **from** winners **where** Id **between** 10 **and** 12

Between 条件将过滤掉符合上述条件的结果。

MongoDB:

# Syntax to query based on a condition
> db.winners.find({condition})# Fetch data based on a condition, Id greater than 2
> db.winners.find({"Id":{"$gt":2}})# Using aggregate, match is just like where in SQL
> db.winners.aggregate(
[{
"**$match**":{"Id":{"$gt":2}}
}])

我们在查找聚合中使用了相同的条件,但是你不认为查找更容易实现吗?发现有它的局限性,这就是为什么你必须在稍后阶段切换到聚合。我建议你*惯使用聚合,这将为你节省几个小时使用 find 的麻烦。

主题演讲:

  1. SQL 区分大小写。
  2. SQL 有表,MongoDB 有集合。
  3. ****分号是分隔每个 SQL 语句的标准方式。
  4. MongoDB 管道函数需要 $ 作为前缀。
  5. 在 MongoDB 中使用"",提高代码可读性。
  6. MongoDB 有 findaggregate 来查询 DB。
  7. 在 MongoDB 中, _id 是一个包含时间戳的 ObjectID。

如果你能走到这一步,你就太棒了。至此,我们结束了系列的第一部分。****

如果您遇到任何错误或需要任何帮助,您可以随时在 LinkedIn 上发表评论或 ping 我。

*****LinkedIn:*https://bit.ly/2u4YPoF

在 Github 上关注我,了解更多令人惊叹的项目和教程。

Github:https://bit.ly/2SQV7ss

我希望这有助于你增强你的知识基础:)

更多关注我!

感谢您的阅读和宝贵时间!

页(page 的缩写)这个系列的第二部分很快就要出来了。永远保持对知识的渴望。

学*业务,成为伟大的数据科学家

原文:https://towardsdatascience.com/learn-the-business-to-become-a-great-data-scientist-635fa6029fb6?source=collection_archive---------23-----------------------

意见

每个数据科学家的核心(抱歉,不是编码)

Unsplash猎人赛跑的照片

许多有抱负的数据科学家认为,成为数据科学家需要具备以下条件:

  • 编码
  • 统计的
  • 数学
  • 机器学*
  • 深度学*

和任何其他技术技能。

上面的列表是准确的;我上面列出了你现在需要的大部分数据科学家资格。这是不可避免的,因为现在许多工作列表总是把这些技能列为先决条件。只需看看下面的数据科学家工作要求和偏好示例。

取自 indeed.com

大多数需求听起来都是技术性的;学位、编码、数学和统计。虽然,有一个潜在的商业理解要求,你可能一开始从这个招聘广告中没有意识到。

如果你仔细观察,你会发现他们需要有应用分析方法解决实际商业问题经验的人。这意味着你的日常任务将包括解决业务问题,反过来,你需要了解公司经营什么样的业务以及流程本身是如何运作的。

你可能会问,“为什么我需要理解它?只要创建机器学*模型,问题就解决了,不是吗?”这种想法很危险,我会解释原因。

提醒一下,我认为让你成为伟大的数据科学家的不仅仅是你的编码技能有多好,或者你对统计理论或者业务理解的掌握程度,而是多种因素的结合。

当然,任何人都可以同意或不同意我的观点,因为我相信没有特定的技能可以让你成为伟大的数据科学家。

数据科学家就业难。要进入这个领域并不容易。有很多申请人和拥有相似技能的人,你需要脱颖而出。商业理解是一种技能,它肯定会让你从池塘里的所有鱼中脱颖而出。

在我作为数据科学家的经历中,没有什么技能比业务理解技能更让我感到被低估了。我甚至以为,你不需要了解我早期职业生涯中的业务。我错了。

不过,我并不惭愧地承认,我起初并不认为业务方面是必不可少的,因为许多数据科学教育和书籍甚至没有教我们这方面的知识。

那么,为什么学*业务至关重要,以及它如何影响您作为数据科学家的就业?

想象一下这种情况。你在以糖果为主要产品的食品行业数据部工作,公司计划发布一款新的酸味糖果产品。然后,公司要求销售部门出售产品。现在,销售部门知道该公司有一个数据部门,并要求数据团队提供新的线索,他们可以在哪里销售酸糖果。

在任何人抱怨“这不是我们的工作,我们创造了一个机器学*模型!”或者“我是数据科学家,不在销售部门工作。”不,这恰恰是数据科学家在公司做的事情;许多项目是与另一个部门合作解决公司的问题。

回到我们的场景,那么如何正确处理这个问题呢?你可能会想,“只需创建一个机器学*模型来生成线索。”是的,这是在正确的轨道上,但你到底如何创建模型?依据是什么?使用机器学*模型解决商业问题是否可行?

你不能突然使用机器学*模型,对吗?这就是作为数据科学家,业务理解如此重要的原因。你需要更详细地了解糖果业。一直问这样的问题,

  • "我们到底想解决什么样的业务问题?"
  • “我们甚至需要一个机器学*模型吗?”
  • “什么样的属性与糖果销售有关?”
  • “公司内外的糖果销售策略和实践如何?”

以及许多你能想到的与业务相关的业务问题。

了解你的公司经营什么样的业务以及与业务相关的一切非常重要,因为作为一名数据科学家,你需要理解数据

虽然说商业理解技能是必不可少的很容易,但要获得这种技能并不容易。

教育是一回事;例如,与拥有生物学学位的人相比,如果你的教育背景是通信,你可能有更大的机会脱颖而出,申请公关公司的数据科学职位。

虽然工作经验很快就涵盖了这一点。在类似行业的另一个职位的工作经验将提供重要的杠杆作用,因为你已经了解业务流程。

对于一名新生来说,这可能是一个很难进入的行业,但事后看来,作为一名新生也有很多好处。我记得泰勒·福克曼在他的 LinkedIn 上的帖子,为什么这个行业应该考虑应届毕业生,我同意。应届毕业生可以:

  1. 有备而来
  2. 渴望了解业务
  3. 产生影响

新生应该成为那些已经建立了数据之旅的公司的目标。该公司可以更容易地教授许多商业方面的知识,因为大学新生在商业领域毫无经验。在我看来,永远不要把新生排除在外。

我也会告诉你我的经历。当我第一次获得数据项目时,我根本没有考虑业务,只是试图建立机器学*模型。结果是多么的灾难性。

我把模型呈现给相关方,脑子里在炒作。我的模型结果不错,对数据了如指掌,也知道自己用的模型的理论。很简单,对吧?所以,错了。原来用户并不在乎我用的型号。他们更感兴趣的是知道我是否已经考虑了业务方法“A ”,或者为什么我使用了与业务完全不相关的数据。最后讨论到我需要更多的商业培训。

这很尴尬,但我一点也不惭愧地承认,不考虑业务理解是我的错。我可能在模型创建或统计方面是最棒的,但不了解这个行业最终会成为一场灾难。从那天起,我试着学*更多关于业务流程本身的知识,甚至在考虑任何技术问题之前。

结论

在我看来,不管是不是大一新生,都要尽量去学业务。

专注于一个你觉得感兴趣的行业;金融、银行、信贷、汽车、糖果、石油等。每一项业务都有不同的方法和策略;你只需要专注于学*你喜欢的行业。

数据科学家就业难。进入这个领域并不容易。有许多申请人和许多拥有相似技能的人,你需要脱颖而出。商业理解无疑是将你与池塘中所有鱼区分开来的技能。

如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。

如果您没有订阅为中等会员,请考虑通过我的推荐订阅。

在强调编码语言或工具之前,先学*这 3 个基本的数据概念

原文:https://towardsdatascience.com/learn-these-3-basic-data-concepts-before-stressing-about-coding-languages-or-tools-e599896e6d4?source=collection_archive---------2-----------------------

爱德华·豪厄尔在 Unsplash 上拍摄的照片

前几天我收到了一个 Instagram DM,这让我开始思考。这个人解释说,他们的职业是数据分析师,有多年的经验。但是,他们也说,他们觉得他们的技术能力略有欠缺,因为他们从未听说过我页面上提到的许多术语。这个人提到他们期待通过学*更多的技术工具(SQL、Python、R 等)来扩展他们的技能。)

当我思考如何进一步建议这个人的时候,我意识到这个人是实现他们期望的转变的最佳人选。为什么?他们已经掌握了数据技能和数据思维,这对于在数据领域取得成功至关重要。

我(和许多其他人)担心掌握现有的每一种技术工具或产品。我担心只拥有微软产品(SQL Server、Excel、Power BI)的经验,觉得自己需要拓宽视野,成为更好的数据分析师。我经常看到数据科学家在网上质疑和争论 Python 和 R 哪个更适合他们的工作。

但是,与我的 Instagram 新朋友交谈让我意识到,这些担忧和辩论非常愚蠢。工具和编程语言在不断发展变化,来来去去。但是你知道什么会留下来吗?核心概念。曾经构建的每一个工具或语言都会依赖于这些核心概念。

如果你知道如何获取一个数据集,操作它,并以一种提供真正洞察力的方式呈现它(或者至少引出更多你以前没有的问题…因为这种情况会发生!!),你已经走上了成为某种数据专家的正确道路。

这种对数据的基本理解是如此强大。您可以理解这一点,并将其与您选择的任何技术工具相结合。然后,您可以对数据进行分组和筛选,以进行业务报告和 KPI 监控,进行统计测试以回答有关数据的问题,预测未来的数据,甚至生成 AI 模型以使用数据来帮助指导业务行动。你可以用包含数百万行的巨大数据集做所有这些事情!

好吧,我知道我在向你推销这个想法,所以让我开门见山吧。如果你理解数据概念以及如何应用它们,你可以很容易地用你选择的任何技术工具或产品来实现这些概念。

不过,别担心,我来这里不只是为了向你推销这个然后离开。我将从一个总体的角度谈论我作为数据分析师日常使用的 3 个基本数据技能。不涉及任何技术术语或代码。如果您开始掌握这些(以及其他)数据概念,那么掌握它们并将其应用于任何工具都很容易。我甚至在文章的结尾有一个严肃的生活帮,它将帮助你在任何你想掌握的工具中进一步运用你的新数据知识。跟着我,我抓住你了!

#1.过滤数据

在数据世界中至关重要的第一个数据概念是过滤数据。老实说,过滤数据是一个超级简单的概念,也是我们人类每天都在做的事情。举这个例子。如果你要去吃麦当劳,你应该问问你的三个室友是否想要一些(因为你不想成为那个室友)。但是,在你去问你的室友是否想吃鸡块之前,你要记得你的三个室友中有两个甚至不喜欢麦当劳,所以你最后只问了一个。基本上你是基于某种“属性”从你的“数据集中”过滤掉了你的两个室友,这种属性就是他们是否喜欢麦当劳。

数据分析师或数据科学家过滤数据的方式完全相同。如果你正在对女性顾客进行分析,你将需要使用你所掌握的任何工具来过滤掉非女性顾客。如果您试图构建一个有助于为成年人推荐护肤产品的模型,您可能会希望过滤掉任何非成年患者的数据。

长话短说,过滤数据就是从你所有的数据集中去掉所有不需要的数据,直到剩下你分析所需的数据。

#2.数据类型转换

另一个常用的数据技能是数据类型转换。数据类型是数据存储在电子表格、软件或数据库中时可以归入的特定类别。数据类型的一些常见示例有:

  • 字符串(例如:“你好,这是一个字符串。”)
  • 整数(例如:400)
  • 小数(例如:400.17)
  • 布尔值(例如:TRUE)

当我们处理数据集时,我们希望确保每个数据属性都存储为正确的数据类型。

我们不希望将整数 123 存储为字符串。如果我们将 123 存储为字符串,电子表格、软件或数据库将无法对其执行必要的操作。电脑会被弄糊涂的。如果我们告诉计算机我们有一个字符串(“123”),但后来我们想把“123”加到某个东西上,计算机会说“等一下”。你教我“123”是一个字符串,基本上是一个单词。丫不能添话狂人!只能加数字!!!!"

抱歉,假设的计算机变得如此激进,但你明白了。为了确保我们能够在以后对数据执行适当的操作,我们希望绝对确保它被表示为正确的类型。

#3.汇总数据

我现在想谈的最后一个概念是聚合数据。聚合数据是如此如此如此强大。聚合数据可以将您从一个由行和列数据组成的巨大文本文件中解放出来,并将其转化为一个更有意义、更悦目的汇总值或汇总表。

注意到我一直在说总结这个词吗?这可能是解释聚合的最佳方式,因为聚合接受多行数据,并将它们汇总到较少的行中。

照片由SQLiteTutorial.Net提供

如果您有一个数据集,其中包含需要相加的数字(如数量或销售额),那么汇总这些数据的最简单方法之一就是求和。在下面的例子中,我取了一个包含我每天喝的咖啡量的数据集。我通过对其求和来对其应用聚合,这在右侧创建了我的数据的汇总视图。这个总结显示我总共喝了 4 杯咖啡(至少在这个数据集中)。

还有许多其他非常直观的聚合操作,即使对于数据世界的新手来说也是如此。这些操作中的每一个都回答了一些问题,这些问题告诉我们关于数据集的更多信息。其他简单聚合操作的一些示例如下:

  • 数数(有多少条记录?)
  • 最大(最大的观察是什么?)
  • 最小(最小的观察值是多少?)
  • 平均(我倾向于观察什么?)

OK coooOooOol..那么下一步是什么?

我知道我之前答应过给你一个生活帮奖,所以别担心——我没有忘记。现在,您已经更牢固地掌握了数据专业人员工作流程中的一些最重要的步骤,您可以将它们应用于您选择的任何技术工具,即使您是一名新手。怎么会?和我们最好的朋友,我们的终极救世主,谷歌一起!

每当我想用某个工具来练*我的技能,并且我需要复*如何正确地执行它,我会以这种格式搜索:

[插入技术工具]中的[插入数据技能]

我向你发誓,每当我用这种格式搜索时,我总能找到很棒的文档、博客帖子或其他资源(比如 Stack Overflow ),将我的想法引向解决方案。

那么,你觉得聚合数据有趣吗?你想提高你的 SQL 技能吗?然后,我建议回顾并着手:

在 SQL 中聚合数据

你基本上是一个在 Python 中过滤数据的专家,但是现在你想在 R 中尝试一下吗?试试我的生活帮和谷歌:

在 R 中过滤数据

听听这个在追求自己的数据职业梦想前几个月不知所措的女孩吧。先学概念。以后再担心技术问题。技术总是在发展,但基础却没有。

原载于 2020 年 8 月 7 日https://data dreamer . io

学会下注——使用贝叶斯决策

原文:https://towardsdatascience.com/learn-to-bet-use-bayesian-bandits-for-decision-making-2e2e489087a5?source=collection_archive---------36-----------------------

贝叶斯思维如何影响我们在概率世界中的决策

我们生活在不确定性中,有时我们不得不在给定的几个选项中做出选择,而我们对这些选项都知之甚少。随着时间的推移,如果我们一次又一次面对同样的选择,我们可能会知道哪个选择会给我们最大的回报,哪个是第二好的,等等。一般来说,这可以说是人类的学*过程,由我们的目标引导,最大化总回报(或最小化总损失或遗憾)。

马库斯·斯皮斯克在 Unsplash 上的照片

此外,一些重要的业务应用程序也可以用这种方式建模。思考以下情况:

(1)给定一堆股票代码,每一个都有不同的回报,你如何理性地选择一个能使你的回报最大化的代码?

(2)有三种网站登录页面设计可供您尝试,您会如何选择一种最大化您的指标(如转化率)的设计?

(3)假设您想要推广您的业务,并且有三个不同的广告场地,您将如何选择一个最符合您预算的场地?

这些现实的业务问题都可以方便地抽象为以下场景:

假设你有 N 个吃角子老丨虎丨机(或强盗),每个都有自己的概率来给你奖励 r。你如何计算出随着时间的推移选择哪个吃角子老丨虎丨机,以便尽可能多地获得奖励?

这种说法看似简单,但实际上,决策过程要复杂得多,因为你要不断处理两难的选择,是坚持当前相对较好的选择,还是尝试其他可能更好的选择,即开发还是勘探。我们需要一个合理的框架来处理这种情况。

照片由凯勒·琼斯Unsplash 上拍摄

贝叶斯强盗

贝叶斯土匪提供了一个直观的解决问题的方法。一般来说,它遵循以下步骤:

  1. 对每个强盗给予奖励的可能性进行初步猜测。用统计学的语言来说,这就是假设每个土匪的行为(给不给奖励)有一定的先验分布。由于我们试图模拟概率,一个方便的先验分布将是贝塔分布,它通常用于模拟 0 到 1 之间的随机变量。请注意,如果您对强盗行为的潜在分布一无所知,您的理性猜测将是平等对待每个强盗,即假设均匀分布,这是 beta 分布的特例。
  2. 从每一个土匪身上抽取一个样本,根据其目前的分布情况。
  3. 关注样本最高的土匪;通过选择来决定你获得的奖励(后悔)的数量,并相应地更新强盗的分布。在统计学的语言中,你有一个随机变量的特定参数的先验分布,现在你有了随机变量的值的新观察,你能够更新你关于随机变量的先验信念,通过应用贝叶斯规则得出后验分布;最终结果是有一组新的分布参数来解释新的观察结果:

先前分配:P(A)

新观察:x

后验分布:P(A|x) ~ P(x|A)*P(A)

后验分布与似然*先验分布成正比

4.回到步骤 2 并重复。

照片由Tine ivaniUnsplash 上拍摄

模拟

让我们看一个带有一些代码的具体例子。

首先,让我们导入必要的包:

import numpy as npfrom scipy.stats import betaimport matplotlib.pyplot as plt

让我们定义我们的强盗;这些数字表示各自的强盗提供奖励的概率,你可以随意修改这些数字并运行不同的模拟:

bandits = np.array([0.75, 0.5, 0.6])

随着基础知识的清除,现在下面的函数说明了贝叶斯强盗的核心:

def experiment(accumulated_rewards_per_bandit, times_chosen_per_bandit, bandits, num_draws=1):

    for _ in range(num_draws):
        bandit_chosen =    np.argmax(np.random.beta(1+accumulated_rewards_per_bandit, 1+times_chosen_per_bandit-accumulated_rewards_per_bandit)) reward = get_reward_from_bandit_i(bandits, bandit_chosen)

        accumulated_rewards_per_bandit[bandit_chosen] += reward times_chosen_per_bandit[bandit_chosen] += 1 a = 1+accumulated_rewards_per_bandit
    b = 1+times_chosen_per_bandit-accumulated_rewards_per_bandit
    return a, b

让我们一行一行地分解这个函数。首先,让我们指定输入参数:

每个强盗累积的奖励:在一个实验中,每个强盗累积的总奖励,它的大小等于强盗的数量。

times _ chosen _ per _ bandit:在一个实验中,每个强盗被选中的次数,其大小等于强盗的数量。

强盗:我们各种奖励概率的强盗。

num_draws:一个实验中的试验次数

回想一下,从根本上说,我们的目标是更好地了解不同强盗的回报概率,这意味着我们试图获得对基础分布越来越准确的估计,在我们的情况下,这些分布都是贝塔分布。

请注意,beta 分布由两个参数 ab,唯一定义,在我们的示例中,这两个参数分别代表强盗获得奖励的尝试次数(在我们的示例中等于累积奖励)和强盗未获得奖励的尝试次数。

因此,我们的目标是在试验中保持这两个量的精确记录。

现在应该清楚我们在上面的函数中试图实现什么了。循环查看试验次数,我们首先找出给出最大样本的强盗,然后通过在下面的行中选择这个强盗来确定我们是否得到任何奖励:

reward = get_reward_from_bandit_i(bandits, bandit_chosen)

这里我使用下面的简单实现来确定奖励:

def get_reward_from_bandit_i(bandits, i):
    return np.random.rand() < bandits[i]

您可以看到这个实现导致奖励为 1 或 0。在实践中,你可能想设计自己的奖励机制来反映你的问题的性质。

在获得奖励(或不获得)后,我们可以更新累积的奖励和为我们的采样 bandit 选择的时间,这将在下一次迭代中作为更新的 beta 分布参数 a 和 b。

最后,在循环所有试验之后,我们获得完全更新的分布参数并返回它们。

现在,我们已经配备了贝叶斯强盗的核心组件,让我们使用下面的代码片段开始运行模拟:

if __name__ == "__main__":
    bandits = np.array([0.75, 0.5, 0.6]) num_draws_per_experiment = [300] accumulated_rewards_per_bandit = np.zeros(bandits.size) times_chosen_per_bandit = np.zeros(bandits.size) for i in num_draws_per_experiment:
        a, b = experiment(accumulated_rewards_per_bandit, times_chosen_per_bandit, bandits, i)

结果

似乎我们需要一种方法来确定我们做得有多好。在本文中,让我们尝试绘制每组 beta 分布参数的概率密度函数,看看它们是否显示出任何可辨别的模式。

让我们发挥这一功能:

def plot_beta(x_range, a, b, filename):
    x = x_range
    y0 = beta.pdf(x, a[0], b[0])
    y1 = beta.pdf(x, a[1], b[1])
    y2 = beta.pdf(x, a[2], b[2]) plt.plot(x, y0, color='red', lw=2, ls='-', alpha=0.5, label='pdf: 1st bandit')
    plt.plot(x, y1, color='green', lw=2, ls='-', alpha=0.5, label='pdf: 2nd bandit')
    plt.plot(x, y2, color='blue', lw=2, ls='-', alpha=0.5, label='pdf: 3rd bandit') plt.legend() plt.savefig(filename)

对不同数量的试验运行绘图功能,我们得到以下 pdf 图:

每个强盗的 pdf 图,试验次数=1,10,50,100

每个强盗的 pdf 图,试验次数=200,500,1000,2000

请注意,第一个强盗(红色)的回报概率最高,为 0.75,在 100 次尝试后,随着其 beta 分布的形状缩小并在真实值的 0.75 附*达到峰值,它逐渐胜出,而其他两个强盗的分布形状仍然相对平坦且分布广泛,这暗示了不确定性。

尽管通过足够多的试验,每个强盗的分布将趋向于在奖励概率的真实值附*达到峰值,但在这个问题中,我们更感兴趣的是找到最好的强盗,而不是精确地推断隐藏的奖励概率。可以对我们的模拟进行一些改进:例如,可以将学*率(> 1 或< 1)应用于累积奖励的更新,以微调我们是倾向于保持当前的好选项还是更多地探索其他选项。

在后续文章中,我将展示贝叶斯土匪如何帮助构建股票的动态投资组合,这可以被建模为具有随时间变化的潜在回报概率的土匪。因此,请关注我,继续关注更多内容。

现在是学*编码的时候了

原文:https://towardsdatascience.com/learn-to-code-e07b2f8cb000?source=collection_archive---------45-----------------------

这是学*编码的最佳时机!

制造者在 UnsplashNESA 的照片

多年来,人们一直告诉你,学*编程是让自己更有竞争力的一个好方法。现在,世界各国都面临着惊人的失业,没有比这更好的时机来采取行动了!

苹果公司首席执行官蒂姆·库克甚至说,学*编码将很快变得比学*英语作为第二语言更重要。

每年,Stack Overflow 都会发布对开发人员的个人资料、职业生涯和生活的深刻见解。Stack Overflow 是一个面向专业和爱好者程序员的问答网站。

去年,* 90,000 名开发人员参与了调查。

调查结果表明,编程工作不仅有很高的职业满意度,而且这些职业实际上是可以实现的,即使是那些没有受过正规培训的人也是如此。

注意:2020 年的结果现在随时都有可能出现——我打算在发布最新数据时更新这篇文章。

为什么要学编码?

好了,你已经听说了编码是一项重要的技能。现在我们来探究一下为什么!

越来越多的工作被自动化,这完全改变了就业市场。这并不意味着引人注目——而是作为一种先发制人的方式来改变你的行业,走在它的前面。

专业开发人员收入颇丰

开发商也是赚大钱!这因国家、城市和语言的不同而不同。

尤其是在现在的新冠肺炎时代,远程工作已经走到了前台。一个编码职业可以让你不那么依赖地理上的收入。

有一点是一致的,那就是开发人员的平均工资很高!

专业开发人员收入颇丰。资料来源:Nik Piepenbreier

我强调了一些在 Medium 上有大量资源的职业,包括 web 开发人员和数据科学家。

根据 Stack Overflow 的调查,所有这些调查的年薪中值接*或超过 10 万美元!

专业开发人员对他们的职业很满意

根据 Stack Overflow 2019 调查结果,专业开发人员对自己的工作非常满意。

事实上,* 3/4 的受访者对自己的职业感到满意。相比之下,只有 1/2 的一般受访者(根据一篇会议委员会文章)。

大多数职业开发人员对自己的职业很满意。资料来源:Nik Piepenbreier

但是我没有受过教育…

我们来看看职业开发者都有什么样的学历。

根据堆栈溢出调查,大多数受访者至少拥有学士学位。但这不应该吓走你:

2019 年,超过 15%的职业开发者没有大学学历!

让我们仔细看看背后的数据:

有些开发人员没有大学学历也能凑合!资料来源:Nik Piepenbreier

总而言之,不要让缺乏大专教育阻碍了你的发展。网上有很多很棒的资源!

重要的是让你的作品为你发光!考虑开发一个展示你技能的作品集。当你没有受过正规教育来支持这一点时,这一点尤其重要。

作品集可以放在像 Github.com 这样的网站上,应该放在你的简历里。

专业人士编码多久了?

超过 2/3 的专业开发人员从事编码工作不到 10 年!

即使获得最低限度的编程技能来自动化你的一些工作,也确实有助于就业。这些类型的技能会让你对现在和潜在的雇主非常有价值。 《挂典》 甚至将编码列为人们必须学*的技能。

让我们来看看人们从事编码工作有多长时间了,专业人士从事专业编码工作有多长时间了:

大多数回答者从事编码工作不到十年。资料来源:Nik Piepenbreier

根据 Stack Overflow,像 VBA 这样的语言开发者拥有最多的经验。

Python 和 PHP 等语言的开发人员经验最少。

这很好,因为你的竞争对手经验更少。

我们很快就会看到 Python 也是最受欢迎的语言之一。

从哪里开始?

选择哪种语言是最常见的问题之一。这是一个棘手的问题,但值得探索。

Stack Overflow 询问他们的回答者他们想学什么语言,喜欢使用什么语言,害怕使用什么语言。虽然调查结果并不是从哪里开始的确定列表,但它们可以给你一个大概的指示,告诉你什么可能是愉快的学*,什么可能不是。

超过四分之一的 2019 受访者想学 Python!资料来源:Nik Piepenbreier

上面的图表显示了专业开发人员最想要的语言——这意味着还不知道它的开发人员想要使用它。

最受喜爱的语言有哪些?

让我们探索一下开发人员使用哪些语言,以及继续喜欢使用哪些语言。

Rust 和 Python 是非常受欢迎的语言。资料来源:Nik Piepenbreier

这些语言是一个很好的地方,可以让你开始探索最适合你想要完成的事情。

开发者现在喜欢什么语言?

让我们看看 Stack Overflow 的数十万名受访者是怎么说的:

VBA 语仍然是一种可怕的语言。资料来源:Nik Piepenbreier

虽然这并不意味着要避免使用什么语言的明确列表,但这可能会让您了解人们在使用什么语言时会感到吃力或乏味。

(这个可怕的数字意味着开发人员目前正在使用这种语言,但是没有兴趣继续这样做。)

现在怎么办?我从哪里开始?

所以,你有学*编程的动力?现在怎么办?

Python 是一个很好的起点!Python 很容易掌握,实现起来也很快,而且背后有一个很棒的、有用的社区。它非常有用,可以让您构建各种各样的工具,从自动化脚本到机器学*模型,再到 web 应用程序。

但是不要止步于此。

四处看看,在谷歌上搜索最受欢迎和最想要的语言,看看什么样的项目能引起你的共鸣。

帮助您起步的资源

  • 我的电子书为数据科学提供了 Python 的完整介绍。点击这里查看。它附带了一个交互式环境。
  • 请关注我的 Medium,并查看我的其他一些关于使用 Python 实现工作自动化的文章。
  • 我是如何通过 CS Dojo 学会编码的——这是一个伟大的 Youtuber 上的一个伟大的视频,它有惊人的资源来指导你进入编程。
  • Kaggle 的培训部分 — Kaggle 是数据科学竞赛的首要资源,拥有一个很棒的培训部分。
  • 代码学院为各种语言提供免费的入门课程。

学*编码。学* Python。

原文:https://towardsdatascience.com/learn-to-code-learn-python-efb037b248e8?source=collection_archive---------49-----------------------

你想学*编码但是不知道从哪里开始吗?你来对地方了。我将向您介绍学* Python 的原因,以帮助您决定它是否适合您,并提供一个资源列表来学*基础知识,设置您的环境,找到项目开始,以及在您的编码之旅中可以去哪里获得帮助和支持。

为什么要学 Python?

Python 是一种多功能的编程语言,可以用于软件开发、数据分析、机器学*甚至 web 开发!如果你想给机器人编程,从事数据科学职业或者做漂亮的可视化,学* python 是一个很好的起点!

如果这是您第一次学*编码,那么语法(语句的结构)与英语相似,需要更少的代码行,一旦您基本掌握了逻辑、语法和结构,就可以很容易地应用于其他编程语言。

然而,如果你更专注于 web 或应用程序开发,你可能会考虑其他编程语言。学*编码时,HTML、CSS 和 JavaScript 也是很好的起点。不过,不要停止阅读,下面的许多资源和技巧都与任何新开发人员相关!

资源

根据你的学*风格,有不同类型的课程可供你选择。有带代码示例的书面教程、带交互式编码问题的短视频、现场编码视频或简单的教科书。我在这个列表中包括了一系列的资源,这样你可以尝试一下,决定哪种学*方式最适合你。

免费学*编码

1。FreeCodeCamp

FreeCodeCamp 是一个学*编程的专用社区平台。他们有课程、教程、视频和文章来帮助您入门,并涵盖许多不同的编程语言。他们网站上的课程主要集中在 web 开发上,如果你想学* HTML、CSS 和 JavaScript,这是一个很好的起点!
对于 python,他们已经编写了一个参考资料综合指南,以及一个 YouTube 课程

编程语言: Python、HTML、CSS、JavaScript + more
级别:初级、中级、高级
内容类型:文章、视频、互动教程

2。HiPy

HiPy 是一个开放的社区,致力于向任何人介绍 Python 编码。他们在利物浦定期举办活动,并有一系列初学者友好的笔记本,你可以通过它来工作,还有一个Python 入门课程,涵盖如何开始。他们还有一个 YouTube 频道,最*还播放了现场编码活动,绝对值得一看!

编程语言: Python
级别:初级、中级、高级
类型:教程、视频、事件

  1. EdX 课程

EdX 有一系列 python 课程可供选择。这些课程可以免费完成,也可以选择付费获得证书。这些课程通常由公司或大学开办,你可能需要探索找到适合你的课程。我发现这些课程时好时坏。

查看这个微软课程为绝对初学者介绍 Python!

编程语言: Python、HTML、CSS、JavaScript +更多
级别:初级、
高级、类型:课程

4。Coursera

与 EdX 类似, Coursera 有一系列不同的免费课程,需要付费才能获得认证。

如果你在寻找机器学*的介绍,我去年完成了吴恩达的机器学*课程,强烈推荐你去看看!它提供了一个广泛的概述,包括每周作业和课程中的问题。我真的很喜欢这种教学风格,作业很有趣,也很有挑战性!我唯一的警告是,作业使用了一种叫做 Octave 的编程语言,这种语言有时会有点尴尬——课程中有 Octave 的介绍,但是如果你是编程新手,你可能会发现有时会有点棘手!

编程语言: Python、HTML、CSS、JavaScript +更多
级别:初级、中级、高级
类型:课程

5。Kaggle 微课

Kaggle 是一个举办竞赛和数据挑战的数据科学平台。它还提供微型课程,包括对 python 的介绍,以及带有包括 python 和数据科学概念的现场编码演示的 YouTube 频道。一旦你掌握了基础知识和数据科学的基础,你就可以加入社区,在运动场比赛中练*你的技能,例如泰坦尼克号挑战赛,或者探索 Kaggle 数据集用于你自己的项目。

编程语言:Python
级别:中级、
高级、类型:教程、视频

6。w3 学校

W3Schools 是一个学* web 技术的网站,包含代码示例和 Python、HTML、CSS 和 JavaScript 的交互式教程。我经常回头查阅 w3 的文档和详细的解释,包括如何使用这个函数或包的例子。

编程语言: Python、HTML、CSS、JavaScript +更多
级别:初学者
类型:文档、教程

7。Udemy

Udemy 提供超过 100,000 门在线课程,主题广泛,语言多样。不同的教师提供了大量的 python 课程,但是您可以通过仅指定免费课程并选择您要寻找的级别和主题来缩小范围。如果你和某个老师很熟,并且喜欢他们的教学风格,我建议你利用上面的资源学*基础知识,并使用 Udemy 深入某个特定的主题。

注意: Udemy 也包含付费课程,但它们经常打折,价格大幅降低,所以最好等这些!

编程语言: Python、HTML、CSS、JavaScript +更多
级别:初级、中级、高级
类型:课程

8。用 Python 自动化枯燥的东西

如果你喜欢书,那么 用 Python 自动化枯燥的东西 是一个很好的起点,内容也可以在网上找到。它提供了关于如何开始的实际例子,以及你可以在每章末尾完成的项目例子。

编程语言: Python
级别:初学者,中级
类型:

9。用于数据科学的 python

如果您已经掌握了基础知识,并且正在寻求探索 Python 与数据科学的关系, Python for Data Science 是一个有价值的资源,同样可以在网上免费获得,尽管从书架上拿一份副本也很方便!

编程语言:Python
级别:中级、
高级、类型:

付费资源

还有一些资源为他们的学*平台提供订阅

1。365 数据科学

365DataScience 是一个数据科学学*平台,初期免费提供课程材料样本。我个人没有使用过这一资源,但它们涵盖了数据科学中的一系列主题,并有一个免费层,让您在承诺订阅之前体验一下。

编程语言: Python,SQL
级别:中级,
高级,类型:互动教程

2。使用 Codecademy 学*基础知识

Codecademy 需要订阅才能访问全部课程内容,并提供不同编程语言的入门和高级课程。随着时间的推移,免费访问的内容发生了显著变化。虽然这是我第一次学* Python 时的首选资源,因为我喜欢课程的互动风格,但现在有了这个平台,你可以中途通过一个章节,除非你注册,否则无法前进。

编程语言: Python、HTML、CSS、JavaScript +更多
级别:初级、中级
类型:互动教程

3。数据请求

如果您已经熟悉 Python 的基础知识,并且希望将您的知识应用到数据科学的概念中,请查看 DataQuest 。像前两个平台一样,DataQuest 也需要订阅,但他们提供免费试用,所以如果你有兴趣,就试试吧!

编程语言: Python,SQL,R
级别:中级,
高级,类型:互动教程

故障排除

学*编码时最难的部分之一是当你陷入困境时,试图找出要搜索的内容。你练*得越多,这就越容易!这里有几个常见的地方,你可能会找到你正在寻找的答案:

1。堆栈溢出

当搜索一个编程问题时,排名靠前的结果通常来自 StackOverflow 。Stackoverflow 是一个开放的社区,人们可以在这里提问,其他开发人员也可以提供帮助。很有可能,你遇到的问题,别人已经在 StackOverflow 上问过了,可能的解决方案正等着你呢!

2。开发到

DEV 是一个软件开发人员的社区,他们聚在一起互相帮助。除了开发社区共享的播客和视频之外,该平台还通过文章、教程和讨论支持协作和网络化学*!如果您注册了,您也可以与社区分享您的编码之旅和您学到的东西,并结识其他学*编码的人!

3。中等

Medium 有一系列致力于学*编码的出版物。TowardsDataScience 有许多关于数据科学和 Python 的文章和教程,BetterProgramming 和 HackerNoon 也有关于编程的内容,你也可以找到公司博客,如网飞技术博客,他们分享技术文章和教程。

4。数据科学堆栈交换

与 StackOverflow 类似,数据科学 Stack Exchange 是一个提出技术问题的论坛,这次专门针对数据科学和机器学*。在对 Python 问题进行故障排除时,该资源经常出现在搜索结果的顶部,并且是另一个社区可能已经有了您正在寻找的答案的站点!

5。推特

Twitter 上有一个庞大的技术社区。许多人加入了 #100DaysOfCode ,承诺在 100 天的过程中每天都发推特,分享他们学到的东西,并在他们的旅程中支持其他人。如果你遇到了困难,你也可以联系这个社区,有人可能会回答你的问题或者给你指出一些可以帮助你的东西。

6。加入 Python 社区

还有在世界各地举办聚会和代码之夜的全球网络。也有许多 meetup 团体专注于举办技术讲座、教程和活动——查看 MeetupEventbrite 了解您当地的活动。同样值得考虑的是有空闲频道的在线社区和小组、电报小组或虚拟聚会,在那里你可以加入学*、分享和交流。

安装您的 Python 环境

到目前为止,您已经阅读了大量的资源,接下来,让我们在您的机器上安装 Python!

安装 Python 时有几种不同的选项,这取决于您使用的操作系统以及您希望如何设置。对于新程序员,我推荐安装 Anaconda ,它上手很快,适用于 Windows、MacOS 和 Linux。

Python 2 还是 Python 3?

对 Python 2 的支持于 2020 年 11 日停止。你可能仍然会发现用 Python 2 编写的软件,但是如果可能的话,我建议安装/升级到 Python 3!

什么是蟒蛇?

Anaconda 是 Python 和 r 的开源发行版,这意味着它安装了您需要开始使用的所有必要软件和软件包。它包括:

  • PythonR 编程语言
  • 预装 python
  • **conda**,一个 python 包管理器,可以让你轻松安装和更新 python 包。你可能还会看到提到的pipcondapip的替代物。
  • Spyder 是一个集成开发环境(简称 IDE),除了测试、调试和检查程序的工具和许多使编程更容易的功能,包括自动完成,它还包括一个文本编辑器——想想微软的 Word,但用于编写代码!
  • (可选但推荐) PyCharm 是另一个 IDE,安装时会提示你是否想和 Anaconda 一起安装。我建议这样做!比起 Spyder,我更喜欢 PyCharm,因为它更容易导航和开始使用。
  • Jupyter Lab/Jupyter 笔记本也可以通过 Anaconda Navigator 安装。这些工具允许你在文本或可视化的同时编写代码,在演示项目或浏览教程时会很有用。

如果您已经有了上面没有包括的首选 IDE,比如 Sublime 或 Visual Studio 代码,请查看 Anaconda 文档以了解如何在 IDE 中选择 Anaconda Python 作为您的 Python 解释器。

浏览器中的 Python

你也可以通过使用小饰品在你的浏览器中访问 Python,如果你想保存你的代码,你也可以在那里设置一个账户。

安装 Python 的其他方法

如果您不想使用 Anaconda,您可以从 Python 软件基金会下载并安装 Python。
如果你使用的是 Linux 或 MacOS,你可能已经预装了 Python,但这可能不是 Python 3。如需更多安装选项,请遵循 RealPython.com 上的说明。

下一步是什么?

那么您已经安装了 python,了解了基础知识,并准备好开始一个项目了!

下面列出了一些可能的项目和挑战,希望能给你一些启发:

1。代码战争

CodeWars 有许多编码招式或挑战,在这里你可以测试你的 python 技能,并竞争解决从初学者到难以置信的高级的问题!

2。欧拉项目

感觉像一个新的挑战?为什么不尝试使用 python 解决前 100 个欧拉项目问题呢?你可以在 Twitter 上关注 #ProjectEuler100 ,加入社区解决挑战!我在 2020 年初开始挑战,目标是在年底前完成所有 100 个目标…进入今年的第 5 个月,我远远落后于目标!

3。开始一个项目

查看 MediumDEV.to 的教程,你可以跟随它开始你的第一个项目,或者如果你正在寻找一个数据科学挑战,查看 Kaggle 上的Titanic Machine Learningchallenge。

请关注我的下一篇文章,我将通过一个项目,探索数据集,创建可视化,并为您提供继续编码之旅的技能和工具。

感谢您的阅读!如果你喜欢我的文章,那么订阅我的每月简讯,在那里你可以将我的最新文章和顶级资源直接发送到你的收件箱!

您可以在 Medium 上关注我以获取更多文章,在 Twitter 上关注我,或者在我的网站上了解更多我正在做的事情。

学会在 5 分钟内创建一个聊天机器人:谷歌的对话流

原文:https://towardsdatascience.com/learn-to-create-a-chatbot-in-5-minutes-googles-dialogflow-4064b4fa336a?source=collection_archive---------23-----------------------

在我看到 Google 的 DialogFlow 之前,我从未意识到构建一个聊天机器人会如此简单。这就像巫师有一根魔杖,聊天机器人不知从哪里冒出来一根鞭子。不管怎样,让我们为自己是这里的巫师而自豪,我们的魔杖就是对话流。

卢卡斯·佛罗伦廷Unsplash 上拍摄的照片

对话框流中的组件

现在让我们进入构建模块,这些模块必须被安排以获得一个功能性的机器人。

代理:代理可以实现为客户支持超级明星,直接与用户打交道,以获得令人敬畏的体验。类似地,在 DialogFlow 中,我们的聊天机器人在高层被称为代理。

意图:代理通过意图和意图连接到用户,一般来说,对用户试图做出的对话请求进行分类。例如,如果一个用户想要查看他的帐户详细信息,那么该请求将被定向到 AccountenquiryIntent。因此,意图是将问题类型重定向到特定类别的守门人

实体:实体处理数据提取部分。它们有助于识别特定的关键词,这些关键词对于引导回复的特定意图至关重要

语境:语境就像自然语言理解在哪里回应当前的对话我们需要获取之前对话的语境。因此,它们有助于将每个对话块连接在一起,以便聊天机器人的回复有意义

满足感:这是谈话的支柱。它使用 API 连接到后端数据库,以存储对话或检索数据库的信息

集成:这些是可以连接到 dialogflow 的外部应用程序,这样我们的聊天机器人就可以在外部世界茁壮成长。一些应用程序包括,slack,脸书信使,Twilio,丨t丨e丨l丨e丨g丨r丨a丨m丨s丨

让我们深入:做部分

现在让我们通过实际实现一些很酷的东西来弄脏我们的手

为了访问 Dialogflow,我们需要一个 Google 帐户。所以一定要有一个,并使用链接进入对话流页面和登录谷歌。接受谷歌的条款和条件并设置您的国家。你将被带到对话流控制台

1:对话流控制台。作者提供的图片来源

1.创建代理:

第一步是创建一个代理,这就是我们实际的聊天机器人。因此,点击页面左上角的创建代理按钮或中间的按钮。给你的聊天机器人起个名字,设置语言和它工作的时区。完成后,点击创建

2:代理设置页面。作者提供的图片来源

2.设置意图:

在屏幕的左上角,我们可能会找到一个名为 Intent 的选项卡。默认情况下,DialogFlow 为我们提供默认的回退意图和欢迎消息意图。如果您点击任何一个意向,您可能会发现:

  • 训练短语:这些是用户在与聊天机器人交互时可能提供的合适对话。我们不需要提供所有可能的对话,相反,我们只提供几个样本。对话流后端的机器学*算法将使用所有合适的短语进行训练
  • 响应:这些是聊天机器人在识别合适的训练对话之一时提供的响应。如果聊天机器人不能识别输入对话,则向用户给出回退问题,以提供更清晰的输入信息

这是一个屏幕截图,显示了培训短语和回答,以及测试对话

图 3: Bot 训练和响应。作者提供的图片来源

3.自定义意图:

要创建自定义意图,请单击创建意图。例如,如果我们计划创建一个帮助预订电影票的聊天机器人,我们可以创建一个名为ordermovieinent 的自定义意图。训练短语中,您可以设置接受屏幕类型和电影名称的对话,并相应地创建响应

4.实体:

实体帮助提取数据的特定部分,以便聊天机器人做出相应的响应。例如,如果对话中有我想今天订票,,系统会自动将今天理解为日期时间字段,并帮助聊天机器人做出响应。我们也可以创建自定义实体。在电影票预订示例中,我们可以创建 tickettype、Moviename 等。作为自定义实体。要创建它,单击左上角选项卡上的实体,并给实体命名。指定变量和同义词。这里有一个例子

图 4:实体设置页面。作者提供的图片来源

5.在意图中使用自定义实体:

我们可以将实体创建为对话中的强制部分,以便用户向机器人提供所有需要的信息。为此,打开已经创建的意图,在动作和参数部分添加创建的实体名称和回退响应(如果用户没有提供)。

图 5:意向设置页面。作者提供的图片来源

一旦它被添加,包括一些训练阶段的例子,包括添加的实体,并点击保存,后面的 ML 模型将训练所有可能的组合

6.背景:

在每一次谈话中,谈话的背景都很重要。这意味着,如果机器人必须迅速回答问题,它应该理解用户以前回答过什么。为了创建这种对话流,我们可以将 sub Intent 添加到已经存在的 Intent 中。

为此,转到意向页面,点击添加跟进意向

图 6:跟进意向设置页面。作者提供的图片来源

选择建立对话所需的意图,例如,如果用户肯定回答,我们可以使用 Yes 跟进意图,这可能会提示他们在电影预订机器人的情况下提供联系方式/其他详细信息。一些流行的跟进意图包括

图 7:流行的跟进意图。作者提供的图片来源

7.履行:

来自用户的响应可以存储到后端使用履行功能的数据库。默认情况下,DialogFlow 为连接到后端提供了两个 API 选项— 1。Webhook 2。内嵌编辑器。“履行”选项卡位于屏幕的左侧

8.集成:

我们可以将我们的聊天机器人与多个可用的外部应用程序集成,如脸书信使、Slack、Twilio、我们自己的网站和许多其他地方。为此,我们只需进入集成,打开我们想要集成的应用程序。

荣誉🙌您已经创建了功能齐全的聊天机器人。DialogFlow 提供了许多更高级的功能,可以很好地进行试验:)

再见!祝学*愉快

学*在 Android 上创建一个涂鸦游戏

原文:https://towardsdatascience.com/learn-to-create-a-doodle-draw-game-on-android-f713e64408a7?source=collection_archive---------43-----------------------

使用 PyTorch 和深度 Java 库

QuickDraw 数据集(来源https://github . com/Google creative lab/quick draw-Dataset/blob/master/preview . jpg)

介绍

涂鸦绘画游戏的目标是以最快的速度创作出一幅特定物品的图画,比如一所房子或一只猫。虽然绘画部分很简单,但在深度学*出现之前,计算机不可能准确猜测你画了什么。与照片不同,绘画也有艺术家特有的创作风格,这使得它们特别难以理解。你可以在这里看到任何涂鸦绘画游戏[的例子。

随着多年来计算能力的稳步增长,现在已经可以在手机操作系统(如 Android)上运行边缘/物联网设备上的机器学*(ML)任务。然而,Android 运行在 Java 上,而大多数深度学*框架,如 TensorFlow 和 PyTorch,都是为 Python 设计的。为了解决这个挑战,我们需要一种在 Java 中构建深度学*模型的方法。Deep Java Library (DJL)是一个新的开源深度学*框架,由 AWS 构建,可以轻松地用 Java 进行深度学*。](https://djl.ai/website/demo.html#doodle)

Android 上的涂鸦应用程序(图片由作者提供)

在本教程中,我们将介绍在 Android 上部署 PyTorch 涂鸦识别模型的主要步骤。因为代码库相对较大,所以我们将涵盖您需要理解的最重要的部分,以便模型能够正确工作。你可以访问我们的示例项目开始制作。

设置

这个项目需要 Android API 26+来使用大多数 DJL 功能。您可以查看我们的示例项目设置以节省一些时间。下面的代码块列出了此项目所需的依赖项:

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'ai.djl:api:0.7.0'
    implementation 'ai.djl.android:core:0.7.0'
    runtimeOnly 'ai.djl.pytorch:pytorch-engine:0.7.0'
    runtimeOnly 'ai.djl.android:pytorch-native:0.7.0'
}

您将使用 DJL 提供的 API 和 PyTorch 包。

步骤 1:定义布局

学*为 Android 创建画图应用的启发,我们可以在 Android 上创建一个视图类来显示结果。

DoodleDraw 布局(图片由作者提供)

正如您在这些图像中看到的,您在主页中创建了两个视图对象。PaintView对象是允许用户涂鸦的对象。ImageView在右下角会显示实际图像馈给模型进行推理。你还在左下角预留了一个按钮来清理画布。

步骤 2:处理绘制动作

在 Android 设备上,您可以定制一个 Android 触摸事件处理程序来响应用户的触摸动作。在这种情况下,我们定义了三个动作处理程序来处理不同的触摸动作:

  • 触摸开始:当检测到触摸动作时触发
  • 触摸移动:当用户在屏幕上移动手指时触发
  • touchUp:当用户完成触摸动作时触发

同时,您使用paths来存储用户在画布上绘制的路径。让我们看看实际的代码。

重写 OnTouchEvent 和 OnDraw

覆盖onTouchEvent函数来处理动作:

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY(); switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN :
            touchStart(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE :
            touchMove(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP :
            touchUp();
            runInference();
            invalidate();
            break;
    } return true;
}

如该代码块所示,您在MotionEvent.ACTION_UP处理程序中添加了一个runInference。该函数用于预测用户画线完成时的涂鸦。我们将在接下来的几个步骤中讨论这一点。

你还需要覆盖 onDraw 函数来显示用户画完的涂鸦:

@Override
protected void onDraw(Canvas canvas) {
    canvas.save();
    this.canvas.drawColor(DEFAULT_BG_COLOR); for (Path path : paths) {
        paint.setColor(DEFAULT_PAINT_COLOR);
        paint.setStrokeWidth(BRUSH_SIZE);
        this.canvas.drawPath(path, paint);
    }
    canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
    canvas.restore();
}

实际图像存储在位图中并显示在屏幕上。

触摸开始

当触摸开始时,下面的代码创建一个新的路径,并在屏幕上记录该路径的坐标。

private void touchStart(float x, float y) {
    path = new Path();
    paths.add(path);
    path.reset();
    path.moveTo(x, y);
    this.x = x;
    this.y = y;
}

触摸移动

在移动过程中,你不断记录坐标并形成一个二次贝塞尔曲线。您可以使用移动动作的绝对差值来校准绘制动作。只有当坐标差超过公差时,它才画一条线。

private void touchMove(float x, float y) {
    if (x < 0 || x > getWidth() || y < 0 || y > getHeight()) {
        return;
    }
    float dx = Math.abs(x - this.x);
    float dy = Math.abs(y - this.y); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        path.quadTo(this.x, this.y, (x + this.x) / 2, (y + this.y) / 2);
        this.x = x;
        this.y = y;
    }
}

修饰

当触摸完成时,下面的代码块在路径上画一条线,并计算路径的矩形边界。

private void touchUp() {
    path.lineTo(this.x, this.y);
    maxBound.add(new Path(path));
}

第三步:开始推理

要在 Android 上运行推理,需要完成以下三项任务:

  • 从 URL 加载模型
  • 定义预处理和后处理
  • 从绘画视图运行推理

为了实现这些目标,您需要创建一个DoodleModel类来覆盖它们。下一节将遍历这个类中的核心逻辑来完成这些任务。

加载模型

DJL 有一个内置的模型管理系统。用户可以在文件系统中指定存储模型的目录。

File dir = getFilesDir();
System.*setProperty*("DJL_CACHE_DIR", dir.getAbsolutePath());

通过定义DJL_CACHE_DIR属性,模型被保存到目标位置。

之后,定义一个标准从 URL 下载模型。zip 文件包含:

  • doodle_mobilenet.pt:py torch 型号
  • synset.txt:包含类名
Criteria<Image, Classifications> criteria =
            Criteria.builder()
                    .setTypes(Image.class, Classifications.class)
                    .optModelUrls("https://djl-ai.s3.amazonaws.com/resources/demo/pytorch/doodle_mobilenet.zip")
                    .optTranslator(translator)
                    .build();
return ModelZoo.loadModel(criteria);

这个代码块还定义了translator。您可以使用这个类对图像进行预处理和后处理。
最后,在主活动中创建一个模型,并使用它生成一个预测器,如下所示:

@Override
protected Boolean doInBackground(Void... params) {
    try {
        model = DoodleModel.loadModel();
        predictor = model.newPredictor();
        return true;
    } catch (IOException | ModelException e) {
        Log.e("DoodleDraw", null, e);
    }
    return false;
}

有关模型加载的更多信息,请参见如何加载模型

使用翻译器定义预处理和后处理

在 DJL,我们定义了一个翻译器接口,用于进行预处理和后处理。这里我们刚刚定义了一个image classificationtranslator实现了DoodleModel中的翻译器:

ImageClassificationTranslator.builder()
    .addTransform(new ToTensor())
    .optFlag(Image.Flag.GRAYSCALE)
    .optApplySoftmax(true).build());

在内部,转换器在创建过程中加载 synset.txt 文件来存储类名。我们的预期输入是图像,我们的输出是分类。对于后处理,我们对输出应用 softmax 操作,并存储在分类类中。要了解更多关于 translator 如何工作并创建您自己的定制翻译器,请参见使用您的模型 进行推理。

从绘画视图运行推理

最后,实现我们之前定义的runInference函数。

public void runInference() {
    // make a copy
    Bitmap bmp = Bitmap.createBitmap(bitmap);
    // do scaling
    bmp = Bitmap.createScaledBitmap(bmp, 64, 64, true);
   // run inference
    Classifications classifications = model.predict(bmp);
   // display input image
    Bitmap present = Bitmap.createScaledBitmap(bmp, imageView.getWidth(), imageView.getHeight(), true);
    imageView.setImageBitmap(present);
   // display output
   if (messageToast != null) {
        messageToast.cancel();
    }
    messageToast = Toast.makeText(getContext(), classifications.toString(), Toast.LENGTH_SHORT);
    messageToast.show();
}

这将在屏幕上创建一个 Toast 弹出窗口,显示结果如下:

吐司(作者图片)

就是这样。您刚刚完成了第一个涂鸦应用程序的创建!

可选:优化输入

为了获得最佳预测,您可能需要计算此图像的最大界限。该模型是在正方形图像上训练的,因此将输入图像设置为正方形将获得最佳结果。

裁剪图像(作者提供的图像)

右边的图像比左边的图像有更好的预测结果,因为它不包含太多的空白。因为所有的路径都可以计算出一个矩形边界,所以我们可以找到所有 x 和 y 坐标的最小和最大值来找到最大的正方形。我们已经定义了一个Bound类来做这件事。之后,按如下方式裁剪存储的位图:

RectF bound = maxBound.getBound();
int x = (int) bound.left;
int y = (int) bound.top;
int width = (int) Math.ceil(bound.width());
int height = (int) Math.ceil(bound.height());
// do crop
Bitmap bmp = Bitmap.createBitmap(bitmap, x, y, width, height);

就是这样!现在你应该可以在你的 Android 设备上创建一个涂鸦游戏了。同样,您也可以参考我们的示例项目以获得完整的示例。

关于深度 Java 库

DJL 标志(图片由作者提供)

深度 Java 库(DJL) 是一个用 Java 编写的深度学*框架,同时支持训练和推理。DJL 建立在现代深度学*引擎(TenserFlow、PyTorch、MXNet 等)之上。您可以轻松地使用 DJL 来训练您的模型或部署您喜爱的模型从各种引擎,没有任何额外的转换。它包含一个强大的 ModelZoo 设计,允许您管理训练好的模型并在一行中加载它们。内置的 ModelZoo 目前支持来自 GluonCV、HuggingFace、TorchHub 和 Keras 的 70 多个预训练和随时可用的模型。

关注我们的 GitHub演示库Slack channeltwitter 获取更多关于 DJL 的文档和示例!

了解 p 值的正确解释

原文:https://towardsdatascience.com/learn-to-read-p-value-in-english-11725c09f30e?source=collection_archive---------31-----------------------

理解低 p 值如何导致拒绝零假设。

图片来自 Unsplash

当我们开始学*概率和统计的概念时,有几个主题需要我们进行逻辑跳跃,常常让我们感到困惑。在我之前的帖子中,我曾经谈到过这样一个话题,置信区间。在这篇文章中,我将尝试解释另一个令人困惑的话题,p 值。(剧透提醒:不,不是概率,而是和概率有关)

为什么我们不能理解 p 值的概念,是因为我们忽略了 p 值的基本解释,只关注它的概率方面。我在这里的目的只是解释 p 值的基本英文解释,这是经常被忽视的。

在开始之前,先讨论两个先决条件:条件概率和假设检验。

条件概率

P(A|B)被解释为给定或以事件 B 为条件的概率。

p(今天会下雨)=0.4 表示今天有 40%的几率会下雨。这是一个无条件的概率。没有与之相关的条件或假设。

p(今天会下雨|天空是灰色的)=0.7 意味着今天下雨的概率增加了,因为我们现在有了天空是灰色的新信息。这个概率回答了这个问题,假设天空是灰色的,今天下雨的可能性有多大。

维基百科的第一段,这个概念解释的很清楚。

现在,如果 P(今天会下雨|天空是灰色的)=0.3,这并不意味着今天下雨的可能性低,但鉴于天空是灰色的,今天下雨的可能性很小。注意那一点!

假设检验:概述

真实世界场景

假设你是 Expedia 的一名数据科学家。你需要分析是什么因素促使新用户成为 Expedia 的忠实客户。你对数据做一些初步的探索性分析。你发现当一个新用户通过一些促销优惠或交易预订时,他/她倾向于回到网站。因此,如果一个新用户在第一次访问 Expedia 时使用一些促销优惠来预订服务,他们比那些没有使用任何交易就直接预订的新用户更有可能回来。

稍微研究了一下艺术,你会发现这些交易和优惠对新网站的访问者来说并不吸引眼球,因为它们是用蓝色显示的。你认为如果交易和优惠重新设计并用红色突出显示,这可能会增加首次用户的保留率。你向企业推荐这个。但是,为了从统计上表明你对自己的主张有多有信心,你需要执行以下步骤,而不是简单的想法叙述:

  • 用红色重新设计网站的推广内容,把这个新版本只展示给网站新增流量的一半。
  • 其余的新用户看到的是旧版本的网站,即蓝色。

如果一天之内有 100,000 个新用户访问该网站,想象一下,向 50,000 个用户显示旧版本,而向其余 50,000 个用户显示新版本。

这样,你就会明白是什么版本的网站引起了用户的注意并使用了这些交易。(点击阅读更多关于 A/B 测试的信息

想象一下,在新版本中,使用促销的新用户的百分比是 40%,而在旧版本中,使用促销的新用户的百分比仅为 20%。

在这里,你观察到使用新版网站时,使用推广的新用户数量增加了 100%。但是在你得出结论,将网站的促销颜色改为红色可以增加使用促销优惠的新用户,从而提高保留率之前,你必须确定这种增加不是随机的。这种增长可能是由于您的抽样方式,或者是因为,一般来说,当天使用新版本的用户不知道任何其他旅游预订网站,或者是因为任何其他随机原因。为了清楚起见,你运行一个假设检验。

假设检验方法

  1. 选择一个测试统计(此处为保留百分比)
  2. 阐明假设

零假设(总是现状): 两个版本没有区别。观察到的差异只是随机的。

另类假设: 两个版本有区别。

3.计算 p 值

p 值是反对零假设的证据。p 值越小,您应该拒绝零假设的证据就越强。

使用 img flip(https://imgflip.com/memegenerator)创建

逻辑飞跃:p 值

维基百科声明:

在假设零假设正确的情况下,p 值是获得至少与观察到的结果一样极端的测试结果的最大概率。

这里我们观察到了两个版本之间 100%差异的结果。所以,观察到的结果是 100%。

为我们的用例将维基百科语句写成一个数学等式:

P 值为 P(两个版本之间的差异≥100% |零假设为真)

用英语阅读这个等式(不是维基百科英语):

p 值是假设零假设为真,两个版本之间的百分比差异至少为 100% (观察到的结果)的概率。

当我们解释 p 值并认为 p 值只是一个概率时,我们经常忘记“给定”这一部分。

需要注意的一件非常重要的事情是,p 值并不能回答问题:这是偶然发生的概率有多大?或者假设为真的概率是多少。相反,p 值回答了这个问题:

如果我们假设这是偶然发生的(零假设为真),那么我们获得大于或等于我们已经观察到的结果的概率是多少。

为了理解这里的细微差别,让我们回到我在文章开头解释的雨的例子。p(今天会下雨|天空是灰色的)没有给出今天会下雨的概率。而是,如果天空是灰色的,今天会下雨的可能性。

现在,如果你重读维基百科的定义,事情就会水落石出。

但是为什么小 p 值会导致我们拒绝零假设呢?

假设,P(两个版本之间的差异≥100% |零假设为真)=0.04

假设零假设为真,只有 0.04 的几率我们观察到至少 100%的差异。因此,在我们的零假设为真的条件下,很难观察到至少 100%的差异。

但是在这里,你需要记住这 100%的差异已经在我们的测试中被观察到了。那么如果在我们的假设下,观察到至少 100%的差异是极不可能的,这表明我们的假设本身就是错误的。因此,我们拒绝我们的零假设,因为从 p 值,我们知道我们的假设是错误的。

加载可能需要一些时间。我假设你现在的脸有点像这样。但是你还记得高中时学过的矛盾证明吗?啊…这个概念有点类似。

因为我们得到 p 值为 0.04,这意味着我们拒绝了我们的零假设。由此,我们可以得出结论,两个版本之间的差异不是随机的,新版本的网站吸引了更多的用户使用推广代码,这对保留很重要。

现在,当 p 值变高时,我们无法拒绝零假设。我们从不接受我们的无效假设。这是因为假设检验类似于矛盾证明法。首先,我们假设零假设为假,开始假设检验。(参见 ThinkStatsT5【http://greenteapress.com/thinkstats/】T6Ch:7pg:80)

p 值总是与阈值α进行比较。alpha 的值取决于用例。最常用的 alpha 值是 0.05。

让我知道你对这篇文章的评论。如果这篇文章有所帮助,请鼓掌。

更多参考:

  1. 思统计(Ch:7)
  2. 道恩·格里菲斯的第一本统计书

🤝在 LinkedIn 上与我联系

学*数据科学的 Web 开发

原文:https://towardsdatascience.com/learn-web-development-for-data-science-2c4564b53670?source=collection_archive---------43-----------------------

如何从数据的海洋中拓宽我们的视野

Unsplash 上由 Atikh Bana 拍摄的照片

数据专家的生活通常相当舒适。我们坐在一个受控、安全的环境中,以特定的模式移动手指,让电子信号做一些事情——为此,我们得到了丰厚的回报。

这是一种便利的、有特权的存在。但在这种情况下,我们应该总是向前看,并问自己,下一步是什么?

这个行业的下一步是什么?为了我们的事业?应该把注意力放在哪里?

我不知道答案,但我非常相信学*做更多的事情。就我个人而言,我喜欢创造东西,我知道这是许多人的共同倾向。

对我们大多数人来说,我们可以让数据做事情。但是当涉及到允许其他人(没有 Python)使用我们的工具时,就不那么容易了。

在这些情况下,没有比我们在 web 开发中学*的技能更好的技能了。

因此,在这篇文章中,我将分享我发现的最好的资源,以开始掌握并快速产生实践 web 开发的切实好处——重点关注:

**> tensorflow.js****> Angular****> The Cloud**
 - Google Cloud
 - Azure

TensorFlow.js

很明显,tensorflow.js 是 JavaScript 中的 tensorflow。这是一个非常酷的项目,对于我们这些目前专注于 Python 和 ML 的人来说,这是进入 web 开发的一个极好的切入点。

对于那些熟悉 TensorFlow(或任何 ML 框架)的人来说,学* tensorflow.js 相当简单,因为我们构建的是相同的工作流,但语法略有不同。

例如,Python 中一个简单的多类分类器如下所示:

model = tf.keras.Sequential()model.add(tf.keras.layers.Dense(
    input_shape=(1, 10),
    activation="sigmoid", units=5
))model.add(tf.keras.layers.Dense(3, activation="softmax"))

用 tensorflow.js 重写,我们得到:

const model = tf.sequential();model.add(tf.layers.dense({
    inputShape: [10],
    activation: "sigmoid", units: 5
}))model.add(tf.layers.dense({activation: "softmax", units: 3})

一切都很熟悉,但是使用 JavaScript 语法。一旦一个模型被构建或导入到 JS 中,我们就开始构建简单的 HTML、CSS 和 JS 页面来支持与模型的交互— ,我将在这里介绍

所有这些都意味着我们逐渐构建了支持我们所使用的工具所需的许多要素。

学* tensorflow.js 最容易的地方是 Coursera 上的 deeplearning.ai:

[## 基于浏览器的模型和 TensorFlow.js

将机器学*模型带入现实世界涉及的不仅仅是…

www.coursera.org](https://www.coursera.org/learn/browser-based-models-tensorflow)

有角的

我们已经构建了一个包含我们模型的简单 web 应用程序。那很好,但是有很多限制。

仅仅用 HTML、CSS 和 JS 来构建一个真正交互式的、响应迅速的、漂亮的 web 应用程序,有点像期望使用普通花园棚中可用的工具和材料来构建一架 F-35。

布里特·盖瑟在 Unsplash 上拍摄的照片

棱角分明不是一般的花园棚子。这是一个非常强大的现代框架,专为构建网络应用而设计。

与大多数其他框架相比,它相对容易掌握。谷歌支持这个项目,Angular 社区非常庞大。

所有这些因素导致了一个蓬勃发展的生态系统,为一个已经强大的工具提供了信息。有很多学*框架的资源,但是我发现有三个资源特别特别。

1.繁忙的开发人员的角度速成班

本课程由 Mosh Hamedani 教授,他是一位非常受欢迎的教师,教授一系列的 web 开发课程。

对我来说,这是对 Angular 的完美介绍——它简短而甜美,没有任何不必要的绒毛。此外,有一整节专门介绍 TypeScript(编程语言),这对初学者非常有用。

[## 繁忙的开发人员的角度速成班

你可能听说过,如今有棱角的开发人员很吃香。而你在这里学角快…

www.udemy.com](https://click.linksynergy.com/link?id=I8HIg4MxNog&offerid=507388.719002&type=2&murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fangular-crash-course%2F)

2.Angular —完整指南(2020 版)

接下来是 Maximilian Schwarzüller 的课程。我认为这家伙真的每天都花一整天来创造有角度的课程。他创作了数量惊人的电影——但他真的 真的 擅长这个。

这是一个更长的课程,涵盖了 Mosh 课程的大部分内容(不包括打字稿介绍),但更深入。

尽管如此,如果你有选择,我无疑会选择 Mosh 的课程,然后是这个。但如果非此即彼——选择这个!

[## Angular —完整指南(2020 版)

掌握 Angular 10(以前的“Angular 2”)并使用 Angular.js 的继任者构建出色的反应式 web 应用程序

www.udemy.com](https://click.linksynergy.com/link?id=I8HIg4MxNog&offerid=507388.756150&type=2&murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fthe-complete-guide-to-angular-2%2F)

3.角形(全应用),带角形材料、Angularfire 和 NgRx

正如我说过的,Maximilian Schwarzüller 设计了很多有角度的课程,这个课程也是由 Max 设计的。

这门课程采取了不同于其他课程的方法。在这里,我们通过构建一个全功能的 web 应用程序来学* Angular!

这是一种不同的方法,我建议在学*本课程之前先熟悉 Angular 但它涵盖了许多很酷的功能。特别是:

  • 棱角分明的材料,谷歌的设计框架——它很漂亮,反应灵敏,非常有用。
  • Angularfire 是一个整合 Angular 应用程序和谷歌云的框架,这是许多现代网络应用程序的关键因素。

[## 角形(全应用),带角形材料、Angularfire 和 NgRx

使用角,角材料,Angularfire(带 Firestore 的+ Firebase)和 NgRx 建立一个真正的角应用程序…

www.udemy.com](https://click.linksynergy.com/link?id=I8HIg4MxNog&offerid=507388.1512962&type=2&murl=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fangular-full-app-with-angular-material-angularfire-ngrx%2F)

我们在 Angular 课程中接触了几次云,老实说,这已经足够让我们开始学*了。

然而,云已经存在,开发我们的云技能伴随着适度确定的未来需求。所以我会考虑在 Angular 或之后继续深造。

谷歌云

到目前为止,最轻松的基于云的设置是 Google Firebase,这是一个为我们管理所有基础设施的平台——我们只需上传代码。

我推荐通过第三角课程学* Firebase。然而,我注意到 Udemy 上有一些其他的 Firebase 特定课程——我从来没有上过,所以我不知道它们是否好。

尽管如此,谷歌云提供的不仅仅是 Firebase。如果你对更广阔的云平台感兴趣——谷歌自己在 Coursera 上提供了很多非常优秀的课程。

[## 谷歌云平台基础:核心基础设施

由谷歌云提供。本课程向您介绍使用谷歌云的重要概念和术语…

www.coursera.org](https://www.coursera.org/learn/gcp-fundamentals)

蔚蓝的

我最后推荐的是 Azure。对我来说,这更像是环境的结合——但是很明显 Azure 确实提供了一个很棒的服务。

现在,毫无疑问,掌握 Azure 的最佳过程是从 Azure 基础认证开始,在学*的同时使用该服务。

该课程提供了 Azure cloud 作为一个整体的广泛视角,允许您通过他们的进一步认证学*更专业的知识。

我不会在这里深入讨论 Azure 但是如果你对它感兴趣,我在这里写了更多关于准备基础认证考试的内容

快乐学*

Web 开发是一项技能,比其他任何技能都更能让你开始与世界其他地方分享你的工作。

我们可以把这些模型、管道和分析放在一个只有我们有钥匙的满是灰尘的柜子里,而不是在它们上面系上几条丝带,并把它们发布给世界其他地方。

我希望这些资源能对你有所帮助。它们是迄今为止我上过的最好的课,我怎么推荐都不为过。

我希望你喜欢这篇文章!如果你有任何问题或想法——让我在 Twitter 或下面的评论中知道。

感谢阅读!

如果你对学*数据科学的 web 开发感兴趣,但还没有准备好参加任何付费课程——试试我的关于 ML web-apps with tensorflow.js 的介绍文章:

[## 如何将 TensorFlow 模型部署到 Web

使用基本 JavaScript 在浏览器中运行 Python 构建的模型

towardsdatascience.com](/how-to-deploy-tensorflow-models-to-the-web-81da150f87f7)

15 分钟学会网络抓取

原文:https://towardsdatascience.com/learn-web-scraping-in-15-minutes-27e5ebb1c28e?source=collection_archive---------20-----------------------

从 Flipkart 网站抓取笔记本电脑数据

Emile Perron 在 Unsplash 上的照片

什么是网页抓取?

Web 抓取,也称为 web 数据提取,是从网站检索或“抓取”数据的过程。收集这些信息,然后导出为对用户更有用的格式,可以是电子表格或 API。虽然网页抓取可以手动完成,但在大多数情况下,自动工具在抓取网页数据时更受青睐,因为它们成本更低,工作速度更快。

网络抓取合法吗?

最简单的方法就是查看网站的 robots.txt 文件。您可以通过将“/robots.txt”附加到您想要抓取的 URL 来找到该文件。它通常位于网站域/robots.txt。如果所有由“用户代理:*”指示的机器人在 robots.txt 文件中被阻止/禁止,则不允许您抓取。为了这篇文章,我正在浏览 Flipkart 网站。所以,要看“robots.txt”文件,网址是www.flipkart.com/robots.txt.

用于网页抓取的库

BeautifulSoup: BeautifulSoup 是一个 Python 库,用于从 HTML 和 XML 文件中提取数据。它与您喜欢的解析器一起工作,提供导航、搜索和修改解析树的惯用方式。

Pandas: Pandas 是一个快速、强大、灵活且易于使用的开源数据分析和操作工具,构建于 Python 编程语言之上。

为什么是 BeautifulSoup?

这是一个从网页中提取信息的不可思议的工具。你可以用它来提取表格、列表、段落,也可以用过滤器从网页中提取信息。更多信息,你可以参考 BeautifulSoup 文档

抓取 Flipkart 网站

from bs4 import BeautifulSoup 
import requests 
import csv
import pandas as pd

首先,我们导入了 BeautifulSoup 和 requests 库,它们对于 web 抓取来说是非常重要的库。

requests: requests 是 Python 中使语言变得有趣的包之一。requests 基于 Python 的 urllib2 模块。

req = requests.get("[https://www.flipkart.com/search?q=laptops&otracker=search&otracker1=search&marketplace=FLIPKART&as-show=on&as=off&page=1](https://www.flipkart.com/search?q=laptops&otracker=search&otracker1=search&marketplace=FLIPKART&as-show=on&as=off&page=1)")  # URL of the website which you want to scrape
content = req.content # Get the content

要获取指定 URL 的内容,请使用请求库提交请求。这是包含笔记本电脑的 Flipkart 网站的 URL。

这是由不同笔记本电脑组成的 Flipkart 网站。该页面包含 24 台笔记本电脑的详细信息。现在,我们尝试提取笔记本电脑的不同特征,例如笔记本电脑的描述(型号名称以及笔记本电脑的规格)、处理器(英特尔/AMD、i3/i5/i7/Ryzen3Ryzen5/Ryzen7)、RAM (4/8/16 GB)、操作系统(Windows/Mac)、磁盘驱动器存储(SSD/HDD、256/512/1TB 存储)、显示屏(13.3/14/15.6 英寸)、保修(现场/有限硬件/国际)、评级(4.1

soup = BeautifulSoup(content,'html.parser')
print(soup.prettify())<!DOCTYPE html>
<html lang="en">
 <head>
  <link href="https://rukminim1.flixcart.com" rel="dns-prefetch"/>
  <link href="https://img1a.flixcart.com" rel="dns-prefetch"/>
  <link href="//img1a.flixcart.com/www/linchpin/fk-cp-zion/css/app.chunk.21be2e.css" rel="stylesheet"/>
  <link as="image" href="//img1a.flixcart.com/www/linchpin/fk-cp-zion/img/fk-logo_9fddff.png" rel="preload"/>
  <meta content="text/html; charset=utf-8" http-equiv="Content-type"/>
  <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
  <meta content="102988293558" property="fb:page_id"/>
  <meta content="658873552,624500995,100000233612389" property="fb:admins"/>
  <meta content="noodp" name="robots"/>
  <link href="https://img1a.flixcart.com/www/promos/new/20150528-140547-favicon-retina.ico" rel="shortcut icon">
....
....
</script>
  <script async="" defer="" id="omni_script" nonce="7596241618870897262" src="//img1a.flixcart.com/www/linchpin/batman-returns/omni/omni16.js">
  </script>
 </body>
</html>

这里我们需要指定内容变量和解析器,也就是 HTML 解析器。所以现在 soup 是我们解析的 HTML 的 BeautifulSoup 对象的一个变量。soup.prettify()显示网页的全部代码。

提取描述

当你点击“检查”标签,你会看到一个“浏览器检查框”打开。我们观察到描述的类名是' _3wU53n ',因此我们使用 find 方法提取笔记本电脑的描述。

desc = soup.find_all('div' , class_='_3wU53n')[<div class="_3wU53n">HP 14s Core i5 10th Gen - (8 GB/512 GB SSD/Windows 10 Home) 14s-cs3010TU Laptop</div>,
 <div class="_3wU53n">HP 14q Core i3 8th Gen - (8 GB/256 GB SSD/Windows 10 Home) 14q-cs0029TU Thin and Light Laptop</div>,
 <div class="_3wU53n">Asus VivoBook 15 Ryzen 3 Dual Core - (4 GB/1 TB HDD/Windows 10 Home) M509DA-EJ741T Laptop</div>,
 <div class="_3wU53n">Acer Aspire 7 Core i5 9th Gen - (8 GB/512 GB SSD/Windows 10 Home/4 GB Graphics/NVIDIA Geforce GTX 1650...</div>,
....
....
<div class="_3wU53n">MSI GP65 Leopard Core i7 10th Gen - (32 GB/1 TB HDD/512 GB SSD/Windows 10 Home/8 GB Graphics/NVIDIA Ge...</div>,
 <div class="_3wU53n">Asus Core i5 10th Gen - (8 GB/512 GB SSD/Windows 10 Home/2 GB Graphics) X509JB-EJ591T Laptop</div>]

使用 find 方法从网站中提取描述——抓取类名为“_3wU53n”的 div 标签。这将返回类名为' 3wU53n '的所有 div 标记。由于 class 在 python 中是一个特殊的关键字,我们必须使用 class keyword 并在这里传递参数。

descriptions = [] # Create a list to store the descriptions
for i in range(len(desc)):
    descriptions.append(desc[i].text)
len(descriptions)24 # Number of laptops
['HP 14s Core i5 10th Gen - (8 GB/512 GB SSD/Windows 10 Home) 14s-cs3010TU Laptop',
 'HP 14q Core i3 8th Gen - (8 GB/256 GB SSD/Windows 10 Home) 14q-cs0029TU Thin and Light Laptop',
 'Asus VivoBook 15 Ryzen 3 Dual Core - (4 GB/1 TB HDD/Windows 10 Home) M509DA-EJ741T Laptop',
 'Acer Aspire 7 Core i5 9th Gen - (8 GB/512 GB SSD/Windows 10 Home/4 GB Graphics/NVIDIA Geforce GTX 1650...',
....
....
'MSI GP65 Leopard Core i7 10th Gen - (32 GB/1 TB HDD/512 GB SSD/Windows 10 Home/8 GB Graphics/NVIDIA Ge...',
 'Asus Core i5 10th Gen - (8 GB/512 GB SSD/Windows 10 Home/2 GB Graphics) X509JB-EJ591T Laptop']

创建一个空列表来存储所有笔记本电脑的描述。我们甚至可以通过点访问来访问子标签。所以现在遍历所有的标签,然后使用。方法只从标记中提取文本内容。在每次迭代中,将文本添加到描述列表中。因此,在遍历所有标签后,descriptions 列表将包含所有笔记本电脑的文本内容(笔记本电脑型号名称和规格的描述)。

类似地,我们应用相同的方法来提取所有其他特征。

提取规格

我们注意到,不同的规格都在同一个 div 下,所有这 5 个特性(处理器、RAM、磁盘驱动器、显示器、保修)的类名都是相同的。

所有的特性都在“li”标签中,所有的类名都是相同的,都是“tVe95H ”,所以我们需要应用一些技术来提取不同的特性。

# Create empty lists for the features
processors=[]
ram=[]
os=[]
storage=[]
inches=[]
warranty=[]for i in range(0,len(commonclass)):
    p=commonclass[i].text # Extracting the text from the tags
    if("Core" in p): 
        processors.append(p)
    elif("RAM" in p): 
        ram.append(p)
# If RAM is present in the text then append it to the ram list. Similarly do this for the other features as well elif("HDD" in p or "SSD" in p):
        storage.append(p)
    elif("Operating" in p):
        os.append(p)
    elif("Display" in p):
        inches.append(p)
    elif("Warranty" in p):
        warranty.append(p)

的。文本方法用于从标签中提取文本信息,这样我们就可以得到处理器、RAM、磁盘驱动器、显示器和保修的值。因此,以同样的方式,我们也将这种方法应用于其余的功能。

print(len(processors))
print(len(warranty))
print(len(os))
print(len(ram))
print(len(inches))24
24
24
24
24

提取价格

price = soup.find_all(‘div’,class_=’_1vC4OE _2rQ-NK’) 
# Extracting price of each laptop from the website
prices = []
for i in range(len(price)):
 prices.append(price[i].text)
len(prices)
prices24
['₹52,990',
 '₹34,990',
 '₹29,990',
 '₹56,990',
 '₹54,990',
....
....
'₹78,990',
 '₹1,59,990',
 '₹52,990']

同样,我们提取每台笔记本电脑的价格,并将所有价格添加到价格列表中。

rating = soup.find_all('div',class_='hGSR34') 
Extracting the ratings of each laptop from the website
ratings = []
for i in range(len(rating)):
    ratings.append(rating[i].text)
len(ratings)
ratings37
['4.4',
 '4.5',
 '4.4',
 '4.4',
 '4.2',
 '4.5',
 '4.4',
 '4.5',
 '4.4',
 '4.2',
....
....
'₹1,59,990',
 '₹52,990']

这里我们得到的评级长度为 37。但是背后的原因是什么呢?

我们观察到推荐的笔记本电脑的类名也与特色笔记本电脑的类名相同,这就是为什么它也提取推荐的笔记本电脑的评级。这导致了收视率的上升。应该是 24 岁,但现在是 37 岁!

最后但同样重要的是,将所有要素合并到一个数据框中,并以所需的格式存储数据!

df = {'Description':descriptions,'Processor':processors,'RAM':ram,'Operating System':os,'Storage':storage,'Display':inches,'Warranty':warranty,'Price':prices}
dataset = pd.DataFrame(data = d) 

最终数据集

将数据集保存到 CSV 文件

dataset.to_csv('laptops.csv')

现在我们将整个数据集放入一个 CSV 文件中。

为了再次验证,我们阅读了 Jupyter 笔记本中下载的 CSV 文件。

df = pd.read_csv('laptops.csv')
df.shape(24, 9)

由于这是一个动态的网站,内容不断变化!

完整代码可以随时参考我的 GitHub 库

在 LinkedIn 上联系我 这里

“你在网络分析工具上每花 20 美元,你就应该在大脑上花 80 美元来理解数据。”—杰夫·绍尔

我希望你觉得这篇文章很有见地。我很乐意听到反馈,以便即兴创作,并带来更好的内容。

非常感谢您的阅读!

在 2020 年格蕾丝·赫柏庆典上了解基于时间数据的尖峰神经网络

原文:https://towardsdatascience.com/learning-about-spiking-neural-networks-for-time-based-data-at-the-grace-hopper-celebration-2020-68ba58fac5bb?source=collection_archive---------51-----------------------

之前的(亲自)格蕾丝·赫柏庆典。来源:https://ghc.anitab.org/previous-years/2017-gallery/

格蕾丝·赫柏 T2 庆典是世界上最大的女性科技会议。今年的会议(当然)是虚拟的,有来自 115 个国家的 30,000 名与会者。2020 年的主题是“我们一起建设”,考虑到今年事件后重建的迫切需要,这似乎格外合适。

提供了大量的讲座、研讨会和主题演讲,特别是我参加了一些非常有趣的技术讲座。这包括关于如何构建人工智能超级计算机的讲座、音译语言的自然语言处理(NLP )(事实证明这非常困难,当前的模型表现不太好)、用于可视化的 NLP 可解释性工具、会见人工智能虚拟助理,甚至是关于因果模型的经济学讲座。

对我来说,真正突出的三个数据科学讲座是关于尖峰神经网络的,谷歌关于负责任地构建人工智能产品的观点,以及足够奇怪的是,来自并不立即令人兴奋的税务软件世界的机器学*案例研究。我会在其他帖子中讨论其中的一些,但在这篇帖子中,我想谈谈脉冲神经网络,这是一种处理基于时间的数据的令人兴奋的神经网络形式。

脉冲神经网络

这次演讲由橡树岭国家实验室的科学家凯瑟琳·舒曼主持。

神经网络和时间序列数据

我对处理空间和时间的机器学*技术特别感兴趣,比如时间序列预测、路由的图形网络以及表示和概念化空间的方法,因为它们以一种真正有形的方式将数据科学的工作与我们生活的世界直接联系起来。所以我很喜欢这个关于脉冲神经网络(SNNs)的演讲,因为神经网络有许多不同的风格,但这一个是专门为处理与时间相关的数据而设计的,特别是来自实时数据源的数据。

如果你对数据科学领域有一点兴趣,你可能会看到下面这张图片,它描述了传统神经网络(NN)的基本模型架构。在一个标准的神经网络模型中,输入数据首先被输入到左边的输入神经元,然后通过称为突触的连接穿过其他神经元的隐藏层。数据在每一步都被转换,一层的输出被用作下一层的输入。

最终,您会到达最终输出图层,该图层会输出您的预测,例如,类别分类或回归中的数值。这里没有实时元素——输入数据同时通过所有层,按顺序通过每个隐藏层,然后一次性输出。

传统的神经网络架构。来源:https://www . kdnugges . com/2019/11/designing-neural-networks . html

介绍脉冲神经网络

但是,如果你的输入数据不是以整齐的方式在同一时间到来,那该怎么办?如果它是时间序列数据,或者以其他方式与时间相关,比如来自自动驾驶汽车上传感器的实时输入,那该怎么办?如果你的输出也是如此——如果这也是基于时间的,就像给自动驾驶汽车发出的何时转弯、何时加速或减速的指令,那会怎么样?

snn 是这个问题的解决方案。它们可以接收基于时间的输入,并产生基于时间的输出。它们没有整齐的层,而是具有更复杂的结构来在神经元之间传递数据,如环路或多向连接。因为它们更复杂,它们需要不同类型的训练和学*算法,比如对类似反向传播的方法进行改变,以适应尖峰行为。

下面的图片是凯瑟琳出色的关于这些网络如何工作的动画。你可以看到神经元和突触的结构是如何比之前图像中看到的清晰的层结构更复杂。在左侧,您可以看到黄线,代表进入网络的输入数据峰值。当这些尖峰到达输入(左边的白色大圆圈)神经元时,它们会刺激神经元,使它们放电(左边的黄色大圆圈)。这些神经元随后向网络产生内部尖峰,然后在整个网络中传播(沿着突触的黄色小圆圈)。这些内部尖峰最终到达输出神经元并产生输出尖峰。就输出而言,重要的数据不仅仅是输出是什么,还有峰值的数量以及峰值之间的时间,所有这些都可以告诉您一些有用的信息。

来源:Catherine Schuman (2020)尖峰神经网络:在神经网络和神经科学之间架起桥梁,在 2020 年格蕾丝·赫柏庆典上的演讲

应用程序

社交网络的潜在应用是巨大的,因为它们可以用于任何与时间相关的事情。给出的例子包括:

  • 玩电脑游戏《小行星》,你控制一艘船向来袭的小行星射击。在下面的幻灯片中,SNN 在左边,游戏在右边。神经元在左侧排列成一个圆圈,因为这是游戏中传感器在船周围的排列方式。SNN 接收来自这些传感器的输入,当小行星靠*时,这些传感器就会触发——来自传感器的每个输入都是一个尖峰信号。然后,它必须决定何时转向、前进或开火,这些都是基于时间的输出。

来源:Catherine Schuman (2020)尖峰神经网络:在神经网络和神经科学之间架起桥梁,在 2020 年格蕾丝·赫柏庆典上的演讲

  • 自主机器人导航。下面的幻灯片显示了模型在模拟中接受训练,然后以小型机器人的形式在真实环境中释放。机器人接受关于其环境的实时激光雷达输入(这告诉它障碍物有多远),它的目标是尽可能多地探索环境,同时避免障碍物并记住它去过的地方。

来源:Catherine Schuman (2020)尖峰神经网络:在神经网络和神经科学之间架起桥梁,在 2020 年格蕾丝·赫柏庆典上的演讲

  • 计算网络中点与点之间的最短路径。在该应用中,图形网络(传统上用于路由算法)被转换为 SNNS,空间中的点被转换为神经元,距离被转换为与特定突触相关联的延迟。对我来说,这是一个特别令人兴奋的应用,因为它使用基于时间的 SNN 来模拟空间——结合了我的两个兴趣。
  • 流行病传播模型。在这里,神经元是群体中的个体,突触是共享的社会联系,尖峰是感染的传播,参数允许对不同的条件进行建模。由于显而易见的原因,这是目前特别有前途的研究途径。

我将在其他帖子中写一些我参加的其他有趣的技术讲座,但 Catherine Schuman 关于 SNNs 的讲座尤其引人注目,是一个令人着迷的话题,我渴望与其他未能参加会议的数据科学家分享。我希望你和我一样对此感兴趣!

学*机器学*背后的高等数学

原文:https://towardsdatascience.com/learning-advanced-mathematics-behind-machine-learning-7582e0b3be1a?source=collection_archive---------16-----------------------

学*机器学*高等数学的全面资源列表

照片由思想目录Unsplash 上拍摄

数学构成了大多数机器学*算法的基础。所以,掌握好数学对理解机器学*是势在必行的。而大多数数据科学家都知道线性代数、统计学等基本数学概念。但他们中的许多人并没有意识到一些深层的数学概念,这些概念可以帮助他们更清楚地了解一种算法是如何工作的,或者让他们了解机器学*的最新研究。

在这篇文章中,我分享了高等数学课程的资源,这些资源有助于机器学*。本文讨论的主题是凸和非凸优化、信息论、概率图形模型等。

给出资源列表是为了假设读者熟悉基本概念,如线性代数、概率论、多变量微积分和多变量统计。理解这些基本主题对于理解本文中的高级课程中的内容是至关重要的。

我还写了另一篇关于这些主题的文章,可以作为这篇文章的前身。请随意查看!

[## 三个月计划学*机器学*背后的数学

为期 3 个月的计划,学*机器学*背后的数学知识

towardsdatascience.com](/three-month-plan-to-learn-mathematics-behind-machine-learning-74335a578740)

本文中的资源可用于攻读博士学位,学生需要对与研究主题相关的数学概念有透彻的理解。

该计划主要分为以下几个部分

  • 凸优化
  • 概率图形模型
  • 非凸优化
  • 信息论

这个列表是永无止境的,但我在这里讨论的以下四个主题在机器学*中是必不可少的,并且可以高度移植到其他工程领域。

充分利用资源:

  • 建议不要听课,即使你知道内容。这样的讲座可以用来修改概念。
  • 一边看讲座一边做手写笔记。它有助于更好地理解和记忆概念。
  • 练*书本或课程作业中的问题。如果有许多类似的问题,每种类型做 1-2 个问题。
  • 在本书的每个讲座/章节之后,尝试推导所讨论的定理/证明,并相应地修改。

凸优化:

http://Thein F2 . informatik . uni-jena . de/Lectures/Convex+optimization . html

机器学*中的大多数方法都是基于寻找使一些目标函数(如二进制交叉熵、均方误差等)最小化的最佳参数。由于这一事实,大多数机器学*问题可以被视为优化问题。使用凸优化,一些机器学*算法使分析变得简单,并确保解的唯一性。凸优化应用于许多工程领域,并且是任何工程学位的基本课题之一。

学*该主题最经典的书是史蒂芬·博伊德博士和列文·范德伯格博士的凸优化书。世界各地的不同大学也提供非常棒的讲座。其中一些列举如下:

  • YouTube 上史蒂芬·博伊德博士的演讲
  • YouTube 上的 CMU 10–725 讲座
  • 【Joydeep Dutta 教授在 NPTEL 上的凸优化

概率图形模型:

https://www2.cs.arizona.edu/~pachecoj/courses.html

概率图形模型提供了一种数学方法来编码图形中随机变量之间的概率关系。通常,图中的节点是变量,边编码了它们之间的概率独立性或依赖性。在大多数现代机器学*研究中,许多机器学*模型是用图形模型定义的。该方法用于描述模型下的概率推理的结构。它也用于其他领域,如生物,金融等。

达芙妮·柯勒和 Nir Friedman 的概率图形模型是学* PGM 的标准书籍。除了这本书,还有一些关于 PGMs 的漂亮课程,列举如下:

  • Tom Mitchell 博士和 Lella Wehbe 博士的讲座。这是一门博士水平的课程。
  • 概率图形模型专业化Coursera斯坦福达弗·柯勒博士提供。

非凸优化:

https://commons . wikimedia . org/wiki/File:rastri gin _ function . png

与凸优化相比,非凸优化是一个相对较新的领域,在神经网络等算法中非常重要。使用凸优化技术来解决非凸问题会导致局部最优而不是全局最优,这是深度学*模型中最大的问题之一。非凸问题有许多可行且非常平坦的区域,曲率变化很大,每个区域有几个鞍点。

很少有足够的资源可用于非凸优化,因为它不是一个既定的领域,仍然是一个活跃的研究领域。最好的阅读资源是【Prateek Jain 博士和 Purushottam Kar 博士的《机器学*的非凸优化》。没有任何课程详细介绍非凸优化。最好的视频资源是在 NIPS 2015 非凸优化研讨会上的演讲。

信息论:

istock.com

信息论与机器学*有着牢固的关系。许多机器学*算法中使用的交叉熵损失是信息论的直接应用。决策树也使用信息论的概念,如熵、互信息等。拆分树形数据结构中的节点。信息论还用于数据压缩、信号处理、信息检索、数据挖掘等。

学*信息论的经典书籍是 David MacKay 的《信息论、推理和学*算法》。除了这本书,作者在剑桥大学还有一门名为“信息论、模式识别和神经网络的课程,和讲座可在 YouTube 上获得。

下一步做什么?

完成上面提到的课程后,可以尝试学*更多与机器学*相关的数学课程。比如测度论、张量代数、数学建模等。都是这样的其他话题。

除了课程之外,你现在可以选择在顶级会议上发表的任何理论机器学*论文,如 NIPS、ICML、ICLR 等。阅读并尝试复制论文的结果。从这个计划中学到的东西也可以用来在任何公司开始你的研究,或者开始攻读博士学位。

学*和寻找检疫工作

原文:https://towardsdatascience.com/learning-and-looking-for-jobs-in-quarantine-c6502a5f5e1e?source=collection_archive---------65-----------------------

苹果 | 谷歌 | SPOTIFY | 其他

Rubén Harris 在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:

冠状病毒隔离从根本上改变了学*和求职的动力。就在几个月前,面对面的训练营和大学项目,人们握手和交换名片的现场网络活动是这个世界的工作方式,但现在,不再是了。考虑到这一点,许多有抱负的技术人员都在问自己,考虑到当前疫情和即将到来的经济衰退的限制,他们应该如何调整自己的游戏计划,以跟上学*或获得下一份工作。

这就是为什么我想和 Rubén Harris 谈谈,他是 Career Karma 的首席执行官和联合创始人,Career Karma 是一家帮助有抱负的开发人员找到最适合他们的编码训练营的初创公司。他有一个很好的视角来分享导航自学和找工作的特殊心理和实践挑战,他很友好地抽出时间与我聊天,这是迈向数据科学播客的最新一集。

以下是我最喜欢的一些外卖食品:

  • 既然面试是通过视频聊天进行的,求职者就有了一个独特的机会,他们可以在练*回答问题的过程中对自己的面试表现进行自我评估。Rubén 还建议准备一些笔记,你可以在谈话中参考,以帮助你更顺利地表达,并让你保持在正轨上。[注意:请记住,正如我的兄弟 Ed 最*在 tweet上说的,Zoom 有一个设置,允许会议主持人看到你屏幕上的内容,所以你可能并不总是能够逃脱这个问题]。
  • 保持学*的动力是一项你可以努力学*和发展的技能,尤其重要的是,现在你不能依赖老师或助教亲自带你去上课或训练营。做到这一点的一个很好的方法是利用原子*惯策略:找到带你去你想去的方向的最小的行动(无论多么可笑的小),并从那里开始。例如,如果你想养成锻炼*惯,先穿上你的运动短裤,然后称之为胜利——如果之后你做了一些俯卧撑,那就太棒了。一旦你养成了“穿上我的短裤”的*惯,把下一个目标定为做一个俯卧撑,并从那里开始培养你的*惯。
  • 另一个伟大的激励策略是公开承诺你的目标。像 Twitter 这样的社交媒体平台可以很好地做到这一点,同时帮助你与面临类似挑战的志同道合的人联系。

你可以在这里的 Twitter 上关注鲁本,在这里找到职业因果的网站

你可以在推特上关注我

订阅《走向数据科学》的 月刊 直接在你的邮箱✨里接收我们最好的文章、视频和播客

学*协会

原文:https://towardsdatascience.com/learning-associations-74a8c27cf142?source=collection_archive---------25-----------------------

购物篮分析和关联规则

关联规则

想象一下,一个在线电子商务网站在数字营销方面尽其所能。利用有机的、付费的、社交的和其他营销技术来吸引消费者访问他们的网站,提供合适的吸引人的内容来通知消费者,并通过他们的产品详情页面和无缝结账流程进一步将他们转化为销售。这个电商团队还有什么可以做的吗?如果会怎样;即使转换率很高,但营销努力和预算大于通过他们的网站销售;他们应该减少他们的数字营销努力吗?如果他们的交谈率下降了呢?

我记得大约十年前,我们会在结账后将额外的产品信息添加到解决页面,这样用户就可以进行额外的购买。我们的营销团队会根据他们的领域专长选择这些交叉销售产品。他们非常仔细,在选择这些产品上花费了大量的时间和精力,因为如果他们不包括这些额外的产品,他们就会失去很多销售机会。

在本文中,我们将查看我们为客户细分分析的相同数据集,但是这次我们将在购买的产品之间创建一个关联规则。关联规则是 X 到 Y 形式的蕴涵,其中 X 是前提规则,Y 是结果规则。关联规则最常见的用途之一是市场篮分析。简单地说,我们希望找到两个项目之间的依赖关系。如果购买商品 X 的人通常也会购买 Y,如果有一个消费者购买了 X,但没有购买 Y,那么这个消费者就是一个潜在客户。

数据收集和清理

正如我前面提到的,我们使用的数据集与我们在上一篇关于客户细分的文章中探索的数据集相同。然而,这一次,我们将关注交易(“InvoiceNo”)和项目(“StockCode”、“Description”),而不是关注客户。

我们在“Description”和“CusomterID”变量上缺少一些值。在这种情况下,我们有两个选择,我们可以简单地删除丢失的值观察值,或者将它们作为我们分析的一部分。因为我们在看项目,描述对我们来说是一个重要的变量,然而,在总共 541909 个观察值中,1454 个并不重要。我们可以保持丢失的值不变。我们也有一些退货(信用),我们删除了这些项目,因为消费者没有完全购买。为了查看购买行为,我们还添加了 InvoiceDay 和 Hour 变量。

数据探索

当我们查看关联规则时,我们主要感兴趣的是了解如果有人购买 X,同一个人购买 Y 的概率是多少。这只是一个条件概率,其中 Y 是我们希望以 X 为条件的产品。在不进入太多关于抛硬币的示例的情况下,我们应该考虑查看客户购买行为。

消费者购买行为

顾客购买行为

购买的前十件商品

十大交易

查看我们的数据,我们可以看到,消费者在一天中的下午 12 点、1 点和 2 点、6 日、7 日、8 日和 17 日进行了最多的购买,并且主要购买了“第二次世界大战滑梯 Asstd 设计”、“巨型袋红色 Retrospot”和“爆米花架”。最大的购买来自发票 541431 和 581483 交易。

建模的数据准备

为了将关联规则应用到我们的数据集,我们需要将数据的当前状态转换为更具事务性的基本数据集。我们关注的是每笔交易中购买的商品。这就是“篮子”这个术语的由来。我们需要关注数据集内的独特产品,并查看购物篮中的商品集合。

当我们转换数据时,我们简单地定义了标识产品的列和标识交易的发票号的行。

随着为消费者在产品中建立关联规则,我们正在寻找集合、子集和超集。集合中有独特的项目,通过购物篮分析,我们可以看到项目集合中较小的集合。例如,我们的数据集中的项目是 X={ "面包"、"黄油"、"奶酪"、"葡萄酒" },X 项目集的子集是 Size 0: {},Size 1:{ "面包" },{ "葡萄酒" },… Size 2: { "面包"、"葡萄酒" }…{"Bread"}的超集是{"Bread "," Butter"}。我们来看看每笔交易的购买情况。

模型开发

在构建关联规则时,我们会考虑使用三个主要参数或衡量标准。

  • 支持关联规则。x 到 Y
  • 关联规则的可信度。x 到 Y
  • Lift,也称为关联规则的兴趣。x 到 Y

Support 简单的表示一个项集的流行度。在数据集中购买的项目集越多,该项目集就越受欢迎。它的计算方法是将项集(例如 X 和 Y)中的项所购买的事务数除以事务总数。

置信度简单地表示关联规则为真的频率。它的计算方法是,购买项集(例如 X 和 Y)中的项的事务数除以包含项集中某项(例如 X)的事务数。简单来说,就是显示 Y 和 x 一起买的百分比。

Lift 简单地表明规则内的关联有多强。它的计算方法是在给定另一个项目(X)的条件下,用一个项目(Y)的概率除以另一个项目(Y)的概率。如果 Lift > 1,Y 很可能用 x 买,如果 Lift < 1,Y 不太可能用 x 买。

置信度是条件概率。为了能够以足够的信心声明规则成立,信心值应该接* 1,并且显著大于购买 y 的概率。我们还希望最大化规则的支持,因为即使这样的客户数量很少,规则也是无价的。

有一种众所周知的高效算法叫做 Apriori ,它可以在大型数据库中找到所有具有高支持度和置信度的规则,只需对数据集进行少量遍历。该算法分两步发现关联规则。

  • 找到有足够支持度的频繁项目。
  • 用足够的信心将它们转化为愤怒。

Apriori 算法的思想很简单。如果一个项目集是频繁的,那么它的所有子集也一定是频繁的。对于一个非频繁项集,它的所有超集都是非频繁的。

例如,在我们的电子商务数据集中,如果一个消费者购买了像 GREEN kind 一样的闹钟烘焙,我们有 65 %的信心他们也会购买闹钟烘焙 LINE RED。作为我们算法中的一个参数,我们将最小支持阈值设置为 5%。当生成规则时,Apriori 从具有单个先例的高可信度规则开始(如我们的“规则”关联规则数据框架所示),并继续构建更复杂的规则,结果是更多的项目。

模型评估

我们已经使用 Apriori 算法创建了用于购物篮分析的模型。我们可以改变和改进某些参数,例如创建关联规则的最小阈值或创建频繁项目的最小支持度。我们还可以定义最小升力和长度。但是,对于我们创建的模型,我们还应该详细查看关联规则。我们可以看的第一个方面是多余的规则。如果存在具有相同或更高置信度的更一般的规则,我们可以消除规则以避免冗余。

让我们详细看看我们的篮子中的频繁项和关联规则。

最常出现的项目集

最常出现的项目集

结论

在购物篮分析和在消费者购买的商品中创建关联规则时,我们不是看消费者购买了多少,而是关注他们购买了什么。在我们的在线零售商数据集中,我们能够找到前因和后果的关联规则,例如:如果消费者购买了粉红色的丽晶茶杯和茶托,我们有 82%的信心他们也会购买绿色的丽晶茶杯和茶托。我们还回顾了最受欢迎的(经常购买的商品)、关联规则、每个关联规则的使用频率,最后,如果消费者购买了商品 Y,则可能会或不可能购买商品 x。

关联规则在机器学*应用中有许多用途。我们回顾了一个关于如何对在线零售商数据集执行 Apriori 算法的示例,以便找出消费者购买的产品之间的关联,这对交叉销售营销方法非常有用。如果这不是一个在线零售商,而是一个书商,方法将是相同的。我们可以对 web 门户应用相同的关联规则方法。在这种情况下,项目将对应于网页中的链接,我们可以预测(估计)用户可能点击的链接。

通过竞赛学*数据科学

原文:https://towardsdatascience.com/learning-data-science-through-competitions-dde82b15984d?source=collection_archive---------48-----------------------

将竞争数据科学作为学*途径的利弊是什么

学*数据科学和机器学*最好的方法是什么?这是我经常从朋友和社交媒体上收到的一个典型问题。我的简短回答是:参加一些数据科学竞赛。但是为了提供更多的细节,在本文中,我将介绍使用竞争数据科学获取知识和经验的所有主要方面。

作者照片

有许多平台和网站提供数据科学和机器学*竞赛,任何人都可以参加并尝试解决给定的任务,与他人竞争一些奖项。目前,最广为人知的此类竞赛平台是 Kaggle ,但还有更多。

在我讲述参加比赛的主要利弊之前,我将首先从一些关于我自己经历的简短背景开始…

大约 5 年前,数据科学和机器学*开始吸引我的注意力。我想学*一些新的东西,这是当时最大的宣传和最有前途的技术。所以我开始四处寻找我想走的学*道路。首先,我参加了一些关于机器学*的初级在线课程。这有助于获得一些基本知识和学*相关术语。但这与“真正的”数据科学任务相去甚远,在完成这门课程后,我真的不觉得我可以去告诉每个人我现在是一名数据科学专家。所以我在找别的东西。这个“其他”结果是数据科学竞赛,这与我所寻找的非常匹配。

这就是为什么…

1.真正的任务

竞赛提供了真实的(或接*真实的)问题来解决。至少如果我们谈论有突出奖金池的严肃比赛。事实上,有人愿意支付真金白银(作为奖金池)来解决这些任务,意味着他们背后隐藏着一些研究或商业价值。当然,这并不一定意味着信用风险评分竞赛获胜者的模型将从现在起直接投入生产,用于评估风险。很可能只有一些想法、方法、特性或工具会从成功的解决方案中提取出来。

但不管是哪种情况,知道问题接*真实意味着如果我们将学会解决这些任务,我们也将能够解决外面的“真实”问题。知道这一点很重要,我们将能够在竞赛平台之外使用获得的知识和技能。

2.社区

如果我唯一想要的只是一个真正需要解决的问题,我可以获取一些真正公开的数据(比如维基百科的使用历史)并尝试预测未来的使用情况。这将是一个真正需要解决的问题,正如我所希望的那样。但是……用这种方式获取知识不太可能成功。和开始时一样,我们需要一些帮助、指导和“好”的例子来学*。现在光是这个问题就够了。

竞争平台上的社区非常适合这一目的。有成百上千甚至成千上万的人在研究同一个问题,所以你并不孤单。这些人正在分享一些想法,对问题的见解,一些基本的入门模型,代码。如果你是初学者,很容易把它们作为起点。它们也不是“太好”,这意味着仍然有足够的空间让你自己进行实验和努力来改进这些解决方案。

这一点很重要,因为我们通过自己动手来学*,而不仅仅是看和听。

3.即时客观反馈

在线课程或学*真实问题的另一个问题是缺乏反馈。当然课程上有作业和考试,但是通过一门考试就代表你现在擅长数据科学了吗?如果其他 10000 人通过了同样的考试,这是否意味着他们都有同样的技能?当然不是。

这也是竞赛有独特之处的地方:排行榜。当您针对给定的问题提出解决方案并提交后,您将立即获得客观的反馈,并获得分数和排名。利用您在排行榜上的位置,您可以将您的模型性能与其他竞争对手根据“真实”未知测试数据开发的其他模型进行比较。我相信这种反馈会比在线课程后的某次考试的“及格”分数更客观、更有价值。如果你的模型不好,你会发现自己在排行榜的最底部。现在,在学*和改进模型的同时,你可以看到自己的进步和向董事会顶端的移动。

这一点很重要,因为反馈会告诉你对于给定类型的数据,什么有效,什么无效。这会让你感受到(你可以称之为体验)不同类型的方法和技术,你将来会用到它们。

4.最先进的算法和工具

一旦竞赛结束,获胜的团队通常会分享他们的方法、模型,有时甚至是他们解决方案的完整源代码。
这会给你带来很好的“证明”,通过赢得资源来学*什么是真正有效的。我说的“证明”是什么意思?对于一些“专家”来说,很容易写一篇关于某种算法、技术或工具的文章甚至一本书,声明这是最好的或最有效的,等等。我们可以找到很多关于这种“最佳”算法和工具的描述。但遗憾的是,这些工具和算法中的一部分远非完美,甚至称不上是最好的。那么我们能相信谁呢?

在我看来,赢得竞争是一个很好的论点,使用的方法值得探索和学*。这一点很重要,因为我们不可能学到所有的东西,所以专注于真正有效和进步的东西是明智的。

5.联系人,认可

通过参加竞赛(即使没赢)、讨论和社区,你会获得一些声誉。一旦你证明了自己是一个优秀的竞争者或者仅仅是一个聪明人,人们会认可你,会开始跟随你并听取你的意见。他们会开始征求你的意见,甚至会提供一些工作或研究机会。

凭借 10 多年的 IT 经验,我经常收到工作邀请。但我从未像在 Kaggle 上赢得我的第一次数据科学竞赛后那样收到过这么多邀请。

这类似于我之前提到的赢得一场比赛作为算法或工具的“证明”——这是一个让人们。每个人都可以声明自己是机器学*方面的专家。而且几乎每个人都能完成一门关于机器学*的在线课程。但是到目前为止,并不是每个人都擅长机器学*。然而,赢得一场比赛是一个很好的理由,让我们相信这个人真的知道一些事情,并且能够把他/她的知识用在真正的任务上(或者至少是非常幸运的)。

获得人脉和声誉是一件好事,因为你永远不知道,通过这种方式,你会有什么改变人生的机会。

6.奖赏

不是每个人都会获奖。这是自然的,因为可能有几千个竞争者,但奖品非常少(通常只有 3 到 5 个,有时甚至只有一个)。所以奖项不应该是参加数据科学竞赛的主要原因。另一方面,随着你在数据科学和竞争方面越来越好,你获得一些奖项的机会将显著增加。

顶级竞争者每年可以从竞赛奖金中获得数千欧元——除了获得知识之外,还能因为做了自己喜欢的事情而获得一些东西,这真是一笔不错的奖金。当然,一名优秀的数据科学家可以通过与提供数据科学任务自由职业机会的公司签订一些合同或做一些其他事情来赚取更多。但是合同意味着承诺和严格的期限。另一方面,竞争是你的自由意志——你可以在喜欢的时候去做,并从中受益,如果你发现有更好或更有价值的事情去做,你可以随时停止。

7.竞争力和乐趣

最后,但同样重要的是,这很有趣!在真正需要的时候,竞争的感觉可以给你额外的动力。

有多少人注册了免费在线课程?又有几个会听完整个课程到最后?根据我的经验,这些数字会有很大的不同。这是因为在开始时,人们有巨大的动力和充沛的精力——他们可以每天花很多时间阅读、学*和实验。但随着时间的推移,热情也在萎缩。完成一项任务并坚持学*需要非常坚强的意志,需要几周甚至几个月的努力。

然而,有了比赛,事情就简单多了。开始时,你会处于最底层。利用你巨大的起点热情,你可以在排行榜上获得很高的名次。然后你只需要一点点就能爬得更高。当你到达那里时,又会有一个人稍微领先一点,所以你会继续追上他。诸如此类。随着你越来越接*顶峰,你会得到更多的动力,因为顶峰就在眼前。额外的动力和竞赛的乐趣有助于不到终点不放弃,并能学到更多。

裘德·贝克在 Unsplash 上的照片

到目前为止,我只谈论了关于竞争数据科学的积极方面。有负面的东西吗?是的,有些担心。虽然不太多,但仍然值得一提。

1.数据质量

可能会出现竞赛组织者未能为竞赛准备好适当数据的情况。这会对你从这些数据中学*的可能性产生负面影响。为了在这样的比赛中表现出色,你必须找到数据泄漏或其他数据准备问题,而不是试图解决一个数据科学预测问题。当然,在数据中发现问题也会教会你一些东西。但总的来说,这样的问题会损害你对给定比赛的学*体验。

幸运的是,我参加过的大多数比赛都是定性准备的,但仍然需要注意潜在的数据问题。

2.有限的知识范围

竞争数据科学可以让我们学到很多东西。对于图像数据、表格数据、自然语言处理任务、时间序列数据以及许多其他数据,存在不同种类的竞争。竞赛涵盖了机器学*的许多方面,包括数据准备、特征工程、交叉验证、模型选择、超参数调整、后处理和堆叠。

但是仍然有一些现实生活中的任务没有被典型的竞赛所涵盖。例如收集数据、选择优化指标、在生产中部署模型。因此,竞赛不会教会你关于数据科学和机器学*的所有知识,你必须找到学*超出范围的东西的方法。

3.花费的时间

时间是我们人类拥有的最宝贵的资源之一。我们必须仔细选择如何花费它。我们的家庭、孩子、工作、兴趣爱好等等——一切都需要时间。几乎所有的时间都不够,所以我们需要做出一些妥协。

而认真争夺前几名需要大量的时间!尤其是在开始的时候,因为有太多的东西需要学*——理论、机器学*算法、术语、编程语言、库、工具和许多其他东西。当然,所有这些东西都将在其他比赛中,在现实生活的数据科学任务中进一步发挥作用,这样花在学*它们上的时间就不会浪费。但肯定的是,有些东西必须被牺牲掉——要么是睡觉的时间,要么是看电视的时间,或者是其他事情。

在我看来,在比赛中投入时间并不是最糟糕的事情,因为从中获得的收益和回报将是巨大的。然而,注意不要超过所有的限制,花一整天的时间去竞争。竞争数据科学可能非常令人上瘾——决定你将在那里花费多少时间,并遵循你的极限!

就是这样。我已经分享了我对竞争数据科学作为一种学*途径的所有正面和负面印象。希望你已经获得了一些有用的见解,现在可以决定你是否想尝试参加一些比赛,如果以前还没有这样做的话。

感谢阅读!

用于鉴别定位的深度特征学*

原文:https://towardsdatascience.com/learning-deep-features-for-discriminative-localization-class-activation-mapping-2a653572be7f?source=collection_archive---------35-----------------------

可解释人工智能的全局平均池和类激活映射

类激活映射1

今天,我将重温 CVPR 2016 年的论文“学*歧视性本地化的深层特征”。该论文由麻省理工学院研究人员周等人1撰写,在可解释人工智能和弱监督检测/定位方面做出了有价值的贡献。其贡献可归纳如下:

  1. 全球平均池使康文网络保持其本地化能力
  2. 引入弱监督、端到端、单路目标定位的类激活映射技术
  3. 在 ILSVRC 2014 上获得 37.1%的前 5 名本地化误差,接*完全监督的 AlexNet 的 34.2%

本白皮书基于之前对 ConvNets 本地化功能的研究,以及全球平均池(GAP)的优势。广泛应用于计算机视觉中的 ConvNets 具有固有的金字塔结构和固有的平移不变性,允许它们通过以分层的方式从空间特征图中提取语义代表性增加的特征。虽然之前的研究2表明,ConvNets 的卷积单元在没有监督的情况下学*位置信息,但当全连接(FC)层(其中神经元密集地连接到前一层的激活值)用于分类时,这种能力就丧失了。在这项工作中,周等人提出了全局平均池作为一种机制来保持 ConvNets 的本地化能力,直到最后一层。

全球平均统筹(缺口)

尽管 GAP 并不是一项新技术——已经作为防止过度拟合的规则进行了研究,但直到这项工作,其潜力才被充分认识到。作者在 GAP 和【3】的全局最大池(GMP)之间进行了显著的比较,目的是弱监督的对象定位。使用 GMP,【3】仅限于定位对象的边界,而 GAP 则使周等人能够识别整个对象的位置(类似于一个遮罩)。这是由这样的认识提供的,即平均池激励对所有区别区域(有助于成功识别对象的特征)的识别,而最大池仅仅激励对图像的最大区别区域的识别。

类激活图(CAM)

CAMs 可以被描述为最后卷积特征映射的点积和 FC 层的类权重(在 GAP 之后应用)的总和。这被正式描述为:

因此,作者将 cam 描述为“在不同空间位置存在的(这些)视觉模式的加权总和”。根据最后一个卷积特征图的分辨率,对 CAM 进行上采样,以显示输入图像中的区别区域,并通过 softmax/sigmoid 输出函数,以生成图像级分类标签。

实验

周等人在 8 个分类数据集上评估了 3 个 ConvNet 基线上的 cam,即 AlexNet、VGGNet 和 GoogLeNet,以及用于弱监督包围盒定位的 ILSVRC 2014 和 CUB-200–2011 数据集。对分类数据集的实验产生了两个主要见解:

  • 首先,这种差距不会严重影响基线模型的分类性能(除了 vanilla AlexNet,他们通过添加 Conv 层进行了调整),同时保留了本地化信息。
  • 第二,在空间和语义特征之间存在折衷,其中移除 Conv 层(以获得更高的映射分辨率,即,最后的卷积特征图较少下采样)有益于定位,但是有害于分类。

这由表 1 中的前 5 和前 1 分类误差在去除 Conv 层之后的轻微增加所证明:

在 ILSVRC 的本地化数据集上进一步评估 CAM 基线。周等人使用在最大的对象特征集群(定义为 CAM 中值>为 CAM 中最大值的 20%的区域)上拟合边界框的阈值技术,生成边界框预测。表 2 和表 3 证明了 CAM 方法比以前的方法(包括【4】的反向传播和【5】的网络中的网络)以及 vanilla(在图像级标签上训练的)ConvNet 基线定位得更好。特别地,GoogLeNet-GAP(使用启发式)获得了接*完全监督(在边界框注释上训练)的 AlexNet 的结果,尽管已经在图像级分类标签上进行了训练。

对 CUB-200–2011 数据集的进一步评估用于细粒度识别和边界框定位。作者报告了 GoogLeNet-GAP 在 3 种设置下的结果,其中训练使用 1)具有图像级标签的弱监督方法,2)具有裁剪的逐代方法,3)具有边界框注释的完全监督方法。分类结果分别为 63.0%,67.8%,70.5%,超过了大多数以前的方法,表明由 GAP 识别的特征有助于分类性能,因此在定位任务之外是有用的。最后,使用边界框 0.5 交集/并集(IoU)标准的评估给出了 41.0%的准确度(相比之下,机会性能为 5.5%)。通过在 CUB-200–2011 数据集上的实验,周等人表明 GAP 方法识别深度的可定位特征,适用于两种分类&定位任务。

对 CUB-200–2011 数据集的评估1

应用

作者进一步探讨了 GAP 方法的模式识别和可视化能力。通过 SUN【6】和 SVT【7】数据集,作者展示了由 GoogLeNet-GAP 生成的特征具有从图像中发现、定位和在某种程度上解释高级概念的潜力,尽管缺乏明确的监督。此外,cam 能够根据查询的感兴趣类别(称为特定类别单元)突出显示不同的区分区域。通过对视觉问答的初步实验,周等人证明了 CAMs 中可能存在的高层次理解能力。

VQA 的凸轮1

结论

“学*区分性定位的深度特征”介绍了一种在分类和定位中都有用的弱监督方法,并在基准数据集上进行严格的实验以验证其结果。通过对全局平均池函数的新颖见解,以及类激活图的开发,这项工作极大地推进了对 ConvNets 内部工作方式的理解。

SUN397、MIT Indoor67、Scene15、SUN Attribute、Caltech101、Caltech256、斯坦福 Action40、UIUC Event8

参考文献

1 B .周、a .科斯拉、a .拉皮德里扎、a .奥利瓦和 a .托拉尔巴。学*深度特征进行鉴别定位。2016 年 CVPR。[2] B .周、V. Jagadeesh 和 R. Piramuthu。 Conceptlearner:从弱标记图像集合中发现视觉概念。2015 年,CVPR。
3奥夸布、博图、拉普捷夫和西维奇。对象本地化是免费的吗?卷积神经网络的弱监督学*。2015 年,CVPR。
4 K. Simonyan、A. Vedaldi 和 A. Zisserman。深层卷积网络:可视化图像分类模型和显著图。2014 年 ICLR 研讨会。
[5]m . Lin、Q. Chen 和 S. Yan。网络中的网络。2014 年 ICLR。
[6]肖、海斯、埃林格、奥利瓦和托雷巴。孙数据库:从修道院到动物园的大规模场景识别。2010 年,CVPR。
[7]k .王、b .巴本科和 s .贝隆吉。端到端的场景文本识别。2011 年,ICCV。

从音频中学*:傅立叶变换

原文:https://towardsdatascience.com/learning-from-audio-fourier-transformations-f000124675ee?source=collection_archive---------22-----------------------

打破信号处理中的一个基本方程

相关文章:

简介:

在 Wave Forms 中,我们看了什么是 Wave,如何将它们可视化,以及如何处理空数据。

在这篇文章中,我的目标是发展一种直觉,什么是傅立叶变换,为什么它在研究音频时是有用的,展示数学证明,使其计算效率高,并可视化结果。我们在这篇(和相关)文章中使用的数据可以在我的本系列 GitHub 存储库中找到。

考虑到这一点,我们开始吧。我们将首先初始化下面的必要变量和包:

从波形中回忆:

1 —作者图片

傅立叶变换:

什么是傅立叶变换?为什么重要?

看上面的图,我们可以看到不同的振幅峰值为独特的声音创造了独特的模式。这是因为所有复杂的声音——就像我们的声音——实际上只是许多正弦和余弦信号的总和。下面的gif展示了该目标的美好愿景:

作者卢卡斯·v·巴博萨——自己的作品,公共领域

需要注意的是,通过使用这种变换,我们将把音频从时域转换到频域。以下是关于这两者的一些要点:

  • 时域着眼于信号幅度随时间的变化。这对理解它的物理形状很有用。为了绘制这个图,我们需要 x 轴上的时间和 y 轴上的振幅。这种形状让我们很好地了解了声音的大小。
  • 频域观察我们记录的组成信号。通过这样做,我们可以找到一种声音的“指纹”。为了绘制这个图,我们需要 x 轴上的频率和 y 轴上的幅度。震级越大,频率就越重要。幅度就是 FFT 结果的绝对值。

离散傅立叶变换

numpy构建的 DFT 如下:

来自加州大学圣巴巴拉分校的德里克·l·史密斯的方程。

学*傅立叶变换时,您可能会看到一个连续版本,即利用积分而不是求和,称为连续傅立叶变换。这种变换的离散形式通常用于计算机的运算。事实上,即使是离散形式,大多数计算机仍然缺乏适当的计算能力来求解下面的原始方程。DFT 有一些很好的特性,便于计算,称为快速傅立叶变换。

快速傅立叶变换

FFT 如下所示:

来自加州大学圣巴巴拉分校的 Derek L. Smith 的方程。

不要让符号困扰你。在离散傅里叶变换中,你处理的是 x 和ω乘积的和。该等式将乘积之和一分为二,一个沿着奇数指数,另一个沿着偶数指数。相对于 DFT,上述过程可以用计算机过程更有效地建模。

现在,让我们想象一下 FFT 是什么样子的。在我们的应用程序中,我们将使用numpy.fft.fft函数,并将其应用于我们的声波。

2 —作者提供的图片

同样,可视化也有一些小问题。然而,这是一个非常简单的解决方法,因为 DFT 具有对称特性。这是有意义的,因为我们在左半部分的可视化模拟了右半部分的可视化。我们将把数组切成两半,从那里开始可视化。

图 3 —作者图片

结论:

在本文中,您现在应该能够提取任何类型的任何复杂信号的傅立叶变换,并找到其独特的指纹。

敬请关注即将发表的文章,因为它们将着眼于更深入的处理和可视化技术,让我们能够从音频中了解更多。

感谢您的阅读。

从音频中学*:波形

原文:https://towardsdatascience.com/learning-from-audio-wave-forms-46fc6f87e016?source=collection_archive---------22-----------------------

波形介绍和零数据处理。

乔纳森·贝拉斯克斯在 Unsplash 上的照片

相关文章:

简介:

答 udio 是一个极其丰富的数据源。根据sample rate每秒采样的点数来量化信号 —一秒钟的数据可能包含数千个点。将这扩展到数小时的录音,你可以看到机器学*和数据科学如何与信号处理技术完美地交织在一起。

这篇文章旨在分析到底什么是波形,并利用 Python 中的librosa进行分析和可视化——与numpymatplotlib一起。

波形:

Waves是重复的signals,根据它们的复杂程度,在振幅上振荡和变化。在现实世界中,waves是连续的、机械的——这与离散的、数字化的计算机截然不同。

那么,我们如何将连续的、机械的东西转化为离散的、数字化的东西呢?

这就是前面定义的sample rate的用处。比如说,录制的音频的sample rate是 100。这意味着,对于每一秒记录的音频,计算机将沿着signal放置 100 个点,试图最好地“跟踪”连续曲线。一旦所有的点都就位,一条平滑的曲线将它们连接在一起,以便人类能够可视化声音。由于录制的音频是以amplitudetime为单位,我们可以直观地说波形是在time domain工作的。

为了更好地理解这种声音,我们来看看三种声音:底鼓、吉他和小鼓。本文的代码和数据可以在我的 GitHub 存储库中找到。

载入数据。

既然数据已经载入,让我们来想象这些声音。

1

从一开始,我们就看到了可视化的一些问题。

虽然我们可以很容易地分辨出可视化之间的一些差异,但这并不像我们希望的那样明显。我们还知道,音频信号不会突然消失,事实上它们会逐渐消失,直到无法感知。这意味着就音频而言,这构成了null数据。

音频中的空数据:

有许多方法可以处理time domain中的null音频数据。然而,这种方法通常是最简单的。

给定signalsignalamplitude的最小值threshold:

  • 取信号中各点的absolute value
  • 如果点数大于threshold,我们保留它。否则,我们删除它。

2

您可以将thresholds视为记录的一种参数。不同的thresholds对不同的声音有不同的作用。摆弄一下threshold是了解如何为什么这种视觉变化的好方法。

既然数据已经从这些录音中移除,那么就更容易看出每个声音中的个性。吉他的形状更加统一,随着时间的推移逐渐消失。底鼓在开始时用力击打,然后很快淹没,留下一些残余的声音。小军鼓是响亮而沙哑的,你不会想重复听。

结论:

这就结束了用librosa在 Python 中处理音频信号的基础。敬请关注更多深入探讨如何从音频中学*的更高级主题的文章!

感谢您的阅读。

注:所有未注明出处的数字均为作者。

从不平衡数据集中学*

原文:https://towardsdatascience.com/learning-from-imbalanced-datasets-b601a1f1e154?source=collection_archive---------29-----------------------

不平衡类是机器学*分类中的一个常见问题,其中每个类中的观察值比例不成比例。在本文中,我们提供了处理不平衡数据集的指南。

艾德亚多·桑奇兹Unsplash 上拍照

数据科学家经常面临处理不平衡数据集的需求。事实上,不平衡类是机器学*分类中的一个常见问题,其中每个类中的观察值比例不成比例。

阶层失衡可以在许多领域找到,包括广告技术、医疗诊断、垃圾邮件过滤和欺诈检测。但大多数机器学*算法在每类样本数量大致相等的情况下工作得最好。这是因为大多数算法都是为了最大限度地提高精度和减少误差而设计的。

在本文中,我们提供了处理不平衡数据集的指南。但是在做我们推荐的任何事情之前,你应该首先确定你是否能收集更多的数据。获取更多的欠采样类总是最好的解决方案。

在你收集了尽可能多的数据之后,处理不平衡的数据集包括选择三件事:正确的度量标准,使用什么样的重采样方法,以及正确的建模框架一旦你预处理了你的数据。‍

选择正确的指标

准确性悖论是一个矛盾的发现,即在预测分析中进行分类时,准确性不是预测模型的一个好指标。这是因为一个简单的模型可能有很高的精确度,但是太粗糙而没有用。例如,如果女性对男性的发生率占主导地位,在 99%的病例中被发现,那么预测每个病例都是女性的准确率将为 99%。维基百科

仔细观察这种自相矛盾的行为会发现两种类型的错误分类:假阳性和假阴性。在一个涉及火灾警报的例子中,假阳性将包括在没有火灾时预测有火灾(预测阳性);假阴性是错误地预测没有火灾(预测阴性),而实际上有火灾。在准确性悖论的情况下,我们可以看到,我们所有的错误都是预测肯定的(意味着有火灾)而不是火灾,因为我们所做的所有预测都不是火灾。这给我们留下了和负面观察一样多的假阴性。

作者照片

为了更仔细地检查我们在假阳性和假阴性方面准确或不准确的地方,我们需要查看密切相关的指标精度和召回。为了全面评估一个模型的有效性,你必须同时检查精度召回。精确度和召回率是可选的性能指标:

  • 精度:实际上有多少比例的肯定识别是正确的?

  • 回忆:正确识别实际阳性的比例是多少?

图片来自维基百科

不幸的是,精确和回忆天生就是矛盾的。也就是说,提高精度通常会降低召回率,反之亦然。精确和召回的重要性取决于问题的商业逻辑。例如,在火灾警报的情况下,我们想要捕捉所有的火灾,即使代价是每隔一段时间触发一次假警报。这意味着回忆比精确更重要。

例如,在 YouTube 推荐中可以看到相反的情况。由于推荐一些你可能不喜欢的东西并没有真正的伤害,所以错误的否定很容易被忽视。与此同时,推荐你不知道并且可能喜欢的东西的好处超过了你仅仅跳过视频的风险。

为了全面了解您的预测的假阳性和假阴性图,我们建议在混淆矩阵的框架中查看您的模型的分数。

最后,如果你的目标是选择一个指标,而不是同时处理两个指标,你可能要考虑 F1 的分数。F1 分数是精确度和召回率的调和平均值,其中 F1 分数在 1 时达到其最佳值(完美的精确度和召回率),在 0 时最差。

重采样方法

数据科学家有多种重采样方法可供选择,每种方法都有各自的优缺点。在这里,我们将重点关注行业中使用的一些更流行的方法。由于不同的建模任务可能需要不同的重采样方法,我们建议您尝试几种方法,以探索哪种方法最适合您的特定问题。

  • 随机欠采样 在随机欠采样中,你从过表示类中选择随机观察值。这应该作为更复杂的建模工作的基线。请注意,随着代表过多和代表不足的标签之间的比率增加,这种方法可能会产生越来越大的偏差。偏差是由于如果不平衡太大,随机样本可能不会从特征空间的整个区域采样。举个例子,假设某个游戏 app 里的标签是购买者,我们有三十六万非购买者。除此之外,数据中的每一行都表示用户的年龄和性别。如果我们以 1:1 的比例进行抽样,我们可能不会对特定年龄以下的女性用户的负面标签进行抽样,或者由于样本量较小,我们的样本通常不代表被抽样的人群。这可能会导致某些特征在预测标注时显得比实际更有影响力。
  • 随机过采样 在随机过采样中,从代表性不足的类别中复制随机观察值。在随机欠采样的情况下,这种采样方法可以用作更复杂建模工作的基线。注意,在尝试过采样技术之前,你应该总是分成“测试”和“训练”组。分割数据之前的过采样可以允许在“测试”和“训练”集中出现完全相同的观察结果。此外,由于阳性标签被重复多次,因此在使用随机过采样时,模型过拟合训练数据是非常常见的。

作者照片

  • 聚类质心 在这种重采样方法中,将一些聚类算法应用于数据,将每个数据点分配给一个聚类,并按等于该聚类大小的比例按聚类执行欠采样。这旨在解决特征空间中的区域在随机下采样中可能不被表示的问题。如果回到用户年龄和性别的例子,聚类模型会根据特征空间确定数据中有 K 个聚类;一群可能是老年女性,另一群可能是年轻男性,等等。然后,将根据每个聚类在数据中的大小按比例进行采样,而不是统一从整个数据集中进行采样。因此,向下采样的数据必然会更准确地代表真实群体(我们从中采样的群体)。

SMOTE(合成少数民族过采样算法) 这种重采样方法沿着观察值和其最*的少数民族邻居之间的线生成新的少数民族类样本。这种方法的一个优点是,它允许您避免过拟合,过拟合是在随机过采样中添加少数实例的精确副本时发生的。这种方法有助于强调存在大比例阳性标记的区域,而不是过度拟合可能无法概括的单个阳性观察。

照片由 Rohit Walimbe 通过数据科学中心拍摄

选择正确的建模框架 每当你遇到机器学*问题时,尝试各种算法是一个很好的经验法则。当您处理不平衡的数据集时,这样做尤其有益。

决策树通常在不平衡数据上表现良好。他们通过学*“如果/否则”问题的层次结构来最小化数据中的熵。

某些模型允许您为损失函数分配权重,以便处理数据集由大小不等的类组成的类。在 scikit-learn 框架中,这通常被称为“class_weights ”,它通常包含一个字典,定义每个类应该受到多少惩罚。这个参数也存在于 XGBoost 框架中,它被称为“scale_pos_weight”

无论您选择什么样的建模框架,我们建议从阅读文档开始,并检查模型是否支持针对不平衡数据情况的某种损失函数惩罚。

结论

正如我们提到的,不平衡数据是一个常见的问题。不要让它吓倒你。虽然处理不平衡的数据的确具有挑战性,但是只要你按照我们在这里提供的指导方针仔细计划,这也是可行的。

你应该总是从小事做起。仔细阅读一种方法,确保你确切地知道在引擎盖下发生了什么。如果你发现一种方法给你带来了价值,你可以通过尝试同一系列的不同方法来进一步调整它。

另外,尊重基线。将你所做的一切与一个简单的基线进行比较,以确保你没有浪费时间,并且通过对你的数据实施这些方法,你实际上已经足够移动指针了。我们建议最简单和最强的基线是随机过采样和随机欠采样。

最后,使用外部库。正如数据科学中 99%的情况一样,你不是第一个遇到你所面临的问题的人!寻找能够解决你正在处理的问题的开源库。如果 python 是您数据科学的首选武器(应该是!),我们推荐不平衡学*(下面的链接)。

有用的资源

以下是一些资源,可进一步帮助您找到处理不平衡数据集的方法:

从多模态目标中学*

原文:https://towardsdatascience.com/learning-from-multimodal-target-5d3d2ea0d4c5?source=collection_archive---------15-----------------------

混合密度神经网络——使用张量流违反假设、实施、分析和应用。

来源:作者

介绍

出于统计和商业原因,为模型评估进行预测并测量其不确定性是非常重要的。基本上,对于监督模型,我们有预测值(x)和目标值(y ),我们尝试使用预测值预测目标值,并量化我们预测的效果。这通常通过最小化平方和或交叉熵误差函数来完成,在连续预测值或分类变量的后验概率的情况下,该函数输出每个预测值的*似平均值。

商业案例示例

让我们考虑一家销售手表的电子商务公司(ABC ),该公司有一个典型的亚马逊类型的业务模型,其中卖家列出要销售的产品,买家访问这些产品。当另一个卖家试图列出类似产品时,ABC 希望对产品列表价格进行建模,以提供建议价格。下面是一款数字式手表的标价分布。

数字型手表上市价格分布|来源:作者

从分布来看,一块数字手表可以卖到 20 美元到 2500 美元。有卖家在卖 3 种不同价位的手表。$20–$500, $700–$1500, $1600–$2500.这种类型的数据违反了线性回归的单峰正态假设之一。然而,在实际场景中,我们不知道基础分布,因为经验分布仍然是正态分布。

拟合模型和违反假设

如果我们用手表的类型作为唯一的预测器来拟合一个线性回归模型,那么通过对第一类手表的过度预测和对第三类手表的低预测,它将为数字类型手表预测 1133 美元。标准偏差是预测中的一个误差,将是 709 美元,使这个模型彻底失败。如果我们用这个预测的平均值(mu)和标准差(sigma)生成随机样本,它也会生成空白区域之间的价格。负价格也一样![注意:我们在拟合模型之前对价格进行对数变换,因为价格无论如何都不是正态分布的,但为了简单起见,我们假设它是正态分布的]。即使将神经网络拟合到这种类型的数据也是完全失败的模型,因为它仍然试图最小化平方误差函数的总和。不同类型的手表标准差不一样怎么办?让我们考虑下面的小提琴情节:

方差递增的双峰分布|来源:作者

每种类型都是双峰分布模型,在不同的水平上有不同的方差。不同类别的手表类型变化的差异。如果我们将神经网络或线性回归拟合到此数据,并且仅使用手表类型作为预测因素,那么误差的预测和标准偏差会发生什么变化?这个数据是否遵循了回归的所有假设?

正态分布方程|来源:维基百科

基本上,当我们最小化线性函数或平方和时,我们最小化给定 x 的线性函数μ的输出的平方误差项(μ( xθ-y)以及函数的参数(θ)。它是唯一一个依赖于 x 的μ,并丢弃了其余的参数(标准差),也称为同方差。

我们可以通过手表类型学*多模态分销参数吗?是,带 MDN

高斯混合模型和混合密度网络

我知道很多人对 GMM 很熟悉,但我还是想描述一下它和 MDN 的区别,因为它们非常相似。GMM 是一种期望最大化无监督学*算法,作为 K-means,除了学*假设分布的参数。K-means 在重叠聚类的情况下不起作用,而 GMM 可以通过学*底层分布的参数来执行重叠聚类分割。对于上面的例子,我们可以通过应用 GMM 来导出基本的三态分布的参数。理论上,GMM 通过优化由下式给出的给定概率分布来计算 n 个分量(聚类)以及相关的 mu、sigma 和聚类成员概率:

https://en.wikipedia.org/wiki/Mixture_model GMM 似然函数|来源:

其中 K 是聚类数,phi 是聚类潜在概率。使用 EM 算法,我们可以学*φ、μ和σ。

对于我们的 ABC 示例,我们用 1500 * 3[样本数*聚类数]φ计算 3 个μs和 3 个μs。为了便于理解,我在上述数据集上训练了 GMM,并验证了集群 mu 和 sigmas 是否接*真实 mu 和信号。

输出【https://github.com/dwipam/MDN/blob/master/gmm.py】|来源:作者

这为混合密度网络(MDN)奠定了基础。我们可以学*依赖于预测器的模型核参数。为此,我们将把我们的核限制为高斯核。MDN 优化了与 GMM 相同的似然函数,并为我们数据集中的每个样本输出 mu、sigma 和 phi

3 集群 MDN 架构|来源:作者

在不深入数学细节的情况下,让我们跳到训练模型。克里斯托弗·贝肖普已经解释得比我所能解释的还要好!

构建和培训 MDN

综合数据集平均分布在 2 个集群和 x 个相关参数(mu,sigma) |来源:作者

生成数据

我们将尝试生成具有以下 x 和 y 关系的数据

x_ = sin(0.5 * x) * 3.0+ x * 0.5)
f1(x) = N(x_, square(x_)/15) + N(0,1) # Cluster 1 y
f2(x) = N(f1(x) + 12, square(x)/100) + N(0,1) # Cluster 2 y
This equation generates data with 2 distinct cluster and x dependent variance.

试衣 MLP

一个完全连接的神经网络用平方和损失函数拟合数据,并从预测中产生随机样本。如前所述,预测值是平均值,标准偏差用以下公式计算

模型的标准差(适马)|来源:作者

其中误差为(y 模型预测)

正态随机样本由平均值和标准差生成。

MLP 估计|来源:作者

这是一个问题,模型通过对 50%的数据预测不足,而对剩余的 50%的数据预测过度,在空白区域内进行预测。因为 means 和 sigmas 是数据相关的,所以让我们尝试使用 MDN

构建 MDN

全连接 4 层神经网络

第一部分相当于某人会为任何其他问题创建一个神经网络。在这里,我们创建了 4 个隐藏层神经网络,每个分别具有(50,20,20,20)个节点。我使用的是 Tanh 激活,但这里任何其他激活都可以,因为我们正在尝试学*的函数是一个简单的函数,对任何其他激活函数都不会有问题。

定义管理部门、西格玛、phi

然后,我们为每个μ、σ和φ创建“k”大小向量。在我们的例子中,K 是 2

  • 我们的目标具有从-ve 到+ve 的值,因此我们不会使用激活函数来估计均值 (mu)。
  • 标准差 (sigma)不能为负,因此我们可以使用 softplus、elu、relu 或任何其他变量,只要它输出值> 0,并且不像 sigmoid 那样限制输出。
  • 在所有 k 上计算后验聚类分配概率 (Pi)。由于它们是互斥事件,我们使用 softmax 激活函数。

可以使用张量流概率内置函数来定义损失函数(TFP . distributions .mixture same family)。然而,如果你真的想计算损失,我们仍然可以用下面的公式。

MDN 负日志损失|来源:作者

无 tfp 的 Tensorflow MDN 损耗。mixture 同一个家庭

损失是使用上述相同的 GMM 似然方程计算的。首先,计算每个分量的μσ,并计算后验概率。然后乘以关联的分量φ并对所有后验概率求和得到似然。然后记录可能性,并对所有样本求和,得到对数可能性。那么平均损失就是负对数似然的平均值,它将进一步进入优化器。如果您想节省一个步骤,让 TensorFlow 来处理,我们可以使用 tensor flow-probability . distributions .mixture same family。张量流概率数据科学家、ML 研究人员和统计学家广泛用于概率建模。

带 tfp 的 Tensorflow MDN 损耗。mixture 同一个家庭

TFP . distributions 几何定义分类损失。由于我们局限于正态分布,我们可以用张量流概率来定义它。我们可以定义正态分布方程来代替!。MixtureSameFamily 会将 mus 和 sigma 的向量转换为混合分布的协方差矩阵。然后使用 log_prob 返回 log_likelihood,最后最小化负的 log-likelihood。

定义优化程序

人们可以使用任何优化器,但我决定你 RMSProp,因为它仍然比随机梯度下降优化器更好。

最后,我们训练我们的网络,从混合分布中生成随机样本,并查看预测平均值(mu)、标准差(sigma)和聚类概率(phi)。

MDN 估计平均值|来源:作者

在学*了包含 2 个组件的 MDN 之后,我们得到了我们所希望的。现在均值的估计不在空白区域,正确地估计了每 x 的双峰分布均值。

为了查看方差,我们可以生成随机样本,并确保这些样本属于各自的聚类。

来自 MDN 估计平均值和 sigmas 的随机样本|来源:作者

与 MLP 模型预测相比,我们可以看到两个不同的集群重叠的基本事实,从而准确估计 x 依赖的双模态分布参数。

估计聚类概率分布|来源:作者

聚类概率(phi)非常接* 50%(46%-54%是模型参数的方差,每次训练可能不同),因为我为每个 x 的每个聚类生成了相同数量的样本,即 P(cluster=1|x) = P(cluster=2|x)。如果不是这种情况,那么我们可以看到不同的集群分配概率的分布。

结论

通过我们之前的 ABC 示例,该公司可以拟合 MDN 并获得对价格分布的真实理解。如果我们不知道我们的目标是多模态分布,聚类概率(phi)可以很好地理解这一点。实际上,训练一个 MDN 是非常耗时和困难的,因为对分布的假设可能不成立。MDN 可以用来学*不同家族的混合分布,但是你的模型和你的假设一样正确!

通过这篇简单的博文,我展示了平方和函数的缺点,以及应用 MDN 测量参数估计的不确定性的优点,以及它们对业务问题的重要性。鉴于其简单的架构和易于实现(感谢 TF),我很想听听读者的想法!

培训笔记本:

[## dwipam/MDN

github.com](https://github.com/dwipam/MDN/blob/master/MDN_NOTEBOOK.ipynb)

参考文献:

MDN 论文-【https://github.com/dwipam/MDN/blob/master/MDN.pdf】T2TF mixture same Family-https://www . tensor flow . org/probability/API _ docs/python/TFP/distributions/mixture same FamilyShaked 的博客-https://engineering . taboo la . com/predicting-probability-distributions/
GMM-https://en.wikipedia.org/wiki/GMM

向巨人学*——你将从中受益的顶级工程博客

原文:https://towardsdatascience.com/learning-from-the-giants-top-engineering-blogs-you-must-follow-fa8a0dd63f18?source=collection_archive---------26-----------------------

学*技巧

在哪里可以读到关于世界上最大的软件系统的有见地的文章

照片由斯蒂芬Unsplash 上拍摄

学*是一个终生的过程。

M M 矿石从根本上说,纵向和横向扩展你的知识是保持个人或专业人士成长的最佳方式。

“对知识的投资总是会有最好的回报”——本杰明·富兰克林

对于开发者社区来说更是如此,在那里事情以疯狂的速度发展。实际上,对于 JavaScript 社区来说,事情可能进展得太快了。有人甚至称之为 JavaScript 疲劳。

在这种情况下,我认为我们应该专注于基础知识和软件设计而不是最新的工具和框架。

帮助我拓宽视野的一件事是阅读世界上最大的科技公司的故事和架构选择,了解他们如何应对最复杂的挑战和规模

我整理了一份工程博客的列表,在这里你可以了解到每一个博客都涵盖了哪些主题,你可以从那里了解到一个你最喜欢的帖子,最后还有一个奖励。我们走吧!****

商务化人际关系网

“职业脸书”,即最大的以就业为导向的在线服务,拥有超过 6.45 亿用户,遍布 200 个国家。

作为一个社交平台,LinkedIn 有各种搜索和内容算法,这些算法是为 9 位数的用户设计的。

他们的团队每月都会发布几次文章,主题包括人工智能&推荐,大规模处理社交互动,以及开源他们的系统。

我推荐一个帖子: 让 LinkedIn 实验引擎快 20 倍

** [## LinkedIn 工程博客

合著者:Sneha Chaudhari,Mahesh Joshi,和京格尔 Polatkan 领英学*是一个平台,领英会员…

engineering.linkedin.com](https://engineering.linkedin.com/blog)

中等

你应该知道 Medium by know,但是阅读这个漂亮的平台如何在引擎盖下工作不是很酷吗?

了解这个最大的在线出版平台是如何运作的非常有价值。你知道媒体使用 React & GraphQL 吗?

他们的帖子涵盖了各种主题,从服务器设计,到代码审查最佳实践,甚至是他们如何处理复杂的 bug

一帖我推荐: GraphQL 服务器设计@ Medium

[## 中等工程

团队建设中的故事。

中等工程](https://medium.engineering)

网飞

全球最大的流媒体提供商和制作公司,拥有超过 1.8 亿付费用户。

除了它给我们的生活带来的娱乐,考虑到它处理的的规模,网飞是惊人的复杂,它的工程博客让我们了解它们是如何“驾驭混乱”

他们有一系列突出的主题,从 ML 和推荐系统数据压缩架构设计

我推荐一个帖子: 为内存受限的电视设备带来丰富的体验

[## 网飞科技博客

了解网飞世界一流的工程成果、公司文化、产品开发等。

netflixtechblog.com](https://netflixtechblog.com)

Quora

地球上最大的个性化知识来源之一。

Quora 太神奇了。我已经使用它很长时间了,它仍然让我惊讶你可以从这个平台学到很多东西,而且不仅仅是在计算机科学方面。

他们的工程博客写了从数据库设计基于 ML 的主题推荐基础设施扩展

一帖我推荐: 使用自然语言模型进行问题批改

[## Quora 的工程

编辑描述

www.quora.com](https://www.quora.com/q/quoraengineering)

松弛的

借助 Slack 摆脱电子邮件噩梦,Slack 是企业消息和交互领域的领导者之一。

有趣的是,我从来没用过 Slack。但其超过 1200 万活跃用户不想转而使用电子邮件。

他们博客的内容从前端架构日常故事以及他们如何设计他们的内部工具。那里的内容密度突出

一帖我推荐: 在桌面上建立黑暗模式

[## 几个人在编码

Slack 工程博客

松弛工程](https://slack.engineering)

Spotify

仅次于网飞,音乐行业最大的流媒体软件。

像网飞一样,Spotify 的规模也很大。截至 2020 年 6 月,每月有 1.3 亿用户收看该平台。

你应该看看他们的博客,阅读那些“不那么关注技术”、关于他们开发的各种服务、或者关于在公司工作的人的故事真的很令人愉快。

一帖我推荐: Spotify Unwrapped:我们如何带给你十年的数据

[## 工程

Spotify 的官方技术博客

engineering.atspotify.com](https://engineering.atspotify.com/)

推特

280 个字符的社交网络。

我发现 Twitter 非常强大。该公司到现在已经有 14 年了,而最*的重新设计语音推文的发布是该公司继续努力的主要特色。

博客详述了复杂的系统工程AI 就他们面临的问题与接触,以及构建他们的网络应用的事实。

我推荐的一个帖子: 将搜索索引延迟减少到一秒

[## 英语(美国)

Twitter 工程团队关于我们的工具、技术和服务的信息。

blog.twitter.com](https://blog.twitter.com/engineering/en_us.html)

爱彼迎(美国短租平台)

租赁和市场公司来统治他们。

在预订住宿方面,Airbnb 占据了相当大的一块蛋糕,拥有大约 1 . 5 亿用户。

他们的博客应该会成为你的最爱之一,它分为两类,核心工程,和数据科学。他们有出色的内容,并专注于开源他们的技术,所以一定要看看!

两个帖子我推荐(一个不够):

[## Airbnb 工程和数据科学

创意工程师和数据科学家构建一个你可以属于任何地方的世界。http://airbnb.io

medium.com](https://medium.com/airbnb-engineering)

脸书工程与研究

无需介绍地球上最大的社交网络。

不管你喜不喜欢这个产品,脸书提供了无数的创新和研究课题,了解他们的基础设施总是很有价值的。

他们有一个博客专注于 facebook.com 的工程,另一个博客专注于 ML、AI 和 AR/VR 的基于研究的主题

我推荐一个帖子: 为新 Facebook.com 重建我们的技术体系

[## 脸书工程

关于基础设施系统、开源、连接、数据中心工程和开发工具的新闻

engineering.fb.com](https://engineering.fb.com/) [## 脸书研究

跳到内容通过研究和创新让人们有能力建立社区帖子下一个理解…

research.fb.com](https://research.fb.com/)

照片墙

脸书的小 1B 收购现在是地球上最大的视觉社交媒体。

Instagram 在收购后开发了大量功能,你会从阅读它们如何为 1B 用户提供更多服务中受到启发。

它们涵盖了关于移动开发的工程决策,在其系统中 ML & AI 的使用,以及基础设施数据驱动的选择。

一帖我推荐: 让 Instagram.com 更快:第三部——先缓存

[## Instagram 工程

来自创建@Instagram 的人们的故事

instagram-engineering.com](https://instagram-engineering.com)

优步

“我累了。我们远离家乡。外面是晚上”。搭个妖孽!

没有一个乘坐和导航系统能与优步的复杂性相提并论。

该公司正在开源许多技术,他们的工程博客专注于大规模的人工智能,处理大量的数据和最*的公司事件。

我推荐一个岗位: 用统计建模大规模监控数据质量

[## 优步工程博客

推动世界发展的软件工程和技术

eng.uber.com](https://eng.uber.com/)

开源代码库

如果你在这里,我不应该介绍 Github,对吗?

版本控制的最大客户,理解他们的挑战有点像递归问题,你不觉得吗?

他们的博客很吸引人,而且比其他人的更广泛,涵盖了工程公司产品的主题。

一帖我推荐: 从 48k 行代码到 10—GitHub 的 JavaScript SDK 的故事

[## GitHub 博客-来自 GitHub 的更新、想法和灵感,帮助开发人员构建和设计…

背景机器学*操作(或 MLOps)使数据科学家能够以更加协作的方式工作,通过…

github.blog](https://github.blog/)

谷歌开发者和谷歌人工智能

最后但肯定不是最不重要的,巨人谷歌。

谷歌无处不在。从在网上搜索到找到最*的星巴克或者在 Youtube 上观看有见地的视频,谷歌的产品几乎没有限制。

他们还有两个博客,一个关注核心工程,另一个关注研究课题。如果你时间不多,就看看研究上的那个,很神奇。

我推荐一个帖子: 用 T5 探索迁移学*:文本到文本的迁移转换器

[## 谷歌开发者博客

随着新的 Google Cloud 函数 Java 11 运行时的测试,Java 开发人员现在可以编写他们的函数了…

developers.googleblog.com](https://developers.googleblog.com/) [## 谷歌人工智能博客

本周标志着完全虚拟的 2020 年计算机视觉和模式识别会议(CVPR 2020)的开始…

ai.googleblog.com](https://ai.googleblog.com/)

bonus-diff . blog

什么?我不知道有叫 diff 的公司?

是啊,你说得对,我也是。

我在搜索这篇文章的资源和附加信息时偶然发现了 这个网站 ,我觉得我必须包含它。

A 答 事实上,它非常方便聚集和订阅你喜欢的博客,而且它专注于开发者社区。它与上面的内容密切相关,因为你可以在这个平台上找到并关注所有最大的博客。

您还可以:

  • 在口袋上保存物品
  • 加入讨论并获得博客推荐
  • 自动订阅您在 GitHub 上关注的用户的博客

如果你不喜欢给上面的所有博客做书签,请看看diff . blog你不会失望的。

今天到此为止,伙计们!你可以随时给我发邮件**联系我Linkedin或者访问我的 GitHub 项目 。****

感谢您的阅读。我希望这对你有所帮助,并祝你在学*之旅中好运!**

向解决市场问题的人学*

原文:https://towardsdatascience.com/learning-from-the-man-who-solved-the-market-536146fefe6c?source=collection_archive---------6-----------------------

金融

我们能从*代史上最好的投资者吉姆·西蒙斯那里学到什么

来源:作者

我第一次听说吉姆·西蒙斯是在 2007 年,当时我还是一名研究生,当我出于好奇阅读微分几何教科书时,偶然发现了这位著名数学家的名字。当时,我一点也不知道,我们正处于*代史上最严重的金融危机之一的边缘,这也是美国政治上的一个重大事件。

2009 年晚些时候,我在墨尔本一所大学的聚会上遇到了一名金融毕业生,当有人问我做什么时,他提到了文艺复兴科技(Renaissance Technologies),简称 RenTech。他开始描绘一幅神秘的、非正统的对冲基金的图画,它不雇佣任何有金融学位的人;只有 STEM 毕业生,最好是物理和数学等硬科学专业的毕业生。这听起来像是一群现代金融炼金术士聚集在纽约长岛某处的办公楼里。

我被迷住了:这是一只对冲基金,它不像大多数基金那样运作,它以自动化、冷静的方式进行所有交易,最大限度地减少了人为干预。这个故事真的打动了我,因为我一直痴迷于预测未来,无论是在交易还是其他领域,并建造机器来帮助我们更有效地做到这一点(当时,我不知道我会在数据科学领域开始职业生涯)。

吉姆·西蒙斯的名字再次出现。

研究生提到我应该在博士论文完成后申请。那时,学术研究仍然是我的心头之物,所以我从未冒险成为一名定量分析师。金钱并不像解决挑战性问题和丰富人类知识那样重要。至少我是这么想的。

因此,有趣的是,十多年后,我会看到吉姆·西蒙斯(Jim Simons)和伦泰克(RenTech)突然出现在我的推特上,他们的旗舰基金 Medallion 的记录显示在推特上,年复年回报率高达 66%(扣除费用后为 39%)。这让我想到了 Gregory Zuckerman 的对 Jim Simons、RenTech 以及成就了 RenTech 今天的辉煌和丰富多彩的角色的描述。

从数据科学的角度来看,RenTech 及其惊人回报的故事很有趣,因为它是首批将我们今天拥有的类似工具(如机器学*)应用于市场的对冲基金之一。这里有一些我们可以从这本精彩的书中吸取的教训。

N

根据模型的定义,既然它是现实的压缩表示,那么它最多只能*似现实。问题是,离现实有多远?

在所谓的硬科学中,模型具有很高的预测准确性。牛顿力学和引力模型(被广义相对论取代)工作得非常好,这样我们就可以相对高精度地发射火箭和探测器进入太空。此外,我们今天依靠的帮助我们发射火箭的物理模型预计在未来几千年内不会改变。这是由于自然过程的美丽:在我们星系角落的引力本质上与宇宙中另一个遥远的角落是一样的。自然过程中存在随机稳定性。

但在模拟市场上的人类活动时,情况并非如此。我们只是没有那么多关于市场行为的清晰数据(尽管这在最*发生了相当大的变化),我们也没有那么多的观察数据,因为股票市场只追溯到大约一百年前。

自然,我们应该对自己构建的模型保持适度的怀疑。

在书中,我们提供了竞争对手的例子。伦泰并不是唯一一家在交易中使用量化方法的公司。另一个竞争基金是长期资本管理公司(LTCM),该公司由约翰·w·梅里韦瑟于 1994 年创立,其杰出人物包括两位诺贝尔经济学奖获得者米隆·s·斯科尔斯(著名的布莱克-斯科尔斯方程的发明者)和 T2·罗伯特·默顿(诺贝尔经济学奖获得者)。与 RenTech 不同,LTCM 的研究人员认为他们的模型反映了事实。他们一点也不知道,他们对模型的绝对信任会在 1998 年晚些时候导致他们的失败,尽管最初有令人印象深刻的收益,但他们还是损失了所有的钱。

相比之下,在 2008 年面临次贷危机时,吉姆·西蒙斯不顾团队的抗议,通过出售来最大限度地减少损失,推翻了系统。此外,在 90 年代第一次海湾战争之前,他用石油看跌期权对冲了该基金。换句话说,仍然有一些决策是基于人类引导的直觉做出的。在极端时期,模型可能会失效,仍然需要人的判断。

LTCM 的困境还因其过度使用杠杆而加剧,正如 Ed Thorp 所提到的,其范围可能从 30 比 1 到 100 比 1,超过了凯利标准所建议的水平。利用杠杆没有错;RenTech 也使用了杠杆。但是当你的判断不正确时,更糟糕的是,你有一种错误的信心,认为你是正确的,认为你知道真相,杠杆会大幅削减你的利润。

这里的关键是一致性 再现性 物理学中的模型一次又一次地准确预测,并且它们的结果可以被复制。相比之下,交易模型,特别是那些处理人类行为的模型,不会保持一致。例如,新产品和新功能会出乎意料地影响消费者的行为和情绪,包括以意想不到的方式使用产品。

有时,当由于模型没有捕捉到的异常情况而导致景观发生剧烈变化时,需要人类的判断。了解一个模型的极限,以及模型中的假设,也是加倍重要的。

此外,作为数据科学家,我们的责任是管理对我们建立的模型的期望,并提醒利益相关者我们工具的局限性。

从字面上看,拥有最干净的数据是值得的

像世界上许多其他数据工程师、科学家和分析师一样,我每天都面临数据问题。从缺失数据到错误建模的数据,再到培训和生产数据之间的分布不匹配,在我的职业生涯中,我都见过。

清理、检查数据是否有意义以及编写数据测试(我称之为数据管理员职责)并不是这份工作中最性感的部分。听着,我明白。数据科学被认为是 21 世纪最性感的工作。它应该是有趣和迷人的,就像启动一群特斯拉 V100s 来训练一个 StyleGAN 来为销售目录生成逼真的假时装模特。基本上,数据科学隐藏的一面没有得到公共关系媒体的关注。

然而这是不可避免的。

作为任何公司中数据生产者的下游消费者,数据中总会有不完美之处,因为出错的方式比正确的方式多得多。有一些 UI/UX 的改变没有传达给数据团队,在我的职业生涯中就发生过一次。除了作者之外,没有人知道对模式所做的更改。一个产品特性被否决,导致模型的准确性显著下降。服务器停机会导致事件丢失。即使在成熟的数据驱动公司,如谷歌,这些问题仍然存在于不同的团队和产品的各个部分。

事实上,作为一名数据管理员,我的意思是,纯粹主义者,实际上是这份工作最重要的部分之一。如果你想让你的模型准确预测,最好首先给它们正确的模式。经常提到的垃圾进-垃圾出规则适用!

在早期,吉姆·西蒙斯和他的团队面临着同样的问题。商品价格数据存在缺口。当时,一个良好的金融和定价数据中央数据库甚至还不存在。

幸运的是,该团队有一位名叫 Sandor Strauss 的数学家,他是他们的第一个数据纯化者。他花了很大力气从 Dunn Hargitt 那里寻找商品数据,然后将它们分类并添加到其他历史信息中。他检查不一致的地方,让一名学生对斯特劳斯收集的商品价格进行数据质量检查,并煞费苦心地将他收集的价格与其他信息来源进行比较,如年鉴和《华尔街日报》的档案。

正是施特劳斯对这项任务的完全奉献和痴迷才产生了巨大的差异。随着数据变得更加清晰,它提供了更多的选择,使 RenTech 能够以更精确的时间增量进行预测和交易。这给了他们超越其他公司的优势,获得了更多的利润。Strauss 后来收集的其他干净的外围数据证明是有价值的,为 RenTech 提供了更多的优势,因为额外的信号被添加到了他们的核心模型中。为确保他们最重要的数据保持干净和最新而付出的所有辛苦投资最终都获得了回报。

在 RenTech 的案例中,数据是由一个极其混乱的市场产生的,数据是由第三方收集的,这些第三方并不总是确保所收集数据的质量。

幸运的是,与 RenTech 不同,我们大多数人都可以在我们工作的地方实现改变,因为我们通常处理内部产生的数据。我们可以倡导、教育和建立确保数据尽可能干净的流程。我们可以改善沟通渠道,以便提前了解上游的变化,如果可能的话,甚至在规划阶段。我们可以说服利益相关者进行文化变革,以改善整个产品的数据收集和分析。它永远不会完美,但目标是尽量减少数据问题,而不是彻底根除它们。

谁知道呢?其中一些数据可能会为未来的产品功能开辟新的途径,就像 RenTech 一样。

我们甚至拥有比以往更多的工具来提供数据质量检查。最*我最喜欢的工具之一是数据构建工具或 dbt ,它通过在 Canva 引入对数据质量的检查和平衡,确实起到了作用。

知道“为什么”并不总是有用的

投资中的一个普遍问题是附加一个错误的叙述来解释市场中的价格变化。

我们人类喜欢故事。我们试图找到任何事情的解释。我们会在媒体上听到为什么某一天市场上涨或者不上涨。也许这是国家就业数据的最新变化。也许是一只蝴蝶在世界的某个角落拍打着翅膀。事实是,没有人能绝对肯定地知道;如果有人声称这样做,这个人要么是妄想,要么是试图向你推销产品的骗子。

然而,我们应该问自己的基本问题是,如果我们知道原因是什么,这有关系吗?

在交易中,因果因素不一定是已知的。然而,重要的是从数据中发现的潜在信号是否有利可图。在这个意义上,预测只限于手头的任务,也就是说,最大化盈利交易的概率;显然,这符合判别模型。虽然相关性不等于因果关系,但它们确实反映了原因的各个方面,并且通常足以用于预测任务。机器学*实际上只是利用许多弱相关性,试图从模型中逆向工程导致这种情况的原因是徒劳的。

请记住,根据这本书,RenTech 的每次交易成功率只有 50%多一点,但他们通过交易量和头寸规模弥补了这一点。我们可以看到预测的准确性很重要,但是如何将预测反馈到决策过程中会对最终结果产生深远的影响。

在我最*预测 Canva 客户保留率的工作中,我很想附上一个故事,解释为什么一些客户保留了我们的订阅产品,而另一些客户没有。像 XGBoost 这样的算法可能会提供特性重要性分数,但它永远无法查明潜在的因果关系因素。然而,在我的用例中,找出原因并不重要,相反,开发一个能很好地完成预期工作的模型对我来说更有指导意义:帮助决定哪些用户在理解我们的产品时需要帮助

理解保留与流失的根本原因将需要额外的外部数据源和领域知识,如定性调查和社交媒体情绪,或新技术,如因果机器学*可解释机器学*

不可否认,在当前个人数据权利的大环境下,随着一般数据保护条例(GDPR) 等法律的实施,以及消费者对所做预测进行解释的权利,这更具挑战性。然而,我们可以通过始终明确训练数据、进入模型的假设以及模型的正确版本化来保持过去的运行记录,从而减轻这种情况。

伦泰克和吉姆·西蒙斯的故事是一个迷人的故事。尽管鉴于 RenTech 的隐秘性,Zuckerman 的书无法提供更多关于其内部工作的细节,但我们对它的一瞥足以为我们提供数据科学急需的课程。他们几十年前面临的问题本质上与我们今天面临的问题相同。

也许最有趣的一课与数据科学无关:吉姆·西蒙斯在 41 岁的成熟年龄开始了他的交易生涯。如果有什么我们可以从中学到的,那就是开始新的东西永远不会太晚!

编辑:之前的一个版本提到吉姆·西蒙斯是诺贝尔奖获得者。

向中华民国学*

原文:https://towardsdatascience.com/learning-from-the-roc-797e19ac8003?source=collection_archive---------38-----------------------

美国教育界似乎刚刚赶上数据科学家多年前就知道的东西。你从错误中学*。

如果说我们的教育系统现在才意识到这一点听起来有些牵强,你并不孤单。这是一个古老的格言,但不知何故它跳过了应用教育理论。不相信我?那就相信哥伦比亚大学心理学教授珍妮特·梅特卡夫(Janet Metcalfe)吧,她在 2017 年出版了《从错误中学*》(就在三年前!).

在这篇开创性的论文中,梅特卡夫博士指出了大量的证据,证明美国教师一贯忽视错误,而是教给学生得出正确答案的方法(即公式)。一个并不令人惊讶的变化是,教授一种方法远不如从错误中学*。日本教师采用的策略(通过错误分析进行教学)和比较这些国家的国际考试分数证实了这一点。要是这两个学科之间有一些交叉授粉就好了!对我们这些数据科学家来说,很明显,从错误中学*是学*一个概念的最好方法。在她的论文中,Metcalfe 博士继续论证了如何从错误中学*更好,并进一步量化了优化学*的条件。

你选择最小化的损失会改变你的机器的学*。

这是我想在数据科学背景下讨论的最后一部分,即优化学*中的细微差别。我们能从教育中学*吗,就像教育应该从数据科学中学*一样?

教师:学生::数据科学家:ML 算法

你还记得标准化考试中的那些类比吗?a 之于 B,如同 C 之于?好吧,这里有一个给你:老师对于学生,就像数据科学家对于机器学*算法一样。顺便说一句,我是一名教师,这个类比并不意味着贬低教师的工作(这是很难的东西!).

这个类比非常适合我们的环境,尤其是如果我们(显著地)简化了老师的角色。想想看,老师的目标是帮助学生学会做出正确的预测。事实上,这些预测非常好,我们称之为“答案”。老师采用一套策略来帮助学生尽可能快地学*。其中一个策略就是指出错误。然后,学生拿起这些错误,并(希望)分析它们,以理解为什么他们的预测是不正确的。然后,他们更新他们对这个概念的心理模型,并再次尝试。对人类来说,这个过程是高效但不快速。学生通过几个例子学*一个新概念,但是需要一些时间来整合信息。

这是一个好的还是一个坏的例子?

数据科学家做完全相同的事情。我们的目标是帮助我们的 ML 算法做出正确的预测。如果他们的预测足够好,那么这些算法就会“回归自然”。就像老师一样,数据科学家指出算法的错误,此时算法分析错误并更新其数字模型。对于计算机来说,这个过程很快,但效率不高。算法可以快速更新自己的模型,但是改变模型需要很多例子。

高效学*

为什么学生,甚至人类,学*效率很高?我的直觉是,我们以一种非常微妙的方式分析错误,这让我们理解为什么一个预测是不正确的。这导致我们心智模型的最佳更新,让我们从更少的错误中学*。它还有一个额外的好处,那就是我们可以在特定的条件下优化以获得正确的答案。让我解释一下:

想象你是一个正在觅食的早期人类。你刚刚看到你的朋友胡摘了一个浆果,吃了它,然后死了(悲惨的故事,对不起)。幸运的是,这是一个学*的时刻!你去研究浆果,注意到它是紫色带黄色斑点的。两天后,你再次觅食,发现了带有黄绿色斑点的紫色浆果。你吃吗?可能没有!犯错的代价非常高,所以即使这个浆果不完全符合模式,也不值得冒这个险。

这种情况下的正确答案是“吃任何不会杀死我们的东西”。所以浆果可能被错误地贴上了有毒的标签(称之为假阳性),但至少你没死。你可以说是以牺牲精确性为代价来优化召回。

想想这个词语的选择。你(你的早期人类版本)正在为回忆而优化。这听起来很像机器学*算法做的事情。事实上,这正是《T4》杂志打算做的事情。它通过最小化损失来优化系统。你(数据科学家)选择最小化的损失改变了你的机器学*的内容。

选择你的损失函数

如果你选择最小化的损失改变了你的机器的学*,难道你不应该选择一个最大化你感兴趣的度量的损失吗?在一个完美的世界里,是的,但不幸的是,你必须与损失函数的限制作斗争。

一般来说,损失函数需要是光滑的,理想情况下也是凸的。如果它不是平滑的,那么你就不能计算一个梯度来更新模型参数。如果它不是凸的,那么你不能保证达到全局最小值,或者有时根本不能达到任何优化。损失函数也不能是“单边的”——例如,只测量精度或召回率。“单边”损失函数会将模型推向“全有或全无”行为,以使损失最小化。最后一点需要注意的是,损失函数需要采用以下形式:

其中 y 是地面真实向量,ŷ是概率预测。

这些限制让你的选择更少,但绝不意味着你没有选择。例如,如果你有兴趣改进的指标是受试者工作特性(ROC ),那么你应该训练它的积分。您应该仔细考虑您有兴趣改进的指标,并在可能的情况下编写一个损失函数来优化该指标。

向中华民国学*

说到这里,你是如何从接收机工作特性中学*到的?幸运的是,一个团队在 2003 年发现了如何做到这一点!你可以点击这里阅读他们的出版物。这个损失在 Keras 中没有实现,但幸运的是,你很容易实现自己的损失函数。下面的代码是(非常)稍微修改过的版本,来自现在已经不存在的 TFLearn 库。

为了训练 auROC,在一个单独的单元中初始化这个函数。然后,在编译模型时引用该函数:

model.compile(optimizer = ‘adam’, loss = auROC(), metrics = …)

利用新冠肺炎开放研究数据集从无标签数据中学*

原文:https://towardsdatascience.com/learning-from-unlabelled-data-with-covid-19-open-research-dataset-cded4979f1cf?source=collection_archive---------30-----------------------

文本搜索结果的客观标准和一些令人惊讶的结果

新冠肺炎开放研究数据集可以帮助研究人员和卫生界对抗全球疫情。Vespa 团队通过发布基于数据集的搜索应用做出了贡献。由于数据没有可靠的标签来判断好的搜索结果和坏的搜索结果,我们想提出客观的标准来评估不依赖于人注释标签的搜索结果。我们使用这个标准来运行实验,并评估术语匹配和语义信号所提供的价值。然后,我们表明,即使在考虑一个专门为科学文本设计的模型的微调版本时,语义信号也只能产生很差的结果。

照片由国家癌症研究所Unsplash 上拍摄

由艾伦人工智能研究所发布的新冠肺炎开放研究数据集(CORD-19)包含超过 44,000 篇学术文章,其中包括超过 29,000 篇全文,涉及新冠肺炎和冠状病毒家族,供全球研究界使用。它的发布是为了动员研究人员应用自然语言处理的最新进展来产生新的见解,以支持与这种传染病的斗争。它确实做到了。

它一发布,就有了一个 Kaggle 挑战,一个数据集资源管理器微调嵌入模型和一个收集标记数据的运行:

鉴于我对 MS MARCO 数据集中包含强烈术语匹配偏差的标签的最新体验,以及我们 vespa.ai 希望快速围绕 CORD-19 数据集构建一个搜索应用的事实,我决定花一些时间思考如何在没有标签数据的情况下在不同匹配标准和排名函数之间进行评估。

文本搜索的客观标准

我们的目标是建立一个客观的标准,摆脱在没有可靠标签时常用的“看起来足够好”的标准。我的建议很简单,我们可以使用文章的标题作为查询,并将相关摘要视为查询的相关文档。

Marc A 在 Unsplash 上拍摄的照片

这个标准很简单,可以扩展到大量数据,因为我们不依赖于人工注释,而且它是有意义的。请这样想,如果您将标题用作查询,而给定的方法无法检索正确的摘要并将其包含在结果列表的前 100 名中,那么对于 CORD-19 搜索应用程序的上下文来说,我们有一个非常次优的排名函数。

结果

本节总结了所获得的一些结果。我们在此报告三个重要指标。查询匹配的文档的百分比、前 100 个位置的召回以及考虑返回的前 100 个文档的平均倒数排名(MRR)。

术语匹配

1 示出了通过对具有术语匹配信号 BM25 分数的文档进行排序而获得的结果。第一行显示了当我们只匹配包含标题中每个单词(和操作符)的摘要的文档时的结果。这种方法限制太多,只匹配一小部分文档(0.01%),因此错过了许多相关的摘要,导致召回率和 MRR 指标很差(分别为 20%和 19%)。

1:涉及术语匹配的关键结果指标。

第二行匹配包含至少一个标题(或操作符)单词的摘要的所有文档。这太宽泛了,几乎匹配了语料库中的所有文档(89%),但却带来了良好的召回率和 MRR 指标(分别为 94%和 80%)。

当使用 Vespa weakAND operator 时,可以获得中间地带。它根据一个简单的计算术语匹配方程跳过许多文档,导致它只匹配 19%的语料库,同时保留了与更昂贵的 OR 运算符检索到的文档相当的召回率和 MRR 指标(分别为 95%和 77%)。我们还可以调整用 weak 和检索多少文档。在这种情况下,我们将其设置为 1.000 个文档,以便与我们在语义搜索实验中使用的最*邻操作符进行比较。

语义搜索

2 的第一行报告了用语义搜索获得的结果。对于这个实验,我们决定使用 scibert-nli 模型,它是 AllenAI 的 SciBERT 的微调版本。我们对这个模型抱有很高的期望,因为它是一个为科学文本设计的模型的微调版本。

2:语义搜索结果的关键指标

然而,结果并不符合我们的期望。我们平均检索了大约 14%的语料库,其中Vespa nearest neighborhood 操作符被设置为检索 1000 个文档。这意味着我们基于标题和抽象嵌入之间的距离检索至少 1000 个文档,其中嵌入由 scibert-nli 模型构建。排名函数被设置为标题和抽象嵌入之间的点积。这种设置导致了我们实验中最差的召回率和 MRR(分别为 17%和 8%)。

当我查看结果时,首先想到的是代码有问题。所以为了检查这一点,我决定运行相同的实验,但是现在使用抽象作为查询。然后,任务变成了试图自我恢复的抽象。如果设置是正确的,结果应该是(接*)完美的,因为相同嵌入之间的距离应该*似为零(除了舍入误差)。

2 的第二行报告了这个健全性检查实验,并验证了我们的设置,获得了完美的回忆和*乎完美的 MRR。当应用于嵌入时,这至少消除了匹配阶段、排序函数和实验设置实现完全出错的可能性。因此,语义模型的糟糕表现继续作为一个奇怪和令人惊讶的结果冲击着我们。

评论

我们尽最大努力清理数据,使实验中只包含有意义的标题和摘要,这样语义搜索实验就不会受到不公平的对待。我们排除了许多标题和/或摘要明显错误的文章,如“作者索引”或“主题索引”。清理将考虑的文档数量从 44,000 个减少到大约 30,000 个。

之后,我们创建了标题和抽象嵌入,没有额外的预处理步骤,因为我们相信这是大多数人将如何使用它:

title_embedding = model(title)
abstract_embedding = model(abstract)

当然,如果有迹象表明这将显著改善结果,我们愿意接受关于如何通过微调模型从文本构建嵌入的建议。所有嵌入都被归一化(L2 范数)为长度 1

我们还结合了术语匹配和语义信号,但与纯粹的术语匹配设置相比,没有明显的改进。

结论

表 3 总结了这里讨论的结果。到目前为止,最明显的赢家是weakAND + BM25组合。语义搜索得到的结果令人失望,值得进一步研究。强调我们在搜索上下文中使用和评估语义模型是很重要的。这里报告的(差的)性能并不一定适用于其他语义任务。

表 3:涉及术语匹配和语义搜索的关键结果指标

拥有客观的标准来评估不依赖于人工注释数据的搜索结果是很重要的,这不仅对于没有显式标签的情况,如 CORD-19 数据集。它在处理具有有偏差标签的数据集时也很有用,例如,MS MARCO 数据集偏向于术语匹配信号,这可能是由于其数据收集设计。

使用 R 函数进行项目监控

原文:https://towardsdatascience.com/learning-how-to-create-function-in-r-can-be-extremely-helpful-for-project-monitoring-f30df3771410?source=collection_archive---------59-----------------------

作者图片

许多人知道 R 允许编写自己的函数,但并不是每个人都在实践中应用这个机会。事实上,R 有很多内置函数,可以满足一些人进行数学或统计分析的需要。然而,学*如何用 R 编写函数也无妨,可以根据您的具体项目需求进行定制。

在讨论具体的例子之前,让我们回顾一下函数的定义。简而言之,函数是一组一个或多个参数的集合,这些参数概述了为了实现结果它必须执行的任务的描述。如果你是函数概念的新手,可以考虑安装“漩涡”包,完成函数的免费互动部分。这一部分结合了一套很好的关于函数的理论和实践材料。

说到功能,需要区分它应该具备的四个重要组成部分。它们是(1)函数名(2)参数(3)主体和(4)返回

function_name

Now, let us check out this example. To find out the mean using R, you need to type mean () — name of variable in brackets. The variable should be numeric. Once you do it, R will give you the mean.

Knowing that mean is the sum of all values divided by the total number of values in the array of data points, you can write the average function in your own way.

Let us review the code above to understand step by step function writing:

首先 ,为函数取一个名字。在这里,函数的名称是 平均值

第二个 ,列出自变量,到函数内部的函数。这里,只有一个参数—函数(x)。

第三个 ,将代码写在函数体 a {紧跟 function(…)的块中。代码告诉 R,如果 x 不是数字,就停止运行。如果 x 是数字,那么创建 y 变量,它等于 x 的总和除以 x 的值的总数。

第四个 ,显示结果。

运行代码并保存后创建了 平均 函数,让我们测试一下。两个函数,mean () —内置 R 和新编写的函数给出相同的结果。

让我们看看你在工作中可能遇到的具体例子。作为监控流程的一部分,您需要获得关于打开的案例数量及其结果状态的详细信息。用于演示的数据集由以下变量组成:程序、案例数、个案工作者和结果。您可以使用 tidyverse 包分组并获得一个百分比表。

这是做这件事的方法:

这是输出:

作者图片

结果显示了整个程序流程。但是,如果您需要通过社会工作者获得该表,您会怎么做?解决方法是使用 tidyverse 进行过滤。如果你有几个社会工作者,这个过程会很好,但是,如果你有超过 50 个社会工作者要报告,这个过程就会变得令人厌烦。这是一个将你的代码转化为功能非常有用的时候。下面的例子展示了你可以如何做。这个例子没有使用社会工作者的真实姓名。相反,它使用社会工作者 A,社会工作者 B,等等。

运行并保存这段代码后,它将成为一个函数。你将能够通过社会工作者获得结果。只需输入 function-metrics(" case worker A "),它将显示您请求过滤的case worker的结果。所创建的函数将提取个案工作者 A 的数据,并向您显示结果。您还可以看到原始代码略有变化。它有一个过滤行代码设置为 选择个案工作者

作者图片

接下来,让我们看看这个想法如何与图表一起工作。这一次我们的仪表盘将按个案工作者显示每月进度。

它有三个要点:

1)未结案件总数

2)结果(实现、放弃、进行中)

3)提供的服务数量

第一步,您必须决定要使用的图表。然后,您可以将代码转换成函数,并开始使用它。作为准备阶段,将这些包加载到 R:

请参阅下面的代码,了解如何做到这一点。该函数被命名为 monthly updates ,应用了与上一个示例相同的逻辑——根据您选择的个案工作者显示结果。

现在,你输入【monthly _ updates】(【个案工作者 A】)或者 (【个案工作者 B】),而不是写很长的代码,就会得到结果。请看下面的*的演示:*

作者图片

学*如何编写函数非常有帮助。上述方法说明了如何将它应用于您的项目监控目的。为项目监控创建一个通用函数将有助于更快地获得结果,并使您的工作效率更高。您可以探索许多其他机会,了解如何根据您的需求和您所做的工作来最好地使用创建函数。

学*对你有好处。原因如下。

原文:https://towardsdatascience.com/learning-is-good-for-you-heres-why-35597cdeebc3?source=collection_archive---------57-----------------------

意见

在任何领域变得停滞不前都不是伟大的;数据科学、写作和技术也不例外。

莎伦·麦卡琴在Unsplash1】上的照片。

目录

  1. 介绍
  2. 教育
  3. 简历
  4. 促进
  5. 健康
  6. 摘要
  7. 参考

介绍

本文的目标是:

1.学*的重要性。

2.仔细看看教育、简历、工作和健康与学*。

如果你想在数据科学、机器学*、编程和可视化,或者任何不同的职业领域和激情中提升自己,有无数的途径来提高你的技能。无论你的目标是考上大学,改善你的简历,还是在工作中得到提升,都有极好的理由和好处继续学*。不仅对学*有一些有形的影响,而且对精神也有好处。下面,我将讨论主要原因,并举例说明如何继续你的学*之路。

教育

照片由斯科特·格雷厄姆Unsplash2】拍摄。

教育中的学*本身是相当有价值的。无论你是获得硕士学位还是推出在线课程,投资教育最终都会获得回报,同时还会获得新的人脉和课程。

以我个人的经历来看,教育一直是我今天成为数据科学家的原因。几年前,我是一名分析化学家,这占据了我大部分的时间。我知道我对其他类似的东西感兴趣,但足够不同,开始在网上研究不同的职业道路。有一次我花了一些时间浏览,我看到了在线硕士课程(此时,我已经有了生物学本科学位,辅修了中文和化学)。几个月后,我找到了 SMU,申请并开始了我的第一门课程。当时,我已经准备好学*,并渴望在一个新的领域开始我的旅程。从那次教育中,我学到了无数有价值的技能,积累了惊人的人脉。它给了我专业追求数据科学的信心和激情。有了教育,我学*的下一个合理步骤是我的简历。

简历

一份简历可能会成为一项令人生畏的任务,也可能让人完全不知所措。你可以寻找无数的例子和方法来制作最好的简历,但是当你这样做的时候,你真的是在为大众制作最好的简历——而不是你自己。

我在简历写作和创作中发现的最好的建议是做你自己。

无论这听起来多么陈词滥调,你都更愿意为一家你不必为之改变自己的公司工作,就像生活中的大多数事情一样。一旦你养成了为他人而顺从自己的*惯,这将对选择雇佣你的工作产生负面影响。

有时候,公司会不喜欢我的简历只有两页,或者是蓝色的。在把它改成一页并转换成黑白后,我意识到我只是合群,而不是突出。我很快就把简历翻回了原来的样子,那是我看到了那些我真正关心并想为之工作的公司的积极反馈和回应,而不是那些想改变我的流程和性格的公司。

学*如何制作一份简历,与其说是寻找符合特定工作描述的关键词,不如说是突出你独特的自我,无论是 SQL 还是 Tableau,是在线课程还是会议,如果这是你在下一份工作中真正想做的事情,就列出并包括它。不要忘记,不只是面试官想找到合适的人选,你也是。

促进

学*是职场晋升不可或缺的一部分。当雇主看到你竭尽全力,并在与当前工作相关的新技能和经验中找到激情时,你很快就会收获认可和晋升的好处。

  • 虽然不能保证,但让自己沉浸在从教程中学*和参加技术、科学、写作或数据科学会议中,你可以通过参与你所在领域的社区而得到提升。

例如,自己写博客欢迎社区加入你的平台——在这里你可以联系他人并向他人学*;被听到、看到,并能够与你所在领域的一些佼佼者合作。

健康

埃内科·乌努埃拉Unsplash【3】上拍摄。

请记住,这篇文章是一篇观点文章,这种学*方式对我有用,我希望对你也有用。我相信学*本身对你的大脑很有好处。健康和学*的主要方面可以用神经科学来概括,更具体地称为【4】。

**Somewhat similar, data science is akin to this form of science in that neural networks act the same, creating new connections from learning, and coming up with better predictions or skills in the case of your own learning.** 

有可能当你训练自己学*时,你会在学*的道路上变得更好,类似于深度机器学*算法的工作方式。

摘要

虽然这篇文章不是关于代码、机器学*算法或教程的,但我相信强调生活中关键时刻学*的好处是很重要的。也许你没有读我的文章就已经相信了这一点,因为你已经订阅或访问了一个博客,并努力从文章中学*新的东西。

我希望这篇观点文章是有趣的,对你有帮助。感谢您的阅读!

参考

1Sharon McCutcheon 在 Unsplash 上拍摄的照片,(2020)

[2]照片由斯科特·格雷厄姆Unsplash 上拍摄,(2016)

3照片由埃内科·乌努埃拉Unsplash(2018)上拍摄

4维基百科,神经可塑性,(2020)

学*朱莉娅——最简单的开始

原文:https://towardsdatascience.com/learning-julia-the-simplest-of-beginnings-464f590e5665?source=collection_archive---------51-----------------------

亚历山大·杜默在 Unsplash 上拍摄的照片

如何使用 FizzBuzz 执行循环和条件函数

在本帖中,我们将创建一个函数来解决过于流行的 FizzBuzz 编程挑战。

看完这篇文章,你会知道:

  • 如何在 Julia 中创建函数
  • 如何执行 for 循环
  • 如何创建 if-else 块
  • 1:5 意味着什么
  • 如何计算一个数被除后的余数

这篇文章是为初级程序员或者那些以前从未听说过 Julia 的人写的。看完这篇文章后,不要指望做惊天动地的大规模并行科学工作负载。就当这是你在茱莉亚这个令人敬畏的世界里卑微的开始。

FizzBuzz 是什么?

如果你从未听说过它, FizzBuzz 是一个简单的计数游戏,旨在教孩子们乘法表。参与者围成一圈,有人从 1 开始计数。下一个人继续 2 等,绕圈。诀窍在于,如果这个数能被 3 整除,那么玩家应该说 Fizz 而不是说这个数。如果这个数字能被 5 整除,那么他们应该说 Buzz 。如果这个数字能被 3 和 5 整除,那么他们应该说 FizzBuzz

我猜你可以用任何其他 2 个数字玩这个游戏,但是 3 和 5 是最受欢迎的选择。

这个简单的游戏已经被翻译成一个折磨初学者的编程挑战。这也给了我们一个在 Julia 中练*循环和 if 语句的好机会。让我们看看如何创建一个函数来打印前 n 个数的解。

我之前已经在 BigQuery 中解决了 FizzBuzz,所以如果你有兴趣知道如何使用 PB 级数据仓库解决这个问题,请在这里查看我的文章

一步一步来

照片由大卫·布鲁克·马丁Unsplash 上拍摄

让我们一步一步来,看看如何解决这个问题,而不是简单地讨论这个问题。

我们在做什么?

我发现对这个功能应该实现什么有一个清晰的概念是非常重要的。在我们的例子中,我们希望打印第一个n数字,但是用 Fizz 替换能被 3 整除的数字,用 Buzz 替换能被 5 整除的数字,用 FizzBuzz 替换能被 3 和 5 整除的数字(或者用 Fizz Buzz 替换能被 3 和 5 整除的数字)。

例子?

有一个关于我们想要达到的目标的想法是很好的,但是有时候通过例子来理解一个任务更容易。对于n=3n=6,我们的函数会输出什么?写下例子将有助于我们找到解决方案,还能让我们检验我们的结果。

因此对于n=3,我们期望得到:

1
2
Fizz

对于 n=6,我们也希望出现“嗡嗡声”:

1
2
Fizz
4
Buzz
Fizz

同样,当我们达到 15 岁时,我们应该说“嘶嘶”。我们也不要忘记这一点!

你的第一个朱莉娅函数

让我们现在开始编码。既然我们正在一个接一个地打印数字,让我们做一个 for 循环。首先,让我们只打印前 n 个数字,然后我们可以稍后将它们更改为嘶嘶声和嗡嗡声。

这是你的第一个 Julia 函数。让我们把它分解一下,看看它有什么作用:

  • 功能function关键字开始,以end结束。中间的一切都是你的功能块。该函数有一个输入n并且不返回任何内容,因为我们只打印数字。
  • 说到打印,我们用的是println,内置的 Julia 函数,代表 print line。这个打印给定的值并开始新的一行,所以我们所有的数字将整齐地打印在彼此下面。
  • 我们这里还有一个 for 循环。这以关键字for开始,以end结束。我们正在循环的数字是i,所以在每次迭代中,i的值将在 for 循环中改变。
  • i会有怎样的变化?这由1:n位给出,即定义了从 1 到 n 的范围,每一步递增 1。要了解更多信息,请在此处搜索使用范围对象创建数组。

显然,这个函数不会给出我们需要的东西,但至少我们有一些基本的函数。让我们来测试一下:

julia> fizzbuzz(5)1
2
3
4
5

分步解决

迈克尔·卡鲁斯在 Unsplash 上的照片

让我们修改上面的内容,这样我们就可以为所有能被 3 整除的数字打印出 Fizz

我们如何做到这一点?我们可以检查,当除以 3 时,余数是否为 0。这叫做一个数的模。有一个函数可以做到这一点— rem()(或者您可以使用%运算符)!

以下是一些关于rem如何运作的例子:

rem(1,3) -> remainder of 1, when devided by 3 -> 1
rem(3,3) -> remainder of 3, when devided by 3 -> 0
rem(8,3) -> remainder of 8, when devided by 3 -> 2

修改我们的函数给我们:

更好看!所以现在,每当i除以 3 的余数为 0 时,我们打印“Fizz”而不是 I。

Julia 中 if 块的条件部分必须始终计算为布尔值—真或假。

如果你明白上面是怎么回事,你就知道 Julia 里的 if-else 块了!👏

继续下一个

同样的逻辑也适用于能被 5 整除的数字。我们只需要把rem的第二个参数改成 5。

来源

再测试一次,看看我们是否还可以:

julia> fizzbuzz(5)1
2
Fizz
4
Buzz

差不多了,现在我们有嘶嘶声和嗡嗡声了!最后一步是添加当数既可被 3 又可被 5 整除时的情况,即被 15 整除:

julia> fizzbuzz(15)1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
Fizz

不对不对。15 岁还有“嘶嘶”声!这是因为 15 能被 3 整除,所以我们的if-else块只到达第一位,检查这个数是否能被 3 整除,然后愉快地终止,只打印“Fizz”。

我们必须确保先检查 FizzBuzz 案件,然后再做其他事情:

如果你不想被 15 整除,你也可以说:(rem(i,3) == 0) & (rem(i,5) == 0

julia> fizzbuzz(15)1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

成功!🎉

通过阅读这篇关于 Julia 的介绍性文章,您了解到:

  • 功能
  • If-else 块
  • 对于循环
  • 余数函数

你还解决了 FizzBuzz 挑战👏!

我真的很喜欢茱莉亚,所以希望将来能从我这里看到更多关于茱莉亚的内容。如果你对学*这种令人敬畏的语言感兴趣,一定要关注我!

学*机器学*为第四次工业革命做准备

原文:https://towardsdatascience.com/learning-machine-learning-in-preparation-for-the-fourth-industrial-revolution-769460be599e?source=collection_archive---------65-----------------------

ML 和 AI 课程的相关资料

机器学*——图片来自 freepik

这篇文章将探索关于 ML 和 AI 课程的评论和其他相关材料。我根据自己的经验对它们进行了排名。此外,我还附上了我记得的所有有用的资料,以及一些我觉得非常有用的网站的链接。

概述

第四次工业革命

第四次工业革命将迎来一个全新的商业格局。承诺改变我们与自身和环境互动的方式

这场工业革命超越了技术驱动的变革。它实际上是关于新流程、技术和商业模式的诞生,这些都将颠覆商业。

第四次工业革命(4IR)由几个领域组成,包括:

  • 物联网
  • 机器人学
  • 数据科学
  • 机器学*
  • 人工智能
  • 三维打印
  • 商业分析
  • 和许多其他技术。

第四次工业革命的关键组成部分之一是大量的数据。每天都有大量的数据被存储和收集。机器学*和人工智能算法可以优化和自动化几个分析过程,这将带来商业上的革命性进步。

随着数据的指数级增长,伴随着技术的快速进步,我们迫切需要成为数据专家。考虑到这一点,我组织了一些与数据科学领域相关的开发课程。

数据科学和机器学*

数据科学旨在从数据中提取尽可能多的洞察力和信息,用于解决复杂的业务流程和辅助决策。

借助数据科学,人们可以发现以前从未想象过的数据中的未知模式和趋势。当有大量数据可以分析以提供更准确的结果时,数据科学是有效和有益的。

机器学* (ML)是 AI 的一个子集。它是一门让计算机执行和学*没有明确编程的任务的科学。机器学*用于发现数据中的模式并进行预测。

如何开始学*

机器学*和人工智能领域的所有可能性都激起了我的兴趣。即将到来的技术革命的想法是我希望成为其中的一部分。因此,学*和建立我在人工智能和机器学*方面的技能是必不可少的。

我想分享我对最*完成的一些课程的反馈。我参加了一些线下的课程,但是在线学*给了我在任何时候想学什么就学什么的选择。

先决条件

有几个先决条件可以帮助您更好地理解这些概念。在继续之前,您需要了解以下几个方面:

  • 微积分基础知识
  • 线性代数
  • 概率与统计
  • 算法和 Python 也是机器学*的先决条件

有益资源/建议

  • 机器学*专用数学— Coursera

本课程由伦敦帝国理工学院教授。我必须提到,它们是繁琐的课程,需要大量的奉献和努力才能完成。但是在学* ML 之前,学*其中解释的概念是至关重要的。

  • Josh Starmer 的 stat quest—YouTube

本课程非常适合学* ML 概念和统计学。本课程将非常复杂的 ML 和统计概念分解成易于理解的部分,便于掌握。我打赌你会喜欢这门课,尤其是有趣的歌唱部分。

  • Python for every one—Coursera

这门课程很容易学*和理解。对于学* Python 来说,这也是一门优秀的初学者课程,它将教授你在开始学* ML 课程之前需要知道的大部分知识。

  • Jupyter 笔记本初学者教程 by Dataquest

我没有选这门课。但是既然强烈推荐,那就应该试一试。

一旦您的 Python 技能很好,您就会想要轻松地使用和操作数据。NumPy、熊猫、Matplotlib 和 Matplotlib 是一些帮助你开始的有用资源。

学*机器学*概念

  • 数据分析师 Nanodegree — Udacity

很多人都推荐这门课程,幸运的是,Udacity 最*与沙特 MSK 学院合作。因此,我注册了这个纳米学位。如果你更喜欢实践而不是理论,那么你应该参加更多关于 Udacity 的课程。他们的课程非常注重实践。但是我发现这门课比其他课容易。如果你是一名年轻的开发人员,首先这是一门很好的课程。

  • CS221:人工智能:技术与原理—斯坦福

我对这门课程没有任何抱怨;作业和实*都很完美。我们每周都有有趣的编码作业。

  • CS229:机器学*—斯坦福

我去年夏天在斯坦福注册了这门课程和 CS221。我分享了我的经验,课程也在网上提供。

这门课很棒。但是如果你不太擅长线性代数,我建议你在选修这门课之前先温*一下。另外,不要把这门课作为你的第一门 ML 入门课。

你可能会发现这个备忘单很有帮助。它是由斯坦福大学毕业生谢尔维·阿米迪设计的。

  • 机器学*— Coursera

由吴恩达教授的这门课程无疑是目前最受欢迎的机器学*课程。这门课程理论性很强,所以如果你在注册之前先上一些实践课程,你会更欣赏它。

  • 数据科学沉浸式—总装

大会最*与沙特 MSK 学院合作。因此,我注册了这个课程。本课程为离线课程,但由于疫情,本课程不得不在线上进行。然而,它仍然是一个非常好的。这门课的及格与否取决于你是否完成了作业和期末专题。好的一面是这门课程需要大量的编码。

  • 深度学*专业化——Coursera

这个专精很神奇,如果你对 AI 有兴趣的话,我建议你上这门课。吴恩达教授解释了人工智能的价值及其带来的改进。本课程简单易学,定义明确。如果你需要一个很好的 AI 职业基础,那就从这门课开始吧。

  • 数据科学伦理— Coursera

该课程由密歇根大学提供,它解释了围绕数据科学的一些道德和法律框架。在使用数据时,理解道德是有好处的

结束了!

机器学*是一个非常实用的研究领域,所以最好的学*方法是边做边学。你可以在 Kaggle 找到很多项目

结论!

随着数据科学继续被用于各种技术和业务流程,它将继续导致数字中断。这不再是是否的问题,而是何时的问题。如果你不能快速适应,你就有被落下的危险。

企业必须现在就开始规划未来,并专注于如何利用第四次工业革命来提高其业务能够为客户提供的价值。

学*多维指数:OLAP DBs 的下一件大事

原文:https://towardsdatascience.com/learning-multi-dimensional-indices-a7aaa2044d8e?source=collection_archive---------45-----------------------

弗兰基·查马基在 Unsplash 上拍摄的照片

世界上数据的泛滥为学*和分析世界各地人们的行为提供了大量的机会。大多数分析至少需要几天的数据,这就需要一个快速的可查询存储引擎。OLAP 数据库的存在仅仅是为了服务于这个目的,也就是说,使大量的数据能够以最小的延迟被容易地查询。

为了最大限度地减少延迟,所有数据库都对数据创建了索引。索引通常是基于树的结构,例如 B 树、R 树等。它基于某个固定的键直接向您提供包含数据的行或块,而不是让您扫描所有的行。

OLAP 数据库的独特之处在于,可以一次对多个列进行查询,例如,通过用户、日期和城市获得订单总数的查询。从技术上讲,您也可以在多个维度上创建索引,但是您必须假设用户将遵循什么样的查询模式。您还必须假设每列将容纳的数据量,以做出有效的索引决策。

如果数据库本身根据插入的数据修改了索引会怎么样?有学问的多维索引是回答这个特殊问题的一种努力。在这篇博客中,我们将看看其中的一种算法。

洪水

Flood 算法是为内存索引设计的。也可以对其进行修改,以便在 OLTP 数据库中使用。洪水背后有两个关键思想:

  1. 使用示例查询筛选器工作负荷来确定某些维度的使用频率、哪些维度一起使用以及哪些维度比其他维度更具选择性。基于这些信息,定制整个布局以优化性能。
  2. 使用经验 CDF 模型将多维倾斜数据展平到统一空间中。

让我们假设需要在 d 维数据上创建索引。在这样的数据中,没有自然的排序顺序。因此,该算法首先选择一个将用于排序的维度。然后,该算法创建一个 d-1 维网格,其中每个维被分成等间距的列。这种网格中的每个单元格都包含多个数据点。

为了确保数据点均匀分布,使用特定维度的最小值和最大值对其进行标准化。最后一个维度用于对每个单元格中的数据进行排序。

询问

一个查询通常由 k 个维度组成,其中 k < d. Since the query already contains the range of values for each dimension that need to be queried, we can simply select all the cells which lie within that range along with cells that have partial overlap. This step is known as Projection.

For the cells which have partial overlap, we can use the fact that the data in them is sorted and select the relevant data using binary search. This is only possible when you have the sort dimension as a part of the query. This step is known as Refinement.

Once we have all the data, we can refine it further to check if any out of range data is there or not and then return the result to the user. This step is known as Scan.

Layout optimization

The primary strength of FLOOD lies in its ability to optimize the data layout to minimize the query latency. To minimize the latency, you first need a proxy to determine the query performance. The algorithm uses a custom cost function to serve the purpose. The cost function is composed of three parts:

  • wpNc ,其中 wp 是对一个单元执行细化的平均时间,Nc 是网格中单元的总数。
  • wrNc 其中 wr 是对一个单元执行细化的平均时间,Nc 是网格中单元的总数。
  • wsNs ,其中 ws 是执行每次扫描的平均时间,Ns 是扫描数据点的总数。

然后,查询时间的模型可以计算为

wpNc + wrNc + wsNs

下一步是计算权重 wp、wr 和 ws。对于该洪水,使用一个简单的模型,该模型采用像元总数、可过滤像元大小的平均值、中间值和尾部分位数、维数等特征。Flood 仅训练权重模型一次,并将其重新用于多个数据布局。

最后一步是优化布局,包括调整排序维度的维度和每个维度中的列数。

在每次迭代中,该算法选择 d 维中的一个作为排序维。其余所有维度都用来创建 d-1 维网格。然后,它运行梯度下降算法来确定最小化查询时间的列数。

Flood 为每个新工作负载重新调整数据布局。由于 DB administrator 不可能生成最可能的查询作为模型的输入,因此 Flood 本身会生成用于训练的查询,方法是将一些维度随机分组,将其他维度随机过滤,而将其余维度置之不理。group by 聚合函数也是随机的。

结论

Flood 算法标志着自学*索引道路上的一个重要里程碑。它具有很高的实用性,可以在真实世界的数据库中使用。然而,Flood 仍然存在一些缺点,需要解决这些缺点以使其成为一个完全通用的算法。其中一些缺点是-

  • 它不支持插入新数据。在新数据到达的情况下,需要再次拟合整个数据集。当前版本仅适用于只读工作负载。
  • 它是单线程的,在其当前实现中不支持并发。
  • 尽管 Flood 针对新的工作负载进行了自我调优,但它仍然很难确定工作负载何时发生了足以触发重新调优操作的变化。

最后,我希望这些问题将在未来得到解决,OLAP 数据库最终将变得至少比本文中展示的快一个数量级。

您可以使用以下参考资料来了解有关已学数据结构和索引的更多信息:

以最简单的方式学* Python 中的一键编码

原文:https://towardsdatascience.com/learning-one-hot-encoding-in-python-the-easy-way-665010457ad9?source=collection_archive---------31-----------------------

在本教程中,我们将从头开始学*特征工程中的一个重要概念,即一键编码。

我们先了解一下情况,然后定义一热编码。有时候解决问题是理解概念的最快方法之一。好吧,我们先创造一个情境(我刚刚虚构的情境)。只需一个平视就可以在我的 GitHub 资源库中找到下面给出的 :

[## 塔努-北帕布/Python

github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Learning_One_Hot_Encoding_in_Python_the_Easy_Way.ipynb)

情况

假设您正在解决一个简单的数据科学问题。现在,实际问题是什么并不重要,但您会陷入这样一种情况:您有一个很小的数据集,其中有 7 个实例,每个实例有 4 个特征。用蹩脚的话说,数据集有 7 行4 列。其中三列为类型object,意味着这些列包含字符串值。另一列是类型int,这意味着它只有整数值。现在说得够多了,让我们实际看看数据集是什么样子的。而不是给你看原始数据。CSV 格式)。我用熊猫库把它格式化成一个数据帧。

为了安全起见,让我们看看列的数据类型。

现在实际情况开始了,因为一些学*算法只处理数字数据,你必须以某种方式处理这些object数据。处理这种情况有两种选择:

  • 删除所有三列然后睡觉
  • 阅读本教程并实现一键编码

我知道选项 1 效果很好,但是有时候你必须集中精力,为了生计而努力工作。现在解决这种情况的方法是将这种object类型的数据转换成几种binary类型的数据。我的意思是要仔细观察数据集。列最喜欢的颜色有 6 个独特的值,如红色、橙色、黄色、绿色、紫色和蓝色。现在我们可以将这个特征转换成一个六个数值的向量,如下所示:

同样,你不认为我们也可以将最喜欢的日子列转换成一个六个数值的向量吗?因为这一栏有 7 个独特的日子,比如周一、周二、周三、周四、周五、周六、周日

现在你可能会想,我们能不能不做同样的事情呢?但这里的关键是不。不要做同样的事情。在这里,我们将学*一个叫做顺序的新概念。既然有体面,好,更好,最好,优秀。我们将它们排序为{过得去,好,更好,最好,优秀}{12,3,4,5}{0,12,3,4}。

这是因为当一些值的排序很重要时,我们可以通过只保留一个变量来替换这些值。

请记住,这种技术并不是在所有情况下都有效。例如,你们中的一些人可能会想,我们不能用同样的技术来填充其他两列的值吗?通过这样做,你肯定会降低特征向量的维数,但是这意味着在该类别中的值之间有一个顺序,并且它经常会混淆学*算法。当没有规则时,学*算法将试图找到一个状态规则,并且该算法很可能过拟合。所以要明智地思考和使用这种技巧。仅当值的顺序很重要时才使用此选项。这种技术可以用在一篇文章的质量、用户对产品的评论、食物的味道等方面。

因此,有意或无意地,你已经学*并掌握了一键编码的概念,以及在哪里使用它。这就是如何将分类或对象类型数据转换成数值类型数据。让我们看看如何实际编码并摆脱这种情况。

从头开始创建数据集

如前所述,这是一个虚构的数据集。为本教程创建。不是针对你。

import **pandas** as **pd****# Creating a list with some values** **studentID** = [1000, 1001, 1002, 1003, 1004, 1005, 1006]**color** = ['Red', 'Orange', "Yellow", 'Green', 'Yellow', 'Purple', 'Blue']**DaysOfTheWeek** = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']**Attitude** = ['Best', 'Decent', 'Better', 'Excellent', 'Excellent', 'Good', 'Best']

现在我们有了列表,让我们将其转换为数据框。为此,我们需要压缩所有列表值,然后存储它。

**# Converting the list into a data frame and simultaneously renaming the columns.****df** = pd.DataFrame(list(zip(studentID, color, DaysOfTheWeek, Attitude)), **columns** =['Student ID', 'Favourite Color', 'Favourite Day', 'Attitude'])print(**df**)

将对象类型数据转换成分类类型

这是因为在大多数情况下,您可能会得到分类类型的数据。但是在这里,上面看到的三个都是一个object类型。如果是这种情况,那么您需要手动将它们转换为分类类型。

**# Converting the object type data into categorical data column**for **col** in ['**Favourite Color**','**Favourite Day**', '**Attitude**']:
    df[**col**] = df[**col**].astype('**category**')print(**df.dtypes**)

将二进制代码分配给分类值

如前所述,我们将只把最喜欢的颜色和最喜欢的日子列转换成二进制值列。我们可以使用 pandas get_dummies方法,而不是手动操作。

**# Assigning the binary values for Favourite Day and Favourite Color columns****df** = pd.get_dummies(data=df,columns=['Favourite Color','Favourite Day'])print(df)

通过这样做,你显然会增加数据集的维度,但是你的学*算法会执行得更好。

将订单分配给名为“态度”的分类列

有两种方法可以做到这一点:

  • 使用字典手动赋值。
  • 使用LabelEncoder方法

选项 1 是没有用的,因为如果你有超过 1000 个唯一值,那么你可能会使用一个循环语句,使你的生活变得复杂。现在是 2020 聪明思考,使用sklearn库来做这件事。

**# Assigning order to the categorical column** from **sklearn.preprocessing** import **LabelEncoder****# Initializing an object of class LabelEncoder
labelencoder** = LabelEncoder() df['**Attitude**'] = labelencoder.fit_transform(df['Attitude'])print(df)

好了,现在你可以使用你最喜欢的学*算法,然后告诉fit(X, y)或其他什么,然后愉快地睡觉。

好了,伙计们,我希望你们今天学到了新东西。这真的是一个非常重要的概念,也是你将会遇到的特性工程技术。这是数据科学面试中最常被问到的问题之一。如果你对本教程有任何疑问,那么评论区就是你的了。在那之前保持安全,再见。下次再见。

学*熊猫简介

原文:https://towardsdatascience.com/learning-pandas-profiling-fc533336edc7?source=collection_archive---------33-----------------------

使用 Python 进行 Pandas Profiling 的全面入门指南

照片由 Sid BalachandranUnsplash 上拍摄

介绍

在当今时代,成为一名数据科学家是一份令人难以置信的令人兴奋和有益的职业。随着技术的爆炸式发展以及每天创建的大量数据和内容,数据科学家需要不断学*新的方法来有效地分析这些数据。任何新数据项目最关键的部分之一是探索性数据分析阶段。作为一名数据科学家,这一阶段允许您学*和熟悉手头的数据,数据从哪里收集,数据中的任何缺口,任何潜在的异常值以及所使用的数据类型的范围。一个已经成为数据科学家常用的工具是 熊猫概况 。Pandas Profiling 是一个用 Python 编写的开源工具,能够生成详细描述数据集中数据类型的交互式 HTML 报告;突出显示缺少的值;提供描述性统计数据,包括平均值、标准差和偏斜度;创建直方图并返回任何潜在的相关性。

安装熊猫档案

对于本文,我们使用的是由 JetBrains 创建的集成开发环境 PyCharm 。PyCharm 是一个非常好的工具,因为它可以处理一些任务,包括为项目创建一个虚拟环境,以及安装代码中引用的包。

要开始,打开 PyCharm 并选择File > New Project,将出现一个对话框,您可以在其中命名项目并创建一个相关的虚拟环境。虚拟环境允许您安装项目可以引用的特定 python 包,而不必在您的机器上全局安装这些包。当您有多个项目需要同一个包的不同版本时,这是很方便的。

一旦在虚拟环境中安装了默认包,我们需要安装 Pandas Profiling。为此,导航至File > Settings > Project > Project Interpreter,选择右上角的+按钮,搜索pandas-profiling,然后按下Install Package

使用 PyCharms 项目解释器安装 Pandas Profiling。

入门指南

对于这个例子,我们已经创建了一个简单的 Python 脚本,您可以使用它开始学*。如果这是你第一次使用 Python,请阅读 入门——Python 熊猫 ,我们在下面的脚本中解释了代码。

一个 Python 脚本将使用假数据生成一个 HTML 熊猫概况报告。

在执行脚本之后,一个名为pandas_profile_text.html的新 HTML 文件将会在您的项目根目录中创建。要查看报告,右击 HTML 文件上的并选择Open in Browser > Default

熊猫概况报告

概观

熊猫概况报告中的概述部分

Pandas Profiling 报告的第一部分“概述”部分显示了整个数据集的汇总统计数据。它返回变量的数量,即传递的数据帧中包含的列数。观察次数是接收到的行数。该概览还提供了缺失单元格或重复行的数量以及受影响记录总数的百分比。丢失的单元格和重复的行统计数据对于数据科学家来说非常重要,因为这些可能表明更广泛的数据质量问题或用于提取数据的代码问题。概述部分还包括内存中数据集大小的数据、内存中平均记录大小以及任何可识别的数据类型。

在 Overview 部分的 Warnings 选项卡下,您可以找到数据集内任何变量的校对警告。在这个例子中,我们收到了一个关于名称电子邮件城市高基数警告。在这个上下文中,高基数意味着被标记的列包含非常多的不同值,在现实世界中,对于雇员编号和电子邮件,您可能会遇到这种情况。

变量—类别

Pandas 特征分析报告分类变量的结果

Pandas Profiling 报告中的变量部分分析传递的数据帧中的列。分类变量是包含表示 Python 字符串类型的数据的列。

为分类变量返回的典型度量是列中字符串的长度。要查看生成的直方图,选择Toggle Details,然后导航至Length选项卡。“长度”选项卡还包含关于字符串长度的最大值、中值、平均值和最小值的统计数据。

变量—数字

Pandas 分析报告数字变量的结果

Pandas Profiling 提供了令人难以置信的对数字变量的深入分析,涵盖了分位数描述性统计。它返回数据集中的最小值最大值以及之间的范围。它显示四分位值,这些值通过将集合分成四个箱来测量数据集中有序值在中位数上方和下方的分布。当考虑四分位数值时,如果四分位数 1 和中位数与中位数和四分位数 3 之间的距离更大,那么我们将其解释为较小值比较大值的分散性更大。四分位数间距就是四分位数三减去四分位数一的结果。

标准差反映了数据集相对于其平均值的分布。较低的标准差意味着数据集中的值更接*平均值,而较高的标准差意味着数据集值分布在更大的范围内。变异系数,也称为相对标准差,是标准差与平均值的比值。峰度可用于通过测量相对于有序数据集均值的分布尾部的值来描述数据的形状。峰度值根据数据的分布和极端异常值的存在而变化。中位数绝对偏差是另一种统计方法,它反映了数据在中位数周围的分布,并且在出现极端异常值时,它是一种更为可靠的分布测量方法。偏斜度反映了标准钟形概率分布的失真程度。正偏度被认为是向右偏度,在分布的右侧有一个较长的尾部,而在左侧有一个负值。

互动和相互关系

熊猫概况报告中的交互图。

交互和相关性部分是 Pandas Profiling 真正领先于其他探索工具的地方。它将所有变量成对分析,并使用 Pearson、Spearman、Kendal 和 Phik 方法突出任何高度相关的变量。它提供了一个强大的、易于理解的可视化表示,可以显示任何紧密相关的数据。作为一名数据科学家,这是一个很好的起点,可以问为什么这些数据对可能相关。

缺少值

熊猫概况报告中的缺失值条形图

缺失值部分基于概述部分的缺失单元格指标。它直观地表示数据帧中所有列的缺失值出现的位置。这一部分可能会强调数据质量问题,并且可能需要将缺失的数据映射到一个缺省值,我们将在后面的文章中讨论这个问题。

样本部分

示例部分显示了数据集头部和尾部的结果快照。如果数据集是按特定列排序的,您可以使用这一部分来了解最小和最大列值所关联的记录类型。

摘要

Pandas Profiling 是一个令人难以置信的开源工具,每个数据科学家都应该考虑将其添加到任何项目的数据探索阶段的工具箱中。通过提供深入的描述性统计数据、可视化分布图和一套强大的关联工具,这是消化和分析不熟悉的数据集的有效方法。

感谢您花时间阅读我们的文章,我们希望您发现它有价值。

深度神经网络的学*过程

原文:https://towardsdatascience.com/learning-process-of-a-deep-neural-network-5a9768d7a651?source=collection_archive---------9-----------------------

人工神经网络是如何学*的?[更新版本]

(来源: https://torres.ai )

这是我两年前写系列的第五帖(帖 3帖 4 )的更新版。在这篇文章中,我将以 Keras为例,直观地展示神经网络学*过程的主要组成部分,Keras 已经成为 TensorFlow 的高级 API ,用于构建和训练深度学*模型。

最后,我们将通过一个名为 TensorFlow Playground 的交互工具来实践这里提出的一些概念。

神经网络的学*过程

神经网络由个神经元相互连接而成;与此同时,我们神经网络的每个连接都与一个权重相关联,该权重在乘以输入值时决定了这种关系在神经元中的重要性。

一个神经元可以被形象化为这张图(来源: https://torres.ai )

每个神经元都有一个激活函数,它定义了神经元的输出。激活函数用于在网络的建模能力中引入非线性。我们有几个激活函数的选项,我们将在本帖中展示。

(a)先前人工神经元的简化表示。(b)更简化的代表性。(来源: https://torres.ai )

根据之前的简化表示,我们可以将前一篇文章中提出的模型表示为将 MNIST 数字分类为:

(来源: https://torres.ai )

训练我们的神经网络,即学*我们的参数值(权重 wijbj 偏差)是深度学*最真实的部分,我们可以将神经网络中的这一学*过程视为神经元层的“往返”迭代过程。“去”是信息的前向传播,“回”是信息的后向传播。

第一阶段前向传播发生在网络暴露于训练数据时,这些数据穿过整个神经网络以计算它们的预测(标签)。也就是说,通过网络传递输入数据,使得所有神经元将它们的变换应用于它们从前一层神经元接收的信息,并将它发送到下一层神经元。当数据已经穿过所有层,并且其所有神经元已经进行了它们的计算时,将到达最后一层,具有那些输入示例的标签预测的结果。

接下来,我们将使用一个损失函数来估计损失(或误差),并比较和衡量我们的预测结果相对于正确结果的好坏程度(请记住,我们是在一个受监督的学*环境中,我们有一个标签来告诉我们期望值)。理想情况下,我们希望成本为零,也就是说,估计值和期望值之间没有偏差。因此,随着模型被训练,神经元互连的权重将被逐渐调整,直到获得良好的预测。

一旦计算出损失,该信息就被反向传播。因此,它的名字:反向传播。从输出层开始,损失信息传播到隐藏层中直接对输出做出贡献的所有神经元。然而,基于每个神经元对原始输出的相对贡献,隐藏层的神经元仅接收总损失信号的一部分。这个过程一层一层地重复,直到网络中的所有神经元都接收到描述它们对总损失的相对贡献的损失信号。

视觉上,我们可以用这个阶段的视觉方案来总结我们所解释的内容(基于我们神经网络的先前视觉表示):

(来源: https://torres.ai )

现在我们已经将这些信息传播回来,我们可以调整神经元之间连接的权重。我们正在做的是,在下次使用网络进行预测时,让损失尽可能接*于零。为此,我们将使用一种叫做梯度下降的技术。这种技术在损失函数的导数(或梯度)的计算的帮助下以小增量改变权重,这允许我们看到朝着全局最小值“下降”的方向;这通常是在我们在每次迭代中传递给网络的所有数据集的连续迭代(历元)中的成批数据中完成的。

概括地说,学*算法包括:

(来源: https://torres.ai )

  1. 从网络参数的值(通常是随机的)开始( wij 权重和 bj 偏差)。
  2. 取一组输入数据的例子,并通过网络传递它们以获得它们的预测。
  3. 将获得的这些预测值与预期标签值进行比较,并用它们计算损失。
  4. 执行反向传播,以便将这种损失传播到构成神经网络模型的每一个参数。
  5. 使用这种传播的信息来更新具有梯度下降的神经网络的参数,从而减少总损失并获得更好的模型。
  6. 继续迭代前面的步骤,直到我们认为我们有一个好的模型。

下面,我们将更详细地介绍我们在本节中强调的每个元素。

激活功能

记住,我们使用激活函数来向前传播神经元的输出。该输出由该神经元所连接的下一层的神经元接收(直到包括输出层)。正如我们已经说过的,激活函数用于在网络的建模能力中引入非线性。下面我们将列举现今使用最多的;都可以在一层 Keras 中使用(我们可以在他们的网站上找到更多信息)。

线性的

线性激活函数基本上是恒等函数,实际上,它意味着信号不变。

(来源: https://torres.ai )

乙状结肠的

sigmoid 函数已经在之前的文章中介绍过了。它的兴趣在于它允许减少有效数据中的极端或非典型值,而不消除它们:它将几乎无限范围的独立变量转换成 0 到 1 之间的简单概率。它的大部分输出将非常接* 0 或 1 的极端值。

(来源: https://torres.ai )

双曲正切

不赘述,我们可以总结一下,tanh 表示双曲正弦和双曲余弦的关系: tanh(x)=sinh(x)/cosh(x) 。与 sigmoid 函数不同,tanh 的归一化范围在-11 之间,这是一些神经网络的输入。tanh 的优点是负数更容易处理。

(来源: https://torres.ai )

Softmax

softmax 激活函数在之前的文章中也有介绍,用于推广逻辑回归,因为它可以包含多个决策限制,而不是二进制分类。正如我们所见,softmax 激活函数通常位于神经网络的输出层,并返回互斥输出类的概率分布。

热卢

激活函数整流线性单元(ReLU)是一种非常有趣的变换,如果输入高于某个阈值,它会激活单个节点。默认的和更常见的行为是,只要输入值小于零,输出就为零,但是当输入值大于零时,输出与输入变量成线性关系,形式为 f(x)=x 。ReLU 激活函数已经被证明在许多不同的情况下都有效,并且目前被广泛使用。

(来源: https://torres.ai )

反向传播组件

总之,我们可以认为反向传播是一种在正确方向上改变神经网络参数(权重和偏差)的方法。它首先通过计算损失项开始,然后考虑到这个计算的损失,用优化算法以相反的顺序调整神经网络的参数。

请记住,在 Keras 中, compile() 方法允许我们定义我们希望学*过程中涉及的组件如何:

model.compile(loss=’categorical_crossentropy’,
              optimizer=’sgd’,
              metrics=[‘accuracy’])

具体来说,在这个例子中,有三个参数被传递给这个方法:一个优化器、一个损失函数和一个度量列表。在像我们的例子这样的分类问题中,精确度被用作一种度量。让我们更深入地探讨一下这些论点。

损失函数

损失函数是量化特定神经网络在训练过程中有多接*理想权重所需的参数之一。

Keras 手册页中,我们可以找到所有可用的损失函数类型。有些有其具体的超参数,必须指出;在前一篇文章的例子中,当我们使用分类 _ 交叉熵作为损失的函数时,我们的输出必须是分类格式。损失的最佳函数的选择在于理解什么类型的误差对于特定的问题是可接受的或不可接受的。

优化者

优化器是 compile() 方法中需要的另一个参数。Keras 目前有不同的优化器可以使用: SGDRMSpropAdagradAdadeltaAdamAdamaxNadam 。你可以在 Keras 文档中找到更多关于它们的细节。

一般而言,我们可以将学*过程视为一个全局优化问题,其中参数(权重和偏差)必须以最小化上述损失函数的方式进行调整。在大多数情况下,这些参数无法解析求解,但一般来说,它们可以通过优化算法很好地逼*,例如上面提到的那些算法。

梯度下降

我们将解释其中一个具体的优化器,以便您理解优化器的整体操作。具体来说就是梯度下降,很多优化器的基础,也是机器学*和深度学*中最常见的优化算法之一。

当更新参数时,梯度下降使用损失函数的一阶导数(梯度)。记住梯度给出了函数在该点的斜率。在不能深入细节的情况下,该过程包括将每个隐藏层的损失的导数与其上层损失的导数链接起来,在计算中结合其激活函数(这就是为什么激活函数必须是可导的)。在每一次迭代中,一旦所有的神经元都具有对应于它们的损失函数的梯度值,参数值就以与梯度指示的方向相反的方向更新。事实上,梯度总是指向损失函数值增加的方向。因此,如果使用梯度的负值,我们可以得到我们倾向于减少损失函数的方向。

让我们以直观的方式来看这个过程,假设只有一维:假设这条线代表损失函数对于每个可能的参数值所取的值,并且梯度的负值由初始点中的箭头来表示:

(来源: https://torres.ai )

为了确定参数的下一个值,梯度下降算法将初始权重的值修改为与梯度相反的方向(因为它指向损失增加的方向,我们希望减少损失),并在此基础上增加一个比例量。这种变化的幅度由梯度值和我们可以指定的学*率超参数决定(我们将很快介绍)。因此,从概念上讲,就好像我们沿着斜坡向下走,直到我们到达局部最小值:

(来源: https://torres.ai )

梯度下降算法重复这个过程,越来越接*最小值,直到参数值达到一个点,超过这个点,损失函数不能减小:

(来源: https://torres.ai )

随机梯度下降

在前面的章节中,我们已经了解了参数值是如何调整的,但没有了解调整的频率:

  • 每个条目示例后?
  • 在每一轮的整套训练实例(epoch)之后?
  • 在训练集的例子样本之后?

在第一种情况下,我们称之为在线学*,即从每个训练实例的观察损失中估计梯度;当我们谈到随机梯度下降(SGD)时也是如此。第二种称为批量学*,称为批量梯度下降。文献表明,通常情况下,在线学*可以获得更好的结果,但有理由证明使用批量学*是正确的,因为许多优化技术只能使用批量学*。

但是,如果数据分布良好,其中的一小部分应该会给我们一个很好的梯度*似值。我们可能得不到最好的估计,但它更快,而且,考虑到我们正在迭代的事实,这种方法非常有用。出于这个原因,经常使用第三个选项,称为小批量。该选项通常与在线一样好,但是更新神经网络的参数需要较少的计算。此外,许多输入示例的梯度的同时计算可以使用矩阵运算来完成,这些运算可以通过 GPU 非常有效地实现,正如我们在之前的帖子中所看到的。

这就是为什么在现实中,许多应用使用随机梯度下降(SGD)和几个例子的迷你巴赫。要使用所有数据,需要做的是将数据分成几批。然后我们取第一批,通过网络,计算其损失的梯度并更新神经网络的参数;这将依次进行,直到最后一批。现在,在一次通过所有输入数据的过程中,只有一些步骤与批次数量相等。

SGD 在 Keras 中非常容易实现。在 compile() 方法中,指出优化器是 SGD(参数中的值 sgd ),然后必须做的就是在训练过程中用 fit() 方法指定批量大小,如下所示:

model.fit(X_train, y_train, epochs=5, batch_size=100)

在这个使用 fit() 方法的代码示例中,我们使用 batch_size 参数将数据分成 100 个一批。通过历元的数量,我们可以显示对所有数据执行该过程的次数。在本文的后面,当我们已经介绍了常用的优化器参数时,我们将回到这两个参数。

模型参数化

如果前一篇文章末尾的读者已经用我们在那里使用的超参数执行了一个模型,我假设该模型的准确性将超过 90%。这些结果好吗?我认为它们非常棒,因为这意味着读者已经用 Keras 编写并执行了他的第一个神经网络。恭喜你!

另一件事是,还有其他模型可以提高精确度。这取决于拥有丰富的知识和大量的实践来处理好我们可以改变的许多超参数。例如,通过简单改变第一层的激活函数,从s 形变为如下所示的 relu :

model.add(Dense(10, activation=’relu’, input_shape=(784,)))

我们可以在差不多相同的计算时间内获得 2%以上的精度。

也可以增加时期的数量,在一层中增加更多的神经元或者增加更多的层。然而,在这些情况下,准确性的提高具有增加学*过程的执行时间的副作用。例如,如果我们向中间层添加 512 个节点,而不是 10 个节点:

model.add(Dense(512, activation=’relu’, input_shape=(784,)))

我们可以用 summary() 方法检查,参数数量增加(是一个全连接)执行时间明显变高,甚至减少了历元数。利用该模型,准确率达到 94%。如果我们增加到 20 个历元,可以达到 96%的准确率。

简而言之,在下一节中,我们将更详细地了解一个无限可能的世界,读者可以意识到,鉴于我们拥有的多种可能性,找到激活函数的最佳参数和超参数的最佳架构需要一些专业知识和经验。

参数和超参数

到目前为止,为了简单起见,我们还没有明确注意区分参数和超参数,但是我认为现在是时候了。通常,我们将模型的参数视为模型内部的配置变量,其值可以根据数据进行估计。相比之下,超参数指的是模型本身外部的配置变量,其值通常无法从数据中估计,并由程序员指定以调整学*算法。

当我说深度学*更像是一门艺术而不是一门科学时,我的意思是找到这些超参数的最优值需要大量的经验和直觉,这些最优值必须在开始训练过程之前指定,以便模型训练得更好更快。鉴于本书的介绍性质,我们不会详细介绍所有这些参数,但我们有值得简要提及的超参数,包括神经网络的结构和拓扑水平(层数、神经元数、它们的激活函数等)。)和学*算法级别(学*速率、动量、时期、批量大小等)。).

接下来,我们将介绍其中一些,其余的将在我们进入卷积神经网络时出现在 futuro 帖子中。

纪元

正如我们已经做的,epochs 告诉我们在训练过程中所有训练数据通过神经网络的次数。一个很好的线索是增加历元的数量,直到验证数据的准确性度量开始降低,即使训练数据的准确性继续增加(这是当我们检测到潜在的过度拟合时)。

批量

正如我们之前说过的,我们可以将训练数据划分为小批量,以便通过网络传递它们。在 Keras 中, batch_size 是指示这些批的大小的参数,这些批将在训练的迭代中的 fit() 方法中使用,以更新梯度。最佳大小取决于许多因素,包括我们用来计算的计算机的内存容量。

学*率

梯度向量有方向和大小。梯度下降算法将梯度的大小乘以一个称为学*率(有时也称为步长)的标量,以确定下一个点。

以更正式的方式,反向传播算法计算误差相对于每个权重如何变化:

为了使用简单的更新规则来更新网络的每个权重:

其中,α是学*率。

例如,如果梯度的大小为 1.5,学*率为 0.01,那么梯度下降算法将选择距离前一点 0.015 的下一点。

这个超参数的适当值非常依赖于所讨论的问题,但是一般来说,如果这个值太大,那么就要迈出巨大的步伐,这有利于在学*过程中走得更快。但在这种情况下,我们可能会跳过最小值,使学*过程难以停止,因为当搜索下一点时,它会永远随机地在“井”的底部跳动。在该图中,我们可以直观地看到可能发生的影响,其中从未达到最小值(在图中用小箭头表示):

(来源: https://torres.ai )

相反,如果学*率很小,将会取得很小的进步,有更好的机会达到局部最小值,但是这会导致学*过程非常慢。一般来说,如果我们的学*模式不起作用,一个好的规则是降低学*速度。如果我们知道损失函数的梯度很小,那么测试它用学*率补偿梯度是安全的。

学*率衰减

但是一般来说,最好的学*速率是随着模型接*一个解而降低的速率。为了实现这种效果,我们有另一个超参数,学*率衰减,它用于随着时代的推移降低学*率,以允许学*在开始时以更大的学*率更快地前进。随着进展,进行越来越小的调整,以促进训练过程收敛到损失函数的最小值。

动力

在我们已经解释的下降梯度算法的可视例子中,为了最小化损失函数,我们保证找到全局最小值,因为没有局部最小值,优化过程会被卡住。然而,在现实中,真实情况更加复杂,从视觉上看,我们似乎可以找到几个局部最小值,损失函数的形式如下图所示:

(来源: https://torres.ai )

在这种情况下,优化器很容易陷入局部最小值,并且算法可能认为已经达到了全局最小值,从而导致次优结果。原因是当我们卡住的时候,梯度是零,我们不再能严格地沿着梯度的路径走出局部最小值。

解决这种情况的一种方法可以是从不同的随机位置重新开始该过程,并且以这种方式增加达到全局最小值的概率。

为了避免这种情况,通常使用的另一种解决方案涉及动量超参数。以一种直观的方式,我们可以看到,如果要前进,它将采取前面步骤的加权平均来获得一点动力,并克服“颠簸”,作为一种不陷入局部最小值的方法。如果我们认为以前的平均值更好,也许这将允许我们进行跳跃。

但是使用平均值已经被证明是一个非常激烈的解决方案,因为,也许在前面步骤的梯度中,它比仅仅在前面步骤中更不相关。这就是为什么我们选择加权先前的梯度,并且动量是用于该加权的 0 和 1 之间的常数。已经表明,使用动量的算法在实践中效果更好。

一种变体是内斯特罗夫动量,这是最*流行的动量更新的稍微不同的版本,当它接*解决方案时,它基本上减慢梯度。

参数权重的初始化

参数权重的初始化并不完全是一个超参数,但它与其中任何一个参数一样重要,这就是我们在本节中做一个简短段落的原因。建议用小的随机值初始化权重,以打破不同神经元之间的对称性,如果两个神经元具有完全相同的权重,则它们将总是具有相同的梯度;这假设两者在随后的迭代中具有相同的值,因此它们将不能学*不同的特征。

按照标准正态分布随机初始化参数是正确的,但它可能会导致渐变消失(当渐变的值太小而模型停止学*或因此花费太长时间时)或渐变爆炸(当算法为权重分配过高的重要性时)的问题。

一般来说,考虑到我们的网络具有的激活功能的类型,可以使用试探法。深入这些细节超出了本书的介绍范围,但是,如果读者想要更深入,我建议你访问斯坦福 Andrej Karpathy 的 CS231n 课程网站,在那里你将获得这一领域非常有价值的知识,这些知识以一种非常说教的方式展现出来。

Keras 中超参数和优化器

我们如何指定这些超参数?回想一下,优化器是模型的 compile() 方法中需要的参数之一。到目前为止,我们都是通过它们的名字来调用它们(用一个简单的字符串来标识它们),但是 Keras 也允许将优化器类的一个实例作为一个参数来传递,并指定一些超参数。

例如,随机梯度下降优化器允许使用动量学*率衰减内斯特罗夫动量超参数:

keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0,      
                     nesterov=False)

上一个方法的参数中指示的值是默认采用的值,其范围可以是:

  • lr:浮点> = 0。(学*率)
  • 动量:浮点> = 0
  • 衰减:浮点> = 0(学*率衰减)。
  • nesterov: boolean(表示是否使用内斯特罗夫动量)。

正如我们已经说过的,Keras 中有几个优化器,读者可以在他们的文档页面上探索。

张量流游乐场

TensorFlow Playground 是一个用 JavaScript 编写的交互式可视化 web 应用程序,允许我们模拟在浏览器中运行的简单神经网络,并实时查看结果:

使用该工具,我们可以试验不同的超参数,并观察它们的行为。事实上,神经网络中超参数所提供的灵活性是它的优点之一,同时也是它的缺点之一,对于那些刚开始学*这个主题的人来说:有许多参数需要调整!

二元分类问题

为了开始理解这个工具是如何工作的,我们可以使用前一篇文章中提出的第一个感知器的例子,一个简单的分类问题。

从这个例子开始,我们选择了上图中“数据”部分所示的数据集,然后单击“播放”按钮。现在我们可以看到 TensorFlow Playground 是如何解决这个特殊问题的。蓝色和橙色区域之间的线开始慢慢移动。你可以按下“重置”按钮,重新测试几次,看看这条线在不同初始值下是如何移动的。

在这种情况下,应用程序会尝试找到允许正确分类这些点的参数的最佳值。如果将光标放在弧上,读者将看到分配给每个参数的值出现(甚至允许我们编辑它):

请记住,当这个权重乘以输入值时,它决定了神经元中这种关系的重要性。

在第一次接触之后,我们将展示一点工具,让我们了解神经网络如何运作。在菜单的上半部分,我们基本上找到了超参数,其中一些我们已经在上一节中评论过:纪元、学*率、激活、正则化率和问题类型。它们都是下拉菜单,我们可以在其中选择这些超参数的值。

在“问题类型”选项卡中,平台允许我们指定两种类型的问题:回归(连续问题)和分类。总的来说,我们可以选择四种类型的数据用于分类,两种类型的数据用于回归:

蓝色和橙色的点构成了数据集。橙色点的值为-1,蓝色点的值为+1。在左侧,在数据类型下面,有不同的参数,我们可以修改这些参数来调整我们的输入数据。

使用“训练与测试数据的比率”选项卡,我们可以控制分配给训练集的数据百分比(如果我们修改它,我们会看到屏幕右侧“输出”中出现的点是如何交互变化的)。数据的噪声水平也可以由“噪声”字段定义和控制;随着噪声的增加,数据模式变得更加不规则。正如我们可以体验到的,当噪声为零时,问题数据在它们的区域中被清楚地区分。但是当达到 50 以上的时候,我们可以看到蓝点和橙点是混在一起的,所以分类起来非常困难。

顾名思义,通过“批量大小”,我们可以确定每个训练批次将使用的数据量。

然后,在下一个专栏中,我们可以选择特性。我建议我们使用“X1”和“X2”这两个可用的词:“X1”是水平轴上的值,“X2”是垂直轴上的值。

神经元网络的拓扑可以在下面的列中定义。我们最多可以有六个隐藏层(通过点击“+”号来添加隐藏层),每个隐藏层最多可以有八个神经元(通过点击相应层的“+”号):

最后,请记住,在训练神经网络时,我们希望最小化“训练损失”,然后将其与测试数据进行比较,“测试损失”也会最小化。在屏幕的右上部分,在一个小图中交互地显示了每个时期中两个度量的变化,其中,如果损失减少,曲线向下。损失测试用黑色画,训练损失用灰色画。

超参数设置基础

用单个神经元分类

现在我们对这个工具有了更多的了解,让我们回到第一个分类示例,它将数据分成两组(聚类)。

我建议我们在前进之前修改一些参数来使用该工具进行练*。例如,我们可以用 0.03 的学*率和一个 ReLU 激活函数来修改一些参数(正则化将不被使用,因为它超出了本书的范围)。

我们将问题保持为分类,并且我建议我们将“训练与测试的比率”设为数据的 50%,并且我们还将“噪声”参数保持为零,以促进解决方案的可视化(尽管我建议稍后您自己练*)。我们可以将“批量大小”保留为 10。

和以前一样,我们将使用“X1”和“X2”作为输入。我建议从单个神经元的单个隐藏层开始。我们可以通过使用“-”或“+”按钮来实现:

在右上方,我们看到“测试损失”和“训练损失”的初始值很高(读者可以得到不同的值,因为初始值是以随机方式生成的)。但是在按下“播放”按钮之后,可以看到“训练损失”和“测试损失”都以非常低的比率收敛,并且保持不变。此外,在这种情况下,黑色和灰色的两条线完全重叠。

用多于一个神经元分类

让我们选择另一组类似于附图中的起始数据:

我们现在想把两个数据集分开:橙色的必须归入一组,蓝色的归入另一组。但问题是,在这种情况下,他们将有一个圆形,橙色点将在外圆,蓝色点将在内。现在,这些点不能像以前那样用一条线分开。如果我们用具有单个神经元的隐藏层作为先前分类的模型进行训练,那么在这种情况下分类将会失败。

我建议我们用隐藏层的多个神经元进行测试。例如,尝试两个神经元:你会发现你还没有调够。我建议你试着用三个。你会看到,最终,你可以得到一个好得多的训练和测试损失:

让我们看看左边的另一个数据集,其中的数据被分成四个不同的正方形区域。现在,这个问题无法用以前的网络解决,但我建议您尝试一下:

可以看出,我们不能得到一个好的分类(虽然在某些情况下,可能发生只有 3 个神经元的情况,因为初始化是随机的,但是如果你做几次测试,你会发现这在一般情况下是不能实现的)。然而,如果我们有 5 个神经元,如下图所示,读者可以看到该神经网络如何获得这种情况下的良好分类:

多层分类

现在,我们将尝试使用该工具中最复杂的模式对数据集进行分类。橙色和蓝色数据点的漩涡结构是一个具有挑战性的问题。如果我们依赖前面的网络,我们看到甚至没有 8 个神经元,工具留给我们的最大值,我们得到一个好的分类结果:

如果读者已经尝试过,在这种情况下,我想你会得到一些测试损失的好值。是时候多放几层了;我向您保证,如果您使用该工具允许的所有层,您将得到它:

但是你会看到,很明显,学*参数的过程需要很长时间。

实际上,用更少的层或神经元你可以得到好的结果;我要求你自己玩一点,比如改变激活函数来得到一个更简单的模型。您还可以考虑测试任何其他参数。

这个工具只考虑密集的神经网络;稍后我们将看到卷积神经网络(和递归神经网络)呈现更复杂的困境。但只有在这些密集的网络中,我们才能看到最难调整的超参数之一是决定模型有多少层以及每层有多少神经元。

在隐藏层中使用非常少的神经元将导致所谓的欠拟合,即缺乏模型拟合,因为隐藏层中只有非常少的神经元来正确检测复杂数据集中的信号。

另一方面,在隐藏层中使用太多的神经元会导致几个问题。首先,它会产生过拟合,当神经网络具有如此大的信息处理能力,以至于训练集中包含的有限信息量不足以训练隐藏层中的所有神经元时,就会发生过拟合。但另一方面,隐藏层中的大量神经元会增加训练网络所需的时间,以至于无法在必要的时间内正确训练神经网络。

显然,我们必须在隐藏层中太多和太少的神经元之间达成妥协,这就是为什么我已经评论说,我们面临的挑战需要更多的艺术而不是科学。

我希望这篇文章对你有所帮助,你会在工作或大学中用到它们。你可以在这里阅读下一篇关于卷积神经网络的文章

** [## 卷积神经网络初学者使用 Keras 和 TensorFlow 2

边做边学:包含 GitHub 代码的实用指南

towardsdatascience.com](/convolutional-neural-networks-for-beginners-using-keras-and-tensorflow-2-c578f7b3bf25)**

通过探索和可视化 Google App 数据学* PySpark

原文:https://towardsdatascience.com/learning-pyspark-by-exploring-and-visualizing-google-app-data-60cfecacc701?source=collection_archive---------15-----------------------

帮助你将熊猫技能移植到 PySpark 的实用指南

Rami Al-zayat 在 Unsplash 上拍摄的照片

Apache Spark 是每个人在处理大数据时都应该知道的不可或缺的数据处理框架。当我们试图对大数据进行数据分析时,我们可能会遇到一个问题,即由于单台计算机的处理能力和内存资源有限,您当前的计算机无法满足处理大数据的需求。虽然我们可以尝试升级我们的计算机以满足大数据处理的需要,但我们很快就会发现,当处理不断增加的数据集时,计算机可以轻松地再次达到其最大容量。

解决这个问题的一个方法是将我们的大数据提取到一个分布式并行处理平台,该平台由一个计算机集群支持,而不是依赖于单个机器。这就是 Apache Spark 在大数据处理中发挥作用的地方。

" Apache Spark 基本上是一个统一的分析引擎,用于并行和批处理系统中的大规模数据处理。" ( 来源)。

Apache Spark 最初是用 Scala 语言编写的,但它也提供了 Python API,即 PySpark 。PySpark 的发布简化了数据科学社区的工作,他们深深扎根于 Python 编程,利用 Apache Spark 的强大功能,而无需学*另一种编程语言,如 Scala。人们可以只编写 Python 脚本来访问 Apache Spark 提供的功能,并对大数据执行数据探索性分析。

照片由 Christina MorilloPexels 拍摄

此外,学* PySpark 并不是一项艰巨的任务,尤其是如果您已经在现有的数据分析工作中使用了 Pandas 一段时间。Spark 提供了一个与熊猫数据帧非常相似的数据帧数据结构。

在本文中,我将通过一个例子来说明我们如何在一个表示为 Spark Dataframe 的 Google App 数据集上执行数据探索和可视化。

数据集

我们将要使用的样本数据集可以从 Kaggle 下载。网站上有两个 csv 文件,我们将只使用其中的一个,即“ googleplaystore.csv ”。数据集是关于谷歌 Play 商店应用程序的,其中包含应用程序名称、类别、评级、价格等信息。

想象一下,如果你打算开发一个移动应用程序,并希望在应用程序开发之前了解更多关于市场趋势的信息,探索这个数据集可能是有用的。

分布式计算平台

我们将需要一个分布式计算平台来托管我们的数据集,并使用 PySpark 处理它。在早期,建立一个分布式计算平台是一项非常复杂和艰巨的任务。

幸运的是,由于云服务的存在,整个设置过程已经大大简化为点击几个按钮。我们将在这里使用云服务之一,即 数据块 。我们将通过 Databricks 建立一个分布式计算环境,以完成本文中介绍的数据探索任务。

设置数据块

第一步:拜访https://databricks.com/

Databricks 网站

第二步:注册一个 Databricks 账户。只需点击右上角的“尝试数据块”。我们将被重定向到一个页面,在那里我们可以继续填写我们的详细信息以注册帐户。

数据块注册页面

第三步:完成注册后,登录社区版。只需点击“在此签名”的小链接。

数据块登录页面

Databricks 提供完全免费的社区版。社区版为我们提供了一个具有 15.3 GB 内存、2 个内核和 1 个 DBU 的集群。这对于学*和实验目的是足够的。

但是,请注意Community Edition 集群将在空闲两小时后自动终止。这意味着我们必须不时地在数据块中重新构建一个新的集群。

(不要担心,在 Databricks 中重建新集群只需点击几下按钮,即可在 1 分钟内完成)。

第四步:建立一个集群。在 Databricks 的主页中,从左侧的面板中选择“集群”。

导航至集群设置页面

接下来,填写下一页中的“集群名称”字段。我们可以根据自己的喜好提供一个集群名。

数据块创建集群页

等待大约 2-3 分钟,然后 Databricks 将集群分配给我们。

数据块簇列表

第五步:上传数据集。从左侧面板中选择“数据”。

导航至添加数据页面

点击“添加数据”。

我们可以选择删除 Kaggle 数据集,或者浏览我们的目录来上传数据集。

将数据上传到数据块

第 6 步:从 Databricks 主页创建一个空白笔记本。为我们的笔记本命名。

在数据块中创建笔记本

新笔记本将自动连接到我们在上一步中刚刚创建的集群。

将群集连接到笔记本电脑

只需点击几下按钮,我们就可以在 Databricks 中建立一个分布式计算平台,并将数据上传到平台上。此外,我们还创建了一个笔记本,我们可以在其中编写 Python 脚本来执行数据分析工作。PySpark 已经内置在笔记本中,这里不需要进一步安装框架。

(请注意 Databricks 中的笔记本,就像我们常用的 Jupyter 笔记本一样,它提供了一个交互式编程接口来编写我们的脚本并可视化输出)

我们现在已经准备好使用 PySpark 开始我们的数据探索之旅。

探索谷歌应用数据

在本节中,我们将开始在 Databricks 笔记本中编写 Python 脚本,以使用 PySpark 执行探索性数据分析。这一节将被分成七个部分,同时还将介绍一些常见的 PySpark 方法。

您可以通过此 链接 访问在线版笔记本,或者您也可以从我的Github下载离线版笔记本。

1 部分:导入库

第一步从导入必备的库/模块开始。

用于导入库的 Python 脚本

1–5 行:

  • 导入本文介绍的数据探索任务所需的所有 PySpark 模块。

第 7 行:

  • PySpark 需要一个 SQLContext 来启动 Spark SQL 的功能。Spark SQL 是用于处理结构化数据的 Spark 模块之一。在后面的阶段,我们将使用它从我们的数据集执行数据查询。
  • 关键字“ sc ”表示 SparkContext。SparkContext 表示到 Spark 集群的连接,被认为是 Spark 功能的主要入口点。

2 部分:读取文件并计算记录的总行数

接下来,我们从外部来源(在本例中是一个 CSV 文件)获取数据。

读取文件和计算总行数的 Python 脚本

第一行:

  • 在 PySpark 中,我们使用 SQLContext 模块中的 read.csv 方法从前面步骤中上传到 Databricks 的数据中读取 csv 文件。请注意,默认情况下,csv 文件存储在 Databricks 中的“FileStore/tables”目录下。
  • read.csv 方法返回一个 Spark 数据帧,并将其赋给变量 df_spark 。Spark 数据帧类似于熊猫数据帧。

第二行:

  • PySpark 使用 count 方法获取从 csv 文件中读取的记录的行数。

记录的总行数

第 3 部分:检查数据

一旦我们从 CSV 文件中读取了原始数据,我们可能会有兴趣通过快速浏览一些记录来了解数据集的一些基本细节。

3.1 显示列细节

打印列详细信息的 Python 脚本

  • printSchema 方法显示每一列的数据类型,也显示一列是否可以为空。此时,我们可以观察到所有的列都是字符串并且可以为空。

列详细信息

3.2 显示前几行记录

显示前五行记录的 Python 脚本

  • 显示 的方法是显示前几行记录。我们可以灵活地向 show 方法传递不同的值,以调整我们想要显示的行数。

前五行记录

3.3 显示特定列

显示特定列的 Python 脚本

  • 我们也可以使用“方法与“ show ”方法连锁,只显示某些指定的列,而不是显示所有的列。

选定列的前五行

第 4 部分:数据争论

乍一看从 CSV 文件中读取的原始数据,我们可能会注意到几个问题:

  • 由于所有列都可以为空,因此某些列中可能存在空值或缺失值。空值或缺失值会导致分析错误。
  • 所有的列都是字符串。当我们希望使用数据进行统计分析或绘制图表时,这将带来问题。
  • 此外,一些列没有以允许数值分析的格式呈现。例如,“尺寸栏中的值在数字后附加一个字母“M”。“安装列的值与逗号和加号字符混合。“价格”值前面也有“$”字符。

一些错误数据格式的例子

这里需要数据清理和转换,以便于数据访问和分析。

4.1 删除空值

在删除空值之前,我们需要确定可以找到空值的列。

Python 脚本显示每列中的空值

  • 上面的代码检查每一列是否存在空值,并计算其频率,然后以如下表格格式显示出来。

每列中存在大量的空值

输出显示“内容分级”、“当前版本”和“ Android 版本”列中有一个空值。接下来我们将使用 dropna 方法从列中删除空值。

移除空值的 Python 脚本

4.2 删除不需要的字符

在 PySpark 中,我们可以将指定列中的数据转换成对我们有用的格式。为此,我们可以用 翻译 的方法。

移除不需要的字符的 Python 脚本

1–3 行:

  • withColumn 的方法是指定我们要转换的列(如 SizeInstallsPrice )
  • 翻译 的方法是用目标字符替换字符模式。例如,translate('Size ',' Mk ','')会将' Size '列中的所有字符' M '或' k '替换为空字符串' '。这意味着附加了大小值的所有字符“M”或“k”都将被删除。采用类似的方法,从安装列中去掉“+”或“,”并从价格列中去掉“$”。

第 5 行:

  • 数据转换后再次显示前五条记录。

转换数据的样本

4.3 过滤不需要的值

此时,我们已经成功地从“大小”列中删除了不想要的字符“M”或“k”。然而,还有一个问题。该栏中存在值随设备变化。这是因为一些应用程序的大小会因设备而异。这样的字符串值与列中的其余值(数值)不一致,因此我们必须删除它们。

移除不需要的值的 Python 脚本

  • 要从一列中过滤出一个特定的值,我们可以使用 where 方法来设置一个过滤条件,其中只有指定列的值(例如" Size ")满足特定的条件(例如!= "随设备变化")将被选择并将其分配回 df_spark。
  • 这种方法将筛选出所有大小值等于“因设备而异”的记录。

4.4 改变列的数据类型

请记住,即使我们已经完成了上面的数据清理和转换步骤,所有的列仍然是字符串格式。我们必须将一些列从字符串转换成数值。

用于更改列的数据类型的 Python 脚本

1–4 行:

  • 我们再次使用 列来设置我们将要使用的特定列。接下来,我们使用 cast 方法来设置一个特定的数据类型( IntegerTypeFloatType ),我们打算将字符串转换为该数据类型。

第 5 行:

  • 再次使用 printSchema 显示每一列中更新的数据类型。

更新的数据类型

4.5 重命名列

现在,我们可以对刚刚转换了值的列进行重命名,以反映这些更改。

用于重命名列的 Python 脚本

1–3 行:

  • 要重命名一个列,我们可以用 的方法来重命名。这个方法有两个参数,1)原始列名和 2)新列名。

第 4 行:

  • 显示记录的前五行,以查看列名的变化。

重命名的列

4.6 删除不需要的列

并非所有的列都与这里的研究相关,我们可以删除那些不相关的列。

删除列的 Python 脚本

  • 删除列很简单。只需使用 drop 方法,并将目标列名(例如评论、流派&当前版本)作为参数传递给该方法。

删除所选列后的数据帧

第五部分:查询数据

最后,我们设法以一种可用的格式获得了一个干净的数据,现在我们准备更深入地研究我们的数据。在本部分中,我们将使用 过滤 的方法,根据不同类型的条件进行数据查询。

5.1 单条件查询

一般来说,我们可以在 filter 方法中设置一个条件,这将返回所有符合条件的记录。让我们看看下面的例子:

用于搜索青少年专用应用程序的 Python 脚本

  • 这个查询是为了搜索青少年专用的应用程序。

过滤记录

用于搜索评分高于 4.2 的应用程序的 Python 脚本

  • 上面的查询是为了搜索“”评分大于 4.2 的记录。

过滤记录

5.2 按值范围查询

PySpark 提供了一个方法,之间,使我们能够搜索一个下限和一个上限之间的记录。**

按值范围搜索的 Python 脚本

  • 上面的代码返回“价格”在 1 美元到 3 美元之间的记录。**

过滤记录

5.3 关键字查询

也可以根据特定列中存在的某些特定关键字来搜索记录。我们可以通过三种方法之一来实现: startswithendswith包含 。下面我们来看几个例子:

****5.3.1开始

使用 startswith 查询数据的 Python 脚本

  • 上面的 startswith 方法返回以“4”开头的“ Android Ver 的记录。这意味着只有运行在 Android 4 上的应用程序的记录才会被返回。

过滤记录

5.3.2 端盖

使用 endswith 查询数据的 Python 脚本

  • 上面的 endswith 方法返回“ Last Updated ”结束于“2018”的记录。这意味着只会返回该应用程序在 2018 年最后更新的记录。

过滤记录

5.3.3 包含

使用包含来查询数据的 Python 脚本

  • 上面的 包含 方法返回的记录中带有 App 包含关键字“照片”。这意味着只会返回名称中包含“照片”关键字的应用程序的记录。

过滤记录

5.4 多条件查询

我们可以在数据查询中使用逻辑运算符,如 &、|、~ 来连接多个搜索条件。

使用逻辑运算符连接多个搜索条件进行查询的 Python 脚本

  • 上面的代码使用了 & 运算符来连接三个搜索条件,以便只返回属于游戏类别并且最后更新年份是 2018 年并且运行在上面的 Android 5 上的 app 的记录。

过滤记录

第 6 部分:描述性统计

我们可以使用 py sparkdescribe方法轻松地对我们的数据集进行快速描述性统计研究。

用于计算描述性统计数据的 Python 脚本

  • 在单行代码中, describe 方法显示了每一列的描述性统计摘要。

描述性统计概要

第 7 部分:数据可视化

我们将进入一个有趣的部分,我们将看到 PySpark 如何提供一些非常用户友好的特性,使用户能够创建不同类型的图表来可视化他们的数据。

在本部分中,我们将使用 PySparkdisplay函数绘制一些图表,以解决一些与 app 开发相关的问题。下面我们来看一些例子。

7.1 饼状图

假设我们想知道哪一类应用程序的市场份额最高。一个简单的解决方案是创建一个饼图,按类别显示安装总数。从那里,我们可以很容易地确定最主要的应用类别。

用于聚合数据和生成图表的 Python 脚本

第一行:

  • 我们使用 groupby 将我们的数据按“类别分组,然后使用 agg 方法应用“ sum ”函数来计算每个类别的安装总数。聚合结果将作为新的数据帧返回,并赋给变量 df_cat_sum

第二行:

  • 我们将 df_cat_sum dataframe 传递给 display 函数。当我们运行上面的代码时,我们将首先看到数据帧以如下表格格式显示:

列入总汇表的数据

  • 如果我们看一下表格的底部,我们会看到有一个下拉列表。当我们点击它时,我们会看到有几个内置的图,我们可以选择来呈现我们的数据。

图的下拉列表

  • 让我们选择“饼图,我们将看到一个饼图正在生成。

(默认情况下,图表的原始大小可能非常小。我们可以通过拖动图表右下角来放大图像来调整大小。)

圆形分格统计图表

从饼状图中可以明显看出,游戏几乎占据了应用程序市场的一半,与其他游戏相比,其市场份额最高。

如上所示,我们不需要编写额外的代码来生成绘图。相反,我们可以使用 显示 功能来处理我们的数据帧,并从下拉列表中选择一个绘图选项来显示我们的数据。

7.2 直方图

另一个问题可能会引起我们的兴趣:应用程序的大小会影响安装率吗?

我们可以预测,用户通常更喜欢轻量级应用程序,它消耗的移动设备存储资源更少。让我们通过绘制直方图来验证它。

用于聚合数据和生成图表的 Python 脚本

  • 上面给出的两行代码类似于 7.1 节中的代码,只是我们试图按大小对整个安装进行分组。
  • 对于这一轮,我们将从下拉列表中选择“直方图”。

从下拉列表中选择直方图

  • 接下来,单击下拉列表旁边的另一个按钮“绘图选项”。

PySpark 绘图选项

  • 将弹出一个定制绘图向导。将“尺寸(M) ”拖至数值字段,点击右下角的“应用”按钮。

自定义绘图向导

  • 我们将看到一个直方图生成如下。

柱状图

从柱状图来看,小于 50 兆的应用最受社区欢迎。超过 100 兆字节的大小往往会驱使一大群用户远离使用它。

7.3 条形图

在开发应用程序时,我们倾向于确保我们的应用程序能够覆盖尽可能大的社区群体。我们应用的接受度高度依赖于能够支持我们应用的 Android 版本。

这就是为什么对当前最广泛支持的 Android 平台的调查非常有助于我们做出更好的决定,为我们的应用程序设置最低操作系统平台。为此,我们可以选择绘制一个条形图,显示不同 Android 版本支持的应用程序的出现次数(最低级别)。

用于计算出现次数并生成图表的 Python 脚本

  • 在上面的代码中,我们使用 count 方法来获得每个应用程序的出现次数,这些应用程序按其支持的最低 Android 版本分组。我们还尝试按降序对结果进行排序。
  • 从图的下拉列表中,选择“条形图”图表。

从下拉列表中选择栏

  • 单击“绘图选项打开“自定义绘图”向导,然后确保我们将“ Android Ver ”拖至系列分组字段,并将“ count ”拖至值字段。最后,单击“应用”按钮。

自定义绘图向导

  • 最后,我们将看到一个条形图生成如下。

条形图

从上面的条形图中,我们了解到 Android 版本 4.1、4.0.3、4.0 和 4.4(最低级别)支持大多数当前应用程序。因此,如果我们打算瞄准更大的市场,明智的做法是让我们的应用程序得到 Android 版本 4 及更高版本的支持。

7.4 堆积条形图

现在,我们希望为我们的应用程序设定一个合理的价格。虽然定价在很大程度上取决于开发和维护成本,但另一个值得考虑的重要因素是用户的承受能力。高昂的价格标签会阻止许多用户使用我们的应用程序,即使我们的应用程序开发和维护得很好。

在这里,我们创建了一个堆积条形图,向我们展示不同用户群的支付能力的一些线索。

仅选择付费应用程序并生成图表的 Python 脚本

  • 在上面的代码中,我们使用 filter 方法只选择那些付费应用的记录,返回的数据帧被赋给一个变量df _ app _ payed
  • 从图的下拉列表中,再次选择“图”。

选择栏选项

  • 单击“绘图选项”打开“自定义绘图”向导,然后确保我们将“内容分级”拖到“关键字”字段,“价格($) ”拖到“系列分组”字段,“T24”安装(+) ”拖到“值”字段。确保选中“堆叠”单选按钮。最后,单击“应用”按钮。

自定义绘图向导

  • 我们将看到一个堆积条形图生成如下。

堆积条形图

显然,0.99 美元的价格标签最广泛地被所有年龄组接受。10 美元以上的价格标签很难获得显著的公共市场份额。

7.5 盒图

最后,我们还有一个问题:应用程序的价格会影响应用程序的评级吗?如果用户付费多了,会不会对 app 寄予更高的期望?

为了解决这个问题,让我们创建一系列的方框图。

基于类别和评级选择记录并绘制图表的 Python 脚本

  • 我们只是通过使用逻辑操作符来应用上一节中介绍的类似步骤&选择属于游戏类别和评级为 5 或更低的记录(这个条件是必需的,因为评级列中有一些异常)。我们还根据评级对过滤后的记录进行降序排序,然后将数据帧赋回变量df _ app _ payed
  • 从图的下拉列表中,选择“方框图”。

选择“方框图”

  • 单击“绘图选项”以打开“自定义绘图”向导,然后确保我们将“评级”拖至 Keys 字段,并将“价格($) ”拖至 Values 字段。最后,单击“应用”按钮。

自定义绘图向导

  • 一系列评级的箱线图如下所示。

箱线图

箱线图没有显示出明显的模式,即中值价格越高,评级越低,反之亦然。价格为 0.99 美元的应用程序可以获得 3.4 到 5 的评级。

结论

在本文中,我们看到了如何使用 PySpark 在分布式计算环境中执行数据探索和可视化。如果您熟悉 Pandas Dataframe,您可以很容易地适应 PySpark Dataframe,因为除了语法上的一些细微差别之外,它们之间有许多相似之处。然而,了解 Pandas 不是为并行处理而设计的,而是基于单线程操作,这一点很重要。因此,Pandas 并不是在大数据环境中处理大量数据集的理想选择。另一方面,PySpark 还提供了一种非常用户友好的方式来从它的数据帧中绘制一些基本的图形。基本上,数据可视化工作可以通过如上所述的图形用户界面来完成。

值得一提的是,还有很多 PySpark 特性没有在本文中讨论,其中两个是弹性分布式数据集(RDD)** 和 Spark MLlib ,它们太宽泛了,无法在一篇文章中涵盖。我在这里的目的是通过主要关注 PySpark 的数据框架来介绍 PySpark,我希望这可以帮助那些已经熟悉 Pandas 的人将数据技能迁移到 py spark。**

我希望你喜欢这篇文章并从中受益。

参考

  1. http://spark.apache.org/
  2. https://databricks.com/

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-1-7fda6662276?source=collection_archive---------37-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

Python,IPython,Jupyter lab 是什么?

这是一个系列的 10 分钟 Python 短文,帮助你开始学* Python。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您想了解关于 Python 特定主题的问题或请求,请随时通过 LinkedIn联系我。

根据 PYPL(编程语言的流行程度),Python 是目前最流行的编程语言。这是有充分理由的,因为它是为通用快速编程而设计的,可读性是核心规则。许多成功的公司,如 Reddit 和 Dropbox,都是围绕 Python 建立的。虽然易学从来就不是设计目标,但许多人都这样描述,很可能是因为 Python 社区非常欢迎初学者。

从主网站来看,Python 自称是一种解释的、面向对象的、具有动态语义的高级编程语言。它被解释,因此,不需要编译步骤,减少了编辑-测试-调试周期的时间。这种语言不仅支持面向对象的编程(函数式编程也很好),而且在 Python 中一切都由一个对象表示。高级别意味着您不必担心低级别的系统细节,如内存分配和垃圾收集。Python 是动态类型的,这意味着变量是对对象的引用(或标签),它们可以在运行时自由改变。对于像 C 这样的静态类型语言来说,情况就不一样了,在 C 语言中,变量类型必须在编译时声明。

我可以想象这些通用的设计规则目前很难掌握,但随着时间和更多的经验,它最终会变得清晰,我保证!我一般建议人们记住的是,Python 被设计得非常简单。我不止一次惊讶于简单的 Python 如何解决一些问题。如果您想快速掌握 Python,您必须亲自动手编写代码。

要开始使用 Python,需要安装一个版本(Mac 和很多 Linux 发行版上已经有预装版本)。虽然最直接的方法是去 Python.org 下载最新版本,但我推荐使用 Miniconda。为此,我写了一篇关于如何和为什么的简短指南。python 安装后,就可以开始使用“Python”了,比如从终端。这就打开了一个所谓的 REPL:阅读、评估、打印、循环。它只是某种直接与 Python 交互的命令行界面(CLI)。您可以直接执行任何 python 代码和/或打开文件来运行 Python 脚本。python 解释器通常用于从 CLI 运行脚本,除了一个快速计算器,我不知道有谁直接使用 REPL 界面。为了更交互地使用 Python,几乎所有人都使用 IPython。

您的终端可能看起来不同,但在这里我启动了两个 REPLs。

IPython 提供了一个增强的交互式 Python shell,开始时只需在终端中键入“ ipython ”(您可能需要使用“ pip install ipython ”来安装它)。IPython 的另一个惊人特性是从 REPL 中分离出“E ”,它称之为“内核”。内核接收执行指令并发回结果。虽然使用内核有很多好处,但广泛使用的一个好处是其他应用程序(如 Spyder 和 Jupyter)连接到 IPython 内核。需要与内核交互的应用程序通常会自己启动。

如果您喜欢使用简单的文本编辑器进行开发,IPython 可能就是您所需要的。你想有一个更成熟的 IDE,有 pyCharm 或 Visual Studio 代码(VSC)。我认为开发人员在那里感觉很自在。对我来说,作为一名数据科学家,我在 Jupyter 笔记本上感觉最舒服。这是 IPython 交互式 shell 和一个文档的组合,您可以将您的代码与结构化的解释片段结合起来。几个星期后,我的记忆会变得模糊,有时我会忘记自己打算做什么。因此,对我来说,围绕代码的文档是非常宝贵的。为了给它一点 IDE 的感觉,他们创建了 Jupyter lab("pip install Jupyter lab"),这是 Jupyter 的一个扩展,具有更多的功能。用你觉得最舒服的方式工作,或者如果你没有偏好,用你同事最常用的方式。对于内部工作,这都是 IPython,它本身就是 Python。

今天的练*:

如果你还没有,我强烈建议你使用 Miniconda 设置 Python,就像这个指南中建议的那样。

  1. 启动基本的 Python REPL 并运行“打印(' hello world ')”命令。您可以使用“quit()”或“exit()”退出它(注意括号?).
  2. 启动 IPython REPL 并运行“print('hello world ')”命令。您可能需要安装 IPython。在这里,您可以使用“退出”或“退出”来退出。
  3. 设置您的首选 Python 环境,即 Jupyter、VSC、Spyder、pyCharm,或者如果您只是从文本编辑器和终端工作,则不设置任何环境。这对于示例来说并不重要,但是我们将展示来自 Jupyter 实验室或简单的 IPython 的所有内容。

如果您有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-10-91b8ff16cd60?source=collection_archive---------47-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

测试你的新技能:编写一个快速排序算法

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

今天,我们不会讨论一个新的话题,而是有一个简短的任务来强化你的知识。大约十年前,我参加了一个演讲,在演讲中,Python 因为做科学计算而得到了推广。在这次演讲中,有一个例子展示了快速排序算法。快速排序是一种相对简单但有效的排序算法。在演讲中让我惊讶的是,在讨论了算法如何使用伪代码工作后,python 解决方案几乎与伪代码完全相同。希望您也能惊讶于用 Python 实现该算法是多么简单。

快速排序算法图。

快速排序是一种所谓的分治算法。首先,它从列表中选择一个元素,这个元素称为 pivot。然后,它遍历剩余的元素,并将它们分成三组:小于透视值、等于透视值和大于透视值。它通过调用本身对更小和更大的部分重复这个过程。最后,它将所有列表合并在一起,得到一个排序后的列表。在伪代码中,它看起来像这样:

仅使用这些信息和我们到目前为止讨论的所有主题,您应该能够编写自己的快速排序算法。您可能需要的唯一东西是一个很好的值排序列表。有许多方法可以创建它们,但是我们还没有讨论可能有助于生成随机数的包。因此,我将提供创建随机数列表的代码:

代码片段从 Python 标准库中导入 random 模块,并用于生成随机数。random()函数返回一个介于 0 和 1 之间的随机数。为了让它们更大一些,我们将它们乘以 100,这样更容易阅读。在实现您的解决方案时,我会保持 N(即值的数量)较小。当一切正常时,可以随意试验排序列表的大小。在 IPython 中测试代码的一个好方法是使用 %timeit 魔法命令。魔术命令是内置于 IPython(而不是 Python 本身)的特殊函数,用于帮助完成各种事情。 %timeit 函数将一个函数重复几次,并给出每次迭代的平均值。这是测试代码执行速度在改变步骤时是否有所提高的一个很好的方法。如果你已经解决了,这里的就是我的解决方案。

我希望你在实现快速排序算法的过程中获得了乐趣。它仍然经常被使用,当然有一些优化。你注意到和伪代码的相似之处了吗?

如有任何问题,欢迎通过 LinkedIn 联系我。

下一次会议将于星期一再次提供。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-11-d44d7df65dac?source=collection_archive---------72-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

用 Python 读写文件

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

imgflp.com 的热图生成器

Python 可以被看作是一把瑞士军刀,附带了许多方便的工具来快速完成工作。一个经常出现的任务是与文件交互。从文本文件加载数据以用于分析,或将计算结果写入日志文件等任务。文件可以被看作是一大串数字,它们被保存在磁盘上的 0 和 1(二进制)中。当人与文件交互时,格式被翻译回我们理解的东西,例如 ASCII 字符(对于一个简单的文本文件)。所有这些实际的存储和翻译都是由我们的操作系统完成的。

有不同类型的文件,例如文本文件、二进制文件、图像等。每种类型都有自己的格式,可能需要特定的处理方法。例如,图像文件可以分成不同的部分:存储一般元数据的头部和存储图像实际数据的数据部分(很可能使用某种压缩)。在一个简单的文本文件中,字节代表字符。这些字符如何被编码取决于所使用的编码。早期使用的是 ASCII,能够表示 128 个字符。如今,UTF-8 是事实上的标准人物代表。这种编码与 ASCII 兼容,但将字符数扩展到超过一百万。UTF-8 使用 8 位进行编码,但可以组合多达 4 个字节来表示一个字符。您可能会想到为文件设置错误的编码会导致错误。尽管如此,从 UTF-8 开始是一个不错的猜测,因为 95%的网络使用这种编码。

处理文本文件时需要注意的另一件事是行尾。虽然这看起来微不足道,但由于历史原因,在如何编码新行方面存在差异。Windows 使用 ASA(美国标准协会)标准,并要求文本文件中的每一行都使用回车符(表示为 \r )和换行符(表示为 \n )结束。基于 Unix 的系统(包括 Linux 和 Mac)只需要换行符 (ISO 标准)。将文本文件从 Linux 发送到 Windows 可能会有些复杂,反之亦然,所以如果您从另一个系统获得文本文件,请注意。

对于其他文件格式,即非文本文件,您很可能会使用软件包。虽然您可以在二进制模式下打开文件,但您必须手动处理文件格式。社区已经提供了处理许多文件的包,很可能也是你想要打开的文件格式。例如 hdf5、jpg、json 或 csv,但是还有很多其他的包来帮助处理文件。在本教程中,我们将只关注文本文件。

要打开文本文件(实际上任何文件都可以打开),我们使用内置的 open() 函数。该函数至少需要一个文件名作为参数,并返回一个文件对象。它有模式作为可选的第二个参数,我们可以设置读取、写入和其他一些特殊模式。我们可以使用 file 对象提供的方法与文件进行交互。让我们从几个例子开始:

在这个例子中,我们以三种不同的模式打开了一个文件。默认情况下,当不提供模式字符串时,文件以读取模式打开( r )。这意味着该文件需要存在,否则 Python 将出现错误:“FileNotFoundError”。要写入一个文件,我们必须使用字符串' w '显式声明写入模式。现在,如果文件存在,它将被打开写入,如果它不存在,一个新的文件将被创建。小心,因为写模式会覆盖现有文件。要追加现有文件,open 函数具有追加模式(a)。

使用可以将字符串写入文件。写()的方法。 print() 函数自动给字符串添加一个换行符 (\n)。向文件中写入行时,情况并非如此。如果你想有一个新的行,你必须显式地添加特殊字符到字符串中。我们称之为单个字符,因为它将被编码为单个字符。反斜杠是表示特殊字符的特殊字符,像换行符 (\n)或者制表符 (\t)。它也可以用来“转义”字符,意思是将字符用作文本而不是语法。例如,在引号前使用反斜杠,不会将其标识为字符串的开头,而只是作为引号字符(“转义”语法定义)。

文件的读取可以使用。read()方法。Python 将文本文件视为可迭代的,并通过换行符(\n)分隔每个项目。因此,我们可以使用 for 循环来遍历整个文件。file 对象还提供了同时处理所有行的方法: readlines ()和 writelines ()。 readlines() 方法读取由换行符分隔的所有行,并将这些行作为列表返回(包括每个字符串中的\n 指示符)。类似地, writelines() 方法将字符串列表写入文件。后者不在列表中的每个字符串之间添加换行符。这可以使用 join 方法来修复: '\n '。加入(我的 _ 列表)。

处理完一个文件后,您必须关闭 file 对象。如果您不这样做,根据您的操作系统,您可能会丢失数据。一些操作系统缓存必须写入磁盘的数据。当文件关闭时,操作系统会将其作为一个大块写入磁盘,以最大限度地减少磁盘访问。这有助于最大限度地减少 IO 操作,在某些情况下还可以更快。这也意味着您必须确保正确关闭文件。每个 file 对象都有一个. close()方法。通过简单地调用该函数,文件被关闭,所有文件被保存。

今天的练*:

我从维基百科复制/粘贴了葡萄酒生产国的数据,并把它们放在一个文本文件中。你可以在这里下载文件,或者自己复制/粘贴表格到一个文件中。这张桌子上有行号、国名和以吨为单位的葡萄酒产量。

作业:
阅读文件,汇总世界上生产的葡萄酒总量。

提示:
——列由一个特殊字符分隔(记住。split()方法?)
-你要把字符串转换成数字。你也注意到令人讨厌的小数点分隔符了吗?(.有一个内置的 sum()可以对你新创建的数字列表求和。

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-12-44806ea44852?source=collection_archive---------54-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

尝试,除了,最后,和上下文管理器

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

当你用 Python 写代码时,你会(很可能)犯错误。有些会导致语法错误,这是因为您很可能拼错了某个单词,从而导致无效的 Python 代码。这些错误并不难改正。Python 中的其他类型的错误是异常。这些错误在将 Python 代码转换成字节码时完全没问题(没有语法错误),但是当试图执行某些东西时,就会出现无效的东西。例如,不能用圆周率除一个字符串。这对我们来说没有什么意义,Python 也不知道该做什么,并引发了一个异常。其中一些例外非常明显。例如,打开一个不存在的文件进行读取会引发 FileNotFound 异常。不是所有的例外都那么明确,甚至都是你的错。例如,尝试联系关闭的 restAPI 也会导致异常。当然,最好是尽量避免所有的错误和异常,但是 Python 中的一个*语总是让我吃惊:

请求原谅比请求允许容易( EAFP )

在 Reddit 上发现的模因是正确的。

Python 有一个用于捕捉异常的结构,即 try/except 块。顾名思义,它将尝试执行 try 块中的所有语句。如果成功了,一切都完成了。如果由于某种原因引发了异常,它将执行 except 块,并且所有错误都被抑制。虽然我们可以讨论这是否是一种好的编程方式,但它是一种非常有效的方式,因为它比试图首先检查所有可能的错误要快得多。try-except 块可以通过提供异常类型来检查许多特定的异常,或者通过将异常类型留空来捕捉任何异常。异常实际上是 exception 类型的对象(你惊讶吗?).让我们从一个如何使用这个结构的例子开始。

在这个例子中,我们有一个有效的函数来除两个数。这将很好地工作,除非你有第二个数字等于零。我们都听说过除数为零是没有定义的,我们从 Siri 那里了解到,你不能在零个朋友之间分配五块饼干。如上面的代码所示,除以零会导致 ZeroDivisionError:

哎呦……

ZeroDivisionError 是一个对象,通过使用 try-except 构造,我们可以捕获错误并阻止我们的脚本崩溃。在示例中,我们创建了 secure_divide ,它将尝试对值进行除法运算。在第一个 except 语句中,我们将专门捕捉 ZeroDivisionError。如果我们除以零,Python 将结束执行这个块中的语句。会不会有另一个问题,例如,如果我们引用一个不存在的变量,它会在第二个 except 块中结束,该块捕获所有(其他)异常。我们可以根据需要测试尽可能多的异常,或者只是捕获所有异常,而不提供异常。

如果您看到一个错误(或异常),我发现最简单的方法是从下到上阅读错误。最后一行显示了异常和错误的简短描述。然后,错误消息在前面有错误的行周围显示代码块。有错误的行显示错误发生在哪一行。如果错误发生在函数中,上面的每个代码段都比高一级,直到第一个代码块是代码的顶层。这有时会令人困惑,因为这些代码块的一部分来自导入的库,即不是您创建的代码。诀窍是忽略这些,并向更高的层次前进,直到你达到自己的代码层次。虽然从技术上讲,错误可能出现在一个包中,但更常见的是我们错误地使用了代码,并在导入的函数中输入了错误的参数。

对于特定的情况,try-except 构造是一个很好的方法,但是我建议尽量少用它。然而,非常有用的一点是 try-(except)-finally 结构。except 在括号之间,因为它是可选的。一个简短的例子:

在本例中,第一个代码片段显示了 try-finally 构造。它将尝试执行 try-block 中的所有代码,不管代码是成功还是失败,它将总是执行 finally 块中的部分。第二部分演示了这一点,我们故意让 try 块失败。在这两种情况下,都会打印“done”字符串。

try-finally 构造非常有用,在 Python 中使用得很多,但可能不是直接可见的。例如,当处理文件时,我们必须确保在完成后关闭文件。这可以通过 try-finally 构造来实现:

不管成功还是失败,try-finally 总是确保文件被关闭。这是一个非常棒的概念,Guido 决定创建一个特殊的构造来使它更加紧凑(并且在脚本的底部没有一个或多个 finally-clauses),即带有关键字的。带有关键字的打开(或连接,或…)一个对象,并将其连接到一个标识符。在下一个缩进的代码块中,变量是可用的,我们可以执行任意多的语句。当我们退出代码块时,或者当一个错误发生时,文件(或者连接,或者……)被关闭,与我们之前创建的 try-finally 构造相同(只是方式更短)。Python 中的这种语法称为上下文管理器,并且不仅仅适用于文件。它也经常与数据库一起使用。对数据库的更改通常会被收集起来,直到您提交它们。上下文管理器可以确保这些行被提交,并且数据库连接被正常关闭,而不管是否有错误。请记住,上下文管理器(使用关键字)确保代码的最后部分总是在代码段的末尾执行。最容易记住的方法是打开文件+关闭文件的例子。

今天的练*:

在 Python 中,获得交互式用户输入的最简单方法是使用 input() 函数。用户可以键入一个值,然后按 enter 键提交该值。该值是一个字符串。

input_value = input()  # *this also works in a  Jupyter Notebook*

赋值:
询问用户年龄,测试是否小于 42。因为输入值是一个字符串,所以需要将其转换为整数。使用 EAFP 原理捕捉无效输入,例如,如果用户输入字符串而不是数字。

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-13-4d8172df24b2?source=collection_archive---------27-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

字典:键值存储

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

模因生成与imgflip.com

Python 中几乎所有的数据类型都是不可变的(不能改变)。到目前为止,我们只看到了强大的列表,它是可变的列表之一。列表是一个有序的容器,可以保存任何类型的数据,包括其他列表。今天,我们将使用另一种可变数据类型:字典。字典是 Python 的另一匹马,它的作用就像一个键值存储。字典中的条目是通过键来访问的。与列表类似,值可以是任何对象,包括其他列表或字典(dictionary-ception)。第一次看到这个可能有点奇怪,但关键也可以是几乎任何东西。几乎任何东西,因为密钥必须是不可变的。可以是整数,字符串,浮点,复数,元组,任何对象,只要是不可变的。让我们看一些例子来说明这一切意味着什么。

使用 dict() 关键字或更短的花括号符号来创建字典。要定义值,您必须提供键-值对,用分号分隔。如前所述,键可以是任何不可变的东西。在这个例子中,我们当然使用了通常没有意义的键(除了一些非常特殊的情况)。要访问这些值,您必须提供括号之间的键。在这个例子中,我们有五个不同的键,我们需要使用确切的标识符。如果您未能提供正确的密钥,将会出现密钥错误。使用字典无法进行切片。因为 Python 中的一切都是对象,所以您也可以将函数用作键或值。因此,使用 key_value[5] 是对打印函数的引用,我们可以立即使用括号为该函数提供参数。如果这是令人困惑的,不要担心。了解这些结构很好,但不经常使用。需要记住的最重要的一点是,列表是有序的,因此可以通过列表中的整数位置来访问,而字典是无序的,只能通过它们的键来访问。从 Python 3.7 开始,保留了字典的顺序(所以它们现在是有序的),而早期版本则不是这样。

我们为列表学*的内置函数和操作符也适用于字典。我们可以用 len() 检查键值对的数量,并使用简单的布尔测试检查字典是否为空。对于列表,我们可以使用关键字中的来检查列表中是否有值。对于字典,这将测试字典中是否存在一个键。此外,字典还附带了一些附加到对象上的方法:

对于字典的迭代,我们必须做一些特殊的事情,因为我们有键值对。对于这一点,字典里有。items() 方法,该方法将键和值压缩在一起。在 for 循环中,您可以对每次迭代的键和值进行解包。要追加到字典中,可以直接使用括号符号。如果这个键不存在,它将被创建一个新的条目,如果存在,它将被更新。为了获得键的列表,字典有keys()方法。这是检查钥匙使用情况的方便快捷的检查。有一个类似的方法可以得到所有的值:。values()

字典是在一个单一的结构中收集各种信息的好方法,并且经常被使用。这对于链接到其他值的值非常有用。例如,一个城市的居民或一顿饭的热量。与列表一起,字典是 Python 中数据结构的核心,并且在许多情况下足以解决问题(与数据类等更复杂的结构相比)。

今天的练*:

较早的加密技术之一是所谓的张敬利密码。这是一种替代密码,其中每个字符移动一个固定的数字。据说朱利叶斯·张敬利用密码对他的具有军事意义的信息进行了编码。据说他用了右移三,意思是所有的 A 都变成了 D,所有的 B 都变成了 E,等等。今天的作业是,你必须解密一条加密信息。

alphabet = 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!?'  # one long string
n = 13  # cipher shift (to the right)encrypted_message = 'VMyAHrM3KFuA MHrDKMzGpul'

任务:
使用字典创建解密密钥,解密秘密消息。

提示:
1。您可以应用切片来相应地移动字母表。你必须将字母切分两次(从 n 移动到结尾+从 n 开始)并连接它们。
2。要创建解密字典,请使用 for 循环来填充它。为此,您可以将两个字符串(alphabet 和 shifted _ alphabet)压缩在一起,并对字符进行迭代。
3。最后,您可以迭代加密的字符,并使用您的解密字典将该字符替换为可读字符。

我已经在我的 Github 上发布了解决方案

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-14-da2cc6a05c59?source=collection_archive---------47-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

元组和集合

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

我们已经对 lists()和 dict()有了一些了解,但是还有另外两种数据类型你会经常遇到:元组和集合。让我们首先从元组开始。元组几乎与列表相同,但是它们是不可变的。这意味着它们在创建后不能改变,因此失去了动态的属性。因为列表是灵活的,所以它们也可能有些慢。如果不需要列表的灵活性,元组可以稍微加快脚本的速度。就我个人而言,我从未注意到任何速度上的差异,因为我使用的列表相对较小。因为元组是不可变的,所以您也可以将它们用作字典键,并使用多个值创建特殊的标识符。这当然是一个特殊的用例,但非常酷。元组最常见的用途是组合多个对象作为函数的返回值。当我刚开始使用 Python 时,我根本没有意识到我在使用元组。首先,让我们从一些例子开始:

元组是使用 tuple() 关键字、更短的括号符号以及我很久以后才意识到的东西创建的,只是通过使用逗号分隔对象。在这个例子中,我们创建了空元组。这当然没有多大意义,因为它们是不可改变的,它们注定永远是空的。如果一个元组有一个或多个值,可以使用括号符号和顺序整数索引像访问列表一样访问它们。然而,更常见的用法是直接将元组解包成多个变量。在这个例子中,我们创建了一个非常有用的函数,它返回两个值。我们没有在 return 语句中包含括号,但是 Python 仍然创建了一个元组。返回值可以被“捕获”为一个元组,或者我们可以将它们解包为两个值。我认为后者更具可读性。如果函数返回许多值,直接使用元组是有意义的。

最后一个基本数据类型是集合。该集合是一种无序的数据类型,也是可变的。我们可以在集合中添加或删除项目,但是只有唯一的项目会被保存,根据定义,集合中没有重复的项目。为了实现这一点,一个集合只能包含不可变的数据类型。这意味着您不能拥有包含列表、词典或其他集合的集合。集合本身的工作方式也非常类似于列表。您可以使用关键字中的来检查列表中是否有值,并使用布尔测试来检查列表是否为空。 len() 函数也像预期的那样工作。有很多方法:例如,添加、删除、弹出等等。使用制表符补全可以很容易地找到这些方法,并且它们都有一个 DocString。

集合可能有许多不同的用例,但我只使用它来获取列表中的唯一条目。例如,如果你有一段文字,很容易将文字分割成一个单词列表。现在,把这个列表转换成一个集合,我们就有了所有独特的单词。要创建集合,我们可以使用 set()关键字或更短的花括号符号。花括号也用于字典,但是,要得到字典,你必须提供键值对。要创建一个集合,只需在花括号内提供用逗号分隔的值。集合不保持顺序(集合是无序的)。因为也没有键,所以我们不能使用括号符号来访问这些值。试图使用 my_set1 访问一个值将导致一个 TypeError 异常,因为一个集合是不可订阅的。集合主要用于检查一个项目是否包含在集合中。还有一些运算与集合的数学定义有关,如并、差、交。

虽然集合很少被使用,但是在特定的用例中它们会很方便。元组被经常使用,但是我们可能没有意识到。解释完这两个类后,您现在知道了 Python 中所有的基本数据类型。当然还有许多其他类型的对象,你甚至可以使用类定义来创建自己的数据类型。但这是未来会议的事情。

今天的练*:

在自然语言处理(NLP)任务中,一种常见的分析是词频分析。一段文本(通常称为语料库)由单词(有时称为标记)组成。检查哪些单词比其他单词用得更频繁可能会很有趣。为此我们可以做一个词频分析。第一步是从文本中找到独特的单词。这闻起来像一套伟大的用法。我从维基百科上复制了一小段文字,并提供了排序功能:

作业:
找出出现频率最高的十个单词及其出现频率。

提示:
1。语料库包含大写和小写字符以及一些标点符号。为了获得更好的结果,你应该把它们都做成同样的大小写,并去掉标点符号()。替换(),。upper(),。下() )
2。语料库是一个巨大的字符串。你可以用把它拆分成单词。split() 功能。
3。使用集合,您可以在列表中找到唯一的项目。我们可以遍历一个列表,统计每个单词在原始单词列表中的出现次数。为此,列表中有计数()方法。将结果填充到一个新的字典中,该字典使用单词作为键,使用频率作为值。
4。我们不必数每个单词。为了获得更好的结果,我们应该排除停用字词集中的字词。
5。如果您有词频字典,使用提供的函数获得元组的排序列表并打印前十个条目。

我已经在我的 Github 上发布了解决方案

如果你有任何问题,请随时通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-15-50523202db27?source=collection_archive---------48-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

在 Python 中使用文件和路径

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

我们已经学*了处理文件的基本知识。使用 open()函数我们可以打开或创建一个文件对象,使用这个文件对象我们可以读写一个文本文件。但是如果我们需要访问多个文件呢?我们需要处理的数据通常不在单个文件中,而是分布在多个文件甚至多个目录中。为了处理文件和路径,我们可以使用几个标准的库包。几年前,我总是用 glob 包来做文件列表,用 os 包来做文件系统操作,比如删除文件。现在我大多使用标准库的 pathlib 包,它结合了前面两个,是平台无关的。pathlib 包引入了 Path() 类,一个表示路径或文件的对象。

要使用 Path() 类,我们需要导入它。下周我们将花一节课来讨论进口实际上是做什么的。现在,我们将只使用 import 语句向 Python 添加额外的功能。我们使用特殊的 from … import … 语句来实现这一点,该语句将一个选择性的部分导入到当前名称空间中(不要担心,我们将在下周讨论这些术语)。让我们来看几个例子:

可以看到, Path() 类非常方便。它带有路径或文件的大量信息。例如,它有一个关于词干文件名或者扩展名的属性。内置了许多方法来提取信息,例如创建日期、文件大小、检查是否存在、它是文件还是目录等等。此外,许多文件系统操作还是可用的。其中一些操作返回一个新的 Path()对象。在我看来,所有的例子都相对容易理解。有一些小的微妙之处值得了解。Path()对象是不可变的数据类型。这意味着您可以将它用作字典键。这很可能也是重命名文件时对象中的路径不变的原因。在接下来的例子中,我们将展示如何处理多个文件。

为了处理多个文件, pathlib 合并了。glob() 方法。它和 glob 包是一样的,在这里你可以根据一个模式找到所有的名字。在这个例子中,我们找到了所有以结尾的文件。txt 扩展名。结果是一个 Path 对象列表,这些对象依次打开前面讨论的所有选项。您可能会注意到,这些文件不是整齐有序的,而是按照它们在文件系统中出现的顺序排列的。你可能注意到的另一件事是“/”操作符。Path()对象定义了“/”运算符,以便您可以连接路径。在我们的例子中,我们用一个目录(一个 Path()对象)和一个文件名(一个字符串)来实现这一点。

Pathlib 将标准库中的许多包组合成一个对象,几乎可以处理任何文件系统。因此,我强烈推荐使用这种方式,而不是使用 os 包的旧标准。虽然这些方法也不错,但是 pathlib 给了你一个更简洁的格式,几乎所有你需要的功能都在手边。

今天的练*:

Path()有许多很好的用例,今天我们也将练*一个。我提供了一个带有文件夹的 zip 文件(这里是)。文件夹中的文件属于“word”类型,每个文件都是包含一个单词的文本文件。

赋值:
使用 pathlib 遍历所有文件,读取所有单词。有一个问题:glob 结果没有按升序排序。因此,你必须从文件名开始按升序排列单词。你能按正确的顺序打印这些单词吗?你可能会发现一个低级的笑话;-).

提示:
1。使用 glob 获取文件列表。
2。当遍历每个文件时,将文件编号作为关键字,将单词存储在字典中。您可以从文件的词干中提取文件号,并使用。split()方法。确保将数字转换为整数。
3。接下来,您必须遍历已排序的键,并打印每个单词,以空格(')作为结束字符(使用 print() 中的 end=' ' 参数)。下面是一个如何对字典键排序的例子,因为我们还没有讨论过 sorted()

my_dict = {4: 'ba', 6: 'bing', 5: 'da', 8:'!!!'}
for key in sorted(my_dict.keys()):
    print(my_dict[key], end=' ')

我已经在我的 Github 上发布了解决方案

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-16-c8b83919a13e?source=collection_archive---------71-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

导入、模块、包、库和框架

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

我们已经引入了一些东西,但没有真正解释发生了什么。今天我们将学* Python 中的导入实际上非常简单。使用导入,我们可以向 Python 添加功能。因为 Python 是一个如此活跃和开放的社区,所以有很多东西需要导入。甚至 Python 本身也附带了丰富的标准特性库(包括电池)。例如, pathlib 库给了你文件系统的超能力。但是也有无数的第三方包和库扩展了 Python 或者使得某种功能非常容易实现。例如,Flask 是创建动态网站的一种非常简单的方法。熊猫增加了一个新的数据帧结构,这对于数据科学来说是惊人的。几乎对于任何用例,都有某种可用的包。

imgflp.com创造的迷因。

在我们开始之前,我们需要澄清一些术语。包含 Python 代码的文件被称为模块,具有。py 分机。模块可以被导入,通常由一个或多个函数或类组成。如果您导入一个模块(另一个。py 文件)到当前脚本中,这些函数和/或类在当前脚本中变得可用。这是一个很好的方式来编码干燥和共享代码。要为多个模块提供结构,您可以将它们组合成一个包。Python 中的包只不过是一个目录,其中包含所有模块和一个名为 init.py 的特殊文件。如果该文件位于目录中,则可以使用目录名导入包。当包变得越来越大时,您可以将它们组织到更多的文件夹中,并创建一个库。在幕后,库在概念上等同于包。框架是库的集合。例如,Flask 有许多用于授权和数据库交互的子包。通常,您导入的所有内容都可以追溯到 Python 脚本。

另一个重要的概念是名称空间。一个名称空间定义了一个名称在哪里是已知的(作用域)。Python 有一个全局内置名称空间,这使得像 print 这样的函数随处可见。在这个名称空间中,我们有模块名称空间。我们创建的 Python 程序也称为模块。我们定义的每个变量在这个模块名称空间中都是已知的。这意味着如果我们在脚本顶部定义 banana=3,从现在开始,这个变量在整个模块中都是已知的。每次创建函数时,它都有自己的名称空间。这意味着每个变量的定义只有函数内部知道,不能从函数外部访问。然而,来自模块命名空间的变量在函数内部是可用的。

对于下一个例子,我们首先需要创建一个模块。为此,我们将使用 IPython 中一个名为%%writefile 的神奇命令。顾名思义,它会将单元格的内容写入一个文件。该文件包含一个包含变量和函数的简短 Python 脚本:

有两种方法可以导入我们的新模块。第一个是常规导入,它将整个文件导入到其词干文件名命名空间(不带扩展名的名称)下。因为模块名可能很长(我们懒得键入),我们可以使用作为关键字将名称空间重命名为较短的名称。很多热门包都有众所周知的缩写:import pandas 为 pd, import matplotlib.pyplot 为 plt 等。另一种导入方法是使用 from … import …构造。通过这种方法,你可以将模块的一部分导入到当前的名称空间中。导入的项目就像在当前模块中定义的一样可用。

当模块变得太大时,明智的做法是将它们分成更小的部分。通常它们以某种方式组合在一起。为此,创建了包。如前所述,包只是一个目录中模块的集合。当存在名为 init 的文件时,目录被检测为包。init 两边的双下划线)。然后使用<directory_name>访问每个模块。<module_name>。</module_name></directory_name>

这是软件包和模块的全部内容。更大的类型(库和框架)是包的集合,组合在一个目录中,访问方式与模块相同。因此,当您使用 pip 安装包时,会创建一个包含 Python 文件的文件夹。这个文件夹位于您的 Python 路径中,这个路径是一个字符串,包含在哪里查找模块和包的目录。当我们导入一个模块时,Python 将首先在当前工作目录中寻找该模块。接下来,它将检查 Python 标准库。如果仍然找不到模块,它将遍历 Python path 环境变量中定义的路径。在 Python 中,这个路径很容易通过 sys 包来访问。使用 sys.path,您可以检查所有路径,甚至可以添加另一个路径,以便可以找到该目录中的包。

当编辑模块时,您会遇到一个有趣的情况:当导入已经导入的模块时,它会一直引用以前导入的模块。这意味着,如果您更改了一个模块并再次导入它,而不重新启动内核,您将仍然使用该模块的旧版本。我不得不艰难地意识到这一点,这花了我几个小时才明白发生了什么。为了解决这个问题,Python 有一个名为 importlib 的附加包,使用 importlib.reload() 函数我们可以强制重新加载一个模块。

我认为现在,我们已经对导入系统以及模块和包的工作原理有了一些了解。当然,还有更多微妙之处需要学*但是现在,这可能就足够了。需要知道的最重要的事情是,您可以使用包来扩展 Python。这个社区非常活跃,几乎任何你想做的事情,都可能有一个包可以帮助你。几乎所有的包都在 Python 包索引( PyPi )中,所以这是一个开始寻找的好地方。如果你偶然发现一些不存在的东西,一般来说创建起来并不困难。如果你想获得不朽的地位,你可以把你的包上传到 PyPi,让其他人使用。分享就是关爱!

今天的练*:

今天的任务是创建你自己的包,它包含两个模块。第一个模块包含字符串函数,第二个模块包含数字函数(如下所述)。测试您的软件包是否正常工作。

# String functions (in a separate module)
def split_string(sentence):
    return sentence.split(' ')def is_long(sentence):
    if len(sentence) > 10:
        return True
    return False# Numeric functions (in a separate module)
def square_root(number):
    return number**0.5def square(number):
    return number * number

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-17-10fd0642a202?source=collection_archive---------70-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

列表理解和地图:一个惊人的捷径

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

Python 的关键元素之一是它的可读性。这种语言迫使你使用缩进来应用结构,这在我看来非常赏心悦目。Python 的关键思想也可以在Python 的禅 中找到。它是解释器中众多复活节彩蛋中的一个(只需键入' import this ')。其中一个非常酷的*惯用法是理解。理解,或者更经常被称为列表理解,因为它们最经常与列表一起使用,是创建列表的一种有点抽象的方式。它们将某种处理步骤与一个循环结合在一起,以填充一个新的列表。为了更清楚地说明这一点,让我们把传统的舞步和积木上的酷小子做个比较:

在传统的循环中,首先需要定义一个空列表。接下来是一个 for 循环,遍历所有计算,并将所有计算结果追加到新的列表中。这三行可以使用 list comprehension 合并成一行,但不会牺牲可读性。在列表理解中,即在由括号标识的列表定义中,有一个 for 循环。这个 for 循环定义了一个用于迭代的变量,我们可以自由选择。我们常常很懒,选择短字母,如 xyz 。尽管如此,使用描述性名称是更好的做法。for 循环的行为与常规 for 循环相同,并在整个 iterable 上迭代。我们可以压缩多个 iterables 或者使用 enumerate,但是我们也需要解包所有额外的变量(或者将它们作为一个元组使用)。需要记住的一件事是,列表理解会创建一个新的列表,即使我们复制了每一个条目并且有相同的列表。理解几乎可以在任何地方工作,并且可以在函数中使用。他们也可以使用字典和集合,但是当然,每个数据类型的定义必须是正确的。

一般来说,理解的语法是:iterable中项目的表达式。由于理解的结果又是可重复的,我们也可以将多个理解嵌套成一个。虽然这很好,但是要记住可读性可能会下降。因此,将你的超级一行改为两行并不是一个坏*惯。

与内联 for 循环一样,我们也可以使用内联 if 语句。我认为对于一般的用法,内联 if 语句会增加代码的混乱,降低可读性。然而,我们可以在理解中使用 if 语句,对于这种用例,它们有时非常简洁。

列表理解是缩短代码的一个很好的方法,而且通常不会牺牲可读性。与内联的 if 语句一起,这是一种创建过滤项目列表的简单方法。另一个非常类似的方法是 map() 函数。这个函数在列表的每一项上映射一个函数,并返回一个包含所有返回值的新列表。使用 for 循环或理解也可以达到同样的效果,但是 map 函数的可读性更好一些,因此,我认为了解以下内容是很有用的:

函数的第一个参数是对函数的引用,第二个参数是 iterable。然而,它返回的结果不是一个列表,而是一个 map-object。map-object 是一种生成器,所以它只在被请求时计算值。这在大多数情况下效率更高,消耗的内存更少。为了查看完整的列表,我们将 map-object 转换成一个列表。正如我们在这里所做的,处理容易映射的数据也更容易并行化(在计算机的多个内核上并行运行)。Python 有多处理包,为 CPU 密集型任务提供了多处理映射功能。

今天的练*:

理解是过滤列表结构数据或组合相似任务的一个好方法。我经常做的事情是,例如在列表理解中读取 CSV 文件,产生 CSV 熊猫数据帧列表。使用 Pandas 中的 concat 功能,我可以在一行中合并所有导入的文件,得到一个包含所有数据的组合数据框。另一个很好的用法是有选择地将值放入列表中。这就是我们今天要练*的,用它来*似圆周率。

作业: 今天我们要用莱布尼茨公式来*似π的值。莱布尼茨公式是一个交替的级数(它改变每个值的符号),当对无穷多个值的级数求和时,你得到圆周率。问题是,我们没有无限的内存,因此,我们截断了这个值,并*似圆周率。莱布尼茨公式指出圆周率 4 等于下面给出的交替级数:

π / 4 = 1/1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + .....

为了解决这个问题,我们可以将它分成几个步骤:
a)为所有奇数
创建一个列表理解 b)使用另一个列表理解使每个第二个值为负
c)使用另一个列表理解,将每个值转换为 1 除以 x
d)将整个列表求和并乘以 4 以获得π的*似值 e)增加数字的数量( n )以获得更好的*似值。

提示:
1。使用 range 获得一个数值 n 以内的数字列表(range(n))。
2。用 2 的模数检查是否是偶数/奇数
3。要获得每一秒的数字,请将 enumerate 与模数一起使用。

import math
actual_pi = math.pin = 100  # amount of numbers

我已经在我的 Github 上发布了解决方案

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-18-4718eb73758c?source=collection_archive---------51-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

关于生成器以及如何创建它们的更多信息

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

我们已经遇到了生成器,它是一个 iterable,可以在需要的时候缓慢地计算值。这在速度上有好处,但最大的好处是减少了内存。常规列表需要一次性分配,一百万个值的列表可能会占用大量内存。当我们一次处理一个(或几个)值时,使用生成器要聪明得多。我们已经看到了 range() 函数,然而这并不是一个正式的生成器(但还是有点类似)。关于生成器,有一点是它只能在 iterable 上迭代一次。范围()可以重复完整迭代。当然,这只是一个细微的差别,但是要牢记在心。在上节课中,我们讨论了理解,但我们没有提到一种特殊类型:生成理解(或生成表达)。这种类型的理解看起来与列表理解相同,但是使用圆括号而不是方括号,并且顾名思义,返回一个生成器。

发电机没有长度,因此不能使用 length() 功能。在这个例子中,我们知道长度,因为我们已经定义了它( range(10) )。然而,如果我们使用生成器来一行一行地遍历一个大文件,根据定义,生成器没有长度。实际上,要获得长度,即要读取的行数,您需要读取整个文件并计算' \n '个字符。这已经花费了一个完整的迭代周期。

从生成器获取下一个值的另一种方法是使用 next() 函数。你必须记住,如果生成器是空的,即完整的迭代已经完成, next() 函数将引发一个 StopIteration 异常。这可能会让您想知道 for 循环是如何工作的,因为您无法检查是否还有剩余的项。原来 for-loop 抓到了 StopIteration 异常:先请求原谅再请求许可

我们了解到,生成器对于减少 Python 程序的内存占用非常有用,甚至可以读取 100GB 的文件。为了完成这些专门的任务,您需要定义自己的生成器函数。生成器函数看起来像一个常规函数,它计算当前值。然后返回这个值,但是我们不使用 return 关键字,而是使用 yield 。通常,当使用 return 时,函数的状态是垃圾收集。这意味着函数中的所有变量都被删除了。使用产量,功能的状态被保持,保持所有变量完整。当 for-loop 或 next()调用请求下一个值时,生成器函数将继续生成下一个值。让我们创建一个简单的生成器:

从生成器函数本身来看,已经很清楚为什么生成器在一次完整的迭代后是空的了。到达 max_number 后,该功能结束,不能产生新的值。为了再次迭代生成器,我们需要再次重新启动生成器。

函数本身可以是任何东西。我们已经提到的例子是一个大于内存的文件的逐行迭代,但是还有许多其他的用法。生成器可以组合一个或多个数据库调用,可以从互联网下载信息,并且可以被定义为可以无限期运行。

生成器是 Python 中的一个高级特性,在某些情况下非常有用。正如我已经提到的,当内存是一个问题时,生成器是一个可能的解决方案。值是动态计算的。如果你只需要几个值(比如 100 个值中的前 10 个),你可以省略不需要的计算,这样可以提高速度。你可以用发电机做更高级的事情,例如堆叠发电机。组合生成器可以模仿管道,这是一种高效的技术,例如在 Unix 世界中。

今天的练*:

当讨论更高级的话题时,作业也会变得更有趣。因为我喜欢数字,今天我们要产生斐波纳契数。斐波那契数列(或斐波那契数列)非常神奇,因为它们在自然界中经常出现。该序列定义了当前的斐波那契数列是前两个数列的和:

F = [0, 1, 1, 2, 3, 5, 8, 13, ....... ]

赋值: 创建一个无限生成器来生成斐波那契数。使用 while 循环(和 break)测试您的函数。由于生成器是无限的,您可以继续第二个循环。

提示 :
a)无限循环可以用永远为真的 while 循环来创建。
b)生成器函数需要跟踪最后两个值并得出总和。

我已经在我的 Github 上发布了解决方案

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-19-4d688c4101ce?source=collection_archive---------58-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

在 Python 中读取错误和异常

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

当我们编码时,犯错是不可避免的。这些错误使得 Python 生成了大量的打印输出,这可能有些令人不知所措。今天的目标是更加熟悉错误读数,并了解它们实际上非常具有描述性。下面是一段相对容易发现错误的代码:

这里我们有两个函数,它们相互嵌套,并被顺序调用。首先我们调用 my_function 并提供一个字符串。在 my_function 中我们调用了另一个叫做 sub_function 的函数。在创建 sub_function 时,我们还没有足够的咖啡,并且犯了一个错别字: print - > pint 。这将创建这个大的打印输出:

我们没能找到绳子!

对于一个丢失的字母来说,这是一个很大的信息,对于新来的人来说可能有点令人生畏。在 IPython 和 Jupyter 中,这种消息被正式称为回溯,是用颜色解析的。如果你运行 vanilla Python,这将会是同样的颜色,看起来更可怕。尽管如此,这条消息实际上是相当翔实的,并与正确的步骤,真的很容易阅读。

底部顶部读取一个 Python 回溯。最后一行告诉您异常的名称和简短描述。在很多情况下,这就是你需要知道的全部。在这个例子中,我们得到一个 NameError ,并告诉我们名称‘品脱’没有被定义。当我编码时,我不断地测试我的代码,因此,记住我只是添加了一行带有 print() 函数的代码。所以,这么小的错别字很快就被识别出来了。如果您不确定这个异常发生在哪里,Python 会给我们提供额外的信息,这些信息分为代码深度的不同级别。每一次,我们调用一个函数,我们就深入一层。基础层是我们调用 my_function()函数的主要代码层。my_function 引入了对 sub_function 进行另一个函数调用的另一个级别。sub_function 创建发生错误的第三个也是最后一个级别。这三个级别在回溯中是可见的,最深的级别(错误实际发生的地方)在底部。在每个级别中,都可以看到一个箭头,指出发生错误的行。它还打印出行号以及有错误的行的前后两行,以便在实际代码中更好地识别这段代码。

你可能会问,如果错误发生在底层,为什么我们需要更高的代码级别。原因是发生了错误,因为我们可能在更早的步骤(更高级)中提供了错误类型的参数。让我们创建另一段错误代码,并一步一步地进行追溯:

阅读回溯消息的步骤。

我们必须自下而上地分析这种追溯。首先(1)我们看到我们有一个值错误。当函数或类获得它不期望的值时,会引发值错误。在这种情况下,int()类需要一个数字的字符串表示。描述使这一点变得更加清楚:基数为 10 的 int()的无效文字:“25beer3”。事实上,从该字符串生成整数是不明确的。添加了基数 10,因为数字也可以是基数 2(二进制)、基数 8(八进制)或基数 16(十六进制)。

接下来,我们需要检查这个错误发生在哪里。在倒数第一个块(2)中,我们确实看到我们试图将变量 number_in_string 转换为整数。就代码而言,这里没有任何错误,所以我们更上一层楼(3)。在这个函数中,同样没有任何错误,所以我们继续到顶层(4)。这里我们发现了错误:我们提供了错误类型的参数。

在这个例子中,很容易修复,因为我们自己提供了一个错误的字符串。在现实生活中,这个字符串可能是从另一个从文件导入的字符串中提取出来的,所以是不可见的。例如,我们正在读取的 CSV 文件可能没有所有行的合理值(只是简单的错误值)。解决方案是在第一次函数调用之前检查字符串是否是我们所期望的,否则替换字符串。根据函数得到错误参数的可能性,可以增加测试。开发人员已经使用单元测试解决了这个问题。测试以检查函数是否按预期工作。在这些单元测试中,我们都可以测试数据的有效性。我的观点是,你需要用常识来判断要测试什么,你可以假设什么是好的。如果有麻烦,你总会有值得信赖的线索来指引你。

本文描述的方法是在代码中查找错误的典型工作流程。大多数时候,最底层的信息就是你所需要的。如果您需要检查异常发生的位置,那是因为我们向函数提供了错误的参数类型。诀窍是找到导致问题的函数。回溯是找到有问题的函数的完美工具。这些类型的错误通常可以通过快速检查要调用的函数的 DocString 来修复。

今天的练*:

发现错误是每个程序员都要掌握的技能。下面我提供了一段可怕的周一早晨的代码。使用错误对话框找到并消除所有的错误。尽量不要直接找到它们,而是真正使用回溯来识别错误,以获得对其格式的一些练*。

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 2

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-2-86a56e6f0568?source=collection_archive---------38-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

使用 Jupyter 实验室和导航笔记本

这是一个系列的 10 分钟 Python 短文,帮助你开始学* Python。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您想了解关于 Python 特定主题的问题或请求,请随时通过 LinkedIn联系我。

希望从第一堂课开始,你已经对 Python 的工作原理有了大致的了解,并且已经成功安装了 Python(还记得我在本指南中关于使用 Miniconda 安装 Python 的建议吗?).在这篇短文中,我们将讨论 Jupyter 笔记本环境。

笔记本是使用单元格构建的交互式文档。有两种类型的细胞,即输入细胞和输出细胞。输入单元格由我们(用户)创建,可以是三种类型:代码单元格、降价单元格或原始单元格。顾名思义,代码单元是一段可以被评估的代码。评估的输出显示在该代码单元格正下方的输出单元格中。降价单元格是带有以降价语言格式化的文本的单元格。有许多不同的格式功能可用,如标题,列表,字体粗细选项。markdown 的好处是,即使不渲染,也非常易读。原始像元是一种特殊类型的像元,Jupyter 不会对其求值,但如果您使用另一个名为 nbconvert 的工具,则可以对其求值。我从未使用过后者,但是当使用像 Sphinx 这样的自动文档套件时,它会很方便。code 单元格和 markdown 单元格的组合使得拥有一个将代码和解释结合起来的优秀分析文档成为可能。这使得笔记本成为分享结果的首选方式。

要安装 Jupyter,有两个选项。只有 Jupyter,它可以让您访问笔记本电脑环境,或者 Jupyter lab,它有更多的功能。两个都好。唯一要记住的是,Jupyter 实验室有时需要更多的步骤来安装定制的小部件。两种方法都安装 Jupyter 笔记本服务器。与 Jupyter 交互的标准方式是通过网络浏览器,但由于它是一种客户端-服务器结构,其他应用程序也可以与之交互。例如,有一个 Visual Studio 代码插件也可以与笔记本服务器交互,可能还有许多其他选项。如果你喜欢,可以随意使用其他的。现在,让我们使用终端在新环境中安装并启动 Jupyter lab:

conda create --name tutor python=3.7
conda activate tutor
pip install jupyterlabjupyter lab

Jupyter 实验室启动后,左侧栏打开。

浏览器应该会打开并显示 Jupyter 实验室的主页。该窗口由三部分组成:与其他应用程序类似的顶部菜单栏、侧菜单选项卡栏和主编辑器窗格。侧边栏由标签组成:文件导航,运行内核,命令,属性检查器,打开标签,如果安装了扩展管理器。目前我们只谈前两个。“导航”选项卡帮助您导航计算机上的文件。您可以浏览和创建目录。出于安全原因,Jupyter 实验室开放时,您不能进入更低的目录。Jupyter 是作为服务器创建的,所以也有上传的选项。“加号”符号在主窗口中打开一个新的启动器选项卡,当 Jupyter lab 启动时,它也会自动打开。在 launcher 选项卡中,您可以创建新的笔记本,在选项卡中打开 IPython 控制台,创建文本文件,甚至是终端。回到侧边栏,另一个选项卡显示活动的内核。每次你打开或创建一个笔记本,一个内核就被启动了。关闭笔记本不会停止内核,除非你关闭 Jupyter lab 或者转到这个标签并关闭它们。如果您不小心关闭了标签,您可以从这里再次打开它。同样值得一提的是,主编辑器面板可以定制为通过拖动标签并排显示文件。一定要试一试。

让我们使用启动器在当前目录中创建新的笔记本。创建后,您可以在文件导航器中右键单击新文件来重命名它。您也可以右键单击选项卡名称来实现相同的目的。还要注意文件导航器中的小绿点,它显示该文件当前作为内核运行。新笔记本相当空,因为它只有一个电池。顶部是一个小菜单栏,显示了一些基本功能,如复制/粘贴、单元格选项和一些内核选项。Jupyter lab 是一个模态编辑器,类似于 vim。它有一个命令模式,您可以在其中导航或编辑单元格,还有一个单元格编辑模式,您可以在其中键入内容。在命令模式下,您可以轻松地添加、删除、剪切或复制单元格。为此,有一些便于记忆的快捷方式(它们也可以在顶部菜单中找到):

  • 箭头键在单元格内移动。按住 shift 键选择单元格。
  • “a”和“b”添加当前单元格上方的单元格下方的单元格
  • “c”、“x”、“v”到复制剪切,或者粘贴单元格。
  • “y”或“m”分别将单元格类型更改为编码或降价。
  • “shift + enter”计算当前单元格。

花些时间了解降价的基本知识是有用的。它们非常简单,你可能只需要几个。看看这个备忘单,你会直观地看到它的语法。

今天的练*:

  1. 创建一个新的笔记本,并将其重命名为合理的名称。
  2. 做一些简单的计算,并评估细胞。
  3. 将单元格更改为 markdown,并编写描述,包括标题。
  4. 在笔记本上移动,复制和粘贴单元格。

作为数值运算符的建议:
+(加法):10 + 12,
-(减法):20 - 30,
*(乘法):3 * 3,
/(除法):49 / 7,
(幂):28。

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python 10

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-20-13af35b86452?source=collection_archive---------66-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

让我们进行分类排序

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

两周前我们写了一个快速排序算法,这是一个相对高效的排序算法。当我们需要对一个列表进行排序时,Python 自带了一个名为 sorted() 的内置排序函数。实现的算法叫做 Timsort ,由 Tim Peters 在 2002 年实现。该函数采用 iterable,默认情况下按升序对值和字符进行排序。sorted()的语法如您所料:

数字按照您预期的方式排序。如果要反转顺序,我们需要将反转参数设置为。Sorted()返回一个新的列表,因此,我们也可以使用 reverse() 函数来反转列表。反向函数返回一个反向迭代器对象。要打印列表,我们需要首先转换它。Sorted()也可以对字符串进行排序,并且会一个字符一个字符地进行排序,从数字开始,然后是字母表。现在,结果是一个字符列表。对字符串列表进行排序时,sorted()会按字母顺序对每一项进行排序。需要记住的是,字符串中的数字是在字符级别上排序的,因此,对文件的排序可能不是您所期望的顺序:

对字符串进行排序时,Python 使用字符的 Unicode 值。这意味着 Unicode 编码的低值(如大写字母)出现在高值字符(如小写字母)之前。如果一个字符串包含一个数字,而你想按这个数字排序,我们需要提供一个键。一个键是一个函数(或者 lambda 函数,我们仍然需要在以后的课程中讨论这个函数),它可以转换条目,使其以不同的方式排序。key-function 的结果可以是排序后可以对其执行排序逻辑的任何内容。在我们的示例中,我们创建了一个从文件名中提取数字并将其转换为整数的函数。Sorted 现在对这些整数进行排序,并按顺序返回原始列表。这使得 key-parameter 成为一种非常强大的列表排序方式。

需要注意的是,sorted()只能对可以与列表中所有其他项目进行比较的项目进行排序。当你提供一个混合类型的列表,比如整数和字符串,说 25 比‘香蕉’大是模棱两可的。字典列表也是如此。它不知道如何比较每个包含不同值的字典。这些问题可以通过定义一个键函数来解决。

今天的练*:

作业 1:
第一个作业你要按照库存水果的多少来排列字典的清单。为此,您需要定义一个键(一个函数)来选择相关的值,并再次明确排序。

fruit_types = [
    {'name': 'banana', 'amount': 123, 'price': 2.50},
    {'name': 'strawberry', 'amount': 23, 'price': 1.75},
    {'name': 'apple', 'amount': 87, 'price': 2.10},
    {'name': 'pear', 'amount': 3, 'price': 1.50},
]

任务 2:
在第二部分中,我们将实现另一种排序算法:冒泡排序。冒泡排序是(剧透)一种效率低得多的排序方式。该算法反复遍历一个列表,比较两个相邻的值,如果它们的顺序不正确,就交换它们。下面是两次迭代的示意图:

该图从比较前两个值开始,当 24 大于 4 时,交换这两个值。接下来的两个值不变。这个过程一直持续到所有值都比较完为止。第一次迭代后,最后一个值是固定的,因为这是列表中最大的值。这意味着对于下一次迭代,我们可以忽略最后一个值,只需比较 75 之前的值。第二次迭代后,最后两个值是固定的。伪代码中的全部代码(读作:几乎是 Python 代码)看起来是这样的:

现在,使用这个伪代码来实现冒泡排序算法,并比较它与我们之前的快速排序算法相比慢了多少。您可以使用神奇的命令 %timeit 来评估排序算法的性能:

解决方案发布在我的 Github 账户上的这里

下一篇文章将在我两周后的假期后发布,也就是 8 月 10 日。

如果您有任何问题,请随时通过 LinkedIn 联系我。

每天 10 分钟学* Python # 21

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-21-f1d8eec408d?source=collection_archive---------77-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

匿名函数也叫λ函数

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

对于新手来说,lambda 函数可能有点吓人。我也避免使用这些函数有一段时间了,因为我从来不知道它们的真正用途。如今,我确实看到了这种结构的好处,但这种好处相当小。你会遇到这些功能,因此,知道发生了什么是很好的。Lambda 函数也被称为匿名函数无名函数,这更好地描述了它们。lambda 函数是没有名字的函数的内联定义。除了没有名字,常规函数和 lambda 函数有什么区别?几乎没有!那么下一个问题是:当一个常规函数做同样的事情时,为什么要使用 lambda 函数?事实上,在大多数情况下,常规函数是可行的。但是,有时候你只需要做一次手术。虽然您仍然可以使用常规函数,但是内联函数(lambda 函数)可能会更容易一些。

lambda 函数的定义很简短:它以关键字 lambda 开始,后跟一个或多个用逗号分隔的参数。分号后面是函数本身的步骤。让我们来看一个例子:

在这个例子中,我们有一个费用清单。每笔费用都是一个元组,包含名称和成本。虽然有其他方法(如列表理解),但我们选择使用 map()来选择所有成本。Map()需要一个函数和一个 iterable。我们现在可以创建一个选择元组第二项的正则函数,但是我们只使用它一次。这意味着 lambda 函数在这里是完美的。map()在每个元组上执行我们的函数,并返回所有成本的列表,后跟一个总和。现在我们来看看更多的例子(免责声明:并非所有都有用):

在示例中,我们展示了 lambda 表达式返回对匿名函数的引用。该函数现在被一个变量捕获,它将不会被“垃圾收集”。这消除了 lambda 函数的好处,即一次性匿名函数,它将在使用后被丢弃。如果添加对 lambda 函数的引用,只需编写一个常规函数即可。常规函数可读性更好。尽管如此,您可以将 lambda 函数捕获到一个引用中,然后该变量就充当一个常规函数(只是不要这样做(-;).

imgflp.com 上产生的模因

只是为了好玩,您也可以直接调用引用,而不用在变量中捕获它。虽然这没有多大意义,但它是可能的,而且完全有效。需要额外的括号,否则将返回函数标识符。

为了证明常规函数和 lambda 函数是相同的,我们可以检查来自 Python 解释器的字节码。为此,我们可以利用 dis 模块,它将实际执行的字节码可视化。所有 Python 命令都可以分解成少量的字节码操作。这里我们比较了常规和 lambda 之间的字节码,看到我们有一个精确的匹配。它们的字节码是一样的!

前面的例子展示了两个有用的新函数:filter()和 reduce()。顾名思义,filter()用于过滤 iterable。iterable 的每一项都被放入一个必须返回布尔值的函数中。如果布尔值为真,则保留该值。如果布尔值为 false,则忽略该值。我们可以提供一个常规函数,但如果是一次性的,lambda 函数可能更容易。

Reduce()是许多其他语言中常见的方法。它接受一个 iterable,并使用提供的函数将 iterable 简化为一个值(同一类型)。实际情况是,它接受 iterable 的前两个值,并根据提供的函数创建一个新值。它重复这个操作,直到只剩下一个值。同样,这可能是一个 lambda 函数的绝佳位置。

今天的练*:

虽然没有 lambda 函数的生活是很可能的,但我认为这是一个很好的很高兴知道。你偶尔会遇到他们。在这个任务中,我们将使用 reduce()找到一组值中的最大值。

赋值:
用 reduce 求 1000 个值中的最大值。

提示:
1。λ函数有两个参数
2。使用内联 if 返回正确的值

一个解决方案是发布在我的 Github 上

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 22

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-22-a1bc96b529a1?source=collection_archive---------56-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

在 Python 中,我们修饰函数以使它们更好

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

装饰者是另一个令人困惑的话题,他们的使用肯定会让人感觉有些不可思议。虽然修饰函数这个术语非常恰当,但它也模糊了正在发生的事情,即:将一个函数包装在另一个函数中。首先,我们将创建一个示例函数:

imgflp.com 上产生的模因

这个函数非常简单,我想每个人都很清楚。我们的工作包括编写许多函数,有时我们需要对函数计时,例如,如果我们想检查一个新的实现是否更快。一种方法是简单地使用时间函数:

希望明确这不是真的。当然,我们可以使用 iPython 的神奇语句%timeit,但是现在让我们忽略这种可能性。当检查这些步骤时,我们看到我们在实际函数之前添加了几个步骤,在函数完成之后添加了几个步骤。解决这个问题的一个方法是将计时放在 square_value 函数中。但是如果你还想为其他功能计时呢?因为很大一部分代码是活的,所以我们可以很容易地将函数包装在函数周围。让我们进行第一次尝试:

这里我们创建了一个新函数,它将函数及其参数作为参数。还记得让捕捉所有未命名参数的 *args 方法吗?我们将这些传递给被调用的函数。与我们之前创建的非常湿的代码相比,这已经是一个很大的改进了。然而,为每个调用包装一个函数仍然令人感觉乏味。难道我们不能定义它让它一直存在吗?你可能猜到我们可以。我们利用了这样一个事实,即我们可以在任何地方定义一个函数,并返回新的定义。这听起来可能很奇怪,但在下一个例子中会很清楚:

timer 函数现在是一个包装函数,它围绕我们的 square_values 创建一个新函数,并返回包装后的函数。这种方法的最大优点是,我们现在可以通过简单地将任何函数封装在我们的 timer()中来为它计时。在这里,我们通过包装状态覆盖了对原始函数的引用。这一步称为修饰函数。因为这一步是非常常见的操作,Python 创建了一个特殊的语法来使用@符号修饰函数:

所以@符号只是语法,没有什么真正神奇的。这是一种用包装函数覆盖原始函数引用的简写符号。

对于初学者来说,装饰者的用例不是那么明显。在我使用 Python 的最初几年,我从未使用过它们。现在,我偶尔使用它们。除了计时功能,日志记录也是一个很好的用例。使用装饰器,您可以在函数级监控您的代码。

有相当多的软件包在它们的语法中使用了装饰器。例如,塞巴斯蒂安·拉米雷斯的 FastApi 使用 decorators 来创建与 RestFull api 端点的链接。Django 和 Flask ,这两个伟大的 web 框架都使用装饰器来做各种事情。例如,确保某个功能仅在用户登录时使用。另一个*乎神奇的用法是与 Numba 一起使用。当用 Numba 装饰函数时,它使用实时(JIT)编译来加速函数,使它们在速度上与编译语言相当。还有很多其他用法,这里的是一个精选列表。

今天的练*:

今天我们将练*装饰者的另一个用例,即改变现有的功能。有时,您会遇到一个您导入的函数,它几乎可以完成您想要的功能。差不多了,但是需要稍微调整一下。为此,您可以编写另一个函数来完成它,或者您可以使用 decorators。如果您需要更改许多以相同格式返回值的函数,则特别方便。让我们看看今天作业的功能。

任务:

编写一个 decorator 函数并修饰 current_temperature(),以便它返回以摄氏度为单位的温度。

提示:

  1. 你可以复制/粘贴我们之前的定时器装饰函数的结构。
  2. 摄氏度=(华氏 32 度)* 5 / 9

我的 Github 上发布了一个解决方案。

如果您有任何问题,请随时通过 LinkedIn 联系我。

每天 10 分钟学* Python # 23

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-23-8fd7e119da8d?source=collection_archive---------54-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

一种全新的程序设计

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

当深入了解编程时,你会遇到两大范例:函数式编程和面向对象编程(OOP)。到目前为止,我们主要做的被称为函数式编程。我还没有为这两个术语找到一个令人满意的全面定义。然而,关键的区别是,函数式编程,顾名思义,是以函数为中心的,程序结构就像一步一步的食谱,而 OOP 是以数据为中心的,数据是以对象为结构的。这主要是处理问题的不同方式。这两种范式之间没有真正的好与坏,因为人们更喜欢网球而不是足球。有时,一种方法似乎更容易解决问题,但我相信你可以用两种方法获得相同的结果。OOP 和函数式方法都与 Python 兼容。

OOP 的核心思想是将程序抽象成对象。对象是将数据和与特定数据相关的代码结合在一起的结构。OOP 的鼓吹者声称这减少了重复的次数,使代码更具可读性。我必须承认,这个想法非常好,确实有一些好处。作为一个很好的入门例子,让我们为一个动物创建一个对象,看看 OOP 在 Python 中是如何工作的。

这个结构看起来并不困难,但是有一些新的概念。要开始一个类定义,首先要有 class 关键字,然后是一个名称。按照惯例,类名以大写字母开头,但是从 Python 的角度来看,任何名称都可以(但是请务必大写)。类似于函数定义,我们有一个分号,所有缩进的代码都属于这个定义。提供一个 DocString 来描述该类是一个很好的做法。在定义本身中,我们现在可以创建变量和方法。方法是类定义中函数的名字。

了解类定义类实例之间的区别很重要。我们在前面的例子中创建的代码从类定义开始,为我们的对象创建一个蓝图。当我们想要使用特定类型的对象时,我们需要创建一个实例。在定义了我们的动物类之后,我们创建了该类的两个实例: animal1animal2 。虽然蓝图定义了哪些数据和方法是可用的,但它并不包含数据本身。当创建类的实例时,我们创建包含实际数据的对象。在我们的示例中, animal1animal2 都属于类型 Animal ,但是它们包含不同的数据:青蛙代表 animal1 ,犀牛代表 animal2 。您可以为以前定义的类创建任意多个实例。

当创建一个类的实例时,我们调用 Python 的一个特殊方法:构造函数。我们可以看到它的特别之处,因为它的名字被双下划线所包围。这些所谓的 dunder-methods 在 Python 中被给予了特殊处理。init dunder-method 表示构造函数,一个在创建类实例时调用的方法。方法可以像常规函数一样接受参数,但是类有一个强制的第一个参数: self 。Python 中的任何类方法都需要这个参数,原因是这个特定的对象包含实例的数据。当我们在 Python 中定义一个类时,我们有一个对该类的引用。这个定义对每个物体都是一样的。为了让每个实例拥有自己的数据集,比如我们有一只青蛙和一只犀牛,每个类都有一个保存实际数据的 self 对象。在构造函数中,我们定义了创建的变量并将数据添加到这个 self 对象中。该对象在实例之间共享,但不在不同的实例之间共享。现在,我们可以在类中定义的其他方法中使用该实例数据,比如在 description() 方法中。这是 Python 开发人员想出的在实例级别存储数据的解决方案。虽然您可以在类级别定义变量(其他编程语言会这样做),但这可能会导致不希望的结果:

这不是一个 bug,而是 Python 的工作方式。该列表是在定义类时定义的。每个实例都获得一个对该列表的引用,因此所有实例共享该列表。这只适用于可变对象。不可变对象通常会在再次更改时获得一个新的引用,因此会覆盖以前的引用。请注意,不要使用默认方法在构造函数中定义所有参数(通常应该使用这种方法)。

我们添加到 self 对象的所有变量都可以使用点符号来访问。一般来说,对象中的所有变量都称为属性,而所有函数都称为方法。两者都应该有唯一的名称,并且可以使用<object name>.<attribute name><object name>.<method name>()来访问。这与 Python 中任何对象的符号相同。字符串和整数都是具有相同方法论的对象。然而,这些类定义了更多的方法。如果对象被加在一起,或者如果对象被相乘,有一些特殊的方法来处理对象的打印。我们还可以定义这些,并根据这些定义制定我们自己的规则:

该类还有两个 dunder-方法。第一个负责类的表示。如果我们简单地输入代表类实例的变量名,即 number1,它将调用 repr dunder-method 并返回它的表示。这个方法必须返回一个字符串,但是这个字符串是什么,我们可以自由定义。第二个 dunder-method 定义了如何添加两个对象。它期望作为一个参数,紧挨着强制的 self 对象,也就是另一个对象。从技术上来说,这可能是任何对象,我们必须在做加法之前测试它是哪种类型。现在,我们假设它将是相同的类型。这可以是任何定义,甚至是我们在这个例子中所做的其他东西。这是非常强大的,因为你可以定义对象,例如联系卡,并使用添加功能,合并两个联系人。当我们使用 Pathlib 模块中的 Path 时,我们看到了一个有趣的例子。路径定义了 divide dunder-method,它将路径:

对于每个数学运算,都有一个可以定义或重载的 dunder-method 。重载意味着你用一个新的定义覆盖一个现有的方法,这个方法可以是一个常规的方法或者是一个 dunder-methods 中的一个。还有几个其他的 dunder-methods ,例如迭代相关的主题。不需要很努力地去了解他们,但是知道他们的存在确实很好。

今天的练*:

作为一种抽象形式,类是很棒的,特别适合于表示我们在现实生活中知道的对象。许多游戏都需要骰子来玩,有各种各样的骰子可供选择。有些人只有四张脸,而有些人可能有 100 张脸。

赋值:
创建一个骰子类,输入面的数量作为参数。它应该有一个 throw()函数来掷骰子,当然是使用正确的骰子,即一个四面骰子只能掷出 12、3 或 4 个骰子。它还应该包含一个 history()方法来显示过去的骰子点数()和一个漂亮的 repr dunder 函数来告诉我们是哪个骰子。

提示:
1。作为 randint(a,b)函数的随机模块在(a,b)之间(包括两个边界)生成随机数。可能对掷骰子有用;-).
2。你可以使用一个列表来跟踪所有以前的滚动。

在我的 Github 上发布了一个解决方案。

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 24

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-24-71adee92cb2d?source=collection_archive---------27-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

父母、子女和遗产

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

昨天,我们讨论了类以及如何使用面向对象编程(OOP)范例来解决问题。我们创建的对象可以模仿现实生活中的对象,数据和方法都捆绑在类中。我们还讨论了 Python 的一些内部工作方式:它使用 dunder-methods 来定义对象之间的交互。我们还没有提到的东西被认为是 OOP 的主要好处:继承。继承是创建一个新的所谓子类的能力,该子类从其父类继承属性。让我们看一个例子来说明这是什么意思:

虽然这很好,但我们都知道正方形是一种特殊类型的长方形,其长度和宽度都相同。编写两个单独的类看起来很湿,因为对象非常相关,我们可以利用继承:

在代码方面,我们有一个小小的好处,因为我们不必重复周长和面积的方法。然而,最大的好处是我们在一个地方而不是两个地方有这些方法的定义。如果我们在这两个方法中的一个上犯了错误,我们只需要修正一个定义。

现在让我们分析这里实际发生了什么。Rectangle 类没有改变,所以没什么好讨论的。然而,在主定义中,Square 类在括号之间添加了 Rectangle 类。使用这种语法,我们定义 Square 类是以矩形为基础构建的,因此继承了它的所有属性。接下来,我们定义一个构造函数,但是当我们从 Rectangle 类继承所有属性时,我们实际上覆盖了继承的构造函数。新的构造函数只取长度,因为正方形的所有边大小相等。现在来点特别的:我们调用构造函数或父类。为了访问父类,Python 有 super()函数。它返回父类的定义,通过直接调用 dunder init 方法,我们可以调用原始构造函数。原始构造函数需要一个长度和宽度,我们通过输入两次长度来提供。原始构造函数将这些值添加到保存实例数据的 self 对象中。新定义也覆盖了 repr dunder 方法。如果我们没有覆盖该方法,它将使用 Rectangle 类中的方法。这是另一个例子:

在这个例子中,我们还有一个更一般的类叫做 Animal,还有一个类是 Animal 类的子类。由于继承,Bird 类从 Animal 类获得所有属性。因为它是一只鸟,所以它得到了另一个名为 Fly()的方法,我们覆盖了这个构造函数,这样就简单了一些。

使用 Imgflip.com 生成的迷因

我们可以让它变得更有趣。一个子类可以有多个父类,因此可以从多个其他类继承属性。虽然这听起来很神奇,但很快就会变得非常混乱。让我们来看一个有三个不同父类的子类,它们实际上是独立的类,即不是专门为多类继承设计的:

这里我们有三个独立工作的类。使用多重继承,我们将这三个类组合成一个定义:HeavyRedSquare 类。新类必须调用所有其他构造函数来初始化这些值。我们可以使用 super()函数来做到这一点,但是这看起来很混乱。第一个 super()调用,不带任何参数,调用第一个父类构造函数(括号中最左边的那个)。在第二个 super()调用中,我们传递了两个参数。第一个参数是几何类,第二个参数是该类的实例对象。这里发生的事情是,我们在几何类中,它本身有颜色类作为父类。调用 super(),现在访问 Color()的构造函数。同样的情况发生在第三个 super()调用中。在这个定义中,权重类是颜色类的父类。以这种方式调用 super,可以访问 Weight 类的构造函数。对于更高级别的构造函数,我们需要传递 self 对象。在第一级,即普通超级()中,它被自动传递。这种写作方式让我很困惑。因此,还有另一种方式我更喜欢,在我看来更干净:

这种方式直接调用类构造函数。因此,我们需要传递 self 对象,即属于这个实例的数据。这是一种我们可以组合对象的方式,也可以独立工作。大多数情况下,当使用继承时,类被设计成一起工作。从这个简单的例子可以看出,它很快就会变得非常复杂。

更常见的是对象是链式继承的。这意味着一个类有一个父类,这个类本身也有一个父类,等等。在 Python 中,一切都是对象,我们已经多次提到过。但我们实际上是指字面意思。Python 中的所有类型都基于对象类型。有一个特殊的 dunder 属性(它不是一个方法)跟踪所有的父节点,顺序是:

所有这些继承的一个恼人之处是在对象中找到方法的源代码。当手动查找特定方法的源代码时,我经常不得不在层次结构中从一个类向上查找另一个类。当使用更高级的 IDE 时,这可能更简单一些。

了解最后一种特殊类型的继承是很重要的:mixins。mixin 是一种设计用来与其他类结合的类,单独实例化没有意义。除了没有构造函数之外,与常规类没有太大区别:

Mixins 非常适合在函数中添加一个通用的保存到磁盘的函数,同样有助于集中您的代码。从这一课中可以学到很多东西。如果你没有得到全部,不要太担心。掌握正在发生的事情是最重要的。继承经常被使用,多重继承不太多。看到后者大多是一个很好的了解。

今天的练*:

继承和混合是很好的概念。让我们一起玩吧。这里有两类形状:

赋值:
写一个 Mixin 来数每个形状的角。

一个解决方案是在我的 Github 上发布

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 25

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-25-a14ac87d16d2?source=collection_archive---------43-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

应得的自创证书

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

今天是每天学* Python 10 分钟的第 25 集。如果你在这里,你应该感到自豪,因为我们已经讨论了 Python 语言的基本、中级和一些高级*惯用法。足以启动您的 Python 开发生涯。我的第一个想法是用一些真实的例子(使用一些库)来结束这个系列。这些例子包括数据可视化、使用矩阵、神奇熊猫图书馆和一些 Scikit-Learn 主题。虽然,我可能仍然会创作这些文章,但它们会在今年晚些时候以一个独立的系列发表(当然不是每天都发表)。如有任何要求或建议,请随时联系我。

当完成一门在线课程时,你经常会在你的 LinkedIn 上获得一个证书来分享。既然你已经做到了这一步,我认为你在这个系列中得到一个也是很重要的。为了证明 Python 是一种通用语言,我们将自己创建一个令人印象深刻的证书!如果你真的把这个贴在你的 LinkedIn 上就太好了,请不要忘记给我加标签。我将祝贺你的成就!好了,让我们尽可能用 Python 的方式创建我们的 Python 证书吧!首先我们需要三个库: matplotlibpillow 用于处理图像,以及 wget 用于下载所需的字体。

使用 Linux 的人可能已经听说过 wget ,这是一个用于从互联网下载文件的命令行界面(CLI)实用程序。在这里,我们已经下载了 wget 的 Python 版本,它可以在任何机器上工作,并使用它来下载字体。现在让我们介绍生成证书的函数:

这是一段很长的代码,但是它确实创建了一个完整的证书,具有人们所期望的所有功能。我们首先导入 pillow 的三个部分,缩写为 PIL: Image、ImageDraw 和 ImageFont。第一个模块保存图像,第二个模块添加许多绘图功能,最后一个模块添加文本绘制功能。另一个新的东西是魔术选项%matplotlib inline,它确保我们将绘图写入笔记本(这在早期是必需的,不确定是否仍然需要)。证书功能本身利用了 pillow 的绘图功能。我们添加了一个双线边框,并在顶部和底部添加了一些矩形。接下来,我们添加两种不同字体的居中文本。为了正式起见,我在底部加上了当前日期和我的签名。我们可以用幸运儿的名字来调用函数 We,它会把图像写到屏幕上。它应该是这样的:

我们非常正式的证书。

嗯,这看起来是合法的(-:。这项工作的最大部分是微调设计。创建单独的组件相对容易。函数中的最后一个操作是将证书作为便携网络图形(PNG)写到磁盘上。所以现在在 LinkedIn 上分享,给我贴标签,超级容易;-).

现在怎么办?

你的下一个问题可能是,现在怎么办?从普通 Python 的角度来看,您现在已经知道了所需的大部分内容。但是在现实生活中,大多数人都是用包来解决自己的问题,有无数的包可以探索。如果你想进入科学计算或数据科学/机器学*领域,下一个合乎逻辑的探索步骤是 Numpy

Numpy 在 Python 中增加了对大型多维数组和矩阵的支持。如果没有 Numpy,我们可能会创建一个列表,这将非常好。Numpy 牺牲了列表中包含任何对象的灵活性,而将固定类型(通常是数字)作为数组,并以惊人的速度编译代码来处理它们。Numpy 比普通 Python 快得多。但是和普通 Python 一样,学*概念需要一些时间。Pablo Carares 为 Numpy 制作了一个惊人的指南,强烈推荐您从那里开始。

Imgflip.com 上产生的模因

如果你知道 Numpy 是如何工作的(你不必是一个 Numpy 大师),下一步肯定是熊猫。就个人而言,我是熊猫的超级粉丝!它提供了一种与你的数据交流的语言。掌握流利的熊猫语有很多好处,我真的建议在这项技能上投资。从熊猫开始,在熊猫文档中有熊猫 10 分钟。每年,PyCon 上都有很棒的教程。我非常喜欢 Brandon Rhodes 在 2015 年的演讲。陈琦程也做了一个很好的关于熊猫的初学者教程。变得擅长熊猫!我保证你会喜欢的!

当你对熊猫感到舒适的时候,接下来的事情就是做数据可视化。绘图本身可以用许多不同的库来完成。一开始,几乎所有人都使用 Matplotlib。它很容易使用,但有其微妙之处。现在,我通常使用 Seaborn ,这是一个基于 Matplotlib 的框架,具有更好的默认设置和更简单的语法。这些不是唯一的选择,还有以及散景,实际上还有更多。我还是觉得从 Matplotlib 开始比较有用。在那之后,如果你想要更多的视觉享受,就选择其他的。

有了所有这些,我们终于准备好看看一些机器学*的东西。虽然我们可以马上去 Scikit-Learn ,我还是建议你去Kaggle.com吧。Kaggle 是以基于问题/项目的方式学*数据科学和机器学*的终极资源。如果这是你的第一次,点击过去最喜欢的泰坦尼克号比赛。这是一个介绍性的比赛,做起来很有趣,你可能还会从比赛中学到一些历史事实。

你成功了!

这是 Python 每天 10 分钟系列的结尾。肯定有一些主题我们没有讨论,比如多处理/多线程或者许多优秀的库和框架的例子。然而,这些确实需要超过 10 分钟。在不久的将来,我可能会写一些这样的教程。如果你有兴趣,请随时联系我。

现在,谢谢你们能走到这一步。我已经通过 LinkedIn 收到了一些积极的信息和反馈。但是,我仍然不知道到底是谁制作了这个系列。所以,如果你想帮我一个忙,把你辛苦挣来的证书放在 LinkedIn 上,给我加个标签。我保证祝贺每个人的成就!一如既往,如果有任何问题、意见或评论,请随时联系我

每天 10 分钟学* Python # 3

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-3-af2967c34a36?source=collection_archive---------48-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

评论:Python 忽略的对你有用!

这是一个系列的 10 分钟 Python 短文,帮助你开始学* Python。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您想了解关于 Python 特定主题的问题或请求,请随时通过 LinkedIn联系我。

每个人都知道评论是重要的,对于每个项目,你可能会对自己说:‘在下一个项目中,我会更加注意评论’。有了笔记本,你已经有了一个很好的结构,但是定期的评论还是很有用的。有时,注释可以帮助解释某个假设或为什么选择某个设置。或者简单地对参数进行内嵌解释。此外,当从一开始就添加特殊的注释(比如 docstrings)时,如果您需要将笔记本转换成常规的 Python 脚本(这非常简单),您可以立即嵌入解释。

Python 中的注释以“#”开头。当 Python 看到 hashtag 时,它会忽略该部分后面的所有内容。此外,在调试或尝试不同的算法编码方式时,注释掉代码是很有用的。在许多编辑器中,包括 Jupyter,您可以使用“ctrl-/”来注释/取消注释一行。这适用于当前行或选定的多行。

作为一种格式标准,建议在内联注释和实际注释之间留两个空格,就像前面代码中所做的那样。添加评论很棒,尽量做到完整。然而,要避免的一件事是过度评论。过度评论意味着你评论了显而易见的东西。对于 Python 来说尤其如此,它被设计成可读的。例如,做一个注释,说您将导入包,然后输入 import 关键字,这显然是过度注释,没有添加信息。

其他语言,如 C 或 Java,能够创建多行注释。Python 本身没有多行注释,最好的方法是在每一行的开头使用一个标签。在特殊情况下,您可以使用三重引号创建多行注释。这实际上不是注释而是多行字符串,没有赋给标签。如果没有赋值,Python 解释器会忽略它。从技术上讲,您可以将这些未赋值的字符串放在代码中的任何地方,但是当将它们放在类或函数定义中时,它们就有了 DocString 的含义。文档字符串是描述函数的一小段特殊注释。虽然您可以自由地为 DocString 创建自己的格式,但是一些大型项目(如 Pandas 或 Numpy)已经对这些格式进行了标准化。熊猫有一个很好的关于如何构建它们的指南。然后这些被用来自动创建文档。我们还没有讨论创建函数,但是我认为这个例子会很清楚:

有不同的方式来设计它们,但是关键的元素是可读性。获得前面代码片段中描述的函数是非常清楚的。我们可能会认为函数名已经足够清楚了,因此,我们做了一些过度注释,但是你可能会创建更复杂的函数,你的同事和很可能还有你未来的自己,会感谢你做出高质量的注释和文档字符串。

DocStrings 通常是个好主意的原因是,在 IPython 和相关的任何地方都可以访问它们。如果您不确定某个函数的参数是什么,或者完全忘记了该函数是做什么的,您总是可以使用“?”来访问 DocString。通过键入函数,而不是写括号,您添加一个问号,您将获得该函数的 DocString。如果您使用的是成熟的 IDE,当您将鼠标悬停在某个函数上时,或者当您在括号之间时,有时会显示这些信息。我发现这些东西会让人分心,通常会把它们关掉。如果你喜欢这些东西,Visual Studio 代码当然不错,我还记得 Jupyter 实验室有一个插件可以做到这一点。

要获得 Python 中某个函数的帮助,只需添加一个?而不是括号。

今天的练*:

  1. 在一个新的笔记本上创建一些简单的计算。
  2. 围绕您的计算添加注释,并添加行内注释
  3. 使用 ctrl-/注释和取消注释行。
  4. 为以下函数创建一个 DocString:

5.使用“?”获取您自己函数的帮助

如果您有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 4

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-4-df06c3c2e6e8?source=collection_archive---------56-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

数字变量以及如何在 Python 中给它们赋值

这是一个系列的 10 分钟 Python 短文,帮助你开始学* Python。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您想了解关于 Python 特定主题的问题或请求,请随时通过 LinkedIn联系我。

在这节课中,我们将讨论变量赋值和数字。正如您在之前的几次会议中所记得的,Python 是动态类型化的。这意味着您不必将类型赋给变量,而是在赋值时自动分配类型。如果我们指定一个没有点的数字,它将被指定为类型 int (整数),如果它有点或小数,它将被指定为类型 float (浮点):

动态类型的一个好处是,一般来说,你不必担心类型转换。如果需要,该值将被转换为类型 float 。与 Python 中的几乎所有类型一样,类型 intfloat 是不可变的,并且在创建后不能更改。当进行基本算术运算时,输入值用于创建新的实例,即新的 int 或 float 值。如果这替换了对前一个结果的引用(变量),垃圾收集将删除该对象。

当然,显式地改变类型是可能的。例如,要将 float 转换为 int,可以使用 int()对它们进行强制转换。但是,此操作将截断所有小数。如果该值为 4.999,int(4.999)将返回 4。如果要四舍五入,可以使用 builtin round()函数。对于向上舍入( ceil )和向下舍入( floor ),您可以从标准库中导入它们(在后面的会话中将详细介绍导入)。使用截断或舍入时要小心。1982 年,范库弗峰证券交易所意外地使用了截断而不是舍入,因此,神秘地降低了他们的指数(钱正在消失)。这种类型转换也用于将文本转换为值,但是要小心,因为字符串应该是有效的数字。

我们刚刚看到了内置方法 round,还有几个,即整数除法、绝对值、模数和复数。这些不常用,但值得一提。

使用变量时,需要先对变量赋值,然后才能使用它们。这可能不足为奇。令人惊讶的是你分配变量的方式。您可以将多个赋值链接起来,也可以使用一种叫做元组解包的技术。当我们讨论元组时,后一个术语将更有意义。下面的例子展示了元组解包,这可能不难理解。

Python 中的 int 值是不受限制的,也就是说,你可以在一个 int 变量中存储任意大的值,它只受系统内存大小的限制。这与许多其他语言不同,在这些语言中,如果不使用额外的包,您只能使用 64 位。float 类似于 double 的 C 实现,它是一个 64 位浮点变量。限制相对较大,但如果您需要更大的数字或更高的精度,您可以使用标准库中的十进制包。float 类型也有特例,它们本身就是有效的 float。比如可以将 infinity 或者 -infinity 定义为 float(a = float(' infinity '))。另一种特殊情况是 nan,它代表“不是一个数”,当一个数没有被定义时(如果没有出现异常),它被赋值。NaNs 也常用来表示缺失的数字。将来,我们会花一些时间处理 nan,因为有时会很棘手。这些特殊情况是通过在内置的 float 类中放入一个字符串(不区分大小写)来调用的。

今天的练*:

  1. 在新的笔记本中,分配各种 int 和 float 值。
  2. 使用新变量进行一些计算。
  3. 测试所有讨论过的舍入策略。
  4. 算“1.2 - 1”。解释为什么这不是一个错误。
  5. 你觉得 float('nan') == float('nan ')等于 False 很奇怪吗?

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 5

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-5-9e012c6920e0?source=collection_archive---------37-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

变量:使用字符串表示文本

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您想了解关于 Python 特定主题的问题或请求,请随时通过 LinkedIn联系我。

在第一节课中,我们已经看到了内置的“ print ”功能,它可以将文本、数字,实际上是任何东西打印到屏幕上。要调用一个函数,我们需要输入它的名字(在这个例子中是 print ),后面跟着一组括号。在括号之间,传递函数的参数。内置函数不需要任何参数,可以使用:" print() "调用,将一个空行打印到屏幕上。我们给它传递了一个参数,那就是一个简短的句子“hello world”。这个参数是一个“ str 类型的对象,在 Python 中是一个字符串。使用“?”检查内置打印功能的文档字符串我们以前学过。

可以使用单引号、双引号或由三次引号符号表示的多行变体来分配字符串。我们在创建文档字符串时已经看到了最后一个方法:

变量名可以是任何东西,除了像“是”或“不是”这样的关键字。函数“print”不是这些关键字中的一个,而是一个标准函数,从技术上讲,您可以用一个新变量覆盖这个函数。Python 中的一切都由对象表示,变量只是一个标签。通过声明一个名为“print”的字符串,标签现在指向新创建的字符串,这在 Python 中完全有效。当然,这可能不是你想要的,所以要小心。选择名字时,尽量简短,所有小写字母和单词用下划线隔开。虽然这样定义变量不是强制性的,但这是一个标准,在著名的 pep8 (Python 增强提案#8)中有记载。有许多 pep 文档,但 pep8 是一个帮助提高可读性的样式指南。这个文档太长了,很难记住,因此,有一些助手可以帮助你设计代码,比如黑色或者薄片 8 ,但是我们将在稍后的阶段研究这些。由于这些自动格式化程序不能帮助您处理变量名,所以请尝试使用建议的约定。它将帮助你使你的代码可读。

来自文档:字符串是 Unicode 码位的不可变序列。这意味着一个字符串是一个字符序列,由于它是不可变的,赋值后不能改变。当我开始学* Python 时,术语“不可变的”让我很困惑。为什么我们要有一个字符串,它在定义后不能改变。他们所说的不可变是指,如果我们在一个字符串上做一个操作,原来的字符串不会改变,但是会从结果中创建一个新的字符串。如果您将结果放入原始变量(具有相同的名称,即引用),当变量指向您的新结果时,您将覆盖对旧对象的引用。如果原始对象没有被任何其他变量引用,Python 使用其垃圾收集器从内存中删除该字符串。

有相当多的操作可以在字符串上执行。最常见的操作之一是连接字符串,就像我们将两个数字相加一样(使用“+”运算符)。虽然不太常见,但您也可以使用' * '操作符将字符串相乘,以从原始字符串的倍数创建新字符串。我猜用途很具体。

因为它是一个字符序列,所以它有一个序列长度。为了得到长度,有内置的“len”函数。序列的另一个特性是我们可以非常容易地迭代字符。我们还没有讨论 for-loops,但是它的语法可读性很强,所以我很确定你会看到下一个例子。

Python 中的一切都是对象,因此每个对象都打包了相关的方法。str 类有很多方法可以选择,我一般都会忘记,不得不 Google。在 Jupyter 或 IPython 中,你可以用点号键入变量的名称,然后按获得建议。

制表符补全是每个人的朋友!

这些方法中的大多数都有不言自明的名称,如“lower”、“upper”和“isdigit”。其他人可能需要一些解释,我们可以随时查看 DocString。我经常使用的方法是。split(),。替换()和。加入()。当这些方法返回一个新的字符串时,你可以链接多个命令。所以做 my_string.lower()是非常有效的。分裂()和更长的链甚至是可能的。创建链时,请记住可读性。

另一种可能用于字符串(因为它们是序列)的技术是切片。虽然分割字符串可能有非常具体的用例,但过程与其他类似序列的数据类型是相同的。通过切片,您可以选择序列的 iᵗʰ元素,方法是在方括号中指明它的序号。Python 从零开始计数,所以第一个元素表示为“my_string[0]”。您也可以选择一个元素,从后面用负数计数。字符串的最后一个元素是“my_string[-1]”。如果您想选择多个字符,您可以使用一个由[start : end : step]构成的范围。在 Python 中,范围包括“开始”元素,但不包括“结束”元素。步长表示您跳过了多少个字符。如果将步长设置为 1,则选择所有字符,如果步长为 2,则跳过第二个字符。没有必要提供全部(开始、结束、步骤)。如果没有提供步长,则使用默认值 1。只提供结尾,所以分号前没有值,意味着到结尾为止的所有内容(但不包括)。这里有几个例子:

一个重要的主题是字符串的格式化,即创建在变量中显示动态内容的字符串。在过去的几年里,这样做的方式已经改变了几次。首先,有 percent 操作符,它起作用,但不是很好。后来。format()方法被添加到字符串中,以提供更大的灵活性。从 Python3.6 开始,f 字符串变得可用,这增加了更多的灵活性。f 字符串是一种特殊类型的字符串,由字符串前的“f”表示。在我看来,f 字符串也比。format()方法,因此,我建议尽可能使用 f 字符串。格式化选项不仅仅限于显示变量本身,还可以添加填充、数字精度、类型等等。这里有一个很棒的小抄

有许多关于字符串的细节,我的一般建议是当你需要它们的时候研究一下。随着时间的推移,你甚至可能记得一对夫妇;-).

今天的练*:

  1. 在一个新的笔记本中,分配不同的字符串。
  2. 使用方法更改下面的字符串:“我叫吉米,我 100 岁了”,以获得您的姓名和年龄。(提示:replace())
  3. 从以下字符串中切分并组合出'我很快乐':
    c,d = '我很悲伤','我希望我很快乐'
  4. 摆弄几根 f 弦,例如显示不同精度的数值,创建不带小数的百分比。

如有任何问题,欢迎通过 LinkedIn 联系我。

下一期(#6)将于周一发布。

每天 10 分钟学* Python # 6

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-6-4a61ddc8747d?source=collection_archive---------64-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

Python 中的条件句:if、elif 和 else 结构

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您想了解关于 Python 特定主题的问题或请求,请随时通过 LinkedIn联系我。

您可能已经知道缩进是 Python 中的一个特性。代码块不是使用花括号或 begin/end 语句,而是按照缩进级别进行分组。一开始,这可能看起来有点奇怪,但这是 Python 可读性如此之好的核心机制之一。你可以自由使用任何数量的缩进,例如两个空格,但是,在默认样式中( pep8 )推荐使用四个空格。如果你选择不同的金额(你不应该这样),或者如果你想使用标签(请不要),这是好的(只有有充分的理由),但你必须保持一致。如果不一致,会出现缩进错误。为了最大限度地减少这些错误,我强烈建议使用一个可以将 tab 键设置为四个空格而不是制表符的编辑器。几乎任何文本编辑器都有这个特性。

既然我们知道缩进很重要,我们可以讨论一个实际使用不同级别嵌套代码块的构造:if-else 语句。这些条件语句在几乎任何编程语言中都是非常常见的构造。它们测试某个条件,如果成功,则运行一条或多条语句,如果条件不成功,则可能运行一组不同的语句。下面是 Python 中一个简单的条件结构:

语法并不难理解。if 语句以 if 关键字开始,后跟一个条件。该条件可以是任何呈现为布尔值的条件。在 Python 中属于 bool 类型的布尔值要么为真(注意大写),要么为假。就像我已经说过很多次一样,Python 中的一切都由一个对象来表示,True 和 False 是已经为您创建的特殊对象。如果变量为真,则该变量指向这个特殊的真实例。在前面的例子中,我们使用双等号()测试变量 a 是否等于 30。如果是这种情况,这将导致 True,否则将导致 False,因此,总是呈现为布尔值。其他条件运算符有大于 ( >)、大于等于 ( > =)、小于 ( <)、小于等于 ( < =),或者不等于(!=).在条件语句之后,分号表示代码块的开始(后面是缩进的语句)。还有一个常用的特殊关键字:is 关键字类似于,但是它测试两个变量(引用)是否指向同一个对象。在 Python 中只有一个真对象,如果两个变量都为真,那么它们指向内存中的同一个对象。我们稍后会了解到,当时,语句相当有用。

Python 以线性方式运行代码,这意味着它从顶部开始,并顺序执行每条语句。这也是我们上面构建的 if-else 语句的情况。首先,它将测试第一个条件,如果这是真的,它将运行缩进的代码块中的代码,但 if-else 构造的其余部分将被忽略。只是,如果 if 语句的第一部分为假,它将继续到下一部分。这可以是 and elif 或一个‘else’。eli 是 else if 的一个更短的符号,在这里你可以测试另一个条件,如果条件为真,后面是另一个缩进的代码块。可以有任意数量的 elif 语句。if-else 结构中最后一个可选语句是 else 语句。这不测试任何条件,但如果 ifelif 语句都不为真,则执行该操作。执行 else 语句后缩进代码块中的所有语句。

如果要测试多个条件呢?对此,有几个逻辑运算符,类似于其他语言,即: and,或not 。这些逻辑运算符“组合”两个布尔值来创建一个新条件。操作符要求两个值都为真,以产生真,而操作符只要求其中一个值为真,以产生真本身。 not 运算符反转布尔值,即 not(True) == False。如果一个变量本身是布尔值,你可以直接测试它的条件。测试像 raining_outside == True 这样的条件是完全有效的,但是,如果布尔变量为 True,则测试 True == True。因为 if 语句需要一个布尔值,所以有一个就足够了。

这就是你需要了解的关于 if 语句流的全部内容。有几个细节很好了解,但不经常使用,但在特定情况下可能有用。例如,对象的一些方法返回一个布尔值,这些可以用 if 语句来测试。上周五我们学*的 str 对象有许多可以直接测试的方法。这些方法通常以 is…()开头,例如: isdigit()isspace()isupper() 。当然,你可以使用任何方法,使用条件运算符创建一个布尔:my _ string . count(' ABC ')= = 2

字符串,实际上是 Python 中的任何序列类型,也可以测试列表中的子序列。这是使用关键字中的完成的,对我来说这感觉很自然。例如,要测试单词“python”是否在字符串“I think python is easy”中,您需要做的唯一事情就是将放在字符串之间的中:“python”放在“I think python is easy”中。如果子字符串(左边部分)在主字符串(右边部分)中,则返回 True。我们将在后面看到类似的模式被用于列表数据类型。

与其他语言类似,也可以创建单行和内嵌 if 语句。这些有时是有用的,但是尽量限制它们,因为它们会扰乱可读性。我认为它们在列表理解中最有用,我们稍后会看到,但是单行/内联 if 语句在 Python 中是有效的。

需要记住的一个细节是,有两种方式来书写,即仅仅是单词(就像我们刚刚做的那样)和分别使用符号 &| 的简写符号。官方说法是,第一种方式是“逻辑与”和“逻辑或”,而后者是“按位与”和“按位或”。对于布尔值,它们在普通 Python 中的含义是相同的,但是在使用其他包时,它们的定义是不同的。例如,像 Numpy 和 Pandas 这样的包创建了由数组或表格数据组成的新数据结构。通常,您希望一次测试多个布尔值(例如熊猫数据帧的所有行)。在这些包中,仍然被定义为测试单个布尔值,而 &| 被定义为测试整个列表,从而用条件测试列表的每一项。如果这还不清楚,我们将在讨论列表时举例说明,所以现在不要担心。

最后一个可能有用的东西是 pass 语句。这只是一个不做任何事情的占位符,用于创建一个空的代码块。当您创建一个 if 语句时,如果条件为真,它至少需要一个语句。如果你还不确定它是什么,你不能让它为空,因为你会得到一个缩进错误。对于这种情况,您可以使用 pass 语句。

今天的练*:

  1. 在一个新的笔记本中,分配各种数字字符串,并测试这些字符串是否是数字。
  2. 测试字符串“3.1415826535897”的前八位是否至少与圆周率的实际值相同。(提示:要获得 pi,首先要有“import math”和“pi = math.pi”。您可能需要将其转换为字符串;-))
  3. 创建 if 语句异常:if 语句中的 if 语句,因此是嵌套的 if 语句。

如果你有任何问题,请随时通过 LinkedIn 联系我。

每天 10 分钟学* Python # 7

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-7-5390dd024178?source=collection_archive---------58-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

Python 中最全面的数据类型:列表

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您想了解关于 Python 特定主题的问题或请求,请随时通过 LinkedIn联系我。

今天我们来看看列表,就数据类型而言,它可以说是 Python 的主力。列表可以被看作是一种容器,可以存储各种信息。这可以是数字、字符串、函数,也可以是任何其他对象(还记得在 Python 中,一切都表示为一个对象吗?).Python 列表是非常通用的,你可以混合和匹配任何你喜欢的对象。如果你愿意,你可以在你的列表中加入几个数字,三个字符串,甚至其他的列表。

是的,列表可以嵌套来创建你自己的“列表异常”。

列表中的列表中的列表中的列表(图片来源:knowyourmeme.com)

列表是使用内置类 list()或较短的括号符号创建的。需要记住的一件重要事情是列表是有序的。这意味着您向列表中添加项目的顺序是存储的。顾名思义,当我们将()项添加到列表中时,这些项会被添加到列表的末尾。使用 pop()方法,我们可以从列表中移除/获取最后一项。Pop 还可以通过索引删除特定项目。这里有几个例子。

列表是 Python 中少数几种可变的数据类型之一。Float、int 甚至 Strings 都是不可变的,每个操作都会创建一个新的实例。但是列表可以更改。例如,您可以将项目添加到列表中,但对象实际上是变化的。我们可以通过使用内置 id()函数来证明这一点。id 函数返回对象在内存中的地址,并且是对象的唯一标识符。让我们研究一下 int 和 list 的这些标识符:

我们刚刚看到,我们可以弹出()列表中的最后一项。为了在不删除项目的情况下获取项目,我们可以使用括号符号的索引方法。Python 从零开始索引,因此,列表中的第一项是 my_list[0] ,第二项是 my_list1等等。与字符串切片类似,索引必须存在,否则将出现“索引超出范围”错误。当您选择范围时,您将获得一个带有子列表的新列表实例。与字符串一样,我们也可以使用负值向后索引,并提供一个步骤。也许你对字符串没有意识到这一点,但是通过一个负的步骤,你可以反转一个字符串或列表:my_list[::-1]或 my_string[::-1]。列表的基本算法如预期的那样工作:用+将两个列表相加,而用将两个列表相乘。两者都返回一个新的列表实例。要创建一个列表的副本,仅仅写 my_new_list = my_old_list 是不够的。这只是复制引用,而不是列表本身。要创建一个真正的新列表,您需要使用 list 类:my _ new _ list = list(my _ old _ list)显式地创建一个列表。切片也返回一个新的 list 实例,所以你也可以通过简单的切片‘all’生成一个副本:my _ new _ list = my _ old _ list[:]*。然而,最后一个切片技巧不适用于字符串。字符串是不可变的,因此不会改变。Python 足够聪明,可以检查具有所需特征的不可变对象是否已经存在于内存中,并将返回一个指向该对象的指针。因此,my_string[:]将返回对同一对象的引用。

列表有许多内置方法。例如,要检查一个列表的长度,即列表中有多少项,我们可以使用 len() 方法。这也非常类似于字符串,其中 len() 返回序列长度(字符数)。两者如此相似的原因是两种类型都是从 iterable 类构建的。其他内置方法例如有 min()、max()、sum()、count()、find()、reversed()、remove()、sort() 。如果您想使用这些方法,可以随意检查它们的文档字符串,或者检查带有制表符结束的方法的完整列表。

在上一篇文章中,我们学*了关键字中的,它可以用来在字符串中查找子字符串。这也适用于在列表中查找项目。列表是引用的有序容器,将检查列表中是否有该项目的引用。如果是这样,它将返回 True,否则返回 False。测试列表是否为空的 Pythonic 方法不是检查列表的长度是否为 0。虽然这样做了,但是列表有一个属性,当它们为空时为 False,如果它们至少包含一项,则为 True。这使得空头支票非常方便。

我们已经提到过元组解包。这是一种从列表或元组等可迭代对象中系统地获取值的技术。之所以这样称呼它,是因为它通常用于元组,但它也同样适用于列表。最显式的方法是在等号前有变量名,用逗号分隔,右边有 iterable:a,b = [12] 。Python 还有一个针对列表的 unpack 操作符,它是放在列表前面的操作符。解释器对链表的解包方式如下:12,3】->12,3* 。如果您想将列表中的单个参数传递给函数,这很有用。反之亦然: a,b,c,d = [12,3,4,5]* 。在此设置中,列表的前两个值将被解包到变量 ab ,最后一个值将被解包到 d 。中间的所有值在 c 中解包。这种情况最常见于带有args 和**kwargs 的函数,这些函数可以接受任意数量的参数。在这里, *操作符是映射(字典)的解包。这到底意味着什么是另一个时间。

今天的练*:

a. 在一个新的笔记本中,创建一个空列表,并追加几个值(数值、字符串和列表)。你还能在列表中追加一个值吗?提示:索引+追加()

b. 用以下列表:

my_list = ['This', 'is', 'a', 'list', 'of', 'words', '!']

加入列表以创建字符串。提示:string 有一个排除列表的 join()方法。

c. 有以下列表:

coffee_drinkers = [“Alfred”, “Dennis”, “Rob”, “Coen”, “Coen”, “Alfred”, “Jeroen”, “Hendri”, “Alfred”, “Coen”, “Rob”, “Dennis”, “Rob”, “Dennis”, “Rob”, “Coen”, “Rob”, “Alfred”, “Jeroen”, “Hendri”, “Alfred”, “Coen”, “Rob”, “Dennis”, “Coen”, “Dennis”, “Rob”, “Jeroen”, “Jeroen”, “Alfred”, “Jeroen”, “Hendri”, “Alfred”, “Coen”, “Rob”, “Dennis”]

a)供应了多少咖啡?谁喝了最多的咖啡?c)以相反的顺序对列表进行排序。

如有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 8

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-8-5e835880f284?source=collection_archive---------58-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

Python 中的循环:暂时

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

今天我们将讨论循环。有两种不同类型的循环,即 for 循环和 while 循环。两者在几乎任何编程语言中都被大量使用,当然这是有原因的。代码中经常出现重复。例如,您有一个值列表,需要过滤低于某个阈值的值。解决这个问题的一种方法是使用 for 循环遍历所有值,并测试该值是否低于设置的阈值。当然,还有其他方法来解决这个问题。

for 循环和 while 循环都有不同的用例。和前面的例子一样,for 循环用于迭代某些东西。这可以是一个简单的计数器(一个值列表),一个字符串列表,实际上是放入 iterable 的任何对象。因此 for-loops 将遍历一个固定的列表。while 循环有不同的目的,因为它不遍历列表,但有一个在每次迭代前测试的条件。如果条件为真,它将执行代码块,当条件为假时,while 循环结束。while 循环用于继续迭代,直到例如用户按下按键或者最小化过程已经达到某个精度。

在许多其他语言中,创建 for 循环来拥有一个计数器是很常见的,然后用它来遍历一个数据结构。在 Python 中,你可以直接遍历一个可迭代对象,比如一个列表。让我们来看一些例子:

for 循环以关键字的开始,后跟一个变量名。这个变量名将被用来引用列表的当前项。因为 Python 是动态类型化的,所以您不必为分配类型而烦恼。这将由 Python 解释器动态设置。变量名后面是关键字中的,后面是 iterable 和分号。与 if 语句类似,循环中的代码通过缩进来标识。缩进加上清晰的语义,使得这些循环可读性极强。

Python 已经打包了一些方便的工具来操作列表。例如,要反转一个列表,可以使用内置的 reversed()方法。这些类型的方法接受一个 iterable(比如一个 list ),并通过应用的操作返回一个新的 iterable。其中一些方法比如 reversed()也内置在列表类本身中( my_list.reverse() )。不同之处在于这些方法改变了列表本身(因为列表是可变的),并且不返回新的列表。

有时候,迭代的时候需要有一个计数器或者索引。对于这种特殊情况,Python 提供了 enumerate,它用连续增加的数字“压缩”你的列表。Zip 可以将多个列表组合成一个单独的 iterable,这个 iterable 可以在一个循环中解包。当然,所有列表的长度必须相同,否则会出现错误。

range()方法用于创建一个数字列表。它接受一个或两个边界值和一个步长。Range()返回一个特殊类型的 iterable,它是一个 range 对象(它不是一个生成器)。在前面的例子中,我们为 for 循环提供了一个列表。这个列表完全定义在内存中的某个地方,等待 for 循环引用。如果我们要对大范围的数字做同样的事情,我们首先需要创建这个列表。这可能会占用大量内存,尤其是当我们迭代数百万个值时( range(1e12) )。对于这种情况,Python 有生成器,这是一种“懒惰执行”的形式。仅当需要该值时,即当 for 循环请求该值时,才会生成该值。虽然 range 与 generators 有一些微妙的区别,但其思想有些类似:只在需要时获取您需要的值,而无需先创建完整的数字列表。

与 if 语句类似,for 循环也可以嵌套。当然,您需要确保两个 for 循环的变量是唯一的。第二个 for 循环从下一个缩进级别开始,并且随着每个 for 循环的增加而增加。虽然 Python 可以接受添加大量嵌套的 for 循环,但一般来说,三个是最大值。如果你最终使用了更多,是时候考虑减少循环次数的策略了。循环很慢,如果你需要大量的循环,矢量化可能是你想要的。

for 循环和 while 循环都有 breakcontinue 关键字来对循环流进行额外的控制。发出中断时,当前循环停止,即如果处于 for 循环,循环停止。如果您在嵌套的 for 循环中,则 for 循环的当前级别将停止。使用 continue 可以进入下一次迭代,忽略 continue 关键字之后的任何语句。这些关键字为流程提供了额外的控制,但是针对特定的用例。

我从未使用过 for-else 或 while-else 结构,但它可能有一些用例。然而,这很容易理解。如果 for 循环或 while 循环成功,即没有中断或错误,则执行 else 之后定义的代码块。

While-loops 是 Python 中创建循环的另一种构造。while 循环测试条件,而不是循环遍历 iterable。while 循环以关键字开始,而后面是条件和分号。

在基于 Python 的 restFul API 服务器中常见的一个构造是一个永无止境的 while 循环。这些循环会一直运行下去(或者直到用户中止程序(或者出现错误)),因为所提供的条件是常量 True。真,永远不会变成假,因为它是真中最真的,而只有通过 break 关键字或神的干预才能停止。while 循环中的条件类似于 if 语句中的条件。因此,您可以使用逻辑运算符( and、not 或)来组合多个。此外,如果您想稍后对循环进行编码,您可以使用 pass 占位符。

今天的练*:

a. 在一个新的笔记本中,创建一个 for-loop,对 1 到 100(包括 100)之间的所有值进行循环,并对所有值求和。(应该是 5050)

b. 循环下面的列表:

my_list = ['Alfred', 'Dennis', 'Rob', 'Coen', 'Coen', 'Alfred', 'Jeroen', 'Hendri', 'Alfred', 'Coen', 'Rob', 'Dennis', 'Rob', 'Dennis', 'Rob', 'Coen', 'Rob', 'Alfred', 'Jeroen', 'Hendri', 'Alfred', 'stop', 'Coen', 'Rob', 'Dennis', 'Dennis', 'Rob', 'Jeroen', 'Jeroen', 'Alfred', 'Jeroen', 'Hendri', 'Alfred', 'Coen', 'Rob', 'Dennis']

a)统计所有名字
b)统计所有名字,但使用继续关键字
跳过“Dennis ”; c)统计所有名字,但使用中断关键字在“stop”处停止

c. 使用 while 循环创建所有值的和,即 1 + 2 + 3 + … + n,其中 n 每一步增加 1。继续,直到总和大于 10000,并返回当前步骤 n。在 while 循环结束后,使用 else 构造打印该值。(应该是 142)

如果您有任何问题,欢迎通过 LinkedIn 联系我。

每天 10 分钟学* Python # 9

原文:https://towardsdatascience.com/learning-python-10-minutes-a-day-9-60ecdf101cb5?source=collection_archive---------47-----------------------

杰瑞米·拉帕克Unsplash 上的原始照片。

每天 10 分钟 Python 速成班

定义函数,停止重复你自己

这是一个系列10 分钟的简短 Python 文章,帮助您提高 Python 知识。我试着每天发一篇文章(没有承诺),从最基础的开始,到更复杂的*惯用法。如果您对 Python 的特定主题有任何问题或要求,请随时通过 LinkedIn 联系我。

你们中的许多人可能已经听说过 DRY 缩写:不要重复自己。有时你的同事开玩笑说你提供了一个湿的解决方案:我们喜欢打字。玩笑归玩笑,当你不得不重复某个步骤时,尽量减少复制和粘贴代码是一个好*惯。在一个富有成效的早晨之后,我们可能都有过这样的时刻,回顾我们的代码,一遍又一遍地看到相同的代码块。这通常是你意识到创建一个函数是个好主意的时候。

使用imgflip.com生成的迷因

函数是可重用的、专门为完成某项任务而设计的代码块。你已经看到了相当多的函数,即内置的 print()len() 。要调用一个函数,你必须键入它的名字,并在后面加上括号。不带括号的名字是指向函数的引用(Python 中的一切都是对象,记得吗?).可以不带参数调用函数,这意味着括号之间没有任何内容。然而,许多函数确实接受一个或多个参数,这些参数可以作为变量或值提供,用逗号分隔。使用 def 关键字,后跟一个函数名、一组括号和一个分号来定义函数。所有代码都是缩进的,类似于 for-loop 或 if-else 语句。按照惯例,函数的命名类似于变量名:所有小写字母用下划线分隔。尽量简短但简洁。为您创建的函数创建 DocString 是一个很好的做法。当然,当非常清楚函数的作用时,这不是必需的,所以在创建 DocString 或注释时使用常识来防止过度注释。

一个函数不仅仅要做一些事情,它还可以返回一个结果。在这个例子中,我们创建了一个给定值加 1 的函数。使用 return 关键字返回结果。要使用返回值,可以将结果赋给一个新变量,或者直接在函数中使用它。您可以返回任何类型的对象,例如 int、float、string、list、functions 或 multiple using tuples。Python 函数总是返回一个对象,但是,如果您没有“捕获”该对象,结果会被解释器垃圾收集并从内存中消失。如果您确实捕捉到了结果,并且该函数没有返回关键字,则返回 Nonetype 的一个对象。这是一个“无”的物体,也就是说,它什么也不代表。我们可以通过使用内置的 type() 函数来测试这一点,该函数返回对象的类。

函数采用的参数是动态类型的,不受 Python 本身的限制。当然,如果您提供了一个字符串,而函数试图对该字符串求平方,它将引发一个错误。类型检查是用户的责任,对于在多个用户之间共享的代码来说是一种很好的做法,尤其是在代码库很大的情况下。对于较小的项目和只为您编写的代码,您可以选择不进行类型检查,这样有可能会出现错误。开发人员喜欢更进一步,将 Python 的默认动态类型行为改为静态类型。从 Python 3.6 开始,您可以在函数定义中提供每个参数的类型和返回值。虽然我理解调试的好处,但我从来没有为此烦恼过。我想对于更大的程序来说,这可能更重要,但是对于数据科学来说,我认为数据完整性比静态类型更重要。另一方面,申请并不需要太多的工作。这里有一个关于 Python 中静态类型化的很好的指南。有时动态类型被用作一个好处。一个函数可以测试它的类型,并为不同的对象做不同的事情。像 Numpy 或 Pandas 这样的许多包使用它来从不同的数据类型创建数组或数据帧。如果我们将它静态地输入,我们将不得不为每个数据类型创建不同的函数。动态打字可能是一种福气,但对其他人来说也可能是一种负担。我从未发现它对我的任何用例有问题。

向函数提供参数的另一种方式是使用命名参数。这些也称为键值参数,以定义的参数名开始,后面跟一个等号和分配的值或变量。对于短函数,即只有一个或两个参数的函数,人们并不真的很麻烦,但当它是一个有许多参数的复杂函数时,这对可读性有很大的帮助。由于参数是显式分配的,因此它们的提供顺序并不重要。如果出于某种原因,您将命名参数与标准的顺序参数相匹配,那么顺序确实很重要,因此在这样做时应该小心。以类似的方式,也可以在函数的定义中提供默认值。这使该参数成为可选参数,因为它已经有一个赋值。所有没有默认值的参数都被自动标记为必需参数,如果不提供这些参数,将会引发错误。另一种常见的做法是将 None 类型指定为默认值。这使得参数是可选的,在函数本身中,您可以测试参数是 None 类型还是其他类型,并相应地采取行动。当然,这样的*惯用法在它们的用例中是相当具体的。

有时你可能会看到一个方法,让函数接受任意数量的参数。这个方法使用 unpack 操作符并收集另一个变量中的所有参数。它区分了命名参数和未命名参数。对于未命名的参数,它使用单星号*操作符,并将它们打包到一个元组中。命名参数是键值参数,是所谓的映射,使用**操作符收集并放入字典中。所以当你看到一个函数是用 *argskwargs 定义的,意思是参数和关键字参数,你就知道这个函数可以接受任意(或灵活)数量的参数。print()函数就是这样一个函数的例子。

今天的练*:

  1. 在一个新的笔记本中,创建你自己的正方形函数。该值接受一个数字,对其求平方,然后返回结果。
  2. 对于下面的列表:
    my_list = ['Alfred', 'Dennis', 'Rob', 'Coen', 'Coen', 'Alfred', 'Jeroen', 'Hendri', 'Alfred', 'Coen', 'Rob', 'Dennis', 'Rob', 'Dennis', 'Rob', 'Coen', 'Rob', 'Alfred', 'Jeroen', 'Hendri', 'Alfred', 'stop', 'Coen', 'Rob', 'Dennis', 'Dennis', 'Rob', 'Jeroen', 'Jeroen', 'Alfred', 'Jeroen', 'Hendri', 'Alfred', 'Coen', 'Rob', 'Dennis']
    创建一个函数,从列表中删除某个名字。该函数接受一个列表和一个名称,遍历列表,如果名称不是给定的名称,则将名称添加到一个新列表中,然后返回列表。
  3. 创建一个函数,返回数字列表中的所有偶数。该函数只接受最大值,默认设置为 100。在函数中,它在一个范围内循环,只将偶数放入一个新的列表中。它返回偶数的列表。你能用一个可选参数 odd 来扩展这个函数吗?提示:当取 2 的模(值% 2)时,偶数返回 0。

如有任何问题,欢迎通过 LinkedIn 联系我。

实践中的学*率计划:以 Keras 和 TensorFlow 2.0 为例

原文:https://towardsdatascience.com/learning-rate-schedule-in-practice-an-example-with-keras-and-tensorflow-2-0-2f48b2888a0c?source=collection_archive---------7-----------------------

添加和定制学*率计划的教程

卢卡·坎皮奥尼Unsplash 上拍摄

训练神经网络的一个令人痛苦的事情是我们必须处理的超参数的绝对数量。例如

  • 学*率
  • Adam 优化算法的动量或超参数
  • 层数
  • 隐藏单元的数量
  • 小批量
  • 激活功能
  • 等等

其中,最重要的参数是学*率。如果你的学*率设置得很低,训练将会进展得很慢,因为你对你的网络中的权重做了非常微小的更新。然而,如果你的学*率设置得太高,它会在你的损失函数中引起不希望的发散行为。

作者使用https://excalidraw.com/创建的图像

在训练神经网络时,随着训练的进行降低学*速率通常是有用的。这可以通过使用学*速率表自适应学*速率来完成。在本文中,我们将重点关注在我们的机器学*模型中添加和定制学*率计划,并查看我们如何在 Keras 和 TensorFlow 2.0 中实践它们的示例

学*费率表

学*率时间表根据预定义的时间表,通过降低学*率来调整训练期间的学*率。流行的学*率计划包括

  1. 恒定学*速率
  2. 基于时间的衰减
  3. 阶跃衰减
  4. 指数衰减

出于演示目的,我们将构建一个图像分类器来处理时尚 MNIST,这是一个具有 10 个类的 70,000 个 28×28 像素的灰度图像的数据集。

请查看我的 Github repo 获取源代码。

使用 Keras 加载数据集

Keras 提供了一些实用函数来获取和加载公共数据集,包括时尚 MNIST。让我们装载时尚 MNIST

fashion_mnist = keras.datasets.fashion_mnist
**(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()**

数据集已经分为训练集和测试集。以下是定型集的形状和数据类型:

>>> X_train_full.shape
**(60000, 28, 28)**
>>> X_train_full.dtype
**dtype('uint8')**

我们将使用梯度下降来训练神经网络,我们必须将输入特征缩小到 0-1 范围。为了在本地机器上进行更快的训练,我们只使用前 10,000 幅图像。

X_train, y_train = **X_train_full[:10000]/255.0**, **y_train_full[:10000]**

创建模型

现在让我们建立神经网络!用 Keras 和 TensorFlow 2.0 创建机器学*模型有 3 种方法。由于我们正在构建一个简单的全连接神经网络,为了简单起见,让我们使用最简单的方法:带有Sequential()的顺序模型。

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flattendef create_model(): 
    model = Sequential([
        Flatten(**input_shape=(28, 28)**),
        Dense(300, activation='relu'),
        Dense(100, activation='relu'),
        Dense(**10, activation='softmax'**),
    ])
    return model

我们的型号有以下规格:

  • 第一层(也称为输入层)有input_shape来设置匹配训练数据的输入大小(28, 28)。输入层是一个Flatten层,它的作用只是将每个输入图像转换成一个 1D 数组。
  • 然后是 2Dense层,一个 300 单位,另一个 100 单位。两者都使用relu激活功能。
  • 输出Dense层有10单元和softmax激活功能。
model = create_model()
model.summary()

1.恒定学*速率

恒定的学*速率是所有 Keras 优化器的默认时间表。例如,在 SGD 优化器中,学*率默认为0.01

要使用定制的学*率,只需实例化一个 SGD 优化器并传递参数learning_rate=0.01

sgd = tf.keras.optimizers.SGD(**learning_rate=0.01**)model.compile(
    **optimizer=sgd,** 
    loss='sparse_categorical_crossentropy', 
    metrics=['accuracy']
)

并使模型符合训练数据:

history_constant = model.fit(
    X_train, 
    y_train, 
    epochs=100, 
    validation_split=0.2,
    batch_size=64
)

让我们画出模型的准确性,这可以作为我们实验其他学*率计划的基线。

恒定学*率——准确度图

2.基于时间的衰减

基于时间的衰减是最流行的学*速率计划之一。形式上,基于时间的衰减定义为:

learning_rate = lr * 1 / (1 + decay * epoch)

其中lr是以前的学*率,decay是超参数,epoch是迭代次数。当decay为零时,这对改变学*率没有影响。当decay被指定时,它将按照给定的固定量减少前一时期的学*率。decay的值通常实现为

decay = initial_learning_rate / num_of_epoches 

在 Keras 中,实现基于时间的衰减的一种方式是通过定义基于时间的衰减函数**lr_time_based_decay()** 并将其传递给LearningRateScheduler回调。

initial_learning_rate = 0.01
epochs = 100
decay = initial_learning_rate / epochs**def lr_time_based_decay(epoch, lr):
    return lr * 1 / (1 + decay * epoch)**history_time_based_decay = model.fit(
    X_train, 
    y_train, 
    epochs=100, 
    validation_split=0.2,
    batch_size=64,
    **callbacks=[LearningRateScheduler(lr_time_based_decay, verbose=1)],**
)

下面是准确率和学*率的曲线图。

基于时间的衰减——精度图

基于时间的衰减—学*率图

3.阶跃衰减

另一种流行的学*率计划是在训练期间的特定时间系统地降低学*率。在形式上,它被定义为:

learning_rate = initial_lr * drop_rate^floor(epoch / epochs_drop)

其中initial_lr是初始学*率,例如 0.01,drop_rate是每次改变学*率时修改的量,epoch是当前的历元数,epochs_drop是改变学*率的频率,例如 10 个历元。类似地,我们可以通过定义一个阶跃衰减函数**lr_step_decay()**并将其传递给LearningRateScheduler回调函数来实现这一点。

initial_learning_rate = 0.01**def lr_step_decay(epoch, lr):
    drop_rate = 0.5
    epochs_drop = 10.0
    return initial_learning_rate * math.pow(drop_rate, math.floor(epoch/epochs_drop))**# Fit the model to the training data
history_step_decay = model.fit(
    X_train, 
    y_train, 
    epochs=100, 
    validation_split=0.2,
    batch_size=64,
    **callbacks=[LearningRateScheduler(lr_step_decay, verbose=1)],**
)

下面是准确率和学*率的曲线图。

基于步进的衰减——精度图

基于步长的衰减—学*速率

4.指数衰减

另一种流行的学*率计划是以指数速度降低学*率。在形式上,它被定义为:

learning_rate = initial_lr * e^(−k * epoch)

其中initial_lr是初始学*率,例如 0.01,k是超参数,epoch是当前纪元编号。类似地,我们可以通过定义一个指数衰减函数**lr_exp_decay()**并将其传递给LearningRateScheduler回调函数来实现这一点。

initial_learning_rate = 0.01**def lr_exp_decay(epoch, lr):
    k = 0.1
    return initial_learning_rate * math.exp(-k*epoch)**# Fit the model to the training data
history_exp_decay = model.fit(
    X_train, 
    y_train, 
    epochs=100, 
    validation_split=0.2,
    batch_size=64,
    **callbacks=[LearningRateScheduler(lr_exp_decay, verbose=1)],**
)

指数衰减—精度图

指数衰减——学*率图

比较模型准确性

最后,让我们使用不同的学*率时间表来比较模型的准确性。

看起来常数基于时间的学*率比阶跃衰减指数衰减对于这个特定的教程有更好的性能。请记住,本教程仅使用前 10,000 幅图像,其中的initial_learning_rate=0.01validation_split=0.2batch_size=64具有任意值。

在现实世界的应用程序中,为了调整学*速率,需要考虑更多的因素。请查看“深度架构基于梯度的培训实用建议”一文,了解一些最佳实践。

好了

感谢阅读。这篇文章涵盖了最流行的学*进度计划。下次我们就来看看自适应学*率

源代码请查看我的 Github 上的笔记本。

如果你对机器学*的实用方面感兴趣,请继续关注。

您可能对我的其他 TensorFlow 文章感兴趣:

通过将 Python 转换成 Rust 来学* Rust

原文:https://towardsdatascience.com/learning-rust-by-converting-python-to-rust-259e735591c6?source=collection_archive---------10-----------------------

Rust 基础入门教程

乐旅行车Unsplash 上拍照

[更新于 2021 年 2 月 18 日。代码更改为要点并添加了链接]

**Table of Contents**[**Introduction**](#3cb0)🦀 [Leetcode Unique Paths](#d2b3)
🦀 [Python Code](#2aa3)
🦀 [First Step in Rust](#f513)
🦀 [Examples of Primitive Data Types:](#5358)
🦀 [Functions](#3775)
🦀 [Statements and Expressions](#edb9)
🦀 [Variables](#0f1c)
🦀 [Macros](#dc94)
🦀 [if-else Statement (Step 2)](#5346)
🦀 [Calling a Function](#f27b)
🦀 [Range](#5d38)
🦀 [Arrays, Tuples, and Vectors](#52ef)
🦀 [as Keyword](#6263)
🦀 [Final Code](#4543)
🦀 [Struct and Impl](#27aa)
🦀 [Trait](#2c53)
🦀 [Runtime & Memory Usage](#7e45)[**Conclusion**](#d7d1)

介绍

Rust 是一种静态和强类型的系统编程语言。Rust 是为渴望语言速度和稳定性的人准备的。

我认为自己是一个新手。写完这篇文章后,我开始学* Rust,并且我每天都在学*新的东西。我现在可以将简单的 Python 代码转换成 Rust,并且能够解释我正在编写的代码。

在本文中,我们将使用一个 Leetcode 问题的 Python 解决方案,并将其转换为 Rust 代码。你不仅会发现两种语言之间的相似之处,还会学到 Rust 编程。

您可以运行代码,也可以在本文的示例中对其进行调整。

[## 你想学 Rust 但是不知道从哪里开始

Rust 初学者的完整资源

towardsdatascience.com](/you-want-to-learn-rust-but-you-dont-know-where-to-start-fc826402d5ba)

Leetcode 唯一路径

LeetCode 是一个非常受欢迎的网站,在那里你可以提高你的编码技能。其中一个问题叫做“唯一路径”,机器人位于一个 m x n 网格的左上角。您只能将向下向右移动,并且您需要找出两点之间有多少条唯一的路径。

图片来自 LeetCode

例如,在下图中,从 A 点到 B 点有 3 条唯一路径,从 A 点到 C 点有 5 条唯一路径。下图帮助您找到从 A 到每个区域的唯一路径的数量。由于您只需将向下移动向右移动,您可以将上面和左边的数字相加,找到到达该点的唯一路径的数量。

作者图片

Python 代码

用 Python 解决这个问题肯定有很多方法,但是我们打算用下面的解决方案

使用 Python 的解决方案。在线尝试这段 Python 代码。

LeetCode 上 Python 代码的结果。

在这段 Python 代码中:

  • 我们创建了一个名为 Solution 的类。我们定义了一个叫做“唯一路径”的方法。(是起始码。)
  • 它将 self、integer m和 integer n作为参数,并返回一个整数。它使用类型注释
  • 如果mn等于 1,那么它返回 1
  • 如果n小于m,则它会切换位置并运行相同的方法。
  • dp = [1]*n将创建一个n编号为 1 的列表。例如[1]*3将创建[1,1,1]
  • 我们使用双 for 循环和 range 将前一个数字添加到下一个项目中。[1,2,3][1,3,6]等。您可以通过将返回值更改为return dp来检查这一点。
  • 我们使用[-1]返回列表中的最后一个数字。

在本文中,我们将逐步将 Python 代码转换为 Rust。

上面的结果显示运行时间为 36 ms,内存使用量为 13.6 MB。我们稍后会将这个结果与 Rust 结果进行比较。

(当我再次提交给 LeetCode 时,结果发生了变化,上面的那个是最好的。你可能会有不同的结果。)

生锈的第一步

我们将从一个基本锈码开始。

生锈的第一步。试试这个锈郎在线。

Rust 总是在你运行程序的时候先运行**main**功能。我们创建一个名为unique_paths的函数,带有两个参数mn,它们是**i32**类型。

在函数中,我们必须声明每个参数的类型。Rust 程序中的每个变量、项目和值都有一个类型。

值的类型定义了保存它的内存的解释。**i32**原语数据类型之一,是一种 32 位固定大小的有符号整数类型**i32**可以容纳-(2)和 2 -1 之间的数字,前者为-2147483648,后者为 2147483647。

原始数据类型的示例:

在线尝试这个原始数据类型示例

更多的原始数据类型在这个链接中。

顺便说一下,Rust 的默认整数类型是**i32**,所以如果你没有在一个 闭包 中标注参数的类型,并且如果它们是整数,Rust 将使用**i32**。Rust 的编译器能够推断出参数和大多数变量的类型。

功能

功能 使用**fn**关键字启动。Rust code 使用蛇形外壳作为功能的传统样式。函数可以返回值,我们使用箭头**->**为返回值声明它们的类型。unique_paths 返回数据类型**i32**。Rust 使用{}作为函数体。

网上试试这个锈郎代码。返回字符串的函数示例。

陈述和表达

我们返回总和,m + n。函数体由一系列语句组成,并以表达式结尾。

语句是执行一些动作并且不返回值的指令。表达式计算出结果值。— 函数体包含语句和表达式

表达式m + n不包括结束分号,因为我们想返回它。如果你在一个表达式的末尾加一个分号,你就把它变成了一个语句,它不会返回值。

变量

**main()**函数中,我们用一个关键字来表示一个变量。默认情况下,局部变量是不可变的,但是您可以使用**mut**使它们可变。对于我们的例子,我们不需要使它可变。

试试锈变量示例在线。

宏指令

**println!()**标准宏之一。它解析格式字符串并将其转换为打印格式。

pritln!按顺序填充占位符。可以用索引和name="vale"

试试 println!宏在线。

if-else 语句(步骤 2)

下一步,我们添加一个**if-else**语句。**expr == expr**(其中expr表示表达式)是相等比较。**expr || expr**是逻辑还是

如果mn中的任何一个等于 1,那么我们返回 1。请注意 1 后面没有分号,因为我们要返回 1

Rust 对于**if**语句中的条件不使用括号。

在线使用 if 语句尝试 Rust 中的步骤 2

**if-else if-else**有如下形式。

在线尝试 if-else if-else 示例

调用函数

在线尝试 Rust 中的步骤 3。

这可能不是传递 LeetCode 所必需的,但是这向您展示了如何从内部调用自己的函数。

如果**n**小于**m**,我们交换变量位置,调用自己的函数。

范围

在 Python 中,我们使用range作为:

for i in range(1,m):
    for j in range(1,n):

在 Rust 中,我们使用....=

尝试范围..在锈线上。

上面的代码将输出 1 到 9。

尝试范围..= in Rust online。

上面的代码将输出 1 到 10。

数组、元组和向量

在 Python 中我们使用了dp = [1]*n。这将创建1n个数字。例如当 n=3 时,[1, 1, 1]

让我们看看 Rust 中的数组、元组或向量中哪一个可以用于此目的。

阵列

数组必须有同类型定长。默认情况下,数组是不可变的,我们不能用**mut** 来改变它的元素。

在线试用锈阵

输出:

one: 1, b: [4, 5, 6], c: [1, 1, 1, 1, 1], d: [1, 1, 1, 1, 1]

我们也不能动态设置数组长度。因为数组的长度是在编译时定义的。变量在编译时是未知的,因为它可以改变。编译器不知道在堆栈上分配多少空间来为数组提供存储。

如果你试图在没有[{:?}](https://doc.rust-lang.org/std/fmt/index.html)的情况下打印,你将会失败。我们不能用默认格式化程序格式化数组。所有 Rust 数据类型都实现了Debug特征,您可以使用{:?}来格式化它并打印一个数组。

所以我们不能在这里使用数组。

元组

元组可以有不同的类型,并且有固定的长度

let tup: (i32, f64, u8) = (100, 2.32, 4);

为了从元组中获取单个值,我们可以使用模式匹配来析构元组值。

在线试试锈元组

输出:

x = 500, y = 6.2, z = 4
1

同样,我们不能使用元组,因为它们必须有固定的长度

矢量

Rust 向量在内存中存储多个相邻的值。向量存储相同类型的值。

具有堆分配内容的连续可增长数组类型。——doc.rust-lang.org

vec!宏创建一个新的向量,保存您给它的值。

let v = vec![1, 1, 1];
// this is the same as above
let u = vec![1; 3];

一个向量就像一个可调整大小的数组,但是所有的元素必须是同一类型。

所以我们需要使用一个向量

dpm = vec![1; m as usize];
dpn = vec![1; n as usize];

作为关键字

第二个数字,长度,在vec![1; 3]中需要是[**usize**](https://doc.rust-lang.org/std/primitive.usize.html)类型。我们将**m****n**标注为**i32** ,但是我们可以使用**as**关键字来转换类型。我们可以只使用as表达式在原始类型之间转换。

最常用于将基元类型转换为其他基元类型。——鲁斯特郎博士

**vectors**有一个方法[**len**](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.len)返回向量中元素的数量。

最终代码

我们使用上述所有代码来获得唯一路径的数量。

在线尝试Rust的最后一步。

你可能注意到了#[allow(unused_variables)]。没有它也能工作,但是编译器会给你一个警告:

warning: unused variable: `i`
  --> main.rs" data-line="11" data-column="13">main.rs:11:13
   |
11 |         for i in 1..dpm.len() {
   |             ^ help: if this is intentional, prefix it with an underscore: `_i`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: 1 warning emitted

为了消除这个警告,我们添加了#[allow(unused_variables)]

稍后我们将看到 LeetCode 的最终代码。在此之前,我们对这段代码进行了更深入的研究。

结构和实现

我们将对上述解决方案应用structimpltrait。请注意,这在 LeetCode 上不起作用。

结构用于将相关属性封装成一个统一的数据类型。结构不同于其他语言中的类。例如,Rust 的 struct 不支持继承。

元组很方便,但是使用像t.0这样的索引并跟踪每个部分的含义并不简单。

Rust 结构包含命名字段。我们使用关键字struct并在花括号内设置字段类型。结构将数据定义为键值对。

struct Name_of_struct {
   field1:data_type,
   field2:data_type,
   ...
}

在线试试的防锈结构

&字符串和字符串

你可能想知道为什么我们需要to_string()。Rust 主要有两种类型的弦:[&str](https://doc.rust-lang.org/std/primitive.str.html)[String](https://doc.rust-lang.org/book/ch08-02-strings.html#what-is-a-string)&str叫做‘串片’。字符串切片具有固定的大小,不能变异。一个String被存储为一个矢量。String是堆分配的,可增长的,并且不是空终止的。(更多信息请点击链接。)

"John"是一个&str,由于我们在struct中将first_name的类型定义为字符串,我们需要使用[to_string](https://doc.rust-lang.org/std/string/trait.ToString.html)将其转换为字符串。

我们将关联函数放入impl块中。

在线试用 Rust impl

方法参数 self、& self 和& mut self

我们在impl Person中增加了一个方法 full_name。该函数将&self作为第一个参数。它可以采用self&self&mut self中的一种。

  • 当我们想要读取结构中的数据,而不是写入数据时,我们使用&self
  • 当我们希望方法获得所有权时,我们使用self
  • 当我们想让方法写入时,我们使用&mut self

我们在p.full_name()中的实例方法中使用点运算符来访问该字段。

让我们将structimpl用于我们的代码:

使用 struct 和 impl 在线尝试

特点

特性 类似于 OOP 语言中的和接口。它们用于定义一个类型必须提供的功能。

尝试使用 trait 在线编写代码。

我们用函数unique_paths添加了一个名为 UiquePaths 的特征。我们需要使用impl trait-name for struct-name更新impl

我们使用::符号在main函数中实例化它。

现在我们实现了structimpltrait

运行时和内存使用

以下解决方案针对 LeetCode 环境进行了调整。

impl Solution {
    pub fn unique_paths(m: i32, n: i32) -> i32 {
        if m == 1 || n == 1 {
            1
        } else {
            let mut dpm = vec![1; m as usize];
            let mut dpn = vec![1; n as usize];
            for i in 1..dpm.len() {
                for j in 1..dpn.len() {
                    dpn[j] += dpn[j-1];
                }
            }
            *dpn.last().unwrap()
        }   
    }
}

铁锈的 LeetCode 结果

请注意运行时间 0 毫秒。Rust 没有运行时间。Rust 适用于零** - 成本抽象。你不必为某些强大的抽象或安全特性付出额外的运行时开销,而在其他语言中你必须为此付出运行时成本。**

…迭代器虽然是一种高级抽象,但会被编译成大致相同的代码,就好像您自己编写了低级代码一样。迭代器是 Rust 的零成本抽象之一,我们的意思是使用抽象不会带来额外的运行时开销。— Rust 编程语言

Rust 的内存使用量为 2.1 MB,而 Python 的内存使用量为 13.8 MB。

Rust 有独特的管理堆内存的方式,它使用一个叫做所有权的概念来管理它。我建议您深入阅读 Rust 文档以了解更多信息。

结论

我们接触了原始数据类型、类型注释、函数、语句、表达式、变量、宏、if 语句、范围、数组、元组、向量、structimpltrait的表面。你可以在官方书籍中找到更多信息。

正如我之前所说,我仍然在学*生锈。我感谢专家对如何改进解决方案的反馈。

我希望你学到了一些东西,并为下一步做好了准备。有许多关键概念我们无法在本文中涵盖。请继续关注下一篇文章。

通过 成为 的会员,可以完全访问媒体上的每一个故事。

https://blog.codewithshin.com/subscribe

** [## 无符号、有符号整数和 Rust 中的造型

理解符号和幅度、一的补码和二的补码

towardsdatascience.com](/unsinged-signed-integers-and-casting-in-rust-9a847bfc398f) [## 学*生锈:常见概念

查看更多关于 Rust String 的信息。

medium.com](https://medium.com/series/101-rust-tips-8f361510683c) [## 学*生锈:所有关于字符串

字符串和&str

medium.com](https://medium.com/series/learning-rust-all-about-strings-c7666812d893)**

有风格地学* TensorFlow 2

原文:https://towardsdatascience.com/learning-tensorflow-2-with-style-eab12fd94365?source=collection_archive---------28-----------------------

通过实现快速神经风格转换来熟悉 TensorFlow 2

个人照片的雾滚过塔马尔派斯山风格化的尖叫由爱德华蒙克

背景

在过去的几年里,我对计算机视觉产生了浓厚的兴趣,并花了相当多的时间参加课程、阅读论文和做与该领域相关的兼职项目。这和我对摄影的热情有很大的重合。引起我注意的一个计算机视觉项目是神经风格转移,首先由莱昂·加蒂斯等人提出,后来由贾斯廷·约翰逊等人提出了特别快速的风格转移。最*在处理代码时,我发现它的大部分都过时了,缺乏支持,因此很难处理。在对其他机器学*框架有所熟悉的同时,我以此为契机更新了代码,对 TensorFlow 2 有了更深入的了解。由于快速风格转换包括生成网络和更复杂的损失函数,它为学*张量流的一些细微差别提供了一个很好的项目,而不是基本的分类模型。

本文的目标是强调使用 TensorFlow 2 的一些核心功能和主要经验,以及它们如何应用于快速风格转换。我将参考与神经类型转移相关的核心概念,但会浏览其他概念,因此熟悉一些会有所帮助。如果你对这个问题完全陌生,我在下面提供了一些有用的资源。

简要概述

样式转移的目标是获取一个内容图像,我们称之为 C ,和一个带有样式的图像, S ,创建一个转换后的图像, Y ,将 S 的样式应用于 C 。换句话说,我们想要混合 C 的内容和 S 的样式,如下图所示。

表示将一个图像的样式应用到另一个图像的内容,以创建一个经过变换的、风格化的图像。

在 Gatys 等人的原始风格转移工作中,具有随机噪声的基础图像 X 被传递到训练过的 VGG 网络中,并且来自指定层的输出被用于提取哪些特征被激活。从在 XC 之间的指定内容层输出的 L2 损失可以帮助学*内容。在 XS 之间来自指定风格滤波器的输出的格拉姆矩阵的 L2 损失可以帮助学*风格。这个图层提取可以在下图右侧的损失网络中看到。当 X 以随机噪声和多次迭代开始一幅图像时,它被训练并转换为 Y 。TensorFlow 团队在这里有一个关于这个原始实现的教程。

Johnson 等人提出的快速风格转换网络架构,注意:我的实现使用 VGG19 vs VGG16,来源:实时风格转换和超分辨率的感知损失 (2016)

在快速风格转换的情况下,生成神经网络被训练来转换任何图像,而不是单个图像被训练和转换。在上面由 Johnson 等人提出的架构中,内容图像被传递到变换网络中,然后变换的输出图像被传递到 VGG 网络中。从那里,使用提取的样式和内容层,变换的图像经历与原始样式转移模型类似的损失。为了训练生成网络,将在多次迭代中使用许多不同的内容图像。训练的时间要长很多,但是推理时间最多可以快 1000 倍!

在下面的例子中,相同的内容图像在不同的训练点通过网络传递。随着训练迭代次数的增加, i ,变换后的图像, X ,向我们期望的内容和风格的混合方向收敛。

创成式模型如何在多次迭代中发生变化的示例。随着时间的推移,通过优化损失函数 L(Cᵢ、s、Xᵢ).,模型训练和转换后的输出 Xᵢ将收敛到我们期望的风格和内容的混合 Yᵢ

模型

为了构建模型,我重点使用了 TensorFlow 的内置特性。在 TensorFlow 核心、Keras 和 TensorFlow 附加组件之间,有许多工具可以利用。

自定义图层

TensorFlow 2 使得将这些层组合成自定义层变得非常容易。在下面的例子中,你将看到我如何建立一个 2D 卷积层和模型的残差块。这些层将用于构建生成性转换网络。

当从 Layer 类继承时,属性和方法将被递归调用。例如,当访问自定义层中的可训练变量时,将返回组成该自定义层的所有层所有可训练变量。这也适用于使用自定义层从模型中调用可训练变量,使得变量访问非常直观。

变压器网络

Keras 函数模型用于构建生成神经网络。Keras 中的功能模型比顺序模型更加通用,因为后者主要用于堆叠层。使用功能模型,可以构建更复杂的神经架构,如共享层模型和多输出模型。与单独堆叠的层相比,这些模型类似于图上的节点。这在 ResNet、InceptionNet 和 MobileNets 等其他体系结构中有所体现。由于我们有一些剩余的模块,功能模型使用起来会更友好一些。

由于我们组成了我们的自定义层,它仍然是非常直观的遵循。首先,实例化层,然后通过层的可调用性传递 Keras 输入,以期望的方式建立模型下面的图。最后,所有层的输出和原始输入用于创建一个tf.keras.Model实例并构建图表。我创建了一个泛型类作为模型的包装器。*如上所述,对model.trainable_variables的调用将从我们的自定义层返回所有可训练变量。

*请注意,您也可以创建继承模型,并仍然使用功能模型,这有一些好处,但我发现它更脊和难以工作。

VGG19 型号

Keras 图书馆包含一些公共网络,包括 VGG 网络。可以使用某些预先训练的权重和修剪最后完全连接的层的选项来创建它们。如果你想对一个给定的问题使用迁移学*,并且需要使用不同的分类层,这是非常有用的。我的实现使用 VGG19 网络,而不是 VGG16,尽管可以使用各种图像识别网络。

正如在概述中提到的,我们将通过 VGG 网络传递我们转换的图像, Xᵢ ,并提取一些输出层。我们将希望有多个层作为输出,而不是一个分类器作为输出。还记得功能模型是如何适用于多输出的吗?可以使用 VGG 网络创建新的功能模型。VGG 输入被传递到新模型中,并且期望层的输出作为模型输出被传递。当新模型被调用时,张量将通过 VGG 模型传递,这些层的输出将被返回。

下面是输出第一个卷积模块第一层(conv1_1)和第三个卷积模块第二层(conv3_2)的示例代码片段,以及几个通道的样本输出。这些输出表示当预训练滤波器在图像上卷积时激活的图像部分。conv1_1 的浅层输出激活边缘等简单特征来分解图像,而深层输出激活更复杂的信息(在这种情况下,它看起来像阴影)。

从 VGG 网络提取输出的例子。注意:在实际实现中,提取了更多指定的过滤器。

a)通过 VGG19 的原始 RGB 图像,conv1 _ 1 层的第 17 个滤波器(索引为 1)的输出,conv3 _ 2 层的第 6 个滤波器(索引为 1)的输出;注意图像 c 由于汇集而变小

层间的 L2 损失然后用于比较 XᵢCᵢ 的内容输出。关于内容,如果汽车图像的“车轮”特征在我们的原始图像上激活,并且也在转换的图像上激活,则内容仍然是强匹配的,并且损失将会更低。同样,gram 矩阵之间的 L2 损失用于比较 XᵢS 的哪些样式特征是激活的特征。

用梯度带训练重量

TensorFlow 2 中较大的变化之一是切换到急切执行。在 TensorFlow 的早期版本中,计算图将首先手动构建,只有在之后才会传入和调用张量。这不太直观,也很难操作。现在,电子传感器可以通过计算来设置和调用。计算图被抽象出来,并在引擎盖下设置和执行。就像在其他很多懒惰与渴望评估的例子中一样,我发现这更容易理解,也更容易调试。

在 TensorFlow 2 中,分类问题在 Keras API 中得到很好的支持。然而,如果您需要创建一个定制的训练循环,训练特定的变量,或者为损失函数提供特殊的输入,这就不那么友好了。在这些情况下,GradientTape 可用于在执行期间跟踪可训练变量,获取梯度,然后通过优化器应用梯度。这非常适合于快速风格转移模型,因为训练涉及具有定制训练循环的生成网络,并且将几个不同的输入传递给损失函数。

监控变量

在 GradientTape 上下文中,可训练变量在向前传递期间被“监视”和跟踪。当稍后执行反向传播时,被监视的变量将根据它们的梯度应用各自的变化。虽然可训练变量可以在训练中被跟踪和调整,但被监视变量将被跟踪,因此它们可以被优化器调整。

无需在 GradientTape 上下文中调用watch,即可隐式观察可训练变量。对于更细粒度的控制,您可以在 GradientTape 的构造函数中关闭它,只有块中显式“监视”的变量才会被跟踪以进行自动区分。GradientTape 上下文还允许您获取被监视的变量,这有助于调试。对于多模型,我发现自己设置被监视的变量比依赖隐式调用更实际。

一旦变量被观察到,张量通过模型并计算损失。对于快速风格转换,我们将通过我们的生成器网络进行正向传递,获得转换后的图像, Xᵢ ,然后将该图像通过 VGG 分类网络。在下面的例子中,我创建了渐变磁带上下文,观察适当的变量,然后向前传递。之后,我使用损失来获得适当的梯度,然后优化器使用这些梯度来调整可训练变量。

结果

现在是有趣的部分!在对每种风格的网络进行数小时的训练后,这些都用默认的训练参数作为通用基线。请注意,为了获得更好的结果,有些模型可以调整得更细或更长。例如,在“尖叫”实现中,有几个未经训练的点是从白色开始的。

具有 1)用于训练的风格图像,2)通常用作基线的芝加哥图像,以及 3)显示变化的个人图像的网络的结果

对摄影、艺术和深度学*充满热情,这是一个非常有趣的项目。我发现 TensorFlow 2 比以前的版本更容易使用。尽管有几个模型和几个活动部件,调用组件并深入了解网络还是很容易的。我发现在 Colab 笔记本中进行开发时,记录变量非常有用。我知道一些工程师也会基于变量名和张量形状来建立单元测试,我可能会在更正式的环境中这样做。

当然,大多数调试都伴随着与数据相关的问题。一个错误是由于不正确地缩小图像,提取了太多的“风格”。本页顶部的照片是一个令人高兴的小意外,尽管当时网络的性能与以前的实现方式不同。另一个错误仅仅是因为我使用了一张非常高分辨率的艺术品照片,而网络实际上把画布的纹理作为风格!

我希望你学到了一些关于深度学*和使用 TensorFlow2 的知识。如果你有兴趣看更多我使用的代码,或者其他与风格转移、深度学*或计算机视觉相关的主题,我在下面提供了一些资源。

额外资源

项目

外部的

几年前,我用这两门课程向自己介绍了 ML 和计算机视觉

除了原始的研究文章之外,这些文章和实现是神经风格转移的重要资源

参考

1 L. Gatys,A. Ecker,M. Bethge,一种艺术风格的神经算法(2015):https://arxiv.org/abs/1508.06576

[2]约翰逊,阿拉希,飞飞,实时风格转换和超分辨率的感知损失(2016):https://arxiv.org/abs/1603.08155

通过聚类发现自然群体

原文:https://towardsdatascience.com/learning-the-clustering-algorithms-through-hands-on-da4b462503ff?source=collection_archive---------56-----------------------

通过简单的实验学*流行的聚类算法

自然群体。图片来源

集群具有跨应用领域的重要用例,以了解数据的整体可变性结构。无论是客户、学生、基因、心电图信号、图像、股票价格的聚类。在我们的一些研究文章中,我们已经在特性选择和投资组合的优化中成功地使用了这一点,但在后面的故事中会有更多。聚类属于无监督类别,根据定义,它试图在数据中找到自然的组。

即使在深度学*时代,聚类也可以为您提供关于数据分布的宝贵见解,从而影响您的设计决策。

在这篇文章中,我们给你一些关于五种聚类算法和 Kaggle 笔记本链接的概述,我们在那里做了一些实验。目的是给你一个快速总结,让你开始申请。

K-表示:

这是所有基于距离的算法中最简单的一种。这是一种分割算法。从 k 个随机点作为聚类中心开始,然后将其余的点分配到最*的聚类中心。完成此分配后,重新计算聚类中心。这个过程一直持续到集群分配没有太大变化。

其中一些问题是:

a)我们需要知道“k”的值

b)受离群值影响。

c)取决于初始化

有些实验是在下面的 Kaggle 笔记本上做的:【https://www.kaggle.com/saptarsi/kmeans-dbs-sg

我们首先解释 k-means 是如何工作的,然后举例说明为什么需要缩放。我们还讨论了如何使用肘图绘制误差平方和,以找到 k 的最佳值。一个简单的例子是“iris”

对应视频:

理论:https://www.youtube.com/watch?v=FFhmNy0W4tE

动手:https://www.youtube.com/watch?v=w0CTqS_KFjY

K-Medoid:

K-Means 对异常值并不稳健。当我们有一个以上的属性时,我们要找到一个整体的中值,这就是所谓的中值。有些实验是用下面的笔记本做的。为了演示异常观测值的问题,我们做了一个添加三个异常观测值的小实验。如你所知,iris 有三个类(Setosa、Verginca 和 Versicolor ),它们被绘制成两个特性。这些由蓝色圆圈标记的特征的添加完全扭曲了聚类。原来的三个类合并成两个聚类,离群点在一个聚类中。

1:受极值影响的 K 均值。图片来源:作者笔记本https://www.kaggle.com/saptarsi/kmedoid-sg

Kaggle 笔记本链接:

https://www.kaggle.com/saptarsi/kmedoid-sg

我们讨论的主要问题是,当标签不可用(轮廓宽度)和可用(纯度)时,如何测量聚类的质量。下面是一个比较 K 均值和 K 中值的极端观测值(异常值)的简短示例。

对应视频:

理论:【https://www.youtube.com/watch?v=q3plVFIgjGQ】T4

动手:https://www.youtube.com/watch?v=L1ykPtlonAU

数据库扫描:

DBSCAN 最有前途的一点是,它将一些点识别为噪声点,这些点如果包含在聚类练*中,将会扭曲整个聚类。该算法可以找到基于密度的聚类,而不是距离。

在卫星和同心圆上比较了 DBSCAN、K-Medoid、K-Means。下面的笔记本包含简单的实验。

https://www.kaggle.com/saptarsi/dbscan-sg

在一个这样的实验中,我们创造了一个噪音点。

X = np.array([[12],[4,2],[3,3],[8,7],[9,9],[10,10],[25,80]])

散点图如下所示:

2:具有一个噪声点的 2D 数据的散点图

图片来源:作者笔记https://www.kaggle.com/saptarsi/dbscan-sg

直观上,我们理解可能有三个集群和一个外围点。

下图比较了聚类结果

图 3: DBSCAN、K-Means 和 PAM 处理噪声点的能力

图片来源:作者笔记https://www.kaggle.com/saptarsi/dbscan-sg

我们可以看到 DBSCAN 清楚地将点置于另一种颜色中,因为 k-意味着原始的两个聚类丢失,对于 k-medoid 更好,但是它没有单独识别外围点。

下面的 make circle 提供了算法的另一个比较,它清楚地显示了 DBSCAN 如何正确地识别属于两个集群的两个圆。

图 4:同心圆上的 DBSCAN、K-Means 和 K-Medoid

图片来源:作者笔记 https://www.kaggle.com/saptarsi/dbscan-sg

对应视频:

理论:【https://www.youtube.com/watch?v=RZg51WH7caQ】T4

动手:https://www.youtube.com/watch?v=A8OnRH42hWE

凝聚聚类:

以上三种是基于分区的聚类,而这是一种分层聚类,通过树状图揭示了关于整体结构的更多语义。层次聚类中的一个重要考虑是当合并到聚类中时要考虑哪个距离,是最小距离、最大距离还是平均距离。在同心圆、半月形、高斯数据和种子数据集上进行了各种实验。包含一些实验的笔记本如下:

[## 聚集聚类 SG

使用 Kaggle 笔记本探索和运行机器学*代码|使用 UCISeeds 的数据

www.kaggle.com](https://www.kaggle.com/saptarsi/agglomarative-clustering-sg)

笔记本上的符号图

图 5:简单的 dendorgam

图片来源:作者笔记https://www.kaggle.com/saptarsi/agglomarative-clustering-sg

对应视频:

理论:https://www.youtube.com/watch?v=RZg51WH7caQ

动手:https://www.youtube.com/watch?v=z7jXh_RzL_k

预期最大化:

其实现方式是通过高斯混合建模。基本上,每个聚类可以被认为来自不同的多元正态分布。与所有 4 种方法相比,这是一种软聚类方法。下面是一个笔记本,里面有一些简单的实验。这是一种更灵活的方法,允许圆具有非球形形状。

https://www.kaggle.com/saptarsi/gmm-sg

对应视频:

理论:【https://www.youtube.com/watch?v=LaL0BfvUurs】T2

动手:【https://www.youtube.com/watch?v=A8OnRH42hWE

总结:

在下表中,我们总结了算法的优缺点

聚类算法的比较。作者创建的图像

何时使用哪种算法?

我总是从 K-Means 开始,观察聚类质量,只有当数据非常随机,密度变化时,我才会选择 DBS can。如果我想应用聚类进行总结 k-medoid 是一个不错的选择。凝聚聚类因其呈现的可视化而具有吸引力。EM 是一个理论上非常健壮的算法,它有许多其他的应用,在有重叠簇的地方 EM 可能是一个很好的选择。

参考资料:

[1]https://towards data science . com/clustering-clearly-explained-5561642 ec20c

[2]https://towards data science . com/unsupervised-machine-learning-clustering-analysis-d 40 F2 b 34 AE 7e

3 Tan PN,Steinbach M,Kumar V .数据挖掘导论。培生教育印度公司;2016.

学*用 Tableau 在 5 分钟或更短时间内预测

原文:https://towardsdatascience.com/learning-to-forecast-effectively-with-tableau-in-6-minutes-or-less-3d77a55930a0?source=collection_archive---------15-----------------------

(舞台上由人扮的)静态画面

谁知道会这么容易?

@softie__arts 创作

使用 Python 和 R 有很多方法来可视化您的数据,但是强大的商业智能工具 Tableau 使得创建可视化成为一个简单的拖放过程。

Tableau 也不仅仅是一个可以用来创建图表的工具。您可以编写自定义 SQL,创建复杂的计算字段,甚至生成高质量的预测!

请继续阅读,快速了解 Tableau 如何通过一次点击自动生成预测(包括 gif)。

Tableau 如何创建预测的简要说明

Tableau 使用指数平滑法创建预测。虽然 Tableau 也支持使用整数值而不是日期,但是您可以在绘制度量值随时间变化的可视化图形上这样做。

预测的好坏取决于它们所依据的数据。

一般来说,在尝试创建预测之前,您应该包括尽可能多的数据。Tableau 在技术上只需要五个数据点就可以创建一个时间序列预测,尽管它甚至会尝试预测一个没有足够数据的视图来建立一个准确的模型,但预测的好坏取决于它们所基于的数据。

如果您基于太少的数据或受外部变量影响太大的数据创建预测,您的预测很可能不适合未来。您还应该注意 Tableau 在每次预测时自动生成的Prediction Intervals,以了解预测值可能落入的范围。

Tableau 将从八个指数平滑模型中选择一个来创建最佳预测(有关更多信息,请参见最后一节)。指数平滑模型也可以考虑Trend(模型的总体上升或下降方向)和Seasonality(特定时期的波动模式)。

在 Tableau 中创建预测

在本演练中,我们将使用 Tableau 附带的“样本超市”数据集。如果您想继续操作,请打开一个新工作簿并连接到此数据源。

我们从一个简单的图表开始,它显示了一段时间内每月的平均销售额:

显示一段时间内平均销售额的基本图表

预测和趋势/季节性定制选项

要使用预测扩展图表,右键单击视图上的任意位置(图表所在的位置)并单击Show Forecast

您可以选择自定义预测的提前期,但是 Tableau 设置了一个默认值(在本例中为 13 个月),这通常是合适的。

在 Tableau 中创建和定制预测

首先,预测只是一条直线,它来自 Tableau 创建的初始模型。这不是默认的,因为 Tableau 会尽最大努力生成一个适合现有数据的模型。但是,有时您必须定制模型,以使其更准确地描绘未来的数据点。为此,再次右键单击视图,单击Forecast Options,然后在Forecast Model面板中选择“自定义”。

在这种情况下,当定制模型TrendSeasonality时,我循环通过不同的选项(加法乘法)。有关这些如何工作的更多信息,请查看 Tableau 文档中的“模型类型”部分。

我决定将Seasonality调整为乘法并保持Trend不变。

预测描述

要了解您的预测是如何生成的,右键单击视图并选择Describe Forecast。这将弹出一个包含预测模型信息的弹出窗口。下面,您可以看到哪些数据用于创建预测,以及对您预测的变量(在本例中为“平均销售额”)的影响。

表格预测汇总说明

如果您点击Model选项卡,您将看到与计算 Tableau 使用的指数平滑预测模型相关的值。

Tableau 预测模型描述

预测化妆品和预测间隔

您可以将图表的预测部分更改为不同的颜色,使其与图表的其他部分更加突出。为此,只需点击Marks卡中的Color按钮,并选择您想要的预测模型颜色。

这也将影响图表中的“预测区间”,该区间显示了预测值可能位于的值范围。您可以通过右击并再次转到Forecast Options来设置预测(置信)区间百分比。默认情况下,预测间隔设置为 95%,但是如果您想查看没有预测间隔的图表,可以自定义该值或将其完全删除。

在 Tableau 中自定义预测

预测与趋势线

除了指数平滑模型,您还可以为图表创建趋势线。只需转到Analytics选项卡,然后双击Trend Line或将其拖至视图。Tableau 将为您提供线性、对数、指数、多项式或幂型趋势线的选项。

如果您将鼠标悬停在趋势线上,您将会看到 Tableau 使用了哪些值来在图表上显示它。对于完整的方程和系数,你可以右键点击趋势线,并前往Describe Trend Line进行总结。

在 Tableau 中创建趋势线

有趣的是,您可以看到原始图表和我们生成的指数平滑预测模型之间的线性趋势线略有不同。

我希望你发现这个快速介绍 Tableau 预测有用!Tableau 是一个非常强大的数据可视化工具,它不仅仅可以创建图表。

和往常一样,理解Tableau(和你使用的其他程序)如何创建预测模型是很重要的,因为你做出的决定不仅要基于数据,还要基于你理解的数据。

通读 Tableau 的预测文档,你也可以浏览 Tableau 可以使用的所有指数平滑模型这里

此外,在可视化数据之前需要采取的一些重要步骤是收集和预处理。您可以利用 Python 中的 Pandas 库来开始这项工作。请随意查看我以前在这些主题上的一些工作:

[## 4 种不同的方法来有效地排序熊猫数据帧

正确探索、理解和组织您的数据。

towardsdatascience.com](/4-different-ways-to-efficiently-sort-a-pandas-dataframe-9aba423f12db) [## 如何使用 Python 和 Xpath 抓取网站

用 XPath 表达式从 HTML 中收集星球大战引言

towardsdatascience.com](/how-to-use-python-and-xpath-to-scrape-websites-99eaed73f1dd) [## 一种快速重新格式化熊猫数据框中的列的方法

使用 df.melt 将多个列压缩成一列。

towardsdatascience.com](/a-quick-way-to-reformat-columns-in-a-pandas-dataframe-80d0b70de026)

感谢您的阅读,祝您的 Tableau 冒险之旅好运!

学会学*更多:元强化学*

原文:https://towardsdatascience.com/learning-to-learn-more-meta-reinforcement-learning-f0cc92c178c1?source=collection_archive---------21-----------------------

建造一个人造大脑

摄影爱好在 Unsplash

强化学*的 ELI5 定义是通过从以前的错误中反复学*来训练一个模型表现得更好。强化学*为代理提供了一个框架来解决现实世界中的问题。他们能够学*规则(或策略)来解决特定的问题,但是这些代理的主要限制之一是他们不能将学*到的策略推广到新的问题。先前学*的规则只适合特定的问题,对于其他(甚至类似的)情况通常是无用的。

另一方面,一个好的元学*模型被期望推广到模型在训练中没有遇到的新任务或环境。适应这种新环境的过程可以被称为小型学*会议,在有限接触新配置的情况下进行测试。在缺乏明确的微调模型的情况下,可以观察到元学*能够自主地调整内部状态以推广到更新的环境。

元强化学*就是应用于强化学*的元学*

此外, Wang et al. 将元学*描述为“使用递归模型的元学*的特殊类别,应用于学*”,这似乎比上面的定义更全面。

我们开始吧

在强化学*中,代理在每一步接收观察 (例如视频游戏中角色的位置),并基于这些观察输出动作 ,如“向前移动”或“向右转”。基于这些行动的结果,代理会收到奖励惩罚,这将在培训中进一步指导它,帮助它为以后的步骤做出更有意义的观察。该模型的目标是最大化奖励和最小化惩罚。

元强化学*中,训练和测试任务是不同的,但是来自同一个问题家族。一个很好的例子是不同布局的迷宫,或者不同概率的多臂强盗问题(解释如下)。

一个简单的实验

多臂强盗问题是一个经典问题,它很好地展示了探索与开发的两难困境。你可以想象自己在一个只有两个杠杆的房间里,其他什么都没有。

多兵种土匪问题;作者图片

  1. 拉左边的杠杆 A1 会给你一个概率 p 来获得奖励 r
  2. 拉右边的杆 A2 会给你一个概率 (1-p) 来获得奖励 r.

为了从逻辑上回答这个问题,你必须知道概率 p 的值。较高的 p 值将保证从杠杆 A1 获得奖励的较高机会,而较低的 p 值将保证从杠杆 A2 获得奖励的较高机会。这正是 meta-RL 如此有趣的原因。如果你在你的模型上投入足够的价值,在与环境互动并从中学*之后,它会越来越好地选择正确的杠杆。传统的基于 RL 的方法将无法处理变化的概率,并且通常会因不同的 p 值而失败。

实际上,受过不同概率的两级问题训练的 meta-RL 智能体能够从两级中选择正确的一级,从而使用非常少量的数据点获得最高的回报。它使用对联(行动,回报)来计算每个杠杆的“风险与回报”因子。

下面是一个示例,左边是一个未经过训练的代理(pp= 0.92),右边是一个经过训练的meta-RL 代理(pp= 0.76)****

未经训练和经过训练的 meta-RL 代理;来源

关键组件

meta-RL 涉及三个关键组件。下面将对它们进行详细描述。

有记忆的模型:没有记忆,meta-RL 模型就没用了。它需要记忆来从直接环境中获取和存储关于当前任务的知识,这将有助于它更新其隐藏状态。一个递归神经网络维护 meta-RL 模型的隐藏状态。

创建一个好的 RNN 的动力对于本文的范围来说太宽泛了。然而,meta-RL 和 meta-RL 都使用 LSTM 来管理它们的隐藏状态。

元学*算法:元学*算法将定义我们如何根据它所学*的内容来更新模型的权重。该算法的主要目标是帮助优化模型,以在最短的时间内解决一个看不见的任务,应用它从以前的任务中学到的东西。以往的研究通常使用普通梯度下降更新的 LSTM 细胞。

爬行动物,都是经过验证的方法,能够更新模型参数,以便在新的和未知的任务上实现良好的泛化性能。

一个合适的 MDPs 分布:一个马尔可夫决策过程(MDP) 是指智能体观察环境输出的整个过程,由一个奖励和下一个状态组成,然后在此基础上做出进一步的决策。由于代理在其培训期间会暴露于许多不同类型的环境和任务,因此它需要能够快速适应不断变化的条件和不同的 MDP。

在这三个组件中,这是研究最少的组件,也可能是关于 meta-RL 的最具体的组件。由于每个任务都是一个 MDP,我们可以通过修改奖励配置环境来构建 MDP 的分布。

进化算法是保证生成良好环境的一个很棒的方法。它们通常是启发式的,受自然选择过程的启发。一群随机产生的解会经历一个评估、选择、突变(如果我们把遗传算法也加入进来)和繁殖的循环;好的解决方案能坚持到最后。王等人的《诗人》是一个基于进化算法的框架的好例子。

下面展示了一对开放式开拓者(POET ),最初从一个普通的环境和一个随机初始化的代理开始。然后,它增长并维护一对一配对环境和代理的群体。根据作者的观点,POET 旨在实现两个目标,进化环境的多样性和复杂性;以及优化代理以解决它们的并行环境。

POET:基于进化算法的框架;来源

没有奖励函数的 MDP 被称为受控马尔可夫过程 (CMP)给定预定义的 CMP,我们可以通过生成奖励函数 R 的集合来学*关于各种任务的知识,这鼓励了有效的元学*策略的训练。

Gupta 等人提出了两种在 CMP 环境下增长任务分布的无监督方法。假设有一个潜在的潜在变量与每个任务相关联,它将奖励函数参数化为潜在变量的函数以及鉴别器函数(用于从状态中提取潜在变量)。 来源

研究论文描述了构造鉴别器函数的两种主要方法:

  1. 对鉴别器的随机权重进行采样
  2. 学*鉴别器功能以鼓励多样性驱动的探索。如果你正在寻找关于这个主题的更全面的分析,你可以参考他们的另一篇论文,“DIAYN(多样性是你所需要的)。

在 CMP 环境中增加任务分布的复杂性超出了本文的范围,我强烈推荐任何感兴趣的人深入研究这篇文章以获得更深入的观点。

与强化学*的比较

meta-RL 系统非常类似于普通 RL 算法的系统,除了最后的奖励以及最后的动作也包括在策略观察中,以及当前状态。这种改变的目的是馈送并跟踪所有任务和观察的历史,以便模型可以基于当前 MDP 在内部更新状态、动作和奖励之间的动态,并相应地调整其针对其他 MDP 的策略。

meta-RL 和 meta-RL 都实现了 LSTM 策略,其中 LSTM 的隐藏状态作为记忆来跟踪特征的变化。该策略本质上是循环的,不需要显式输入最终值。

meta-RL 论文中使用的不同演员-评论家架构(全部都是循环模型);来源

训练程序如下进行:

  1. 品尝新 MDP
  2. 重置模型的隐藏状态
  3. 收集多个轨迹并更新模型的权重
  4. 从步骤 1 开始重复

超出

训练 RL 算法有时会很困难。如果一个元学*代理能够变得如此聪明,以至于它能够根据在特定任务上接受训练时推断出的知识来解决的任务分布变得非常广泛,那么我们将朝着广义智能(或新的流行词——人工通用智能{AGI})的方向前进,本质上是建立一个能够解决所有类型的 RL 问题的大脑。

作为旁注,我还想指出 meta-RL 和AI-GAs(J . Clune 著)之间毫不奇怪的相似之处,后者提出通往 AGI 的有效途径是让学*自主。它基于三个支柱:元学*架构、元学*算法和有效学*的自动生成算法。

参考资料和进一步阅读

没有亚瑟·朱利安尼的努力,这项工作是不可能完成的。你可以在这里查看他对 meta-RL 算法的出色实现。王等人的这篇研究论文也让我对 meta-RL 的一些核心概念有了很好的见解,如果你想有一个更全面的看法,我强烈推荐阅读它。最后,Clune、Stanley、Lehman 和 Wang 在工程博客上发表的这篇文章也帮助我理解了这些领域的开放性,以及如何克服极其困难的挑战。Lilian Weng 的这个博客也是一个很好的进一步阅读的资源。

学*为信息检索排序:深入研究 RankNet。

原文:https://towardsdatascience.com/learning-to-rank-for-information-retrieval-a-deep-dive-into-ranknet-200e799b52f4?source=collection_archive---------12-----------------------

深入了解可用于信息检索的最新排名系统。

文档排序是信息检索中的一项重要任务。(图片由弗洛里安·施梅兹Unsplash 上拍摄)

机器学*和人工智能目前正在推动计算机科学领域的创新,它们正被应用于跨学科的多个领域。然而,传统的最大似然模型仍然可以大致分为两类问题的解决方案。

  1. 分类——旨在根据各种特征将特定的数据实例标记到桶中。
  2. 回归——我们希望得到一个连续的实数作为给定特性集的输出。

机器学*的一个相对较少探索的应用是根据相关性对数据进行排序,这在搜索引擎等信息检索系统中变得有用。这些类型的模型更关注项目的相对排序,而不是单个标签(分类)或分数(回归),并被归类为 学*排序 模型。

rank net 简介

2005 年,克里斯·伯格斯等人。艾尔。微软研究院推出了一种新颖的方法来创建学*排名模型。他们的方法(在这里可以找到)采用了一个概率成本函数,该函数使用一对样本项目来学*如何对它们进行排序。该功能主要是尝试最小化纠正所选项目的错误排序所需的交换次数。他们的论文进一步探索了这种方法,通过神经网络实现这种成本函数,并通过梯度下降进行优化。这个名为“ RankNet ”的网络也在一些真实世界的数据上进行测试,以显示其有效性。

如本文中所实现的,RankNet 的工作总结如下。

训练网络

  1. 构造了一个具有一个输出节点的两层神经网络。输出值对应于该项与集合的相关性,并且输入层可以基于特征向量的大小而具有多个节点。
  2. 从数据集中选择两个随机样本,并分别对这两个样本进行前向传播,从而产生两个输出值,每个项目一个。
  3. 确定成本,该成本是这两个输出值之差的激活函数(e g: sigmoid )。假设第一个样本的排名高于第二个样本,并计算适当的损失。
  4. 这种损失被反向传播到网络中以学*所选择的例子。
  5. 执行步骤 2-4,直到训练完成(基于时期数)。

图片:所描述网络的前向传播演示。(礼貌:自己)

步骤 3 中提到的假设只不过是确定两个选定项目的预期等级。该等级可以通过比较特定项目相对于整个集合的相关性评级来确定。此外,可以通过基于一些假设手动设置相关性,或者通过使用人工评级者基于相关性对结果进行分类,来确定该相关性评级。

检索一个集合的排名

  1. 为了对特定集合中的项目进行排序,每个项目的特征向量通过网络传播,并且输出被存储。
  2. 现在,只需按照输出的降序排列项目,就可以对项目进行排序。

Burges 和他的同事用一些人工数据证明了这种方法的有效性。他们采用了两个排序函数,一个随机 2 层神经网络,以及一个随机多项式函数。在对 5000 个特征向量输入运行 100 个时期的数据后,他们获得了如下所示的结果。

图:两个排名函数的成对%正确结果。(礼貌:学*使用梯度下降法排名)

此外,这种方法在真实世界的数据——给定查询的搜索引擎结果——上进行了测试。需要注意的一点是,由于该模型不执行传统的分类或回归,因此其准确性必须基于排名质量的度量来确定。现实世界示例的排名准确度度量被选择为“NDCG”(正常贴现累积收益),这是用于评估特定排名集合的有效性的流行方法。NDCG 得出一个介于 0 和 1 之间的结果,1 代表项目的最佳排序。在训练了六个不同的排名函数(包括 RankNet 的两个不同实现)之后,对于搜索结果的给定查询/文档特征向量,在测试集上获得了以下结果。

图片:RankNet 与其他系统的比较。(礼貌:学*使用梯度下降法排名)

因此,我们看到 RankNet(一层和两层)的平均 NDCG 明显高于其他排名函数。

未来的改进

Burges 和他的同事进一步将 RankNet 的概念发展成训练时间更短、精度更高的模型。

λrank

在原始 RankNet 的训练过程中,发现不需要计算成本本身。相反,成本的梯度足以确定这对项目的预测排名。这可以被视为指示特定项目的移动方向的箭头。

图像:成本梯度的可视化,用箭头指示移动方向。(承蒙:从兰克内到兰达兰克到兰达玛特:概述)

此外,当他们通过交换文件导致的 NDCG 变化来放大这个梯度时,他们获得了更好的结果。因此,LambaRank 被证明训练速度更快,准确性也有所提高。

λmart

在另一个版本中,引入了渐变增强的树版本的 LambaRank】。在实验数据集中,这已被证明比前两个模型更加准确。

结论

因此,我们已经看到了一些最先进的排序技术,当我们想要在信息检索系统中对一组项目进行排序时,这些技术非常有用。所以问题来了,是什么阻止我们去实现这些模型呢?答案很简单——没事

(对于感兴趣的人,我自己使用 Keras 和 TensorFlow 实现的 RankNet 可以在https://github.com/devanshgoenka97/RankNet)

参考

1】:Burges,c .,Shaked,t .,Renshaw,e .,Lazier,a .,Deeds,m .,Hamilton,n .,&Hu lender,G. (2005)。学*使用梯度下降进行排序ICML 05 年

2】:布格斯,c,拉格诺,r . j .&勒,Q.V. (2007)。学*用非光滑代价函数排序

【3】:吴,q,Burges,c,Svore,k,&高,J. (2009)。适应信息检索措施的助推信息检索,13 ,254–270。

【4】:布格斯,C. (2010)。从兰克内到兰达兰克再到兰达玛特:概述。

用迷你批处理学* Wasserstein

原文:https://towardsdatascience.com/learning-with-minibatch-wasserstein-d87dcf52efb5?source=collection_archive---------36-----------------------

迷你批次 Wasserstein 距离属性简介

当我们对迷你批次使用 Wasserstein 距离时会发生什么?论文的结果来自 minibatch Wasserstein 的学*:渐*和梯度性质,发表在 AISTATS 2020 会议上。

对于许多机器学*应用,如生成模型1或领域适应[2],最优传输已经变得非常流行。在这些应用中,人们希望最小化源数据和目标数据之间的统计距离。为此,瓦瑟斯坦距离成了一项基本资产。它既可以用原始公式[2,3]计算,也可以用对偶公式1计算,并依靠小批量进行优化。不幸的是,由于连续函数的梯度计算,对偶可能导致数值不稳定,因此使用原始公式。出于学*目的,可以在[第 9.4、4 节]中找到对每种配方的利弊的综述。

然而,计算迷你批次之间的初始 Wasserstein 距离 并不等同于计算完全测量之间的初始 wasser stein 距离 。在这个故事中,我将描述minibatch wasser stein distance,其中 mini batch 范式对损失的后果被 置之不理。 对所呈现结果的全面回顾可见于我们的 AISTATS2020 论文【5】。

声明:为了简单起见,我将给出 Wasserstein 距离的结果,但所有这些结果都可以扩展到所有最优运输变量。我们也考虑一般地面成本。此外,我们将不区分元素集和它们的度量。

瓦瑟斯坦距离

基于 Kantorovich 问题, **Wasserstein 距离通过根据地面度量寻找测量值α和测量值β之间的最小位移成本来测量两个分布之间的**距离。设α (size n )和β (size n )为两个离散有界一致测度C 为一个度量(size n × n )。瓦瑟斯坦距离定义为:**

情商。(1):瓦瑟斯坦距离

⟨在哪里?,.⟩是 Frobenius 乘积和 E ( α,β)约束的集合。Wasserstein 距离必须在完全测量值α和β之间进行计算。U 不幸的是,它在数据数量上有一个立方复杂度 O(n^3) ,使它不适合大数据应用。OT 问题的变体出现了,如熵 OT 或 Sinkhorn 散度,但它仍然具有平方复杂度。为了克服这种复杂性,可以依靠计算源和目标测量的小批次之间的 Wasserstein 距离。

小批量 Wasserstein 距离

使用小批量策略很有吸引力,因为它在小批量大小上给出了一个立体的复杂性 O(m^3) 。然而,最优运输的原始公式不是一个总和,使用小批量并不等同于等式。(1).实际上,它 并不计算瓦瑟斯坦距离 ,而是计算从输入测量中采样的迷你批次 上瓦瑟斯坦距离的 期望值。形式上,它计算:

情商。(2) : 批次间 Wasserstein 距离的期望值

其中 m 为批量。由于它不等同于原始问题,所以理解这个新的损失是很有趣的。我们将回顾运输计划的结果,渐*统计特性,最后,一阶优化方法的梯度特性。

估计小批量 Wasserstein

让我们首先设计一个估计量。情商。(2)可以用以下估算器进行估算:

情商。(3):Eq 的估计量。(2)

其中总和取自源和目标测量中所有可能的小批测量 A 和 B。然而,要计算的小批量项目太多了。幸运的是,我们可以依赖子样本量。我们注意到 D_k,一组基数 k ,其元素是均匀绘制的小批偶。我们定义:

情商。(4):方程的不完全估计量。(2)

其中 k 是 minibatch 对的数量。我们还可以为运输计划计算一个类似的估计量,以估计小批量范式对运输计划的影响,更具体地说,是样本之间的联系(本文将详细介绍这一结构)。这个想法是平均样本之间的连接,以获得平均运输计划。

情商。(5):小批量 Wasserstein 计划估计量

当然,存在一个不完全的估计量,它遵循与等式 1 相同的结构。(4):

情商。(6):小批量 Wasserstein 计划不完全估计量

由于现在我们可以估计我们的数量,我们将给出一个小而有用的例子。

1D 案例:迷你批次切片 Wasserstein

1D 案例是一个有趣的特例。这很有趣,因为当数据位于 1D 时,我们可以获得接*形式的瓦瑟斯坦距离,然后,我们可以很容易地计算加班计划。1D 案例也是一个广泛使用的距离的基础,切片瓦瑟斯坦距离。计算全部最小批量 OT 计划的公式(等式。(5))可以在论文中找到。

我们考虑了源域和目标域的 20 个数据,采用统一的权重,并绘制了几个 ot 场景的平均运输计划。实验显示了不同批量的小批量 OT 计划 m正则化变量(熵+ L2)的 OT 计划之间的差异。

1D 措施的不同 OT 问题之间的运输计划[5]

我们在小批量瓦瑟斯坦距离正则化瓦瑟斯坦变异之间看到了相似的效应我们得到个样本之间的非最优连接。对于小批量 Wasserstein 距离,当 m 减少时连接数量增加。当正则化系数变大时,它类似于熵 OT 变量。人们还可以注意到,当批量减少时,连接的最高强度降低,这是由于约束。既然我们已经看到了小批量对运输计划的影响,让我们回顾一下损失的性质。****

基本属性

由于我们有了一个新的损失函数,有必要回顾它的优点和缺点,以比较概率分布。它具有以下属性:

  • 对于 iid 数据, Uũ是 Eq 的无偏估计量。(2)
  • Uũ的论点是对称的
  • 严格来说是 阳性
  • U( α,α)和ũ(α,都是 严格意义上的

这里有趣的属性是最后一个。对于非平凡测度,我们打破了可分性距离公理。因此, minibatch Wasserstein 距离不是距离 。这是获得数字速度的代价。我们将在梯度流实验中强调这种效应。

由于我们不知道分布 αβ,我们想知道等式。(2)可以用等式有效地估计。(4).

统计特性

我们的不完全估计器定义了一个 不完全双样本 U-统计量 。U-statistics 是由 Hoeffding 在 60 年代开发的[6]。使用 Hoeffding 不等式,可以得到我们的估计量围绕其期望值的偏差界限,概率为 1-δ:

其中 M 是支撑α和β的大小。这个偏差范围表明,如果我们增加数据 n 和批次 k 的数量,同时保持小批次大小固定,误差会以指数速度收敛到 0。值得注意的是,界限不依赖于数据的维度,这在高维优化时是一个有吸引力的属性。

对于生成模型,我们发现小的 k 足以获得有意义的结果,但是使用小批量会导致更长的训练时间。

运输计划和边际利润也有类似的性质。预计运输计划与 1/n 之间的偏差概率为 1-δ:

到边缘的距离

因为我们知道我们的损失有很大的统计性质,我们知道要研究是否可以用现代优化框架将其最小化。

SGD 的无偏梯度

众所周知,经验 Wasserstein 距离相对于连续测量值之间的 Wasserstein 距离具有偏差梯度[7]。这种偏差使得最小化经验 Wasserstein 距离不会导致连续测量之间的 Wasserstein 距离最小化。

与 Wasserstein 距离不同,mini batch wasser stein具有很好的属性,即具有 无基底梯度 ,因此我们可以使用 SGD 和我们的不完全估计量来最小化连续测量之间的损失。

这一结果在熵 OT 变体中得到了证明。与瓦瑟斯坦距离不同,熵 OT 处处可微。这是我们证明的一个基本要素。它允许我们使用无偏估计量和微分引理来证明无偏梯度。然而,我们在实践中使用迷你批次 Wasserstein 距离时没有遇到任何问题。

生成模型

我们举例说明了生成模型的小批量 Wasserstein 损失的使用。目标是学*生成模型以生成接*目标数据的数据。我们绘制了 8000 个点,它们遵循 2D 的 8 个不同的高斯模式(每个模式 1000 个点),其中模式形成一个圆。生成数据后,我们使用迷你批次 Wasserstein 距离和迷你批次 Sinkhorn 散度作为平方欧几里德成本的损失函数,并将它们与 WGAN 1及其具有梯度惩罚 WGAN-GP [8]的变体进行比较。

高斯模式生成[5]

我们看到,我们能够按照不同的模式生成数据。在 CIFAR 10 数据集上使用 minibatch Sinkhorn 散度的更广泛的结果可在3中获得。

梯度流量

在本节中,我们将介绍小型 Wasserstein 梯度流的使用。我们考虑来自名人数据集的 5000 张男性和 5000 张女性图像,并希望在男性和女性图像之间应用梯度流。梯度流的目的是模拟一个分布,该分布在每次迭代中遵循梯度方向,使最小批次 Wasserstein 距离最小化。形式上,我们对以下等式进行积分:

对于这个实验,我们将批量大小 m 设置为 500,将批量对数量 k 设置为 10。

5000 个男性图像和 5000 个女性图像之间的梯度流实验[5]

我们看到沿着梯度流动的图像的自然演变。然而最后的结果有点模糊。这是因为事实上小批量 Wasserstein 距离不是距离,并且我们与目标分布不匹配。

大规模颜色转移

我们还用我们的方法进行了颜色转移实验。颜色传输的目的是转换源图像的颜色,使其符合目标图像的颜色。最优运输是解决这个问题的一个众所周知的方法[9]。两点云图像之间的传输计划通过使用重心投影给出了传输颜色映射。其思想是使用已开发的小批量运输计划估计器,该估计器具有较小的内存和计算成本。我们使用了两张各为 1M 像素的图像,几个批次大小和批次数量。据我们所知,这是第一次有一种方法能够处理大规模的颜色转换。

大规模彩色转印[5]

我们可以看到,当批量太小时,颜色的多样性下降,就像熵解算器对大正则化参数所做的那样。这显然是由于源样本和目标样本之间的大量连接。然而,即使对于 100 万像素,1000 的批量大小也足以保持良好的颜色多样性。

结论

在这篇文章中,我们描述了小批量 Wasserstein 距离。一个 Wasserstein 距离变量,其目的是计算迷你批次上的原始 Wasserstein 距离。我们描述了一个形式,这个损失函数的基本性质,渐*性质,最后,优化程序。然后我们通过三个不同的实验研究了它的用途。关于我们如何改善迷你批次 Wasserstein 距离还有许多问题,我们将在未来的博客帖子中详细介绍。

文献学

1马丁·阿尔乔夫斯基,苏史密斯·钦塔拉,莱昂·博图。瓦瑟斯坦甘,ICML 2017

[2] BB Damodaran,B Kellenberger,R Flamary,D Tuia,N Courty,“ DeepJDOT:无监督域适应的深度联合分布最优传输”,ECCV 2018。

3奥德·热纳维、加布里埃尔·佩尔、马尔科·库图里。用 sinkhorn 分歧学*生成模型,AISTATS 2018

4加布里埃尔·佩尔,马尔科·库图里。计算最优运输,基础与趋势

[5]基利安·法特拉斯、尤尼斯·津、雷米·弗拉芒里、雷米·格里邦瓦尔、尼古拉斯·库蒂。用 minibatch Wasserstein 学*:渐*和梯度性质,AISTATS 2020

[6]瓦西里·赫夫丁。有界随机变量和的概率不等式,美国统计协会杂志 1963 年

[7]马克·贝勒马尔、伊沃·达尼埃尔卡、威尔·达布尼、沙基尔·穆罕默德、巴拉吉·拉克什米纳拉亚南、斯蒂芬·霍耶、雷米·穆诺斯。Cramer 距离作为有偏 wasserstein 梯度的解决方案。

[8]伊桑·古尔拉贾尼、法鲁克·艾哈迈德、马丁·阿尔约夫斯基、文森特·杜穆林、亚伦·库维尔。wasser stein GANs 的改进培训,NIPS 2017

[9]西拉·费拉丹斯、尼古拉·帕帕达基斯、朱利安·拉宾、加布里埃尔·佩雷、让-弗朗索瓦·奥约尔。正则化离散最优运输。计算机视觉中的尺度空间和变分法。

在不确定中学*

原文:https://towardsdatascience.com/learning-with-uncertainty-591f2cdee7?source=collection_archive---------35-----------------------

强化学*导论

现代强化学*背后的思想建立在试错学*和计算自适应控制的理论之上。这些方法的总体目标是构建一个代理,当它在反馈循环中与随机环境交互时,它可以最大化某个行为的回报。在面对不确定性时,代理通过从环境中接收到的响应来更新其决策策略。

通用强化学*框架。智能体在反馈配置中与环境交互,并根据它从环境中获得的响应更新其选择动作的策略。

试错搜索是从动物心理学领域学*行为的一种方法。桑代克、巴甫洛夫和斯金纳是这个学*领域的主要支持者。试错学*理论关注的是主体如何通过加强或削弱心理联系来学*行为,这种心理联系是基于主体在执行特定动作后从环境中感知到的满意或不满意(Thorndike,1898)。这种学*的想法被称为“效果法则”,其中“满意”是基于“奖励”的伴随行为的强化,“不适”导致由于“惩罚”而导致的行为中止。B.F. Skinner 在他关于操作性条件作用的工作中进一步探讨了这些奖励和惩罚的想法,该工作假设代理人根据刺激或行动自愿加强其行为,导致来自环境的反应(Skinner,1938)。另一方面,巴甫洛夫的经典条件作用认为,刺激的配对(其中第一个是无条件刺激)通过主体的行为产生了非自愿的反应(巴甫洛夫,1927)。这两种学*的行为理论都涉及到某种刺激对反应的联合配对的概念,由此一个主体的行为受到反馈循环中重复动作的制约。

T 型迷宫。T 型迷宫用于条件反射实验,以检查啮齿动物在使用不同时间表的连续试验中学*寻找食物的行为。

试错学*和效果法则有两个不同的特性影响了现代强化学*技术,因为它们是选择性的和联想性的。现代 RL 是选择性的,因为对于环境的特定状态,一个动作是从一组动作中取样的,它是关联的,因为有利的动作及其关联状态被记住(即存储在记忆中)(萨顿和巴尔托,1998)。

自适应控制领域涉及学*复杂动态系统中控制器(或代理)的行为,其中受控系统的参数中存在不确定性。(Bellman,1961)将控制问题分为确定性、随机性和适应性。在自适应控制系统中,系统中存在相当大的不确定性,对环境的结构或参数的分布知之甚少。虽然可以使用实验来获得关于系统的一些信息,但是所花费的时间将使得这种方法不可行。因此,需要在“在线”配置中学*控制器的行为。(Bellman,1957a)将 Bellman 方程展示为捕捉动态系统的状态和值函数的函数,并引入动态规划作为寻找自适应控制问题的最优控制器的一类方法。(Bellman,1957b)将马尔可夫决策过程(MDP)公式化为离散时间随机控制过程,用于建模强化学*框架,其中主体在反馈回路中与环境交互。Markov 属性假设当前状态获取了预测下一个状态及其预期响应所需的所有信息,而不依赖于先前的状态序列。换句话说,马尔可夫性质是环境的未来状态仅依赖于当前状态的条件概率。因此,如果我们知道当前状态,它就有条件地独立于过去的状态。MDP 基于环境状态具有马尔可夫性的理论假设。

文献学

  • 巴甫洛夫 IP (1927)。由 Anrep GV 翻译。“条件反射:大脑皮层生理活动的调查”。大自然。121 (3052): 662–664.Bibcode:1928Natur.121..662D。doi:10.1038/121662a0。
  • 斯金纳 B. F. (1938)。生物行为:实验分析。阿普尔顿世纪。
  • 萨顿和巴尔托(1998 年)。强化学*导论(第 2 卷第 4 期)。剑桥:麻省理工学院出版社。
  • 桑代克,E. L. (1898)。动物智力:动物联想过程的实验研究。心理学评论:专论增刊,2(4),i-109。https://doi.org/10.1037/h0092987.
  • 萨顿和巴尔托(1998 年)。强化学*:导论。麻省理工出版社。
  • 贝尔曼,R. E. (1961)。自适应控制过程——指南之旅。普林斯顿:普林斯顿大学出版社。
  • 贝尔曼,R. E. (1957a)。动态编程。普林斯顿:普林斯顿大学出版社。
  • 贝尔曼,R. E. (1957b)。马尔可夫决策过程。数学与力学杂志,6(5),679–684。从 www.jstor.org/stable/24900506.取回

最初发表于【https://ekababisong.org】

学* Wolfram:从零到英雄

原文:https://towardsdatascience.com/learning-wolfram-from-zero-to-hero-2ac4fd6914d9?source=collection_archive---------32-----------------------

通过这一快速介绍,快速启动您的数据科学能力

照片由海伦娜·洛佩斯Unsplash 拍摄

Wolfram 语言提供了一个超级丰富的笔记本界面和数千个精心设计的函数,让数据科学项目变得令人愉悦。借助优秀的教程、详尽的参考文档和上下文相关的帮助,现在开始使用 Wolfram 语言比以往任何时候都更容易。

作为一名长期使用 Wolfram 语言的程序员,我认为分享一下我对如何将这个强大的应用程序添加到您的数据科学技能组合中的看法会很有用。

(图片由作者提供)

开始的最好地方是“程序员快速入门”教程。它出色地介绍了从定义函数的基础到更高级的主题,如构建界面和将笔记本、图形和图像部署到 Wolfram Cloud。每个部分都有一个视频,涵盖了相同的主题,这给了你另一个很好的学*选择。

[## Wolfram 语言教程:程序员快速入门

花几分钟时间阅读本教程,快速掌握 Wolfram 语言的基础。几乎…

www.wolfram.com](https://www.wolfram.com/language/fast-introduction-for-programmers/en/)

您可以通过点击教程中的“入门”按钮立即开始使用 Wolfram 语言。这将在 Wolfram Cloud 中打开一个笔记本,不需要下载或注册任何东西。只需尝试教程中的例子,并开始尝试!

磨练编程技能的下一步是访问“Wolfram U”学*网站。

[## Wolfram U:面向学生和专业人士的开放课程

为 Mathematica、Wolfram 语言、数据科学、机器等开放课程、课堂、培训、免费视频和活动

www.wolfram.com](https://www.wolfram.com/wolfram-u/)

对于数据科学家来说,在“数据科学&统计学”部分有一些非常非常好的课程和视频。这里的主要课程“多层面数据科学”是一门在线课程,包含带解说的视频、带代码的笔记本,可用于临时编码区:

(图片由作者提供)

每个部分都有一个小测验,所以你可以很容易地测试自己。

在这一点上,我建议注册一个免费的基本 Wolfram 云。这使您能够在学*语言的同时进行疯狂的编程实验:

[## 沃尔夫拉姆云

Wolfram 语言的云访问。

www.wolframcloud.com](https://www.wolframcloud.com/)

另一个选择是为开发者下载免费的 Wolfram 引擎。这使您可以访问本地机器上的核心语言。它不包括漂亮的 Wolfram 笔记本接口,但是你可以把这个引擎挂在 Jupyter 笔记本接口上。

此外,许多人已经为各种 ide 开发了插件,这些插件都列在开发人员的主资源页面上:

[## 面向软件开发人员的 Wolfram

Wolfram 技术堆栈使您能够在几分钟内开发和部署一个有用的应用程序,并构建…

www.wolfram.com](https://www.wolfram.com/developer/)

如果你想体验完整的 Wolfram 笔记本界面(而且我强烈推荐这个!)您可以从 Wolfram 桌面试用版开始,此处提供:

[## Wolfram|One:云桌面计算平台

云+桌面上的高级混合计算平台。利用以下各项的全部功能,让您的发展更进一步

www.wolfram.com](https://www.wolfram.com/wolfram-one/)

最后,在 Wolfram 语言中保持高效的最佳长期资源是广泛的参考文档,它们被深度集成到笔记本中。至少有两个很棒的用户社区,你可以在那里提问。首先是 Wolfram 社区,这不仅是一个提问的好地方,也是一个与他人分享你的工作的好地方。其次,Mathematica&Wolfram Language Stack Exchange网站非常适合提问(和回答)问题。

(图片由作者提供)

我希望这对您有用,并祝您在下一个数据科学项目中好运!

学* Wolfram:与 Web 浏览器交互

原文:https://towardsdatascience.com/learning-wolfram-interacting-with-web-browsers-29900c1a5cea?source=collection_archive---------48-----------------------

自动化您的 Web 测试和浏览工作流

杰克·范德斯波尔在 Unsplash 上的照片

当我在质量保证部门工作时,我的工作之一是在一些网站上做回归测试。那时只有有限的自动化工具,所以我的解决方案包含了发布鼠标和按键事件的 Java 机器人类。这当然非常脆弱。

最*,自动化 web 浏览器交互变得更加容易。WebDriver 协议指定了一组非常好的命令和交互来与浏览器对话。Wolfram 语言(WL)使用这个协议让你直接从一个笔记本会话中控制浏览器。笔记本的交互特性非常适合增量开发 web 自动化工作流。在这个故事中,我将向您展示如何开始使用这个功能。

要启动一个新的 web 浏览器会话,您可以使用 StartWebSession 命令。如果没有函数参数,它将在你的电脑上启动一个 Chrome 浏览器。也支持 Firefox 浏览器。

(图片由作者提供)

要打开网页,您可以使用 WebExecute 命令。此命令是您用来控制 web 浏览器的主要功能。您指定会话,并给它一个命令,如“open 网页”、“ClickElement”或“JavascriptExecute”:

(图片由作者提供)

例如,要单击搜索图标(右上角的放大镜),您可以通过它的 XPath 或 CSS 选择器来引用它。你可以在浏览器的开发者控制台找到这些。一个写得好的 web 页面为特定的元素使用惟一的 ID,在这种情况下,ID 是“_nav-search”。执行该命令会在浏览器中显示搜索栏:

(图片由作者提供)

同样,您可以在输入栏中键入文本。例如,如果我想搜索“数据集”,我可以指定元素和搜索文本。通过在字符串末尾添加一个“\n”(换行符)来模拟按 enter 键:

(图片由作者提供)

为了检索和检查页面内容,我通常使用一小段 javascript。例如,检索页面上所有链接的 URL 的一种方法是,我使用下面的 javascript 代码片段:

(图片由作者提供)

结果是一个 WL 字符串列表,该列表可用于回归测试或进一步的导航步骤。同样,您可以收集网页上所有图像的 URL,然后将这些图像直接导入到您的 WL 会话中以供进一步检查。

当您完成浏览器会话时,您可以使用 DeleteObject 命令来结束它。这将关闭 web 浏览器并结束连接:

有关这一有用功能的更多信息,请查看 Web 浏览器自动化的指南页面。要了解更多关于 WL 的入门知识,请查看我最*的一篇名为“学* Wolfram:从零到英雄”的文章。上面图片中显示的完整代码的笔记本可以从这里获得。只需点击该链接,然后将笔记本下载到您的桌面上。

学* Wolfram:增强机器学*项目的资源

原文:https://towardsdatascience.com/learning-wolfram-resources-to-supercharge-your-machine-learning-projects-37d7472d5c02?source=collection_archive---------68-----------------------

使用 Wolfram 改善您的工作流程和工作效率

照片由 Cookie 在 Unsplash 上的 Pom 拍摄

《纽约客》上一幅著名的漫画曾调侃道:“在互联网上,没人知道你是一只狗”。这个笑话背后的想法是,在互联网上,任何人都可以伪装成任何人,并且很难验证某人就是他们所说的那个人。

但那幅漫画发表于 1993 年,远在人工智能和机器学*算法出现之前。今天,这幅漫画的标题可能是“在互联网上,没有人知道你是一台电脑”,电脑盯着屏幕:我们与互联网服务和应用程序的交互如此之多,以至于我们经常无法立即分辨我们是在和一个真人还是一个机器人说话。

位于所有这些人工智能核心的机器学*算法是复杂的数值优化,旨在生成极有可能的输出(数字、文本、图像、语音等)。)基于某些输入(还有数字、文本、图像、语音等)。)

一个好的机器学*框架提供了这些类别的算法,但是一个伟大的机器学*框架也使它易于学*、易于使用和易于开发。有很多好的机器学*框架(也许太多了?)在那里,任何人都可以通过大量的努力,对它们进行编程,以慢慢获得有用的结果。但不幸的是,没有太多伟大的机器学*框架。

Wolfram 语言确实提供了一个很好的机器学*框架,因为它易于学*和使用,而且——因为它是基于 Apache MXNet 的——非常适合研究和开发。

[## 机器学*:Wolfram 方法

适用于各种应用的自动化、最先进的机器学*…

www.wolfram.com](https://www.wolfram.com/featureset/machine-learning/)

Wolfram 语言本身非常容易学*,因为它丰富的笔记本界面鼓励交互式实验。要了解更多关于学* Wolfram 语言的基础知识,请查看我最*的帖子:

[## 学* Wolfram:从零到英雄

通过这一快速介绍,快速启动您的数据科学能力

towardsdatascience.com](/learning-wolfram-from-zero-to-hero-2ac4fd6914d9)

接下来,为了学*如何使用机器学*框架进行开发, WolframU 学*资源网站有大量的视频教程和 mooc来帮助你入门。这些教程和工作流程,以及包含数千个真实示例的大量参考文档,使学*和使用变得非常容易:

[## 机器学*-Wolfram 语言文档

Wolfram 语言包括广泛的最先进的集成机器学*能力,从高度…

reference.wolfram.com](https://reference.wolfram.com/language/guide/MachineLearning.html)

Wolfram 机器学*框架的另一个主要特征是包含了 Wolfram 神经网络库,这是一个预先训练好并可立即使用的神经网络的大型库。这意味着您可以用不到一行代码访问大量高性能的神经网络:

(图片由作者提供)

最后,因为这个框架是建立在 Apache 的 MXNet 之上的,所以它有很好的性能。对来自 Nvidia 的 GPU 硬件的支持是内置的,即使在多个 GPU 板上也可以快速训练。

最好的开始方式是使用 Wolfram|One 平台进行尝试,该平台包括此处描述的一切,包括访问 Wolfram 云。

[## Wolfram|One:云桌面计算平台

云+桌面上的高级混合计算平台。利用以下各项的全部功能,让您的发展更进一步

www.wolfram.com](https://www.wolfram.com/wolfram-one/)

使用 Wolfram technologies 会给你带来巨大的竞争优势,你的秘密开发者酱,或者像我喜欢想的那样:“在互联网上,没有人知道你在使用 Wolfram”。

图片由作者根据 Cookie 在 Unsplash 上的 Pom 照片制作

学* Wolfram:使用时间序列

原文:https://towardsdatascience.com/learning-wolfram-working-with-timeseries-a7e8e91174ab?source=collection_archive---------38-----------------------

一个关于美国煤炭生产的计算思维故事

作者在 Unsplash 上使用paweczerwiński的照片制作的图片

在世界范围内,煤炭正被其他形式的能源慢慢取代,以帮助减少地球大气中的温室气体。在美国,美国能源信息署(EIA)收集能源信息,如一段时间内的煤炭产量。这个故事使用这个时间序列数据来说明 Wolfram 语言中的一些时间序列功能。

开始之前,我们需要访问 EIA 的数据。我写了一个名为UnitedStatesCoalProduction的简单函数来访问他们的数据 API,并按地区导入煤炭产量数据:

UnitedStatesCoalProduction = ResourceFunction[
"user:arnoudb/DeployedResources/Function/UnitedStatesCoalProduction"]

调用这个函数有两个参数。第一个参数使用类似“KY”的代码来指定区域。第二个论据是 API key 可以从 EIA 网站获取。如何操作的详细信息记录在功能参考文件页。调用该函数的典型方法如下:

kentucky = UnitedStatesCoalProduction["KY",key]

这将返回一个 TimeSeries 对象。在 Wolfram 笔记本中,总是大量使用排版显示格式,它用一个摘要框来格式化:

(图片由作者提供)

时序对象可直接用于可视化功能,如日期列表图:

(图片由作者提供)

时序对象可以直接用于常见的统计函数。请注意所有煤炭产量数字是如何与其单位(短吨)一起存储的。跟踪单位总是有用的,尤其是在处理多个数据集和不同单位时:

In[.]:= Mean[kentucky]Out[.]= Quantity[9.53609*10^7, "ShortTons"]

让我们来看另一个数据集,伊利诺伊州的:

illinois = UnitedStatesCoalProduction["IL", key]

我们可以将这两个数据集绘制在一起,并用清晰的标签来修饰这个图。我将 y 轴换算成百万短吨,让人类更容易读懂:

DateListPlot[
 {kentucky, illinois}/10^6,
 PlotLegends -> {"Kentucky", "Illinois"}, 
 FrameLabel -> {"Year", "Short Tons (millions)"}
]

(图片由作者提供)

显然,肯塔基州的煤炭产量下降了很多,而伊利诺伊州在过去十年中实际上增加了产量。

Wolfram 语言中的时序对象处理基本的数学运算,如加、减、除和乘。例如,为了比较肯塔基州和伊利诺伊州的煤炭产量比率,简单地划分时间序列:

DateListPlot[kentucky / illinois,
 FrameLabel -> {"Year", "Ratio Kentucky vs Illinois"},
 GridLines -> Automatic
]

(图片由作者提供)

时间序列可以在其他时间间隔重新采样。当您需要比较两个具有不相容间隔的时间序列时,这可能会很有用。对时间序列进行重采样可以使数据标准化。以下示例显示了如何以三个月的时间间隔进行重新采样。

TimeSeriesResample[kentucky, Quantity[3, "Months"]]

(图片由作者提供)

要提取具有开始和结束日期/时间的时间序列的一部分,可以使用 TimeSeriesWindow 函数。例如,这将提取 2005–2010 年的时间序列数据:

TimeSeriesWindow[kentucky, {
 DateObject[{2005}, "Year"],
 DateObject[{2010}, "Year"]
}]

(图片由作者提供)

有关时序操作相关函数的完整列表,您可以阅读时序处理文档指南页面。

要制作一个类似于本文顶部所示的非常漂亮的可视化图形,您可以使用我之前关于如何装扮您的数据可视化的文章中的提示和技巧。

us = UnitedStatesCoalProduction["US", key];
DateListPlot[us/10^6, 
 PlotRangePadding -> None, PlotRange -> {0, 1400},
 PlotStyle -> Directive[White, AbsoluteThickness[5]],
 PlotLabel -> Style["United States Total Coal Production (2000-2020)", "Subsection"], 
 FrameLabel -> {"Year", "Short Tons (millions)"},
 ImageSize -> Large, Prolog -> Inset[image, Center, Center, Scaled[{1.2, 1.2}]]]

作者在 Unsplash 上使用了paweczerwiński的照片

离开学术界进入工业界,优化你的学*方式

原文:https://towardsdatascience.com/leaving-academia-for-industry-and-optimizing-how-you-learn-9ca9978e2868?source=collection_archive---------17-----------------------

苹果 | 谷歌 | SPOTIFY | 其他 | 剪辑

伊恩·哈洛在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:

我不记得有多少次我忘记了一些重要的事情。

不过,我确信这是经常发生的事情:我经常忘记宝贵的生活经验、技术概念和有用的统计理论。更糟糕的是,我经常在努力学*之后忘记这些事情,所以我的健忘完全是浪费时间和精力。

这就是为什么我抓住机会与 Cerego 的科学副总裁 Iain Harlow 聊天的原因,Cerego 是一家通过优化信息提供方式来帮助企业为员工建立培训课程的公司,以最大限度地保留和学*成果。

Iain 非常了解学*,并就如何优化自己的学*提出了一些很好的见解,但他在解决数据科学问题和聘用数据科学家方面也有很多专业知识,这是他在 Cerego 工作中关注的两件事。他也是学术界的资深人士,并分享了一些关于学术界研究和工业界研究之间差异的有趣观察。

我们的谈话涵盖了很多领域,但以下是我最喜欢的一些要点:

  • 当你忘记某件事时,通常并不是你的大脑失去了曾经拥有的关于那件事的信息。相反,我们容易忘记事情,因为我们的大脑不记得我们在寻找的信息存储在哪里。打个计算机科学的比方,遗忘有点像失去了指向包含我们试图检索的信息的内存地址的指针:数据存储在某个地方,只是我们想不起在哪里。
  • 这种观点的一个含义是,一旦学会了信息,练*检索信息比大多数人认为的更重要。虽然这与直觉相反,但定期测试你的知识与一开始就学*它一样重要,因为它迫使你练*回忆。
  • 学术界的生活和工业界的生活最大的区别之一就是批评。在学术界,所有的想法都倾向于被怀疑和批判,而在工业界,大多数人会认为他们周围的人知道他们在做什么。虽然这可以在短期内让事情变得更令人愉快,但这也意味着行业数据科学家、分析师或机器学*工程师有更多的责任来确保他们的工作检查无误。
  • 产品直觉真的很重要,它通常伴随着专业知识。你对你的客户、你的用户群或你的问题空间了解得越多,你就越能更好地识别你的模型成功所需的特征。
  • 因此,公司非常关心你培养产品意识的能力。最好的方法是通过个人项目,使用独特或不寻常的数据集,迫使你问这样的问题,“我能从这些数据中获得什么价值?”
  • 求职者通常认为面试就像是大学考试,被设计成一系列“抓住你”的问题。在现实中,面试官通常利用工作面试来筛选解决问题的能力,而不在乎“得分”表现。这似乎是一个微妙的区别,但它很重要:这意味着在许多情况下,你的分析和沟通能力比原始的技术能力更重要。因此,实践你的数据故事和产品直觉是一个很大的优势。

夹子

你可以在 Twitter 上关注伊恩,你也可以在 Twitter 上关注我在这里

你也可以在 Twitter脸书LinkedIn 上查看 Cerego。

我们正在寻找能与我们的观众分享有价值的东西的客人。如果你碰巧认识一个合适的人选,请在这里告诉我们:publication@towardsdatascience.com

战争的教训:作为一名军事分析家我学到了什么

原文:https://towardsdatascience.com/leaving-the-war-12d8f98d7f20?source=collection_archive---------44-----------------------

作为一名军事数据分析师,我学到了什么,你如何应用它,以及我为什么离开。

我在美国海军做了 6 年的情报专家,在阿富汗和非洲服过预备役和现役。军事情报训练是学*分析推理、数据分析以及如何发展向大群人展示你的发现的能力的最佳途径之一。

我们被教导成为顶级分析师所需要的一切。以下是我一直铭记在心的三条重要经验。这些经验适用于数据分析领域的所有人。

坐在后面手里拿着 kindle 的是我。

分析师的三个教训

第一课:人可能会死

在军事领域,如果你犯了一个错误,有人可能会死。所以,你最好确保你的信息是正确的。在平民世界里,赌注没有那么高,但这个教训是正确的。这可能不是一个人的生命受到威胁,但它可能是一笔重要的销售交易或一次成功的营销活动。仔细检查所有东西。

如何申请:

  • 精神饱满地回来:完成项目后,去散散步或分散注意力,这样你就能精神饱满地回来。当我们在一个项目上工作时,我们的大脑开始疲劳,我们更容易错过小错误。
  • 询问好友:在分享你的项目之前,把它带给你的好友,询问他们的意见。让他们尽可能批判性地评估它——如果你能给他们一个提示列表就更好了——比如“我的视觉效果清楚吗?”或者“你能仔细检查我的数学吗?”
  • 检查你的资料来源:对数据来源持批评态度。探索他们的方法,并确保您传达的是来自该数据的正确信息。

第二课:没人在乎

注意力是有限的。在军事领域,当我给海军上将或舰长们做报告时,我能看出他们的心思在别处。他们在考虑下一个任务。你组织中的首席执行官和其他领导人也在做同样的事情。他们在考虑下一笔交易或收到的最后一封电子邮件。你必须能够吸引并保持利益相关者的注意力。你需要的人关心。

如何申请:

  • 让他们震惊:当你开始交流你的数据分析时,你应该总是以这样的问题开始:“他们不知道什么?”并以此为线索。你希望能够震撼听众,让他们全神贯注于你。如果你用他们已经熟悉的信息来引导,你最终可能会失去他们。
  • 当利益相关者提问时,如果你不知道答案,你可以说:“我会研究一下,然后再给你答复。”这有两个目的——吸引利益相关者的注意力,因为他们希望在未来与你交谈;防止你的陈述偏离轨道。
  • 让它变得别致:你的图表需要漂亮。花额外的时间学*如何有效地可视化您的数据。想想你的颜色,以及它们是如何搭配的。了解最佳数据可视化实践。我强烈推荐用 Dat a 讲故事作为学*数据可视化最佳实践的良好起点。

第三课:那是什么鬼东西

你一定很好奇。在军事分析领域,我们不断地查看数据并相互询问“这是什么?为什么会这样?这是什么意思?”—我们需要理解数据中更奇怪的部分。在平民世界里,当你在数据中看到一些东西,你会说,“那到底是什么?”不要就此打住——挖到你知道为止。

如何申请:

  • 大声说出来:当你在数据集中遇到异常时,比如地图中的异常值或异常点,你不应该隐瞒。深入探究,试着理解它是如何发生的。询问这对您的其他数据意味着什么。
  • 讲故事:数据在给你讲故事,你只需要找到它。当回顾数据时,实际上写下你开始看到的故事。在军事领域,这是一份报告。在平民世界,它可能是一个单独的文件,详细说明您的发现。
  • 承认自己的无知:有时候你只需要承认自己不知道。带着你的问题或疑问去找一个值得信赖的顾问或同事,请他们帮忙解决这个难题。

为什么我决定离开

作为一名军事分析家有巨大的压力。人们期望我们做到完美,因为错误的后果可能会导致生命损失。在我们的分析和陈述中,我们不能马虎。我们需要确保自己无可指责。当你面临如此多的风险时,它会从你的工作和生活中吸取快乐。我发现自己在应对焦虑。我变成了一个不健康的完美主义者。我对工作失去了热情。

随着我与军方的合同即将结束,我面临着一个艰难的选择。我应该在这个已经成功的世界里继续吗?或者我应该离开并可能失败?

我对自己的军事记录非常自豪。我获得了三枚军用航空奖章,和我的机组人员一起被提名参加著名的 T2 麦凯奖。我所做的工作拯救了许多人的生命,让我真正感觉到我在为这个世界做出有意义的贡献。

最终,我决定离开军队,加入平民世界,这样我就可以重拾对数据分析的热情。

下一步是什么?

我目前正在为 WeWork 学*分析,我发现让我在军队中取得成功的经验也适用于我目前的职业生涯。我希望我对数据分析的热情能够为个人和公司解决现实世界的挑战。

如果你想听更多,想看我的旅程, 和我在 twitter 联系。

激活、卷积和池化—第 1 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-activations-convolutions-and-pooling-part-1-ddcad4eb04f6?source=collection_archive---------59-----------------------

FAU 讲座笔记深度学*

经典激活

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎回到深度学*!所以在今天的讲座中,我们想谈谈激活和卷积神经网络。我们把它分成几个部分,第一部分是关于经典激活函数。后面会讲到卷积神经网络,池化,之类的。

人造神经元和它们的生物对应物有一些微弱的相似之处。 CC 下的图片来自深度学*讲座的 4.0 。

让我们从激活功能开始,你可以看到激活功能可以追溯到生物动机。我们记得到目前为止我们所做的一切,不知何故,我们也以生物学的实现为动机。我们看到生物神经元通过突触与其他神经元相连。这样,他们实际上可以互相交流。突触有髓鞘,有了髓鞘,它们实际上可以电绝缘。它们能够与其他细胞交流。

当超过某个阈值时,生物神经元就会激活。 CC 下的图片来自深度学*讲座的 4.0 。

当他们交流时,他们不仅仅是发送他们收到的所有信息。他们有一个选择机制。因此,如果你有一个刺激,它实际上不足以产生一个输出信号。总信号必须高于阈值,然后发生的是动作电位被触发。之后,它重新极化,然后回到静止状态。有趣的是,细胞被激活的程度有多强并不重要。它总是返回相同的动作电位,回到静止状态。

轴突的详细视图。来自深度学*讲座CC BY 4.0 下的图片。

实际的生物激活甚至更复杂。你有不同的轴突,它们与其他神经元的突触相连。在路径上,它们被许旺细胞覆盖,然后许旺细胞可以将这种动作电位传递给下一个突触。有离子通道,它们实际上用于稳定整个电过程,并在激活脉冲后使整个事情再次进入平衡。

生物神经元观察综述。 CC 下的图片来自深度学*讲座的 4.0 。

所以,我们可以看到知识本质上存在于神经元之间的连接中。我们有抑制性和兴奋性连接。突触在解剖学上加强了前馈处理。所以,这和我们目前看到的非常相似。然而,这些连接可以是任何方向的。因此,它们也可以形成循环,你有完整的神经元网络,它们与不同的轴突相连,以形成不同的认知功能。关键是激活的总数。只有当激活的总数超过阈值时,你才会真正的激活。这些激活是具有特定强度的电尖峰,老实说,整个系统也是时间相关的。因此,它们也随时间对整个信息进行编码。所以,不只是我们有一个单一的事件通过,而是整个过程以一定的频率运行。这使得整个处理过程能够持续一段时间。

符号函数不适合梯度下降。 CC 下的图片来自深度学*讲座的 4.0 。

到目前为止,人工神经网络中的激活都是非线性激活函数,主要由通用函数逼*来驱动。所以如果我们没有非线性,我们就不能得到一个强大的网络。如果没有非线性,我们只能以矩阵乘法结束。所以与生物学相比,我们有一些符号函数可以模拟全有或全无的反应。通常,我们的激活没有时间成分。也许,这可以通过符号函数的激活强度来建模。当然,这在数学上也是不可取的,因为正弦函数的导数在任何地方都是零,除了在无穷远处的零点。所以这绝对不适合反向传播。因此,我们一直使用 sigmoid 函数,因为我们可以计算解析导数。现在的问题是“我们能做得更好吗?”。

线性激活在建模方面没有太大帮助,但是它们在数学上很容易掌握。来自深度学*讲座CC BY 4.0 下的图片。

那么,我们来看看一些激活函数。我们能想到的最简单的方法是线性激活,我们只是复制输入。我们可能希望用某个参数α对其进行缩放,然后得到输出。如果我们这样做了,我们就得到了α的导数。这非常简单,它会将整个优化过程转化为一个凸问题。如果我们不引入任何非线性,我们基本上就陷入了矩阵乘法。因此,我们在这里列出它只是为了完整性。它不允许你建立我们所知的深度神经网络。

sigmoid 函数是可微分的,并且可以用于神经网络建模。 CC 下的图片来自深度学*讲座的 4.0 。

现在,sigmoid 函数是我们开始的第一个函数。它本质上具有朝向 1 和 0 的饱和度。因此,它有一个非常好的概率输出。然而,当 x 值变得很大或很小时,它会饱和。你可以看到,导数已经在 3 或-3 左右,很快接*零。另一个问题是它不是以零为中心的。

Sigmoid 激活将输出分布移向正值。来自深度学*讲座CC BY 4.0 下的图片。

零点对中的问题是,你总是产生正数,与你得到的输入无关。您的输出将总是正的,因为我们映射到 0 和 1 之间的值。这意味着,如果我们有一个零均值的信号作为激活函数的输入,它将总是向一个大于零的均值移动。这被称为连续层的内部协变量移位。因此,各层必须不断适应不断变化的分布。因此,批量学*减少了更新的方差。

tanh 激活解决了内部协变量移位的问题。 CC 下的图片来自深度学*讲座的 4.0 。

那么我们能做些什么来弥补这一点呢?嗯,我们可以用其他的激活功能,一个非常流行的是 tangens 双曲线。这里用蓝色显示。你可以看到它有非常好的特性。例如,它以零为中心,乐存从 1991 年就开始使用。所以,你可以说它是 sigmoid 函数的一个移位版本。但是一个主要的问题仍然存在。这就是饱和。所以你可以看到,也许在 2 或-2,你已经看到导数非常接*于零。所以还是会造成渐变消失的问题。

消失和爆炸梯度给训练网络带来了很大的问题。 CC 下的图片来自深度学*讲座的 4.0 。

嗯,现在这里的本质是 x 如何影响 y 。我们的 sigmoid 和双曲线正切,它们将 x 的大区域映射到 y 的非常小的区域。因此,这意味着 x 的大变化将导致 y 的小变化。所以梯度消失了。这个问题被反向传播放大了,在反向传播中,你有很多非常小的步骤。如果它们接*于零,并且你将这些更新步骤彼此相乘,你会得到一个指数衰减。网络建立得越深,梯度消失得越快,更新下层就越困难。所以,一个非常相关的问题当然是爆炸梯度。所以,这里我们有一个问题,我们有高价值,这些高价值互相放大。结果,我们得到一个爆炸梯度。

不仅η的选择对训练网络至关重要。来自深度学*讲座的 4.0CC 下的图片。

因此,我们可以考虑一下我们之前见过的反馈环路和控制器。我们已经看到,如果您在训练迭代中测量损失,您的损失曲线会发生什么。如果你不适当地调整学*率,你会得到爆炸梯度或消失梯度。但不仅仅是学*率η。这个问题也可能被激活函数放大。特别地,消失梯度是那些饱和激活函数出现的问题。所以我们可能想考虑一下,看看我们是否能得到更好的激活函数。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

所以,下一次深度学*,我们将确切地看看这些激活功能。你今天所看到的基本上是经典的,在下一节课,我们将讨论为了建立更稳定的激活函数所做的改进。这将使我们能够进入真正的深层网络。非常感谢您的收听,下次再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学*的教育材料,或者看看我们的深度 学* 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 或 T21 上的掌声或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1 I. J. Goodfellow、d . ward-Farley、M. Mirza 等人,“最大网络”。载于:ArXiv 电子版(2013 年 2 月)。arXiv:1302.4389[统计 ML】。
[2],,,,任等,“深入挖掘整流器:在 ImageNet 分类上超越人类水平的表现”。载于:CoRR abs/1502.01852 (2015)。arXiv: 1502.01852。
3君特·克兰鲍尔(Günter Klambauer),托马斯·安特辛纳(Thomas Unterthiner),安德烈亚斯·迈尔(Andreas Mayr),等,“自归一化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。
【四】、和水城颜。“网络中的网络”。载于:CoRR abs/1312.4400 (2013 年)。arXiv: 1312.4400。
[5]安德鲁·马斯、奥尼·汉南和安德鲁·吴。“整流器非线性改善神经网络声学模型”。在:过程中。ICML。第 30 卷。1.2013.
[6] Prajit Ramachandran,Barret Zoph,和 Quoc V. Le。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
【7】Stefan elf wing,内池英治,多亚贤治。“强化学*中神经网络函数逼*的 Sigmoid 加权线性单元”。载于:arXiv 预印本 arXiv:1702.03118 (2017)。
[8]克里斯蒂安·塞格迪、、·贾等,“用回旋深化”。载于:CoRR abs/1409.4842 (2014 年)。arXiv: 1409.4842。

激活、卷积和池化—第 2 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-activations-convolutions-and-pooling-part-2-94637173a786?source=collection_archive---------62-----------------------

FAU 讲座笔记深度学*

现代激活

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

整流线性单元(ReLU)是最早的现代激活之一。 CC 下的图片来自深度学*讲座的 4.0 。

欢迎回到激活函数和卷积神经网络的第 2 部分!现在,我们想继续讨论激活函数和深度学*中使用的新函数。最著名的例子之一是整流线性单元(ReLU)。现在 ReLU,我们前面已经遇到过了,它的思想是简单地将负半空间设置为 0,将正半空间设置为 x,这就导致了整个正半空间的导数为 1,而其他地方的导数为 0。这很好,因为这样我们得到了一个很好的概括。由于分段线性,有一个显著的加速。该函数可以很快求值,因为我们不需要在实现方面通常有点慢的指数函数。我们没有这个消失梯度的问题,因为这个函数的导数有很大的高值区域。缺点是它不是以零为中心的。现在,这还没有用整流线性单元解决。不管怎样,这是一大进步。有了 ReLUs,你可以第一次建立更深层次的网络,更深层次的网络,我指的是隐藏层多于三层的网络。

经典的机器学*总是使用三个隐藏层。用imgflip.com创造的迷因。

通常在经典的机器学*中,神经网络被限制在大约三层,因为在这一点上你已经得到了消失梯度问题。较低的层从未看到任何梯度,因此从未更新它们的权重。因此,ReLUs 实现了深度网络的训练,而无需无监督的预训练。你已经可以建立深度网络,但你必须进行无人监督的预训练,有了 ReLUs,你可以直接从零开始训练,只需把你的数据放进去,这是一大进步。此外,实现非常容易,因为如果单元被激活,一阶导数为 1,否则为 0。所以没有二阶效应。

一个大问题是死亡关系。来自深度学*讲座CC BY 4.0 下的图片。

还有一个问题:垂死的瑞卢斯。如果你的权重和偏差被训练成对 x 产生负的结果,那么你最终只会得到一个零导数。ReLU 总是产生一个零输出,这意味着它们不再对你的训练过程有所贡献。所以,它就停在这一点,因为 0 阶导数,不可能更新。这个宝贵的 ReLU 突然总是 0,再也无法训练了。如果你的学*率太高,这种情况也会经常发生。在这里,你可能要小心设置学*率。有几种方法可以解决这个问题,我们将在接下来的几个视频中讨论。

泄漏的 ReLUs 有助于避免死亡 ReLUs。 CC 下的图片来自深度学*讲座的 4.0 。

缓解这个问题的一个方法是不仅使用一个 ReLU,而且使用一种叫做泄漏或参数 ReLU 的东西。这里的方法是,不要将负半空间设置为零,而是将其设置为一个小数值。所以,你用α乘以 x,把α设为一个小数字。然后,你有一个与 ReLU 非常相似的效果,但你不会以垂死的 ReLU 问题结束,因为导数从来不是零,而是α。我首先通常将值设置为 0.01。参数 ReLU 是进一步的扩展。在这里,你使α成为一个可训练的参数。所以你可以知道每个激活函数应该有多大。

指数线性单位。来自深度学*讲座CC BY 4.0 下的图片。

也有指数线性单位,这里的想法是,你在负半空间上找到一个缓慢衰减的光滑函数。你可以看到,我们把它设为α乘以 x 的指数减 1。这就产生了导数 1 和α指数 x,这也是获得饱和效应的一种有趣方式。这里,我们没有消失梯度,它也减少了激活的变化,因为我们也可以得到负输出值。

比例指数线性单位旨在保持 0 均值和 1 方差。 CC 下的图片来自深度学*讲座的 4.0 。

如果您选择指数线性单位的这种变体,您将增加一个额外的标度λ。如果您的输入具有零均值和单位方差,您可以选择α和λ以及此处报告的这两个值,它们将保持零均值和单位方差。因此,这种比例指数函数(SELU)也摆脱了内部协变量移位的问题。所以这是 ReLU 的另一个变体,好的性质是,如果你有这些零均值单位方差输入,那么你的激活将保持在相同的规模。你不必关心内部协变量的变化。关于内部协变量移位,我们可以做的另一件事是巴赫归一化。这是我们将在几个视频中讨论的内容。

更多激活功能。 CC 下的图片来自深度学*讲座的 4.0 。

好的,还有哪些激活功能?有学*激活功能的 maxout。可以使用径向基函数。有一种 softplus,它是 1 的对数加上 e 的 x 次方,被发现不如 ReLU 有效。

我们完成新的激活功能了吗?用 imgflip.com创造的迷因

这真的越来越荒谬了,不是吗?那么,我们现在应该用什么呢?人们甚至走得更远,试图找到最佳的激活函数。为了找到它们,他们使用了强化学*搜索。

寻找最佳激活确实是计算密集型的。来自深度学*讲座的 4.0CC 下的图片。

我们将在后面的课程中讨论强化学*。我们在这里只讨论结果。这种强化学*类型的设置的一个问题是它在计算上非常昂贵。在强化训练程序的每一步,你都必须从头开始训练整个网络。所以,你需要一台超级计算机来做这样的事情,搜索激活函数就是参考文献[6]。谷歌已经在 2017 年发布了它,他们实际上做到了这一点。因此,策略是定义搜索空间,然后使用带有强化学*的递归神经网络执行搜索,最后,他们希望使用最佳结果。

参考文献[6]中使用的搜索空间。 CC 下的图片来自深度学*讲座的 4.0 。

他们使用的搜索空间是,他们把 x 放入一些一元函数中。然后这些一元函数使用一个二进制核心单元组合起来。然后,这可以再次与 x 的另一个实例一元合并,然后使用二元函数产生最终输出。所以,这基本上是他们所经历的搜索空间。当然,他们采用这种模型,因为你可以用这种表达式解释很多典型的激活函数,比如 sigmoid,等等。

谷歌发现的“新”激活功能。来自深度学*讲座CC BY 4.0 下的图片。

我们看到这些是他们认为有用的激活功能。所以,我们不能自己做手术,但是我们当然可以看看他们的结果。这里有一些例子,有趣的是,你可以看到他们得到的一些结果,甚至不再是凸函数。他得出的一个普遍结论是,复杂的激活功能通常表现不佳。他们发现了 x 乘以σ(β x)的东西,他们称之为 swish 函数。因此,这似乎表现得很好,实际上他们使用搜索确定的这个函数之前已经被提议为 sigmoid 加权线性单元[7]。

在搜索激活时是否发现任何显著的差异? CC 下的图片来自深度学*讲座的 4.0 。

所以让我们来详细看看结果。现在声明:永远不要在你的结果中显示表格。努力寻找更好的代表!然而,我们没有找到更好的代表。这里我可以展示的是,这些是他们获得的最高精度。这是在 ImageNet 上训练的 inception Resnet v2 架构中完成的。在倒数第三行,您可以看到 ReLU 的结果,然后下面两行显示 swish-1 和 swish 的结果。现在,我们想问的问题是:“这些变化实际上意义重大吗?”所以,显著性意味着你要计算观察结果是随机结果的概率,你要确保你报告的结果不是随机的。在整个处理链中,我们经常会遇到随机初始化,我们有很多步骤可能会引入采样误差,等等。所以你真的要确保结果不是随机的。因此,我们有显著性检验。如果你仔细观察,你真的会问自己:“这里报道的变化实际上有意义吗?”。

我们对激活函数的观察总结。 CC 下的图片来自深度学*讲座的 4.0 。

因此,我们的建议是去 ReLU。它们工作得非常好,如果您有一些问题,您可以选择使用批处理规范化,我们将在下一个视频中讨论。另一个有趣的事情是缩放的指数线性单元,因为它具有这种自适应属性。所以,这真的很吸引人,但是先试试 ReLU 吧。这真的是你想走的典型道路。对最佳激活函数的搜索是一个困难且广泛的优化问题,它并没有给我们带来更好的激活函数。所以我们这里已经有的足够解决你的大部分问题了。关于好的激活函数,我们所知道的是我们从这些观察中所知道的:它们具有几乎线性的区域以防止梯度消失,它们具有饱和区域以提供非线性,并且它们应该是单调的,因为这对我们的优化非常有用。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。来自深度学*讲座CC BY 4.0 下的图片。

这已经把我们带到了下节课的预*。在下一堂课中,我们真的想研究卷积神经网络,看看我们如何减少连接数量和参数数量,以构建真正深度的网络。所以,我希望你喜欢这个讲座,我期待着在下一个讲座中见到你!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1 I. J. Goodfellow、d . ward-Farley、M. Mirza 等人,“最大网络”。载于:ArXiv 电子版(2013 年 2 月)。arXiv:1302.4389[统计 ML】。
[2],,,,任等,“深入挖掘整流器:在 ImageNet 分类上超越人类水平的表现”。载于:CoRR abs/1502.01852 (2015)。arXiv: 1502.01852。
3君特·克兰鲍尔(Günter Klambauer),托马斯·安特辛纳(Thomas Unterthiner),安德烈亚斯·迈尔(Andreas Mayr),等,“自归一化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。
【四】、和水城颜。“网络中的网络”。载于:CoRR abs/1312.4400 (2013 年)。arXiv: 1312.4400。
[5]安德鲁·马斯、奥尼·汉南和安德鲁·吴。“整流器非线性改善神经网络声学模型”。在:过程中。ICML。第 30 卷。1.2013.
[6] Prajit Ramachandran,Barret Zoph,和 Quoc V. Le。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
【7】Stefan elf wing,内池英治,多亚贤治。“强化学*中神经网络函数逼*的 Sigmoid 加权线性单元”。载于:arXiv 预印本 arXiv:1702.03118 (2017)。
[8]克里斯蒂安·塞格迪、、·贾等,“用回旋深化”。载于:CoRR abs/1409.4842 (2014 年)。arXiv: 1409.4842。

激活、卷积和池化—第 3 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-activations-convolutions-and-pooling-part-3-d7faeac9e79d?source=collection_archive---------47-----------------------

FAU 讲座笔记深度学*

卷积层

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎回到深度学*!今天,我们想继续讨论卷积神经网络。在这个讲座中,我们真正想看到的是构建深层网络的基石。所以我们今天要学*的是卷积神经网络,这是深度网络最重要的组成部分之一。

到目前为止,我们所有的层是完全连接的。 CC 下的图片来自深度学*讲座的 4.0 。

到目前为止,我们已经有了这些完全连接的层,其中每个输入都连接到每个节点。这是非常强大的,因为它可以表示输入之间的任何线性关系。本质上在每一层之间,我们有一个矩阵乘法。这实质上意味着从一层到另一层,我们可以有一个完整的表现变化。这也意味着我们有很多联系。

图像具有高维数,这对神经网络是一个挑战。 CC 下的图片来自深度学*讲座的 4.0 。

所以让我们想想图像,视频,声音,机器学*。然后,这是一个缺点,因为他们通常有巨大的输入大小。您需要考虑如何处理这些大的输入量。让我们说,我们假设我们有一个 512 乘以 512 像素的图像,这意味着一个具有八个神经元的隐藏层已经具有 512 个^ 2 + 1,用于偏差乘以 8 的可训练权重。仅一个隐藏层就有超过 200 万个可训练权重。当然,这不是办法,规模确实是个问题。还有更多。

机器学*的一个典型案例:给猫和狗分类。来自深度学*讲座CC BY 4.0 下的图片。

假设我们想在猫和狗之间进行分类。如果你看这两张图片,你会发现这些图片的大部分都是空白区域。因此,它们不是很相关,因为像素通常是非常糟糕的特征。它们高度相关,依赖于尺度,并有强度变化。因此,它们是一个巨大的问题,从机器学*的角度来看,像素是一种糟糕的表示。你想创造一些更抽象的东西,更好地总结信息。

像素不是我们作为特征的首选。 CC 下的图片来自深度学*讲座的 4.0 。

所以,问题是:“我们能找到一个更好的代表吗?”在图像中,我们当然有一定程度的局部性。因此,我们可以尝试在不同的位置找到相同的宏功能,然后重用它们。理想情况下,我们希望构建类似于特征层次的东西,其中我们有边和角,然后形成眼睛。然后,我们有眼睛、鼻子和耳朵组成一张脸,然后脸、身体和腿将最终形成一只动物。所以,构图很重要,如果你能学会更好的表达,那么你也能更好地分类。

好的特征能够描述一个组合层次。 CC 下的图片来自深度学*讲座的 4.0 。

所以这真的很关键,我们在卷积神经网络中经常看到的是,在早期的层上可以找到非常简单的描述符。然后,在中间层,你会发现更多的抽象表示。在这里,我们发现眼睛、鼻子等等。在更高的层次,你会发现真正的受体,比如这里的脸。因此,我们希望具有本地敏感性,但我们希望将它们扩展到整个网络,以便对这些抽象层进行建模。我们可以通过在神经网络中使用卷积来做到这一点。

为了对特征层次进行建模,我们以交替的方式组合卷积和下采样/池。来自深度学*讲座CC BY 4.0 下的图片。

这是这些架构的总体思路。他们不是将一切与一切完全联系起来,而是为每个神经元使用一个所谓的感受野,就像一个过滤器内核。然后,他们在整个图像上计算相同的权重——本质上是卷积——并产生不同的所谓特征图。接下来,要素地图将转到池化图层。然后,汇集试图引入抽象,并缩小图像。接下来,我们可以再次进行卷积和合并,然后进入下一阶段。你继续下去,直到你有一些抽象表示,然后抽象表示被送到一个完全连接的层。最终,这个完全连接的层映射到最终的类,即“汽车”、“卡车”、“货车”等等。这就是分类结果。因此,我们需要卷积层、激活函数和池来获得抽象并降低维度。在最后一层,我们找到完全连接的分类。

卷积利用图像的局部结构。 CC 下的图片来自深度学*讲座的 4.0 。

让我们从卷积层开始。因此,这里的想法是,我们希望通过仅连接邻域中的像素来利用空间结构。然后,这可以在全连接层中表示,除非我们想要在全连接层中表示,否则我们可以将矩阵中的每个条目设置为零,除非它们通过本地连接来连接。这意味着我们可以忽略空间距离上的很多联系。另一个技巧是你使用大小为 3 x 3,5 x 5 和 7 x 7 的滤镜,你希望它们在整个图层上都是一样的。因此,小邻域内的权重是相同的,即使你移动它们。他们被称为捆绑或共享的重量。如果你这样做,你实际上是在模拟一个卷积。如果你有相同的权重,那么这和你在任何图像处理课上学到的过滤器模板的概念是完全一样的,所以,我们本质上在这里构建了具有可训练过滤器模板的网络。

动画显示了过滤遮罩如何在输入(底部)上移动以产生最终的要素地图(顶部)。来自深度学*讲座CC BY 4.0 下的图片。

这里,我们看到了这个过程的放大图。因此,如果你上过信号处理课,卷积本质上可以表示为对两个函数的积分,其中一个函数对另一个函数进行移位,然后对最终结果进行积分。

信号处理中的卷积。 CC 下的图片来自深度学*讲座的 4.0 。

互相关是一个相关概念,您会看到互相关和卷积之间的唯一区别是τ的符号。在卷积中,你向负方向移动,在互相关中,你向正方向移动。我们经常看到的是,人们谈论卷积,但他们实际上实现了互相关。所以他们基本上翻转了面具的方向。所以,如果你正在创造一些可以训练的东西,这实际上并不重要,因为你无论如何都会学*这个函数的符号。所以,两种实现都很好。互相关实际上经常在实际的深度学*软件中实现。通常,您无论如何都会随机初始化权重。因此,差异没有影响。

填充解决了边界处缺少观察值的问题。来自深度学*讲座CC BY 4.0 下的图像。

我们需要讨论的另一件事是不同的输入大小,以及卷积实际上是如何被用来处理的。因此,这个感受野意味着输出实际上更小,因为我们只能接*最接*的边界。所以,如果你想计算你的感受野边界上的卷积核,你实际上可以到达视野之外。处理这种情况的一种方法是减小要素图和下一个相应图层的大小。您也可以使用填充。许多人所做的只是零填充。因此,所有未观察到的值实际上都设置为零,然后您可以保持相同的大小,只需卷积整个图像。还有其他策略,如镜像等,但零填充可能是最常见的一种。

使用多通道卷积的前向通过。来自深度学*讲座CC BY 4.0 下的图像。

这样,你得到了前进的路径。你实际上不必用小的卷积核来实现它。您也可以使用傅立叶变换来实际执行卷积。所以,你有一个二维输入图像。假设这是一个多通道图像,例如 S 是颜色的数量。然后,应用三维滤镜。这里可以看到,在空间域中有卷积核,但在 S 方向上,它与通道完全相连。如果你这样做了,你可以应用这个内核,然后你得到一个输出遮罩(蓝色显示),内核显示在这里。然后,我们在这里返回这个输出字段。现在,如果你有另一个内核,那么你可以用同样的填充产生第二个遮罩,如绿色所示。这样,您就可以开始构建一个又一个的要素地图。

卷积只是矩阵乘法的一种。 CC 下的图片来自深度学*讲座的 4.0 。

让我们谈一谈卷积实现和反向传递。卷积表示为矩阵乘法 WW 是一个托普利兹矩阵。因此,这个 Toeplitz 矩阵是一个循环矩阵,因为它是通过权重共享构造的。这意味着,如果您实际上正在构建这个矩阵,那么在被训练的每一行中,您具有本质上相同数量的权重,但是它们被移动了一个,这仅仅是因为它们在每一行中使用相同的权重来计算不同的本地字段。这给了我们一个循环矩阵,这意味着我们停留在矩阵乘法的领域。因此,我们的卷积也可以实现为矩阵乘法,因此我们简单地继承了与全连接层相同的公式。因此,如果我们想要反向传播误差,只需用 W 乘以反向传播的输入误差。如果您想要计算权重的更新,它实际上是误差项乘以我们从正向转置的输入中获得的值。因此,这与我们之前看到的完全连接图层的更新公式完全相同。这很好,没有那么多需要记住的。当然,你必须确保你能正确地分担重量,我们会在练*中展示给你看。对我们来说,现在,我们可以把它当作矩阵乘法,你在练*中看到的一个有趣的事情是,反向传递也可以表示为卷积。

卷积使我们能够显著减少权重的数量,并处理任意大小的图像。 CC 下的图片来自深度学*讲座的 4.0 。

现在,我们从卷积层中获得了什么?如果现在堆叠多个滤波器,我们就可以得到一个可训练的滤波器组。比方说,我们有八个过滤器,产生八个节点和一个 5x5 的邻域。然后,我们突然有了 5 乘 8 = 200 的权重。200 磅比我们之前见过的 200 万磅要小得多。此外,卷积可以独立于图像大小应用。所以,我们能做的就是用这些滤镜来转换任何类型的图像。这意味着当我们有不同的输入量时,我们产生的激活图也会改变。我们会在下一节课中看到更多。这里非常好的一点是,我们有更多的数据来训练单个重量。

使用步进和扩张卷积,各种有趣的处理步骤都是可能的。使用 gifify 生成的图像。点击查看完整视频

也有像交错回旋这样的东西。这是当你试图将池化机制和降维机制结合到卷积中的时候。就像每个点都跳过一步。因此,对于步距 s,我们描述一个偏移,然后我们本质上产生一个激活图,该激活图具有依赖于该步距的较低维度。

使用 s = 2 跨越卷积。来自深度学*讲座的 4.0CC 下的图片。

因此,我们将输出大小减少了 1/s,因为跳过了这么多步骤,从数学上来说,这就是同时进行卷积和二次采样。我们这里有一个小动画,向你展示这是如何实现的。

扩张的卷积通过在输入域中跳跃来增加卷积的感受野。 CC 下的图片来自深度学*讲座的 4.0 。

也有像扩张我们萎缩的脑回这样的事情。这里的想法是,我们不是在增加步幅,而是在增加输入空间的间距。现在,感受野不再连接,但我们看到的是分布在一个邻域内的单个像素。这就给了我们一个参数更少的更宽的感受域。

1x1 卷积支持按像素完全连接的层。 CC 下的图片来自深度学*讲座的 4.0 。

另一个非常有趣的概念是 1x1 卷积。到目前为止,我们有这些邻域的 H 滤波器,在深度方向上,我们有 s,记住,它们在深度方向上是完全连接的。这也很有趣,因为现在如果你有一个 1x1 卷积,那么这本质上是一个完全连接的层。所以你只需要在一维上有一个完全连接的层,然后你可以输入任意的数据。它所做的是在通道的方向上计算数量减少的特征图,因为在那里我们有完整的连接。本质上,我们现在可以进行通道压缩。使用 1x1 卷积,我们可以将输入展平到一维,并将所有内容映射到通道方向。因此,1x1 卷积是完全连接的层。因此,如果我们以适当的方式安排输出,我们基本上也可以用它们来表达完全连接的层的整个概念。

4中介绍了 1x1 卷积。来自深度学*讲座CC BY 4.0 下的图片。

这是在网络论文4中首次描述的,我们在讨论不同的架构时也会谈到。这些 1x1 卷积减小了网络的大小,特别是压缩了信道,并且它本质上学*了维数减少。因此,它们帮助您减少特征空间中的冗余。等效的,但更灵活的当然是 NxN 卷积。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

所以下一次在深度学*中,我们将讨论池机制以及如何减少特征图的大小,而不是使用卷积步长或 atrous 卷积。你也可以在我们将在下节课讨论的池化步骤中对此进行显式建模。非常感谢大家的聆听,下节课再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1 I. J. Goodfellow、d . ward-Farley、M. Mirza 等人,“最大网络”。载于:ArXiv 电子版(2013 年 2 月)。arXiv:1302.4389[统计 ML】。
[2],,,,任等,“深入挖掘整流器:在 ImageNet 分类上超越人类水平的表现”。载于:CoRR abs/1502.01852 (2015)。arXiv: 1502.01852。
3君特·克兰鲍尔(Günter Klambauer),托马斯·安特辛纳(Thomas Unterthiner),安德烈亚斯·迈尔(Andreas Mayr),等,“自归一化神经网络”。在:神经信息处理系统的进展。abs/1706.02515 卷。2017.arXiv: 1706.02515。
【四】、和水城颜。“网络中的网络”。载于:CoRR abs/1312.4400 (2013 年)。arXiv: 1312.4400。
[5]安德鲁·马斯、奥尼·汉南和安德鲁·吴。“整流器非线性改善神经网络声学模型”。在:过程中。ICML。第 30 卷。1.2013.
[6] Prajit Ramachandran,Barret Zoph,和 Quoc V. Le。“搜索激活功能”。载于:CoRR abs/1710.05941 (2017 年)。arXiv: 1710.05941。
【7】Stefan elf wing,内池英治,多亚贤治。“强化学*中神经网络函数逼*的 Sigmoid 加权线性单元”。载于:arXiv 预印本 arXiv:1702.03118 (2017)。
[8]克里斯蒂安·塞格迪、、·贾等,“用回旋深化”。载于:CoRR abs/1409.4842 (2014 年)。arXiv: 1409.4842。

前馈网络—第 1 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-feedforward-networks-part-1-e74db01e54a8?source=collection_archive---------48-----------------------

FAU 讲座笔记深度学*

我们为什么需要深度学*?

FAU 大学的深度学*。来自深度学*讲座CC BY 4.0 下的图片。

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

这堂课的大纲。 CC 下的图片来自深度学*讲座的 4.0 。

欢迎大家参加我们的深度学*讲座!今天,我们要深入这个话题。我们想介绍一些对该领域至关重要的重要概念和理论。今天的主题是前馈网络,前馈网络本质上是我们今天使用的神经网络的主要配置。所以在接下来的几个视频中,我们想谈谈第一批模型和它们背后的一些想法。我们也介绍一些理论。一个重要的模块是关于通用函数逼*,我们将从本质上说明神经网络能够逼*任何类型的函数。随后将引入 softmax 功能和一些激活。最后,我们想谈一谈如何优化这些参数,特别是反向传播算法。

感知器描述了一个线性决策边界。 CC 下的图片来自深度学*讲座的 4.0 。

让我们从模型开始,你已经听到的是感知器。我们已经讨论过这个,它本质上是一个函数,将任何高维输入映射到权重向量和输入的内积。然后,我们只对计算出的带符号距离感兴趣。你可以从本质上理解这一点,就像你在右边看到的那样。决策边界以红色显示,您用内积计算的实际上是新样本到决策边界的带符号距离。如果我们只考虑标志,我们就能决定我们是站在一边还是另一边。

经典的模式识别流水线。来自深度学*讲座CC BY 4.0 下的图片。

现在,如果你看看经典的模式识别和机器学*,我们仍然会遵循所谓的模式识别管道。我们对一些测量值进行了转换和预处理,以提高质量,例如降低噪声。在预处理中,我们基本上停留在与输入相同的域中。因此,如果您有一个图像作为输入,预处理的输出也将是一个图像,但对于分类任务可能具有更好的属性。然后,我们要做特征提取。你还记得苹果和梨的例子。从这些特征中,我们提取特征,然后产生一些高维向量空间。然后,我们可以继续进行分类。

感知器不能解决非线性可分问题,如逻辑异或任务。 CC 下的图片来自深度学*讲座的 4.0 。

现在,我们在感知器中看到的是,我们能够模拟线性决策边界。这立即导致了感知机不能解决逻辑异或(即所谓的异或)的观察。你可以在左边看到上面 XOR 问题的可视化。想象一下,你有一些类的分布,左上角和右下角是蓝色的,另一个类是左下角和右上角的。这是受逻辑异或函数的启发。你将不能用一个单一的线性决策边界来分离这两个点云。所以,你要么需要曲线,要么使用多条线。用一个单一的感知器,你将无法解决这个问题。因为人们一直在争论:“看,我们可以用感知器来模拟逻辑功能。如果我们在感知器的基础上构建感知器,我们基本上可以构建所有的逻辑!”

2004 年,人工智能冬季项目的资金被大幅削减.图片来自 Giphy

现在,如果你不能构建 XOR,那么你很可能无法描述整个逻辑,因此,我们永远不会实现强大的人工智能。这是一段时间,人工智能研究的所有资金都被大幅削减,人们将不会获得任何新的拨款。他们不会得到资金来支持这项研究。因此,这一时期被称为“艾冬天”。

从感知机到多层感知机。来自深度学*讲座的 4.0CC 下的图片。

随着多层感知器的引入,事情发生了变化。这是感知器的扩展。你不只是做一个单一的神经元,而是使用多个这样的神经元,并把它们排列成层。这里你可以看到一个非常简单的草稿。所以,它非常类似于感知器。你基本上有一些输入和权重。现在,你可以看到,它不仅仅是一个简单的总和,我们还有几个非线性的总和。然后,它们再次分配权重并再次汇总,以进入另一个非线性。

深层网络将许多层排列在彼此之上。 CC 下的图片来自深度学*讲座的 4.0 。

这非常有趣,因为我们可以使用多个神经元。我们现在还可以模拟非线性决策边界。你可以继续,然后把这个分层排列。所以你通常做的是,你有一些输入层。这是我们的向量 x。然后,你有几个感知器,你安排在隐藏层。它们被称为隐藏的,因为它们不会立即观察到输入。他们分配权重,然后计算一些东西,只有在最后,在输出端,你又有一个层,你可以观察实际发生了什么。所有这些隐藏层之间的重量,都是无法直接观察到的。在这里,只有当你输入一些信息,计算激活时,你才能观察到它们,然后在最后,你可以获得输出。所以,在这里你可以观察到你的系统中发生了什么。

泛逼*允许我们学*紧集上的任何连续函数 f( x )。来自深度学*讲座的 4.0CC 下的图片。

现在,我们将研究所谓的通用函数逼*器。这实际上只是一个只有一个隐藏层的网络。通用函数逼*是一个基本的理论,因为它告诉我们,用一个单一的隐藏层,我们可以逼*任何连续函数。那么,让我们深入研究一下这个定理。它从一个正式的定义开始。我们有一些𝜑(x)和𝜑(x)是非常数的,有界的,单调递增的函数。存在一些大于零的𝜀,并且对于定义在某个高维空间ℝᵐ的紧子集上的任何连续函数 f( x ),存在整数和实常数𝜈和 b,以及实向量 w ,在这里可以找到*似。在这里,你现在可以看到*似值是如何计算的。你有一个输入加上一些偏差的权重的内积。这进入一些激活函数𝜑(x).这是一个非常数、有界、单调递增的函数。然后你有另一个使用这些𝜈的线性组合,然后产生输出资本 F( x )。所以 F( x )是我们的*似值,*似值是由线性组合计算出的非线性的线性组合。如果你这样定义,你可以证明,如果你从真函数 F( x )中 f( x ),两者之间的绝对差由一个常数𝜀.限定𝜀大于零。

我们真的需要深度学*吗?图片来自knowyourmeme.com

这已经是非常有用的*似值了。有一个上限𝜀,但现在它没有告诉我们𝜀实际上有多大。所以,𝜀可能真的很大。通用逼*定理也告诉我们,如果我们增加 n,那么𝜀下降。如果你用 n 趋*于无穷大,𝜀会趋*于零。所以,我们在这个隐藏层中采用的神经元越多,我们的逼*就越好。这意味着,我们可以用一个隐藏层来逼*任何函数。所以你可能会说,如果你可以用一个层来*似所有的东西,为什么人们要做深度学*呢?

分类树可以细分ℝᵐ.的任何分区来自深度学*讲座的 4.0CC 下的图片。

如果一层就够了,深度学*就没有任何意义。我刚刚向你证明了这一点。所以可能不需要深度学*?让我们看一些例子:我在这里取了一个分类树,分类树是一种细分空间的方法。这里我举一个二维例子,我们有一些输入空间 x₁和 x₂.这很有用,因为我们可以在幻灯片上非常有效地将其可视化。我们的决策树做以下事情:它决定 x₁是否大于 0.5。请注意,我在右边展示的是决策边界。在下一个节点,如果你走到左边,你看着 x₂,决定它是大于还是小于 0.25。在另一边,你简单地再看一下 x₁,决定它是大于还是小于 0.75。现在,如果你这样做了,你可以在叶节点中分配类。在这些叶子中,你现在可以,例如,赋值 0 或 1,这给出了这个地方的一个细分,它具有镜像 l 的形状。

尝试将分类树转换为单个隐藏层网络。 CC 下的图片来自深度学*讲座的 4.0 。

这是一个函数,这个函数现在可以用一个通用函数*似器来*似。所以让我们试着去做。我们可以把它变成一个网络。让我们使用下面的想法:我们的网络有 2 个输入神经元,因为它是一个二维空间。有了我们的决策边界,我们也可以形成这些决策 x₁大于或小于 0.5。所以,我们可以立即采用这个。我们实际上也可以采用所有其他内部节点。因为我们在这个例子中使用了一个 sigmoid,所以我们也使用了内部节点的逆节点,并将它们作为额外的神经元放入。当然,在这里我不需要学*任何东西,因为对于第一个隐藏层的连接,我可以从树的定义中得到它们。它们已经预先定义好了,所以这里不需要学*。在输出端,我必须学*一些权重,这可以通过使用最小二乘*似来完成,然后我可以直接计算这些权重。

在每个节点中创建的输入空间的空间细分的可视化。我们无法使用这种单层网络找到精确的解决方案。来自深度学*讲座CC BY 4.0 下的图片。

如果我真的这样做了,我们也可以找到一个很好的可视化。你可以看到,通过我们的决策边界,我们实际上是在隐藏层中构建一个基础。你可以看到,如果我用 0 和 1 作为黑白,对于每个隐藏节点,我都在构造一个基向量。然后,它们基本上被线性加权以用于输出。你可以这样做,把每个像素乘以每个像素,然后简单地求和。这就是隐藏层的作用。然后,我主要对组合这些空间向量感兴趣,这样它将产生期望的 y,现在,如果我在最小二乘意义上这样做,我得到右边的*似值。所以还算不错。我把这个放大了一点。这就是我们想要的。这是镜像的 L,这是我刚刚提出的*似值。现在,你可以看到它有点像 l 形,但这里的值在[0,1]之间,我的六神经元*似的𝜀可能在 0.7 的范围内。所以它确实有点作用,但是*似值不是很好。在这种特殊的配置中,你必须大大增加神经元的数量,以降低误差,因为这是一个非常困难的问题。几乎无法*似。

使用两层,任何分类树都可以映射到神经网络,而不会丢失信息。 CC 下的图片来自深度学*讲座的 4.0 。

那么,我们还能做什么?好吧,如果我们想要这样,我们可以,例如,增加第二个非线性。然后,我们会得到我们想要的解决方案。所以你可以看到,也许一层在表现方面不是很有效率。有一种算法可以将任何决策树映射到神经网络上。算法如下:你取所有的内部节点,这里是 0.5,0.25 和 0.75 之间的决定。这些是内部节点,然后你把它们适当地连接起来。你把它们连接起来,这样你就能准确地形成子区域。这里你可以看到这是我们的 L 形,为了构建左上角的区域,我们需要访问第一个决策。它将空间分为左半空间和右半空间。接下来,我们可以访问第二个决策。这样,我们可以使用这两个决定,以便在左上角形成这个小补丁。对于从决策边界出现的所有四个补丁,我们基本上得到一个节点。这仅仅意味着对于每个叶节点,我们在第二层得到一个节点。因此,第一层中的每个内部节点一个节点,第二层中的每个叶节点一个节点。然后,在输出中组合它们。在这里,你甚至不需要计算任何东西,因为我们已经知道为了达到正确的决策界限,这些必须如何合并。通过这种方式,我们设法将你的决策树转换成神经网络,它会按照我们希望的那样进行正确的逼*。

我们反复出现的座右铭:我们需要更深入!图片来自knowyourmeme.com

我们从这个例子中学到了什么?我们可以用一个只有一个隐藏层的通用函数逼*器来逼*任何函数。但是如果我们深入研究,我们可能会发现一个更有效的问题分解。所以这里的分解首先是内部节点,然后是叶节点。这使我们能够推导出一个只有七个节点的算法,并且可以精确地*似这个问题。所以你可以说,通过建立更深的网络,你增加了额外的步骤。在每一步中,你都试图简化功能和表达的力量,这样你最终能更好地处理决策。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。来自深度学*讲座CC BY 4.0 下的图片。

现在,让我们回到我们的通用函数逼*定理。所以,我们已经看到了它的存在。它告诉我们,我们可以用一个隐藏层来逼*一切。这已经是一个很酷的观察结果,但是它没有告诉我们如何选择 n,也没有告诉我们如何训练。所以通用逼*定理有很多问题。这就是我们为什么要进行深度学*的本质原因。然后,我们可以建立系统,通过不同的步骤开始解开表象。如果我们这样做,我们可以建立更高效、更强大的系统,并对它们进行端到端的培训。这是我们走向深度学*的主要原因。我希望任何从事深度学*的人都知道通用*似,以及为什么深度学*实际上有意义。好了,今天就到这里。下一次,我们将讨论激活函数,并在下一组视频中开始介绍反向传播算法。敬请关注!我希望你喜欢这个视频。期待在下一部中见到你!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1 R. O .杜达,P. E .哈特和 D. G .斯托克。模式分类。约翰威利父子公司,2000 年。
[2]克里斯托弗·m·毕晓普。模式识别和机器学*(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
3f·罗森布拉特。"感知器:大脑中信息存储和组织的概率模型."摘自:《心理评论》65.6 (1958),第 386-408 页。
4 WS。麦卡洛克和 w .皮茨。"对神经活动中固有思想的逻辑演算."发表于:数学生物物理学通报 5 (1943),第 99-115 页。
[5]d . e .鲁梅尔哈特、G. E .辛顿和 R. J .威廉斯。"通过反向传播误差学*表征."载于:自然 323 (1986),第 533-536 页。
[6] Xavier Glorot,Antoine Bordes,Yoshua Bengio。“深度稀疏整流器神经网络”。《第十四届国际人工智能会议论文集》第 15 卷。2011 年,第 315-323 页。
[7]威廉·h·普雷斯、索尔·a·特乌考斯基、威廉·t·维特林等《数值计算方法》第三版:科学计算的艺术。第三版。美国纽约州纽约市:剑桥大学出版社,2007 年。

前馈网络—第 2 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-feedforward-networks-part-2-c91b53a4d211?source=collection_archive---------54-----------------------

FAU 讲座笔记深度学*

如何训练网络?

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎来到深度学*!所以在这个小视频中,我们想继续深入了解神经网络的一些基本功能。特别是,我们希望研究 softmax 函数,并研究一些关于我们如何潜在地训练深度网络的想法。好的,让我们从分类的激活函数开始。

不同类型标签编码策略综述。 CC 下的图片来自深度学*讲座的 4.0 。

到目前为止,我们已经通过标签-1 和+1 描述了基本事实,但是当然,我们也可以有类 0 和 1。如果我们只在两个类之间做决定,这真的只是一个定义的问题。但是如果你想进入更复杂的情况,你希望能够分类多个类。在这种情况下,你可能想要一个输出向量。这里,基本上每个类 K 有一个维度,其中 K 是类的数量。然后,您可以将基本事实表示定义为一个向量,该向量除了一个位置之外都是零,这就是真实类。这也被称为一键编码,因为向量的其他部分都是 0。只有一个有 1。现在,你试着计算一个分类器,它将产生我们各自的向量,有了这个向量,你就可以继续进行分类了。

softmax 函数允许将任意向量缩放到 0 到 1 之间的值。来自深度学*讲座CC BY 4.0 下的图片。

所以本质上就像我在猜测每个类的输出概率。特别地,对于多类问题,这已经被证明是解决这些问题的更有效的方式。问题是你想得到一种接* 0 和 1 的概率输出,但是我们通常有一些可以任意缩放的输入向量 x 。所以,为了产生我们的预测,我们使用了一个技巧。诀窍是我们使用指数函数,因为它会将一切映射到一个正空间。现在,您要确保可以达到的最大值正好是 1。因此,对所有的类都这样做,并计算所有输入元素的所有指数的和。这就给了你这种转换所能达到的最大值。然后,将所有给定的输入除以这个数,这将始终缩放到[0,1]域。产生的向量也将具有这样的性质,如果你将所有元素相加,它将等于 1。这是 Kolmogorov 提出的概率分布的两个公理。所以,这允许我们把网络的输出,总是当作一种概率。如果您在文献和软件示例中查找,有时 softmax 函数也称为归一化指数函数。这是一回事。

一个典型的多类问题以及如何计算它的 softmax 函数。 CC 下的图片来自深度学*讲座的 4.0 。

现在,让我们看一个例子。假设这是我们对神经网络的输入。所以,你在左边看到这个小图像。现在,你为这三类问题引入标签。等等,少了点什么!是四级问题!所以,你为这个四类问题引入标签。然后,您有一些任意输入,显示在 x 下标 k 列中。因此,它们的范围是从-3.44 到 3.01。这不是很好,所以我们用指数函数。现在,所有的东西都被映射成正数,这些数字之间有很大的差别。因此,我们需要重新调整它们的比例,你可以看到,在这张图片中,重金属返回的概率当然是最高的!

交叉熵可以用来度量两个概率分布之间的差异。来自深度学*讲座CC BY 4.0 下的图片。

那么,让我们继续讨论一下损失函数。所以损失函数是一种告诉你一个网络的预测有多好的函数。一个非常典型的就是所谓的交叉熵损失。在两个概率分布之间计算交叉熵。所以,你有你的基本事实分布和你正在估计的。然后,您可以计算交叉熵,以确定它们的连接程度,即它们相互对齐的程度。然后,你也可以用这个作为损失函数。在这里,我们可以使用这样的属性:除了 true 类之外,所有的元素都为零。所以我们只需要确定 y hat 下标 k 的负对数,这里 k 是真类。这大大简化了计算,我们去掉了上面的求和。顺便说一下,这有几个更有趣的解释,我们将在下一个视频中讨论它们。

softmax 损失将 softmax 函数与交叉熵损失相结合。 CC 下的图片来自深度学*讲座的 4.0 。

现在,如果你这样做,我们可以插入 softmax 函数,并构建所谓的 softmax 损失。你可以看到,我们有 softmax 函数,然后我们只对有真类的元素取负对数。这是在网络训练中经常使用的东西。这种 softmax 损失非常常用,对一个热编码的地面真相非常有用。它也代表了一个直方图。它与统计和分布有关。此外,所有的多类问题都可以用这种方法一次性解决。

更改单个权重将影响所有其他后续权重。 CC 下的图片来自深度学*讲座的 4.0 。

我想在这个视频中谈论的另一件事是优化。所以,我们根本没有考虑的一件大事是我们实际上如何训练这些网络。我们已经看到这些无法直接观察到的隐藏层。这给我们带来了一个非常困难的情况,你可能会认为右边的图像与左边的非常相似:如果你改变了这一系列事件中的任何事情,它可能会从本质上摧毁整个系统。所以,你必须非常小心地调整路径上的任何东西,因为你必须考虑到所有其他的处理步骤。这真的很难,你必须小心调整什么。

在最优化问题中训练神经网络。来自深度学*讲座CC BY 4.0 下的图片。

现在,我们将走简单的路,我们将把它公式化为一个优化问题。我们已经讨论过,我们需要某种损失函数。损失函数告诉我们预测与实际训练数据的拟合程度。输入是权重 wx 输入向量和 y 它们是我们的基本事实标签。我们必须考虑所有 M 个训练样本,这允许我们描述某种损失。因此,如果我们这样做,我们就可以计算出损失的期望值,它实际上是所有观测值的总和。然后,这个缩放的总和被用于确定整个训练数据集的拟合度。现在,如果我们想要创建一组最优的权重,我们要做的是选择在整个训练数据集上最小化关于 w 的损失函数。

使用沿着负梯度方向的迭代更新找到更好的权重。 CC 下的图片来自深度学*讲座的 4.0 。

现在我们有了一些数学原理,告诉我们该怎么做,我们知道最小化。让我们尝试一个显而易见的选择:梯度下降。因此,我们选择找到最小化所有训练样本损失的最小值 w 。为了做到这一点,我们计算梯度,我们需要对 w 进行一些初步猜测。有许多不同的方式来初始化 w 。有些人只是使用随机初始化的权重,然后你继续做梯度下降。所以,你一步一步地沿着负梯度方向,直到你到达某个最小值。所以在这里,你可以看到这个初始的 w ,这个步骤可能是随机的。然后在步骤 2 中,迭代直到收敛。因此,计算损失函数相对于 w 的梯度。那么你需要一些学*率η。η实际上告诉你这些单个箭头的步长。然后,你沿着这个方向,直到你到达一个最小值。现在,η通常被称为学*率。有趣的是,这种方法非常简单,你总能找到最小值。它可能只是一个局部函数,但是您可以最小化该函数。很多人做的是运行几次随机初始化。这些随机初始化然后被用来寻找不同的局部最小值。然后,他们简单地为他们的最终系统取最好的局部最小值。

网络是典型的嵌套函数,这使得梯度计算有点困难。来自深度学*讲座的 4.0CC 下的图片。

我们试图优化的这个 L 是什么?嗯, L 是在输出层计算的。因此,我们将输入输入到整个网络的网络流程中,然后,最终,我们计算出与我们期望的输出之间的差异、拟合度或损耗。所以你可以说,如果第一层是 f 第二层是 g ,那么我们感兴趣的是计算某些输入的Lx 和 w 。我们使用 w 下标 f 计算 f ,然后使用权重 w 下标 g ,计算 g ,最后,我们计算 gy 之间的拟合度。这就是我们需要在损失函数中计算的。

你会发现这有点困难,而且对于更深的网络来说会变得更加困难。因此,我们将看到,我们需要能够有效地做到这一点。有一种非常有效的算法可以解决这类问题,它被称为反向传播算法,这将是我们下节课的主题。所以,非常感谢大家的收听,下期视频再见!

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1 R. O .杜达,P. E .哈特和 D. G .斯托克。模式分类。约翰威利父子公司,2000 年。
[2]克里斯托弗·m·毕晓普。模式识别和机器学*(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
3f·罗森布拉特。"感知器:大脑中信息存储和组织的概率模型."摘自:《心理评论》65.6 (1958),第 386-408 页。
【4】WS。麦卡洛克和 w .皮茨。"对神经活动中固有思想的逻辑演算."发表于:数学生物物理学通报 5 (1943),第 99-115 页。[5] D. E .鲁梅尔哈特、G. E .辛顿和 R. J .威廉斯。"通过反向传播误差学*表征."载于:自然 323 (1986),第 533-536 页。
[6]泽维尔·格洛特,安托万·博德斯,约舒阿·本吉奥。“深度稀疏整流器神经网络”。《第十四届国际人工智能会议论文集》第 15 卷。2011 年,第 315-323 页。
[7]威廉·h·普雷斯、索尔·a·特乌考斯基、威廉·t·维特林等《数值计算方法》第三版:科学计算的艺术。第三版。美国纽约州纽约市:剑桥大学出版社,2007 年。

前馈网络—第 3 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-feedforward-networks-part-3-d2a0441b8bca?source=collection_archive---------52-----------------------

FAU 讲座笔记深度学*

反向传播算法

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

对于今天的示例函数,我们将计算数值导数和解析导数。 CC 下的图片来自深度学*讲座的 4.0 。

欢迎大家来深度学*!谢谢收听。今天的主题是反向传播算法。所以,你可能会对我们如何在复杂的神经网络中计算这些导数感兴趣。让我们看一个简单的例子。我们真正的函数是 2 x ₁加 3 x ₂的 2 加 3 次方。现在,我们要计算 f( x )在位置(1 3)ᵀ相对于 x ₁.)的偏导数有两种算法可以非常有效地做到这一点。第一个是有限差分。第二个是解析导数。因此,我们将在这里浏览两个示例。

有限差分使用小的 h 找到形式导数定义的*似值。 CC 下的图片来自深度学*讲座的 4.0 。

对于有限差分,想法是你在某个位置 x 计算函数值。然后,将一个非常小的增量 h 加到 x 上,并在那里对函数求值。你也可以计算 at 函数 f(x) 并取两者之差。然后,你除以 h 的值。所以这其实就是导数的定义:它是 f(x+h)f(x) 之差除以 h 其中我们让 h 趋*于 0。现在,问题是这不是对称的。所以,有时候你想要一个对称的定义。我们不是精确地在 x 处计算这个值,而是回到 h/2 处,再回到 h/2 处。这允许我们精确地计算位置 x 处的导数。然后,还是要分过 h 。这是一个对称的定义。

使用 h = 0.02,我们可以在数值上逼*导数。 CC 下的图片来自深度学*讲座的 4.0 。

对于我们的示例,我们可以这样做。我们来试着评价一下这个。我们取我们原来的定义(2 x ₁+ 3 x ₂) + 3。我们想看看位置(1 3)ᵀ.让我们使用上面的+ h/2 定义。这里,我们将 h 设置为一个小值,比如 2 ⋅ 10⁻。我们把它插上,你可以在这一排看到。所以这将是((2(1+10⁻ +9) + 3),当然,我们也要减去第二项的小值。然后,我们也除以较小的值。因此,我们将得到大约 124.4404 减去 123.5604。这大约是 43.9999。因此,我们可以计算任何函数的这个值,即使我们不知道函数的定义,例如,如果一个函数只有一个我们无法访问的软件模块。在这种情况下,我们可以用有限差分来*似偏导数。

使用有限差分的简短总结。 CC 下的图片来自深度学*讲座的 4.0 。

实际上,我们在适合浮点精度的 1⋅ 10⁻⁵范围内使用 h 。根据您的计算系统的精度,您还可以确定 h 的合适值。你可以在参考文献 7 中找到答案。我们看到这真的很好用。我们可以对任何函数求值,我们不需要知道正式的定义,但是,当然,这在计算上是低效的。假设你想确定一个维数为 100 的函数的所有偏导数的集合的梯度。这意味着你必须对函数求值 101 次来计算整个梯度。因此,对于一般优化来说,这可能不是一个很好的选择,因为它可能会变得低效。但是当然,这是一个非常酷的方法来检查你的实现。想象你实现了分析版本,有时你会犯错误。然后,你可以以此为窍门,检查你的解析导数是否正确实现。这也是您将在这里的练*中详细了解的内容。如果你想调试你的实现,这真的很有用。

计算解析梯度的四个规则。来自深度学*讲座的 4.0CC 下的图片。

好,我们来谈谈解析梯度。现在解析梯度,我们可以用一组解析微分规则来推导。所以第一条规则是常数的导数是 0。那么,我们的算符是一个线性算符,这意味着如果我们有不同分量的和,我们可以重新排列它。接下来,我们还知道单项式的导数。如果你有一些ⁿ,导数将是⋅xⁿ⁻。如果您有嵌套函数,则链规则适用。这本质上是我们反向传播算法需要的关键思想。你会看到,某个嵌套函数对 x 的导数,将是该函数对 g 的导数乘以函数 gx 的导数。

我们应用前面的四个规则来计算函数的解析导数。来自深度学*讲座的 4.0CC 下的图片。

好的,让我们把它们放在右上方。我们将在接下来的几张幻灯片中用到它们。让我们来计算一下,这里你会看到,f( x )对 x ₁的偏导数在(1 3)ᵀ.)然后,我们可以插入定义。所以,这将是(2 x ₁+9)的偏导数。我们已经可以写出 9,因为我们已经可以插入 3,然后乘以 3 得到 9。在下一步中,我们可以计算外函数的偏导数。现在。这是链式法则的应用,我们引入这个新变量 z 。在下一步中,我们可以计算 z2 次方的偏导数,其中我们必须将指数减少 1,然后乘以这个指数。所以,这将是 2(2 x ₁+9)乘以 2 x ₁+9.的偏导数所以,我们可以进一步简化。你可以看到,如果我们对 2 x ₁+9 求导, x ₁抵消了。减去常数 9,只剩下 2。所以最后,我们得到 2(2 x ₁+9)乘以 2。现在如果你代入 x₁= 1,你会看到我们的导数等于 44。在我们之前评估过的数值实现中,您可以看到我们有 43.9999。所以,我们很亲密。当然,解析梯度更精确。

我们对解析梯度的观察总结。 CC 下的图片来自深度学*讲座的 4.0 。

现在的问题是:“我们能自动做到这一点吗?”答案当然是肯定的。我们使用这些规则,链式规则、线性和其他两个规则来分解神经网络的复杂功能。我们不手动这样做,但我们在反向传播算法中完全自动这样做。这将比有限差分计算效率更高。

简单来说就是反向传播。来自深度学*讲座CC BY 4.0 下的图片。

因此,你可以在这里简单地描述反向传播算法:对于每个神经元,你需要有输入 x ₁, x ₂,当然还有输出 y hat。然后,你可以计算——绿色的——向前传球。你在某个地方计算损失函数,然后你得到关于 y 的导数,它来自于后向通道。然后,对于网络图中的每个元素,你需要知道相对于输入的导数,这里是 x₁和 x₂.当然,我们在图中缺少的是可训练的重量。对于可训练的权重,我们还需要计算关于它们的导数,以便计算参数更新。因此,对于每个模块或节点,你需要知道相对于输入的导数和相对于权重的导数。如果你对每个模块都有,那么你就可以组成一个图,有了这个图,你就可以计算非常复杂函数的任意导数。

我们例子中的向前传球。来自深度学*讲座的 4.0CC 下的图片。

让我们回到我们的例子,并应用反向传播。那么,我们该怎么办?我们先计算向前传球。为了能够计算正向传递,我们插入中间定义。所以我们现在把它分解成 2 倍于₁的 a 和 3 倍于₂.的 b 然后,我们可以计算这些:我们得到值 2 和 9 为 ab 。这使得我们可以计算出两者之和 c 。这相当于 11。然后,我们可以计算出 e ,它不是别的,而是 c 的 2 次方。这给了我们 121,现在我们最终计算出 g ,也就是 e 加 3。所以,我们得到了 124。

对于我们的例子,反向传播的反向传递。 CC 下的图片来自深度学*讲座的 4.0 。

好,现在我们需要反向传播。所以我们需要计算偏导数。这里, g 相对于 e 的偏导数将为 1。然后,我们计算 ec 的偏导数,你会看到这是 2 c 。当 c 为 11 时,计算结果为 22。然后,我们需要 c 相对于 a 的偏导数,也是 1。现在,我们需要 a 关于 x₁.的偏导数如果你看这个方块,你可以看到这个偏导数是 2。所以我们必须把所有的偏导数从右到左相乘,才能得到结果:1 乘以 22 乘以 1 乘以 2,这将是 44。这就是应用于我们例子的反向传播算法。

长链的增殖受到正反馈的影响。正反馈反馈会导致灾难CC 下的图片来自深度学*讲座的 4.0 。

现在,我们确实有一个稳定性问题。在反向传播算法的范围内,我们相当频繁地与可能的高值和低值相乘。这就给我们带来了正反馈的问题,这会导致灾难。这个小视频展示了正反馈的一个例子,以及它是如何导致灾难的。

权重的迭代更新构成了反馈回路。来自深度学*讲座CC BY 4.0 下的图片。

现在,我们能做些什么呢?这本质上是一个反馈循环。我们有这个控制器和输出,在这里我们计算梯度。你可以看到η的值。所以,如果η太高,就会产生正反馈。这将导致我们的更新价值非常高,然后我们的损失可能会增长或真正爆炸。因此,如果它太大,我们甚至可能会增加损失函数,尽管我们试图将其最小化。还可能发生的是,如果你把η选得太小,那么你会得到蓝色曲线。这就是所谓的消失梯度,我们的步长太小,我们没有很好的收敛。所以没有减少损失。也是一个叫做“消失渐变”的问题。所以,只有选择合适的η,你才会获得很好的学*率。有了一个好的学*率,损耗应该会随着这条绿色曲线的多次迭代而快速下降。然后我们应该进入某种收敛,当我们不再有变化时,我们基本上处于训练数据集的收敛点。然后我们可以停止更新我们的权重。所以,我们看到 EDA 的选择对我们的学*是至关重要的,只有你说得恰当,你才会得到一个良好的培训过程。

反向传播算法综述。来自深度学*讲座的 4.0CC 下的图片。

所以让我们总结一下反向传播:它是围绕链式法则建立的。它使用向前传球。一旦我们结束并评估损失函数——本质上是与我们学*目标的差异——我们就可以反向传播。使用动态编程方法,这些计算非常有效。反向传播不是一种训练算法。这只是一种计算梯度的方法。当我们在下节课中讨论损失和优化时,你会看到实际的培训计划。一些非常重要的结果是:我们有一个偏导数的乘积,这意味着数值误差增加了。这可能会很成问题。也是因为偏导数的乘积,我们会得到消失或爆炸的光栅。因此,当值非常低,接*于零时,开始将它们相乘,就会出现指数衰减,导致梯度消失。如果你有非常高的数字,当然,你也可以很快达到指数增长——爆炸梯度。

符号激活功能。 CC 下的图片来自深度学*讲座的 4.0 。

我们看到梯度对我们的训练至关重要。所以我们来谈谈激活函数和它们的导数。其中一个经典的例子是符号函数。我们已经在感知器里有了。现在,你可以看到它是对称的,并在 1 和-1 之间归一化。但是请记住,我们正在讨论偏导数,以便计算权重更新。所以,这个函数的导数有点问题,因为除了点 0,它在任何地方都是 0,这里的值基本上是无穷大。所以把这个和梯度下降结合起来用并不是很好。

乙状结肠函数。来自深度学*讲座CC BY 4.0 下的图片。

那么人们一直在做什么呢?他们转换到不同的函数,其中一个流行的是 sigmoid 函数。因此,这是一个 s 形函数,它在分母中使用负指数函数来缩放 0 到 1 之间的所有内容。好的一面是,如果你计算它的导数,这基本上就是 f(x)乘以 1 — f(x)。所以,至少导数可以很有效地计算出来。在向前传递时,你总是要处理指数函数,这也是一个问题。同样,如果你在-3 到 3 之间看这个函数,你会得到适合反向传播的梯度。一旦你远离-3 或 3,你会发现这个函数的导数将非常接*于零。所以,我们有饱和,如果你期望有一对 sigmoid 函数,那么它很可能会产生非常低的值。这也会导致渐变消失。

校正的线性单位。 CC 下的图片来自深度学*讲座的 4.0 。

那么人们做了什么来战胜它呢?嗯,他们引入了一个分段线性激活函数,称为“整流线性单元”(ReLU),它是零和 x 的最大值。所以,所有低于零的都被削波为零,其他的都保持不变。这很好,因为我们可以非常有效地计算。这里不涉及指数函数,如果 x 大于零,而其他地方都是零,那么导数就是 1。所以,消失的梯度要小得多,因为基本上整个正半空间都可以用于梯度下降。ReLU 也有一些问题,我们将在讨论激活函数时详细讨论。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

好了,现在你理解了反向传播算法的许多基本概念。但是我们仍然必须讨论更复杂的情况,特别是在特定的层。所以现在,我们在神经节点水平上做了所有的事情。如果你想在神经元水平上做所有的反向传播,这是非常困难的,你会很快失去监督。因此,我们将在下节课中介绍层抽象,看看如何计算整个层的梯度。所以敬请关注,继续收看!我希望你喜欢这个视频,并看到你在下一个。谢谢大家!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1 R. O .杜达,P. E .哈特和 D. G .斯托克。模式分类。约翰威利父子公司,2000 年。
[2]克里斯托弗·m·毕晓普。模式识别和机器学*(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
3f·罗森布拉特。"感知器:大脑中信息存储和组织的概率模型."摘自:《心理评论》65.6 (1958),第 386-408 页。
4 WS。麦卡洛克和 w .皮茨。"对神经活动中固有思想的逻辑演算."发表于:数学生物物理学通报 5 (1943),第 99-115 页。
[5]d . e .鲁梅尔哈特、G. E .辛顿和 R. J .威廉斯。"通过反向传播误差学*表征."载于:自然 323 (1986),第 533-536 页。
[6] Xavier Glorot,Antoine Bordes,Yoshua Bengio。“深度稀疏整流器神经网络”。《第十四届国际人工智能会议论文集》第 15 卷。2011 年,第 315-323 页。
[7]威廉·h·普雷斯、索尔·a·特乌考斯基、威廉·t·维特林等《数值计算方法》第三版:科学计算的艺术。第三版。美国纽约州纽约市:剑桥大学出版社,2007 年。

前馈网络—第 4 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-feedforward-networks-part-4-65593eb14aed?source=collection_archive---------75-----------------------

FAU 讲座笔记深度学*

层抽象

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎大家观看我们下一个关于深度学*的视频!所以,今天我们要再次讨论前馈网络。在第四部分中,主要的焦点将放在层抽象上。当然,我们讨论了这些神经元和单个节点,但对于更大的网络来说,这变得非常复杂。所以我们想在梯度的计算中引入这个分层的概念。这真的很有用,因为我们可以直接谈论整个层的梯度,而不需要去所有不同的节点。

每个神经元在应用非线性之前计算两个向量的内积。 CC 下的图片来自深度学*讲座的 4.0 。

那么,我们该如何表达呢?让我们回忆一下我们的单个神经元在做什么。单个神经元本质上是在计算其权重的内积。顺便说一下,我们跳过了这个偏差符号。所以,我们将这个向量扩展了一个额外的元素。这使我们能够描述偏差和内积,如幻灯片所示。这真的很好,因为这样你就可以看到输出 y hat 只是一个内积。

完全连接的层可以用矩阵乘法来表示。来自深度学*讲座CC BY 4.0 下的图片。

现在考虑我们有 M 个神经元的情况,这意味着我们得到一些 y 帽子指数 m 。都是内积。所以,如果你把这个带入向量符号,你可以看到向量 y hat 就是矩阵 x 与矩阵 W 的乘法运算。你看一个全连通的层不是别的,就是矩阵乘法。因此,我们基本上可以使用这个全连接层来表示任意连接和拓扑。然后,我们还应用逐点非线性,以便我们得到非线性效果。矩阵符号的好处是,我们现在可以用矩阵运算来描述整个层的导数。

具有三个输入的双神经元全连接层。 CC 下的图片来自深度学*讲座的 4.0 。

因此,我们的全连接层将得到以下配置:三个输入元素和每个神经元的权重。假设你有两个神经元,然后我们得到这些权重向量。我们将两者乘以 x 。在正向传递中,我们已经使用矩阵为整个模块确定了这个 y hat。如果你想计算梯度,那么我们需要两个偏导数。这些和我们已经提到的一样,我们需要关于重量的导数。这将是相对于 W 的偏导数和相对于 x 的偏导数,用于反向传播,以将其传递到下一个模块。

简而言之,全连通层的偏导数。 CC 下的图片来自深度学*讲座的 4.0 。

那么我们如何计算呢?嗯,我们有一层是 y 帽子等于Wx。所以在正向传递中有一个矩阵乘法。然后,我们需要对重量求导。现在你可以看到,我们需要做的是,我们需要一个矩阵导数。y 相对于 w 的导数就是ᵀ.因此,如果我们有损失进入我们的模块,我们的权重更新将是这个损失向量乘以 x ᵀ.所以,我们有一些损失向量和ᵀ,这意味着你有一个外积。由于转置,一个是列向量,另一个是行向量。所以,如果你把两者相乘,你会得到一个矩阵。上述相对于 W 的偏导数将总是产生一个矩阵。然后你看最下面一行,你需要 y hat 相对于 x 的偏导数。顺便说一句,你也可以在矩阵食谱中找到。它非常非常有用。你可以在这本书里找到各种矩阵导数。所以如果你这样做,你可以看到上面的方程,相对于 x 的偏角是 W ᵀ.现在,你有了ᵀ,再乘以一些损失向量。这个损失向量乘以一个矩阵,会变成一个向量。这是您将在反向传播过程中传递给下一个更高层的向量。

单层线性网络仅仅是矩阵乘法。 CC 下的图片来自深度学*讲座的 4.0 。

好,让我们来看一些例子。我们先有一个简单的例子,然后是一个多层的例子。因此,这个简单的例子将是我们已经拥有的同一个网络。这是一个没有任何非线性的网络 W x 。现在,我们需要一些损失函数。这里,我们不取交叉熵,而是取 L2 损失,这是一个常见的向量范数。它只需将网络输出减去所需输出,然后计算 L2 范数。这意味着我们对不同的向量值进行元素平方,并将它们相加。最后,我们将不得不取一个平方根,但是我们想省略它。所以,我们用它的 2 次方。当我们现在计算这个 L2 范数的 2 次幂的导数时,当然,我们有一个 2 的因子出现。这将在开始时被这个因子 1/2 抵消。对了,这是回归损失,也有统计关系。我们将在更详细地讨论损失函数时讨论这一点。L2 损失的好处是,你还可以找到它的矩阵衍生物矩阵食谱。我们现在计算 L 相对于 y hat 的偏导数。这将为我们提供 Wxy ,我们可以继续计算权重的更新。所以权重的更新是我们用损失函数的导数计算出来的。损失函数相对于输入的导数是 Wxy 乘以 xᵀ 。这将为我们提供矩阵权重的更新。我们要计算的另一个导数是损失相对于 x 的偏导数。因此,正如我们在上一张幻灯片中看到的那样,这将是 W ᵀ乘以来自损失函数的向量: Wxy,,正如我们在幻灯片的第三行中所确定的。

线性三层网络作为逐层导数计算的例子。 CC 下的图片来自深度学*讲座的 4.0 。

好吧,让我们添加一些层,并改变我们的估计到三个嵌套函数。这里,我们有一些线性矩阵。所以,这是一个学术上的例子:你可以看到,通过将₁的 W 、₂的 W 和₃的 W 相乘,它们会简单地折叠成一个矩阵。尽管如此,我还是觉得这个例子很有用,因为它向您展示了在反向传播过程的计算中实际发生了什么,以及为什么这些特定的步骤真的很有用。所以,我们再次采用 L2 损失函数。这里,我们有三个矩阵。

最后一层的导数只需要链式法则的一次应用。来自深度学*讲座的 4.0CC 下的图片。

接下来,我们要继续计算导数。现在对于衍生产品,我们从第三层开始,最外层。你可以看到,我们现在计算损失函数相对于₃.的偏导数第一,链式法则。然后,我们必须计算损失函数相对于 f₃( x 哈特相对于₃.w的偏导数损失函数的偏导数也是 L2 范数的内部部分。那么这个w₃t18】w₂wx——y也是如此。网络的偏导数将会是(wwx),正如我们在上一张幻灯片中看到的。注意,我用一个点来表示矩阵操作符的亲和力。对于矩阵来说,是从左乘还是从右乘是有区别的。两个乘法方向都不一样。因此,我表示你必须从右边计算这个乘积。现在,让我们这样做,我们结束了对 W₃的最后更新,这是简单地从这两个表达式计算出来的。

更深层次的衍生工具需要多重应用链式法则。 CC 下的图片来自深度学*讲座的 4.0 。

现在,对₂的偏导数有点复杂,因为我们要应用链式法则两次。所以,我们必须再次计算损失函数对 f₃(xhat 的偏导数。然后,我们需要 f₃(xhat 对 W ₂的偏导数,这意味着我们必须再次应用链式法则。所以我们必须展开 f₃(xhat 相对于 f₂(xhat 的偏导数,然后展开 f₂(xhat 相对于₂.w的偏导数这个变化不大。损失项与我们以前使用的相同。现在,如果我们计算 f₃(xhat 相对于 f₂(xhat 的偏导数——还记得 f₂(x)=wwx吗——它将是 W ,我们必须从左侧将其相乘。然后,我们继续计算 f₂(xhat 相对于w₂.的偏导数你继续留在(wx)。所以,最终的矩阵导数是这三项的乘积。我们可以对最后一层重复这个步骤,但是现在我们必须再次应用链式法则。我们已经看到预先计算的两个部分,但我们必须再次应用它。这里我们得到了 f₂(xhat 相对于 f₁(xhat 的偏导数,以及 f₁(xhat 相对于₁w的偏导数,这就产生了我们之前用过的两个项。f₂( x 帽子相对于 f₁( x 帽子的偏导数,即 Wx ,将会是 W 。然后,我们还要计算 f₁( x 相对于 W ₁.的偏导数这将是 xᵀ的比赛。所以,我们最终得到这个偏导数的四项乘积。

偏导数越深,需要相乘的项就越多。 CC 下的图片来自深度学*讲座的 4.0 。

现在,你可以看到,如果我们做反向传播算法,我们会以非常相似的方式处理。首先,我们计算整个网络的转发路径,并评估损失函数。然后,我们可以看看不同的偏导数,根据我想去的地方,我必须计算各自的偏导数。对于最后一层的更新,我必须计算损失函数的偏导数,并将其乘以最后一层相对于权重的偏导数。现在,如果我进入倒数第二层,我必须计算损失函数的偏导数、最后一层相对于输入的偏导数以及倒数第二层相对于权重的偏导数,以获得更新。如果我想去第一层,我必须计算整个层的所有相应的反向传播步骤,直到我在第一层上完成相应的更新。您可以看到,我们可以预先计算许多这些值,并重复使用它们,这使我们能够非常有效地实现反向传播。

偏导数的分层计算总结。来自深度学*讲座CC BY 4.0 下的图片。

让我们总结一下到目前为止我们所看到的。我们已经看到,我们可以将 softmax 激活函数与交叉熵损失结合起来。然后,我们可以很自然地处理多类问题。我们使用梯度下降作为训练网络的默认选择,并且我们可以使用该策略实现局部最小值。当然,我们只能通过有限差分来计算梯度,这对于检查你的实现非常有用。这是你在练*中绝对需要的东西!然后,我们使用反向传播算法非常有效地计算梯度。为了能够更新完全连接的层的权重,我们已经看到它们可以被抽象为一个完整的层。因此,我们也可以计算逐层导数。因此,不需要在节点级别计算所有内容,但您可以真正进入层抽象。你也看到了矩阵演算非常有用。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

深度学*下一次会怎样?我们会看到,现在,我们只有有限的损失函数。因此,我们将看到问题适应回归和分类的损失函数。我们现在讨论的非常简单的优化,只有一个η,可能不是正确的方法。所以,有更好的优化程序。它们可以适应每一个参数的需要。然后,我们还将看到一个论点,为什么神经网络不应该表现得那么好,以及一些最*的见解,为什么它们实际上表现得相当好。

一些备考的综合题。来自深度学*讲座CC BY 4.0 下的图片。

我也有几个综合问题。所以你绝对应该能够为多类分类命名不同的损失函数。如果你想和我一起参加口试,一键编码是每个人都需要知道的。你必须能够描述这一点。然后,当然,我可能不会在考试中问,但对你的日常工作非常有用的事情是,你使用有限差分,并使用它们进行实现检查。你必须能够描述反向传播算法,老实说,我认为这是一种学术方法,但这种描述反向传播算法的多层抽象方法非常有用。如果你想解释考试情况下的反向传播,这也很好。你还能描述出什么?爆炸和消失梯度的问题是:如果你选择的η太高或太低会发生什么?什么是丢失的曲线,它在迭代中是如何变化的?看看这些图表。它们真的很重要,它们还能帮助你了解你的训练过程中出了什么问题。所以你需要意识到这些,现在你也应该清楚为什么符号函数不是激活函数的好选择。这篇文章下面有很多参考资料。所以,我希望你仍然喜欢这些视频。请继续观看,下期视频再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1 R. O .杜达,P. E .哈特和 D. G .斯托克。模式分类。约翰威利父子公司,2000 年。
[2]克里斯托弗·m·毕晓普。模式识别和机器学*(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
3f·罗森布拉特。"感知器:大脑中信息存储和组织的概率模型."摘自:《心理评论》65.6 (1958),第 386-408 页。
【4】WS。麦卡洛克和 w .皮茨。"对神经活动中固有思想的逻辑演算."发表于:数学生物物理学通报 5 (1943),第 99-115 页。[5] D. E .鲁梅尔哈特、G. E .辛顿和 R. J .威廉斯。"通过反向传播误差学*表征."载于:自然 323 (1986),第 533-536 页。
[6]泽维尔·格洛特,安托万·博德斯,约舒阿·本吉奥。“深度稀疏整流器神经网络”。《第十四届国际人工智能会议论文集》第 15 卷。2011 年,第 315-323 页。
[7]威廉·h·普雷斯、索尔·a·特乌考斯基、威廉·t·维特林等《数值计算方法》第三版:科学计算的艺术。第三版。美国纽约州纽约市:剑桥大学出版社,2007 年。

简介—第 1 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-introduction-part-1-5a1729abd580?source=collection_archive---------37-----------------------

FAU 讲座笔记深度学*

激励和高调应用

FAU 大学的深度学*。来自深度学*讲座CC BY 4.0 下的图片。

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是讲座视频&配套幻灯片的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎大家参加这学期的深度学*讲座!如你所见,我不在演讲厅。像你们中的许多人一样,我在我的家庭办公室,为了阻止当前的疫情,我们必须在家工作。

因此,我决定把这些讲座录下来,然后放到网上,这样每个人都可以自由使用。您将看到我们对此格式做了一些更改。首先,我们缩短了讲座的时间。我们不再连续走 90 分钟。相反,我们决定将长度缩减成更小的部分,这样你可以在 15 到 30 分钟内一次看完,然后停下来继续下一节课。这意味着我们必须引入一些变化。当然,像每个学期一样,我们也更新了所有的内容,这样我们就真正呈现了当前研究的最新水平。

深度学*流行语。 CC 下的图片来自深度学*讲座的 4.0 。

这第一堂课将是关于深度学*的介绍,我们将在这堂课中讨论各种各样的主题——首先也是最重要的,当然是深度学*。我们在这里总结了一些你可能已经听过的流行语。我们涵盖了从监督学*到非监督学*的主题。当然,我们谈到了神经网络、特征表示、特征学*、大数据、人工智能、机器表示学*,但也包括分类、分割、回归和生成等不同的任务。

导言的大纲。来自深度学*讲座CC BY 4.0 下的图片。

让我们简短地看一下大纲。所以首先,我们从一个动机开始,为什么我们对深度学*感兴趣。我们看到,在过去的几年里,我们已经取得了巨大的进步,因此,研究一些应用和已经取得的一些突破将是非常有趣的。然后在接下来的视频中,我们想谈谈机器学*和模式识别,以及它们与深度学*的关系。当然,在第一节课中,我们也想从最基础的开始。我们会谈到感知器,我们还会谈到一些组织问题,你们会在第五段视频中看到。

英伟达股票市值。 CC 下的图片来自深度学*讲座的 4.0 。

所以让我们来看看动机,以及现在正在发生的有趣的事情。首先也是最重要的,我想给你看这个关于英伟达股票市值的小图表。您可以在这里看到,在过去几年中,特别是自 2016 年以来,市值一直在增长。这种增长惊人的一个原因是,深度学*发现始于 2012 年,大约在 2016 年真正起飞。所以,你可以看到很多人需要额外的计算硬件。Nvidia 正在制造通用图形处理器,允许在其主板上进行任意计算。与每两年将计算能力增加一倍的传统硬件相比,图形卡在大约 14 到 16 个月内将计算能力增加一倍,这意味着它们拥有相当惊人的计算能力。这使我们能够训练真正深度的网络和最先进的机器学*方法。

你可以看到在 2019 年/2018 年底左右有一个相当大的下降。在这里,你可以看到,推动英伟达市场份额价值的不仅仅是深度学*。同时还有另一件非常有趣的事情正在发生,那就是比特币挖掘。在这段时间,比特币的价值确实下降了,Nvidia 股票的市值也下降了。所以这也部分与比特币有关,但你可以看到价值再次上升,因为深度学*对计算能力有巨大的需求。

图像网络挑战。 CC 下的图片来自深度学*讲座的 4.0 。

现在,我们可以瞄准哪些有趣的应用呢?因此,深度学*的大爆炸伴随着所谓的图像网络挑战而来。这是一个非常庞大的数据集,这个庞大的数据集有大约 1400 万张图片,被标记为大约 20,000 个同义词集。所以。这个图像网大规模视觉识别的挑战正在使用大约一千个类。在 image net 挑战之前,分类成一千个类别基本上被认为是完全不可能的。这里使用的图片都是从网上下载的,每张图片都有一个标签。所以,这是一个非常大的数据库,它允许我们将大量的类别分配到单独的图像中。

图像净结果。 CC 下的图片来自深度学*讲座的 4.0 。

现在是 2012 年,Alex Network 的胜利向前迈进了一大步。AlexNet 真的把错误率减半了。因此,如果我们看一下我们在 image net 挑战范围内获得的不同错误率,您可以看到,对于前 5 名错误,我们开始时的错误率约为 25%。所以在 2011 年和之前几年,我们大约在 25%左右,你可以看到这在过去几年里停滞不前。2012 年,第一个卷积神经网络(CNN)在这里推出,CNN 几乎将错误率减半。这是一个很大的惊喜,因为当时没有人能做到。您可以看到,不仅在 2012 年有所进步,而且在 2013 年等错误率越来越下降,直到我们基本上达到了与人类大致相同的水平。

图像净结果。来自深度学*讲座CC BY 4.0 下的图片。

因此,那里的神经网络报告了第一批结果,人们声称已经有了超人的表现。那么,真的是超人的表现吗?嗯,没有多少人真正评估过整个测试集。所以,你实际上可以说超人的表现应该是超级卡帕西——一种表现,因为他实际上经历了整个测试数据集。

ImageNet 示例。 CC 下的图片来自深度学*讲座的 4.0 。

现在有问题吗?是的,ImageNet 有几个问题。上面第一行可能是相当简单的例子,但是如果你看下面一行,也有一些非常困难的例子。所以,如果你只展示了图像的一部分,或者特别是如果你看到樱桃上也有一只狗,你很难区分这些图像。当然,如果每张图片只有一个标签,这就成问题了。也许一个标签不足以描述一幅完整的图像。

深度学*行业用户。 CC 下的图片来自深度学*讲座的 4.0 。

所有这些东西现在都在工业中使用。有大量部署用户,包括谷歌、苹果、IBM、Deep Mind,但也有许多其他公司从这里开始。所以你可以看到深度学*已经部分解决了网飞挑战。这是一个 100 万美元的挑战,实际上是建立一个推荐系统,推荐你真正喜欢的电影。你可以看到医疗保健正在进入:西门子和通用电气。但戴姆勒等汽车制造商和许多其他汽车制造商也在前往那里,因为自动驾驶是一个巨大的趋势。

游戏的突破。来自深度学*讲座CC BY 4.0 下的图片。

让我们来看看几个非常好的突破。例如,人们一直试图在各种游戏中击败人类,我们从 1997 年就知道我们可以在国际象棋中击败人类。所以在 1997 年,IBM 的“深蓝”打败了国际象棋世界冠军加里·卡斯帕罗夫。但是解象棋要简单一点,因为它没有那么复杂的走法。他们解决这个游戏的方法是,他们有一个开始移动的字典。然后,他们在游戏的中间部分对整个游戏进行了一次强力搜索,在游戏快结束时,他们再次使用了字典。

阿尔法星打塞拉勒。完整视频可以在这里找到。使用 gifify 生成的图像。

现在围棋是一个更难的挑战,因为在游戏的每一步中,你都可以在棋盘的每一部分放置一块石头。这意味着,如果你真的想进行彻底的搜索,寻找游戏中所有不同的机会,只有在走了几步后,实际的走法数量才会因为大的分支因子而激增。以目前的计算能力,我们无法暴力破解整个游戏。但是,2016 年 AlphaGo,一个深度思维创造的系统,真的打败了一个职业围棋手。2017 年,AlphaGo Zero 甚至超越了每一个人类,而且仅仅是靠自我对弈。不久之后,AlphaGo Zero 推广到了其他一些棋盘游戏。他们甚至设法开发了其他不同于典型棋盘游戏的游戏。在 AlphaStar 中,他们击败了职业星际玩家。因此,这确实是一项非常有趣的技术。

谷歌深梦。 CC 下的图片来自深度学*讲座的 4.0 。

在谷歌的深层梦想中,有一种理解网络内部运作的尝试,他们对网络在展示图像时会梦到什么感兴趣。因此,他们的想法是显示一些任意的输入图像或噪声作为输入,然后不是调整网络参数,而是将输入调整到网络的高激活状态。这取决于我们在看非常有趣的图像。因此,你可以创建非常令人印象深刻的神秘图像,如这里的右手边所示,有了这些输入和网络的改进。

更深的梦。来自深度学*讲座CC BY 4.0 下的图片。

或者你甚至可以放入蓝天,然后调整成神经元。然后你可以看到天空中突然出现了各种各样的东西,如果你仔细观察,你可以看到出现了像海军上将狗、猪蜗牛、骆驼鸟或狗鱼这样的动物。

显示 Yolo 能力的示例序列。完整的序列可以在这里找到。使用 gifify 生成的图像。

那么,还有什么有趣的呢?嗯,也有实时物体检测成为可能的方法,如 Yolo (你只看一次)。他们使用多个区域,检测边界框,并非常快速地对它们进行分类,这是实时运行的。它不仅仅适用于像 image net 这样的单个场景图像,在 image net 中,每个图像基本上只有一个对象,但它适用于完全混乱的场景。你甚至可以看到这些检测器对看不见的输入进行处理,比如电影场景。现在,你可能会说这些都是非常有趣的例子,但是我们能每天都使用它吗?或者仅仅是研究产生了奇特的视频?

Siri 使用深度学*技术。来自深度学*讲座CC BY 4.0 下的图片。

真的很好用。您可能已经看到语音识别界面已经有了巨大的改进。此外,借助深度学*技术,Siri 语音识别现在可以识别大约 99.7%的口语单词。所以在 100 个单词中,不到一个单词被错误识别,你可以看到 Siri 正在被使用。许多人在手机上使用它。他们用它来发号施令,它甚至可以在各种环境下工作。此外,在户外的路上环境中,当有背景噪音并且 Siri 仍然工作时。

Alexa 正在使用深度学*。 CC 下的图片来自深度学*讲座的 4.0 。

亚马逊现在也在部署一些非常有趣的东西。你可以看到,现在很多人家里都有这个亚马逊产品,他们可以远程控制不同的东西。他们可以点餐,通常效果很好。但是,当然,口音很重的用户仍然会遇到麻烦。

谷歌翻译使用深度学*。 CC 下的图片来自深度学*讲座的 4.0 。

我猜你们中的许多人也一直在使用谷歌翻译,这是一个非常好的翻译工具,在过去的两年里已经有了很大的改进。也许两年前,他们的性能确实有所提高,这是因为他们转向了一种通用的深度学*方法,在这种方法中,他们不仅学*单对语言,而且同时使用所有语言来训练深度翻译软件。如果你看看今天的谷歌翻译,很多东西都可以自动翻译,通常只需要在输出中做一些改变,这样你就有一个非常好的翻译。所以,这些是我们今天看到的深度学*令人兴奋的高调应用。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。来自深度学*讲座CC BY 4.0 下的图片。

所以,下一次在《深度访谈》中,我想向你们展示一些不仅仅发生在谷歌和大公司身上的事情。实际上,在埃尔兰根小镇,我们也有一些令人兴奋的发展,我认为值得展示。所以,希望你喜欢这个视频,下次在深度学*上再见。

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等,“在没有人类知识的情况下掌握围棋”。载于:自然 550.7676 (2017),第 354 页。
2】David Silver,Thomas Hubert,Julian Schrittwieser 等《用通用强化学*算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
3 M. Aubreville,M. Krappmann,C. Bertram 等,“一种用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
4大卫·伯内克、克里斯蒂安·里斯、伊里·安杰罗普洛斯等,“利用天空图像进行连续短期辐照度预报”。载于:太阳能 110 (2014),第 303–315 页。
【5】Patrick Ferdinand Christ,Mohamed Ezzeldin A Elshaer,Florian Ettlinger 等,“使用级联全卷积神经网络和 3D 条件随机场在 CT 中自动分割肝脏和病灶”。国际医学图像计算和计算机辅助施普林格会议。2016 年,第 415–423 页。
[6] Vincent Christlein,David Bernecker,Florian hnig 等,“使用 GMM 超向量和样本支持向量机进行作家识别”。载于:《模式识别》63 期(2017),第 258–267 页。
[7]弗罗林·克里斯蒂安·盖苏,波格丹一世·乔格斯库,托马索·曼西等,“医学图像中解剖标志检测的人工代理”。发表于:医学图像计算和计算机辅助介入——MICCAI 2016。雅典,2016 年,第 229-237 页。
[8]贾登,魏东,理查德·索彻等,“Imagenet:一个大规模的层次化图像数据库”。载于:计算机视觉和模式识别,2009 年。CVPR 2009。IEEE 会议。2009 年,第 248-255 页。
[9]卡帕斯和飞飞。“用于生成图像描述的深层视觉语义对齐”。载于:ArXiv 电子版(2014 年 12 月)。arXiv: 1412.2306 [cs。简历】。
[10]亚历克斯·克里热夫斯基、伊利亚·苏茨基弗和杰弗里·E·辛顿。“使用深度卷积神经网络的 ImageNet 分类”。神经信息处理系统进展 25。柯伦咨询公司,2012 年,第 1097-1105 页。
【11】Joseph Redmon,Santosh Kumar Divvala,Ross B. Girshick 等《你只看一次:统一的、实时的物体检测》。载于:CoRR abs/1506.02640 (2015 年)。
[12] J .雷德蒙和 a .法尔哈迪。YOLO9000:更好、更快、更强。载于:ArXiv 电子版(2016 年 12 月)。arXiv: 1612.08242 [cs。简历】。
[13]约瑟夫·雷德蒙和阿里·法尔哈迪。“YOLOv3:增量改进”。In: arXiv (2018)。
[14]弗兰克·罗森布拉特。感知器——感知和识别自动机。85–460–1.康奈尔航空实验室,1957 年。
[15] Olga Russakovsky,Jia Deng,苏浩等,“ImageNet 大规模视觉识别挑战赛”。载于:《国际计算机视觉杂志》115.3 (2015),第 211–252 页。
【16】David Silver,Aja Huang,Chris J .等《用深度神经网络和树搜索掌握围棋博弈》。载于:《自然》杂志 529.7587 期(2016 年 1 月),第 484–489 页。
[17] S. E. Wei,V. Ramakrishna,T. Kanade 等,“卷积姿态机器”。在 CVPR。2016 年,第 4724–4732 页。
【18】Tobias würfl,Florin C Ghesu,Vincent Christlein,等《深度学*计算机断层成像》。国际医学图像计算和计算机辅助斯普林格国际出版会议。2016 年,第 432–440 页。

简介—第 2 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-introduction-part-2-acabbb3ad22?source=collection_archive---------53-----------------------

FAU 讲座笔记深度学*

FAU 的亮点

FAU 大学的深度学*。来自深度学*讲座CC BY 4.0 下的图片。

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

所以,非常感谢你再次收听,欢迎来到我们深度学*讲座的第二部分,特别是导言。所以,在介绍的第二部分,我想给你们看一些我们在模式识别实验室做的研究,在德国 FAU。

今天的汽车是巨大的传感器系统。 CC 下的图片来自深度学*讲座的 4.0 。

我想强调的第一个例子是与奥迪的合作,我们正在与辅助和自动驾驶合作。我们正在研究汽车中的智能传感器。你可以看到今天的奥迪 A8 本质上是一个巨大的传感器系统,它有摄像头和不同的传感器。数据被实时处理,以便弄清楚关于环境的事情。它有停车辅助等功能。还有一些功能可以在驾驶和交通堵塞时为你提供支持,这些都是通过传感器系统完成的。当然,这涉及到许多检测和分割任务。

在线道路场景分析。完整视频可以在这里找到。使用 gifify 生成的图像。

您可以在这里看到一个示例,我们显示了汽车记录的一些输出。这是一个正面视图,我们实际上是在环顾四周,必须检测汽车。你还必须检测——这里用绿色显示——你实际上可以开车去的自由空间,所有这些都必须被检测到,其中许多事情都是通过深度学*完成的。当然,今天有一个巨大的挑战,因为我们需要测试算法。通常这是在模拟环境中完成的,然后产生大量数据以使它们可靠。但最终,这必须在路上运行,这意味着你必须考虑一年中不同的时期和不同的日光条件。这让一切变得异常艰难。你在研究中看到的是,许多检测结果都是在阳光明媚的好天气下进行的。一切都很好,所以算法工作得很好。

但真正的挑战实际上是在多雨的天气条件下,夜晚,冬天,雪,你仍然希望能够检测,当然,不仅仅是汽车,还有交通标志和地标。然后你分析你周围的场景,这样你就可以对你的自动驾驶系统有一个可靠的预测。

可再生能源系统中的智能设备。来自深度学*讲座CC BY 4.0 下的图片。

我们还研究了智能设备,当然,这里有些非常有趣的话题是可再生能源和电力。我们通常面临的一个问题是在生产时,没有足够的风吹或者没有足够的阳光照射。然后,你必须启动备用发电厂,当然,你不想生产过剩,因为那会产生不能很好储存的能量。现在能量的储存效率不是很高。有一些想法可以解决这个问题,比如实时价格,但你需要的是能够识别和预测在不久的将来会产生多少电力的智能设备。

我们来看一个智能设备的例子。比方说,你有一台冰箱或一台洗衣机,你可以对它们进行编程,让它们在消耗能源的时候灵活变化。当价格较低时,你也可以在一夜之间或一小时内开始洗涤。因此,如果你有可以预测当前价格的智能设备,那么你将能够在本质上平衡能源系统的节点,同时消除峰值条件。假设有很多风在吹。那么,很多人冷却冰箱、洗碗或洗衣服就说得通了。当然,这可以通过递归神经网络来完成,然后预测将产生多少电力,并在客户端使用它来平衡电力生产。

太阳能发电厂依赖于当地可能快速变化的天气条件。 CC 下的图片来自深度学*讲座的 4.0 。

这个例子展示了一个太阳能发电厂。他们对预测短期电力生产感兴趣,以便通知其他设备或启动备用发电厂。这里的关键时间大约是 10 分钟。因此,这里的想法是监测天空,检测云,估计云的运动,然后直接从当前的天空图像预测,在接下来的 10 分钟内将产生多少电力。所以,假设有一朵云很快就要遮住太阳了。然后,你想启动发电机或通知设备不要消耗这么多能量。现在云真的很难用算法来描述,但我们在这里所做的是,我们正在使用一个深度网络来尝试学*这种表示。这些深度学*功能可以预测电力生产,我们实际上成功地产生了大约 10 分钟的可靠预测。使用传统的模式识别技术,我们只能进行大约 5 分钟的预测。

深度表示学*支持稳定的电力生产预测。 CC 下的图片来自深度学*讲座的 4.0 。

我今天想展示的另一个非常激动人心的话题是作家认可。现在这里的任务是,你有一篇文章,你想找出是谁写了这篇文章。因此,我们不是在识别写了什么,而是在识别谁写了文本。这里的想法是再次训练一个深度网络,这个深度网络然后学*描述一个人如何写作的抽象特征。所以它只看字母周围的小块,这些字母周围的小块被用来预测谁实际上写了这篇文章。

作家一代可以创作手写文字。更多细节可以在文森特的博客中找到。来自深度学*讲座的 4.0CC 下的图片。

我的一位同事刚刚提交了一份非常好的材料,他刚刚提交给一个国际会议,他也能够生成特定人的独特笔迹。像许多方法一样,你可以看到这些深度学*方法当然可以用于非常好的目的,比如识别一个人在历史文本中写了什么。但是你也可以用非常相似的方法制造假货和传播错误信息。所以你可以看到,在很多技术中,当然这也是伦理在深度学*领域非常重要的原因。

深度学*支持肿瘤诊断。 CC 下的图片来自深度学*讲座的 4.0 。

我们正在做的大部分工作实际上都与医疗应用有关。深度学*的一个非常酷的应用是你想要筛选非常大部分的数据。所以我的一个同事开始研究整张幻灯片。这是用于肿瘤诊断的,例如,你有兴趣弄清楚癌症的侵袭性。如果你观察某个时间点上正在进行的细胞分裂的数量,你就可以知道癌症的侵袭性。所以,你实际上感兴趣的不仅仅是找出癌细胞,而是你想知道这些癌细胞实际上经历有丝分裂的频率,即细胞分裂。检测到的有丝分裂的数量表明了这种特定癌症的侵袭性。现在,这些完整的幻灯片图像非常大,你不想单独查看每个细胞。你可以做的是,你可以训练一个深度网络来观察所有的细胞,然后在临床常规中对整个载玻片进行分析。目前,人们并没有看到整张幻灯片。他们在观察高能量场,就像你在这张图片上看到的一小部分。

临床常规目前只能看几个高倍放大来估计有丝分裂数。 CC 下的图片来自深度学*讲座的 4.0 。

这是一个高功率场。在临床常规中,他们计算视野内的有丝分裂。所以当然,他们只是不在单一的高功率场做它。他们通常观察十个高倍场来评估癌症的侵袭性。使用深度学*方法,你可以处理所有的幻灯片。

使用空间转换器进行细胞定位和计数。来自深度学*讲座CC BY 4.0 下的图片。

这就是深度学*方法的样子。你在网络中有一部分定位细胞,然后网络的另一部分对细胞进行分类,不管是有丝分裂细胞,正常细胞还是癌细胞。

血管造影术允许使用静脉造影剂来显现血管。 CC 下的图片来自深度学*讲座的 4.0 。

非常有趣的事情也可以用缺陷像素插值来完成。这里,我们看到一个小场景,展示了心脏的冠状动脉。典型地,这些冠状动脉不是静止的。它们在移动,因为它们在移动,所以很难看到和分析它们。因此,为了创建清晰的冠状动脉图像,通常要做的是注射造影剂,而你之所以能在这张图像中看到冠状动脉,是因为它们现在充满了碘基造影剂。否则,因为血液在 X 射线吸收方面非常接*水,所以你什么也看不到。

呼吸和心脏运动使得心脏减影成像困难。来自深度学*讲座CC BY 4.0 下的图片。

使动脉可视化的一种非常普通的技术是拍摄两幅图像:一幅有造影剂,一幅没有。现在,如果你减去两者,你只会看到造影剂。在心脏介入治疗中,这是非常困难的,因为心脏一直在运动,而患者在呼吸。因此很难应用像数字减影血管造影术这样的技术。

使用深度学*技术的缺陷像素插值允许虚拟数字减影血管造影的计算。 CC 下的图片来自深度学*讲座的 4.0 。

这里我们提出分割检测到的血管。因此,我们使用深度学*框架,实际上是分割血管。一旦我们有了血管分割,我们就用它作为掩模。然后,如果没有造影剂,我们使用深度学*方法来预测掩模的像素。这将使这些像素从图像中消失。现在,你可以把这张虚拟的非对比图像从原始投影中减去,你就得到一张数字减影血管造影照片。这项技术也适用于动态图像。因此,没有深度学*的技术,这是做不到的。插值的实际实现是由 U-Net 完成的。在这节课的后半部分,当我们讨论图像分割时,你们会听到这种情况,它通常会用到。U-Net 是一个通用的图像到图像转换器。你也可以用它来产生无对比度的图像。

强化学*允许类似放射科医生的标志检测。图片由 Florin Ghesu 提供。

在全身图像中经常做的另一个重要部分是,你想要定位不同的器官。我的同事 Florin Ghesu 开发了一种聪明的方法来找出不同器官的位置。所以,我们的想法是以一种非常类似于放射科医生的方式来处理图像:你从查看图像的一小部分开始,然后你试图预测你必须去哪里找到感兴趣的特定器官。当然,在单一分辨率水平上这样做是不够的。因此,您还可以在更小的分辨率级别上细化搜索,以便获得器官质心的非常精确的预测。这种预测非常快,因为你只看体积的一小部分。所以你可以在大约两秒钟内完成 200 个解剖标志。另一个非常有趣的部分是,你产生了一条也可以被解释的路径。即使在体积中不存在特定标志的情况下,这种方法也不会失败。因此,假设您在一个甚至没有显示臀部的体积中寻找髋骨。然后,您将看到虚拟代理试图离开该卷,它不会预测错误的位置。相反,它会告诉你髋骨会低得多,你必须把音量留在这个位置。

深度学*地标检测也适用于 X 射线投影。图片由 Bastian Bier 提供。

正如我的同事 Bastian Bier 所演示的那样,地标检测也可以用于投影图像。他开发了一种非常有趣的方法,利用地标的三维位置。利用三维位置,您可以创建地标的虚拟投影,并训练基于投影图像的分类器。使用基于投影图像的分类器,您可以在感兴趣的特定解剖结构的任意视图中检测界标。在这里,我们展示了一个髋骨的例子,你可以看到,如果我们向前投影,并试图检测界标,这实际上是一个非常困难的任务。使用 Bastion 设计的方法,我们能够跟踪整个髋骨,并直接从投影视图中找到髋骨上的特定标志。所以这里的想法是,你用一个卷积姿态机。这里,我们基本上单独处理每个地标,然后通知在第一部分中已经检测到的不同地标关于相应的其他地标的位置。然后,你一次又一次地处理,直到你有一个最终的地标位置。

根据患者体表数据从内部器官进行预测。 CC 下的图片来自深度学*讲座的 4.0 。

我的同事夏忠一直致力于器官位置的预测,他一直在做的是,他基本上是使用一个三维相机来检测病人的表面。然后,他想预测器官在体内的实际位置。现在,这非常有趣,因为我们可以利用这些信息来预测不同器官将会受到多少辐射剂量。因此,如果我知道器官在哪里,那么我就可以调整我的放射治疗计划,甚至是成像,以便选择 x 射线设备的位置,使风险器官的剂量最小。这可以帮助我们减少器官的剂量和在相应治疗后发生癌症的风险。

基于主体的器官分割。来自深度学*讲座CC BY 4.0 下的图片。

现在,这种仅从表面信息预测器官位置的方法也可以用于在介入 CT 中执行器官分割。因此,这里的想法是,你从一个器官的初始点云开始,然后像前面基于代理的方法一样对它进行优化。我们逐步修改网格,使其与特定图像中的器官形状相匹配。你可以在左边看到一些手术前的 CT 图像,从这里,我们可以训练算法并产生点云。

基于智能体的器官分割。图片由夏忠提供。

然后,您可以训练一个网络来对这些点云进行变形,并生成新的形状,使它们与实际的图像外观相匹配。有趣的是,这种方法预先知道器官的形状,只对器官做微小的改变,以匹配当前的图像。这允许我们在介入数据中产生非常快速和非常准确的器官分割。因此,我们用常规的 CT 数据进行训练,但它也适用于用移动 C 型臂或血管造影系统完成的图像,这些图像的质量要低得多。这些图像在介入环境中用于引导目的。我们可以在比如说 0.3 到 2.6 秒内应用我们的方法,这比传统的 U-Net 方法快大约 50 到 100 倍,在传统的 U-Net 方法中,你可以进行完全的 3-D 处理。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。来自深度学*讲座CC BY 4.0 下的图片。

所以,下一次在深度学*中,我们不仅会谈论成功,还会谈论深度学*的局限性。此外,我们还想讨论几个可能有助于减少这些限制的未来方向。非常感谢您的观看,希望在下一段视频中见到您。

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等,“在没有人类知识的情况下掌握围棋”。载于:自然 550.7676 (2017),第 354 页。
2】David Silver,Thomas Hubert,Julian Schrittwieser 等《用通用强化学*算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
3 M. Aubreville,M. Krappmann,C. Bertram 等,“一种用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
4大卫·伯内克、克里斯蒂安·里斯、伊里·安杰罗普洛斯等,“利用天空图像进行连续短期辐照度预报”。载于:太阳能 110 (2014),第 303–315 页。
【5】Patrick Ferdinand Christ,Mohamed Ezzeldin A Elshaer,Florian Ettlinger 等,“使用级联全卷积神经网络和 3D 条件随机场在 CT 中自动分割肝脏和病灶”。国际医学图像计算和计算机辅助施普林格会议。2016 年,第 415–423 页。
[6] Vincent Christlein,David Bernecker,Florian hnig 等,“使用 GMM 超向量和样本支持向量机进行作家识别”。载于:《模式识别》63 期(2017),第 258–267 页。
[7]弗罗林·克里斯蒂安·盖苏,波格丹一世·乔格斯库,托马索·曼西等,“医学图像中解剖标志检测的人工代理”。发表于:医学图像计算和计算机辅助介入——MICCAI 2016。雅典,2016 年,第 229-237 页。
[8]贾登,魏东,理查德·索彻等,“Imagenet:一个大规模的层次化图像数据库”。载于:计算机视觉和模式识别,2009 年。CVPR 2009。IEEE 会议。2009 年,第 248-255 页。
[9]卡帕斯和飞飞。“用于生成图像描述的深层视觉语义对齐”。载于:ArXiv 电子版(2014 年 12 月)。arXiv: 1412.2306 [cs。简历】。
[10]亚历克斯·克里热夫斯基、伊利亚·苏茨基弗和杰弗里·E·辛顿。“使用深度卷积神经网络的 ImageNet 分类”。神经信息处理系统进展 25。柯伦咨询公司,2012 年,第 1097-1105 页。
【11】Joseph Redmon,Santosh Kumar Divvala,Ross B. Girshick 等《你只看一次:统一的、实时的物体检测》。载于:CoRR abs/1506.02640 (2015 年)。
[12] J .雷德蒙和 a .法尔哈迪。YOLO9000:更好、更快、更强。载于:ArXiv 电子版(2016 年 12 月)。arXiv: 1612.08242 [cs。简历】。
[13]约瑟夫·雷德蒙和阿里·法尔哈迪。“YOLOv3:增量改进”。In: arXiv (2018)。
[14]弗兰克·罗森布拉特。感知器——感知和识别自动机。85–460–1.康奈尔航空实验室,1957 年。
[15] Olga Russakovsky,Jia Deng,苏浩等,“ImageNet 大规模视觉识别挑战赛”。载于:《国际计算机视觉杂志》115.3 (2015),第 211–252 页。
【16】David Silver,Aja Huang,Chris J .等《用深度神经网络和树搜索掌握围棋博弈》。载于:《自然》杂志 529.7587 期(2016 年 1 月),第 484–489 页。
[17] S. E. Wei,V. Ramakrishna,T. Kanade 等,“卷积姿态机器”。在 CVPR。2016 年,第 4724–4732 页。
【18】Tobias würfl,Florin C Ghesu,Vincent Christlein,等《深度学*计算机断层成像》。国际医学图像计算和计算机辅助斯普林格国际出版会议。2016 年,第 432–440 页。

简介—第 3 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-introduction-part-3-22142caad28a?source=collection_archive---------65-----------------------

FAU 讲座笔记深度学*

深度学*的局限性和未来方向

FAU 大学的深度学*。来自深度学*讲座CC BY 4.0 下的图片。

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

感谢收看深度学*的下一期视频。所以,我想在这个视频中展示给你的是深度学*的一些局限性。所以,你可能想知道有什么限制吗?我们说完了吗?我们不是在这里学到了可以解决所有问题的东西吗?

图像字幕的正面例子。 CC 下的图片来自深度学*讲座的 4.0 。

当然也有一些限制。例如,像图像字幕这样的任务会产生令人印象深刻的结果。你可以看到网络能够识别棒球运动员,穿着粉色裙子在空中跳跃的女孩,甚至是弹吉他的人。

图像字幕中的错误。 CC 下的图片来自深度学*讲座的 4.0 。

所以我们来看一些错误。在左边,你可以看到,这显然不是棒球棒。此外,这不是一只猫在中心的形象,他们也像在右手边的一个轻微的错误:在行李箱顶部的猫不是黑色的。

清除图像字幕中的错误:来自深度学*讲座CC 下的图像 4.0

有时它们甚至是简单的错误,比如左图中的这个:我没有看到路中间有一匹马,右图中也没有一个女人在镜子前抱着一只泰迪熊。

这当然是因为有几个挑战,其中一个主要挑战是训练数据。深度学*应用需要巨大的人工标注数据集,而这些数据集很难获得。注释既费时又费钱,而且常常含糊不清。所以,正如你在 image net challenge 中已经看到的,有时不清楚分配哪个标签,显然你必须分配标签的分布。此外,我们看到,即使在人工注释中,也存在典型的错误。为了得到一个真正好的标签,你需要做的是,你实际上需要请两个甚至更多的专家来完成整个贴标过程。然后,您可以找到标签分布非常明显的实例。这些是典型的原型,标签的广泛分布是人们不确定的图像。如果我们有这样的问题,那么我们的性能通常会显著下降。因此,问题是我们能在多大程度上进行模拟,例如扩展训练数据。

当然,也存在信任和可靠性方面的挑战。因此,对于高风险的应用程序来说,验证是强制性的,监管机构对此可能会非常严格。他们真的想了解那些高风险系统中发生了什么。端到端学*本质上禁止识别各个部分是如何工作的。因此,监管者很难判断哪个部分做了什么,以及这个系统实际上为什么会工作。在这一点上,我们必须承认,这在很大程度上还没有解决。很难区分网络的哪个部分在做什么。基于经典算法的模块化方法可能是未来解决这些问题的一种方法。

经典的 CT 重建使用滤波和反投影来生成 CT 切片图像。 CC 下的图片来自深度学*讲座的 4.0 。

这就把我们带到了未来的方向,我们在埃尔兰根喜欢做的事情是学*算法。例如,你可以看看经典的计算机断层摄影,它是用滤波反投影公式表示的。你必须沿着投影方向过滤,然后在角度上求和,以产生最终图像。所以这个卷积和反投影实际上可以用线性算子来表示。因此,它们本质上是矩阵乘法。

滤波反投影可以在数学上等同地映射到具有三层的神经网络上。来自深度学*讲座CC BY 4.0 下的图片。

现在,这些矩阵乘法可以作为一个神经网络来实现,这样你就有了一个算法或网络设计,可以为特定目的进行训练。

扇形束几何形状的重构网络。 CC 下的图片来自深度学*讲座的 4.0 。

因此,在这里,我们扩展了这种方法,以便将其应用于扇束投影数据。这是对算法的一个微小修改。也有像限角情况这样无法解决的情况。

完整的 CT 扫描。来自深度学*讲座的 4.0CC 下的图片。

在这个图像中,你看到一个完整的扫描,这产生了一个合理的 CT 图像。然而,如果你只错过了 20 度的旋转,你已经看到了严重的伪像:

这个 CT 扫描只少了 20 度的旋转。 CC 下的图片来自深度学*讲座的 4.0 。

现在,如果你把你的重建算法转换成一个神经网络,并用一些训练数据重新训练它。这里只有 15 幅图像,您可以看到,即使在看不见的数据上,我们也能够恢复大部分丢失的信息:

已知的 CT 重建能够补偿丢失的 20 度旋转。来自深度学*讲座CC BY 4.0 下的图片。

现在,如果你看这张图片的顶部,你可以看到质量减少了。我们显示了右侧左图中红线后的线图:

不同 CT 重建的线轮廓比较。 CC 下的图片来自深度学*讲座的 4.0 。

现在这里是绿色,你可以看到基本上没有受到影响的参考图像。一旦引入角度限制,就会出现红色曲线,在图像的顶部显示这些伪像。现在,如果你进一步采取我们的深度学*方法,你会得到蓝色曲线,这大大减少了角度和限制带来的问题。现在,有趣的部分是因为我们的算法受到了传统 CT 重建算法的启发,所有这些层都有解释:它们与特定的功能相关联。在如此短的扫描中,你通常会做什么,就是对测量了两次的射线进行加权,这样相对的射线正好加在一起。

用于网络初始化的经典 Parker 权重。来自深度学*讲座的 4.0CC 下的图片。

你可以看到图中帕克的体重。现在,如果我们训练我们的算法,主要的变化是帕克权重。发生的情况是,我们可以看到重量的增加,特别是在训练后穿过具有角度限制的区域的光线中:

训练算法后的冗余权重。 CC 下的图片来自深度学*讲座的 4.0 。

因此,网络学会了在那些没有被测量的射线中使用来自稍微不同方向的信息。你甚至可以继续,然后将这种重建方法与额外的去条纹和去噪步骤结合起来,我们将在这节课结束时展示。因此,我们也可以在低对比度信息中显著改善。

额外的去条纹和去噪声进一步改善了重建。来自深度学*讲座CC BY 4.0 下的图片。

在这里,您可以在左上角看到全扫描参考的图像,在右上角看到仍有明显条纹的神经网络输出,在右下角,您可以看到条纹减少网络。它能够真正减少那些由角度限制引起的条纹。与左下方的去噪方法相比,您可以看到这些条纹会减少,但仍然存在。只有这样一个训练有素的方法,了解问题是什么,实际上能够有效地减少那些伪像。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

所以下一次在深度学*中,我们想看看基本的模式识别和机器学*。有哪些基本规则,这与深度学*有什么关系?然后,我们想继续讨论感知器,它是神经网络的基本单元。从这些感知器,你可以建立那些真正的深度网络,我们一直在这个和以前的视频中。所以,我希望你喜欢这个视频,如果你下次收听的话,那就太好了。谢谢大家!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等,“在没有人类知识的情况下掌握围棋”。载于:自然 550.7676 (2017),第 354 页。
2】David Silver,Thomas Hubert,Julian Schrittwieser 等《用通用强化学*算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
3 M. Aubreville,M. Krappmann,C. Bertram 等,“一种用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
4大卫·伯内克、克里斯蒂安·里斯、伊里·安杰罗普洛斯等,“利用天空图像进行连续短期辐照度预报”。载于:太阳能 110 (2014),第 303–315 页。
【5】Patrick Ferdinand Christ,Mohamed Ezzeldin A Elshaer,Florian Ettlinger 等,“使用级联全卷积神经网络和 3D 条件随机场在 CT 中自动分割肝脏和病灶”。国际医学图像计算和计算机辅助施普林格会议。2016 年,第 415–423 页。
[6] Vincent Christlein,David Bernecker,Florian hnig 等,“使用 GMM 超向量和样本支持向量机进行作家识别”。载于:《模式识别》63 期(2017),第 258–267 页。
[7]弗罗林·克里斯蒂安·盖苏,波格丹一世·乔格斯库,托马索·曼西等,“医学图像中解剖标志检测的人工代理”。发表于:医学图像计算和计算机辅助介入——MICCAI 2016。雅典,2016 年,第 229-237 页。
[8]贾登,魏东,理查德·索彻等,“Imagenet:一个大规模的层次化图像数据库”。载于:计算机视觉和模式识别,2009 年。CVPR 2009。IEEE 会议。2009 年,第 248-255 页。
[9]卡帕斯和飞飞。“用于生成图像描述的深层视觉语义对齐”。载于:ArXiv 电子版(2014 年 12 月)。arXiv: 1412.2306 [cs。简历】。
[10]亚历克斯·克里热夫斯基、伊利亚·苏茨基弗和杰弗里·E·辛顿。“使用深度卷积神经网络的 ImageNet 分类”。神经信息处理系统进展 25。柯伦咨询公司,2012 年,第 1097-1105 页。
【11】Joseph Redmon,Santosh Kumar Divvala,Ross B. Girshick 等《你只看一次:统一的、实时的物体检测》。载于:CoRR abs/1506.02640 (2015 年)。
[12] J .雷德蒙和 a .法尔哈迪。YOLO9000:更好、更快、更强。载于:ArXiv 电子版(2016 年 12 月)。arXiv: 1612.08242 [cs。简历】。
[13]约瑟夫·雷德蒙和阿里·法尔哈迪。“YOLOv3:增量改进”。In: arXiv (2018)。
[14]弗兰克·罗森布拉特。感知器——感知和识别自动机。85–460–1.康奈尔航空实验室,1957 年。
[15] Olga Russakovsky,Jia Deng,苏浩等,“ImageNet 大规模视觉识别挑战赛”。载于:《国际计算机视觉杂志》115.3 (2015),第 211–252 页。
【16】David Silver,Aja Huang,Chris J .等《用深度神经网络和树搜索掌握围棋博弈》。载于:《自然》杂志 529.7587 期(2016 年 1 月),第 484–489 页。
[17] S. E. Wei,V. Ramakrishna,T. Kanade 等,“卷积姿态机器”。在 CVPR。2016 年,第 4724–4732 页。
【18】Tobias würfl,Florin C Ghesu,Vincent Christlein,等《深度学*计算机断层成像》。国际医学图像计算和计算机辅助斯普林格国际出版会议。2016 年,第 432–440 页。

简介—第 4 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-introduction-part-4-2e86af0498ce?source=collection_archive---------58-----------------------

FAU 讲座笔记深度学*

模式识别短期课程

FAU 大学的深度学*。来自深度学*讲座CC BY 4.0 下的图片。

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎来到我们的深度学*讲座。我们现在在引言的第 4 部分。现在,在第四条道路上,我们想谈谈机器学*和模式识别,首先我们必须介绍一些术语和符号。

这节课的注释。 CC 下的图片来自深度学*讲座的 4.0 。

所以,在整个系列讲座中,我们将使用下面的符号:矩阵是粗体大写的。所以,这里的例子有 MA 。向量是粗体的,小写的例子有 vx 。标量是斜体和小写的:y,w,α。对于函数的梯度,我们使用梯度符号∇,对于偏导数,我们使用偏导数符号∂.此外,我们有一些关于深度学*的细节。因此,可训练权重通常称为 w。特征或输入为 x 。它们是典型的向量。然后,我们有基本事实标签,即 y。我们有一些估计输出,即 y hat,如果我们有一些迭代正在进行,我们通常在上标上,并将其放入括号中。这里是一个迭代索引:变量 x 的迭代 I。当然,这是一个非常粗略的符号,我们将在整个讲座中进一步发展它。

经典图像处理流水线。来自深度学*讲座的 4.0CC 下的图片。

如果你听过我们组以前的讲座,那么你应该知道模式识别的经典图像处理流水线。它通过采样进行记录,然后进行模数转换。然后是预处理、特征提取和分类。当然,在分类这一步,你还得做训练。模式识别管道的第一部分将在我们的讲座介绍模式识别中介绍。分类的主要部分包含在模式识别中。

经典特征提取。下图 CC BY 4.0 来自深度学*讲座

现在,你在这幅图像中看到的是一个经典的图像识别问题。比方说,你想区分苹果和梨。现在,你可以做的一个想法是,你可以围绕它们画一个圆,然后测量长轴和短轴的长度。所以,你会认出苹果是圆的,梨更长。所以,它们的椭圆在长轴和短轴上有所不同。

向量空间中的苹果和梨。 CC 下的图片来自深度学*讲座的 4.0 。

现在,你可以把这两个数字表示成一个向量值。然后,你进入一个二维空间,这基本上是一个向量空间表示,你会发现所有的苹果都位于 x 轴的对角线上。如果它们的直径和一个方向增加,另一个方向的直径也增加。你的梨偏离了这条直线,因为它们的短轴和长轴不同。现在,你可以找到一条线把这两者分开,这就是你的第一个分类系统。

现在,许多人对大数据处理如何工作的看法显示在这个小图中:

“那么,这是你的机器学*系统?”

“是的,把数据倒入这一大堆线性代数中,然后收集另一边的答案。”

“如果答案是错的呢?”

“搅拌这堆东西,直到它们看起来合适为止!”

KXCD 机器学*

所以,你可以在这张图中看到,当然这是许多人认为他们接*深度学*的方式。你只需将数据输入,最后你只需稍微搅拌一下,就能得到正确的结果。

深度学*中的管道。 CC 下的图片来自深度学*讲座的 4.0 。

但实际上并不是这样。提醒他们你想做的是你想建立一个学*分类的系统。这意味着从你的测量你首先要做一些预处理,如减少噪音。你必须得到一幅有意义的图像,然后进行特征提取,从中你可以进行分类。现在,与深度学*的不同之处在于,你把所有的东西都放在一个单一的引擎中。因此,预处理、特征提取和分类只需一步即可完成。你只需要使用训练数据和测量来产生那些系统。现在,这已被证明在许多应用中有效,但正如我们在上一个视频中已经讨论过的,您必须拥有正确的数据。你不能只是倒入一些数据,然后搅拌,直到它开始看起来正确。你必须有一个适当的数据集,一个适当的数据收集,如果你没有以适当的方式这样做,你只会得到废话。

模式识别的前两个假设。 CC 下的图片来自深度学*讲座的 4.0 。

当然,我们有几个假设,这些假设也适用于深度学*领域。所以在经典模式识别中,我们遵循这些假设。所以,第一个假设是,有代表性的抽样模式的可变性,这些抽样模式在课堂和问题域ω中给出。这里,您有所有这些类别的培训示例,它们具有代表性。所以,这意味着如果你有一个新的观察,它将与你已经收集的那些模式相似。下一个假设是,存在一个简单模式,这个简单模式具有一些特征,这些特征描述了某个类的成员资格。所以,你必须能够以某种方式处理数据,从而得到这个抽象的表示。有了这种表示,您就可以在分类器中派生出类。

模式识别的公设 3。来自深度学*讲座CC BY 4.0 下的图片。

此外,同一类的特征在特征域中应该是紧凑的。所以,这意味着不同类的特征,它们应该与其他类分开,而同一类的特征应该彼此靠*。因此,理想情况下,你需要的是较小的组内方差和较大的组间距离。此图中显示了一些示例。所以左上角是一个非常简单的例子。中间那个也是可解的。第三个变得更难,当然,你仍然可以用一个非线性的边界把它们分开。左下角的情况更复杂,因为这里的类是混杂的,你需要在这些类周围画出区域。它们也可能非常紧密地交织在一起,但仍然是可分的,当然,你可能会有数据,但很难弄清楚哪一部分属于哪一部分。通常情况下,如果您遇到像右下方这样的情况,您没有一个非常好的特征表示,您需要考虑是否没有找到更好的特征。今天许多人做的是他们只是说:“哦,让我们去深度学*,只是学*一个合适的表示,然后就可以了。”

模式识别排在#4 到#6 之后。 CC 下的图片来自深度学*讲座的 4.0 。

因此,一个复杂的模式由彼此之间有一定关系的简单成分组成,并且该模式可以被分解成这些部分。此外,复杂的图案具有特定的结构,并且不是每个简单部分的排列都给出有效的图案,并且许多图案可以用相对较少的部分来表示。当然,如果简单零件的特征仅略有不同,则两种模式是相似的。看到模式识别的这些基本假设后,我们将看到其中许多仍然适用于深度学*的世界。然而,我们看不到事物是如何分解的。相反,我们建立系统来逐渐简化输入,这样你就可以将它们分解成部分和更好的表示。

生物神经元。来自深度学*讲座CC BY 4.0 下的图片。

现在,让我们从最基本的开始。感知器是大多数神经网络中的基本单元,也是人们对感知器非常感兴趣的原因。实际上,当罗森布拉特在 20 世纪 50 年代介绍它们的时候,人们真的很兴奋,因为罗森布拉特把这种感知机和生物神经元很好地联系在一起。现在,一个生物神经元通过突触与其他神经元相连,并计算传入的兴奋性和抑制性激活的总和。如果它们足够大,那么神经元就会放电,如果你有某个超过阈值的电位,它就会放电。然后,它传递信息,这是典型的全有或全无反应,这意味着如果你有一个更高的刺激,你超过了阈值,这并不意味着它会引起更高的反应。它要么开火,要么不开火。所以它本质上是一个二元分类器。

感知。 CC 下的图片来自深度学*讲座的 4.0 。

这个概念可以很容易地转换成矢量表示。他设计了一个系统,输入向量由输入值 x₁到 x_n 指定,然后加上一个偏差。在这里,你把它们乘以权重,然后加起来。然后,你有一个激活函数,要么激活,要么不激活,这里为了简单起见,我们可以简单地用符号函数。所以,如果你有一个积极的激活,你就发射。如果你有一个负面的激活,你不会开枪。这可以用符号函数来表示。现在,这导致了一个相当有问题的训练程序。

分类器训练的感知器目标函数。来自深度学*讲座CC BY 4.0 下的图片。

当然,如果你想训练,你需要有各自类的观察元组。这是你的训练数据集,然后你需要确定误分类特征向量的集合 M。这些向量中,预测的数字 y 和实际的类成员 yᵢ.不匹配如果你计算神经元的输出。现在,如果你有这个集合 M,它必须在训练迭代的每一步之后被确定,那么你试图最小化下面的优化问题:描述你的错误分类的问题本质上是所有你的错误分类样本的总和,其中你计算你的实际神经元的输出。然后乘以真实的类成员。因为两者不匹配,意味着这一定是负的。然后,将上述项乘以负 1,以便为大量错误分类创建一个高值。你试图将这一项最小化。

感知器权重更新程序。 CC 下的图片来自深度学*讲座的 4.0 。

这基本上导致了一个优化过程,你有一个迭代过程。因此,这种迭代优化必须为权重确定更新的梯度步长。一旦更新了权重,就必须再次确定错误分类的向量集。现在的问题是,在每一次迭代中,M 的组合基数可能会改变,因为每一步你都会有更多的错误分类。你实际上计算的是函数相对于权重的梯度,它只是输入向量乘以正确的类减一。这会给你一个重量的更新。

感知学*的权重更新策略。来自深度学*讲座CC BY 4.0 下的图片。

现在,如果您计算这个梯度,策略 1 将处理所有样本,然后执行权重更新。策略 2 是在每个丢失的分类样本之后采取更新步骤,然后直接更新权重。因此,每次迭代都有一个更新规则,简化为:旧的权重加上错误分类的样本乘以类成员。这给了你新的权重。现在,您优化到收敛或预定义的迭代次数。这个非常简单的程序有许多缺点,我们将在本课程的稍后部分讨论。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

所以,在下节课中,如果你想获得一个证书,我们想看看几个重要的组织事项。此外,我们将对您到目前为止看过的四个视频进行一个简短的总结。希望你喜欢这个视频,希望下次再见!

如果你喜欢这篇文章,你可以在这里找到更多的文章,在这里找到更多关于机器学*的教育材料,或者看看我们的深度 学* 讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 或 T21 上的掌声或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等,“在没有人类知识的情况下掌握围棋”。载于:自然 550.7676 (2017),第 354 页。
2】David Silver,Thomas Hubert,Julian Schrittwieser 等《用通用强化学*算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
3 M. Aubreville,M. Krappmann,C. Bertram 等,“一种用于组织学细胞分化的导向型空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
4大卫·伯内克、克里斯蒂安·里斯、伊里·安杰罗普洛斯等,“利用天空图像进行连续短期辐照度预报”。载于:太阳能 110 (2014),第 303–315 页。
【5】Patrick Ferdinand Christ,Mohamed Ezzeldin A Elshaer,Florian Ettlinger 等,“使用级联全卷积神经网络和 3D 条件随机场在 CT 中自动分割肝脏和病灶”。国际医学图像计算和计算机辅助施普林格会议。2016 年,第 415–423 页。
[6] Vincent Christlein,David Bernecker,Florian hnig 等,“使用 GMM 超向量和样本支持向量机进行作家识别”。载于:《模式识别》63 期(2017),第 258–267 页。
[7]弗罗林·克里斯蒂安·盖苏,波格丹一世·乔格斯库,托马索·曼西等,“医学图像中解剖标志检测的人工代理”。发表于:医学图像计算和计算机辅助介入——MICCAI 2016。雅典,2016 年,第 229-237 页。
[8]贾登,魏东,理查德·索彻等,“Imagenet:一个大规模的层次化图像数据库”。载于:计算机视觉和模式识别,2009 年。CVPR 2009。IEEE 会议。2009 年,第 248-255 页。
[9]卡帕斯和飞飞。“用于生成图像描述的深层视觉语义对齐”。载于:ArXiv 电子版(2014 年 12 月)。arXiv: 1412.2306 [cs。简历】。
[10]亚历克斯·克里热夫斯基、伊利亚·苏茨基弗和杰弗里·E·辛顿。“使用深度卷积神经网络的 ImageNet 分类”。神经信息处理系统进展 25。柯伦咨询公司,2012 年,第 1097-1105 页。
【11】Joseph Redmon,Santosh Kumar Divvala,Ross B. Girshick 等《你只看一次:统一的、实时的物体检测》。载于:CoRR abs/1506.02640 (2015 年)。
[12] J .雷德蒙和 a .法尔哈迪。YOLO9000:更好、更快、更强。载于:ArXiv 电子版(2016 年 12 月)。arXiv: 1612.08242 [cs。简历】。
[13]约瑟夫·雷德蒙和阿里·法尔哈迪。“YOLOv3:增量改进”。In: arXiv (2018)。
[14]弗兰克·罗森布拉特。感知器——感知和识别自动机。85–460–1.康奈尔航空实验室,1957 年。
[15] Olga Russakovsky,Jia Deng,苏浩等,“ImageNet 大规模视觉识别挑战赛”。载于:《国际计算机视觉杂志》115.3 (2015),第 211–252 页。
【16】David Silver,Aja Huang,Chris J .等《用深度神经网络和树搜索掌握围棋博弈》。载于:《自然》杂志 529.7587 期(2016 年 1 月),第 484–489 页。
[17] S. E. Wei,V. Ramakrishna,T. Kanade 等,“卷积姿态机器”。在 CVPR。2016 年,第 4724–4732 页。
【18】Tobias würfl,Florin C Ghesu,Vincent Christlein,等《深度学*计算机断层成像》。国际医学图像计算和计算机辅助斯普林格国际出版会议。2016 年,第 432–440 页。

简介—第 5 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-introduction-part-5-a3b9faacd313?source=collection_archive---------41-----------------------

FAU 讲座笔记深度学*

练*与展望

FAU 大学的深度学*。来自深度学*讲座CC BY 4.0 下的图片。

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

一种快进到逐层的反向传播。别担心,我们会解释所有的细节。 CC 下的图片来自深度学*讲座的 4.0 。

感谢再次收听,欢迎来到深度学*!在这个小视频中,我们将了解组织事项并结束介绍。那么,让我们来看看组织事项。现在,你能在 FAU 这里得到的模块总共由五个 ECTS 组成。这是讲课加练*。所以,仅仅观看所有这些视频是不够的,你必须通过练*。在练*中,您将使用 Python 实现我们在这里讨论的所有内容。我们将从零开始,所以你将实现感知器神经网络,直到深度学*。最终,我们甚至会朝着 GPU 实现和大型深度学*框架前进。所以,这是必修部分,仅仅通过口试是不够的。

我们还将在练*中实现最大池。 CC 下的图片来自深度学*讲座的 4.0 。

练*的内容是 Python。如果你从未使用过 python,你将对它做一个介绍,因为 Python 是深度学*实现今天使用的主要语言之一。你真的会从零开始开发一个神经网络。会有前馈神经网络,会有卷积神经网络。您将研究正则化技术,以及如何实际调整权重,使它们具有特定的属性。你将会看到如何用某些或正则化技术来克服过度拟合。当然,我们也将实现循环网络。稍后,我们将使用 Python 框架并将其用于大规模分类。对于这些练*,您应该具备 Python 和 NumPy 的基础知识。你应该了解矩阵乘法等线性代数。图像处理是一个明确的优势。你应该知道如何处理图像——当然——这门课的要求是模式识别基础知识,并且你已经参加过模式识别的其他课程。如果您还没有,您可能需要参考其他参考资料才能跟上这个课程。

你应该对这门课的练*编码充满热情。照片由马库斯·斯皮斯克派克斯拍摄。

你应该带着对编码的热情,你必须做很多编码,但是你也可以在练*中学*。如果你在这门课之前没有做过大量的编程工作,你会在练*上花很多时间。但是如果你完成了这些练*,你将能够在深度学*框架中实现一些东西,这是非常好的训练。学完本课程后,您不仅可以从 GitHub 下载代码并在自己的数据上运行,还可以:

  • 你也了解网络的内部运作,
  • 如何编写自己的层和
  • 如何在非常低的水平上扩展深度学*算法。

在本课程的练*中,你也将有机会使用真正的大数据集。图片由 Marc Aubreville 提供。点击查看完整视频。

所以,注意细节,如果你不太*惯编程,这将花费一些时间。整个学期将有五次练*。除了最后一个练*,所有的练*都有单元测试。因此,这些单元测试应该可以帮助你实现,在最后一个练*中,将有一个 PyTorch 实现,你将面临一个挑战:你必须解决图像识别任务,以便通过练*。截止日期在各自的练*环节中公布。所以,你必须在学生宿舍为他们注册。

到目前为止,我们在讲座中看到的是,深度学*越来越多地出现在日常生活中。所以,这不仅仅是研究中的一项技术。我们已经看到这种技术真正出现在许多不同的应用中,从语音识别、图像处理等等到自动驾驶。这是一个非常活跃的研究领域。如果你在做这个讲座,你已经为与我们的实验室或行业或其他合作伙伴的研究项目做了很好的准备。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。来自深度学*讲座CC BY 4.0 下的图片。

到目前为止,我们研究了感知机及其与生物神经元的关系。所以,下一次关于深度学*,我们将从下一节课开始,这意味着,我们将把感知器扩展为通用函数逼*器。我们将研究这些模型的基于梯度的训练算法,然后我们还将研究梯度的有效计算。

现在,如果你想准备口语考试,最好想几个综合问题。问题可能是

  • "模式识别的六个假设是什么?"
  • "什么是感知器目标函数?"
  • “你能说出深度学*成功解决的三个应用吗?”

当然,我们还有很多进一步的阅读材料。所以你可以在幻灯片上找到链接,我们也会在这篇文章下面贴上链接和参考资料。

如果你有任何问题,

  • 你可以在练*中请教老师,
  • 你可以给我发邮件,
  • 或者如果你正在 youtube 上看这个,你可以使用评论功能提出你的问题。

所以,有很多联系方式,当然,我们有很多前五个视频的参考资料。现在阅读它们太快了,但你可以暂停视频,然后查看它们,我们也会在这篇文章下面的参考资料中发布这些参考资料。所以,我希望你喜欢这个视频,下次在深度学*中再见!

注意:FAU 的练*材料很广泛。为了了解我们的练*,我们在 GitHub 上创建了 这些例子。完整的锻炼计划目前只对 FAU 的学生开放。如果您对 GitHub 上的练*以外的其他练*感兴趣,请联系我。

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1大卫·西尔弗、朱利安·施利特维泽、卡伦·西蒙扬等,“在没有人类知识的情况下掌握围棋”。载于:自然 550.7676 (2017),第 354 页。
2】David Silver,Thomas Hubert,Julian Schrittwieser 等《用通用强化学*算法通过自玩掌握国际象棋和松木》。载于:arXiv 预印本 arXiv:1712.01815 (2017)。
3 M. Aubreville,M. Krappmann,C. Bertram 等,“一种用于组织学细胞分化的导向空间转换器网络”。载于:ArXiv 电子版(2017 年 7 月)。arXiv: 1707.08525 [cs。简历】。
4大卫·伯内克、克里斯蒂安·里斯、伊里·安杰罗普洛斯等,“利用天空图像进行连续短期辐照度预报”。载于:太阳能 110 (2014),第 303–315 页。
【5】Patrick Ferdinand Christ,Mohamed Ezzeldin A Elshaer,Florian Ettlinger 等,“使用级联全卷积神经网络和 3D 条件随机场在 CT 中自动分割肝脏和病灶”。国际医学图像计算和计算机辅助施普林格会议。2016 年,第 415–423 页。
[6] Vincent Christlein,David Bernecker,Florian hnig 等,“使用 GMM 超向量和样本支持向量机进行作家识别”。载于:《模式识别》63 期(2017),第 258–267 页。
[7]弗罗林·克里斯蒂安·盖苏,波格丹一世·乔格斯库,托马索·曼西等,“医学图像中解剖标志检测的人工代理”。发表于:医学图像计算和计算机辅助介入——MICCAI 2016。雅典,2016 年,第 229-237 页。
[8]贾登,魏东,理查德·索彻等,“Imagenet:一个大规模的层次化图像数据库”。载于:计算机视觉和模式识别,2009 年。CVPR 2009。IEEE 会议。2009 年,第 248-255 页。
[9]卡帕斯和飞飞。“用于生成图像描述的深层视觉语义对齐”。载于:ArXiv 电子版(2014 年 12 月)。arXiv: 1412.2306 [cs。简历】。
[10]亚历克斯·克里热夫斯基、伊利亚·苏茨基弗和杰弗里·E·辛顿。“使用深度卷积神经网络的 ImageNet 分类”。神经信息处理系统进展 25。柯伦咨询公司,2012 年,第 1097-1105 页。
【11】Joseph Redmon,Santosh Kumar Divvala,Ross B. Girshick 等《你只看一次:统一的、实时的物体检测》。载于:CoRR abs/1506.02640 (2015 年)。
[12] J .雷德蒙和 a .法尔哈迪。YOLO9000:更好、更快、更强。载于:ArXiv 电子版(2016 年 12 月)。arXiv: 1612.08242 [cs。简历】。
[13]约瑟夫·雷德蒙和阿里·法尔哈迪。“YOLOv3:增量改进”。In: arXiv (2018)。
[14]弗兰克·罗森布拉特。感知器——感知和识别自动机。85–460–1.康奈尔航空实验室,1957 年。
[15] Olga Russakovsky,Jia Deng,苏浩等,“ImageNet 大规模视觉识别挑战赛”。载于:《国际计算机视觉杂志》115.3 (2015),第 211–252 页。
【16】David Silver,Aja Huang,Chris J .等《用深度神经网络和树搜索掌握围棋博弈》。载于:《自然》杂志 529.7587 期(2016 年 1 月),第 484–489 页。
[17] S. E. Wei,V. Ramakrishna,T. Kanade 等,“卷积姿态机器”。在 CVPR。2016 年,第 4724–4732 页。
【18】Tobias würfl,Florin C Ghesu,Vincent Christlein,等《深度学*计算机断层成像》。国际医学图像计算和计算机辅助斯普林格国际出版会议。2016 年,第 432–440 页。

损失和优化—第 1 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-loss-and-optimization-part-1-f702695cbd99?source=collection_archive---------64-----------------------

FAU 讲座笔记深度学*

分类和回归损失

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎大家来深度学*!所以,今天我们想继续讨论不同的损失和优化。我们想继续讨论这些有趣问题的更多细节。先说损失函数吧。损失函数通常用于不同的任务,不同的任务有不同的损失函数。

分类和回归是深度学*的两个常见任务。 CC 下的图片来自深度学*讲座的 4.0 。

我们面临的两个最重要的任务是回归和分类。因此,在分类中,您希望为每个输入估计一个离散变量。这意味着你要在左边的两类问题中决定它是蓝点还是红点。所以,你需要建立一个决策边界的模型。

在回归中,想法是你想要建模一个解释你的数据的函数。所以,你有一些输入函数,比如说 x₂,你想用它来预测 x₁。为此,您需要计算一个函数,该函数将为任何给定的 x₂.生成适当的 x₁值在这个例子中,你可以看到这是一个直线拟合。

损失函数和最后激活函数之间的差异很重要。 CC 下的图片来自深度学*讲座的 4.0 。

我们讨论了激活函数,最后一次激活为 softmax,以及交叉熵损失。不知何故,我们把它们结合起来,很明显,我们网络中最后一个激活函数和损失函数是不同的。最后一个激活函数应用于每批中的单个样品 x。它也会在培训和测试时出现。因此,最后一个激活函数将成为网络的一部分,并保留在那里以产生输出/预测。它通常会产生一个矢量。

现在,损失函数结合了所有 M 个样本和标签。在它们的组合中,它们产生了一个损失,这个损失描述了拟合度有多好。因此,它只在训练期间出现,损失通常是一个标量值,描述拟合的好坏。所以,你只在训练时间需要它。

大多数训练损失与使用最大似然估计的概率解释有关。来自深度学*讲座CC BY 4.0 下的图片。

有趣的是,许多损失函数可以放在一个概率框架中。这就导致了最大似然估计。在最大似然估计中——提醒一下——我们认为一切都是概率性的。因此,我们有一组观察值 X ,它们由单独的观察值组成。然后,我们有相关的标签。它们也来源于某种分布,观察值表示为 Y 。当然,我们需要一个条件概率密度函数来描述 yx 之间的关系。特别是,在给定一些观察值 x 的情况下,我们可以计算出 y 的概率。这将是非常有用的,例如,如果我们想决定一个特定的类。现在,我们必须以某种方式模拟这个数据集。它们是从一些分布中提取的,然后给定数据集的联合概率可以作为单个条件概率的乘积来计算。当然,如果它们是独立的,并且分布相同,您可以简单地将它们作为整个训练数据集的大型产品。所以,你得到了所有 M 个样本的乘积,这只是条件的乘积。这很有用,因为我们可以通过最大化整个训练数据集的联合概率来确定最佳参数。我们必须通过评估这个大型产品来完成。

负对数似然将乘积转换成总和,最大值转换成最小值。来自深度学*讲座的 4.0CC 下的图片。

现在,这个大型产品有几个问题。特别是,如果我们有高值和低值,它们可能会很快抵消掉。因此,将整个问题转换到对数域可能会很有趣。因为对数是一个单调的变换,它不会改变最大值的位置。因此,我们可以使用对数函数和负号将最大化转化为最小化。我们可以不看似然函数,而是看负对数似然函数。然后,我们的大乘积突然变成了所有观测值的和乘以条件概率的负对数。

让我们假设一个单变量高斯模型作为统计基础。 CC 下的图片来自深度学*讲座的 4.0 。

现在,我们可以看看单变量高斯模型。现在我们又是一维的,可以用正态分布来建模,然后选择网络的输出作为期望值,1/β作为标准差。如果我们这样做,我们可以找到以下公式:β的平方根除以 2π的平方根乘以负β的指数函数乘以标签减去对 2 的幂的预测除以 2

只需几个步骤,我们就可以转换高斯分布的对数似然。来自深度学*讲座CC BY 4.0 下的图片。

好的,让我们继续,把它放进我们的对数似然函数。记住这是真的东西,你应该在口语考试中知道。每个人都需要知道正态分布,每个人都需要能够将这种宇宙高斯分布转换成损失函数。如果我们这样做,你会看到我们可以使用对数。它非常方便,因为它允许我们在这里分割产品。然后,我们还看到对数与指数函数相抵消。我们简单地得到这个β乘以 2 乘以 y 下标 m 减去 y hat 下标 m 的 2 次方。我们可以通过应用对数并求出平方根 2π来进一步简化第一项。然后,我们看到前两项的和不依赖于 M,所以我们可以简单地乘以 M,以便去掉和,只将和移到最后一项。

最后,我们到达 L2 损失。 CC 下的图片来自深度学*讲座的 4.0 。

现在,你可以看到,这里只有最后一部分实际上取决于 w。其他所有东西甚至都不包含 w。因此,如果我们寻求朝着 w 优化,我们可以简单地忽略前两部分。然后,我们只剩下右边的部分。你会看到,如果我们现在假设β为 1,我们最终得到的是 1/2,和是差的平方根。这正是 L2 的标准。如果你用向量符号来写,你会得到这个。当然,这相当于一个方差均匀的多维高斯分布。

其他 Lp 范数也可以作为损失函数。 CC 下的图片来自深度学*讲座的 4.0 。

好吧,这不仅仅是 L2 的损失。L1 也有损失。所以,我们也可以替换它们,我们也会在几个视频中看到不同 L 范数的一些性质。这通常是一个非常好的方法,并且它对应于最小化预期的错误分类概率。这可能会导致收敛缓慢,因为它们不会惩罚严重的错误分类概率,但在极端的标签噪声中它们可能是有利的。

对于分类,我们假设分类分布。来自深度学*讲座CC BY 4.0 下的图片。

现在,让我们假设我们想要分类。然后,我们的网络会给我们提供一些概率输出。比方说,我们只分为两类。然后,我们可以将它建模为伯努利分布,其中有 0 类和 1 类。当然另一类的概率简单来说就是一减 p 。这给了我们概率分布 p ʸ时报(1-p)⁻ʸ.通常,我们不会只有两个类。这意味着我们需要推广到多元或分类分布。那么 y 通常再次被建模为独热编码向量。然后,我们可以将分类分布记为所有类别的概率与基础事实标签的幂(零或一)的乘积。

分类分布的一个例子。 CC 下的图片来自深度学*讲座的 4.0 。

让我们看一个分类分布的例子。我们想举的例子是伯努利试验,抛硬币。我们将头部编码为(1)0)ᵀ,尾部编码为(0)1)ᵀ.然后,我们有一个不公平的硬币,这个不公平的硬币偏好概率为 0.7 的尾部。头的可能性是 0.3。然后,我们观察到真正的标签 y 是尾部。现在,我们可以使用上面的等式,并插入那些观察值。这意味着我们得到 0.3 的 0 次方和 0.7 的 1 次方。某事物的 0 次方总是等于 1。那么 0.7 的 1 次方当然是 0.7。这给了我们 0.7,这意味着我们的不公平硬币观察到尾部的概率是 70%。

使用 softmax 函数,我们总是可以将任意比例的值转换为 0 和 1。这使得分类分布能够用作损失函数。来自深度学*讲座的 4.0CC 下的图片。

我们总是可以使用网络中的 softmax 函数将一切转换成概率。现在,我们可以看看这在我们的分类分布式系统中是如何表现的。这里,我们简单地用分类分布代替条件分布。这就给了我们一个负的对数似然函数。同样,我们在这里做的与口试高度相关。因此,每个人都应该能够解释如何利用分类分布,从概率假设得出相应的损失函数。所以在这里,我们再次应用负对数似然。我们插入分类分布的定义,它就是我们所有 y 下标 k 的乘积与基础真值标签的幂。这可以进一步简化,因为乘积可以通过移动对数转换成和。如果我们这样做,你可以看到地面真理标签的力量实际上可以拉到对数前面。我们看到我们最终得到了交叉熵。现在,如果您再次使用一键编码的技巧,您可以看到,我们最终会得到交叉熵损失,即整组观察值之和乘以输出的对数,正好是基本事实标签为 1 的位置。因此,我们忽略了类和中的所有其他项。

交叉熵及其与 KL 散度的关系。 CC 下的图片来自深度学*讲座的 4.0 。

有趣的是,这也可以与 Kullback Leibler (KL)散度联系起来。KL 散度是一个非常常见的构造,你可以在许多机器学*论文中找到。在这里,你可以看到定义。本质上,我们在 x 的整个区域上有一个积分,它是对 p(x)乘以 p(x)的对数除以 q(x)的概率的积分。q(x)是要比较的参考分布。现在,您可以看到,您可以使用对数的属性将二者分成两部分。所以,我们得到了右手边的负部分,也就是交叉熵。左手边就是熵。因此,我们可以看到,这个训练过程本质上等同于最小化交叉熵。所以,为了最小化 KL 散度,我们可以最小化交叉熵。你应该记住,这种关系在机器学*论文中经常出现。所以,如果你把这些东西记在心里,你会发现它们更容易理解。

交叉熵的使用指南。来自深度学*讲座CC BY 4.0 下的图片。

现在,我们可以用交叉熵进行回归吗?嗯,是的,我们当然能做到。但是你必须确保你的预测,对于所有的类,都在[0,1]的范围内。例如,您可以使用 sigmoid 激活函数来实现这一点。那么你必须小心,因为在回归中,通常你不再是一个热编码。所以,这是你必须妥善处理的事情。如前所述,这种损失相当于最小化 KL 发散。

本单元总结。 CC 下的图片来自深度学*讲座的 4.0 。

让我们总结一下到目前为止我们所看到的。所以 L2 损失通常用于回归。交叉熵损失通常用于分类,通常与独热编码结合使用。当然,你可以从严格概率假设的最大似然估计中得到它们。所以我们现在做的完全符合概率论。在缺乏更多领域知识的情况下,这些是我们的首选。如果你有额外的领域知识,那么,当然,用它来构建一个更好的估算器是一个好主意。交叉熵损失本质上是多元的。所以,我们不仅仅被两类问题所困。我们也可以去多维回归和分类问题。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

下一次在深度学*中,我们想深入一些关于损失函数的细节,特别是,我们想强调铰链损失。这是一个非常重要的损失函数,因为它允许您嵌入约束。我们将会看到,与经典的机器学*和模式识别也有一些关系,特别是支持向量机。所以我希望你喜欢这个视频,我期待着在下一个视频中见到你!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1克里斯托弗·贝肖普。模式识别和机器学*(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[2]安娜·乔洛曼斯卡,米凯尔·赫纳夫,迈克尔·马修等人,“多层网络的损耗面”在:AISTATS。2015.
【3】Yann N Dauphin,Razvan Pascanu,卡格拉尔·古尔切赫勒等《高维非凸优化中鞍点问题的识别与攻击》。神经信息处理系统进展。2014 年,第 2933–2941 页。
4宜川唐。“使用线性支持向量机的深度学*”。载于:arXiv 预印本 arXiv:1306.0239 (2013 年)。
[5]萨尚克·雷迪、萨延·卡勒和桑基夫·库马尔。《论亚当和超越的趋同》。国际学*代表会议。2018.
[6] Katarzyna Janocha 和 Wojciech Marian Czarnecki。“分类中深度神经网络的损失函数”。载于:arXiv 预印本 arXiv:1702.05659 (2017)。
【7】Jeffrey Dean,Greg Corrado,Rajat Monga 等,《大规模分布式深度网络》。神经信息处理系统进展。2012 年,第 1223-1231 页。
[8]马人·马赫瑟雷奇和菲利普·亨宁。“随机优化的概率线搜索”。神经信息处理系统进展。2015 年,第 181–189 页。
【9】杰森·韦斯顿,克里斯·沃特金斯等《多类模式识别的支持向量机》在:ESANN。第 99 卷。1999 年,第 219-224 页。
[10]·张,Samy Bengio,Moritz Hardt 等,“理解深度学*需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。

损失和优化—第 2 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-loss-and-optimization-part-2-11b08f842aa7?source=collection_archive---------43-----------------------

FAU 讲座笔记深度学*

支持向量机打败深度学*了吗?

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

欢迎回到深度学*!那么,让我们继续我们的讲座。我们想谈谈损失和优化。今天,我们想谈谈损失函数和最优化。我想看看更多的优化问题,其中一个优化问题,我们已经在感知器案例中见过了。

感知器能够通过引入一组错误分类来优化符号激活函数。 CC 下的图片来自深度学*讲座的 4.0 。

你还记得我们最小化了所有错误分类样本的总和。我们选择这个是因为我们可以以某种方式摆脱符号函数,只查看与错误分类相关的样本。此外,请注意,这里我们没有 0/1 类别,而是-1/1,因为这允许我们与类标签相乘。这将总是导致错误分类样本中的负数。然后我们在最开始加上这个负号,这样我们总是以一个正值结束。这个正值越小,我们的损失就越小。所以,我们寻求最小化这个函数。在这个准则中,我们没有符号函数,因为我们找到了一种优雅的方式来表达这个损失函数。现在,如果它在,我们会遇到问题,因为这只会计算错误分类的数量,我们不会区分它是远离决策边界还是靠*决策边界。我们将简单地以计数结束。如果我们观察梯度,它基本上会在任何地方消失。所以这不是一个简单的优化问题。我们不知道往哪个方向走,所以找不到好的优化。上次我们是怎么做的?嗯,我们需要放松这一点,也有办法解决这个问题。

铰链损耗是符号函数的凸松弛。 CC 下的图片来自深度学*讲座的 4.0 。

一种方法是将所谓的铰链损耗包括在内。现在,有了铰链损耗,我们可以将这个 0/1 函数放宽到在一个较大的域上表现为线性。这个想法是,我们基本上使用一条线,它在 x 轴上的位置是 1,在 y 轴上的位置也是 1。如果我们这样做,我们可以简单地用 max 函数重写。因此,如果我们的值大于 1,那么铰链损耗就是所有样本之和,基本上等于 0。所以,我们不得不重写右边的部分,重新表述一下。我们取 1-y 下标 m 乘以 y hat。在这里,你可以看到我们将有相同的约束。如果我们有相反的边界,这一项将是负的,通过符号,它当然会翻转,这样我们最终会有大量的错误分类的大值。我们摆脱了必须找到误分类集 m 的问题。现在,我们可以通过使用此 max 函数来获取完整的样本集,因为满足此约束的所有内容都将自动箝位到 0。所以,它不会影响这个损失函数。因此,这是表述同一问题的一种非常有趣的方式。我们隐式地得到了在这个损失函数中只考虑误分类样本的情况。可以看出,铰链损失是我们先前考虑的误分类损失的凸*似。这类优化问题的一个重要因素当然是梯度。这个损失函数有一个拐点。因此,导数在点 x = 1 处不连续。所以不清楚导数是什么,现在你可以说:“好的,我不能计算这个函数的导数。所以,我在劫难逃了!”

如果你必须最小化导数不连续的损失函数,那么次梯度可以节省时间。 CC 下的图片来自深度学*讲座的 4.0 。

幸运的是,次梯度扭转了局面。让我们引入这个概念,为了这样做,我们来看看凸可微函数。据此,我们可以说,在任意点 f( x ,我们基本上可以找到 f( x )的一个下界,它由某个 f( x₀ )加上 f( x₀ )的梯度乘以从 xx₀ 的差来表示。那么,让我们看一个图表来展示这个概念。如果你在这里看这个函数,你可以看到我可以取任意一点 x₀ 并计算梯度,或者在这种情况下,它只是构造的切线。这样做,你会看到在切线的任何一点都将是整个函数的下限。如果我沿着切线方向,我在哪里取这个点并不重要,我总是在构造一个下界。现在,这种定义更适合我们。

次梯度允许我们计算凸函数的下界,即使它们没有连续导数。来自深度学*讲座的 4.0CC 下的图片。

所以,现在让我们扩展一下梯度,进入次梯度的方向。在次梯度中,我们定义了保持这种性质但不一定是梯度的东西。所以向量 g 是凸函数 f( x₀ )的次梯度,如果我们有相同的性质。所以,如果我们沿着次梯度方向,乘以 xx₀ 之差,那么我们总是有一个下界。这样做的好处是,我们基本上可以放松计算梯度的要求。可能有多个 g 满足这个属性。所以, g 不要求唯一。所有这些次梯度的集合称为次微分。那么次微分就是一组满足上述性质的次梯度。如果 f( x )在 x₀ 可微,我们可以简单地说,包含所有次微分的集合就是包含梯度的集合。

ReLU 的子梯度。 CC 下的图片来自深度学*讲座的 4.0 。

现在我们来看一个不成立的例子。在这个例子中,我们有一个整流线性单元(ReLU ),它也有完全相同的问题。这又是一个凸函数,这意味着在扭结点,我们可以找到很多次梯度。实际上,你看到的是绿线和红线。它们都是可行的次梯度,而且它们满足这一性质,即它们是各自函数的下界。这意味着我们现在可以定义一个次微分,我们的次微分本质上是 1,其中 x₀大于 0。我们有 0,这里它比 0 小。我们正好有 g——在位置 x₀ =0 处,g 可以是 0 到 1 之间的任何数字。这很好,因为我们现在可以基本上沿着这个次梯度方向。只是曲线的不同部分对梯度的定义不同。特别是在扭结位置,我们有这种情况,我们会有多种可能的解决方案。但是对于我们的优化,只需要知道其中一个子梯度就足够了。我们不必计算整个集合。因此,我们现在可以简单地扩展我们的梯度下降算法,以推广到次梯度。有证据表明,对于凸问题,使用次梯度理论仍然可以找到全局最小值。所以,我们现在可以说:“我们正在看的函数,它们是局部凸的。”这允许我们找到局部最小值,即使有 ReLUs 和铰链损耗。

子梯度是梯度的一种推广,它允许最小化非光滑函数。 CC 下的图片来自深度学*讲座的 4.0 。

所以,让我们总结一下:次梯度是对凸非光滑函数梯度的推广。梯度下降算法被这些函数各自的次梯度算法所取代。尽管如此,这允许我们继续我们之前对分段连续函数所做的。你只是选择了一个特定的次梯度,你可能甚至没有注意到差异。好的一面是,我们不只是把它作为一个“工程解决方案”来做,而且有一个坚实的数学理论证明这确实是可行的。因此,我们可以用它来计算 ReLU 和铰链损耗。这在数学上是合理的,我们可以继续前进,不用太担心。

不应该用支持向量机代替深度学*吗? CC 下的图片来自深度学*讲座的 4.0 。

如果人们说“哦,支持向量机(SVMs)比你正在做的要好得多,因为它们总是达到全局最小值,”会怎么样那么,使用 SVM 不是更好吗?那么,让我们来看看 SVM 实际上是做什么的。支持向量机计算最优分离超平面。它也在计算某个平面,这个平面将两个类分开,它想最大化两个集合之间的间隔。所以,你试着找到平面,或者在这个简单的例子中,产生最大余量的线。超平面或决策边界是黑线,虚线表示这里的边界。因此,SVM 试图在分离这些类时找到最大的边距。通常所做的是,你找到这个最小化问题,其中 w 是我们的超平面的法向量。然后我们最小化法向量的大小。请注意,这个法向量没有缩放,这意味着如果你增加 w 的大小,你的法向量会变长。如果你想计算带符号的距离,通常要除以法向量的大小。这意味着如果你增加这个法向量的长度,你的距离会变小。如果你想最大化距离,你可以最小化法向量的长度。显然,你可以把它压缩到零,然后你就有了无限远的距离。仅仅最小化 w 会导致平凡解 w = 0 。为了防止这种情况,你把它放在一个约束优化中,要求所有样本的所有观测值 m 都被投影到决策边界的右侧。这是由这里的约束最小化引入的。因此,您希望带符号的距离乘以真实标注减去 1,使其小于 0。

软间隔支持向量机允许轻微的误分类。 CC 下的图片来自深度学*讲座的 4.0 。

现在,我们可以把它扩展到这两类在所谓的软边缘 SVM 中不是线性可分的情况。这里的技巧是我们引入一个松弛变量ξ,它允许一个错误的分类。ξ被加到决策边界的距离上。这意味着,如果分类不正确,我可以将单个点移回决策边界。为了限制ξ的过度使用,我假设ξ都小于或等于 0。此外,我假设所有ξ的总和需要最小化,因为我希望尽可能少的错误分类。

软裕度 SVM 可以使用具有铰链损耗的目标函数来重新表达。 CC 下的图片来自深度学*讲座的 4.0 。

这就引出了软裕度 SVM 的完整公式,如果我想在联合优化中这样做,就要把它转换成拉格朗日对偶函数。为了做到这一点,你引入拉格朗日乘数λ和ν。你可以看到,上一张幻灯片中的约束现在接受乘数λ和ν。当然,还有一个额外的新 m,它是针对单个约束而引入的。现在,你看到这形成了一个相当复杂的优化问题。尽管如此,我们仍然有一个单一的拉格朗日函数,可以寻求最小化所有的 w ,ξ,λ和ν。这里引入了很多参数。我们可以稍微重新排列一下,将许多参数合并成一个总和。如果我们放弃支持向量解释,我们可以把这个和看作一个常数。因为我们知道所有的 lambdas 都大于或等于 0,这意味着所有将被错误分类或比 1 更接*决策边界的事物都将产生正损失。如果用最大值函数代替 lambda 项,会得到同样的结果。在错误分类的情况下,或者如果你在边缘区域内,优化将总是产生零或更大的值。在这个技巧中,我们通过引入 max 函数来抑制小于 0 的所有内容,即,在正确的边上和边距之外,来*似这个。现在,你可以看到,我们可以非常优雅地将它表示为铰链损耗。因此,你可以证明支持向量机和铰链损耗公式与那些约束等价于一个总的乘法常数,如参考文献1所示。如果别人说:“哦,你做不了深度学*。拿个 SVM 来代替吧!”。好吧,如果你选择了正确的损失函数,你也可以将支持向量机纳入你的深度学*框架。这实际上是一个很好的观察。

关于深度学*和支持向量机的开放点。来自深度学*讲座的 4.0CC 下的图片。

好吧,一些开放点:离群值受到线性惩罚。铰链损耗有一个变种,它对异常值的惩罚更强。举例来说,你可以通过引入正方形来实现。所以也是一个很常见的选择见参考文献4。因此,我们也可以将这种铰链损耗应用于多类问题,我们在这里引入的只是一个简单的加法,然后我们做一对多。所以,我们不只是对一个阶级进行分类,而是对一个阶级和其他阶级进行分类。这里介绍了新的分类器。最终,这会导致多级铰链损耗。

如参考文献4所示,支持向量机和深度学*是兼容的。 CC 下的图片来自深度学*讲座的 4.0 。

所以,让我们总结一下:我们已经看到,我们可以将支持向量机整合到神经网络中。我们可以用铰链损耗来实现,铰链损耗是一个损耗函数,可以放入各种约束条件。你甚至可以将强迫选择实验作为损失函数。这就是所谓的用户流失。因此,这是一个非常灵活的功能,允许你在深度学*的框架内制定各种约束优化问题。你也可以将各种约束优化放入深度学*框架中。你学*了次梯度,以及为什么我们可以处理非光滑的目标函数,这也很酷。所以这也是一个非常有用的部分,如果你遇到一个数学家,他们告诉你“哦,这里有一个弯折,你不能计算梯度!”。所以从现在开始,你说:“嘿,次梯度拯救世界!”。这样,我们只需要找到一个可能的梯度,然后它仍然有效。这真的很好。如果有人接*你说 ReLUs 在你的梯度下降程序中不合适,请查阅我们的参考资料。这是有证据的。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。来自深度学*讲座CC BY 4.0 下的图片。

下一次在深度学*中,我们想继续深入研究优化。到目前为止,我们考虑过的所有优化程序,它们只有这个η,不知何故对所有变量都是一样的。现在,我们已经看到,不同的层参数可能会有很大的不同,因此不应该一视同仁。其实这样会导致大麻烦。但是,如果你研究更高级的优化程序,他们有一些很酷的解决方案,如何自动处理不同的个体权重。敬请关注!我希望你喜欢这个讲座,并希望在下一个视频中再次欢迎你!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1克里斯托弗·贝肖普。模式识别和机器学*(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[2]安娜·乔洛曼斯卡,米凯尔·赫纳夫,迈克尔·马修等人,“多层网络的损耗面”在:AISTATS。2015.
【3】Yann N Dauphin,Razvan Pascanu,卡格拉尔·古尔切赫勒等《高维非凸优化中鞍点问题的识别与攻击》。神经信息处理系统进展。2014 年,第 2933–2941 页。
4宜川唐。“使用线性支持向量机的深度学*”。载于:arXiv 预印本 arXiv:1306.0239 (2013 年)。
[5]萨尚克·雷迪、萨延·卡勒和桑基夫·库马尔。《论亚当和超越的趋同》。国际学*代表会议。2018.
[6] Katarzyna Janocha 和 Wojciech Marian Czarnecki。“分类中深度神经网络的损失函数”。载于:arXiv 预印本 arXiv:1702.05659 (2017)。
【7】Jeffrey Dean,Greg Corrado,Rajat Monga 等,《大规模分布式深度网络》。神经信息处理系统进展。2012 年,第 1223-1231 页。
[8]马人·马赫瑟雷奇和菲利普·亨宁。“随机优化的概率线搜索”。神经信息处理系统进展。2015 年,第 181–189 页。
【9】杰森·韦斯顿,克里斯·沃特金斯等《多类模式识别的支持向量机》在:ESANN。第 99 卷。1999 年,第 219-224 页。
[10]·张,Samy Bengio,Moritz Hardt 等,“理解深度学*需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。

损失和优化—第 3 部分

原文:https://towardsdatascience.com/lecture-notes-in-deep-learning-loss-and-optimization-part-3-dc6280284fc1?source=collection_archive---------37-----------------------

FAU 讲座笔记深度学*

使用 ADAM 和超越进行优化…

FAU 大学的深度学*。下图 CC BY 4.0 来自深度学*讲座

这些是 FAU 的 YouTube 讲座 深度学* 的讲义。这是与幻灯片匹配的讲座视频&的完整抄本。我们希望,你喜欢这个视频一样多。当然,这份抄本是用深度学*技术在很大程度上自动创建的,只进行了少量的手动修改。如果你发现了错误,请告诉我们!

航行

上一讲 / 观看本视频 / 顶级 / 下一讲

到目前为止,我们认为优化主要是直接梯度下降法。 CC 下的图片来自深度学*讲座的 4.0 。

欢迎大家参加我们下一次关于深度学*的讲座!今天,我们想谈谈优化。让我们更详细地看看梯度下降法。所以,我们已经看到梯度本质上优化了经验风险。在这个图中,你可以看到我们朝着这个局部最小值前进了一步。我们有这个预定义的学*率η。因此,梯度当然是针对每个样本计算的,然后保证收敛到局部最小值。

梯度下降的不同采样策略。 CC 下的图片来自深度学*讲座的 4.0 。

当然,这意味着对于每次迭代,我们必须使用所有样本,这被称为批量梯度下降。所以你必须查看每一次迭代,每一次更新,所有的样本。可能真的有很多样本,特别是如果你看大数据一个计算机视觉的问题。这当然是凸优化问题的首选,因为我们可以保证找到全局最小值。每次更新都保证减少误差。当然,对于非凸问题,我们无论如何都有一个问题。此外,我们可能有记忆限制。这就是为什么人们喜欢其他方法,如随机梯度下降 SGD。在这里,他们只使用一个样本,然后立即更新。因此,这不再必然降低每次迭代中的经验风险,并且由于传输到图形处理单元的延迟,这也可能是非常低效的。但是,如果您只使用一个示例,您可以并行执行许多事情,因此它是高度并行的。两者之间的一个折衷是,您可以使用小批量随机梯度下降。这里你使用的 B and B 可能是一个比整个训练数据集小得多的随机样本,你实际上是从整个训练数据集中随机选择的。然后,评估子集 b 上的梯度。这称为小批量。现在,可以非常快速地评估这个小批量,您也可以使用并行化方法,因为您可以并行执行几个小批量步骤。然后,你只需做加权求和并更新。因此,小批量是有用的,因为它们提供了一种正则化效果。这通常会导致较小的η。因此,如果在梯度下降中使用小批量,通常较小的η值就足够了,而且效率也有所提高。通常,这是深度学*中的标准情况。

深度学*如此有效的可能原因。来自深度学*讲座CC BY 4.0 下的图片。

很多人都这么做,这意味着梯度下降是有效的。但问题是:“这怎么可能行得通?”我们的优化问题是非凸的。存在指数数量的局部最小值,2015 年有一篇有趣的论文,其中他们表明我们通常使用的度量是高维函数。在这个环境中有许多局部极小值。有趣的是,这些局部最小值接*全局最小值,实际上它们中的许多是等价的。更大的问题可能是鞍点。此外,局部最小值甚至可能比全局最小值更好,因为全局最小值是在您的训练集上获得的,但最终,您希望将您的网络应用于可能不同的测试数据集。实际上,训练数据集的全局最小值可能与过度拟合有关。也许,这对训练好的网络的泛化能力来说,更是雪上加霜。

过度供应可能是对深度神经网络有效性的一种回答。 CC 下的图片来自深度学*讲座的 4.0 。

对此,另一个可能的答案是 2016 年的一篇论文。作者建议过度供应,因为网络有许多不同的方式来*似期望的关系。你只需要找到一个。你不需要找到所有的人。一个就够了。梁看向艾尔通。通过随机标签实验验证了这一点。这里的想法是,你基本上随机化你不使用原始的标签。你只是随机地分配任何一个类,如果你随后表明你的实验仍然解决了问题,那么你就创造了一个过度拟合。

η的选择对成功学*至关重要。来自深度学*讲座CC BY 4.0 下的图片。

我们来看看η的选择。我们已经看到,如果你的学*速度很慢,我们甚至可能在达到收敛之前就停止了。如果你有一个太大的学*率,我们可能会来回跳跃,甚至找不到局部最小值。只有有了适当的学*率,你才能找到最小值。实际上,当你远离最小值时,你希望能够大步前进,而当你越接*最小值时,就越是小步前进。如果你想在实践中这样做,你的工作与学*率的衰减。所以,你要逐渐适应你的η。你从 0.01 开始,然后每 x 个周期除以 10。这有助于您不会错过您实际寻找的本地最小值。这是一个典型的实际工程参数。

我们能去掉我们的“工程参数”η吗? CC 下的图片来自深度学*讲座的 4.0 。

现在,你可能会问我们不能摆脱这个魔法吗?那么通常会怎么做呢?相当多的人建议在类似情况下进行线搜索。所以,线搜索,当然需要你估计每一步的最优η。所以,你需要多次求值,以便在梯度指向的方向上找到正确的η。反正是吵的不得了。所以,人们已经提出了方法,但它们不是深度学*领域目前的最先进水平。然后,人们提出了二阶方法。如果研究二阶方法,需要计算 Hessian 矩阵,这通常非常昂贵。到目前为止,我们还没有经常看到这种情况。有 L-BFGS 方法,但是如果您在批次设置之外操作,它们通常不会很好地执行。所以,如果你使用小批量,它们就没那么好了。你可以在参考文献[7]中找到谷歌的一份报告。

我们能使用持续方向改善我们的噪音梯度下降吗?来自深度学*讲座CC BY 4.0 下的图片。

我们还能做什么?当然,我们可以加速持续梯度的方向。所以,这里的想法是,你以某种方式跟踪平均值,这里用 new v 表示。这实质上是最后几个梯度步骤的加权和。你把当前的梯度方向用红色表示,并与前面的步骤平均。这给了你一个更新的方向,这通常被称为动量。

动量项的正式定义。来自深度学*讲座CC BY 4.0 下的图片。

所以,我们引入了动量项。在那里,你用一个新的权重添加了一些动量,用 v 上标 k-1 表示。这个动量项基本上是以迭代的方式计算的,其中你迭代地更新过去的梯度方向。所以你可以说,通过迭代计算这个加权平均值,你保留了之前梯度方向的历史,然后用新的梯度方向逐渐更新它们。然后你选择动量项来执行更新,而不仅仅是梯度方向。因此,μ的典型选择为 0.9、0.95 或 0.99。如果你想让他们更加强调之前的渐变方向,你也可以从小到大调整他们。这克服了随机梯度下降中的不良 Hessians 和方差。它将抑制振荡,并且通常加速优化过程。尽管如此,我们还是需要学*率衰减。所以,这并没有解决η的自动调节。

内斯特罗夫动量试图预测动量项。 CC 下的图片来自深度学*讲座的 4.0 。

我们也可以选择一种不同的动量方式:内斯特罗夫加速梯度或简单的内斯特罗夫动量。这执行了一个前瞻。这里,我们也有动量项。但是我们没有计算当前位置的梯度,而是在计算梯度之前加入了动量项。所以,我们实际上是在试图逼*下一组参数。我们在这里使用前瞻,然后我们执行梯度更新。所以你可以重写这个来使用传统的渐变。这里的想法是将内斯特罗夫加速度直接放入梯度更新中。这一项将用于下一次梯度更新。所以,这是一个等价的公式。

动量和内斯特罗夫动量相比较。 CC 下的图片来自深度学*讲座的 4.0 。

让我们想象一下。在这里,你可以看到动量和内斯特罗夫动量。当然,它们都使用了一种动量项。但是它们使用不同的方向来计算梯度更新。这是最主要的区别。

在这个例子中,你可以看到内斯特罗夫动量项的强度。来自深度学*讲座CC BY 4.0 下的图片。

在这里,你可以看到这些动量项的对比例子。在这种情况下,两个方向的方差都有很大的差异。因此,左右方向的方差非常大,上下方向的方差相当小。我们试图找到全局最小值。即使你引入动量项,这通常会导致梯度方向非常强烈的交替。你仍然会得到这种强烈的振荡行为。如果你使用内斯特罗夫加速梯度,你可以看到我们计算这个前瞻,这允许我们沿着蓝线。所以,我们直接向期望的最小值移动,不再交替。这是内斯特罗夫的优势。

一些参数的更新可能与其他参数不同。 CC 下的图片来自深度学*讲座的 4.0 。

如果我们的功能有不同的需求呢?因此,假设一些特性很少被激活,而另一些特性经常被更新。然后,我们需要网络中每个参数的单独学*率。对于不频繁的参数,我们需要大的学*率,对于频繁的参数,我们需要小的学*率。

AdaGrad 为每个参数引入了单独的缩放。来自深度学*讲座的 4.0CC 下的图片。

为了适当地适应变化,这可以用所谓的 AdaGrad 方法来完成。它首先使用梯度来计算某个 g 上标 k,然后计算梯度与其自身的乘积,以跟踪变量 r 中的元素方差。现在,我们使用我们的 gr 元素与η组合来衡量梯度的更新。因此,现在我们构建更新的权重,并且每个参数中权重的方差通过乘以相应元素的平方根来合并,即其标准偏差的*似值。所以,这里我们把它记为一个完整矢量的平方根。这里所有其他的东西都是标量,这意味着这也产生了一个矢量。然后,该向量逐点乘以实际梯度,以执行局部缩放。这是一个很好且有效的方法,并且允许对所有不同权重的所有不同维度的个体学*率。一个问题可能是学*率下降过快。

RMSProp 建立在 AdaGrad 的基础上。 CC 下的图片来自深度学*讲座的 4.0 。

这是一个问题,并导致了一个改进的版本,这里的改进版本是 RMSProp。RMSProp 现在再次使用它,但他们引入了这个ρ,现在ρ被用来引入一个延迟,这样就不会有很高的增加。在这里,您可以设置这个ρ,以便抑制学*率方差的更新。所以,Hinton 建议 0.9,η = 0.001。这一转变导致积极减少被固定,但是我们仍然必须设置学*率。如果你没有适当地设置学*速度,你就会遇到问题。

阿达德尔塔除掉了η。来自深度学*讲座的 4.0CC 下的图片。

现在,Adadelta 试图在此基础上进一步改进。他们实际上使用了我们的 RMSProp 并去掉了η。我们已经看到了 r,它是以一种阻尼方式计算的方差。然后,另外,他们介绍这个δₓ.它是某项 h 和 r 的加权组合,我们之前已经看到,乘以梯度方向。因此,这是一个额外的阻尼因子,代替了原始公式中的η。因子 h 被再次计算为δₓ上的滑动平均值,作为元素间的乘积。所以,这样你就不用再设定学*率了。还是要选择参数ρ。对于ρ,我们建议使用 0.95。

Adam 使用来自深度学*讲座CC 下的 4.0 的额外动量项 v. Image 构建 Adadelta。

正在使用的最流行的算法之一是 Adam,Adam 本质上也在使用这个梯度方向 g 。然后,你基本上有一个动量项 v 。此外,你还有这个 r 术语,它再次试图单独控制每个维度的学*速率。此外,Adam 引入了额外的偏置校正,其中 v1 减μ的比例缩放。 r 也是 11 减ρ缩放。这就导致了最终的更新项,它包括学*率η、动量项和相应的缩放比例。这种算法叫做 Ada 感受性 M 矩估计。对于 Adam,建议值为μ = 0.9,ρ = 0.999,η= 0.001。这是一种非常稳健的方法,并且非常常用。我们可以把它和内斯特罗夫加速梯度结合起来,得到“那达慕”。但是,你仍然可以改进这一点。

AMSGrad 修复了 Adam 中的收敛问题。 CC 下的图片来自深度学*讲座的 4.0 。

根据经验观察,Adam 无法收敛到最优/良好的解决方案。在参考文献[5]中,你甚至可以看到,对于凸问题,Adam 和类似的方法并不能保证收敛。在最初的收敛证明中有一个错误,因此,我们建议使用修正 Adam 的 AMSGrad 来确保不增加步长。所以,你可以通过在动量更新项上增加一个最大值来修正它。所以如果你这样做,你会得到 AMSGrad。这被证明是更加鲁棒的。这种效果已经在大型实验中得到证实。我们在这里学到的一个教训是,你应该睁大眼睛。即使是经过科学同行评审的东西,也可能存在后来被发现的问题。我们在这里学到的另一件事是,这些梯度下降程序——只要你大致遵循正确的梯度方向——你仍然可以得到相当不错的结果。当然,这样的梯度方法真的很难调试。所以,一定要调试你的渐变。正如您在本例中看到的,这种情况确实会发生。即使是大型软件框架也可能遭受这样的错误。很长一段时间,人们都没有注意到他们。他们只是注意到奇怪的行为,但问题依然存在。

今天讲座的总结。 CC 下的图片来自深度学*讲座的 4.0 。

好了,让我们总结一下。随机梯度下降加内斯特罗夫动量加学*率衰减是许多实验中的典型选择。它收敛最可靠,并在许多先进的论文中使用。然而,它的问题是,这种学*率衰减必须加以调整。亚当有个人学*率。学*率表现很好,但当然,损失曲线很难解释,因为你不会有固定学*率下的典型行为。我们在这里没有讨论,我们只是暗示了分布式梯度下降。当然,您也可以以并行方式执行此操作,然后在分布式网络的不同节点或不同的图形板上计算不同的更新步骤。然后你把它们平均起来。这也被证明是非常健壮和非常快速的。

对你工作的实用建议。来自深度学*讲座CC BY 4.0 下的图片。

一些实用的建议:从使用带动量的小批量随机梯度下降开始。坚持默认的势头。当你对你的数据有感觉的时候,给亚当一个尝试。当你发现你需要单独的学*速率时,Adam 可以帮助你获得更好或更稳定的收敛。您也可以切换到 AMSGrad,这是对 Adam 的改进。当然,首先开始调整学*速度,然后留意异常行为。

在这个深度学*讲座中,更多令人兴奋的事情即将到来。 CC 下的图片来自深度学*讲座的 4.0 。

好了,这让我们对接下来的几个视频有了一个简短的展望,以及我们要做的事情。当然实际的深度学*部分,到目前为止我们根本没有讨论过这个。因此,我们仍然需要讨论的一个问题是,我们如何处理空间相关性和特征。我们经常听到卷积和神经网络。下次我们将看到为什么这是一个好主意,它是如何实现的。当然,我们应该考虑的一件事是如何使用方差,以及如何将它们合并到网络架构中。

可能有助于备考的问题。来自深度学*讲座CC BY 4.0 下的图片。

一些综合问题:“我们分类回归的标准损失函数是什么?”当然,L2 用于回归,交叉熵损失用于分类。你应该能推导出这些。这真的是你应该知道的事情,因为统计数据及其与学*损失的关系真的很重要。统计假设,概率理论,以及如何修改这些来得到我们的损失函数,都与考试高度相关。次微分也很重要。“什么是次微分?”"在我们的激活函数出现拐点的情况下,我们如何优化?"“铰链损耗是多少?”"我们如何合并约束?"尤其是“对于那些声称我们所有的技术都不好,因为 SVM 更好的人,我们该怎么说?”你总是可以证明,它取决于一个乘法常数,就像使用铰链损耗一样。“什么是内斯特罗夫势头?”如果有人在不久的将来会问你关于你在这里学到的东西的问题,你应该能够解释这些非常典型的事情。当然,我们又有大量的参考资料(见下文)。我希望你也喜欢这次讲座,我期待着在下一次讲座中见到你!

如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激你在 YouTube、Twitter、脸书、LinkedIn 上的鼓掌或关注。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。

参考

1克里斯托弗·贝肖普。模式识别和机器学*(信息科学和统计学)。美国新泽西州 Secaucus 出版社:纽约斯普林格出版社,2006 年。
[2]安娜·乔洛曼斯卡,米凯尔·赫纳夫,迈克尔·马修等人,“多层网络的损耗面”在:AISTATS。2015.
【3】Yann N Dauphin,Razvan Pascanu,卡格拉尔·古尔切赫勒等《高维非凸优化中鞍点问题的识别与攻击》。神经信息处理系统进展。2014 年,第 2933–2941 页。
4宜川唐。“使用线性支持向量机的深度学*”。载于:arXiv 预印本 arXiv:1306.0239 (2013 年)。
[5]萨尚克·雷迪、萨延·卡勒和桑基夫·库马尔。《论亚当和超越的趋同》。国际学*代表会议。2018.
[6] Katarzyna Janocha 和 Wojciech Marian Czarnecki。“分类中深度神经网络的损失函数”。载于:arXiv 预印本 arXiv:1702.05659 (2017)。
【7】Jeffrey Dean,Greg Corrado,Rajat Monga 等,《大规模分布式深度网络》。神经信息处理系统进展。2012 年,第 1223-1231 页。
[8]马人·马赫瑟雷奇和菲利普·亨宁。“随机优化的概率线搜索”。神经信息处理系统进展。2015 年,第 181–189 页。
【9】杰森·韦斯顿,克里斯·沃特金斯等《多类模式识别的支持向量机》在:ESANN。第 99 卷。1999 年,第 219-224 页。
[10]·张,Samy Bengio,Moritz Hardt 等,“理解深度学*需要反思泛化”。载于:arXiv 预印本 arXiv:1611.03530 (2016)。

神经单词嵌入的法律应用

原文:https://towardsdatascience.com/legal-applications-of-neural-word-embeddings-556b7515012f?source=collection_archive---------35-----------------------

探索法律领域中的词语嵌入

来源:谷歌开发者

LegalTech 的一个基本问题是,文字——所有法律文件的基本货币——是一种机器无法直观理解的非结构化数据形式。因此,为了处理文本文档,单词必须用实数向量来表示。

传统上,像单词袋(BoW)这样的方法将单词标记/n 元语法映射到术语频率向量,术语频率向量表示单词在文档中出现的次数。使用一键编码,每个单词标记/n 元语法由一个向量元素表示,并根据单词在文档中是否出现或出现的次数标记为 0、12 等。这意味着,如果一个单词在语料库词汇表中不存在,该元素将被标记为 0,如果它存在一次,该元素将被标记为 1,依此类推。

来源:分析步骤

问题是这产生了非常高维度的非常稀疏的矩阵(即大部分包含零)。例如,具有 30,000 个唯一单词标记的语料库将需要具有 30,000 行的矩阵,这在计算上是极其繁重的。此外,这种方法不能捕捉语义、上下文和单词关系,因为它只能显示单词在文档中出现的频率。这种无法表示语义的情况持续存在,即使 BoW 由 TF-IDF 度量补充,因为虽然后者能够表示单词对语料库有多重要的度量(即,相对于普通 BoW 表示的改进),但它仍然是基于单词令牌/n-gram 在语料库中出现的频率来计算的。

相比之下,现代单词嵌入(word2vec、GloVE、fasttext 等)依赖于神经网络来将单词的语义属性映射到维度明显更少的密集向量表示中。

首先,应该说单词嵌入是以分布语义假设为前提的,即在相同的上下文中使用和出现的单词往往具有相似的含义。这意味着神经网络通过单词所在的上下文来学*单词的矢量表示。

这里的“上下文”由大小为 n 的滑动上下文窗口表示,其中目标单词之前的 n 个单词和目标单词之后的 n 个单词将落入上下文窗口内(例如,在该示例中 n =2)。然后,当上下文窗口沿着句子向下移动时,该模型将通过使用一个热点编码的上下文向量来训练,以预测一个热点编码的目标向量。

在这样做的时候,单词嵌入可以捕获 BoW 没有捕获到的语义关联和语言上下文。本文将探讨法律人工智能技术中神经单词嵌入的影响。

捕捉法律术语之间的关系

单词嵌入的一个重要含义是它捕获了单词之间的语义关系。

  1. 具有相似含义和上下文的单词将在向量空间中占据更*的空间位置,如余弦相似性所测量的。这些词向量也可以相加或相乘,而不会失去它们固有的语义特征和关系。
  2. 编码单词之间的矢量差也可以表示单词之间的关系。例如,在“男人是国王,女人是王后”中的单词关系可以用 vec(国王)-vec(男人)+ vec(女人)= vec(王后)来表达。在法律领域,Ash (2016 年)同样表明,公司税和所得税之间的关系可以通过 vec(公司所得税)-vec(公司)+ vec(个人)= vec(个人所得税)来描述。

描绘出法律术语和对象之间的关系的能力在提高我们对法律推理的理解的能力方面具有令人兴奋的含义。一个有趣的方向是利用 doc2vec 对司法意见进行潜在的矢量化,以识别/聚类具有相似信念模式的法官(基于法律意见的保守性、引用的判例等)。

另一个功能是,词嵌入可以捕捉司法意见中隐含的种族和性别偏见,这是通过词嵌入联想测试(WEAT)来衡量的。单词嵌入是强大的,因为它们可以用数学或图表的形式表现社会偏见。例如,Bolukbasi (2016 年)表明,在谷歌新闻文章上训练的单词嵌入表现出显著的性别偏见,这可以通过单词嵌入的方向以几何方式捕获(即,性别中立的单词可以与性别中立的单词线性分离)。

来源:https://www . semantic scholar . org/paper/Man-is-to-Computer-Programmer-as-Woman-is-to-Word-Bolukbasi-Chang/CCF 6a 69 a 7 f 33 BCF 052 a 7 def 176d 3 b 9 de 495 beb 7)

因此,单词嵌入可以反映向量关系,如“男人对于程序员,就像女人对于家庭主妇”,因为单词“男人”在谷歌新闻语料库中更频繁地与单词“程序员”或“工程师”一起出现,而单词“女人”将更频繁地出现在“家庭主妇”或“护士”旁边。

应用于法律领域,我们可以将司法意见的 WEAT 分数制成表格,该领域的初步研究显示了有趣的趋势,例如(I)男性法官比女性法官显示出更高的性别偏见(即更高的 WEAT 分数),以及(ii)白人法官比黑人法官显示更低的种族偏见。在这一领域还有更多有待探索。

提高法学研究

来源:http://mlwiki.org/index.php/Information_Retrieval

单词嵌入对于改进法律研究平台(在机器学*术语中称为法律信息检索(LIR)系统)背后的技术也具有根本性的意义。

目前,大多数 LIR 系统(如 Westlaw 和 LexisNexis)仍然是主要利用关键字搜索功能的布尔索引系统。

这意味着系统通常通过使用基于字符串的算法来测量两个文本字符串之间的相似性,来寻找查询关键字的文字匹配或变体。然而,这些类型的搜索无法理解律师查询背后的意图,这意味着搜索结果通常包含不足(即,缺少不包含关键字的相关信息,但可能是其变体)或包含过度(即,返回包含关键字的不相关信息)。

然而,单词嵌入增强了商用语义搜索 LIR 的潜力。因为它允许从业者以数学方式捕捉语义相似性,所以单词嵌入可以帮助 LIR 系统找到不仅是查询字符串的精确匹配的结果,而且是可能相关或语义接*但在某些单词上不同的结果。

来源:https://www . onto text . com/knowledge hub/fundamentals/what-is-semantic-search/

例如,Landthaler 表明,有效的结果可以通过首先将每个搜索短语中的单词向量相加为一个搜索短语向量来产生。然后,通过大小为 n (其中 n =搜索短语中的字数)的窗口顺序解析该文档,并且计算搜索短语向量和累积向量的余弦相似度。这不仅能够返回精确的关键字匹配结果,还能够返回语义相关的搜索结果,从而提供更直观的结果。

来源:https://www . law technology today . org/2017/11/legal-consumer-research/

这一点尤其重要,因为研究表明,使用布尔索引搜索 LIR 系统(在全文法律文档中搜索查询术语的精确匹配)的参与者的召回率可能低至 20%(即,LIR 仅检索到 20%的相关文档)。然而,平均而言,这些参与者估计他们的检索率高达 75%,这要高得多。这意味着律师经常会忽略可能支持他们案件的相关先例或判例法,只是因为 LIR 系统将字符串相似性置于语义相似性之上。因此,单词嵌入具有显著解决这一不足的潜力。

结论与未来走向

总的来说,神经单词嵌入的领域是迷人的。不仅从数学上捕捉语义上下文和单词关系的能力在学术上引人入胜,单词嵌入也是市场上许多法律技术产品背后的一个非常重要的驱动力。

然而,单词嵌入不是没有限制的,ML 实践者有时转向更新的预训练语言建模技术(例如,ULMFit、ELMo、OpenAI transformer 和 BERT)来克服单词嵌入的一些固有问题(例如,假设单义)。尽管如此,词嵌入仍然是当今最吸引人的 NLP 主题之一,从稀疏的、基于频率的向量表示向更密集的语义表示向量的转变是推进 NLP 子域和法律人工智能领域的关键一步。

使用深度学*的乐高迷你人物性别分类

原文:https://towardsdatascience.com/lego-minifigure-gender-classification-using-deep-learning-2358f4082842?source=collection_archive---------68-----------------------

实践教程

与 CNN 的和转移学*

詹姆斯·庞德Unsplash 上拍摄的照片

通过我在 Udacity 的深度学*纳米学位的卷积神经网络(CNN)部分的工作旅程,我决定从事我自己的项目,看看 CNN 是否能够对乐高迷你人物的性别进行分类。

我决定这样做的原因是因为我是一个乐高迷,多年来一直在收集迷你玩具。我想我现在有超过 200 个小家伙,大部分是从盲袋中获得的。

哦,我还拍了他们的照片,分享到 Instagram 上!

Instagram: @Let_It_Lego

为什么要用迁移学*?

迁移学*是指使用预先训练好的神经网络,并将其用于不同的数据集。

由于我有一个小数据集,我想利用 ImageNet 的预训练图像,因为它有许多人和衣服的照片,所以应该更容易确定迷你人物的特征。由于人体特征和迷你人物服装的相似性,我会将我的数据集归类为与 ImageNet 中的相似。

根据 Udacity 的说法,如果新数据集很小,并且与原始训练数据相似,则必须按如下方式更改神经网络:

  • 切掉神经网络的末端
  • 添加与新数据集中的类数量相匹配的新完全连接图层
  • 随机化新的全连接层的权重;冻结预训练网络的所有权重(以避免过度拟合)
  • 训练网络以更新新的全连接层的权重

在神经网络的末端添加并训练全连接层。资料来源:Udacity

您将在后面的代码中看到我是如何做到这一点的。

收集数据

我给我自己的迷你人像拍了照片来组成数据集。由于我只有有限的数量(超过 200 张),我从不同的角度拍摄了每个迷你人像的照片,以便为数据集获取更多的照片。

为了确保 CNN 不会接触到不容易区分男性和女性的物品,我确保脱下了迷你人佩戴的任何配饰,比如这些:

斗篷,服装,怪异的帽子,等等。

我也没有包括像这些人一样不是人类的迷你人:

海绵宝宝!

最后,我的数据集看起来像这样:

照片数据集的片段。

代码

我首先在库中加载:

%matplotlib inline
%config InlineBackend.figure_format = 'retina'import matplotlib.pyplot as plt
import numpy as np
import torch
from torch import nn
from torch import optim
import torch.nn.functional as F
from torchvision import datasets, transforms, models

并检查了 Cuda 是否可用,以便我可以利用谷歌 Colab 的 GPU。

train_on_gpu = torch.cuda.is_available()if not train_on_gpu:
    print('CUDA is not available.  Training on CPU ...')
else:
    print('CUDA is available!  Training on GPU ...')

加载和转换数据集

我将完成的数据集作为 zip 文件保存到 Dropbox 中,其中的内容被拆分到一个 Train/Test 文件夹中,另一个 Boy/Girl 文件夹位于其中。

然后我生成了一个下载链接,这样我就可以使用!wget!unzip将图片加载到 Google Colab 中。

由于我拍摄的图像尺寸很大,我需要对它们进行转换,以便输入数据可以与预先训练的模型所期望的(在我的例子中,是 VGG16)一起工作。我还使用了 PyTorch 的 ImageFolder 类,以便能够从我在 zip 文件中创建的 train 和 test 文件夹中加载数据。

data_dir = 'Lego (compressed pics)'# VGG-16 Takes 224x224 images as input, so we resize all of them
data_transform = transforms.Compose([transforms.Resize((224, 224)),
                                     transforms.ToTensor()])train_data = datasets.ImageFolder(data_dir + '/Train',              
transform=data_transform)test_data = datasets.ImageFolder(data_dir + '/Test',             
transform=data_transform)

在这里你可以看到我是如何将照片分配到一个训练和测试集的。

训练和测试图像的数量。

为训练和测试数据集创建数据加载器:

# how many samples per batch to load
batch_size = 20# number of subprocesses to use for data loading
num_workers = 0train_loader = torch.utils.data.DataLoader(train_data, 
batch_size=batch_size, num_workers=num_workers, shuffle=True)test_loader = torch.utils.data.DataLoader(test_data, 
batch_size=batch_size, num_workers=num_workers, shuffle=True)# specify the image classes
classes = ['Boy', 'Girl']

现在我们来可视化一批训练数据。

# obtain one batch of training images
dataiter = iter(train_loader)
images, labels = dataiter.next()
images = images.numpy()  # convert images to numpy for display# plot the images in the batch, along with the corresponding labels
fig = plt.figure(figsize=(25,4))
for idx in np.arange(20):
  ax = fig.add_subplot(2, 20/2, idx+1, xticks=[], yticks=[])   
  plt.imshow(np.transpose(images[idx], (1, 2, 0)))   
  ax.set_title(classes[labels[idx]])

可视化一批训练数据。

定义模型

这将通过加载预训练的 VGG16 模型来实现。

# Load the pretrained model from PyTorch
vgg16 = models.vgg16(pretrained=True)# Freeze training for all feature layers so the model doesn't change # the parameters it was pre-trained on
for param in vgg16.features.parameters(): 
    param.requires_grad = False

如前所述,预训练模型的分类器不符合我们试图实现的目标,因为它的最后一层输出 1000 个特征,而我们只需要 2 个(因为我们只有男孩和女孩两个类)。

所以我们需要去掉最后一层,用我们自己的线性分类器代替它。

n_inputs = vgg16.classifier[6].in_features
last_layer = nn.Linear(n_inputs, len(classes))vgg16.classifier[6] = last_layerif train_on_gpu:
    vgg16.cuda()

现在分类器就是我们想要的了!

指定损失函数和优化器。

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(vgg16.classifier.parameters(), lr=0.001)

训练网络

训练网络。

测试

下面,您可以看到通过对以前看不到的数据测试训练模型来确定每个性别类别的准确性。换句话说,我们使用训练好的模型来预测迷你人的性别,并将其与实际性别(目标)进行比较。

确定测试精度。

可视化测试结果

可视化样本的测试结果。

样本结果!

结论

结果似乎相当不错!在测试的 20 幅样本图像中,只有一幅预测了错误的性别。请记住,我只使用了一个小数据集,所以如果我有一个更大的数据集,结果可能会改变。

如果你有兴趣更详细地阅读我的代码,请访问下面我的 Github。

[## oscarkwok/乐高-性别

GitHub 是超过 5000 万开发者的家园,他们一起工作来托管和审查代码,管理…

github.com](https://github.com/oscarkwok/Lego-Gender/blob/main/Classifying_Lego_Minifigure_Gender.ipynb)

这是一个有趣的项目,我能够应用我从 Udactiy 的深度学*纳米学位中学到的东西。随着课程的进展,我希望能写更多关于我的项目,敬请关注!

如果您有任何问题或意见,请在下面留下您的反馈。你也可以在 Linkedin 上关注我,或者在这里与我联系。

posted @ 2024-10-15 13:41  绝不原创的飞龙  阅读(727)  评论(0)    收藏  举报