TowardsDataScience-博客中文翻译-2020-一百零三-

TowardsDataScience 博客中文翻译 2020(一百零三)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

亚马逊美食评论的情感分析:从 EDA 到部署

原文:https://towardsdatascience.com/sentiment-analysis-on-amazon-food-reviews-from-eda-to-deployment-f985c417b0c?source=collection_archive---------24-----------------------

Unsplash 上由 Ayesha Firdaus 拍摄的照片

Amazon.com 公司是一家总部位于华盛顿州西雅图市的美国跨国科技公司。亚马逊专注于电子商务、云计算、数字流媒体和人工智能。由于他们在电子商务平台上实力雄厚,他们的评论系统可能会被卖家或客户滥用,他们会撰写虚假评论来换取激励。手动检查每一篇评论并标注其观点是昂贵的。因此,更好的方法是依靠机器学习/深度学习模型。在本案例研究中,我们将关注亚马逊上的 美食评论数据集 ,该数据集可在 Kaggle 上获得。

注意:本文不是对我们问题的代码解释。相反,我将解释我使用的方法。你可以从 这里 看我的代码。

关于数据集

该数据集由亚马逊超过 10 年的美食评论组成,包括截至 2012 年 10 月的 568,454 条评论。评论包括评级、产品和用户信息以及纯文本评论。它还包括所有其他亚马逊类别的评论。

我们有以下栏目:

  1. 产品 Id:产品的唯一标识符
  2. 用户 Id:用户的唯一标识符
  3. 配置文件名称:用户的配置文件名称
  4. 有用性分子:认为评论有用的用户数量
  5. 有用性分母:表示他们认为评论是否有用的用户数量
  6. 分数:评分在 1 到 5 之间
  7. 时间:时间戳
  8. 摘要:审查摘要
  9. 文本:评论

目标

给出一个评价,确定该评价是正面的(评分为 4 或 5)还是负面的(评分为 1 或 2)。

如何确定一个点评是正面还是负面?

我们可以使用分数/评级。评分为 4 或 5 可视为正面评价。评级为 1 或 2 可被视为负面评级。评级为 3 的审查被认为是中性的,此类审查在我们的分析中被忽略。这是一种确定评论极性(积极/消极)的近似和代理方式。

探索性数据分析

基本预处理

作为基本数据清理的一步,我们首先检查任何丢失的值。幸运的是,我们没有任何缺失值。接下来,我们将检查重复条目。经过分析,我们发现对于不同的产品,同一用户在同一时间给出了相同的评论。实际上这没有意义。所以我们将只保留第一个,删除其他重复的。

重复条目的示例:

数据

现在我们的数据点减少到 69%左右。

分析评论趋势

回顾趋势

  • 从 2001 年到 2006 年,审查的次数是一致的。但之后,评论的数量开始增加。在这些评论中,许多评论的五星评级都很高。也许这是未经核实的帐户,以虚假评论不适当地提升卖家。另一个原因可能是由于用户帐户数量的增加。

分析目标变量

如前所述,我们将所有高于等级 3 的数据点指定为正类,低于等级 3 的数据点指定为负类。我们将忽略其余的要点。

目标

观察:很明显,我们的分类数据集不平衡。所以我们不能选择准确性作为衡量标准。所以这里我们将使用 AUC(ROC 曲线下面积)

为什么不平衡数据集的准确性不行?

考虑这样一个场景,我们有一个不平衡的数据集。例如,考虑信用卡欺诈检测的情况,其中 98%的点数为非欺诈(1),其余 2%的点数为欺诈(1)。在这种情况下,即使我们预测所有的点都是非欺诈的,我们也将获得 98%的准确性。但事实并非如此。所以我们不能用准确性作为衡量标准。

什么是 AUC ROC?

AUC 是 ROC 曲线下的面积。它告诉我们这个模型在多大程度上能够区分不同的类。AUC 越高,模型预测 0 为 0 和 1 为 1 的能力越强。用 TPR 对 FPR 绘制 ROC 曲线,其中 TPR 在 y 轴上,FPR 在 x 轴上。

分析用户行为

用户行为

  • 在分析了用户带来的产品数量后,我们知道大多数用户都只带了一种产品。
  • 另一件要注意的事情是,有用性分母应该总是大于分子,因为有用性分子是认为评论有用的用户数量,而有用性分母是表示他们认为评论是否有用的用户数量。有一些数据点违背了这一点。所以我们去掉这些点。

在我们的预处理之后,数据从 568454 减少到 364162。也就是说,大约 64%的数据仍然存在。现在让我们进入我们的重要部分。正在处理审阅数据。

预处理文本数据

在我们进一步分析和建立预测模型之前,文本数据需要一些预处理。因此,在预处理阶段,我们按以下顺序执行以下操作

  • 从移除 Html 标签开始。
  • 删除任何标点符号或有限的一组特殊字符,如、或。或者#!等等。
  • 检查单词是否由英文字母组成,并且不是字母数字
  • 将单词转换成小写
  • 最后,删除停用词

列车测试分离

一旦我们完成预处理,我们将把数据分成训练和测试。我们将在根据时间对数据排序后进行拆分,因为时间的变化会影响评论。

向量化文本数据

之后,我应用了 bow 矢量化、tfidf 矢量化、average word2vec 和 tfidf word2vec 技术来描述我们的文本,并将它们保存为单独的矢量。由于对大量数据进行矢量化是很昂贵的,所以我计算了一次并存储起来,这样我就不想一次又一次地重新计算了。

注意:我对单词包和 tfidf 使用了一种单字方法。在 word2vec 的情况下,我训练了模型,而不是使用预先训练好的权重。对于 bow/tfidf,您总是可以尝试使用 n-gram 方法,并且可以在 word2vec 的情况下使用预先训练的嵌入。

您应该始终尝试根据训练数据来拟合您的模型,并根据测试数据来转换它。不要试图在测试数据上安装矢量器,因为这会导致数据泄漏问题。

TSNE 可视化

代表 t 分布随机邻居嵌入的 TSNE 是最流行的降维技术之一。它主要用于较低维度的可视化。在进入机器学习模型之前,我试图在更低的维度上可视化它。

TSNE

我在 TSNE 遵循的步骤:

  • 保持困惑不变,我在不同的迭代中运行 TSNE,找到了最稳定的迭代。
  • 现在保持迭代不变,我在不同的困惑下运行 TSNE,以获得更好的结果。
  • 一旦我得到了稳定的结果,用同样的参数再次运行 TSNE。

但是我发现 TSNE 不能很好地分离低维的点。

注:我用随机的 20000 分(平均等级分布)试了试 TSNE。大量数据点可能会改善结果

机器学习方法

朴素贝叶斯

如果我们有一个基线模型来评估,在机器学习中总是更好。我们将从创建一个朴素贝叶斯模型开始。对于朴素贝叶斯模型,我们将拆分数据进行训练、cv 和测试,因为我们使用的是手动交叉验证。最后,我们在 bow 特征和 tfidf 特征上尝试了多项式朴素贝叶斯。在超参数调优之后,我们以下面的结果结束。

朴素贝叶斯

我们可以看到,在这两种情况下,模型都有点过度拟合。别担心,我们也会尝试其他算法。

逻辑回归

由于算法很快,我很容易在 12gb 内存的机器上训练。在这种情况下,我只将数据分为训练和测试,因为 grid search cv 进行内部交叉验证。最后,我对 bow 特性、tfidf 特性、平均 word2vec 特性和 tfidf word2vec 特性进行了超参数调优。

逻辑回归

尽管 bow 和 tfidf 特征在测试数据上给出了更高的 AUC,但是模型稍微有些过度拟合。平均 word2vec 特征使模型更一般化,在测试数据上 AUC 为 91.09。

avg-word2vec 上的性能指标逻辑回归

支持向量机

接下来,我尝试了 SVM 算法。我尝试了线性 SVM 和 SVM 径向基函数。SVM 在处理高维数据时表现良好。具有平均 word2vec 特征的线性 SVM 产生了更一般化的模型。

SVM

平均 word2vec 上的性能指标线性 SVM

决策树

尽管我们已经知道这种数据很容易在决策树上过度拟合,但我只是尝试了一下,看看它在基于树的模型上表现如何。

在超参数调优之后,我得到了下面的结果。我们可以看到,与逻辑回归、朴素贝叶斯和 SVM 相比,模型过拟合,决策树的性能较低。我们可以通过使用像成本复杂性修剪这样的后期修剪技术在一定程度上克服这个问题,或者我们可以在它上面使用一些集成模型。在这里,我决定使用像 random forest 和 XGboost 这样的集合模型,并检查性能。

决策树

随机森林

对于随机森林,我们可以看到测试的 AUC 增加了。但是,大多数模型还是有点过度拟合。

随机森林

XG-Boost

Xg-boost 的表现也与随机森林相似。大多数模型都过拟合。

xgboost

在尝试了几种机器学习方法后,我们可以看到逻辑回归和线性 SVM 平均 word2vec 特征给出了一个更一般化的模型。

不要止步于此!!!

序列模型呢。事实证明,它们能很好地处理文本数据。接下来,我们将尝试使用深度学习方法来解决问题,看看结果是否有所改善。

深度学习方法

基本上,如果我们使用序列模型来解决这个问题,文本预处理会有一些不同。

  • 初始预处理与我们之前所做的相同。我们将删除标点符号,特殊字符,停用词等,我们也将每个单词转换成小写。
  • 接下来,我们将使用另一种方法,而不是直接对数据进行矢量化。首先,我们通过编码将文本数据转换成有序的。也就是说,对于语料库中的每个独特的单词,我们将分配一个号码,如果单词重复,号码就会重复。

例如,“这是真正美味的食物,非常棒”的顺序是“25,12,20,50,11,17,25,12,109”,而“这是糟糕的食物”的顺序是“25,12,78,11”

  • 最后,我们将把每个序列填充到相同的长度。

填料

标绘后,序列的长度,我发现大部分评论的序列长度≤225。所以我把序列的最大长度取为 225。如果序列长度> 225,我们将按顺序取最后 225 个数字,如果长度< 225,我们用零填充初始点。

我们的模型由一个具有预训练权重的嵌入层、一个 LSTM 层和多个密集层组成。我们尝试了 LSTM 和密集层的不同组合以及不同的漏失。我们使用手套向量进行预训练嵌入。我认为这在一定程度上对我们 AUC 分数的提高起到了重要作用。最后,我们用两个 LSTM 层和两个密集层得到了更好的结果,并且丢失率为 0.2。我们的架构如下所示:

体系结构

我们的模型在第二个纪元中很容易就收敛了。我们得到了约 94.8%的验证 AUC,这是我们得到的一般化模型的最高 AUC。

有一个 LSTM 层

有两层 LSTM

我们的一些实验结果如下:

LSTM 结果

就这样,我成功地训练了一个模型。这里来了一个有趣的问题。但是怎么用呢?放心吧!我还将解释我如何使用 flask 部署模型。

使用 Flask 的模型部署

这是大家错过的最精彩的部分。如何部署我们刚刚创建的模型?我选择 Flask,因为它是一个基于 python 的微型 web 框架。由于我来自一个非 web 开发人员的背景,Flask 相对来说比较容易使用。

现在,我们将通过预测文本“食物有好味道”的情感来测试我们的应用程序。我们将通过创建如下请求来测试它

试验码

我们的应用程序将输出给定文本成为相应类的概率和类名。在这里,我们的文本被预测为概率约为 94%的正类。

在外

你可以玩我的 Github 项目的全部代码。

改善范围:

  • 尽管如此,我们目前的模式还有很大的改进空间。为了训练机器学习模型,我从来没有使用过完整的数据集。你可以试试。它可能有助于克服我们的 ml 模型的过度拟合问题。
  • 我只对我们的深度学习模型使用了预训练单词嵌入,而没有对机器学习模型使用。所以你可以尝试使用预训练嵌入,就像手套或 word2vec 与机器学习模型一样。

参考文献

亚马逊评论的情感分析

原文:https://towardsdatascience.com/sentiment-analysis-on-amazon-reviews-45cd169447ac?source=collection_archive---------21-----------------------

来源:archwiz, via: Shutterstock

更好地理解数据是数据分析的关键步骤之一。在这项研究中,我将分析亚马逊的评论。这些评论是非结构化的。换句话说,这篇文章没有条理。然而,情感分析通过自动标记帮助我们理解所有这些非结构化文本。情感分析帮助我们以高效且经济的方式处理大量数据。

这项研究是更大研究的一部分。为了检查特征提取和数据清洗部分(上一步),可以检查 [我的上一篇帖子](http://Before making predictions based on machine learning models, we need to understand the data better. The reviews are unstructured. In other words, the text is unorganized. Sentiment analysis, however, helps us make sense of all this unstructured text by automatically tagging it. Sentiment analysis helps us to process huge amounts of data in an efficient and cost-effective way. That’s why, sentiment analysis was applied in on the text data.) 。你可以在这里 找到这项研究的所有 Python 代码 。在这项研究中,我将:

  • 简要介绍情感分析的理论背景
  • 执行情感分析
  • 为每个步骤提供 python 代码。

什么是 NLTK?

为了执行情感分析,我们将使用 Python 的 NLTK 包。Christopher Manning 说:“NLTK 有点像 NLP 的瑞士军刀,意思是它对任何事情都不太好。但是它有很多基本的工具。”对于访问 Wordnet,这是一个简单的解决方案。

什么是 Wordnet?

T21 是由普林斯顿大学开发的一个大型英语词汇数据库。名词、动词、形容词和副词被分成认知同义词组(同义词组),每个同义词组表达一个不同的概念。同素集通过概念语义和词汇关系相互联系(Fellbaum,1998)。换句话说,Wordnet 可以被描述为在线词库。它告诉你词义和词义之间的关系。Wordnet 最初创建于 1985 年,目前仍在改进中。

Wordnet 可通过以下方式获得:

import nltk
nltk.download('wordnet')

在这项研究中,我们将使用两个主要的情感分类器:

1.极性

2.主观性

Python 的 TextBlob 包是一种执行情感分析的便捷方式。当计算单个单词的情感时,TextBlob 取整个文本的平均值。对于同音异义词,Textblob 不与不同的含义进行协商。换句话说,只考虑单词在整个文本中最常见的意思。为了制作所有这些模型,Textblob 使用 WordNet 数据库。

极性

极性是浮动的,在[-1,1]的范围内,其中 1 表示肯定的陈述,而-1 表示否定的陈述。图 1 显示了评论中极性得分的分布。大多数评论都是在积极的一面(图 1)。

# Create quick lambda functions to find the polarity of each review# Terminal / Anaconda Navigator: conda install -c conda-forge textblobfrom textblob import TextBlobdf['Text']= df['Text'].astype(str) #Make sure about the correct data typepol = lambda x: TextBlob(x).sentiment.polarity
df['polarity'] = df['Text'].apply(pol) # depending on the size of your data, this step may take some time.import matplotlib.pyplot as plt
import seaborn as snsnum_bins = 50
plt.figure(figsize=(10,6))
n, bins, patches = plt.hist(df.polarity, num_bins, facecolor='blue', alpha=0.5)
plt.xlabel('Polarity')
plt.ylabel('Number of Reviews')
plt.title('Histogram of Polarity Score')
plt.show();

图 1:评论极性分数的分布

在图 2 中,可以观察到,与差评相比,好评(好评=1)具有更高的极性。另一方面,好的评论也有更高数量的负极性评论。这是一个不平衡的数据,好评的数量高于差评。因此,在这一类别中看到更多的极端值并不奇怪。

plt.figure(figsize=(10,6))
sns.boxenplot(x=’Good_reviews’, y=’polarity’, data=df)
plt.show();

图 2:关于好或坏评论的极性分布的箱线图。

正如我们从这个方框图中看到的,

  • 我们有一些极性很低(非常负面)的好评
  • 一些负面评价具有很高的极性(正面陈述)

让我们来看看其中的一些:

df.loc[(df.polarity == 1 & (df.Good_reviews == 0))].Text.head(10).tolist()

表 1: 极性为 1(最正面)的评论,好评为 0(差评)

当检查表 1 时,可以看到一些评论实际上是正面的,但不知何故得到了不好的评论分数。请记住,这些都是极端的案例评论,看到他们的评级没有太大意义也就不足为奇了。

标点符号 vs 极性:从图 3 可以看出,标点符号的值低时,极性较高。对此的一个可能的解释是,更加注意标点符号的人在他们的产品评价中更倾向于平衡。尽管有异常值,平均极性得分几乎是一条线,在 0.25 左右。该信息与图 1 一致。我们还可以看到,在极性的两个方向上都存在极端情况(图 3)

plt.figure(figsize=(15,8))
df3= df.loc[df.upper <= 50]
sns.boxenplot(x='upper', y='polarity', data=df3)
plt.xlabel('Punctuation', fontsize=13)
plt.ylabel('Polarity Score', fontsize=13)
plt.title('Punctuation vs Polarity Plot', fontsize=15)
plt.show();

图 3:标点符号的数量和极性得分

乐于助人与极性:图 4 呈现了好评类别中乐于助人极性之间的关系。有一些有趣的异常值。例如,一些评论的极性最低(最负面),但评级很好(好评论为 1),有用性超过 3。这个组合是一个有争议的案例。当我们更仔细地看这些案例时,我们可以看到这些评论没有对购买使用负面的词语(表 2)。那些否定的表达是为了和其他购买进行比较。目前,NLP 方法在处理这种单词用法方面做得不太好。

plt.figure(figsize=(12,6))
df_sub= df.loc[df.HelpfulnessNumerator <=30]
sns.boxenplot(x='HelpfulnessNumerator', y='polarity', hue='Good_reviews', data=df_sub)plt.xlabel('Helpfulness Numerator', fontsize=13)
plt.ylabel('Polarity Score', fontsize=13)
plt.title('Helpfulness Numerator vs Polarity', fontsize=15)
plt.show();

图 4:好评类别中的有用性和极性

表 2

主观性

主观性用于单个句子,以确定一个句子是否表达观点。就主观性而言,世界上的文本信息可以大致分为两大类:事实和观点。主观句通常指的是个人观点、情感或判断,而客观句指的是事实信息。事实是关于实体、事件和属性的客观表达。观点通常是描述人们对实体、事件及其属性的情绪、评价或感觉的主观表达(刘,2010)。

在情感分析中,主观性也是一个位于[0,1]范围内的浮点数。当接近 0 时,更多的是关于事实。当主观性增加时,它接近于一种意见。在数据集中,评论的主观性分数的分布类似于正态分布(图 5)。当我们检查主观性极性、好评特征之间的关系时,我们可以看到主观性和极性显示出漏斗模式(图 6)。还可以观察到,主观性评分低的评论在极性上也是中性评论。

对于创建主观性评分:

sub = lambda x: TextBlob(x).sentiment.subjectivity
df['subjectivity'] = df['Text'].apply(sub)
df.sample(10)

检查主观性分数的分布:

# Density Plot and Histogram of subjectivity
plt.figure(figsize=(10,5))
sns.distplot(df['subjectivity'], hist=True, kde=True,
bins=int(30), color = 'darkblue',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4})plt.xlim([-0.001,1.001])
plt.xlabel('Subjectivity', fontsize=13)
plt.ylabel('Frequency', fontsize=13)plt.title('Distribution of Subjectivity Score', fontsize=15)

图 5:亚马逊评论中主观性分数的分布

plt.figure(figsize=(10,6))
sns.scatterplot(x='polarity', y='subjectivity', hue="Good_reviews", data=df)
plt.xlabel('Polarity', fontsize=13)
plt.ylabel('Subjectivity', fontsize=13)
plt.title('Polarity vs Subjectivity', fontsize=15)
plt.show();

图 6:主观和极性得分调整到好评类别

图 7 展示了极性和主观性如何受到评论评级的影响(好的评论特征)。在阅读这个图时,我们需要记住 y 轴在一个非常小的范围内。我们可以看到,两组之间的平均主观性得分差异可以忽略不计。(你可以在 我的 GitHub repo 上找到这个剧情的代码)

图 7:评论评级的极性和主观性得分的平均值

审查极端评论

为了更好地理解我们的数据,我们需要从不同的角度来检查它。有一些评论可以被认为是一个极端的案例。例如,表 3 给出了 10 条评论,它们具有最高的极性(最积极的情绪),但是“好评”值为 0,并且是最主观的(意见)。这些推文很难被情感分析算法评分。毫不奇怪,他们的得分最高(极性=1)。

df.loc[(df["Good_reviews"] == 0) & (df.polarity == 1 ) & (df.subjectivity ==1), "Text"].head(10).tolist()

表 3

为了理解数据是如何形成的以及情感分析是如何工作的,让我们用不同的标准来检查更多的评论(表 4 和表 5)。

df.loc[(df["Good_reviews"] == 1) & (df.polarity == 1 ) & (df.subjectivity ==1), "Text"].sample(5).tolist()

表 4

df.loc[(df["Good_reviews"] == 1) & (df.polarity == -1 ) & (df.subjectivity ==1), "Text"].sample(5).tolist()

表 5

总之,通过这项研究,我试图通过将情感分析应用于亚马逊评论数据来展示它是如何工作的。在接下来的研究中,我将通过一步一步的解释来展示如何使用潜在狄利克雷分配(LDA)进行主题分析。

开心分析!

*特别感谢我的朋友 Tabitha Stickel 校对这篇文章。

我的情感分析进一步内容推荐:

参考文献:

费尔鲍姆,C. (1998 年)。WordNet:一个电子词汇数据库。布拉德福图书公司。吉邦,欧克斯,m .&贝洛特,P. (2016 年 6 月)。从表情符号到情感分析。

刘,学士(2010)。情感分析和主观性。自然语言处理手册2 (2010),627–666。

斯坦福 CS224N:具有深度学习的 NLP

基于 TextBlob 的远程学习微博情感分析

原文:https://towardsdatascience.com/sentiment-analysis-on-the-tweets-about-distance-learning-with-textblob-cc73702b48bc?source=collection_archive---------14-----------------------

人们对远程学习有什么看法?

故事横幅,作者图片

大家好,

Covid19 疫情在 2020 学年引入了远程学习。虽然有些人可以很容易适应,但有些人发现这种方法效率很低。如今,正在讨论重新开放学校的问题。大部分专家建议至少一个学期再上线。作为一名通过远程学习度过上学期的学生,我可以找到很多时间花在学习自然语言处理上。最后,我决定探究一下人们对远程学习的看法。

我正在计划这个故事作为一个端到端的项目。我们将探索与远程学习相关的推文,以了解人们的意见(也称为意见挖掘)并发现事实。我将使用基于词典的方法来确定推文的极性(我稍后会解释)。TextBlob 将是我们实现这一目标的工具。我们还将建立一个机器学习模型,通过使用伯努利 朴素贝叶斯分类器来预测推文的正面和负面。

我们的工作流程如下:

  1. 数据收集
    • Twitter API
      -使用 tweepy 检索推文
  2. 预处理和清理
    -删除重复项
    -数据类型转换
    -删除无信息列
    -去掉停用词、标签、标点和一两个字母的单词
    -对单词进行标记
    -应用词条化
    -词频-逆文档频率矢量化
  3. 探索性数据分析
    -可视化数据
    -比较字数
    -调查创建次数分布
    -调查推文位置
    -查看热门推文和最常用词
    -制作词云
  4. 情感分析
  5. 机器学习
  6. 摘要

要求

开始之前,请确保以下库在您的工作区中可用。

pandas
numpy
matplotlib
seaborn
TextBlob
wordcloud
sklearn
nltk
pickle

您可以使用以下命令安装非内置库。

pip install pycountry
pip install nltk
pip install textblob
pip install wordcloud
pip install scikit-learn
pip install pickle

你可以在这里找到完整的代码。

1.数据采集

首先,我们需要一个 Twitter 开发者账号 才能被允许使用 Twitter API 。你可以在这里得到账号。审批可能需要几天时间。我已经完成了这些步骤。一旦我得到了这个帐户,我就创建了一个包含 API 信息的文本文件。它位于项目的向上目录中。文本文件的内容如下。如果你想使用它,你必须用你的信息替换它。

CONSUMER KEY=your_consumer_key
CONSUMER KEY SECRET=your_consumer_key_secret
ACCESS TOKEN=your_access_token
ACCESS TOKEN SECRET=your_access_token_secret

之后我创建了一个名为get _ tweets . py的 py 文件来收集远程学习相关的推文(只有英文)。您可以在下面看到完整的代码。

上面的代码搜索包含以下标签的推文

#远程教育,#在线学校,#在线教学,#虚拟学习,#在线教育,#远程教育,#在线课堂,#数字学习,#电子学习,#在线学习

和以下关键字

“远程学习”、“在线教学”、“在线教育”、“在线课程”、“在线学期”、“远程课程”、“远程教育”、“在线课堂”、“电子学习”、“电子学习”

它还过滤转发以避免重复。

get_tweets 函数将检索到的 tweets 存储在临时 pandas 数据帧中,并在输出目录中保存为 CSV 文件。大约花了 40 个小时收集了 202.645 条推文。之后,它给了我以下文件

输出文件,按作者分类的图像

为了将所有 CSV 文件连接成一个文件,我创建了包含以下代码的 concatenate.py 文件。

最终,我们有了 tweets_raw.csv 文件我们来看看它是什么样子的。

*# Load the tweets
tweets_raw = pd.read_csv("tweets_raw.csv")# Display the first five rows
display(tweets_raw.head())# Print the summary statistics
print(tweets_raw.describe())# Print the info
print(tweets_raw.info())*

**

乍一看,我们可以看到 DataFrame 中有 202.645 条推文,包括内容、位置、用户名、转发次数、收藏夹数、创建时间特征。位置栏也有一些缺失值。我们将在下一步处理它们。

2.预处理和清洗

根据以上信息,未命名:0* 和未命名:0.1 列对我们来说没有任何信息,因此我们将删除它们。在列创建的*的数据类型也应该是 datetime。同样,如果有重复的推文,我们也需要删除它们。**

*# We do not need first two columns. Let's drop them out.
tweets_raw.drop(columns=["Unnamed: 0", "Unnamed: 0.1"], axis=1, inplace=True)# Drop duplicated rows
tweets_raw.drop_duplicates(inplace=True)# Created at column's type should be datatime
tweets_raw["Created at"] = pd.to_datetime(tweets_raw["Created at"])# Print the info again
print(tweets_raw.info())*

tweets 计数已经减少到 187.052 (有 15.593 个重复行)。“创建于”列的数据类型也更改为数据时间 64【ns】

现在,让我们整理一下推文的内容。我们需要去掉停用词标点符号标签提及链接一两个字母的单词。我们还需要对推文进行标记。

标记化就是把一个句子拆分成单词和标点符号。句子“这是一个例子。”可以像[“这个”、“是”、“一个”、“例”、“等”这样进行标记化。”]

停用词是常用的词,它们对句子的意义没有贡献,如“一个”、“一个”、“这个”、“在”、“在”等等。

词汇化 就是把一个单词还原成它的词根形式的过程。这个根形式叫做一个 引理 。比如单词running*runrun*的引理就是 run

让我们定义一个函数来完成所有这些操作。

函数调用后,我们的处理后的列将如下所示。你可以看到推文被标记化了,它们不包含停用词、标签、链接和一两个字母的单词。我们还对它们进行了引理化操作。

我们得到了我们想要的。不用担心学习在线教育等词汇。我们稍后会处理它们。

在探索性数据分析中,推文长度和推文中的字数也可能是有趣的。让我们抓住他们!

*# Get the tweet lengths
tweets_raw["Length"] = tweets_raw["Content"].str.len()# Get the number of words in tweets
tweets_raw["Words"] = tweets_raw["Content"].str.split().str.len()# Display the new columns
display(tweets_raw[["Length", "Words"]])*

注意,我们没有使用经过处理的* tweets。*

地点呢?

当我们调用 tweets_raw DataFrame info 函数时,我们看到在“Location”列中有一些缺失值。缺失的值显示为 NaN 。我们将用“未知”标签来填充丢失的值。**

*# Fill the missing values with unknown tag
tweets_raw["Location"].fillna("unknown", inplace=True)*

我们有多少独特的位置?

*# Print the unique locations and number of unique locations
print("Unique Values:",tweets_raw["Location"].unique())
print("Unique Value count:",len(tweets_raw["Location"].unique()))*

输出显示位置信息是混乱的。有 37.119 个唯一位置。我们需要按国家对它们进行分组。为了实现这一点,我们将使用 python 中的 pycountry 包。如果你有兴趣,你可以在这里找到进一步的信息

让我们定义一个名为 get_countries 的函数,它返回给定位置的国家代码。

成功了!现在我们有 156 个独特的国家代码。我们将在探索性数据分析部分使用它们。

现在是时候对推文进行矢量化了。我们将使用 tf-idf(词频-逆文档词频) 矢量化。

Tf-idf(词频—逆词频)是一个统计概念,用于获取语料库中的词频。我们将使用 scikit-learn 的tfidf 矢量器。矢量器将计算语料库中每个单词的权重,并返回一个 tf-idf 矩阵。您可以在此找到更多信息

td =词频(j 中每个 I 出现的次数)
df =文档频率
N =文档数量
w = tf-idf 对每个 ij (文档)的权重。

由于内存限制,我们将只选择前 5000 个单词进行 tf-idf 矢量化。您可以通过使用其他方法,如散列来试验更多。

*# Create our contextual stop words
tfidf_stops = ["online","class","course","learning","learn",\
"teach","teaching","distance","distancelearning","education",\
"teacher","student","grade","classes","computer","onlineeducation",\ "onlinelearning", "school", "students","class","virtual","eschool",\ "virtuallearning", "educated", "educates", "teaches", "studies",\ "study", "semester", "elearning","teachers", "lecturer", "lecture",\ "amp","academic", "admission", "academician", "account", "action" \
"add", "app", "announcement", "application", "adult", "classroom", "system", "video", "essay", "homework","work","assignment","paper",\ "get", "math", "project", "science", "physics", "lesson","courses",\ "assignments", "know", "instruction","email", "discussion","home",\ "college","exam""use","fall","term","proposal","one","review",\
"proposal", "calculus", "search", "research", "algebra"]# Initialize a Tf-idf Vectorizer
vectorizer = TfidfVectorizer(max_features=5000, stop_words= tfidf_stops)# Fit and transform the vectorizer
tfidf_matrix = vectorizer.fit_transform(tweets_processed["Processed"])# Let's see what we have
display(tfidf_matrix)# Create a DataFrame for tf-idf vectors and display the first rows
tfidf_df = pd.DataFrame(tfidf_matrix.toarray(), columns= vectorizer.get_feature_names())
display(tfidf_df.head())*

它返回给我们一个稀疏矩阵。你可以看看它下面的内容。

毕竟,我们将新的数据帧保存为 CSV 文件,以便以后使用,而无需再次执行整个操作。

*# Save the processed data as a csv file
tweets_raw.to_csv("tweets_processed.csv")*

3.探索性数据分析

探索性数据分析是数据科学项目不可或缺的一部分。只要我们理解我们的数据告诉我们什么,我们就可以建立我们的模型。

*# Load the processed DataFrame
tweets_processed = pd.read_csv("tweets_processed.csv", parse_dates=["Created at"])*

首先,让我们看看数据集中最早和最新的 tweets 创建时间。

*# Print the minimum datetime
print("Since:",tweets_processed["Created at"].min())# Print the maximum datetime
print("Until",tweets_processed["Created at"].max())*

这些推文是在 2020 年 7 月 23 日至 8 月 14 日之间创建的。创作时间呢?

*# Set the seaborn style
sns.set()# Plot the histogram of hours
sns.distplot(tweets_processed["Created at"].dt.hour, bins=24)
plt.title("Hourly Distribution of Tweets")
plt.show()*

直方图表明,大多数推文是在一天的 12 点至 17 点之间创建的。最受欢迎的时间是下午 15 点左右。

让我们看看我们已经处理过的位置。

*# Print the value counts of Country column
print(tweets_processed["Country"].value_counts())*

显然,这些位置对我们来说是无信息的,因为我们有 169.734 个未知的 位置。但我们仍然可以查看最热门的推特国家。

根据上面的柱状图, 美国英国印度 是我们数据集中排名前 3 的国家。

现在,让我们来看看最受欢迎的推文(就转发和收藏而言)。

*# Display the most popular tweets
display(tweets_processed.sort_values(by=["Favorites","Retweet-Count", ], axis=0, ascending=False)[["Content","Retweet-Count","Favorites"]].head(20))*

热门推文,点击图片看更好

推文中的常用词也能告诉我们很多。让我们从我们的 Tf-idf 矩阵中获取它们。

*# Create a new DataFrame called frequencies
frequencies = pd.DataFrame(tfidf_matrix.sum(axis=0).T,index=vectorizer.get_feature_names(),columns=['total frequency'])# Display the most 20 frequent words
display(frequencies.sort_values(by='total frequency',ascending=False).head(20))*

文字云会更好。

文字云,作者图片

显然,人们谈论的是【付款】“求助”是使用频率最高的词之一。我们可以说人们正在大量寻求帮助:)

4。情绪分析

经过预处理和 EDA,我们终于可以专注于我们在这个项目的主要目标。我们将使用 TextBlob 来计算推文的情感特征,如 极性主观性 。它通过使用预定义的单词分数给我们这些值。您可以查看文档了解更多信息。

极性 是在 -1 1 之间变化的一个值。它向我们展示了给出的句子是还是**

主观性0 到 1 之间的另一个值变化,它向我们表明句子是关于一个事实还是观点(客观还是主观)。

让我们用 TextBlob 计算极性和主观性得分

我们需要将极性分为积极的、中性的和消极的。

我们也可以像下面这样把它们数起来。

***# Print the value counts of the Label column
print(tweets_processed["Label"].value_counts())***

结果和我预料的不一样。正面推文明显比负面多。

到目前为止,我们将推文标记为积极、中立和消极。让我们仔细检查一下我们的发现。我将从标签数开始。

***# Change the datatype as "category"
tweets_processed["Label"] = tweets_processed["Label"].astype("category")# Visualize the Label counts
sns.countplot(tweets_processed["Label"])
plt.title("Label Counts")
plt.show()# Visualize the Polarity scores
plt.figure(figsize = (10, 10)) 
sns.scatterplot(x="Polarity", y="Subjectivity", hue="Label", data=tweets_processed)
plt.title("Subjectivity vs Polarity")
plt.show()***

由于基于词典的分析并不总是可靠的,我们必须手动检查结果。让我们来看看极性得分最高/最低的热门(根据转发和收藏)推文。

***# Display the positive tweets
display(tweets_processed.sort_values(by=["Polarity", "Retweet-Count", "Favorites"], axis=0, ascending=False)[["Content","Retweet-Count","Favorites","Polarity"]].head(20))# Display the negative tweets
display(tweets_processed.sort_values(by=["Polarity", "Retweet-Count", "Favorites"], axis=0, ascending=[True, False, False])[["Content","Retweet-Count","Favorites","Polarity"]].head(20))***

正面推文,点击图片看更好

负面推文,,点击图片看得更清楚

根据上面的结果,TextBlob 已经正确地完成了它的工作!我们可以像上面那样为每个标签制作单词云。为此,我将定义一个函数。该函数将以一个数据帧和一个标签作为参数,用 tf-idf 矢量器对 处理过的 tweets 进行矢量化。最后,它会为我们制作单词云。由于计算的限制,我们将只查看最受欢迎的 50 条推文。你可以用更多的数据来尝试。

很明显,推特上负面消息的人发现远程学习很无聊,很可怕,很糟糕。另一方面,有些人喜欢远程学习的选择。

让我们来看看各国的正面和负面推文数量。

时间和推特的极性有什么关系吗?

***positive = tweets_processed.loc[tweets_processed.Label=="Positive"]["Created at"].dt.hour
negative = tweets_processed.loc[tweets_processed.Label=="Negative"]["Created at"].dt.hourplt.hist(positive, alpha=0.5, bins=24, label="Positive", density=True)
plt.hist(negative, alpha=0.5, bins=24, label="Negative", density=True)
plt.xlabel("Hour")
plt.ylabel("PDF")
plt.title("Hourly Distribution of Tweets")
plt.legend(loc='upper right')
plt.show()***

上面的直方图表明,时间和推文的极性之间没有关系。

我想在这里结束我的探索,以保持这个故事简短。

5.建立一个机器学习模型

我们根据极性分数给推文贴上了标签。让我们通过使用多项式朴素贝叶斯分类器来建立机器学习模型。我们将使用 tf-idf 向量作为特征,标签作为目标。

***# Encode the labels
le = LabelEncoder()
tweets_processed["Label_enc"] = le.fit_transform(tweets_processed["Label"])# Display the encoded labels
display(tweets_processed[["Label_enc"]].head())***

我们已经对标签进行了编码。

“正”= 2

“空档”= 1

“负”= 0

***# Select the features and the target
X = tweets_processed['Processed']
y = tweets_processed["Label_enc"]***

现在,我们需要将数据分成训练集和测试集。由于我们的数据不平衡,我们将使用 train_test_split分层 参数。

***X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=34, stratify=y)***

现在,我们可以创建我们的模型。由于我们早期的 tf-idf 矢量器适合整个数据集,我们必须初始化一个新的。否则,我们的模型可以通过测试集进行学习。

***# Create the tf-idf vectorizer
model_vectorizer = TfidfVectorizer()# First fit the vectorizer with our training set
tfidf_train = vectorizer.fit_transform(X_train)# Now we can fit our test data with the same vectorizer
tfidf_test = vectorizer.transform(X_test)# Initialize the Bernoulli Naive Bayes classifier
nb = BernoulliNB()# Fit the model
nb.fit(tfidf_train, y_train)# Print the accuracy score
best_accuracy = cross_val_score(nb, tfidf_test, y_test, cv=10, scoring='accuracy').max()
print("Accuracy:",best_accuracy)***

虽然我们没有做任何超参数调优,但是精度还不错。我们来看看混淆矩阵和分类报告。

***# Predict the labels
y_pred = nb.predict(tfidf_test)# Print the Confusion Matrix
cm = confusion_matrix(y_test, y_pred)
print("Confusion Matrix\n")
print(cm)# Print the Classification Report
cr = classification_report(y_test, y_pred)
print("\n\nClassification Report\n")
print(cr)***

还有很多工作要做,以提高模型在负面推文中的表现,但我把它留给另一个故事:)

最后,我们可以保存模型以备后用。

***# Save the model
pickle.dump(nb, open("model.pkl", 'wb'))***

摘要

综上,让我们记住我们一起做的事。首先,我们使用 Twitter API 和 tweepy 库收集了关于远程学习的推文。之后,我们对它们应用了常见的预处理步骤,比如标记化、词条化、删除停用词等等。我们通过使用汇总统计和可视化工具来研究数据。毕竟,我们使用 TextBlob 来获得推文的极性分数,并解释了我们的发现。因此,我们发现,在我们的数据集中,大多数推文对远程学习持积极态度。不要忘记,我们只使用了基于词典的方法,这是不太可靠的。希望这个故事对你理解推文的情感分析有所帮助。

参考

【1】(教程)在 Python 中简化情感分析。(未注明)。数据营社区。https://www . data camp . com/community/tutorials/simplizing-情操-分析-python

【2】李,J. (2020 年 5 月 19 日)。 Twitter 情感分析| NLP |文本分析。中等。https://towards data science . com/Twitter-情操-分析-NLP-文本-分析-b7b296d71fce

【3】李,c .(2019 . 9 . 20)。用于品牌改进和话题跟踪的实时推特情感分析(第 1/3 章)。中等。https://towards data science . com/real-time-Twitter-opinion-analysis-for-brand-improvement-and-topic-tracking-chapter-1-3-e02f 7652 D8 ff

【4】randers 112358。(2020 年 7 月 18 日)。如何用 Python 对一个 Twitter 账号做情感分析。中等。https://medium . com/better-programming/Twitter-情操-分析-15d8892c0082

【5】Python 中的词干化和词条化。(未注明)。数据营社区。https://www . data camp . com/community/tutorials/stemming-lemma tization-python

关于 2020 年美国大选的推特数据情感分析

原文:https://towardsdatascience.com/sentiment-analysis-on-twitter-data-regarding-2020-us-elections-1de4bedbe866?source=collection_archive---------11-----------------------

马库斯·温克勒在 Unsplash 上的照片

据热门科技网站 GeeksforGeeks 称,情感分析是通过“计算”来确定一篇文章是正面、负面还是中性的过程。这也被称为意见挖掘,得出一个发言者的意见或态度。

情绪分析被许多数据分析公司用于各种主题。使用它的一些受欢迎的市场有:

  • 业务:许多公司的营销团队使用它来制定业务战略,了解客户如何看待他们的产品,并了解客户的行为,以提高销售额。
  • 政治:在政治领域,它用于跟踪候选人有利的地区,并致力于候选人不利的地区,以提高他们在选举中的机会。

美国总统选举定于 11 月 3 日举行,还剩不到一周的时间,这是了解美国不同州对候选人——共和党现任总统唐纳德·特朗普和民主党挑战者乔·拜登——的公众情绪和看法的好时机。

为了进行这项分析,我收集了过去一周使用 Twitter 的公开 API 发布的推文,并使用 VADER 情绪分析对这些推文进行了情绪分析。

数据争论

为了使用 Twitter api,我们需要一个 Twitter 开发人员帐户,该帐户允许我们访问访问令牌、访问令牌秘密、API 密钥和 API 秘密密钥。我在一个属性文件中记录了这些参数,这个文件放在我的一个驱动器文件夹中。我使用 python 的 configparser 来读取这些数据,以便使用 twitter API。

import configparser
import os
import tweepy as tw
import pandas as pdconfig = configparser.RawConfigParser()
config.read('/content/drive/My Drive/Colab Notebooks/twitter.properties')accesstoken = config.get('twitter','accesstoken')
accesstokensecret = config.get('twitter','accesstokensecret')
apikey = config.get('twitter','apikey')
apisecretkey = config.get('twitter','apisecretkey')auth = tw.OAuthHandler(apikey, apisecretkey)
auth.set_access_token(accesstoken, accesstokensecret)
api = tw.API(auth, wait_on_rate_limit=True)search_words = "Joe Biden" *# This will be changed to Donald Trump when we retrieve tweets related to him.*
date_since = "2020-10-27"

Twitter 在他们的 API 开发中大量使用分页。为了执行分页,Twitter 为每个请求提供了一个页面/光标参数。因此,这需要大量的 boiler plate 代码来管理分页循环。为了使分页更容易,需要的代码更少,Twitter API 或 Tweepy 使用了 Cursor 对象。

现在,由于游标是通过 callable 传递的,所以我们不能将参数直接传递给方法。相反,参数被传递到游标构造函数方法中。对于搜索 tweets 的 api,我们传递以下参数:

  1. 问:这是推文中要搜索的关键词。对于我们的项目,我们传递候选人的名字(Donald Trump/Joe Biden)。
  2. lang:这是我们想要从 API 中检索的 tweets 的语言。由于美国很大程度上是一个英语国家,英语也是官方语言,我们检索用英语制作的推文。
  3. 因为:这是我们想要检索推文的日期。出于我们的目的,我们对当前的政治对话感兴趣,以了解选举前的当前情绪。所以我们通过了上周二的法案,也就是选举前一周。

另一个需要记住的因素是 tweepy 搜索 api 一次最多检索 1500 条推文,然后有 15 分钟的冷却时间。

tweets = tw.Cursor(api.search, q=search_words, lang="en", since=date_since).items(100)
tweets

搜索 api 调用的结果是一个迭代器对象。

搜索 api 调用的结果是一个游标项迭代器对象。从这个迭代器对象中,我们迭代获取地理、文本、用户名和位置细节。一些细节如地理和位置细节取决于特定用户是否共享这些细节。如果用户不共享这些详细信息,我们将获得这些列的空白数据。

然后,我们将列表转换成熊猫数据帧。

tweet_details = [[tweet.geo, tweet.text, tweet.user.screen_name, tweet.user.location] for tweet in tweets]
tweet_df = pd.DataFrame(data=tweet_details, columns=["geo","text","user","location"])
tweet_df.head()

查看 tweet 文本,我们注意到有许多字符对情感分析没有任何价值。许多推文前面都有 RT,这表明推文被转发了。推文前面还有转发推文的用户的名字,这也是我们不关心的信息。我们还删除了任何可能出现在推文中的 html 网站链接。所有这些数据清理都是在 Python 的“重新”内置包的帮助下完成的。

import re
def clean_tweets(text):
  text = re.sub("RT @[\w]*:","",text)
  text = re.sub("@[\w]*","",text)
  text = re.sub("https?://[A-Za-z0-9./]*","",text)
  text = re.sub("\n","",text)
  return texttweet_df['text'] = tweet_df['text'].apply(lambda x: clean_tweets(x))
tweet_df['Subject'] = search_words
tweet_df.head(20)

在这个分析中,我们最关心的是从 twitter 数据中找出当前美国每个州的政治情绪。为了做到这一点,我们需要对从 tweepy API 中提取的原始数据进行更多的过滤。正如我们之前所讨论的,tweepy API 为我们提供了发布推文的用户的位置,前提是他/她与我们共享这些信息。这个位置数据大部分是空白的。对于其他人,它可能只包含国家名称、城市名称或用逗号分隔的城市和州,等等。

在下一部分中,我们形成一个美国各州的列表和另一个美国各州代码的列表,以便提取位置记录中包含这些代码的 tweets。

P.S .这是一种非常幼稚的净化方式。一个更好的方法是使用 Google Maps API,从位置数据中获取州信息,前提是它在美国。然而,由于我的谷歌地图付费账户的问题,我不得不与这种幼稚的方式作斗争。

states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New York', 'New Mexico', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming']stateCodes = ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA', 'HI', 'ID', 'IL', 'IN', 'IA', 'KS', 'KY', 'LA', 'ME', 'MD', 'MA', 'MI', 'MN', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NJ', 'NM', 'NY', 'NC', 'ND', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VT', 'VA', 'WA', 'WV', 'WI', 'WY']stateMapping = {'AL': 'Alabama', 'AK': 'Alaska', 'AZ': 'Arizona', 'AR': 'Arkansas', 'CA': 'California', 'CO': 'Colorado', 'CT': 'Connecticut', 'DE': 'Delaware', 'FL': 'Florida', 'GA': 'Georgia', 
                  'HI': 'Hawaii', 'ID': 'Idaho', 'IL': 'Illinois', 'IN': 'Indiana', 'IA': 'Iowa', 'KS': 'Kansas', 'KY': 'Kentucky', 'LA': 'Louisiana', 'ME': 'Maine', 'MD': 'Maryland', 'MA': 'Massachusetts', 'MI': 'Michigan', 'MN': 'Minnesota', 'MS': 'Mississippi', 'MO': 'Missouri', 'MT': 'Montana', 'NE': 'Nebraska', 'NV': 'Nevada', 'NH': 'New Hampshire', 'NJ': 'New Jersey', 'NY': 'New York', 'NM': 'New Mexico', 'NC': 'North Carolina', 'ND': 'North Dakota', 'OH': 'Ohio', 'OK': 'Oklahoma', 'OR': 'Oregon', 'PA': 'Pennsylvania', 'RI': 'Rhode Island', 'SC': 'South Carolina', 'SD': 'South Dakota', 'TN': 'Tennessee', 'TX': 'Texas', 'UT':  'Utah', 'VT': 'Vermont', 'VA': 'Virginia', 'WA': 'Washington', 'WV':  'West Virginia', 'WI': 'Wisconsin', 'WY': 'Wyoming'}tweet_copied_df = tweet_df
for index, row in tweet_df.iterrows():
  flag = 0
  if row.location:
    locationSplit = row.location.split(',')
    for word in locationSplit:
      word_stripped = word.strip()
      if word_stripped in states:
        flag = 1
        row['state'] = word_stripped
      elif word_stripped in stateCodes:
        flag = 1
        row['state'] = stateMapping[word_stripped]
  if flag == 0:
    tweet_copied_df = tweet_copied_df.drop(index=index)
  else:
    tweet_copied_df.loc[index, 'state'] = row['state']

最后,我们将清理后的数据附加到一个现有的 csv 文件中,以创建一个 twitter 数据语料库,我们将在其上使用我们的情感分析器。出于这个项目的目的,我在一个循环中运行了上面的代码行,每次迭代之间间隔 15 分钟。

tweet_copied_df.to_csv('tweets_election.csv', header=**False**, mode='a')

情感分析

我们使用 VADER 情感分析器来执行情感分析。根据 GeeksforGeeks 的说法,VADER (Valence Aware 字典和情感推理器)是一个词汇和基于规则的情感分析工具,专门针对社交媒体中表达的情感。情感词典是词汇特征的列表,用更简单的术语来说,这些词通常根据它们的语义取向被标记为正面或负面。VADER 不仅将情绪分为积极或消极,还告诉我们情绪有多积极或消极。

import nltk
from nltk.sentiment.vader import SentimentIntensityAnalyzer
nltk.download('vader_lexicon')sid = SentimentIntensityAnalyzer()

接下来,我们将两位候选人的推文分离到不同的数据帧中。

tweets_election_df = pd.read_csv('tweets_election.csv')
tweets_trump = tweets_election_df[tweets_election_df.Subject == 'Donald Trump']
tweets_trump.drop(tweets_trump.columns[0], axis=1, inplace = **True**)
tweets_trump.head()

tweets_biden = tweets_election_df[tweets_election_df.Subject == 'Joe Biden']
tweets_biden.drop(tweets_biden.columns[0], axis=1, inplace = **True**)
tweets_biden.head()

df = pd.merge(tweets_trump['state'].value_counts(), tweets_biden['state'].value_counts(), right_index = **True**, 
               left_index = **True**)
df = df.rename(columns = {"state_x": "Total Trump Mentions", "state_y": "Total Biden Mentions"})
ax = df.plot(kind='barh', figsize=(16, 25), zorder=2)

*# Despine*
ax.spines['right'].set_visible(**False**)
ax.spines['top'].set_visible(**False**)
ax.spines['left'].set_visible(**False**)
ax.spines['bottom'].set_visible(**False**)

*#Replacing ticks with horizontal lines*
*#ax.tick_params(axis="both", which="both", bottom="off", top="off", labelbottom="on", left="off", right="off", labelleft="on")*
vals = ax.get_xticks()
**for** tick **in** vals:
      ax.axvline(x=tick, linestyle='dashed', alpha=0.4, color='#eeeeee', zorder=1)

*# Set y-axis label*
ax.set_ylabel("States", labelpad=20, weight='bold', size=12)
ax.set_title('Comparison of Twitter mentions of both candidates in all US states as per data collected',fontweight="bold", size=15)

上图显示了我们分析的一个巨大缺点。像许多其他数据集一样,我们的数据集不是一个分布良好的数据集。这意味着我们有一些州,比如佛罗里达、加利福尼亚、德克萨斯,它们比其他州拥有更多的数据。还有,似乎与特朗普相关的数据量以微弱优势超过拜登的数据。

我们现在继续进行情感分析。首先,我们将 polarity_scores()方法应用于每条 tweet 文本,以便理解 tweet 的情感。这个方法调用的结果是一个字典,显示推文中负面、中性和正面情绪的强度。所有这三个值被用来创建第四个数字,这是推文的总体复合情绪。我们会用这个数字来判断一条推文的情绪是正面的、负面的还是中性的。

tweets_trump['sentiment'] = tweets_trump['text'].apply(lambda x: sid.polarity_scores(x))
tweets_biden['sentiment'] = tweets_biden['text'].apply(lambda x: sid.polarity_scores(x))def sentimentVerdict(sentiment):
  if sentiment['compound'] >= 0.05:
    return "Positive"
  elif sentiment['compound'] <= -0.05:
    return "Negative"
  else:
    return "Neutral"tweets_trump['sentiment_overall'] = tweets_trump['sentiment'].apply(lambda x: sentimentVerdict(x)
tweets_biden['sentiment_overall'] = tweets_biden['sentiment'].apply(lambda x: sentimentVerdict(x))tweets_trump.head()

既然我们已经将每条推文数据分为正面、负面或中性,我们可以按州分组,并了解该州公众对特定候选人的总体看法。这是我们的下一步行动。

tweets_trump_location = tweets_trump.groupby(['state', 'sentiment_overall']).count()
tweets_trump_location = tweets_trump_location['user']
tweets_biden_location = tweets_biden.groupby(['state', 'sentiment_overall']).count()
tweets_biden_location = tweets_biden_location['user']tweets_location_df = pd.DataFrame({'State': [state for state in states],
        'Trump Positive': [0 for state in states],
        'Trump Negative': [0 for state in states],
        'Trump Neutral': [0 for state in states],
        'Trump Total': [0 for state in states],
        'Biden Positive': [0 for state in states],
        'Biden Negative': [0 for state in states],
        'Biden Neutral': [0 for state in states],
        'Biden Total': [0 for state in states]})
tweets_location_df.set_index('State', inplace = True)
for state in states:
  positiveTrump, negativeTrump, neutralTrump, positiveBiden, negativeBiden, neutralBiden = 0, 0, 0, 0, 0, 0
  try:
    positiveTrump = tweets_trump_location[state]['Positive']
  except:
    positiveTrump = 0

  try:
    negativeTrump = tweets_trump_location[state]['Negative']
  except:
    negativeTrump = 0

  try:
    neutralTrump = tweets_trump_location[state]['Neutral']
  except:
    neutralTrump = 0

  try:
    positiveBiden = tweets_biden_location[state]['Positive']
  except:
    positiveBiden = 0

  try:
    negativeBiden = tweets_biden_location[state]['Negative']
  except:
    negativeBiden = 0

  try:
    neutralBiden = tweets_biden_location[state]['Neutral']
  except:
    neutralBiden = 0

  totalTrump = positiveTrump + negativeTrump + neutralTrump
  totalBiden = positiveBiden + negativeBiden + neutralBiden

  if totalTrump == 0:
    tweets_location_df.at[state, 'Trump Positive'], tweets_location_df.at[state, 'Trump Negative'], tweets_location_df.at[state, 'Trump Neutral'] = 0,0,0
  else:
    tweets_location_df.at[state, 'Trump Positive'] = round((positiveTrump/totalTrump)*100.0)
    tweets_location_df.at[state, 'Trump Negative'] = round((negativeTrump/totalTrump)*100.0)
    tweets_location_df.at[state, 'Trump Neutral'] = round((neutralTrump/totalTrump)*100.0)
  tweets_location_df.at[state, 'Trump Total'] = totalTrump

  if totalBiden == 0:
    tweets_location_df.at[state, 'Biden Positive'], tweets_location_df.at[state, 'Biden Negative'], tweets_location_df.at[state, 'Biden Neutral'] = 0,0,0
  else:
    tweets_location_df.at[state, 'Biden Positive'] = round((positiveBiden/totalBiden)*100.0)
    tweets_location_df.at[state, 'Biden Negative'] = round((negativeBiden/totalBiden)*100.0)
    tweets_location_df.at[state, 'Biden Neutral'] = round((neutralBiden/totalBiden)*100.0)
  tweets_location_df.at[state, 'Biden Total'] = totalBiden
tweets_location_df

总结我们的分析,我们使用上面的分析来分类一个状态是否是下列之一:

  • 强烈共和党:对特朗普的正面推文数量超过对拜登的正面推文数量,对特朗普的负面推文数量少于拜登,或者对特朗普持中立态度的推文数量多于拜登。
  • 强烈民主党:拜登的正面推文数量超过特朗普,拜登的负面推文数量少于特朗普,或者对拜登持中立态度的推文数量多于特朗普。
  • 有点像共和党:特朗普的正面推文和拜登的正面推文之间的差距大于负面推文的差距。
  • 有点民主:正面的特朗普推文和正面的拜登推文之间的差距小于负面推文的差距。
  • 数据不足:任何一个参赛者的推文数量少于 15 条的州。
tweets_location_df['Predicted Judgement'] = 'Neutral'
for index, row in tweets_location_df.iterrows():
  if row['Trump Total'] <= 15 and row['Biden Total'] <= 15:
    tweets_location_df.loc[index, 'Predicted Judgement'] = 'Insufficient Data'
  else:
    if row['Trump Positive'] > row['Biden Positive'] and (row['Trump Negative'] < row['Biden Negative'] or row['Trump Neutral'] > row['Biden Neutral']):
      tweets_location_df.loc[index, 'Predicted Judgement'] = 'Strongly Republican'
    elif row['Biden Positive'] > row['Trump Positive'] and (row['Biden Negative'] < row['Trump Negative'] or row['Biden Neutral'] > row['Trump Neutral']):
      tweets_location_df.loc[index, 'Predicted Judgement'] = 'Strongly Democratic'
    elif row['Trump Positive'] - row['Biden Positive'] > row['Biden Negative'] - row['Trump Negative']:
      tweets_location_df.loc[index, 'Predicted Judgement'] = 'Somewhat Republican'
    elif row['Biden Positive'] - row['Trump Positive'] > row['Trump Negative'] - row['Biden Negative']:
      tweets_location_df.loc[index, 'Predicted Judgement'] = 'Somewhat Democratic'
tweets_location_df = tweets_location_df.rename(columns={'Trump Positive': 'Trump Positive (in %)', 
     'Trump Negative': 'Trump Negative (in %)',
     'Trump Neutral': 'Trump Neutral (in %)',
     'Trump Total': 'Trump Total Mentions',
     'Biden Positive': 'Biden Positive (in %)',
     'Biden Negative': 'Biden Negative (in %)',
     'Biden Neutral': 'Biden Neutral (in %)',
     'Biden Total': 'Biden Total Mentions'})
tweets_location_df

tweets_location_df.groupby('Predicted Judgement').size()

从我的分析结果来看,根据目前的情绪,共和党以 21 比 16 领先。然而,由于数据不足,我无法了解 13 个州的观点,这 13 个州的观点可能会对任何一方的命运产生重大影响。最终的选举结果将决定我的分析是否成功。在我们等待星期二的时候,我鼓励所有美国人走出家门,去投票。

需要改进的地方

这个分析有一些缺点,我想在这里指出来。根据我的观察,这里有一些:

  1. 数据的分布很差。我在之前的分析中指出了这一点,我觉得这可能在我的分析中包含了一些偏见。理想情况下,两个候选人在所有州的推文数量应该相同。但在现实世界中,这即使不是不可能,也是很难实现的。然而,一个需要改进的地方是包括一些分布模型,以使我的数据集趋向于状态的均匀分布。
  2. 分析中的位置识别部分需要改进。如前所述,理想情况下,如果推文来自美国,可以将推文的位置提供给 Google Maps API,以获取推文发布地所在的州。
  3. 对一个国家的预测判断是可以改进的。我用来预测一个州是民主党还是共和党的整体判断的逻辑还可以改进。我用我在这个领域有限的技术知识和理性为这个计算做了一个逻辑,但这是开放的进一步建议和改进。

这款笔记本就这么多了!如果你还没有弄明白,这个项目的全部是使用 Python 完成的。

以下是 GitHub 储存库的链接:https://GitHub . com/pritamguha 31/sensation-Analysis-on-Twitter-data-ahead-of-2020-US-Elections

随时欢迎分享和反馈。

情感分析:VADER 还是文本斑点?

原文:https://towardsdatascience.com/sentiment-analysis-vader-or-textblob-ff25514ac540?source=collection_archive---------29-----------------------

两种常用库及其性能比较。

Unsplash 上由 Austin Distel 拍摄的照片

什么是情感分析?

对于大多数企业来说,了解客户对其产品/服务的感受是非常有价值的信息,可用于推动业务改进、流程变革,并最终提高盈利能力。
情感分析是通过使用自然语言处理(NLP)来分析信息并确定负面、正面或中性情感的过程。

非常简单地概括这个过程:
1)将输入的内容标记成它的组成句子或单词。
2)用词性成分(即名词、动词、限定词、句子主语等)识别和标记每个标记。3)指定一个从-1 到 1 的情感分数。
4)返回分数和可选分数如复合分数、主观性分数等。

我将研究两个常见的库在这个任务中的表现——text blob 和 VADER。

对于每个图书馆,我将使用来自 IMDB 的更一般的评论声明以及一个包含更多俚语、表情符号等的 Twitter 帖子。

我们要分析的情感陈述将是:

IMDB 审查:

I am a life long Star Wars fan and this was the first time I came out disappointed. And I am not picky, I was mostly happy even with the last two movies, but this one is the worst Star Wars movie yet.

推特声明:

I cannot stop watching the replays of this **incredible** goal. THE perfect strike 💘😁💘😁💘😁

文本 Blob

" TextBlob 是一个用于处理文本数据的 Python (2 和 3)库。它提供了一个简单的 API,用于处理常见的自然语言处理(NLP)任务,如词性标注、名词短语提取、情感分析、分类、翻译等

从 TextBlob 的网站这里

VADER

VADER (Valence Aware 字典和情感推理器)是一个基于词典和规则的情感分析工具,专门针对社交媒体中表达的情感

来自 VADER 的 Github 这里

通过 TextBlob 运行,我们可以看到如下输出:

IMDB: Sentiment(polarity=-0.125, subjectivity=0.5916666666666667)
Twitter: Sentiment(polarity=0.95, subjectivity=0.95)

极性是一个介于-1 和 1 之间的浮点数,其中-1 是一个否定的陈述,1 是一个肯定的陈述。从上面,我们可以看到 IMDB 的声明被认为是负面的,但并不严重,Twitter 的声明是非常积极的。
主观性是 TextBlobs 对陈述是否被视为更多观点或基于事实的评分。较高的主观性分数意味着它不太客观,因此会非常固执己见。

而如果我们用 VADER 的情绪来代替:

IMDB:{'neg': 0.267, 'neu': 0.662, 'pos': 0.072, 'compound': -0.9169}
Twitter:{'neg': 0.026, 'neu': 0.492,'pos': 0.482,'compound': 0.9798}

VADER 的操作略有不同,将输出 3 个分类级别的得分,以及一个复合得分。
从上面,我们可以看到 IMDB 评论中有大约 66%的单词属于中性情感类别,然而它的复合分数——即“标准化、加权、综合分数”——将其标记为非常负面的陈述。基于 0.9798 的复合得分,Twitter 声明再次被评为非常积极。

两个库输出相对相似的结果,但是 VADER 从 IMDB 评论中发现了更多的负面论调,而 TextBlob 忽略了这一点。
这两个库都具有高度的可扩展性,可以查看与自然语言处理相关的许多其他类别,例如:

词性标注

将句子转换成元组列表(单词、标签)的过程。的标记是词性标记,表示这个词是名词、形容词还是动词等。

('I', 'PRP')
('can', 'MD')
('not', 'RB')
('stop', 'VB')
('watching', 'VBG')
('the', 'DT')
('replays', 'NN')
('of', 'IN')
('this', 'DT')
('incredible', 'JJ')
('goal', 'NN')
('THE', 'DT')
('perfect', 'JJ')
('strike', 'NN')
('💘😁💘😁💘😁', 'NN')

标记化

将句子或文本块分解成单独的“记号”进行分析。

['I', 'can', 'not', 'stop', 'watching', 'the', 'replays', 'of', 'this', 'incredible', 'goal', 'THE', 'perfect', 'strike', '💘😁💘😁💘😁']

N-grams

将句子分成大小为 n 的块。在下面的例子中,我使用 n=5,因此它输出所有可能的连续 5 个标记的块。

[WordList(['I', 'can', 'not', 'stop', 'watching']),
WordList(['can', 'not', 'stop', 'watching', 'the']), WordList(['not', 'stop', 'watching', 'the', 'replays']), WordList(['stop', 'watching', 'the', 'replays', 'of']), WordList(['watching', 'the', 'replays', 'of', 'this']), WordList(['the', 'replays', 'of', 'this', 'incredible']), WordList(['replays', 'of', 'this', 'incredible', 'goal']), WordList(['of', 'this', 'incredible', 'goal', 'THE']), WordList(['this', 'incredible', 'goal', 'THE', 'perfect']), WordList(['incredible', 'goal', 'THE', 'perfect', 'strike']), WordList(['goal', 'THE', 'perfect', 'strike', '💘😁💘😁💘😁'])]

还有很多很多!

你真正受到限制的只是你的创造力和你想要深入你的陈述的程度。
这两个库都提供了大量的特性,最好尝试运行一些关于你的主题的样本数据,看看哪个最能满足你的需求。根据我的测试,VADER 似乎在俚语、表情符号等方面表现更好,而 TextBlob 在更正式的语言使用方面表现强劲。

照片由 Prateek KatyalUnsplash 上拍摄

带有 BERT 的情感分析器(构建、调整、部署)

原文:https://towardsdatascience.com/sentiment-analyzer-with-bert-build-tune-deploy-da84c0f2366d?source=collection_archive---------52-----------------------

简要说明我如何开发情感分析器。它涵盖了文本预处理、模型构建、调优、API、前端创建和容器化。

资料组

我使用了斯坦福大学 NLP 小组发布的数据集。我合并了两个文件,即包括 239,232 个文本片段的“dictionary.txt”和包含分配给各种文本片段的情感分数的“impression _ labels . txt”。

用正则表达式进行文本预处理

为了清理文本,我通常使用一堆包含正则表达式的函数。在common.py中,您可以找到所有这些,例如下面描述的remove_nonwords:

类似的函数也用于空行、特殊符号、数字和 html 代码删除。

在文本清理之后,是时候创建 BERT 嵌入了。为此,我使用了 bert-as-service 。它非常简单,只包含 3 个步骤:下载一个预先训练好的模型,启动 BERT 服务,使用客户端对指定长度的句子进行编码。

运行服务时,可以设置多个参数。例如,为了定义max_seq_len,我计算了 0.9 分位数的训练数据长度。

预处理数据具有包含 768 个特征的数据帧形式。完整代码请上nlp_preprocess.py

用 Keras 建模

在这一部分,我们在不同的参数上建立和训练模型。假设我们需要如下 5 层神经网络。我们将参数化 batch_size、历元数、前 4 个密集层和 5 个下降层中的节点数。

用神圣的模型调谐

现在我们可以调整参数了。我们将使用sacred模块。这里的要点是:

1。创建一个实验并添加观察者

首先,我们需要创建一个记录各种信息的实验和观察器。很简单!

2.定义主功能

当我们运行 Python 脚本时,@ex.automain装饰器定义并运行实验的主函数。

3。添加配置参数

我们将通过配置范围来定义它们。

4。添加指标

在我们的例子中,我想知道 MAE 和 MSE 分别是T21。我们可以为此使用 Metrics API。

5。运行实验

前面步骤的功能存储在model_experiment.py脚本中。为了对一堆参数运行我们的实验,我们为所有可能的排列创建并运行run_sacred.py.,MAE 和 MSE 将被保存在 MongoDB 中。

我得到的最好成绩是 MAE 分数的 9%。这意味着我们的情感分析器工作得非常好。我们可以用model_inference功能来查看。

请注意,分数是标准化的,因此也可以获得异常值。模型保存后,我们可以构建一个 Web API!

用 Flask 创建 Web API

现在,我们希望创建一个 API 来运行函数中的代码,并在浏览器中显示返回的结果。

语法@app.route('/score', methods=['PUT'])让 Flask 知道函数score应该被映射到端点/分数methods列表是一个关键字参数,它告诉我们允许哪种 HTTP 请求。我们将使用PUT请求来接收用户的句子。在函数score中,我们得到一个字典形式的分数,因为它可以很容易地转换成 JSON 字符串。完整代码在api.py中提供。

前端

对于 web 界面,创建了三个文件:

  • index.html提供了站点的基本结构:标题、描述、输入文本区和带分数的圆圈。
  • style.css用于网站样式。
  • index.js提供交互性。它负责读取用户输入,处理 API 请求并显示计算出的分数。这里的三个主要功能是:

对于坡度,使用 HSV 模型。饱和度和值是常量。色调对应于分值。在范围[0;中更改色调;120]产生从红色到黄色到绿色的平滑颜色变化。

码头集装箱化

Docker 的高明之处在于,一旦你将一个应用程序及其所有依赖项打包到容器中,你就能确保它能在任何环境下运行。通常建议通过对每个容器使用一个服务来分隔关注的区域。在我的小应用程序有 3 个部分应该结合起来:伯特即服务,应用程序和前端。帮助您构建 Docker 映像和运行容器的工具是 Docker Compose

将我们的代码进行文档化需要做的步骤:

  • 为 bert-as-service、api 和前端创建单独的文件夹,
  • 把相关文件放在那里,
  • requirenments.txtDockerfile添加到每个文件夹中。第一个文件应该包含将通过第二个文件中的命令安装的所有需要的库。其格式在 docker 文档中有描述
  • 在 3 个文件夹目录中创建docker-compose.yaml。在这个文件中定义组成应用程序的 3 个服务,以便它们可以在一个隔离的环境中一起运行。

现在我们已经准备好构建和运行我们的应用程序了!请参见下面的输出示例。

像往常一样,请随意查看我的 GitHub 上的完整代码。

[## GitHub-zuzadeu/带 BERT 的情感分析器

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/zuzadeu/Sentiment-Analyzer-with-BERT)

Python 中的情感分类

原文:https://towardsdatascience.com/sentiment-classification-in-python-da31833da01b?source=collection_archive---------10-----------------------

使用 VADER 和 TextBlob 进行情感分析,使用 scikit-learn 进行监督文本分类

这篇文章是构建情感分类器的三篇连续文章中的最后一篇。做了一些探索性文本分析预处理文本之后,是时候将评论分类为情绪了。在这篇文章中,我们将首先看看两种不用建立模型就能获得情感的方法,然后建立一个定制模型。

照片由混合Unsplash 上拍摄

在我们开始之前,让我们后退一步,快速地看一下更大的画面。 CRISP-DM 方法概述了成功的数据科学项目的流程。在本帖中,我们将做一些数据科学家在建模阶段会经历的任务。

CRISP-DM 工艺流程摘录

0.Python 设置

这篇文章假设读者(👀是的,你!)可以访问并熟悉 Python,包括安装包、定义函数和其他基本任务。如果您是 Python 的新手,这个是一个很好的入门地方。

我在 Jupyter 笔记本里测试过 Python 3.7.1 的脚本。

让我们在开始之前确保您已经安装了以下库:
◼️ 数据操作/分析: numpy,pandas ◼️ 数据分区:sk learn ◼️文本预处理/分析: nltk,textblob
◼️ 可视化: matplotlib,seaborn

一旦你安装了 nltk ,请确保你已经从 nltk 下载了【停用词】**【wordnet】【Vader _ lexicon】,脚本如下:

import nltk
nltk.download('stopwords') 
nltk.download('wordnet')
nltk.download('vader_lexicon')

如果你已经下载了,运行这个会通知你。

现在,我们准备好导入包了:

# Set random seed
seed = 123# Data manipulation/analysis
import numpy as np
import pandas as pd# Text preprocessing/analysis
import re
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import RegexpTokenizer
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from textblob import TextBlob
from scipy.sparse import hstack, csr_matrix
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import MinMaxScaler# Modelling
from sklearn.model_selection import train_test_split, cross_validate, GridSearchCV, RandomizedSearchCV
from sklearn.linear_model import LogisticRegression, SGDClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.pipeline import Pipeline# Visualisation
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.set(style="whitegrid", context='talk')

1.数据📦

我们将使用 IMDB 电影评论数据集。您可以在这里下载数据集,并将其保存在您的工作目录中。保存后,让我们将其导入 Python:

sample = pd.read_csv('IMDB Dataset.csv')
print(f"{sample.shape[0]} rows and {sample.shape[1]} columns")
sample.head()

让我们来看看情绪之间的分歧:

sample['sentiment'].value_counts()

在样本数据中,情感是平均分配的。让我们将目标编码成数字值,其中正数为 1,负数为 0:

# Encode to numeric
sample['target'] = np.where(sample['sentiment']=='positive', 1, 0)# Check values
sample.groupby(['sentiment', 'target']).count().unstack()

让我们留出 5000 个案例进行测试:

# Split data into train & test
X_train, X_test, y_train, y_test = train_test_split(sample['review'], sample['sentiment'], test_size=5000, random_state=seed, 
                                                    stratify=sample['sentiment'])# Append sentiment back using indices
train = pd.concat([X_train, y_train], axis=1)
test = pd.concat([X_test, y_test], axis=1)# Check dimensions
print(f"Train: {train.shape[0]} rows and {train.shape[1]} columns")
print(f"{train['sentiment'].value_counts()}\n")print(f"Test: {test.shape[0]} rows and {test.shape[1]} columns")
print(test['sentiment'].value_counts())

我们将快速检查训练数据集的头部:

train.head()

好吧,我们开始吧!🐳

1.情感分析💛

在这一节中,我想向您展示两种非常简单的方法来获得情感,而无需构建自定义模型。我们将用 VADER文本块提取极性强度分数。

1.1.VADER 的情感分析

“VADER (Valence Aware 字典和情感推理器)是一个基于词典和规则的情感分析工具,专门针对社交媒体中表达的情感。”

让我们从一个简单的例子开始,看看我们如何使用 VADER 情感分析器提取情感强度分数:

example = 'The movie was awesome.'
sid = SentimentIntensityAnalyzer()
sid.polarity_scores(example)

neg,neu,pos: 这三个分数相加为 1。这些分数显示了属于该类别的文本的比例。 复合: 这个分数范围从-1(最负)到 1(最正。

虽然不是所有的评论都像我们手头的例子一样简单,但很高兴看到例子评论的分数看起来大多是正面的。现在,让我们将强度分数添加到训练数据中:

train[['neg', 'neu', 'pos', 'compound']] = train['review'].apply(sid.polarity_scores).apply(pd.Series)
train.head()

一旦我们初始化了分析器对象,获得情感分数只需要一行代码。我们要进一步检查分数吗?让我们从得分最高的 5 条记录开始:

train.nlargest(5, ['pos'])

很高兴看到所有的评论都是正面的。让我们为阴性做同样的事情:

train.nlargest(5, ['neg'])

这个看起来也不错。但我们可能会看到数据的极端,那里的情绪更加明显。让我们用直方图直观显示分数,以便更好地理解:

for var in ['pos', 'neg', 'neu', 'compound']:
    plt.figure(figsize=(12,4))
    sns.distplot(train.query("target==1")[var], bins=30, kde=False, 
                 color='green', label='Positive')
    sns.distplot(train.query("target==0")[var], bins=30, kde=False, 
                 color='red', label='Negative')
    plt.legend()
    plt.title(f'Histogram of {var} by true sentiment');

从直方图来看,似乎 pos、neg 和潜在的 compound 列在对积极和消极情绪进行分类时是有用的。我们可以使用这些分数快速地将每个评论分为正面或负面类别。让我们看看它会做得多好:

train['vader_polarity'] = np.where(train['pos']>train['neg'], 1, 0)
target_names=['negative', 'positive']
print(classification_report(train['target'], 
                            train['vader_polarity'], 
                            target_names=target_names))

使用 VADER ,我们可以不费吹灰之力获得大约 69%的准确率。不过,正面和负面评论的表现看起来有所不同。我们对正面评论的召回率更高,准确率更低——这意味着我们有更多的误报(看到我在那里做了什么吗?你明白我为什么把正面评价编码为 1 了吗?🙊).让我们看看混淆矩阵:

# Create function so that we could reuse later
def plot_cm(y_test, y_pred, target_names=['negative', 'positive'], 
            figsize=(5,3)):
    """Create a labelled confusion matrix plot."""
    cm = confusion_matrix(y_test, y_pred)
    fig, ax = plt.subplots(figsize=figsize)
    sns.heatmap(cm, annot=True, fmt='g', cmap='BuGn', cbar=False, 
                ax=ax)
    ax.set_title('Confusion matrix')
    ax.set_xlabel('Predicted')
    ax.set_xticklabels(target_names)
    ax.set_ylabel('Actual')
    ax.set_yticklabels(target_names, 
                       fontdict={'verticalalignment': 'center'});# Plot confusion matrix
plot_cm(train['target'], train['vader_polarity'])

正如我们所见,我们有许多真阳性和假阳性。事实上,大约 67%的预测是积极的。让我们看看如果使用复合分数,性能是否会提高。

train['vader_compound'] = np.where(train['compound']>0, 1, 0)
print(classification_report(train['target'], 
                            train['vader_compound'], 
                            target_names=target_names))

plot_cm(train['target'], train['vader_compound'])

性能看起来非常相似。我使用训练数据集进行评估,因为我们在这里不是训练模型。但是,如果对测试数据进行同样的操作,结果应该非常相似。

🔗nltk 中关于【VADER】VADER 的更多信息。

1.2.使用 TextBlob 进行情感分析

另一种获得情感分数的方法是利用 TextBlob 库。使用来自 TextBlob 对象的情感属性,我们也可以提取相似的分数。下面是我们如何使用之前的示例进行提取:

*TextBlob(example).sentiment*

极性: 范围从-1(最负)到 1(最正) 主观性: 范围从 0(非常客观)到 1(非常主观)

我们的例子被分析为非常主观的肯定陈述。是真的,不是吗?在这两个分数中,极性与我们更相关。让我们将强度分数添加到训练数据中,并检查具有最高极性分数的 5 个记录:

*train[['polarity', 'subjectivity']] = train['review'].apply(lambda x:TextBlob(x).sentiment).to_list()columns = ['review', 'target', 'polarity', 'subjectivity']
train[columns].nlargest(5, ['polarity'])*

如你所见,用 TextBlob 添加情感强度分数也很简单。让我们来看看极性分数最低的 5 条记录:**

*train[columns].nsmallest(5, ['polarity'])*

是时候绘制一些直方图来更好地理解分数了:

*for var in ['polarity', 'subjectivity']:
    plt.figure(figsize=(12,4))
    sns.distplot(train.query("target==1")[var], bins=30, kde=False, 
                 color='green', label='Positive')
    sns.distplot(train.query("target==0")[var], bins=30, kde=False, 
                 color='red', label='Negative')
    plt.legend()
    plt.title(f'Histogram of {var} by true sentiment');*

**

正如所料,极性分数看起来可能有助于对积极情绪和消极情绪进行分类。让我们使用极性分数进行分类,并查看性能:

*train['blob_polarity'] = np.where(train['polarity']>0, 1, 0)
print(classification_report(train['target'], 
                            train['blob_polarity'], 
                            target_names=target_names))*

使用 TextBlob ,我们可以不费吹灰之力获得大约 69%的准确率。同样,我们有许多假阳性,事实上,甚至比以前更多。让我们看看混淆矩阵:

*plot_cm(train['target'], train['blob_polarity'])*

这一次,假阳性的数量高于真阴性的数量。预测偏向积极情绪,因为 76%的预测是积极的。

🔗关于 TextBlob 的更多信息。

1.3.两者之间的关系

让我们来比较一下 VADERTextBlob 的分数有多相似:

*pd.crosstab(train['vader_polarity'], train['blob_polarity'])*

他们的分类中有大约 79%的重叠,大多数是正面情绪。让我们来看看极性得分:

*plt.figure(figsize=(12,12))
sns.scatterplot(data=train, x='polarity', y='compound',
                hue='target', palette=['red', 'green'], 
                alpha=.3)
plt.axhline(0, linestyle='--', color='k')
plt.axvline(0, linestyle='--', color='k')
plt.title('Scatterplot between polarity intensity scores');*

这张图显示的信息比前一张表多一点。在左下象限,我们主要看到红色圆圈,因为两种方法中的负面分类都更精确。在右上象限,有大量的圆圈,大部分是绿色的,但颜色混合不像以前那么纯。剩下的两个象限显示了两个分数不一致的地方。总的来说,在图的右半部分,颜色比左半部分更混合。

我们从两者中得到非常相似的 69%的总体准确度;然而,当我们仔细观察预测时,这两种方法之间的性能是不同的。

现在你知道如何用 VADER文本块获得情感极性分数。如果您有未标记的数据,这两个工具为自动标记您的数据提供了一个很好的起点。是时候建立模型了!✨

2.模拟ⓜ️

在本节中,我们将:

  1. 选择合适的预处理方法和算法
  2. 探索添加 VADER文本斑点情感分数作为特征是否会提高模型的预测能力
  3. 构建管道并调整其超参数
  4. 在看不见的数据上测试最终管道

情感分类是监督分类模型的一个应用。因此,我们在这里采用的方法可以推广到任何监督分类任务。

2.1.选择合适的预处理方法和算法

我之前的帖子中,我们探索了三种不同的文本预处理方法,并列出其中两种:简单方法简单方法。在这两个选项中,我们现在将测试这两个选项之间的模型性能是否有任何差异,并选择其中一个来使用向前移动。为了使事情变得简单,我们将创建两个函数(这些函数的想法是从这里得到的启发):

*# Define functions
def create_baseline_models():
    """Create list of baseline models."""
    models = []
    models.append(('log', LogisticRegression(random_state=seed, 
                                             max_iter=1000)))
    models.append(('sgd', SGDClassifier(random_state=seed)))
    models.append(('mnb', MultinomialNB()))
    return modelsdef assess(X, y, models, cv=5, scoring=['roc_auc', 
                                        'accuracy', 
                                        'f1']):
    """Provide summary of cross validation results for models."""
    results = pd.DataFrame()
    for name, model in models:
        result = pd.DataFrame(cross_validate(model, X, y, cv=cv, 
                                             scoring=scoring))
        mean = result.mean().rename('{}_mean'.format)
        std = result.std().rename('{}_std'.format)
        results[name] = pd.concat([mean, std], axis=0)
    return results.sort_index()*

我挑了三个算法来试: 逻辑回归分类器随机梯度下降分类器多项朴素贝叶斯分类器 。让我们启动模型:

*models = create_baseline_models()
models*

现在,让我们检查使用更简单方法时的模型性能:

*# Preprocess the data
vectoriser = TfidfVectorizer(token_pattern=r'[a-z]+', 
                             stop_words='english', 
                             min_df=30, 
                             max_df=.7)
X_train_simpler = vectoriser.fit_transform(X_train)# Assess the model
assess(X_train_simpler, y_train, models)*

很高兴看到我们获得了更好的性能:与仅使用情感分数相比,基线模型的准确率为 86–89%。由于这些职业相当平衡,我们将主要关注准确性。但是,我们将确保稍后更仔细地检查预测,以评估模型。性能指标在逻辑回归随机梯度下降之间看起来非常接近,后者在训练中更快(参见 fit_time )。朴素贝叶斯是三个人中训练速度最快的,但是表现比其他两个人稍差。现在让我们来评估一下简单方法:

*# Define function
def preprocess_text(text):
    # 1\. Tokenise to alphabetic tokens
    tokeniser = RegexpTokenizer(r'[A-Za-z]+')
    tokens = tokeniser.tokenize(text)

    # 2\. Lowercase and lemmatise 
    lemmatiser = WordNetLemmatizer()
    tokens = [lemmatiser.lemmatize(t.lower(), pos='v') 
              for t in tokens]
    return tokens# Preprocess the data
vectoriser = TfidfVectorizer(analyzer=preprocess_text, 
                             min_df=30, 
                             max_df=.7)
X_train_simple = vectoriser.fit_transform(X_train)# Assess models
assess(X_train_simple, y_train, models)*

性能看起来和以前差不多。因此,我们将倾向于使用更简单的方法,并继续使用它。在这三种算法中,我们将选择随机梯度下降,因为它最能平衡速度和预测能力。

2.2.评估附加功能

在本节中,我们将探讨添加 VADER文本斑点情感分数作为特征是否会提高模型的预测能力。让我们快速检查一下是否有任何高度相关的特性:

*plt.figure(figsize = (14,5))
columns = ['target', 'neg', 'neu', 'pos', 'compound', 'polarity', 
           'subjectivity']
sns.heatmap(train[columns].corr(), annot=True, cmap='seismic_r');*

最相关的特征是复合。让我们运行一个快速模型,看看哪些分数更有用:

*# Initialise a model
sgd = SGDClassifier(random_state=seed)# Initialise a scaler
scaler = MinMaxScaler()# Assess the model using scores
scores = train[['neg', 'neu', 'pos', 'compound', 'polarity', 
                'subjectivity']]
assess(scaler.fit_transform(scores), y_train, [('sgd', sgd)])*

我们使用分数得到大约 77%的准确率。现在让我们检查系数:

*# Fit to training data
sgd.fit(scores, y_train)# Get coefficients
coefs = pd.DataFrame(data=sgd.coef_, columns=scores.columns).T
coefs.rename(columns={0: 'coef'}, inplace=True)# Plot
plt.figure(figsize=(10,5))
sns.barplot(x=coefs.index, y='coef', data=coefs)
plt.title('Coefficients');*

似乎我们只能使用阴性、阳性极性,因为它们是得分中最主要的特征。让我们看看是否可以通过将这些选择的分数添加到先前预处理的数据来改进模型结果。

*# Add features to sparse matrix
selected_scores = train[['neg', 'pos', 'polarity']]
X_train_extended = hstack([X_train_simpler, csr_matrix(scaler.fit_transform(selected_scores))])# Assess
assess(X_train_extended, y_train, [('sgd', sgd)])*

由于添加这些分数并没有改进模型,因此没有必要将它们作为特征添加。这也将使我们的渠道保持简单!

2.3.构建管道并调整其超参数

是时候构建一个小管道,将预处理器和模型放在一起了。我们将微调它的超参数,看看我们是否能改进这个模型。首先,让我们尝试理解三个超参数的影响:对于向量机的min_dfmax_df和对于随机搜索模型的loss:

*# Create a pipeline
pipe = Pipeline([('vectoriser', TfidfVectorizer(token_pattern=r'[a-z]+')),
                 ('model', SGDClassifier(random_state=seed))])# Prepare a random search
param_distributions = {'vectoriser__min_df': np.arange(10, 1000, 10),
                       'vectoriser__max_df': np.linspace(.2, 1, 40),
                       'model__loss': ['log', 'hinge']}
r_search = RandomizedSearchCV(estimator=pipe, param_distributions=param_distributions, 
                              n_iter=30, cv=5, n_jobs=-1, random_state=seed)
r_search.fit(X_train, y_train)# Save results to a dataframe
r_search_results = pd.DataFrame(r_search.cv_results_).sort_values(by='rank_test_score')*

这里,我们正在尝试 30 种不同的超参数空间指定的随机组合。这需要一段时间来运行。随机搜索的输出将保存在名为r_search_results的数据帧中。让我们创建另一个数据框架,其中包含一些我们更感兴趣的列:

*columns = [col for col in r_search_results.columns 
           if re.search(r"split|param_", col)]
r_summary = r_search_results[columns].copy()
r_summary.columns = [re.sub(r'_test_score|param_', '', col) 
                     for col in r_summary.columns]
columns = [col.split('__')[1] if '__' in col else col 
           for col in r_summary.columns ]
r_summary.columns = columns
r_summary.head()*

让我们将输出可视化,以便更好地理解超参数的影响:

*# Create a long dataframe
r_summary_long = pd.melt(r_summary, 
                         id_vars=['min_df', 
                                  'max_df', 
                                  'loss'], 
                         value_vars=['split0', 
                                     'split1', 
                                     'split2', 
                                     'split3', 
                                     'split4'])# Plot hyperparameter 'loss'
plt.figure(figsize=(8,4))
plt.title('Performance by loss')
sns.boxplot(x='value', y='loss', data=r_summary_long, 
            orient='h')
plt.xlim(.8, .9);*

看起来loss='hinge'会带来稍微好一点的性能。让我们看看数字超参数:

*for param in ['min_df', 'max_df']:
    plt.figure(figsize=(8,4))
    sns.scatterplot(x=param, y="value", data=r_summary_long, 
                    x_jitter=True, alpha=0.5)
    plt.ylim(.8, .9);*

由于min_df和准确度之间似乎存在负相关关系,我们将把min_df保持在 200 以下。max_df没有明显的趋势,可能是因为业绩受min_dfloss的影响更大。虽然他们三个都是这样,但是对于max_df来说更明显。现在,我们对这些超参数如何影响模型有了一些了解,让我们更精确地定义管道(max_df=.6loss=’hinge')并尝试使用网格搜索进一步调整它:

*# Create a pipeline
pipe = Pipeline([('vectoriser', TfidfVectorizer(token_pattern=r'[a-z]+', max_df=.6)),
                 ('model', SGDClassifier(random_state=seed, loss='hinge'))])# Prepare a grid search
param_grid = {'vectoriser__min_df': [30, 90, 150],
              'vectoriser__ngram_range': [(1,1), (1,2)],
              'vectoriser__stop_words': [None, 'english'],
              'model__fit_intercept': [True, False]}
g_search = GridSearchCV(estimator=pipe, param_grid=param_grid, cv=5, n_jobs=-1)
g_search.fit(X_train, y_train)# Save results to a dataframe
g_search_results = pd.DataFrame(g_search.cv_results_).sort_values(by='rank_test_score')*

网格搜索也需要一些时间,因为我们有 24 种不同的超参数组合要尝试。像以前一样,输出将保存到名为g_search_results的数据帧中。让我们将更多相关列提取到另一个数据框架中:

*columns = [col for col in g_search_results.columns 
           if re.search(r"split|param_", col)]
g_summary = g_search_results[columns+['mean_test_score']].copy()
g_summary.columns = [re.sub(r'_test_score|param_', '', col) 
                     for col in g_summary.columns]
columns = [col.split('__')[1] if '__' in col else col 
           for col in g_summary.columns ]
g_summary.columns = columns
g_summary.head()*

使用这些组合中的任何一种,我们都可以达到约 0.9 的交叉验证精度。很高兴看到边际增长。

*# Create a long dataframe
g_summary_long = pd.melt(g_summary, 
                         id_vars=['min_df', 
                                  'ngram_range', 
                                  'stop_words', 
                                  'fit_intercept'], 
                         value_vars=['split0', 
                                     'split1', 
                                     'split2', 
                                     'split3', 
                                     'split4'])
g_summary_long.replace({None: 'None'}, inplace=True)# Plot performance
for param in ['ngram_range', 'stop_words', 'fit_intercept']:
    plt.figure(figsize=(8,4))
    plt.title(f'Performance by {param}')
    sns.boxplot(x='value', y=param, data=g_summary_long, orient='h')
    plt.xlim(.85, .95);*

我们可以看到,换成ngram_range=(1,2),model 表现更好。stop_words=None也是如此。另一方面,我们是否拟合截距并没有太大的影响,这意味着我们可以将这个超参数保留为默认值。我认为这已经足够好了,我们现在可以定义最终的管道了。

2.4.在看不见的数据上测试最终管道

使用网格搜索中的顶部组合,这是我们最终管道的样子:

*pipe = Pipeline([('vectoriser', TfidfVectorizer(token_pattern=r'[a-z]+', min_df=30, max_df=.6, ngram_range=(1,2))),
                 ('model', SGDClassifier(random_state=seed, loss='hinge'))])pipe.fit(X_train, y_train)*

我们的管道很小很简单。让我们看看它的系数:

*coefs = pd.DataFrame(pipe['model'].coef_, 
                     columns=pipe['vectoriser'].get_feature_names())
coefs = coefs.T.rename(columns={0:'coef'}).sort_values('coef')
coefs*

具有最高或最低系数的特征看起来很直观。但是看看我们拥有的特性数量:49,577!这主要是因为放松了min_df,增加了二元模型,没有删除停用词。如果我们热衷于减少特征的数量,我们可以改变管道中的这些超参数。如果我们开始减少特征,我们会注意到特征数量和模型精度之间的权衡。最佳平衡是什么样的取决于具体情况。让我们来评估管道:

*train_pred = pipe.predict(X_train)
print(classification_report(train_pred, 
                            y_train, 
                            target_names=target_names))*

*test_pred = pipe.predict(X_test)
print(classification_report(test_pred, 
                            y_test, 
                            target_names=target_names))*

在训练集和测试集上的准确率分别约为 0.94 和 0.92。这两种观点的精确度和召回率看起来非常相似。我们有稍微多一点的假阴性。让我们绘制混淆矩阵:

*plot_cm(test_pred, y_test, target_names=target_names)*

看起来不错。这么🎊现在,我们有了一个将大约 90%的评论归类为正确观点的管道。让我们看看做一次预测需要多长时间。我们将使用 Jupyter 笔记本的魔法命令%timeit:

*for i in range(10):
    lead = X_test.sample(1)
    %timeit pipe.predict(lead)*

尽管%timeit运行了多个循环,并给出了运行时间的均值和标准差,但我注意到我每次得到的输出都略有不同。因此,我们正在查看%timeit的 10 个循环以观察范围。

单次预测大约需要 1.5 到 4 毫秒。这需要在用例的生产环境的上下文中进行评估。

好了,这就是这篇文章的内容。💫

照片由伯爵克里斯Unsplash 上拍摄

您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果您使用 我的推荐链接 ,*成为会员,您的一部分会费将直接用于支持我。*

谢谢你看我的帖子。希望您已经学会了一些不同的实用方法,可以在构建或不构建定制模型的情况下将文本分类为情感。以下是本系列其他两篇文章的链接:◼️python 中的探索性文本分析
◼️python 中的文本预处理

以下是我的其他 NLP 相关帖子的链接:
◼️Python 中的简单 word cloud
(下面列出了一系列关于 NLP 介绍的帖子)
◼️ 第一部分:Python 中的预处理文本
◼️ 第二部分:词条满足和词干的区别
◼️ 第三部分:TF-IDF 解释
◼️ 第四部分:python 中的监督文本分类模型

再见🏃💨

PyTorch 中基于 CNN 的餐馆评论情感分类

原文:https://towardsdatascience.com/sentiment-classification-using-cnn-in-pytorch-fba3c6840430?source=collection_archive---------10-----------------------

使用 Word2Vec 嵌入作为输入实现卷积神经网络(CNN)以分类 PyTorch 中的 Yelp 餐馆评论

在 PyTorch 中使用 CNN 进行情感分类

在本文中,我将解释 CNN 如何用于文本分类问题,以及如何设计网络以接受 word2vec 预训练的嵌入作为网络的输入。您将了解如何在 PyTorch 中为情感分类问题构建自定义 CNN。

我之前的帖子中,我介绍了 PyTorch 的基础知识以及如何实现用于情感分类的逻辑回归。如果你是 PyTorch 新手,可以参考一下。如果你想习惯用 PyTorch 定义网络,请参考的前馈神经网络文章。我在以前的帖子中解释了使用决策树分类器使用 BOWTF-IDFWord2VecDoc2Vec 向量进行情感分类的其他方法,最后也会进行比较。现在让我们开始加载数据吧!

迪皮卡·巴德提供的按情感分类的餐馆评论示例

加载数据

Yelp 餐馆评论数据集可以从他们的网站下载,那里的数据格式是 JSON。提供的数据实际上不是 python 可读的正确 json 格式。每一行都是 dictionary,但是为了使它成为有效的 json 格式,应该在文件的开头和结尾加上方括号,并在每一行的末尾添加,。将INPUT_FOLDER定义为 yelp review.json 文件所在的本地目录中的文件夹路径。将OUTPUT_FOLDER声明为一个路径,您希望在该路径中写入以下函数的输出。json 数据的加载和前 100,000 行的写入在下面的函数中完成:

一旦运行了上面的函数,您就可以为接下来的步骤将它加载到 pandas dataframe 中了。对于这个实验,只取了少量的数据,这样就可以更快地运行以查看结果。

探索数据

在加载数据之后,创建用于情感指示的新列。原始数据集中并不总是存在带有您想要的预测标签的某个列。在大多数情况下,这可以是一个派生列。对于这种情况,数据中的stars列用于导出情绪。

输出:

在数据可用之后,完成从星星到情绪的映射,并绘制每个情绪的分布。

输出:

完成后,检查每个情感的行数。情感类别如下:

  1. 阳性:1
  2. 负数:-1
  3. 中性:0

这三种情绪的行数分布不均匀。在这篇文章中,不平衡类的问题将不会被处理,这就是为什么,简单的函数检索每个情绪的前几个记录被写。在本例中,top_n是 10000,这意味着将获取总共 30,000 条记录。

输出:

如何对文本数据进行预处理?

预处理包括许多步骤,如标记化、去除停用词、词干化/词条化等。这些常用的技巧在我之前的弓的帖子里有详细解释。这里,下一阶段只解释必要的步骤。

为什么需要对这段文字进行预处理?—并非所有信息都对预测或分类有用。减少字数将减少模型的输入维度。这种语言的书写方式,包含了大量语法特有的信息。因此,当转换成数字格式,像大写,标点符号,后缀/前缀等字的具体特征。都是多余的。以相似单词映射到单个单词的方式清理数据,并从文本中删除语法相关信息,可以极大地减少词汇量。应用哪种方法和跳过哪种方法取决于手头的问题。

1.停用词的删除

停用词是在不同的自然语言处理(NLP)任务中作为前置步骤经常使用并从句子中移除的词。停用词的例子有:a、an、the、this、not 等。每个工具都使用一组稍微不同的停用词列表,但是在短语结构很重要的情况下,比如在情感分析的情况下,就避免使用这种技术。

移除停用字词的示例:

输出:

从输出中可以看出,删除停用词就删除了获取情感所需的必要词,有时它可以完全改变句子的意思。在上面这段代码打印的例子中,很明显,它可以将否定句转换成肯定句。因此,对于情感分类来说,这个步骤被跳过。

2.标记化

标记化是将句子/文本分割成称为标记的单词阵列的过程。这有助于分别对每个单词进行转换,也是将单词转换为数字所必需的。执行标记化有不同的方式。我已经在我的上一篇文章的标记化部分解释了这些方法,所以如果你感兴趣的话,你可以去看看。

Gensim 的[simple_preprocess](https://radimrehurek.com/gensim/utils.html)允许你将文本转换成小写,并删除标点符号。它还有minmax长度参数,这有助于过滤掉那些长度范围内的罕见单词和最常见的单词。

这里,simple_preprocess用于获取数据帧的标记,因为它已经为我们做了大部分预处理。让我们应用此方法来获取数据帧的令牌:

输出:

3.堵塞物

词干处理将单词还原为其“词根”。不同于使用语法规则和字典将单词映射到词根形式的词干化,词干化只是删除后缀/前缀。词干分析广泛用于 SEOs、Web 搜索结果和信息检索的应用中,因为只要词根在文本的某个地方匹配,它就有助于检索搜索中的所有相关文档。

有不同的算法用来做词干分析。PorterStammer(1979)、LancasterStammer (1990)和 SnowballStemmer(可以添加自定义规则)。NLTK 或 Gensim 包可用于实现这些词干提取算法。兰开斯特比波特慢一点,所以我们可以根据大小和所需的响应时间来使用它。Snowball stemmer 是 Porter stemmer 的略微改进版本,通常比后者更受欢迎。不太清楚哪种方法会产生准确的结果,因此必须试验不同的方法,并选择给出更好结果的方法。在这个例子中,波特斯特梅尔被使用,这是简单和快速的。以下代码显示了如何在数据帧上实现词干,并创建新列stemmed_tokens:

输出:

分成训练集和测试集:

训练数据将用于训练模型,测试数据是模型预测分类的数据,它将与原始标签进行比较,以检查准确性或其他模型测试指标。

  • 训练数据(用于训练 ML 模型的数据子集)~70%
  • 测试数据(用于测试从训练数据训练的 ML 模型的数据子集)~30%

尽量平衡两个集合中的类数,使结果不偏不倚或者成为模型训练不足的原因之一。这是机器学习模型的关键部分。在现实世界的问题中,存在不平衡类的情况,需要使用过采样少数类、欠采样多数类(scikit-learn 包中的重采样函数)或使用 Imblearn 包中的 SMOTE 功能生成合成样本等技术。

在这种情况下,数据分为两部分,训练和测试,70%在训练中,30%在测试中。在进行拆分时,最好在训练和测试数据中平均分布类别。这里使用了 scikit-learn 包中的函数 train_test_split

输出:

从上面的输出可以看出,数据是按比例分配给每个类的。打印训练和测试中每个情感的行数。

用于文本分类的卷积神经网络

现在,我们准备深入研究如何使用 CNN 进行文本分类,以及如何构建输入。CNN 涉及两种操作,可以认为是特征提取器:卷积和池化。这些操作的输出最终连接到多层感知器以获得最终输出。

神经网络只对数字数据起作用,因此首要任务是找到从文字到数字格式的合适转换。这里我们将使用大小为 500 的 Word2Vec 向量作为输入,这在我之前的文章中已经解释过了。

  • 卷积层——这些层用于通过在输入上滑动小内核窗口来发现模式。它不是在图像的小区域上增加过滤器,而是通过嵌入窗口大小提到的几个词的向量来滑动。为了查看单词嵌入序列,窗口必须查看一个序列中的多个单词嵌入。它们将是尺寸为window_size * embedding_size的矩形。例如,在我们的例子中,如果窗口大小是 3,那么内核将是 3*500。这实质上代表了模型中的 n 元语法。内核权重(过滤器)被成对地乘以单词嵌入,并被求和以获得输出值。随着网络被学习,这些内核权重也被学习。以下显示了如何在卷积层中进行计算的示例(使用了填充,这将在后面解释)。

通过 Dipika Baad 进行文本分类的 CNN 计算

  • 卷积的输入和输出通道—这里,nn.Conv2d用于创建卷积层。在图像的情况下,不同颜料的输入被分别给出,在这种情况下,如果是 RGB,则输入通道的数量是 3,如果是灰度,则输入通道的数量是 1。在这种情况下,我们只输入一个特征,即单词嵌入,因此conv2d的第一个参数是1,输出通道是特征总数,将是NUM_FILTERS。我们可以为每个窗口大小设置多个滤波器,因此总输出会有这么多。
  • 填充——有时滑动时,内核大小不会完全覆盖。因此,为了使高度相同的大小,填充使用。这里我们用了window_size-1。下面的动画展示了它如何使用 window_size-1 填充。

带填充的滑动窗口,用于 CNN 分类,文本由迪皮卡·巴德提供

  • Maxpooling —一旦我们有了特征向量,并且它已经提取了重要的特征,就足以知道它存在于句子中,就像一些积极的短语“棒极了的食物”,并且它出现在句子中的什么地方并不重要。Maxpooling 用于获取这些信息,并丢弃其余的信息。例如,在上面的动画中,我们有特征向量,在应用最大池后,将选择最大值。在上面的例子中,当verydelicious在短语中时,它显示 max,这是有意义的。

迪皮卡巴德对特征向量的最大池化结果

一旦对所有特征向量应用了最大池,就可以像前馈神经网络一样添加更多层。让我们开始实施吧!下面的代码显示了在构建网络之前需要包含的基本库。我在 Google colab 上用的是 GPU,所以设备指示的是 cuda。

输出:

生成输入和输出张量

输入将是用嵌入大小 500 训练的 Word2Vec 向量。由于我们希望保持句子的长度不变,当句子的长度小于语料库中最长的句子时,将使用填充标记来填充多余的剩余单词。让我们使用下面的函数来训练 Word2Vec 模型。如果你有兴趣了解更多关于 Word2Vec 的知识,那么可以参考我之前的文章。模型是在整个语料库上训练的。

一旦模型准备好了,我们就可以创建一个函数来生成输入张量。

找到的句子的最大长度为 927。所以每个输入张量都是这个大小。为了创建输出张量,必须完成从标签到正值的映射。目前我们用-1 表示阴性,这在神经网络中是不可能的。输出层中的三个神经元将给出每个标签的概率,因此我们只需要映射到正数。功能如下:

定义 CNN

下面的代码显示了如何定义 CNN。一些参数,如窗口大小,过滤器的数量可以调整,以获得不同的结果。在这里,我已经加载了上面生成的模型,这是为了当你在不同时间训练 word2vec 和在不同时间运行 CNN 时,最好使用保存文件中的模型。

训练 CNN 模型

一旦定义了网络,我们就可以开始初始化用于训练的必要对象,如模型对象、损耗和优化对象。下面的代码显示了如何训练 CNN 模型。我已经运行了 30 个时代。在训练数据的每一步都记录损失。

测试模型

测试模型代码如下所示。损失图也绘制和代码保存图。当您正在进行多个实验,并且想要比较不同超参数的所有组合后的结果时,这非常有用。

输出:

从损失图中可以清楚地看出,损失在稳步减少,并且损失波动不大,这表明学习率不是太高。与以前的方法相比,0.72的准确性非常好,在以前的方法中,决策分类器与 BOWTF-IDFWord2VecDoc2Vec 以及使用 PyTorch 的逻辑回归一起使用。这个精度接近我们使用简单的前馈神经网络的精度。因此,使用 CNN 总是没有必要的。根据问题的复杂性和可用于计算的资源,应该使用适当的方法。

所以现在你可以很容易地用这种方法对你自己的数据集进行实验!我希望这有助于您理解如何使用 PyTorch 构建 CNN 模型来对餐馆评论数据进行情感分析。请随意扩展这段代码!这适用于存在多个类别的任何其他文本分类问题。如果我可以考虑改进这个模型,我会使用不同的学习速率、时期、不同的窗口大小、嵌入大小、滤波器数量和其他优化算法,如SGDRMSProp等。预处理可以改为使用词汇化或其他词干算法来查看结果如何变化。你的项目有很大的试验空间。

一如既往—愉快的实验和学习:)

PyTorch 中基于逻辑回归的情感分类

原文:https://towardsdatascience.com/sentiment-classification-using-logistic-regression-in-pytorch-e0c43de9eb66?source=collection_archive---------25-----------------------

在 PyTorch 中实现逻辑回归,用于 Yelp 餐馆评论数据上的情感分类,其中输入特征是单词包(BOW)

迪皮卡·巴德在 PyTorch 中使用逻辑回归进行情感分类

将评论数据分类为不同情感的逻辑回归将在深度学习框架 PyTorch 中实现。这是为了熟悉 PyTorch 框架的基本功能,比如如何定义神经网络?以及如何在 PyTorch 中调优模型的超参数?将在这篇文章中讨论。在我之前的帖子中,决策树分类器与不同输入特征(如 BOWTF-IDFWord2VecDoc2Vec )的比较将在最后进行。

在那些帖子中,我已经讨论了预处理文本和加载数据的主题。这将类似于那些职位。让我们从加载数据开始。

迪皮卡·巴德提供的按情感分类的餐馆评论示例

加载数据

Yelp 餐馆评论数据集可以从他们的网站下载,那里的数据格式是 JSON。提供的数据实际上不是 python 可读的正确 json 格式。每一行都是 dictionary,但是为了使它成为有效的 json 格式,应该在文件的开头和结尾加上方括号,并在每一行的末尾添加,。将INPUT_FOLDER定义为 yelp review.json 文件所在的本地目录中的文件夹路径。将OUTPUT_FOLDER声明为一个路径,您希望在该路径中写入以下函数的输出。json 数据的加载和前 100,000 行的写入在下面的函数中完成:

一旦运行了上面的函数,您就可以为接下来的步骤将它加载到 pandas dataframe 中了。对于这个实验,只取了少量的数据,这样就可以更快地运行以查看结果。

探索数据

在加载数据之后,创建用于情感指示的新列。原始数据集中并不总是存在带有您想要的预测标签的某个列。在大多数情况下,这可以是一个派生列。对于这种情况,数据中的stars列用于导出情绪。

输出:

在数据可用之后,完成从星星到情绪的映射,并绘制每个情绪的分布。

输出:

完成后,检查每个情感的行数。情感类别如下:

  1. 阳性:1
  2. 负数:-1
  3. 中性:0

这三种情绪的行数分布不均匀。在这篇文章中,不平衡类的问题将不会被处理,这就是为什么,简单的函数检索每个情绪的前几个记录被写。在本例中,top_n是 10000,这意味着将获取总共 30,000 条记录。

输出:

如何对文本数据进行预处理?

预处理包括许多步骤,如标记化、去除停用词、词干化/词条化等。这些常用的技巧在我之前的弓的帖子里有详细的讲解。这里,下一阶段只解释必要的步骤。

为什么需要对这段文字进行预处理?—并非所有信息都对预测或分类有用。减少字数将减少模型的输入维度。这种语言的书写方式,包含了大量语法特有的信息。因此,当转换成数字格式,像大写,标点符号,后缀/前缀等字的具体特征。都是多余的。以相似单词映射到单个单词的方式清理数据,并从文本中删除语法相关信息,可以极大地减少词汇量。应用哪种方法和跳过哪种方法取决于手头的问题。

1.停用词的删除

停用词是在不同的自然语言处理(NLP)任务中作为前置步骤经常使用并从句子中移除的词。停用词的例子有:a、an、the、this、not 等。每个工具都使用一组稍微不同的停用词列表,但是在短语结构很重要的情况下,比如在情感分析的情况下,就避免使用这种技术。

移除停用字词的示例:

输出:

从输出中可以看出,删除停用词就删除了获取情感所需的必要词,有时它可以完全改变句子的意思。在上面这段代码打印的例子中,很明显,它可以将否定句转换成肯定句。因此,对于情感分类来说,这个步骤被跳过。

2.标记化

标记化是将句子/文本分割成称为标记的单词阵列的过程。这有助于分别对每个单词进行转换,也是将单词转换为数字所必需的。执行标记化有不同的方式。我已经在我的上一篇文章的标记化部分解释了这些方法,所以如果你感兴趣的话可以去看看。

Gensim 的[simple_preprocess](https://radimrehurek.com/gensim/utils.html)允许你将文本转换成小写,并删除标点符号。它还有minmax长度参数,这有助于过滤掉那些长度范围内的罕见单词和最常见的单词。

这里,simple_preprocess用于获取数据帧的标记,因为它已经为我们做了大部分预处理。让我们应用此方法来获取数据帧的令牌:

输出:

3。词干

词干处理将单词还原为其“词根”。不同于使用语法规则和字典将单词映射到词根形式的词干化,词干化只是删除后缀/前缀。词干分析广泛用于 SEOs、Web 搜索结果和信息检索的应用中,因为只要词根在文本的某个地方匹配,它就有助于检索搜索中的所有相关文档。

有不同的算法用来做词干分析。PorterStammer(1979)、LancasterStammer (1990)和 SnowballStemmer(可以添加自定义规则)。NLTK 或 Gensim 包可用于实现这些词干提取算法。兰开斯特比波特慢一点,所以我们可以根据大小和所需的响应时间来使用它。Snowball stemmer 是 Porter stemmer 的略微改进版本,通常比后者更受欢迎。不太清楚哪种方法会产生准确的结果,因此必须试验不同的方法,并选择给出更好结果的方法。在这个例子中,波特斯特梅尔被用来简单和快速。以下代码显示了如何在数据帧上实现词干,并创建新列stemmed_tokens:

输出:

分成训练集和测试集:

训练数据将用于训练模型,测试数据是模型预测分类的数据,它将与原始标签进行比较,以检查准确性或其他模型测试指标。

  • 训练数据(用于训练 ML 模型的数据子集)~70%
  • 测试数据(用于测试从训练数据训练的 ML 模型的数据子集)~30%

尽量平衡两个集合中的类数,使结果不偏不倚或者成为模型训练不足的原因之一。这是机器学习模型的关键部分。在现实世界的问题中,存在不平衡类的情况,需要使用像过采样少数类、欠采样多数类(scikit-learn 包中的重采样函数)或使用 Imblearn 包中的 SMOTE 功能生成合成样本等技术。

在这种情况下,数据分为两部分,训练和测试,70%在训练中,30%在测试中。在进行拆分时,最好在训练和测试数据中平均分布类别。这里使用了 scikit-learn 包中的函数 train_test_split

输出:

从上面的输出可以看出,数据是按比例分配给每个类的。打印训练和测试中每个情感的行数。

PyTorch 入门

PyTorch 是一个开源的机器学习库,用于计算机视觉和自然语言处理,基于 Torch 库。PyTorch 的主要特点是使用 GPU 和深度神经网络进行张量计算。张量被定义为torch.tensor它们是像 Numpy 数组一样的多维数字数组,但是能够在 GPU 上运行。你可以从这里通过简单的教程,熟悉不同类型的张量

PyTorch 中深度学习的构建模块

  1. 亲笔签名 PyTorch 使用了一种叫做自动微分的方法。在神经网络中,您需要计算梯度,这样可以节省操作次数,因为它会记录完成的操作,并重放这些操作来计算梯度。
  2. Optim 要使用torch.optim,我们必须使用构造优化器对象。这通常需要包含需要优化的模型参数和优化相关参数(如学习速率、权重衰减等)的 iterable。
  3. nn 神经网络可以使用torch.nn构建。一个nn.Module包含层和一个返回输出的方法 forward(input)。

下面的代码显示了需要包含的主库以及如何识别当前设备。加载张量和进行计算的位置由神经网络层中使用的不同函数中的device参数决定。我已经使用 google colab 进行了实验,并在硬件加速器中设置了运行时 GPU,这就是为什么我可以看到torch.cuda.is_available在我的情况下是正确的。

输出:

我不会详细讨论神经网络是如何工作的,因为这不是这篇文章的主题。为了获得了解培训过程所需的基本信息,您可以在这里阅读

神经网络中使用的不同函数

通常在获得标注预测的输出图层上,softmax 函数与F.softmax一起使用。其他功能通过torch.nn.functional可用。目标函数是您的网络被训练以最小化的函数,在这种情况下称为损失函数或成本函数。在神经网络通过训练实例的每次迭代结束时计算损失。它们通过nn用于例如nn.NLLLoss()。为了优化网络,不同的算法,如 SGD,Adam 和 RMSProp 等。被使用。例如,要使用 SGD,您需要初始化optim.SGD。然后在初始化对象上的step()函数是在网络上完成优化的地方。

下面我们来深入探讨一下如何构建神经网络!我们将通过建立一个进行逻辑回归的基本网络来了解这一点。

生成输入和标签张量

第一步是要有函数,可以创建输入张量和相应标签,即输出张量,输入到网络进行训练。对于逻辑回归,我们将使用 BOW 向量作为输入,它只不过是语料库中词汇大小的数组,值是语料库中单词的频率,索引是单词的唯一 id。我们将从使用 Gensim 包的corpora.Dictionary构建的字典中获得唯一的 id。这类似于我在 BOW post 中所做的,但我添加了另一个名为 padding 的参数,它将用于其他任务,如 CNN,其中您希望对文档中的每个单词使用单词嵌入。对于此示例,填充被关闭。

之后,你就可以创建弓矢量函数了,如下所示。Vocab 大小为30056。您可以看到我在创建张量时是如何分配设备的:

为了创建输出张量,必须完成标签到正值的映射。目前我们用-1 表示阴性,这在神经网络中是不可能的。输出层中的三个神经元将给出每个标签的概率,因此我们只需要映射到正数。功能如下:

使用 BOW 的逻辑回归

使用 Softmax (s rc 的逻辑回归函数示例

逻辑回归是一种回归模型,但当对每一类的预测概率使用阈值时,可用于分类问题。它使用 Sigmoid 函数或 Softmax 函数来获得类的概率。Softmax 函数通常用于多类分类的情况。标签节点的最高概率将被选为该输入的预测类标签。Softmax 取输入向量 i = 1,2,..,K,并输出由与输入数的指数成比例的 K 个概率组成的概率分布。输出大小相同,值在范围(0,1)内,它们的总和都是 1。每个元素 Xi 被应用到 softmax,j 从 1 到 k。它如何工作的例子如下所示。

Softmax 公式(s rc

输出:

逻辑回归的架构:

  • 输入将与字典中的词汇大小相同
  • 输出大小将与标签数量相同
  • 正向函数将首先运行线性图层,然后计算值的 Log softmax。
  • SGD 优化器通常用于逻辑回归,因此在这里也以适当的学习速率使用。

首先让我们通过创建一个继承nn.Module的类来定义神经网络。forward功能被覆盖,以告诉网络如何向前传球。

让我们初始化模型对象,使用负对数似然损失函数和 SGD 进行优化的损失函数。对于损失,通常使用交叉熵损失函数,在这种情况下,您不需要单独计算 Log Softmax。这里我们分开使用它,这样你可以了解每个步骤的组成部分,以及如何在其他情况下实现或改变它们,如二进制分类。

终于我们准备好训练模型了!😃

训练逻辑回归模型

下面的代码将在 epochs 设置为 100 的训练数据上训练模型。

输出:

测试模型

一旦模型准备好了,我们现在就可以测试它。为了比较这些数字,我把张量带回了 cpu。我们将使用用于获取测试数据集上的输入张量的相同函数。

输出:

分类报告显示平均准确度为0.70。与用于训练的数据量相比,这是一个相当好的结果。可以对预测的概率值使用torch.argmax函数来获得标签。正面和负面情绪的准确性优于中性,这是有意义的,因为与正面和负面情绪中的常用词相比,很难区分中性评论。在上面的结果中,01分别代表负和正。

这种准确性优于我在以前的帖子中实现的方法,其中使用决策树分类器基于 BOW、TF-IDF、Word2Vec 和 Doc2Vec 向量作为输入进行分类。这表明,实现简单逻辑回归的神经网络可以更好地执行针对多个时期训练的简单 BOW 向量。它可以更好地提取词语和情感之间的关系并进行分类。本教程介绍 PyTorch 以及如何用它构建简单的分类器。

所以现在你可以很容易地用这种方法对你自己的数据集进行实验!我希望这有助于您理解如何使用 PyTorch 构建神经网络模型来对餐馆评论数据进行情感分析。请随意扩展这段代码!这适用于存在多个类别的任何其他文本分类问题。如果我可以考虑改进这个模型,我会使用不同的学习速率、时期,并尝试使用不同的输入类型,而不仅仅是弓。可以试试 TFIDF,Word2Vec,Doc2Vec 等。看看你会得到什么结果。预处理可以改为使用词汇化或其他词干算法来查看结果如何变化。

一如既往—愉快的实验和学习:)

基于逻辑回归的情感分类 Yelp 评论分析

原文:https://towardsdatascience.com/sentiment-classification-with-logistic-regression-analyzing-yelp-reviews-3981678c3b44?source=collection_archive---------14-----------------------

柴坦尼亚·皮拉拉在 Unsplash 上的照片

几周前你刚开了自己的公司。

你想了解顾客对你的产品和服务的感受,所以你去了社交媒体平台(推特、脸书等)。)来看看人家都说了些什么。

哇哦。好像已经有几千条关于你的生意的帖子了。你很兴奋,但是你很快意识到自己一个人读完所有的书是不可行的。

你开始怀疑:有没有办法从文本信息中提取客户的情绪?

古玩目录

  1. 为什么情感分析很重要?
  2. 什么是逻辑回归?
  3. 我们应该使用哪些指标来评估模型?
  4. 模型如何理解文本输入?
  5. 我们如何知道哪些文本特征是重要的?
  6. 我们能进一步改进我们的模型吗?
  7. 接下来我们能做什么?

动机

情感分析是一种非常有效的工具,不仅可以让企业了解整体品牌认知,还可以评估客户对特定产品线或服务的态度和情感[1]。

这种数据驱动的方法可以帮助企业更好地了解客户,发现他们观点的微妙变化,以满足不断变化的需求。

概观

这篇文章是我探索 Yelp 数据集的第二部分。有关数据集的更多信息,以及对其业务数据和提示数据的一些探索性数据分析,请参见我下面的帖子:

[## 发现你下一个最喜欢的餐馆 Yelp 数据集上的探索和可视化

你用 Yelp 找好餐馆吗?这篇文章揭示了流行的 Yelp 数据集中的见解和模式。

towardsdatascience.com](/discover-your-next-favorite-restaurant-exploration-and-visualization-on-yelps-dataset-157d9799123c)

这篇文章主要关注 Yelp 数据集中的 review.json 文件,它包含了 Yelp 用户写的评论。此外,每个评论都包括一个相应的“星级”,或用户对企业的评级,可以作为情绪的代理。目标是建立一个模型,在给定文本数据的情况下,可以对评论的情绪进行分类(正面或负面)。此外,我们感兴趣的是哪些文本特征是对该分类任务最有帮助的预测器。

逻辑回归

一般来说,有两种不同类型的分类模型:生成式模型(朴素贝叶斯、隐马尔可夫模型等。)和判别型模型(Logistic 回归、SVM 等)。).最终,两个模型都试图计算 p(类|要素)或 p(y|x)。关键区别在于,生成模型试图首先对联合概率分布 p(x,y)建模,然后使用 Baye 定理计算条件概率 p(y|x),而判别模型直接对 p(y|x)建模。关于这两种模型之间的比较的详细讨论,参见吴恩达的论文这里

在这篇文章中,我将检验一个流行的判别模型——逻辑回归。关于它的数学基础(sigmoid 函数、成本函数、决策边界等)的更多细节,见这篇文章。).

要查看我的完整 Python 代码,请查看我的 Kaggle 内核或我的 Github 页面。现在让我们开始吧!

偷看评论

让我们从评论数据集中取出126】百万条记录来进行分析。“文本”列将是我们的模型输入。让我们来看看一个有积极情绪的随机评论(评分为 5.0):

"I love Deagan's. I do. I really do. The atmosphere is cozy and festive. The shrimp tacos and house fries are my standbys. The fries are sometimes good and sometimes great, and the spicy dipping sauce they come with is to die for. The beer list is amazing and the cocktails are great. The prices are mid-level, so it's not a cheap dive you can go to every week, but rather a treat when you do. Try it out. You won't be disappointed!"

当我们考虑特征提取时,这里的几个线索可以帮助我们推断这是积极的情绪,如“爱”、“舒适”、“为...而死”、“令人惊叹”和“不会失望”。

让我们看一个负面评价(评分 1.0):

"If I could give less than one star, that would have been my choice.  I rent a home and Per my lease agreement it is MY responsibility to pay their Pool Service company.  Within the last year they changed to PoolServ.  I have had  major issues with new techs every week, never checking PH balances, cleaning the filter, and not showing up at all 2 weeks in the past 2 months. I have had 4 different techs in the past 4 weeks.   I have emailed and called them and they never respond back nor even acknowledged my concerns or requests.  I cannot change companies but I'm required to still pay for lousy or no service.  Attached are a couple pictures of my pool recently due to one tech just didn't put any chlorine in it at all according to the tech who came the following week to attempt to clean it up.  Please think twice before working with these people.  No one wants to work with a business that doesn't return phone calls or emails."

尽管它很长,但我们仍然可以看到诸如“不到一星”、“糟糕”、“从不回复”、“没有服务”等线索是有用的预测因素。

让我们快速确认数据中没有缺失值:

text     0.0
stars    0.0
dtype: float64

将评分转化为积极和消极情绪

让我们绘制收视率分布图:

我们可以看到,在 100 万条评论中,几乎有一半包含 5.0 的评级。

在这个任务中,我们希望将所有的评论文本分为两类:积极情绪和消极情绪。因此,我们首先需要将“星星”值转换成两个类别。在这里,我们可以将‘4.0’和‘5.0’视为正面情绪,将‘1.0’和‘2.0’视为负面情绪。我们可以将“3.0”视为中性,甚至将每个明星视为其自己的情感类别,这将使其成为一个多类分类问题。但是,为了简单的二进制分类,我们可以将带有“3.0”的排除在外。

然后,我们将积极情绪编码为 0 类,消极情绪编码为 1 类。因为我们知道类 0 中的样本比类 1 中的样本多,所以我们的基线模型可以是简单地将每个评论标记为类 0 的模型。让我们检查一下基线精度:

0.74

在我们继续之前,让我们花点时间了解一下评估指标。

评估指标

Jason Brownlee 在他的一篇文章中说,“分类器的好坏取决于用来评估它的度量标准”[2]。

在每个分类问题中,准确性可能不是合适的评估标准,特别是当类别分布不平衡时,以及当假阳性和假阴性的业务影响不相等时。例如,在信用卡欺诈检测问题中,预测每个交易是非欺诈的基线模型将具有超过 99.99%的准确度,但这并不意味着它是合适的模型,因为假阴性的百分比将是 100%,并且与假阳性相比,每个假阴性(未检测到欺诈交易)对企业和客户来说可能具有高得多的成本。

在此任务中,以下是一些合适的评估指标:

  1. 精度 — TP/(TP+FP),意思是模型归类为阳性的点实际上是阳性的比例。
  2. 回忆 — TP/(TP+FN),意思是被模型正确分类的实际阳性的比例。
  3. F1 得分—精确度和召回率的调和平均值。

查看这篇文章,了解关于这些指标的更多详细讨论。

在此任务中,我们将使用测试集上的 F1 分数作为关键评估指标。

列车测试分割

让我们留出 30%的数据作为测试集,按类标签分层。

train, test = train_test_split(df_reviews, test_size = 0.3, stratify = df_reviews['labels'], random_state = 42)

文本预处理

在大多数文本挖掘或 NLP 相关的任务中,清理文本是至关重要的一步。让我们首先删除所有非字母字符,标点符号,并确保所有字母都是小写字母。稍后我们还将评估移除停用词和词干化/词条化的效果。

矢量化

为了让模型能够处理文本输入,我们需要将它们转换成向量。有几种不同的方法来表示这些文本特征,下面是最常见的几种:二进制,例如,单词“good”是否存在。2.计数,例如“好”这个词在这篇综述中出现了多少次,类似于朴素贝叶斯中的单词袋模型。3.TF-IDF,这是与文档相关的每个文本特征的加权重要性(在此阅读更多)。

让我们首先尝试使用所有单字的二进制表示。

cv= CountVectorizer(binary=True, analyzer = text_prep, min_df = 10, max_df = 0.95)
cv.fit_transform(train['text'].values)
train_feature_set=cv.transform(train['text'].values)
test_feature_set=cv.transform(test['text'].values)

我使用了 sklearn 的 CountVectorizer 对象来提取所有的单词特征,如果这个单词出现在少于 10 条评论或超过 95%的评论中,就会被排除。

让我们检查一下我们的字典里有多少独特的单词:

train_feature_set.shape[1]
--------------------------------------------------------------------
40245

大约有 40K 个独特的单词。例如,让我们检查单词“tasty”的索引:

cv.vocabulary_['tasty']
--------------------------------------------------------------------
35283

适合 LR 车型

现在,我们准备使用 sklearn 拟合我们的第一个逻辑回归模型:

lr = LogisticRegression(solver = 'liblinear', random_state = 42, max_iter=1000)
lr.fit(train_feature_set,y_train)
y_pred = lr.predict(test_feature_set)
print("Accuracy: ",round(metrics.accuracy_score(y_test,y_pred),3))
print("F1: ",round(metrics.f1_score(y_test, y_pred),3))
--------------------------------------------------------------------
Accuracy:  0.955
F1:  0.914

让我们绘制一个混淆矩阵来可视化预测结果:

可视化特征重要性

逻辑回归的一个好处是,我们可以很容易地找到每个特征的重要性。让我们想象一下与消极情绪最相关的前 10 个词:

这些话在我们的预料之中。让我们检查所有包含“中毒”一词的评论,看看有多少属于负面情绪类别:

0.904

同样,让我们来看看积极情绪的前 10 个相关词:

注意,高肯定特征重要性与类 1 的高可能性相关,低否定(高绝对值)特征重要性与类 0 的高可能性相关。

在检查了积极的评论后,我意识到“对接”这个词在顶部,因为大多数给“4.0”星的评论都提到“我对接一颗星是因为……”。

改进策略

在我们建立了第一个模型之后,让我们检查几个想法,看看我们的模型是否可以进一步改进。

想法 1:降低概率截止阈值

为了减少假阴性,一种直觉是降低截止阈值(默认为 0.5)。这将提高召回率,但也会降低准确率。因此,我们需要检查这是否会提高 F1 的整体得分:

******** For i = 0.3 ******
F1: 0.91

******** For i = 0.4 ******
F1: 0.915

******** For i = 0.45 ******
F1: 0.915

******** For i = 0.5 ******
F1: 0.914

我们可以看到,F1 分数对该阈值的变化相对稳健。

想法 2:过采样类别 1 或欠采样类别 0

过采样少数类和欠采样多数类是处理不平衡分类的常用方法(此处阅读更多)。然而,在这种情况下,F1 分数并没有提高。

过采样等级 1 的性能:

Accuracy:  0.95
F1:  0.908

欠采样等级 0 的性能:

Accuracy:  0.947
F1:  0.904

想法 3:去掉停用词和词干

去除停用词和词干可以去除噪音,从而减少词汇量。然而,准确度和 F1 分数都略微降低

Accuracy:  0.949
F1:  0.902

想法 4:用 TF-IDF 代替二进制表示

这一次,F1 分数略有增加,但增幅不大。

Accuracy:  0.958
F1:  0.919

想法 5:将单词和双词作为特征包含进来

动机可以用这个例子来说明:

以我们最初开发的 LR 模型为例,然后在这篇评论中预测——“我不喜欢食物或服务”:

test_review = cv.transform(["I did not enjoy the food or the service"])
lr.predict_proba(test_review)
--------------------------------------------------------------------
array([[0.50069323, 0.49930677]])

该模型认为这一评论是积极的,因为该模型只接受与积极情绪相关联的单词,如“enjoy”,而不考虑否定“enjoy”含义的“did not”。

在我们把单词和双词(两个单词的序列)都考虑进去之后,我们首先看到词汇量的增加:

488683

拟合该模型后,我们看到两个指标都有所改善,尤其是 F1 得分。

Accuracy:  0.969
F1:  0.942

让我们再次检查它对同一个句子的预测:

test_review = cv.transform(["I did not enjoy the food or the service"])
lr.predict_proba(test_review)
--------------------------------------------------------------------
array([[0.2678198, 0.7321802]])

现在,它以相对较高的可信度做出正确的预测。

我们可以再次看到正面和负面情绪的 10 大新特征:

我们开始看到诸如“两颗星”、“不值得”、“不谢谢”、“不推荐”之类的二元词出现在热门功能中。

请注意,“失望”可能看起来是一种消极的情绪,但这可能是因为它是“不要失望”短语的一部分。

我们应该包括三元模型(三个单词的序列)或者更高阶的 N 元模型吗?请注意,随着我们包含越来越高阶的 N 元文法,我们的特征大小变得越来越大,这消耗了更多的内存空间,并且还存在极度稀疏的问题(在此阅读更多)。

后续步骤

以下是对后续步骤的一些想法:

  1. LR 模型中有几个超参数我们可以调整,调整它们可以得到更优化的模型。此外,为了避免过度拟合,尝试交叉验证以获得每个模型更准确的指标(点击这里查看 grid search)。
  2. 将“3.0”视为中性,或将每个类别视为其自己的类别,并重新制定这些模型。
  3. 建立一个交互式情感分析器,允许用户输入评论,并给出对其情感的预测。具有增量学习的内置功能,用户可以帮助模型在做出错误预测时进行学习。

摘要

让我们回顾一下。

我们使用逻辑回归建立了一个情感分类模型,并尝试了不同的策略来改进这个简单的模型。在这些想法中,包含二元模型作为特征对 F1 分数的提高最大。对于简单模型和改进模型,我们还分析了其最重要的文本特征。

我希望你喜欢这篇文章,并请分享你的想法:)

DS/ML 初学者?查看我的另一篇关于如何使用经典 Iris 数据集构建第一个 Python 分类器的帖子:

[## 使用 Python Scikit-learn-Iris 数据集探索分类器

如何用 Python 构建第一个分类器的分步指南。

towardsdatascience.com](/exploring-classifiers-with-python-scikit-learn-iris-dataset-2bcb490d2e1b)

参考

[1]http://copper Taurus . com/insights/opinion-analysis-Product-management/#:~:text = Product % 20 reviews % 20 provide % 20 opinion % 20 analysis,successive % 20 refinement % 20 of % 20 their % 20 offering。【2】https://machine learning mastery . com/tour-of-evaluation-metrics-for-unbalanced-class ification/

使用 VADER 的情感分析

原文:https://towardsdatascience.com/sentimental-analysis-using-vader-a3415fef7664?source=collection_archive---------1-----------------------

情绪的解释和分类

情感分析是一种文本分析方法,它检测文本中的极性(例如,正面意见或负面意见,无论是整个文档、段落、句子还是子句。

情感分析旨在基于文本中主观性的计算处理来测量说话者/作者的态度、情感、评价、态度和情绪。

来源:MonkeyLearn,图片链接:【https://bit.ly/2X806dW

为什么情感分析很难执行?

尽管理论上看起来很容易,但情绪分析是一个棘手的问题。一个文本可以同时包含多种情感。举个例子,

“演技不错,但电影本来可以更好”

上面这句话包含了两个极性!!!

VADER

VADER(用于情感推理的效价感知词典)是用于文本情感分析的模型,其对情感的极性(积极/消极)和强度(强度)都敏感。它在 NLTK 包中提供,可以直接应用于未标记的文本数据。

VADER 情感分析依赖于一个字典,该字典将词汇特征映射到情感强度,即情感得分。文本的情感得分可以通过对文本中每个词的强度求和得到。

例如,像、【爱】、【享受】、【快乐】、【喜欢】这些词都传达了一种积极的情绪。VADER 也足够聪明,能够理解这些词的基本语境,比如“不爱”作为否定陈述。也理解大写和标点符号的侧重点,比如“享受”**

极性分类

我们不会试图确定一个句子是客观的还是主观的,是事实还是观点。相反,我们只关心文本是否表达了积极的、消极的或中立的 T21 观点。

文档级范围

我们还会尝试将一个文档或段落中的所有句子聚合在一起,得出一个整体观点。

粗略分析

我们不会尝试进行精细的分析来确定积极/消极的程度。也就是说,我们并不试图猜测一个评论者给了多少颗星,只是想知道这个评论是正面的还是负面的。

主要步骤:

  • 首先,考虑被分析的文本。一个基于整段评论的模型可能是无效的。确保为手头的任务使用合适的模型。
  • 接下来,决定要执行的分析类型。一些基本的情感分析模型更进一步,考虑两个词的组合,或二元模型。我们将学习完整的句子,为此我们将导入一个名为 VADER 的经过训练的 NLTK 词典。

要使用的数据集

对于这个模型,您可以使用各种数据集,如亚马逊评论、电影评论或任何产品的任何其他评论。

**import** **nltk**
nltk.download('vader_lexicon')**from** **nltk.sentiment.vader** **import** SentimentIntensityAnalyzer

sid = SentimentIntensityAnalyzer()

VADER 的SentimentIntensityAnalyzer()接受一个字符串,并返回四个类别的得分字典:

  • 否定的;消极的;负面的;负的
  • 中立的
  • 积极的
  • 复合值(通过对上述的分数进行归一化计算)

让我们通过情感分析仪来分析一些随机陈述

a = 'This was a good movie.'
sid.polarity_scores(a)OUTPUT-{'neg': 0.0, 'neu': 0.508, 'pos': 0.492, 'compound': 0.4404}a = 'This was the best, most awesome movie EVER MADE!!!'
sid.polarity_scores(a)OUTPUT-{'neg': 0.0, 'neu': 0.425, 'pos': 0.575, 'compound': 0.8877}

使用 VADER 分析评论

**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**

df = pd.read_csv('../TextFiles/reviews.tsv', sep='**\t**')
df.head()

df['label'].value_counts() OUTPUT-neg    5097
pos    4903
Name: label, dtype: int64

清理数据(可选)

这一步是为了清除评论中的任何空白。

*# REMOVE NaN VALUES AND EMPTY STRINGS:*
df.dropna(inplace=**True**)

blanks = []  *# start with an empty list*

**for** i,lb,rv **in** df.itertuples():  
    **if** type(rv)==str:            
        **if** rv.isspace():        
            blanks.append(i)     

df.drop(blanks, inplace=**True**)

向数据帧添加分数和标签

现在,我们将向原始数据帧添加列,以存储 polarity_score 字典、提取的复合得分以及从复合得分派生的新“正/负”标签。我们将使用这最后一列来执行准确性测试。这种方法中的评论将被分为负面、正面和中性比率。

df['sc ores'] = df['review'].apply(**lambda** review: sid.polarity_scores(review))

df.head()

现在会将化合物作为单独的列,所有大于零的值都将被视为正面评价,所有小于零的值都将被视为负面评价。

df['compound']  = df['scores'].apply(**lambda** score_dict: score_dict['compound'])

df.head()

df['comp_score'] = df['compound'].apply(**lambda** c: 'pos' **if** c >=0 **else** 'neg')

df.head()

所以现在我们有了一个完整的分析,无论是正面的还是负面的。

现在让我们通过一些新的评论来测试我们的模型表现如何!

*# Write a review as one continuous string (multiple sentences are ok)*
review = 'The shoes I brought were amazing.' # Obtain the sid scores for your review
sid.polarity_scores(review)OUTPUT-
{'neg': 0.0, 'neu': 0.513, 'pos': 0.487, 'compound': 0.5859}review='The mobile phone I bought was the WORST and very BAD'# Obtain the sid scores for your review
sid.polarity_scores(review) OUTPUT-{'neg': 0.539, 'neu': 0.461, 'pos': 0.0, 'compound': -0.8849}

结论

VADER 分析的结果似乎不仅显著,而且非常令人鼓舞。结果显示了在网站中文本数据可能是一系列文本的复杂混合的情况下,通过利用 VADER 将获得的优势。

额外资源

我在《走向数据科学》杂志上发表了两篇关于这个博客相关主题的文章。为了更好地理解自然语言处理,请阅读这些文章

词干 vs 词汇化——https://link.medium.com/JWpURpQjt6

词语向量和语义—https://link.medium.com/tuVCswhYu6

这只是对什么是情绪分析以及 VADER 如何工作的一个小小的窥探。如有任何疑问和澄清,请随时回复本博客。

谷歌 Play 商店应用点评

原文:https://towardsdatascience.com/sentiments-of-google-play-store-apps-reviews-13f9ee7246c6?source=collection_archive---------36-----------------------

基于评论者报告的情绪分析谷歌 Play 商店应用程序评论

关于这篇文章

他的文章在谷歌 Play 商店应用评估的背景下讨论了一个数据可视化项目的结果。T2 谷歌 Play 商店 T3 是世界上使用最多的数字分发服务之一,拥有大量的应用程序和用户。因此,有很多关于应用程序及其用户评价的数据可用。
该项目是作为巴西纳塔尔北里奥格朗德联邦大学 Metrópole Digital 学院的数据科学 I 课程的一部分征集的,用于练习课堂上所学的科目。

方法

在这个项目中,我们将在 Kaggle 中可用的谷歌 Play 商店应用数据集中搜索趋势。为此,我们将确定一些初始假设,并试图找到有助于巩固这些假设的信息。我们将使用 Google ColabPython 来完成这个项目。
这个项目使用的代码可以在这个 GitHub 库中找到。

设置和下载数据

该项目中使用的软件包有:

  • Google . Colab:Google Colab 中的文件操作;
  • Kaggle :从 Kaggle 网站导入数据集;
  • 熊猫:数据集操作;
  • NumPy :处理数学运算;
  • Pyplot :创建图形和表格。

代码 01:设置环境和下载数据。作者代码。

通过 Kaggle API,我们可以下载数据集。我们的主数据集包含谷歌 Play 商店可用应用程序的信息,还有一个包含应用程序评论信息的辅助数据集。

过滤评论

代码 02:过滤评论。作者代码。

表 01:过滤的评论数据集。图片作者。

reviews 数据集包含大量无效观察值。由于我们将使用数字数据,并且无法识别缺失数据的值,因此最好完全删除这些观察值。这个项目中不会用到“翻译评论”这一栏,所以我们也可以删除它。此外,可以优化列的名称。
每个应用程序都有多个评论,所以我们需要与它合作。

转换

正如我们在 unique 方法中看到的,情绪列假设了三个值:负面的、中性的和正面的。知道了这一点,我们可以应用李克特量表来评估这些信息的数值。
李克特量表是问卷中最常见的心理测量量表。它包括要求回答者在从负面到正面的范围内评价某事。
对于本项目,李克特量表为-1 表示负面,0 表示中性,1 表示正面。这样,当计算平均值时,我们得到一个介于-1 和 1 之间的数字,其中较高的值意味着更多的正面评价,较低的值意味着更多的负面评价,以及更接近零的中性。

代码 03:转换数据。作者代码。

组合和重新过滤

函数 merge 将完成几乎所有需要的工作。常见的一栏是 app 名称,是 reviews_mean 的索引。因为索引保留了“App”这个名称,所以该函数仍然可以访问它。默认的“内部”方法将只保留两个数据集中有值的观测值。
得到的数据集有 1229 个观测值,而 reviews_mean 有 865 个观测值。这意味着出于某种原因,我们的数据集中有多个外观的应用程序。删除重复将确保每个应用程序只有一个观察。

现在,我们将只选择所需的列,并将 Installs 列的值更改为 numeric。

代码 04:合并和重新过滤数据。作者代码。

表 02:过滤后的数据集。图片作者。

分析

首先,我们先建立一些初始假设。这些可能是在调查数据或初步猜测之前看起来合乎逻辑的事情。

  1. 情绪影响 app 的最终评分;
  2. 付费内容会有更好的评分;
  3. 热门类别有更积极的情绪。

人气和评分

代码 05:创建直方图。作者代码。

让我们检查一下我们现在的数据。为此,我们希望看到情绪和评级的直方图。如果我们的假设是真的,如果情绪有很多高值,那么评级也会有很多高值,这意味着在我们的数据集中这两个变量之间有很高的相关性。

图 01:情绪和评级直方图。图片作者。

查看直方图,我们可以看到两列都有积极的趋势。在情绪方面,大多数值都高于中性值(0),在-1 到 1 的范围内约为 0.5。但是对于评级栏来说,这种趋势看起来更加明显,在 0 到 5 的范围内,许多值都在 4 到 5 左右。

代码 06:计算中位数并绘制散点图。作者代码。

中间值有助于形象化。作为第二个资源,我们可以通过评级绘制一个情绪线图,并查看线条的行为。如果情绪影响了评级,我们可以预期接近直线上升。

图 02:情绪 x 评级散点图。图片作者。

付费内容和评级

首先,我们需要分离内容类型(免费和付费)。然后,我们可以得到每个类别的平均值。

代码 07:计算免费和付费内容的平均值。作者代码。

正如我们所见,付费内容的平均值略高于免费内容的平均值。但是这种差异似乎不足以支持我们的假设。此外,只有 9 个付费应用程序,这可能会误导由于低数量的观察信息。

热门类别和人气

代码 08:绘制渐变线。作者代码。

在我们的数据集中,我们有 Installs 列,包含应用程序被安装的次数,通过分组和排序,我们获得了类别的流行度排名。

让我们来看看人气排名中的情绪反应。我们将使用渐变线来帮助我们看到图形中的变化。

图 03:人气排名 x 人气的渐变线。图片作者。

结果

我们所有的三个假设都在分析部分被观察到了。由于我们只是试图看到数据的宏观状态来猜测关于它的事情,而没有使用任何真实的信息测试或推断,我们无法做出任何假设。尽管如此,这个项目的工作可以帮助创造一个更好的假设。

  • 假设 1 :直方图指出了情绪和评级之间的某种联系,但这可能是由于相似的因果关系,而不是由于这两个变量之间的相关性。之后创建的散点图没有添加任何新的信息,保持我们从直方图的猜测。
  • 假设 2 :由于付费类别的观察数量较少,该数据集不适合回答我们的假设。分析手段,两者并无显著差异。
  • 假设 3 :观察创建的图形,没有明确的信息可以获得。随着受欢迎程度等级降低,更高情感值的出现更少,这可能有助于我们最初的假设。

下一个

在未来的工作中,有许多可行的方法来继续这个项目。首先,有可能假设其他假设,并尝试像我们所做的那样将其可视化。
另一种可能是通过统计检验和方法来验证这里提出的假设。

最后,人们可以用推理的方法接近数据集,试图找到关于它的新信息。例如,卡方检验可以应用于这里使用的李克特量表。

参考文献

python 中的 Sentinel-2 图像聚类

原文:https://towardsdatascience.com/sentinel-2-image-clustering-in-python-58f7f2c8a7f6?source=collection_archive---------23-----------------------

关于如何在 python 中使用 scikit-learn 和 rasterio 执行无监督分类的分步教程

左图:苏丹杰济拉州 Elhasaheesa 地区的 Sentinel-2 图像。右图:Elhasaheesa 聚类图像(4 类)。

聚类或无监督分类是根据统计相似性将图像的像素值分组或聚集成一定数量的自然类(组)的过程。在本教程中,我们将在 jupyter 笔记本中使用 rasterio 进行 sentinel-2 图像操作,并使用 power fullscikit-learnpython 包进行聚类。

Scikit-learn 是一个针对 Python 编程语言的免费软件机器学习库,包含各种分类、回归和聚类算法。要安装此软件包:

conda install -c anaconda scikit-learn

Rasterio 是一个开源的 python 库,可以读写不同格式的栅格数据集,如卫星影像和地形模型,如 GEOTIFF 和 JP2。

conda install -c conda-forge rasterio

算法: Scikit-learn 有不同的聚类算法,这些算法可以直接从聚类子库中导入。 K-Means 算法简单,是聚类中使用最多的算法之一。它基本上将 n 个观察值(在我们的例子中是像素值)分成 k 个簇(由用户预先定义的类的数量),其中每个观察值属于具有最近平均值的簇。本教程将基于 K-means,但你可以很容易地切换到尝试其余的,代码将几乎保持不变,但你只需要改变算法。

本教程将分别使用苏丹杰济拉州 El-hasaheesa 和 Elmanagel 地区的 Sentinel-2 图像进行训练和预测。这个数据和本教程的完整代码可以在 github 上找到。

要开始这项工作,首先要导入所有需要的包:

import rasterio as rio
from rasterio.plot import show
from sklearn import cluster
import matplotlib.pyplot as plt
import numpy as np

然后将使用 rasterio 打开图像并读入其元数据

# Open the image 
elhas_raster = rio.open("Elhasaheesa.tif")print(elhas_raster.meta)

元数据为我们提供了有关图像的信息,如数据类型、大小(宽度、高度)、计数(波段数)和坐标参考系统。为了更好地可视化这张图像,首先需要通过拉伸来调整它的对比度,你可以在这里 阅读更多关于图像增强的内容

# Read, enhance and show the image
elhas_arr = elhas_raster.read() # read the opened image
vmin, vmax = np.nanpercentile(elhas_arr, (5,95))  # 5-95% contrast stretch# show the enhanced image
plt.figure(figsize=[20,20])
show(elhas_raster, cmap='gray', vmin=vmin, vmax=vmax)
plt.show()

如果我们打印此图像的形状,我们会看到它的顺序为(带、高、宽),这需要首先更改为形状顺序(高、宽、带)。我们将通过以下方式改革这一模式:

  • 使用元数据中的图像大小、计数和数据类型创建一个空数组。
  • 使用一个 for 循环来分割每个波段,并在我们的空数组中重组它。

在这个循环的最后,我们将得到一个具有所需形状顺序的新数组,它具有相同的大小和带数。

# create an empty array with same dimension and data type
imgxyb = np.empty((elhas_raster.height, elhas_raster.width, elhas_raster.count), elhas_raster.meta['dtype'])# loop through the raster's bands to fill the empty array
for band in range(imgxyb.shape[2]):
    imgxyb[:,:,band] = elhas_raster.read(band+1)

现在,我们几乎准备好训练我们的分类器,但首先,我们需要将我们的 X(宽度)和 Y(高度)维度转换为 1 维,因此要有一个 2d 数组而不是 3d 数组,然后我们可以将它提供给 K-means 分类器。

# convert to 1d array
img1d=imgxyb[:,:,:3].reshape((imgxyb.shape[0]*imgxyb.shape[1],imgxyb.shape[2]))

训练:要设置的最重要的参数是 n_clusters ,它表示我们要将像素分组到的簇的数量,在我们的图像中,我们可以直观地看到它有三个主要类别(建筑区、裸地和耕地),但我们还有一个额外的类别,即感兴趣区域之外的黑色区域,其像素也可以分组到一个组中。K-means 有一些其他参数,如最大迭代次数和初始化次数,但在本教程中我们将把它们保留为默认值。

cl = cluster.KMeans(n_clusters=4) # create an object of the classifier
param = cl.fit(img1d) # train itimg_cl = cl.labels_ # get the labels of the classes
img_cl = img_cl.reshape(imgxyb[:,:,0].shape) # reshape labels to a 3d array (one band only)

为了显示结果图像,我想使用一个自定义的颜色图,我可以控制每个类的颜色。我们将保持外部区域为黑色,其余的类使用红色、绿色和黄色。

# Create a custom color map to represent our different 4 classes
cmap = mc.LinearSegmentedColormap.from_list("", ["black","red","green","yellow"])# Show the resulting array and save it as jpg image
plt.figure(figsize=[20,20])
plt.imshow(img_cl, cmap=cmap)
plt.axis('off')
plt.savefig("elhas_clustered.jpg", bbox_inches='tight')
plt.show()

预测:一旦训练了分类器,就可以用它来预测任何看不见的图像中的相同的学习聚类。我们将使用 Elmanagel locality(与 Elhasaheesa 相邻)的图像来预测上面的 4 个类。

要使用 Elmanagel 的图像进行预测,我们需要对之前的图像进行所有的预处理(重新调整形状并重新形成 2d 数组),然后才能将其提供给分类器。此外,还需要前面相同的步骤来显示得到的预测聚类。

# open the raster image
elmanagel = rio.open(‘elmanagel.tif’)# create an empty array with same dimensions and data type 
elman_xyb = np.empty((elmanagel.height, elmanagel.width,elmanagel.count), elmanagel.meta['dtype'])# loop through the raster bands and fill the empty array in x-y-bands order
for band in range(elman_xyb.shape[2]):
    elman_xyb[:,:,band] = elmanagel.read(band+1)# convert to 1d array
elman_1d = elman_xyb[:,:,:3].reshape(elman_xyb.shape[0]*elman_xyb.shape[1], elman_xyb.shape[2])# predict the clusters in the image 
pred = cl.predict(elman_1d)# reshape the 1d array predictions to x-y-bands shape order (only one band)
elman_cul = pred
elman_cul = elman_cul.reshape(elman_xyb[:,:,0].shape)

现在让我们在子图中显示原始图像和结果预测图像,但首先,我们将通过对比度拉伸来增强原始图像,以便更好地查看。

elman_arr = elmanagel.read() # Read the image
vmin, vmax = np.nanpercentile(elman_arr, (5,95)) # 5–95% contrast stretch# show the original and predicted image
fig, (ax1,ax2) = plt.subplots(figsize=[15,15], nrows=1,ncols=2, sharey=False,)
show(elmanagel, cmap='gray', vmin=vmin, vmax=vmax, ax=ax1)
show(elman_cul, cmap=cmap, ax=ax2)
ax1.set_axis_off()
ax2.set_axis_off()
fig.savefig("pred.png", bbox_inches='tight')
plt.show()

左图:原图。右图:集群图像。

参考文献

[## 卫星图像聚类

应用科学与技术丛书(BRIEFSAPPLSCIENCES)遥感的一部分

link.springer.com](https://link.springer.com/chapter/10.1007/978-981-13-6424-2_3) [## sci kit-学习

“我们使用 scikit-learn 来支持前沿基础研究[...]" "我认为这是我设计过的最棒的 ML 套装…

scikit-learn.org](https://scikit-learn.org/stable/) [## Rasterio:访问地理空间栅格数据- rasterio 文档

编辑描述

rasterio.readthedocs.io](https://rasterio.readthedocs.io/en/latest/) [## 遥感概论

为什么我们要增强卫星图像?使用不同的图像增强方法来准备“原始数据”,以便…

seos-project.eu](https://seos-project.eu/remotesensing/remotesensing-c05-p02.html)

软件设计中关注点的分离

原文:https://towardsdatascience.com/separation-of-concerns-in-software-design-aaad847b3b44?source=collection_archive---------26-----------------------

应用计算机科学的基本原理来提高各级软件的质量

艾伦·格林伍德在 Unsplash 上的照片

关注点分离 (SoC)是软件开发中最基本的原则之一。

SoC 是如此重要,以至于 5 个坚实的原则中有 2 个(单一责任和界面分离)是从这个概念直接衍生出来的。

原则很简单:不要把你的程序写成一个完整的块,相反,要把代码分解成小块,这些小块是系统中最终确定的小块,每个小块都能够完成一项简单而独特的工作。

在这篇文章中,我详细阐述了在抽象的所有层次应用这个深刻的原则:从每个功能内部的编程代码和模块的设计到整个应用程序的架构,所有这些都是为了实现我们所说的定性软件的特征。

用于编程功能的 SoC

如果我们拿最底层(实际的编程代码)来说,SoC 指导我们避免编写冗长复杂的函数。当函数开始变大时,这是一个危险信号,表明该方法可能一次处理太多的事情。

在这种情况下,SoC 推动我们重构它,变成一个更简洁、更具描述性的版本。在这个过程中,原始算法的一部分被导出并封装在具有私有访问级别的独立的较小函数中。我们获得了代码的清晰性,算法的大部分最终变得可以被其他部分重用,即使我们最初没有预料到这种情况会发生。

模块的 SoC

在更高的层次上,这一原则告诉我们将功能分组到独立的模块中,每个模块负责完成一组具有明确逻辑关系的任务。

这个过程非常类似于我们必须为功能所做的事情:分离不太相关的功能,并将服务于相同明确目的的功能组合在一起

内聚和耦合

关注点分离的应用包括两个过程:减少耦合和增加内聚

内聚性是通过职责集、细节层次和位置来衡量相似性。比如函数drawCircledrawTriangle足够内聚,属于同一个负责绘图的模块,感觉在代码中把这两个函数放在一起很自然(高相似~高内聚)。

耦合则是衡量该部分对系统其余部分的依赖程度(低依赖~松耦合)。

前述的drawCircledrawTriangle可以被另一个功能drawCybertruck使用。我们也可以将这个函数放在绘图模块中,但是drawCyberthuck可能依赖于物理引擎和外部状态。因此,这将使整个绘图模块的可重用性大大降低,并与其他一些组件紧密耦合。

你可以看出原始绘图函数和drawCyberthuck属于不同的抽象层次和逻辑复杂度,因此它们需要驻留在不同的模块中。

如果在某个时候我们决定在另一个项目中使用绘图模块——将不再依赖于物理引擎,所以我们将能够更容易地提取它。

一种快速记住应该增加或减少哪个属性的方法:

  • 解耦是好的——所以我们需要瞄准一个松耦合
  • 内聚的代码是好的——我们需要瞄准高内聚

高内聚(低分散)代码的一个很好的例子是使用闭包回调而不是委托方法。

这里我应该注意,代码示例是在 iOS 应用程序开发的环境中用 Swift 编写的,但并不太多,它们很好地展示了这个概念。

考虑发送网络请求的代码:

// configuring and sending the request
session.send(request: URLRequest) { response in
    // handling the response
}

想象一下,如果 URLSession 有一个基于委托的 API 来发出请求:所有的响应都将被交付给一个函数handle(response: URLResponse, for request: URLRequest)

这将使网络更加容易出错和乏味,因为处理所有响应的逻辑现在必须绑定到那个函数。

使用基于回调的 API,动作和动作的结果在一个地方处理,这使得跟踪执行流更加容易。

如果我们需要在函数或模块之间跳来跳去,因为我们遵循算法的逻辑,这意味着代码具有低内聚,这通常被称为意大利面条代码

松耦合和高内聚的好处

遵循关注点分离的原则有助于改进代码库的许多特性:

  1. 更清晰的代码。当每个模块都有一个简洁明了的 API 和一组有逻辑作用域的方法时,理解程序中发生的事情就容易多了。
  2. 更好的代码重用性(干原理)。重用代码的主要好处是降低了维护成本。每当您需要扩展功能或修复 bug 时——当您确定它只出现在一个地方时,这样做就不那么痛苦了。
  3. 更好的测试性。具有适当范围功能的独立模块以及与应用程序其余部分的隔离很容易测试。您不需要设置整个环境来查看您的模块如何工作——用虚拟模拟或假数据源替换相邻的真实模块就足够了。通过这种方式,您可以通过验证输出将模块测试为黑盒,或者通过查看在连接的模块上调用了哪些方法将模块测试为白盒( BDD )。
  4. 更快的项目进展。无论是新功能还是现有功能的更新,模块的隔离都有助于确定程序中可能受变化影响的区域,从而加快开发速度。
  5. 更容易组织多个工程师同时开发。他们只需要就他们在哪个模块上工作达成一致,以确保他们不会互相干扰。只有模块 API 的更新可以作为明确通知其他开发人员的标志,而大多数更改可以在其他贡献者没有立即注意的情况下添加。当与良好的测试覆盖相结合时,并行开发变得和每个单独工作的工程师的累积生产率一样有效(它通常更慢)。

如你所见,从程序员的角度来看,耦合和内聚是最终影响使用代码的便利性的特征。

用于系统设计的 SoC

对于一堆具有不同职责和明确目的的模块,我们仍然需要概述一个全局策略,以说明模块之间应该如何相互引用。

如果我们不引入这种策略,我们可能会以一个关系错综复杂、数据流难以跟踪的系统而告终。

系统设计的主要目标是勾勒出模块相互感知的边界。

每个现有的架构模式都提供了这种策略。以我们为例,模型-视图-控制器,我们会看到视图不允许与模型直接交互,而应该使用控制器作为中介。

在我看来,这些策略往往来自于纵容不好的普遍观念。在我看来,这要么导致过度设计的解决方案,要么导致职责分离不足的系统。

我倾向于认为系统的设计需要一个更加正式的方法,有明确的标准和动机。

我们已经看到,当 SoC 应用于功能和模块时,总是会产生更多可重用、可测试和可维护的代码。那么,为什么不将内聚性和耦合性作为这些指标,并在应用程序级别应用 SoC 呢?

这就是我们如何将模块分成的方法。这不是一个具体的架构模式,而是我刚才谈到的策略的高级规范。

模块按层分组,就像我们从一组不同的功能中形成一个模块一样。

基于系统中相似的职责和相同的抽象级别,在一层中产生的模块集具有高度的内聚性,而层之间的通信和环境感知非常受限,以实现松散耦合。

我们不仅限制了通信——底层具有更高环境细节的层(存储库,如数据库包装器或网络服务)被禁止直接引用在更高层(业务逻辑或 UI)中定义的任何东西。

因此,如果我们只采用与后端对话的网络服务,它应该对系统的其余部分一无所知并且只提供发送请求的 API。

业务逻辑层将知道并使用该存储库,但是它不知道是否有任何 UI 附加到系统上。

UI 层知道业务逻辑模块,并使用它们的 API 来读取最新的数据和触发动作,但同时,它对存储库一无所知,因为业务逻辑对它隐藏了实际的底层基础结构。

这样我们可以保证整个系统内在的可测试性,其中每一层要么不知道另一层的存在,要么是高度解耦,很容易被测试中的模拟包围。

贮藏室ˌ仓库

尽管业务逻辑和 UI 的解耦是一个标准举措,但我发现令人惊讶的是,我们为 iOS 开发的大多数流行模式都没有强调业务逻辑与数据网关(如网络层)解耦的重要性。

我多次看到请求直接从视图控制器或其他业务逻辑模块发出。数据库查询、用户默认值和任何其他本地或远程数据存储也是如此。

正如您可能猜到的,我不喜欢这里的紧耦合。但这不仅仅是模块之间的耦合,这或多或少是可以容忍的。

我们讨论的是算法的输入和算法本身之间的紧密耦合。这样的代码几乎不可能测试或进化。

您不希望在业务逻辑中嵌入直接读写操作的原因有很多,因此无法轻松地用模拟的调用交换真实的调用:

  1. 在运行未完成的算法时,您可能会意外损坏有价值的数据
  2. 对真实数据的访问可能很慢(本地资源的文件很大,访问远程资源时网络/测试服务器很慢)
  3. 外部数据可能不可用(本地数据库为空,需要预先填充,服务器关闭或互联网连接中断)
  4. 后端可能会在你意想不到的时候突然改变响应格式

后一种情况是臭名昭著的。当然,在一个理想的世界里,这种情况永远不会发生,但它确实发生了,而且比你想象的还要频繁。就算是 CI 也救不了你。

应用程序将停止工作,而第一个被指责的人将是你,移动工程师。你的应用损坏。在失败被发现后的最初几分钟,你不得不找借口,看起来很可怜。

想象一下,你公司的首席执行官正在为投资者展示一个重要活动的应用程序,这种情况发生了。

理想的解决方法是:应用程序不会崩溃,而是优雅地显示一条用户友好的错误消息。我们交给老板另一个设备,它可以使用模拟的演示数据在离线模式下运行,演示继续进行,事故几乎没有被注意到。

离线演示模式?听起来工作量很大!但是如果您已经从数据网关中分离和抽象出来,就不是这样了。

当我们有一个从其他地方查询数据的业务逻辑模块时,我们需要将访问外部数据资源的问题提取到一个单独的模块中,并将不必要的查询细节隐藏在外观后面。

这就是知识库的形成过程。

让我们看一个例子。我们有一个 ViewController,它加载并显示一些项目的列表:

首先要做的是引入ListRepository协议并重构 ViewController 来使用它:

现在,我们可以自由地替换实际适用于后端的实现:

或者甚至在离线模式下提供演示数据的虚拟存储库:

通过这种设置,应用程序可以配置为使用真实的网络 API 或模拟数据,我们也可以将这些数据保存在捆绑资源中,而不是硬编码。

对于上面的例子,我还应该注意,当我们实现异步 API 调用的存根时,我们应该始终保持它的异步性(从内部DispatchQueue.main.async触发回调)。否则,我们将会释放萨尔戈。

您可以看到存储库在我为 SwiftUI 应用提议的 Clean 架构变体中扮演了一个固有的角色:

[## SwiftUI 的干净架构

VIPER、MVVM、Clean Swift (VIP)、RIBs 或 ELM 是否适合 SwiftUI 项目?

medium.com](https://medium.com/swlh/clean-architecture-for-swiftui-6d6c4eb1cf6a)

结论

关注点分离是一个巨人,他的肩膀上站着许多我们今天知道的时髦术语模式。仅仅这个原则就为软件质量在各个层面上的显著提高提供了必要的指导。

在编写代码或设计架构时,不要忽略它。松耦合和高内聚是你的朋友!

为了更好的可测试性,将算法从输入和输出中分离出来,即使没有坚实的基础,你的软件也会坚如磐石:)

推特上关注我,关注即将发布的帖子!顺便说一下,我所有的文章都可以在我的技术博客( RSS )中免费阅读:

[## 阿列克谢·瑙莫夫

iOS 开发最佳实践、软件架构设计、功能反应式编程、Swift、SwiftUI、Combine…

nalexn.github.io](https://nalexn.github.io/?utm_source=xm)

九月版:部署机器学习模型

原文:https://towardsdatascience.com/september-edition-deploying-machine-learning-models-309518cca140?source=collection_archive---------31-----------------------

月刊

从您的投资中获得最大收益

照片由来自 PexelsPixabay 拍摄

通常,数据科学任务的最后一步是部署。假设你在一家大公司工作。您正在为公司的客户构建一个项目,并且您已经创建了一个运行良好的模型。不幸的是,您创建的模型只有在客户拥有您编写的代码、您创建的环境和您一直在使用的机器的情况下才能被客户使用。

然而,如果您将您的模型部署到生产中,客户唯一需要的就是…产品。换句话说,一个机器学习模型将提供真正的价值,当它对用户可用时,它是为创建的。在投入生产之前,您的模型只是一个概念验证(PoC ),然后它就成为可交付产品。

有许多方法可以部署机器学习模型。部署的基本理念包括允许最终用户利用您的模型。产品需要根据最终用户的需求进行定制,因为他们将会使用它。部署是至关重要的一步,因为它允许其他人使用构建的机器学习模型。

选择如何将您的模型部署到产品中可能很困难,您需要评估最终用户想要什么和需要什么。也许你的模型需要实时工作。也许需要用它来一次做很多预测。你可能需要一个特定的架构,等等。一个产品可能有很多很多的需求,更重要的是,它需要在所有用例上工作,这就是为什么调试你的模型是必不可少的。

《走向数据科学》的编辑迈克尔·阿玛尼奥斯。

为什么我们用 Go 而不是 Python 部署机器学习模型

凯勒·凯瑟 — 5 分钟阅读

生产机器学习不仅仅是 Python 脚本

用 Python 开发 NLP 模型&用 Flask 逐步部署

苏珊李 — 6 敏念

Flask API,文档分类,垃圾邮件过滤器

部署 ML 模型有两种截然不同的方式,以下是两种方式

由汤姆·格雷克——9 分钟读完

如果一个 ML 模型用 Jupyter 做了一个预测,周围有人听吗?

使用 Streamlit 快速构建和部署仪表板

通过马腾 Grootendorst — 7 分钟读取

将您的 Streamlit 应用程序部署到 Heroku,展示您的数据解决方案

构建并部署您的第一个机器学习 web 应用

Moez Ali — 11 分钟读取

使用 PyCaret 在 Python 中训练和部署机器学习管道的初学者指南

构建 Web 应用来部署机器学习模型

李宗德魏恩 — 19 分钟读完

所以我们已经建立了我们的 ML 模型——现在呢?如何使用 Flask 离开 Jupyter 笔记本并进入 Web 应用程序!

如何使用 Angular 部署 TensorFlow Web 应用

詹姆斯·布里格斯

在角度构建的 web 应用程序中使用 Python 构建的模型

让我们部署一个机器学习模型

达里奥·拉德契奇 — 5 分钟阅读

如何在生产中使用机器学习模型

新视频

新播客

我们也感谢最近加入我们的所有伟大的新作家朱迪·周卡米拉·哈马尔契科娃金蒙·金罗恩·西林斯基尼尔斯·弗拉舍尔马特伊万·戴维斯达尼·索利斯布恩·杨史蒂夫·利文博士 罗宾·怀特安德烈亚斯·坎兹格泽戈尔兹·梅勒帕万·库马尔·博伊纳帕里阿列克谢·赫鲁斯塔列夫普拉蒂克·罗伊杰森·詹森德鲁·西沃德何塞·赫拉索等众多。 我们邀请你看看他们的简介,看看他们的工作。

英语到法语翻译的 Seq2Seq 建模

原文:https://towardsdatascience.com/seq2seq-modelling-for-english-to-french-translations-f6e4aa7aa02c?source=collection_archive---------42-----------------------

使用 Tensorflow 和 Keras 从头构建 Seq2Seq 网络

在隔离期间,我试图学习如何说法语,让自己有事可做。这一尝试并不成功,因此我建立了一个神经网络来尝试为我学习它。

为了做到这一点,我使用了一个具有注意力层的 seq2seq 递归神经网络,在加拿大第 36 届议会的众议院和参议院辩论中进行了训练(见此处)。基于注意力的 seq2seq 模型通常用于各种各样的任务,事实上,如果你曾经使用过 Siri 或谷歌翻译,你就有可能从这种模型中受益。

但是在我开始讨论我们如何自己构建一个之前,我认为快速了解 seq2seq 模型如何工作背后的一些理论是一个好主意——重点关注使这些模型表现如此良好的几个关键元素。

Alex OvsUnsplash 上拍摄

什么是 seq2seq 模型?

seq2seq 模型关于 NLP 的目标实质上是在考虑输入单词序列时计算输出单词序列的概率。这对机器翻译很有用,因为我们可能有一堆潜在的翻译,我们想知道哪个序列是最好的——例如狗是大的>大的是狗。或者我们可能需要选择一个最适合给定序列的词——例如上班迟到>上班慢跑迟到。

对于机器翻译,我们需要将一个单词序列编码成一个易于被模型消化的向量,然后让模型将这个向量解码成我们的目标语言。我们可以使用一个模型来进行编码和解码,但当您考虑到输入长度可能与输出长度不匹配时,问题就出现了,例如,“我妈妈爱法国”翻译成“ma maman aime la france”,需要一个额外的单词。这些输出序列长度不一定事先知道。

这将我们引向 seq2seq 模型。这个想法是,你得到一个模型——编码器——把一个单词序列转换成一个编码器向量,这个向量代表你要翻译的句子中的所有信息。然后你得到一个解码器,它使用 softmax 函数获取这个向量并输出翻译后的单词。

首先,编码器接受一个输入序列,并返回它自己的隐藏状态。当计算编码器隐藏状态(ht)时,我们只需要考虑当前输入(xt)和先前步骤隐藏状态(ht-1 ),因此等式看起来像这样

然后,解码器获取编码器的最后一个隐藏向量(c=ht)、前一个隐藏状态(ht-1)和前一个预测输出字(yt-1)。考虑到我们也是从编码器的最后一个隐藏向量计算的,我们使用先前预测的输出字可能看起来很奇怪,但是使用它允许 softmax 对当前预测(yt)产生影响。此外,yt-1 实际上给出了关于前一个单词是什么的明确答案,而不是概率分布,这有助于防止模型重复单词。所以总的来说,我们的解码器隐藏状态的公式看起来像这样-

现在我们需要做的就是在最后应用一个 softmax 函数,因为本质上这仍然是一个多类分类问题,但是现在我们的类是下一个时间步目标语言中的每个单词。

LSTM 细胞

因此,上面我们已经为 seq2seq 模型设计了结构。但是你可能想知道编码层和解码层是由什么组成的。编码器/解码器层可以由基本的 RNN 单元组成,但是这些单元不能在长序列中寻找上下文。因此,如果它试图根据前面的单词预测下一个单词,它可能会很好地处理类似“坐在椅子上的人”的事情,因为坐和椅子之间没有很大的差距。然而,对于像“正在做牛排…然后我坐下来吃牛排“它可能不会表现得很好,因为我们想要预测的单词(牛排)和这个单词的上下文之间有更大的差距(关于为什么 RNN 细胞在长序列上表现不好的详细信息,Bengio 等人有很好的论文详细说明了困难

这就是 LSTM 细胞的用武之地。不仅仅是将前一时间步的隐藏状态与当前输入相结合,还有四个层在起作用。基本的想法是,这些细胞可以将对未来决策有用的信息保存在细胞内。

加戈、詹妮弗·乔安娜&瓦斯科、瓦伦蒂娜&茹卡沃斯基、巴特克&帕塔奇尼、乌戈&蒂哈诺夫、瓦迪姆&维克托斯、胡安&巴拉格尔、卡洛斯。(2019).序列对序列自然语言到类人机器人手语。链接

在每个时间步,我们都要修改以下内容-

输入门-

遗忘之门-

输出-

前三个方程都非常相似。sigmoid 函数,因此它们的输出将位于 0 和 1 之间,这意味着它们的输出向量可以定义另一个向量可以通过第一个向量的量。xt 是当前输入,ht-1 是前一时间步隐藏层,W U 是权重。

然后我们有了新的存储单元,它与标准的 RNN 层相同,只是我们用输入向量的输出来控制它的输出。我们可以将这一层视为候选隐藏状态。

然后我们将它们与最终的存储单元和隐藏状态结合在一起。

输入门决定了我们对当前单词向量的关心程度。换句话说,它决定了你想让当前输入的新计算状态通过多少。例如,如果我们试图预测电影评论的情绪,但当前向量正在谈论这个人晚餐吃了什么,那么权重可能接近于零,当前向量将不会通过这个门。

输出门将对当前预测重要的内容与对未来重要的内容分开,因此它不会对当前时间步长的单元输出产生影响,但会改变其隐藏状态。这很有用,因为有时当前步骤可能现在对输出没有用,但以后可能会有一些好处。

遗忘门使用当前步骤输入来决定我们应该从长期状态(h(t-1))中遗忘什么。所以回到前面的例子,如果我们试图预测一部电影评论的情绪,而前面的时间步骤只是关于情节,而当前的时间步骤是“我讨厌它”,你可能会想忘记前面的信息,只关注当前的时间步骤。值得注意的是,所有这些门都是向量,我们不应该认为它们是绝对的,而是会忘记一个长期隐藏的单元的某些元素。

所有上面的层都是单层神经网络,然后我们把它们放在最终的存储单元(ct)中,就像这样-

这个等式有直观的意义,因为我们的遗忘门(ft)决定了我们想要忘记多少以前的记忆,所以我们将其应用于以前的时间步。同时,我们希望将当前时间步长的输入门(it)和标准 RNN 单元(c̃t)结合在一起。

最后,我们使用这个存储单元和输出门来确定时间 t -时的隐藏状态 ht

基本上就是这样了!要更详细地了解 LSTMs 是如何工作的,这里有一些很好的资源

[## 了解 LSTM 网络

2015 年 8 月 27 日发布人类不是每秒钟都从零开始思考。当你读这篇文章时,你…

colah.github.io](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)

注意层

在我们进入代码之前,我将快速讨论一下注意力层,因为它在这个模型的性能中起着很大的作用。

尽管 LSTM 单元对于单词远离模型试图预测的单词的上下文很有帮助,但它并没有完全缓解这个问题。注意层允许解码器关注在该时间步获得正确输出所需的序列部分,从而缩短输入字到其翻译之间的路径,从而减轻 LSTMs 可能具有的一些存储器限制。它通过提供一种针对源序列上的所有标记对目标序列中的标记进行评分的方式来实现这一点,并使用这种方式来改变解码器序列的输入。分数然后被输入到 softmax 激活中,以进行注意力分配。

注意力如何融入模型架构的其他部分?我们不是只发送编码器的最终状态,而是将其所有输出发送给解码器。在每个时间步,解码器的注意力单元计算所有这些编码器输出的加权和,并使用 softmax 激活函数确定在每个步骤中它将关注哪些单词。关于注意力机制的更详细的解释,请看这里

[## 注意力和增强递归神经网络

递归神经网络是深度学习的主要内容之一,允许神经网络与序列一起工作…

蒸馏. pub](https://distill.pub/2016/augmented-rnns/)

数据清理和准备

现在,我们已经快速浏览了理论,我们可以进入实际的编码,我不会覆盖项目中的所有代码,但会在最后将 github repo 与所有内容联系起来。此外,如果你的计算机上没有 GPU 访问,我会推荐使用谷歌 Colab 这样的东西,这样你就可以使用他们的免费 GPU,因为它将大大加快训练时间。

第一步是清理数据,并将其转换成可用的格式。要做到这一点,我们需要删除所有奇怪的东西,如空格,标点符号和不可打印的符号。

接下来,我们需要限制每个句子的长度,以加快训练速度。此外,对于目标序列,我们需要在每个序列的开头和结尾添加一个开始字符()和一个结束字符()。我们这样做是为了当我们想要翻译看不见的数据时,我们可以输入开始字符来让模型运行,并在翻译完成时给模型一个停止的方法。最后,我们需要填充英文数据,这样每个序列都是相同的大小。

我们准备的下一步是为每种语言创建字典,字典中的每个单词都与一个数字相关,该数字可以很容易地为模型进行编码。重要的是,我们将在字典中添加一个符号,用于解释模型词汇表之外的单词。

最后,我们必须实际编码我们的训练和测试数据。在每一个时间步,我们都将输入数据和下一步的目标数据提供给模型。

手套嵌入

因此,我们可以从这里直接进入建模,但我们可以采取一个额外的步骤,可以大大提高模型的性能。我不会说太多细节,但基本上我们可以在模型中给单词预设权重,以反映单词的相似程度——例如,国王和王后比国王和胡萝卜更相似。关于这个概念的更详细的观点,这里是原文——https://nlp.stanford.edu/pubs/glove.pdf

创建和训练模型

好了,现在我们已经做好了所有的数据准备,我们可以开始创建模型了。编码器模型是一个两层 LSTM,解码器是一个单层 LSTM,还增加了一个关注层。这提供了很好的性能,仅在几个时期后验证精度就达到了 0.96,但在未来,我希望研究双向 LSTMs 来提高性能。

在训练初始模型后,我们将训练好的层转移到推理模型中,这样我们就可以实际使用它了。

运行推理模型

最后,在创建我们的推理模型后,我们可以用它来翻译任何我们想要的英语句子!为此,我们将英语句子输入推理编码器,然后将编码数据和起始标记输入解码器。接下来,我们使用 while 循环继续遍历整个句子,直到模型预测到结束标记()或者达到最大句子长度。

测试模型

那么模型做的怎么样呢?我用下面验证集中的几个句子进行了测试-

接下来,我想尝试一个全新的句子

总的来说,只有几个训练时期非常棒!

结束语

在本文中,我们展示了 seq2seq 模型在机器翻译中的强大功能。然而,还有更多事情要做!在未来,我想引入波束搜索和双向层,因为它们可以进一步提高性能。对于这个项目中使用的完整代码,你可以访问 github repo 这里

注意:具有注意机制的序列 2 序列模型

原文:https://towardsdatascience.com/sequence-2-sequence-model-with-attention-mechanism-9e9ca2a613a?source=collection_archive---------4-----------------------

Bahdanau 和 Luong 提出的序列 2 序列模型中注意机制的详细解释

在本文中,您将了解到:

  • 为什么我们需要序列 2 序列模型的注意机制?
  • Bahdanua 的注意力机制是如何工作的?
  • Luong 的注意力机制是如何工作的?
  • 什么是本地和全球关注?
  • Bahdanau 和 Luong 注意机制的主要区别

先决条件:

像 LSTM 和 GRU 这样的循环神经网络(RNN)

Seq2Seq-神经机器翻译

什么是注意,为什么我们需要序列 2 序列模型的注意机制?

让我们考虑两个场景,场景一,你正在阅读一篇与当前新闻相关的文章。第二种情况是你准备考试。两种情况下的注意力水平是相同还是不同?

与新闻文章相比,你在准备考试时会相当注意阅读。在准备考试的时候,你将会更加关注关键词来帮助你记住一个简单或复杂的概念。这同样适用于任何深度学习任务,我们希望专注于感兴趣的特定领域。

序列到序列(Seq2Seq)模型使用编码器-解码器架构。

seq2seq 的几个用例

  • 神经机器翻译(NMT)、
  • 图像字幕,
  • 聊天机器人
  • 抽象文本摘要等。

Seq2Seq 模型将源序列映射到目标序列。在神经机器翻译的情况下,源序列可以是英语,目标序列可以是印地语。

我们将英语中的源句子传递给编码器;编码器将源序列的完整信息编码成单个实值向量,也称为上下文向量。这个上下文向量然后被传递给解码器,以产生目标语言(如印地语)的输出序列。上下文向量负责将整个输入序列总结成一个向量。

如果输入的句子很长,来自编码器的单个向量能否容纳所有相关信息提供给解码器?

在预测目标词时,是否可以关注句子中的几个相关词,而不是保存整个句子信息的单个向量?

注意力机制有助于解决问题。

注意机制的基本思想是避免试图学习每个句子的单个向量表示,而是基于注意权重来注意输入序列的特定输入向量。

在每一个解码步骤,解码器将被告知需要对每个输入单词给予多少“关注”,使用一组**。这些注意力权重向解码器提供上下文信息以进行翻译

巴赫达瑙注意机制

Bahdanau 等人提出了一种学习联合对齐和翻译的注意机制。它也被称为附加注意,因为它执行编码器状态和解码器状态的线性组合

让我们来理解巴赫达瑙提出的注意机制

  • 编码器(前向和后向)和解码器的所有隐藏状态都用于生成上下文向量,不像 seq2seq 中只使用最后一个编码器隐藏状态而不加注意。
  • 注意机制利用由前馈网络参数化的比对分数来比对输入和输出序列。它有助于注意源序列中最相关的信息。
  • 该模型基于与源位置和先前生成的目标单词相关联的上下文向量来预测目标单词。

注意机制

具有注意机制的 Seq2Seq 模型由编码器、解码器和注意层组成。

注意力层包括

  • 对准层
  • 注意力权重
  • 上下文向量

比对分数

比对分数映射了位置j”周围的输入和位置I”处的输出匹配得如何。分数基于预测目标单词之前的前一解码器的隐藏状态 s₍ᵢ₋₁₎ 和输入句子的隐藏状态 hⱼ

解码器决定需要关注源句子的哪一部分,而不是让编码器将源句子的所有信息编码成一个定长向量

与源序列具有相同长度的对齐向量,在解码器的每个时间步长进行计算

在我们的例子中,为了预测第二个目标词,,我们将为输入词 快速生成一个高分**

注意力权重

我们将 softmax 激活函数应用于比对分数,以获得注意力权重

Softmax 激活函数将获得总和等于 1 的概率,这将有助于表示每个输入序列的影响权重。输入序列的注意力权重越高,其对预测目标单词的影响就越大。

在我们的例子中,我们看到输入单词【तेज़ी】具有较高的注意力权重值****

上下文向量

上下文向量用于计算解码器的最终输出。上下文向量𝒸ᵢ是注意力权重和编码器隐藏状态(h₁、h₂、…,hₜₓ)的加权和,其映射到输入句子。****

预测目标词

为了预测目标单词,解码器使用

  • 上下文 vector(𝒸ᵢ),
  • 前一时间步的解码器输出(y ᵢ₋₁ )和
  • 前一个解码器的隐藏状态( sᵢ₋₁)

解码器在时间步长 I 的隐藏状态

卢昂注意机制

Luong 的注意力也被称为倍增注意力通过简单的矩阵乘法将编码器状态和解码器状态转化为注意力分数。简单的矩阵乘法使它更快更节省空间。****

Luong 根据注意力在源序列中的位置提出了两种类型的注意机制

  1. ****全局关注关注所有源位置
  2. ****局部注意力其中注意力仅放在每个目标单词的源位置的一个小子集上

全局和局部注意力的共性

  • 在解码阶段的每个时间步长 t,全局和局部注意这两种方法首先将堆叠 LSTM 顶层的隐藏状态 hₜ作为输入。
  • 这两种方法的目标都是导出一个上下文向量 𝒸ₜ 来捕捉相关的源端信息,以帮助预测当前的目标单词 yₜ
  • 注意力向量作为输入被馈送到下一个时间步骤,以通知模型关于过去的对齐决策。

全局和局部注意力模型在如何导出上下文向量𝒸ₜ方面有所不同

在我们讨论全局和局部注意之前,让我们先了解 Luong 的注意机制在任何给定时间 t 所使用的惯例

  • 𝒸ₜ:语境向量
  • aₜ:对齐向量
  • hₜ:当前目标隐藏状态
  • hₛ:电流源隐藏状态
  • yₜ:预测当前目标词
  • ˜ₜ : 注意力向量

全球关注

全球注意力来源:基于注意力的神经机器翻译的有效方法

  • 当计算上下文向量𝒸ₜ.时,全局注意力模型考虑编码器的所有隐藏状态
  • 通过将当前目标隐藏状态h与源隐藏状态 hₛ 中的每一个进行比较,得到等于源序列中时间步长数量大小的可变长度对齐向量t1】aₜ****
  • 比对分数被称为基于内容的函数,我们考虑了三种不同的备选方案

  • 全局上下文向量𝒸ₜ是根据对齐向量 aₜ 在所有源隐藏状态 hₛ 上计算的加权平均值

当源序列是大段或者大文档时会怎样?

当全局注意力模型考虑源序列的所有单词来预测目标单词时,它变得计算昂贵,并且翻译更长的句子可能具有挑战性****

我们可以通过使用局部注意来解决全局注意模型的这一缺陷

当地的关注

局部注意力来源:基于注意力的神经机器翻译的有效方法

  • 局部注意力只集中在每个目标单词的源位置的一个小的子集上,不像全局注意力那样集中在整个源序列上
  • 计算成本低于全局注意力
  • 局部注意力模型首先在时间 t 为每个目标单词生成对齐位置 Pₜ
  • 上下文向量 𝒸ₜ 是作为所选窗口内的源隐藏状态集合的加权平均值导出的
  • 可单调或预测地选择对齐位置

Bahdanau 和 Luong 注意机制的主要区别

双向编码器中前向和后向隐藏状态的 Bahdanau 级联。Luong attention 在编码器和解码器的顶层都使用隐藏状态

Bahdanau 和 Luong 注意机制中注意的计算

Bahdanau 等人在双向编码器中使用前向和后向隐藏状态的连接,在他们的非堆叠单向解码器中使用先前目标的隐藏状态

Loung 等人的注意力在编码器和解码器中的顶部 LSTM 层使用隐藏状态

Luong 注意机制使用当前解码器的隐藏状态来计算对齐向量,而 Bahdanau 使用前一时间步的输出

对齐功能

Bahdanau 仅使用 concat 评分比对模型,而 Luong 使用 dot、general 和 concat 评分比对模型

有了注意力机制的知识,你现在可以构建强大的深度 NLP 算法。

参考资料:

通过联合学习对齐和翻译 Dzmitry Bahdanau 的神经机器翻译

基于注意力的神经机器翻译的有效方法:Minh-Thang Luong Hieu Pham Christopher d . Manning

** [## 神经网络中的注意机制

在机器翻译中,编码器-解码器架构是常见的。编码器读取一个单词序列,然后…

devopedia.org](https://devopedia.org/attention-mechanism-in-neural-networks)**

序列模型和递归神经网络

原文:https://towardsdatascience.com/sequence-models-and-recurrent-neural-networks-rnns-62cadeb4f1e1?source=collection_archive---------9-----------------------

理解深度递归神经网络(RNNs)

序列模型

序列模型是输入或输出数据序列的机器学习模型。序列数据包括文本流、音频片段、视频片段、时间序列数据等。递归神经网络(RNNs)是一种用于序列模型的流行算法。

序列模型的应用 1。语音识别 : 在语音识别中,给定一个音频片段作为输入,然后模型必须生成它的文本副本。这里输入和输出都是数据序列。

语音识别(来源:作者)

2.情感分类:情感分类中的对一段文本中表达的观点进行分类。这里的输入是一个单词序列。

情感分类(来源:作者)

3.视频活动识别 : 在视频活动识别中,模型需要识别视频片段中的活动。视频剪辑是视频帧序列,因此在视频活动识别的情况下,输入是数据序列。

视频活动识别(来源:作者)

这些例子表明序列模型有不同的应用。有时输入和输出都是序列,有时输入或输出都是序列。递归神经网络(RNN)是一种流行的序列模型,它对序列数据表现出高效的性能。

递归神经网络

递归神经网络(RNN)是一种深度学习算法,是一种专门用于处理序列数据的人工神经网络架构。rnn 主要用于自然语言处理领域。RNN 维护内存,因此它们对于涉及顺序数据的机器学习问题非常有效。rnn 也用于时间序列预测。

传统的 RNN 建筑(来源:Stanford.edu)

使用 RNNs 而不是标准神经网络的主要优点是标准神经网络中没有共享的特征。在 RNN,权重是跨时间共享的。RNNs 可以记住它以前的输入,但是标准的神经网络不能记住以前的输入。RNN 利用历史信息进行计算。

损失函数

在 RNN,损失函数是根据每个时间步的损失定义的。

重量损失的导数

在 RNN,反向传播在每个时间点进行

RNN 建筑

基于输入和输出的数量,有几种 RNN 架构
1。一对多架构:图像字幕就是这种架构的一个很好的例子。在图像字幕中,它获取一幅图像,然后输出一系列单词。这里只有一个输入,但有许多输出。

2.多对一架构:情感分类是这种架构的一个很好的例子。在情感分类中,给定的句子被分类为肯定或否定。在这种情况下,输入是单词序列,输出是二进制分类。

3.多对多架构:在多对多架构中有两种情况,

  • 第一种是输入长度等于输出长度。命名实体识别是一个很好的例子,其中输入序列中的单词数等于输出序列中的单词数。
  • 多对多架构的第二种是当输入长度不等于输出长度时。机器翻译是这种架构的一个很好的场景。在机器翻译中,RNN 阅读一种语言的句子,然后将其转换成另一种语言。这里输入长度和输出长度是不同的。

RNN 建筑(来源:https://Calvin feng . git book . io)

长短期记忆(LSTM)

传统的 rnn 不擅长捕捉长程相关性。这主要是由于消失梯度问题。当训练非常深的网络时,梯度或导数随着其向下传播而指数下降。这就是所谓的消失梯度问题。这些梯度用于更新神经网络的权重。当梯度消失时,权重将不会更新。有时候会
完全停止神经网络的训练。这种消失梯度问题是非常深的神经网络中的常见问题。

为了克服 RNNs 中的梯度消失问题,Sepp Hochreiter 和 Juergen Schmidhuber 引入了长短期记忆。LSTM 是对 RNN 隐藏层的修改。LSTM 使 RNNs 能够长时间记住它的输入。在 LSTM 中,除了隐藏状态,单元状态被传递到下一个时间步。

基本 RNN 和 LSTM 单位的内部结构(资料来源:stanford.edu)

LSTM 可以捕捉远程依赖。它可以长时间记忆以前的输入。LSTM 的牢房里有三道门。LSTM 的记忆操作是通过这些门完成的。长短期记忆(LSTM)利用门来控制递归网络记忆中的梯度传播。

  • 遗忘门:遗忘门删除单元状态中不再有用的信息
  • 输入门:输入门增加了对单元状态有用的附加信息
  • 输出门:输出门增加了对单元状态有用的附加信息

LSTM 的这种门控机制允许网络学习何时忘记、忽略或保留记忆单元中的信息。

LSTM 是一种非常流行的序列模型深度学习算法。苹果的 Siri 和谷歌的语音搜索是一些使用 LSTM 算法的真实例子,它是这些应用程序成功的背后。最近的研究表明,LSTM 算法可以提高机器学习模型的性能。LSTM 也用于时间序列预测和文本分类任务。

参考文献

https://www . researchgate . net/publication/13853244 _ Long _ Short-Short _ Memory
https://Stanford . edu/~ shervine/teaching/cs-230/cheat sheet-recurrent-neural-networks

序列对序列模型:使用 Tensorflow 2 的注意力网络

原文:https://towardsdatascience.com/sequence-to-sequence-models-attention-network-using-tensorflow-2-d900cc127bbe?source=collection_archive---------46-----------------------

第 2 部分:序列到序列模型:从 RNN 到变压器

在本系列教程的第 1 部分中,我们讨论了带有简单编码器-解码器网络的序列间模型。简单网络更容易理解,但它也有其局限性。

简单编码器-解码器网络的局限性

如果您还记得第 1 部分,解码器仅基于编码器的最后隐藏输出进行解码。 这意味着,为了让普通的编码器-解码器网络正常工作,编码器需要确保在最后的隐藏状态输出中编码所有必要的信息。 这对于短序列很有效,但对于长序列效果不佳。

这就是为什么attention是序列到序列模型中的一个关键概念[1]。

注意力是如何工作的

注意机制的目标是向解码器提供上下文信息,以便解码器能够以更高的准确度解码。注意力网络表示上下文向量和整个输入序列之间的关系,而不是依赖编码器的最后隐藏状态中的单个上下文向量。

图 1:bahda nau 注意的编码器-解码器模型[1]

  • 我们计算一个上下文向量 c 作为输入序列的隐藏状态的总和,用alignment scores加权。
  • alignment scores给位置处的输入 x 和位置处的输出*分配一个 分数***

图 2:注意力等式[4]

  • 不同的注意机制以不同的方式计算这个score
  • 解码器使用这些注意力分数来决定在每个解码时间步长对输入给予多大程度的关注

计算注意力得分主要有四种不同的方法——加法(Bahdanau 的注意力)和乘法(Luong 的注意力)、自我注意力和键值注意力。这里我们将重点关注 Bahdanua 的注意力。

巴丹瑙注意了

Bahdanau 等人[1]提出了原始的注意力机制,该机制使用一个隐藏层前馈网络来计算注意力对准分数[2]

图 3 —注意力得分计算

这里,vW是学习到的——注意网络的参数。 W₁W₂ 是分别学习当前隐藏状态的变换和编码器输出 s 的独立矩阵。**

如果你有点困惑,不要担心。我们会写一个方法让 Bahdanau 注意,让事情变得更清楚。

使用 Tensorflow 2.0 实现 Bahdanau 注意力

BahdanauAttention初始化器中,你会看到我们正在初始化三个Dense层— W1W2V。如图 3 所示,这些Dense层将用于计算正向传播中的分数,也称为call方法中的分数。

我们向W1W2层传递什么?W1W2分别将当前隐藏状态和编码器输出作为输入。在call方法内部——隐藏状态和编码器输出分别由queryvalue表示。一旦我们使用来自Decoder网络的BahdanauAttention,你会对分数计算有更清晰的了解。

接下来,当我们通过 softmax 层传递score时,我们计算attention_weights。由于 softmax 返回多类分类问题中目标类的概率分布[5],因此attention_weights本质上代表了解码器在解码过程中关注了哪个单词。

最后,我们计算context_vector,解码器将使用它来预测最可能的输出。

编码器和解码器:

Encoder等级与第一部分中描述的等级相同。除了添加了如下所示的注意机制之外,Decoder类也非常相似。

你会注意到在line #19我们正在初始化attention层。在call方法的前向传播过程中,我们用当前的隐藏状态和编码器输出实例化了attention层,该输出转化为BahdanauAttention类中的queryvalueattention层输出context_vectorattention_weights(第20行)。context_vector与解码器输入x连接(第#行26)。该连接的结果然后通过gru单元和一个完全连接的层(线# 35)。这里的Decoder类也输出attention_weights,稍后您可以使用它来可视化解码器关注的地方[3]

把所有的放在一起

端到端的工作流程与我们在第一部分中描述的相同——数据清理、定义EncoderDecoder类、训练模型、推理和评估。关于工作代码,请参考 TensorFlow 示例代码这里的

参考:

  1. 联合学习对齐和翻译的神经机器翻译https://arxiv.org/abs/1409.0473
  2. NLP 深度学习最佳实践https://ruder . io/Deep-Learning-NLP-Best-Practices/index . html #注意
  3. 有注意力的神经机器翻译https://www . tensor flow . org/tutorials/text/NMT _ with _ Attention
  4. https://lilian Weng . github . io/lil-log/2018/06/24/attention-attention . html
  5. Softmax 的直观解释https://www . machine curve . com/index . PHP/2020/01/08/how-the-soft max-activation-function-work/

序列到序列模型:使用 Tensorflow 2 的编码器-解码器

原文:https://towardsdatascience.com/sequence-to-sequence-models-from-rnn-to-transformers-e24097069639?source=collection_archive---------17-----------------------

第 1 部分:序列到序列模型:从 RNN 到变压器

来自 Pixabay莫尼卡普的图片

序列到序列模型是对序列数据进行操作的基本深度学习技术。它将一个结构域的序列转换成另一个结构域的序列[1]。这些模型可以是基于 RNN 的简单编码器-解码器网络或高级的基于注意力的编码器-解码器 RNN 或最先进的变压器模型。序列到序列模型有许多应用,例如机器翻译、语音识别、文本摘要、问题回答、需求预测等等。

本文是关于序列到序列模型的三篇文章中的第 1 篇,在这篇文章中,我们将重点构建一个机器翻译系统。在这一部分中,我们将关注基于 RNN 的编码器-解码器网络的内部工作。为了举例说明,我们将构建一个西班牙语到英语的翻译模型。

本文的重点是模型架构、训练和使用 Tensorflow 2.0 的推理过程。因此,我们将省略关于数据准备的讨论。作为参考,数据准备部分可以按照 Tensorflow 教程[2]进行。如果您是 Tensorflow 2.0 的新手,您可能需要特别关注create a tf.data dataset部分[2]

如果你觉得这篇文章很有趣,请随时联系 LinkedIn。

编码器-解码器模型

直观上,编码器对输入进行编码,解码器将其解码到所需的域。在我们的例子中,编码器将对输入的西班牙语句子进行编码,解码器将它们解码成英语。在基于递归神经网络(RNN)的架构中,编码器和解码器都是 RNN 或其变体之一,如 LSTM 或 GRU。在本文中,我们将使用 GRU 单元。

图 1:机器翻译的编码器-解码器模型

编码器

  • 编码器的输入是英语单词。在每个时间步长,一个英语单词作为输入与前一个时间步长(称为隐藏状态)的 RNN 的输出一起传递给 RNN。一开始,这个隐藏状态被初始化为零。
  • 编码器通过这个 RNN 网络对输入数据进行编码

解码器

  • 在训练阶段,解码器的输入是移动一步的西班牙语单词。也就是说,给解码器一个它should have预测的输入字,而不管它实际预测的是什么。
  • 对于第一个时间步长,解码器被赋予start-of-sequence (SOS)。解码器应该以一个end-of-sequence (EOS)标记结束句子。

推理过程:

序列对序列模型中的一个关键概念是理解训练和推理模型的不同之处。它是关于解码器的。我们在推断时间和训练时间如何将输入提供给解码器是不同的。你大概可以直观的理解,在推理时间里,我们不知道目标翻译的单词。因此解码器将被馈送前一时间步的输出。当然,对于第一个时间步长,解码器被赋予start-of-sequence (SOS)

让我们深入研究一下实现。

编码器型号

我们将使用 Tensorflow 2 构建一个Encoder类。首先,确保您导入了必要的库

import tensorflow as tf

EncoderDecoder类都将继承自tf.keras.Model。至少,这些类将有两个方法——一个初始化器__init__方法和一个call方法。call方法在网络的正向传递过程中执行。如果您熟悉 Pytorch,那么您很可能熟悉这种定义模型的风格。

Encoder类中,我们还将定义一个初始化隐藏状态的方法。

__init__方法中,我们需要定义层——例如Embedding层、GRU层或完全连接的Dense层。我们还需要初始化定义这些层所需的变量。具体来说,我们需要定义

  • vocab_size:训练数据中的唯一单词数
  • embedding_dim:您希望嵌入的尺寸。一般来说,越高越好,但这也带来了计算和内存成本。
  • enc_units:GRU 单位的数量。例如,在figure-1中,我们有n个编码器单元
  • batch_size:你希望你的模型在每个时期训练的数据量。

call方法中,你想做你认为你的模型在网络的前向传播中应该做的操作。在编码器的情况下,我们需要得到嵌入的输入字,并通过 GRU 层传递它。

解码器模型

Decoder类与Encoder类非常相似。除此之外,您需要通过完全连接的Dense层传递 GRU 单元的输出,以便从网络中获得预测。

训练编码器-解码器网络

首先,我们将定义网络的优化器和损失函数。我们将使用 Adam 优化器。既然是分类问题,我们就用CrossEntropy损失作为损失函数。

在训练过程中—

  • 我们通过返回encoder outputencoder hidden state的编码器输入。
  • 然后将encoder outputencoder hidden statedecoder input传递给解码器。decoder input<SOS>(句首)标记开始。
  • 解码器输出predictiondecoder hidden state
  • prediction用于计算损失
  • 我们根据当前时间步的输入为下一个时间步创建decoder input。这个迫使解码器学习目标输出的过程称为teacher forcing
  • 当前时间步的decoder hidden state被送至下一个时间步。
  • 接下来,我们将计算梯度。随着 Tensorflow 进入急切执行模式[6],我们将使用tf.GradientTape来跟踪计算梯度的操作。梯度计算相对于模型的可训练参数发生。因此,在下面的行19中,你会发现我们正在总结编码器和解码器的可训练变量。
  • 当在tf.GradientTape的上下文中执行操作时,它们被记录。默认情况下会记录可训练参数[7]。如果你想记录张量,你必须通过在tf.GradientTape的上下文中调用watch方法来手动完成。
  • 最后,我们将对优化器应用梯度,优化器将更新模型参数——aka。反向传播。

推理

您可能已经注意到,在培训时,我们保存了模型检查点。保存检查点是保存模型的一种方式。或者,如果您有一个keras.Model对象,那么您可以使用saved_model.save来保存模型[8]。要运行推理,您需要重新加载检查点[9]。

如前所述,推理过程与训练过程非常相似,只是我们如何馈送给解码器。这里,解码器的输入是解码器在前一时间步的输出——无论它预测了什么,而不是目标。如果你理解训练过程,代码是简单的。

如果你已经理解到这一点,可以写一个基于 RNN 的编码器-解码器,可以做训练和编码推理方法-祝贺你!

即将推出!第 2 部分—关注基于 RNN 的编码器-解码器网络

参考:

  1. 十分钟序列对序列学习介绍https://blog . keras . io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras . html
  2. 关于数据处理/清理的一切https://www . tensor flow . org/tutorials/text/NMT _ with _ attention
  3. 原序对序纸https://arxiv.org/pdf/1409.3215.pdf
  4. https://machine learning mastery . com/define-encoder-decoder-sequence-sequence-model-neural-machine-translation-keras/
  5. 理查德·索契的机器翻译讲座
  6. 张量流急切执行https://www.tensorflow.org/guide/eager
  7. 张量流梯度带https://www.tensorflow.org/api_docs/python/tf/GradientTape
  8. https://www.tensorflow.org/guide/saved_model
  9. 张量流检查点https://www.tensorflow.org/guide/checkpoint

Python 中的序列解包

原文:https://towardsdatascience.com/sequence-unpacking-in-python-14d995f9a619?source=collection_archive---------33-----------------------

了解 Python 序列解包

来源

python 中的序列解包允许您获取集合中的对象,并将它们存储在变量中以备后用。这在函数或方法返回一系列对象时特别有用。在这篇文章中,我们将讨论 python 中的序列解包。

我们开始吧!

python 的一个关键特性是任何序列都可以通过赋值被解包到变量中。考虑与 Nike run 应用程序上特定跑步的属性相对应的值列表。该列表将包含跑步的日期、配速(分钟)、时间(分钟)、距离(英里)和海拔(英尺):

new_run = ['09/01/2020', '10:00', 60, 6, 100]

我们可以通过赋值用适当命名的变量解开这个列表:

date, pace, time, distance, elevation = new_run

然后,我们可以打印这些变量的值,以验证赋值是否正确:

print("Date: ", date)
print("Pace: ", pace, 'min')
print("Time: ", time, 'min')
print("Distance: ", distance, 'miles')
print("Elevation: ", elevation, 'feet')

我们正在解包的序列中的元素也可以是序列。例如,除了整体跑步的平均配速,我们还可以有一组英里分割:

new_run_with_splits = ['09/01/2020', '10:00', 60, 6, 100, ('12:00', '12:00', '10:00', '11;00', '8:00', '7:00')]

现在让我们打开新序列的包装:

date, pace, time, distance, elevation, splits = new_run_with_splits

我们可以打印英里分割:

print("Mile splits: ", splits)

我们甚至可以进一步解开前面代码中的拆分列表。让我们用表示英里数的变量来解开分割列表:

date, pace, time, distance, elevation, (mile_2, mile_2, mile3_, mile_4, mile_5, mile_6) = new_run_with_splits

让我们打印英里变量:

print("Mile Two: ", mile_2)
print("Mile Three: ", mile_3)
print("Mile Four: ", mile_4)
print("Mile Five: ", mile_5)
print("Mile Six: ", mile_6)

我们还可以使用' _ '字符来删除不需要的值。例如,如果我们想省略日期和高度,我们会这样做:

_, pace, time, distance, _, (mile_2, mile_2, mile_3, mile_4, mile_5, mile_6) = new_run_with_splits

我们还可以使用 python 的“星形表达式”(*)来解包任意数量的元素。例如,如果我们想存储第一个和最后一个变量,并将中间值存储在一个列表中,我们可以执行以下操作:

date, pace, time, distance, elevation, (first, *middle, last) = new_run_with_splits

让我们打印第一个、中间和最后一个变量:

print("First: ", first)
print("Middlle: ", middle)
print("Last: ", last

我想强调的是,我们序列中的对象可以是任何类型。例如,对于英里分割,我们可以使用字典而不是元组:

new_run_with_splits_dict = ['09/01/2020', '10:00', 60, 6, 100, {'mile_1': '12:00', 'mile_2':'12:00', 'mile3':'10:00', 'mile_4':'11;00', 'mile_5':'8:00', 'mile_6':'7:00'}]

让我们打开新清单:

date, pace, time, distance, elevation, splits_dict = new_run_with_splits_dict

现在,我们可以通过键访问英里分割值:

print("Mile One: ", splits_dict['mile_1'])
print("Mile Two: ", splits_dict['mile_2'])
print("Mile Three: ", splits_dict['mile_3'])

我就讲到这里,但是我鼓励你自己去研究代码。

结论

在这篇文章中,我们讨论了如何在 python 中解包序列。首先,我们展示了如何解包与发布到 Nike Run 应用程序的跑步相关的值列表。我们还展示了序列中的值也可以是序列,其中序列或其元素可以存储在单独的变量中供以后使用。然后,我们展示了如何使用下划线字符删除值。接下来,我们讨论了如何使用 python“星形表达式”解包任意数量的对象。最后,我们演示了如何从对象列表中解包一个字典对象,并通过键访问字典值。我希望你觉得这篇文章有趣/有用。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!

建议中的顺序决策

原文:https://towardsdatascience.com/sequential-decision-making-in-recommendations-6ebddb8f46dd?source=collection_archive---------59-----------------------

活动讲座

Jaya Kawale | TMLS2019

在多伦多机器学习峰会上的演讲

关于演讲者

Jaya Kawale 是网飞大学的高级研究科学家,致力于解决与网飞主页上的建议相关的问题。在加入网飞之前,她曾在 Adobe 研究实验室和雅虎工作。研究。她在明尼苏达大学获得了博士学位,她的论文赢得了在超级计算 11 上颁发的“通过计算探索科学”奖。她在包括 NeurIPS、KDD、CIKM、SDM 和 IJCAI 在内的顶级会议上发表了多篇论文。

建议中的顺序决策

使用 GANs 的顺序图像生成

原文:https://towardsdatascience.com/sequential-image-generation-with-gans-acee31a6ca55?source=collection_archive---------36-----------------------

生成敌对网络(GANs)在生成非常清晰和真实的图像方面非常成功。这篇文章简要地解释了我们的基于 GANs 的图像生成框架,它顺序地组成一个图像场景,将潜在的问题分解成更小的问题。有关深入的描述,请参见我们的出版物:用 GANs 进行场景生成的基于层的顺序框架。

图 1:建议的图像生成过程。给定一个语义布局图,我们的模型一步一步地组成场景。第一行显示了输入语义图和由最新基线生成的图像。

什么是生成性对抗网络?

图 2:氮化镓框架。

生成对抗网络(GAN) [1]是一类机器学习框架。两个神经网络:(I)生成器,和(ii)鉴别器在一个博弈论场景中相互竞争。生成器将随机噪声作为输入,并生成假样本。鉴别器试图区分从训练数据集中提取的样本(真实样本,例如手写数字图像)和由生成模型产生的样本(假样本)。这个游戏驱动鉴别器学习正确地将样本分类为真或假。同时,生成器试图欺骗分类器,让它相信它的样本是真实的。在收敛时,生成器样本与训练数据无法区分。更多详情请看原文本帖。GANs 可用于图像生成;他们能够学习生成清晰逼真的图像数据。

单镜头图像生成限制了用户对所生成元素的控制

图 3:前景对象的不同缩放。

在 GAN 文献[2,3,4]中已经广泛研究了自动图像生成问题。它主要被认为是学习从单源,例如噪声或语义图,到目标,例如斑马的图像的映射。这个公式对单独控制场景元素的能力设置了主要的限制。因此,举例来说,很难改变一个斑马的外观或形状,同时保持图像场景的其余部分不变。让我们看看图 3。如果我们改变对象大小,即使每行的输入噪声相同,背景也会改变。

我们的方法:基于层的顺序图像生成

我们的主要想法类似于风景画家如何首先勾画出整体结构,然后用其他元素逐渐修饰场景,以填充场景。例如,绘画可以从山脉或河流作为背景开始,而树木和动物作为前景实例依次添加。

主要目标被分解成两个更简单的子任务。首先,我们用背景生成器 Gbg 根据噪声生成背景画布 x0 。其次,我们用前景生成器 Gfg 依次添加前景对象,以达到最终的图像 xT ,其中包含画布上预期的 T 个前景对象(T 不固定)。我们的模型允许用户控制要生成的对象,以及它们的类别、位置、形状和外观。

图 4:提议的框架概述。Gbg、Gfg 分别是背景和前景生成器。

表现如何?

我们用 MS-COCO 数据集的子集运行了几个实验。图 5 比较了数据集中六个对象类的场景生成任务的不同基线的视觉结果。标准的 CNN 产生模糊的结果,尽管 L1 损失,以补救这一特殊问题。Pix2Pix [2]生成更清晰的图像。然而,标准的 CNN 和 Pix2Pix 都试图复制地面真相,这表明它只记住了数据集。它们在生成过程中缺乏随机性,这抑制了生成图像的多样性。应该避免这种行为,因为目标是生成逼真的场景,而不是模仿数据集中的场景。当添加最新的 GANs 训练技术时,多样性和图像质量得到改善,如 Pix2Pix++和我们提出的模型所示。然而,当存在多个对象(第 1、2、4 和 5 行)时,Pix2Pix++似乎很难处理。它不能产生一个可信的场景。我们的模型明确地将前景和背景生成过程分开,克服了这些问题。

图 5:使用来自训练集的对象遮罩与现有技术模型的比较。从上到下:羊、牛、熊、大象、长颈鹿和斑马。地面真实对应于原始图像。

前景对象遮罩变换

在这个实验中,将几个仿射变换应用于输入对象遮罩。图 6 示出了当平移、旋转和缩放操作变换前景对象时,Pix2pix++和所提出的顺序模型如何保存场景。考虑 Pix2Pix++模型(图 6 的左栏)。应用平移时,前景和背景都会改变。旋转对象时,前景对象开始与背景融合。Pix2Pix++似乎学习了地面和斑马腿之间的颜色相关性,这使得无法绘制旋转较大的对象。当对象放大时,前景对象的颜色开始在背景中渗色。相比之下,我们提出的顺序模型(图 6 的右栏)保留背景直到仿射变换,并且不会遭受对象混合或渗色。然而,它确实稍微改变了前景物体的外观。

图 6:物体遮罩仿射变换。Pix2Pix++无法保留场景。它要么改变背景,混合前景和背景,要么遭受颜色混合。我们的模型不会受到这些伪像的影响。

前景物体遮挡

在这个实验中,两个前景对象在水平轴上平移,直到它们彼此遮挡。图 7 比较了 Pix2Pix++和所提出的顺序模型在它们各自的对象遮罩变得更接近时如何生成前景对象。首先,Pix2Pix++不能正确地描绘这两个对象。考虑 zebra 示例和 Pix2pix++模型。当蒙版彼此轻微接触时(第 2 行),它会在错误的位置分割斑马。当它们被完全遮挡时(第 4 行),它只绘制一条斑马。第二,Pix2Pix++倾向于为两个对象产生相似的模式。现在考虑长颈鹿的例子和 Pix2pix++模型。当遮罩变得更近时(第 2 行),它会为长颈鹿输出相似的颜色。当它们彼此轻微接触时(第 3 行),它会合并长颈鹿,并绘制一个连续的图案。当它们被完全遮挡时(第 4 行),它会画一个有两个头的长颈鹿。这两种类型的伪影不会出现在我们提出的顺序模型中。

图 7:水平平移两个物体,直到它们相互遮挡。Pix2pix++描绘了前景对象上的伪像,这在我们提出的模型中是不存在的。

前景对象控件

在这个实验中,我们展示了物体的外观可以通过改变相关的噪声来改变。在图 8 中,我们添加了来自不同噪声矢量但在相同背景上具有相同遮罩的前景对象。

图 8:通过改变相关的输入噪声 z1 来控制前景物体的外观。

超出生成的背景

我们的前景模型也可以用于图像编辑的目的,通过添加一个对象到现有的图像。在图 9 中,我们将对象添加到相同的场景,但是具有不同的照明或季节条件。前景模型知道背景场景的内容及其环境条件,例如全局照明。

图 9:向现有图像添加新对象。全局照明影响对象外观。

超越对象遮罩

在当前的问题公式中,前景生成器以对象遮罩为条件。这限制了用户对所提出的顺序模型的控制,因为用户将不得不画出物体的形状来获得场景。在这个实验中,我们展示了如何通过引入一个单独的掩码生成器模型来轻松扩展当前的框架。这个想法是基于边界框生成物体形状。它们可以进一步用作当前框架的输入。遮罩生成器是一个条件 GANs 模型,它将边界框和对象类作为输入,并在感兴趣的区域中输出对象遮罩。图 10 呈现了从边界框生成的掩模样本及其最终生成的图像。

图 10:从边界框而不是对象遮罩开始生成图像。请注意,掩码是在本实验中生成的。盒子的位置控制水平线,而形状控制视点。

要了解更多关于我们方法的细节或看到更多结果包括定量结果,您可以看看我们的出版物:

用 GANs 生成场景的基于层的顺序框架。在 AAAI。2019.

如果您想在您的项目中使用我们的方法,可以在这里获得代码

参考

[1] I. Goodfellow、J. Pouget-Abadie、M. Mirza、B. Xu、D. Warde-Farley、S. Ozair、a .库维尔和 Y. Bengio,“生成性对抗网络”,载于《神经信息处理系统进展》,第 2672-2680 页,2014 年。

[2] P. Isola,J.-Y. Zhu,T. Zhou,A. A. Efros,“有条件对抗网络的图像到图像翻译”,2017 年 IEEE 计算机视觉与模式识别大会(CVPR),第 5967–5976 页,2017。

[3]宫户,t;t .片冈;Koyama,m;还有吉田,Y. 2018。生成对抗网络的谱归一化。在 ICLR。

[4]王;刘,男,女;朱;陶;考茨,j;和卡坦扎罗,B. 2018。用条件 gans 进行高分辨率图像合成和语义处理。在 CVPR。

二元序列中的序列相关性

原文:https://towardsdatascience.com/serial-dependence-in-binary-sequences-409c5e8f54d0?source=collection_archive---------50-----------------------

用 Meixner 正交多项式检验序列相关性

2018 Julian Wergieluk

在这篇博文中,我将研究随机二进制序列中的序列(即时间)依赖现象。

随机二进制序列是由随机过程产生的 0 和 1 的序列。大多数随机数生成器生成的主要输出是二进制的。二进制序列通常对随机事件的发生进行编码:

  • 金融市场的极端回报。
  • 机器、服务器等的故障
  • 金融市场风险模型中的风险价值超额指标。

在许多这样的情况下,有必要确保被跟踪的事件彼此独立地发生。例如,生产系统中事件的发生不应该使系统更容易发生事件。为此,我们需要仔细研究一下所考虑的二进制序列的依赖结构。

概述

在这篇博文中,我将开发并测试一种评分方法,用于量化随机二进制序列中的依赖强度。Meixner 依赖分数易于实现,并且基于与几何分布相关联的正交多项式。

读完这篇博文,你会知道:

  1. 如何用统计术语来表述序列相关性度量的问题。
  2. 如何从几何分布中导出迈克尔逊多项式?
  3. 如何计算等待时间序列的 Meixner 依赖分数,以量化依赖强度。
  4. 如何使用简单的 Monte-Carlo 实验测试依赖性评分方法,该实验涉及具有已知依赖性结构的马尔可夫链。

问题的统计公式

给定一个随机变量序列 X = (X[0],X[1],…,X[n]) 取集合 {0,1} 中的值和一个概率 p∈(0,1) ,我想考察 X 的元素之间的序列依赖关系。这个调查应该基于从 X 中抽取的一个样本 x ,即一个有限的 0 和 1 序列 (x[0],x[1),...,x[n]) 。这是一个非常困难和深刻的问题,在这篇博文中,我将重点收集证据来支持或拒绝以下两个基本假设:

  1. 随机变量X【I】具有分布 Ber( p )(成功概率为 p 的伯努利分布)。
  2. 随机变量X【I】是独立的。

如果我们假设 x 的元素是来自一个固定伯努利随机变量 X[0] 的独立样本,那么我们可以通过计算 x[0],x[1],…,x[n] 的平均值来估计概率 p 。这是因为 X[0] 的期望是 𝔼 X[0] = p

为了给串行相关性检测问题设置一个合适的上下文,让我注意到随机二进制序列 x 通常与具有两个状态的系统的谨慎观察相关联。如果 x[0] = 1 ,我们说“一个事件”发生在时间 i

我们如何检查我们的事件是否彼此独立地发生,并收集事件时间之间没有序列相关性的证据?

我们经常倾向于在不存在序列相关性的情况下看到序列相关性。典型的例子是赌场里的赌徒所经历的“好运连连”。

为了根据观察结果 x 严格研究序列 X 中的序列相关性问题,我们可以看看事件之间等待时间的分布。例如序列

[0, 1, 1, 0, 0, 1, 0, 0]

产生以下等待时间序列

[1, 3].

请注意,等待时间计算会丢弃事件序列 x 中的初始零和尾随零。

为了基于 x 正式定义等待时间序列y =(y【1】,…,y【m】),考虑索引I =(I【1】,I【2】,…) 的序列,使得对于每个 i∈ I 我们有 x 我们出发了

对于同分布的伯努利随机变量序列,等待时间序列由几何分布的同分布随机变量组成。让我们仔细看看它的属性。

几何分布

参数为 p 的几何分布的概率质量函数(PMF)由下式给出

参数为 p=0.1 的几何分布的 PMF 如下。

参数为 p=0.1 的几何分布的概率质量函数

测试等待时间序列是否遵循几何分布的一种方法是查看由该分布生成的正交多项式

一族正交多项式与 上的每个概率分布 μ 密切相关。对于任何这样的分布,我们可以将(平方可积)实值函数 fg 之间的标量积定义为

其中 Y 是分布为 μ 的随机变量。对于几何分布,上述标量积采用以下形式

我们说函数 fg 正交(相对于 μ )当且仅当 ⟨f,g⟩ = 0。

最后,一个多项式序列 (q[i])i≥ 0 称为正交,当且仅当,对于所有的 k ≠ i ,q[i]⟩ = 0 ,每个q[I】都有度 i 。因此,对于 i > 0 ,我们得到 𝔼 qi = 0 。这是我将要用来检查给定的 Y 是否遵循几何分布的工具。

对应于几何分布的正交多项式族 M = (Mi) 是由负二项分布(几何分布的推广)导出的 Meixner 族的特例。Meixner 家族的成员满足以下方便的递归关系:

M1 = 1M-1 = 0 。该关系用于计算序列 M 。另外,请注意 M[k] 取决于参数 p 的值。

在配套的 python 源代码中,函数meixner_poly_eval用于在给定的点集上计算 Meixner 多项式到给定的次数。我用这个函数画出了这些多项式的 55 次曲线。

p=0.1 到 55 度的 Meixner 正交多项式的图

如上所述,对于每个多项式M【k】(y)M 中的等式

当且仅当 Y∈ Geom( p )和 k > 0 成立。

这个关系可以用来检验给定的等待时间样本是否属于参数为 p 的几何分布。我们将估计期望值 𝔼 Mk 并将估计值用作分数:接近零的值可以解释为参数为 p 的几何分布的证据。如果值远离零,这是一个信号,表明我们需要重新考虑我们的假设,并可能放弃关于原始事件序列的 i.i.d .假设。注意,如果事件是独立的,也可能出现与零的显著偏差,但是真实概率p’与假定的 p 显著不同。如前所述,这很容易测试。

Meixner 依赖分数

为了获得在上述意义上量化串行相关性程度的单个数字(分数),我们将定义 Meixner 相关性分数(MDS) 作为在等待时间 y=(y[1】的样本上评估的第一个 k Meixner 多项式的期望估计的平均值,..,y[m]) :

使用正交多项式来测试二进制序列中依赖结构假设的思想源于矩推断方法,并在金融文献中被发展用于回溯测试风险值模型。在这篇博客文章中,我采用了 Candelon 等人提出的方法,请参见下面的参考资料部分。

蒙特卡罗研究

为了找出上面设计的过程是否有机会在实践中起作用,我将使用综合生成的数据来测试它。这种类型的测试程序通常称为蒙特卡罗(MC)研究。它不会用真实世界的数据替换测试,但可以帮助在受控环境中评估统计方法。

我们要执行的实验包括以下步骤:

  1. 使用具有已知序列相关性结构的模型生成二进制序列。
  2. 估计对 k=1,…,10 的期望 𝔼 Mk
  3. 在大量独立试验中重复第 1 步和第 2 步,并将汇总结果可视化。

让我们从一个简单的例子开始,用成功概率 p[0] 来模拟伯努利随机变量的 i.i.d 序列。这可以用作健全性检查,并测试我们的过程实现是否正确。

对于下面的实验,我们设置 p[0] = 0.05 并模拟来自 X = (X[1])的 5000 个样本,..,X[1000])

对于一个具有简单形式的序列相关性的模型,我们选择概率0<p[1]<p[0]<p[2]<1,并设置序列中随机变量的分布 X = (X[0],X[1],X[2],…) 如下。让 X[0] 为伯努利,成功概率 p[0]X[i] 对于 i > 0 的分布以 X[i-1] 为条件:

为了将该模型与具有成功概率
的 I . I . Bernoulli 模型 p[0] 进行比较,我们需要设置 p[1]p[2] ,使得 X[i] 的无条件
分布为 Ber (p[0])

换句话说,对于给定的0<P[1]<P[0]<1,我们寻找的是P[2]∑(0,1) ,使得上述定义的随机二进制序列满足 P(X[i] = 1) = p[0]
这个二元序列可以用状态空间{0,1}表示为简单的马尔可夫链,转移概率矩阵 P 由下式给出

而初始分布 λ = (1-p[0],p[0])X[i] 的边际分布由下式给出

这个基本结果可以在任何一本关于马氏链的书中找到(参见下面的参考资料部分)。找到一个 p[2] 使得 P(X[i] = 1) 尽可能接近 p[0] 的任务,可以用现成的优化算法,例如 BFGS 很容易地解决。

例如,对于 p[1] = 0.02p[0] = 0.05 ,上述过程很快得出 p[2] = 0.62

蒙特卡罗研究结果

让我们测试下面的值 p[1]p[2] 的依赖评分算法。Meixner 多项式的 MC 评估产生以下 Meixner 相关性分数:

+------+------+-------+
|  p1  |  p2  |  MDS  |
+------+------+-------+
| 0.5, |  0.5 | 0.083 |
|  0.4 | 0.24 | 0.194 |
|  0.3 | 0.43 | 0.382 |
|  0.2 | 0.62 | 0.583 |
+------+------+-------+

同样,对长度为 1000 的样本的 5000 次模拟产生了下面的期望估计直方图。

正如我们所见,直方图略微向左偏移。

这篇博文中展示的所有结果和图表都是使用以下 Python 脚本生成的: meixner.py

结束语

在这篇博文中,我们了解了二进制序列中的序列相关性的概念。我们基于 Meixner 正交多项式实现了一种串行依赖性检测方法,Meixner 依赖性得分,并使用简单的马尔可夫链模型测试了它的性能。

依赖性测试的一个重要财务用例是分析由市场风险模型生成的风险价值超出事件序列。市场风险模型广泛用于银行业的监管资本要求计算,以及资产管理行业的投资组合构建和风险管理。

风险价值 (Var)是固定时间范围内金融资产价格损失分布的分位数。例如,持有黄金多头头寸的投资者可能对美元黄金价格在一天时间范围内的 95% VaR 感兴趣。对于校准良好的风险值模型,在一个投资期内观察到的 5%营业日的极端损失将超过 95%的风险值分数。VaR 超过事件不仅必须以预期的频率发生,还必须相互独立。对市场风险模型进行适当校准,将超出事件的相关性降低到较低水平,通常比超出频率的简单校准要困难得多。但这在金融危机时期尤为重要,因为低估风险不可避免地会导致投机倒把,甚至可能导致更严重的损失。

非常感谢 Sarah Khatry 阅读了这篇博文的草稿,并提供了无数的改进意见和更正。

参考

成为数据科学家的一系列免费课程

原文:https://towardsdatascience.com/series-of-free-courses-to-become-a-data-scientist-3cb9fd591739?source=collection_archive---------4-----------------------

链接到知名大学的高质量课程,可以免费学习。循序渐进地学习这些课程,成为一名数据科学家。

来源:蒂姆·莫斯霍尔德

现在有很多资源声称它们会让你成为一名数据科学家。刚开始在网上上课的时候,我花了一段时间才明白哪些课程好。我开始了一门课程,几天或几周后,我意识到它没有帮助。再次转移到别的东西上。我希望我能找到一个可靠的向导,告诉我到底该学什么,从哪里开始,以及如何进行学习之旅。虽然我找到了一些材料,但我仍然不得不挣扎了很多。这就是为什么我决定分享一个完整的学习和课程计划,最终给你足够的知识来找到一份数据科学家的工作。最棒的是,它是免费的!

我将展示一条成为 Python 数据科学家的途径。因为我是 python 用户,我喜欢。还有,我相信如果你是初学者,学好一门语言是很好的。然后继续学习更多。以下是循序渐进的免费学习计划:

1.学习 Python

如果你不知道 Python,这个免费课程是一个好的开始。Udacity 有一门免费的课程“计算机科学入门”,教授 python 编程语言,有很多例子和练习题,对初学者来说非常好。不幸的是,如果你去 Udacity 的主页搜索它,它现在会把你重定向到另一个课程。但是幸运的是,在下面的链接中,你仍然可以找到所有的资料。

[## Udacity CS101 资源

这个页面为我的 Udacity cs101:计算机科学入门(构建搜索引擎)收集了一些资源…

www.cs.virginia.edu](http://www.cs.virginia.edu/~evans/cs101/)

这门 Python 课程应该给你足够的知识,让你开始学习数据科学工具。

2.了解 Python 的数据科学库

Coursera 有很多课程,你可以免费学习。是学习者的福气。他们有密歇根大学的专业“应用数据科学与 Python ”。它包含以下五门课程:

a.Python 中的数据科学简介

b.应用 Python 进行绘图、制图&数据展示

c.在 Python 中应用机器学习

d.在 Python 中应用文本挖掘

e.应用 Python 进行社会网络分析

我只想警告你一件事。如果你选择学习这些课程,你必须保持耐心。因为作业很难,尤其是如果你是初学者。你只需要不断努力,做到最好。但是因为作业很难,如果你能完成作业,你真的会学得很好。你只需要花足够的时间在上面。如果你不想要证书,只想学习,你不需要支付任何费用。你可以免费旁听所有课程。

下面是查找审计选项的说明。不要在专业化页面注册。只免费 7 天。转到个别课程的页面。然后,您会在页面顶部看到一个注册选项。甚至不要从那里注册。继续向下滚动单个课程的页面。在每周的课程讨论和教员信息之后,你会发现另一个注册选项。单击注册选项。一个窗口将会打开,在它的底部,你会看到一个非常小的“审计”选项。单击审核选项并从那里注册。即使你不能按时完成,你也可以再次审计。您可以根据需要多次审核课程。如果你不能遵循上面的指示,我有一个视频可以带你完成这个过程:

3.学习 SQL

SQL 是数据分析师或数据科学家的必备之一。如果你已经完成了上述专业之一的课程,学习 SQL 应该很容易。有一些共同的想法。这里有一个专业,可以教你足够多的 SQL,让你开始成为一名数据科学家:

[## 了解数据科学的 SQL 基础知识

由加州大学戴维斯分校提供。这个专业是为以前没有编码的学习者设计的…

www.coursera.org](https://www.coursera.org/specializations/learn-sql-basics-data-science)

该专业有四门课程:

a.用于数据科学的 SQL

b.使用 SQL 进行数据争论、分析和 AB 测试

c.使用 Spark SQL 的分布式计算

d.SQL for Data Science 顶点项目

我之前已经解释过如何审核这些课程。

4.了解更多信息

学完以上课程后,你就可以申请工作了。你会发现很多适合你的机会。但是,如果你想在数据科学方面取得进步,还有很多东西要学。例如,在处理数据时,了解一些统计学概念是很好的。上面步骤 2 中的应用机器学习课程教你,如何使用一个非常好的机器学习库 scikit-lean。它给出了许多机器学习算法的基本概念,你可以通过从 scikit-learn 库中调用它们来使用它们。它适用于很多问题。但是从头开始学习编写算法会给你更多的能力。以下是一个统计专业化课程和一个机器学习课程的链接:

用 Python 统计

机器学习

对于初学者来说,这可能看起来太多了。但是请记住,你不必在一天之内学会所有的东西。无论何时你要改变职业或者开始新的事情,都需要时间。如果你能做到步骤 2 中提到的数据科学专业化,那么学习 SQL 将会非常容易和快速。所以,这并不像看起来那么难。再给你一个提示。当你有一个好的学习伙伴时,保持动力和耐心会容易得多。大概你已经知道了,只是提醒一下。

推荐阅读:

[## 12 周能成为数据科学家吗?

12 周的合理学习目标是什么

towardsdatascience.com](/can-you-become-a-data-scientist-in-12-weeks-58ed9e3064a6) [## 学习编程、软件工程、机器学习等的最佳免费资源

找到所有高质量的计算机科学课程,从麻省理工学院,哈佛大学,和其他大的大学成为专家…

towardsdatascience.com](/best-free-resources-to-learn-programming-software-engineering-machine-learning-and-more-89ee724b90c3) [## 使用 Pandas Cut 或 Qcut 方法对数据进行分类和分段

当你在寻找一个范围而不是一个确切的数值,一个等级而不是一个分数

towardsdatascience.com](/sort-and-segment-your-data-into-bins-to-get-sorted-ranges-pandas-cut-and-qcut-7785931bbfde) [## 如何在 Python 中呈现多个变量之间的关系

了解如何使用 Python 中的多元图表和绘图来呈现要素之间的关系

towardsdatascience.com](/how-to-present-the-relationships-amongst-multiple-variables-in-python-fa1bdd4f368c) [## Pandas 的 Groupby 功能详细,可进行高效的数据汇总和分析

学习对数据进行分组和汇总,以使用聚合函数、数据转换、过滤、映射、应用函数…

towardsdatascience.com](/master-pandas-groupby-for-efficient-data-summarizing-and-analysis-c6808e37c1cb) [## Python 中从头开始的多项式回归

学习用一些简单的 python 代码从头开始实现多项式回归

towardsdatascience.com](/polynomial-regression-from-scratch-in-python-a8d64845495f) [## 置信区间、计算和特征

什么是置信区间,如何计算它及其重要特征

towardsdatascience.com](/confidence-interval-calculation-and-characteristics-1a60fd724e1d)

从 API 提供预测

原文:https://towardsdatascience.com/serve-predictions-from-an-api-1d84b4ac9a7c?source=collection_archive---------53-----------------------

使用 Python 和 Flask 建立与 ML 模型交互的 API

弗洛里安·克拉姆在 Unsplash 上拍摄的照片

关于

在本文中,我将尝试演示如何建立一个快速的 Flask API 来为 ML 模型预测服务。

一旦你创建并训练了你的模型,你就会想要与它互动。虽然可以在 jupyter 笔记本中手动完成这项工作,但您很可能希望自动完成预测。

我已经使用 React.js 创建了一个仪表板,它使用户能够配置游戏的功能,然后我们可以将其发送到 API 以接收预测。

安装

继续启动你选择的编辑器。我用的是 VS 代码,是免费的,可以在这里下载。它非常直观,当您第一次启动它并开始处理 python 文件时,它会提示您安装一些模块,帮助您轻松创建 python 文件。

这里有一篇关于为 python 开发设置 VS 代码的很棒的文章:

[## Visual Studio 代码中的 Python

使用 Microsoft Python 扩展,在 Visual Studio 代码中使用 Python 是简单、有趣且高效的。的…

code.visualstudio.com](https://code.visualstudio.com/docs/languages/python)

创建 Flask 服务器

现在我们准备写一些代码。

继续创建一个新文件夹,为 Flask 服务器创建一个新文件,为“PredictGame”路径创建一个新文件:

让我们继续为我们的 Flask 服务器添加基本功能。

首先,我们加载设置 REST 服务器所需的 flask API。

然后导入将要实现的 provider 类,它将负责处理预测请求。

最后,我们告诉编译器启动服务器。

路由处理器

现在,我们有了一种与将要接收的请求进行交互的方法,以及一种发送回正确信息的方法。

让我们继续创建一个路由处理器,它将包含我们接收游戏信息的所有逻辑,并发送回正确的预测。

首先,我们导入所需的库。我们从 Flask 导入“reqparse”和资源。

我们将使用' reqparse '使处理请求参数像使用字典一样简单。

“Resource”将允许我们继承一个超类,该超类将允许我们实现不同的 HTTP 方法,如“get”、“delete”、“put”、“post”。

这对我们来说很容易,因为我们需要做的就是在“get”方法中实现功能。

接下来,我们导入“xgboost ”,因为我们必须创建一个新的模型,将预训练的权重加载到该模型中。

我们导入 numpy,因为模型期望数据是某种形状,并且是 numpy 数组类型。

最后,我们导入 json,这样我们可以将游戏参数从 json 对象转换成 python 列表。

在我们的构造函数中,我们设置了参数解析器,并用保存的权重初始化模型。

然后,我们创建我们的“get”方法,该方法只是从请求中解析游戏对象,然后我们将游戏对象格式化为模型期望的格式,最后,我们进行预测并在字典中返回它们。

这是一个超级基本的实现,没有任何错误处理或类型检查。

最后,在底部我们有一个私有的 helper 方法,用于将数据转换成正确的格式。

启动服务器

首先,在 server.py 文件所在的目录中打开一个终端,并使用以下命令运行该文件:

$ python server.py

这将启动 Flask 服务器,您应该会看到一些文本,宣布服务器正在运行,并且您可以在以下地址找到它:

现在我们的服务器正在运行,我们可以与 API 进行交互。

使用 API

现在我们已经有了一个运行的服务器,我们需要测试我们的工作。

虽然测试 API 端点最流行的工具肯定是 Postman,但是有几种方法可以发出 HTTP 请求。

Postman 是一个免费的应用程序,用于使用 HTTP 创建和运行测试,当您发出请求时,它可以让您准确地看到正在发送的内容和正在接收的内容。

继续并下载 Postman ,我们可以用它来发出 http 请求并查看原始响应。

[## 下载邮差 App

下载邮差!加入依赖 Postman 作为唯一完整 API 的 1100 万开发者和 50 万家公司…

www.postman.com](https://www.postman.com/downloads/)

下载完成后,继续打开它,您应该会看到类似如下的屏幕:

令人欣慰的是,邮差用户界面非常直观,很容易适应所有东西的位置。

输入我们要测试的 URL,在本例中为:

http://127.0.0.1:5000/game

请注意,您的地址可能会因端口而异。此外,“127.0.0.1”有时也被称为“localhost”,因此向以下地址发送请求基本上是一样的。

http://localhost:5000/game

注意地址末尾的/game,这是我们在 server.py 文件中设置的路由。

回到 Postman,在 Query Params 下,您应该看到一个“key”“value”字段的列表。

在这些字段中键入我们的参数,将会自动用正确的值和特殊字符(如空格)的 URI 编码填充我们的 URI。

继续用下面的值创建一个“游戏”键(我知道它很长,每个游戏预测都是基于 84 个不同的特性):

[5.39279682138009,6.683608045460701,0.15919970376939438,3.55590999603135,1.1554737031359337,0.7067666437650326,1.1426873175695553,1.2569168628035827,-0.7803980111346107,-0.2962583460820777,-0.24055440492626987,-1.7136287338568992,-0.1651305355827784,-0.2036357303066871,-0.4540528313626752,-0.48914117436953486,-0.22271712167442767,-0.5282740359736868,-0.031858861469518406,-0.24937339127109132,-0.32994634379035076,-0.512297869820368,-0.7031963621472596,-0.07105583014744833,-0.29576266052192457,0.1870374024689484,-0.14092851934520698,-0.33523660382633563,-0.14365069955967955,-0.12421426326285712,-0.06650450595001171,-0.10261069449730548,-0.1123532348785659,3.27774725901111,-0.45335715532058596,-0.16592152231605703,1.5775085110873435,1.5048682557955273,1.9597419248177352,-0.48621831608959837,1.642609246782289,0.5213592693458309,-0.48290073165693087,-0.3244873199973241,-0.301429739232314,2.4736135100111123,-0.22133313058352583,3.8765749060205286,-0.23604923873792524,-0.2401213205987764,-0.27373953556863745,-0.35059866422759306,4.098403285704536,4.559516332813075,-0.28035794137016523,-0.2973715918552079,-0.30799315147252165,3.713847136118922,3.139731271607883,-0.2625780433542825,2.3218106291644776,-0.30943922402842255,2.6890016668398484,-0.2316238571204376,3.884818704555654,-0.35758626244129893,-0.31778939411173085,-0.24428267916420615,-0.43130531370481745,-0.2341397130078093,-0.22087023503836106,-0.3216777806746954,-0.21651103657152967,-0.28636063937475126,-0.21776380127418174,-0.2768681688204387,-0.7287651618291123,-0.355929439908863,-0.24655521427098337,-0.22667679255666365,-0.2785523148360368,-0.2524454873949673]

继续按“发送”,您应该会得到类似如下的回复:

完美!我们的服务器接受一个表示单个游戏特性的浮点字符串列表,并返回一个数字,该数字是 Steam 商店中外观的预测排名。

结论

在本文中,我们经历了创建一个 HTTP 服务器的整个过程,该服务器可以接受一个包含游戏特性列表的请求,然后用一个表示 Steam store 页面上预测排名的数字进行响应。

我们将服务器做得非常简单,没有处理任何错误处理或参数验证。关于如何做到这一点,有大量的参考资料,并且可能是将来的一篇文章。

感谢您的阅读,如果您有任何想法或问题,请让我知道,我很乐意有机会谈论任何与技术相关的话题。

使用简单的 Python 服务器为您的机器学习模型提供服务

原文:https://towardsdatascience.com/serve-your-machine-learning-models-with-a-simple-python-server-5a72d005e0ae?source=collection_archive---------28-----------------------

如何轻松服务于机器学习模型

许多数据科学项目中最大的挑战之一是模型部署。在某些情况下,您可以批量离线进行预测,但在其他情况下,您必须实时调用您的模型。

此外,我们看到越来越多的模型服务器像[TensorFlow Serving](https://www.tensorflow.org/tfx/guide/serving)[Torch Serve](https://pytorch.org/serve/)被发布。尽管有很多很好的理由在生产中使用这些解决方案,因为它们快速高效,但是它们不能封装模型技术和实现细节。

这就是为什么我创造了[mlserving](https://pypi.org/project/mlserving/)。一个 python 包,帮助数据科学家将更多的火力集中在机器学习逻辑上,而不是服务器技术上。

作者图片

mlserving尝试一般化预测流,而不是您自己实现预测,或者为此使用另一个服务应用程序。

通过实现一个简单的接口,您可以轻松地为您的模型设置一个端点。

作者图片

这个接口表示一个通用的预测流。

让我们看一个例子(假设我们已经有了一个训练好的模型)

首先,我们将训练好的模型加载到构造函数中,并实现接口。

稍后,我们创建一个ServingApp,并添加我们刚刚实现的推理处理器。

在这个例子中,我们没有对输入进行任何处理,但是正如您所看到的,为您的模型设置一个端点是非常容易的。

通过发送 POST 请求来调用我们的模型。

curl -X POST [http://localhost:1234/api/v1/predict](http://localhost:1234/api/v1/predict) \
-H 'Content-Type: application/json' \
  -d '{
    "features": [...]
}'

使用 TensorFlow 服务也不例外,用我们的定制处理来包装 TensorFlow 服务非常容易,但首先,我们需要设置我们的 TensorFlow 服务。在本例中,我们将使用 docker:

docker run -p 8501:8501 \
  --mount type=bind,source=/path/to/my_model/,target=/models/model \
  -e MODEL_NAME=model -t tensorflow/serving

在这里阅读更多:https://www.tensorflow.org/tfx/serving/docker

现在我们已经成功运行了 TensorFlow 服务,让我们围绕它创建一个 python 处理层:

这一次,我们没有在构造函数中加载我们的模型,因为 TensorFlow Serving 已经加载了它。

def predict方法由TFServingPrediction 实现,基本上,它发送从def pre_process 返回的有效载荷,并处理 TensorFlow 服务的推理。所以我们剩下要做的就是实现预处理和后处理。

就是这样!我们已经设法用一个易于使用的 API 来包装我们的模型。

我很乐意听到任何反馈或建议,随时联系!

感谢阅读!

附加资源

无服务器:无痛的 AWS 样板文件

原文:https://towardsdatascience.com/serverless-a-painless-aws-boilerplate-e5ec3b4fb609?source=collection_archive---------16-----------------------

为 AWS lambda 部署提供支持离线测试的样板文件

AWS Lambda

无服务器开发由于易于部署而受到关注。此外,鉴于 AWS lambda 能够将其他服务与 AWS SDK 集成,它已经成为一种流行的选择。然而,如果你不具备可伸缩性,当你扩展你的 API 时,从小处着手可能会给你留下巨大的重构空间。因此,在这里,我将总结我在一家初创公司的经验,并分享一个很好的样板文件,通过以一个简单的 REST API 作为起点,它将使您的开发变得快速和可伸缩。我假设您对 AWS 部署如何工作和云形成有所了解。

要记住的要点

  1. Cloudformation 模板将只允许每个部署 200 个资源。(文档)。因此,服务部署应该以更细粒度的方式完成。
  2. 每个部署的服务将拥有多个资源,并独立访问其他服务。
  3. 如果我们有单独的服务,我们可以单独捆绑,使捆绑包的大小更小。

在本文中,让我们关注第一个限制。针对这一限制的唯一可行的解决方法是使用只关注一个任务的隔离服务(这确实是使用微服务的动机。).让我们使用无服务器框架来制作样板文件(入门指南:此处为)。还有,你需要无服务器离线插件(获取:这里)。

构建无服务器配置

简而言之,我们将为每个服务建立单独的文件夹,并为每个文件夹建立一个service.yml。在无服务器框架中,当我们部署或运行离线插件时,我们可以使用--option VALUE提供任何选项。我们将利用这个工具来选择单独的服务进行部署或离线运行。我们将在命令行中使用--service选项加载每个服务,并使用--stage选项进行分段。

在这个样板文件中,我将如下组织我的文件夹结构。

- serverless.yml (main serverless config file)
- prod.env.yml (configs for the prod environment)
- dev.env.yml (configs for the dev environment)
- offline-serverless.js (offline runner for testing)
- package.json (node modules neede, for nodejs)// Folders containing the application logic- first-service
-- service.yml
-- main.js- second-service
-- service.yml
-- main.js// Utils for routing
- utils
-- lambda-router.js
-- errors.js (Error message, not essential)
-- db-util.js (Managing the database connection)

serverless.yml 的内容

这是我们服务结构的核心。在 YML 中,我们可以构造符号,以便在运行时填充部分文件。在我们的例子中,从每个服务的service.yml文件中选择与服务相关的内容。

我们的serverless.yml如下所示。

无服务器. yml

这里,package将携带要包含的文件夹,而functions将携带每个服务内部的功能。这些将从每个服务的文件夹的service.yml文件中加载。

部署脚本命令示例:

serverless deploy --stage dev --service service1

用于测试的离线配置

离线运行命令的示例如下所示:

serverless offline start --stage dev --service service1 --port 3000

然而,为了测试,我们必须在不同的端口上运行每个服务。下面是一个脚本,使我们的任务变得简单。

无服务器-offline.js

这里PATH1PATH2是基本路径(例如;users/为用户服务,posts/为帖子服务)。这在服务内部是不相关的,因此,请注意,我已经删除了基本路径;在第 24 行。每个服务都专注于一件事,所以拥有一个单独的基本路径是多余的(然而我们将在最终的 API 部署中拥有它)。

我们可以简单地离线运行我们所有的服务进行测试;

node offline-serverless.js

每个服务内部的内容

每个服务应包含所需的资源。在这个例子中,我们将放置 REST API 端点。这段代码将如下所示。

service.yml

注意,这里我们包括了node_modules utils和携带逻辑的文件。

部署

部署就像普通的无服务器框架部署一样。然而,在 API 网关中有一些值得注意的事情。

具有多个服务的示例部署视图

如前所述,尽管我们的应用程序有端点,如users/profile-detail,但我们的用户服务将只接受profile-details,因为它的唯一目的是处理用户。然而,我们需要 API 知道users/请求必须提供给用户服务 lambda。我们就是这么做的。

转到—API,然后转到自定义域名。您将看到以下视图。

自定义域名

在这里,您可以单击编辑并添加自定义映射。例如,在上面的设置中,我将它们添加如下。

基本路径、服务和阶段的映射

对于这个 API,生产环境只有一个映射。如果你有几个在线测试的环境,你必须这样设置。在这里,我已经购买了一个域,并为我的 API 链接了子域。然而,您可以使用无域 API,但是这样您将不得不依赖 AWS 为每个服务随机生成的 URL(不整洁!).

清盘

  • 路径是相对于serverless.yml记录的,所以加载外部文件时要小心。总是使用__dirname + ‘/file.extension’来加载文件。
  • 我为这个样板文件做了一个 repo ,包括我的 lambda 路由器和 DB 处理器。看一看,星,叉,提高,发个 PR 给我。
    https://github . com/anuradhawick/AWS-lambda-server less-boilerplate
  • 看看 lambda 路由器吧,它非常简单,支持LAMBDA_PROXY集成(请看这里的)。你可以在这里看到我是如何使用它的
  • 如果您计划向serverless-offline.js添加更多服务,请选择不同的端口及其基本路径。更新第 4 行中的services数组。

相信这篇文章会对日以继夜辛勤工作的开发者有所帮助。
感谢阅读!干杯!

带 HuggingFace 和 AWS Lambda 的无服务器 BERT

原文:https://towardsdatascience.com/serverless-bert-with-huggingface-and-aws-lambda-625193c6cc04?source=collection_archive---------12-----------------------

用 BERT、HuggingFace、无服务器框架和 AWS Lambda 构建一个无服务器问答 API。

Samule 孙Unsplash 上的照片

原载于 2020 年 6 月 30 日https://www . philschmid . de

介绍

“无服务器”和“BERT”是强烈影响计算世界的两个主题。无服务器架构允许我们动态扩展和缩小软件,无需管理和配置计算能力。它允许我们,开发者,专注于我们的应用

伯特可能是最有名的自然语言处理模型。你可以说它改变了我们处理文本数据的方式以及我们可以从中学习到什么。“BERT 将帮助[Google]搜索[实现]更好地理解[ing]10 个搜索中的一个” 。伯特及其伙伴罗伯塔、GPT-2、艾伯特和 T5 将在未来几年推动商业和商业理念,并将像互联网曾经做过的那样改变/颠覆商业领域。

搜索语言理解伯特

想象一下,将这两者结合在一起,您将获得怎样的商业价值。但是 BERT 并不是最容易在无服务器架构中部署的机器学习模型。BERT 很大,需要相当大的计算能力。您在网上找到的大多数教程都演示了如何在“简单”的环境中部署 BERT,比如一个具有 16GB 内存和 4 个 CPU 的 VM。

我将向您展示如何利用无服务器架构的优势,并在无服务器环境中部署 BERT 问答 API。我们将使用 HuggingFace 的变形金刚库、无服务器框架和 AWS Lambda。

通过 Huggingface 创建变压器库

变形金刚 logo by huggingface

变形金刚库为自然语言理解(NLU)和自然语言生成(NLG)提供最先进的机器学习架构,如 BERT、GPT-2、罗伯塔、XLM、DistilBert、XLNet、T5。它还提供了 100 多种不同语言的数千个预训练模型,并在 PyTorch & TensorFlow 2.0 之间具有深度互操作性。它使开发人员能够针对不同的 NLP 任务(如文本分类、情感分析、问答或文本生成)微调机器学习模型。

自动气象站λ

AWS Lambda 是一种无服务器计算服务,让你无需管理服务器就能运行代码。它只在需要的时候执行你的代码,并且自动伸缩,从每天几个请求到每秒几千个请求。您只需为您消耗的计算时间付费,当您的代码不运行时,则不收费。

AWS Lambda 标志

无服务器框架

无服务器框架帮助我们开发和部署 AWS Lambda 功能。它是一个 CLI,开箱即可提供结构、自动化和最佳实践。它还允许我们专注于构建复杂的、事件驱动的、无服务器的架构,由函数和事件组成。

无服务器框架标志

如果你不熟悉或者还没有设置无服务器框架,看看这个无服务器框架快速入门

辅导的

在我们开始之前,确保您已经配置并设置了无服务器框架。你还需要一个工作的 Docker 环境。Docker 环境用于构建我们自己的 python 运行时,我们将其部署到 AWS Lambda。此外,您需要访问 AWS 帐户来创建 S3 桶和 AWS Lambda 函数。

在教程中,我们将使用预先训练好的BERT模型构建一个问答 API。这个想法是我们发送一个上下文(小段落)和一个问题给 lambda 函数,它会用问题的答案来响应。

由于本指南不是关于构建模型,我们将使用一个预构建的版本,这是我用distilbert创建的。你可以在这里查看 colab 笔记本

在我们开始之前,我想说我们这次不会深入细节。如果你想更多地了解如何在 AWS Lambda 中使用深度学习,我建议你看看我的其他文章:

我们正在构建的架构将会是这样的。

我们要做什么:

  • 使用无服务器框架创建 Python Lambda 函数
  • 创建一个 S3 桶并上传我们的模型
  • 配置serverless.yaml,添加transformers作为依赖项,并设置一个 API 网关用于推理
  • colab 笔记本中的BERT型号添加到我们的功能中
  • 部署和测试功能

你可以在这个 GitHub 库colab 笔记本中找到我们正在做的一切。

创建 Python Lambda 函数

首先,我们通过使用带有aws-python3模板的无服务器 CLI 创建 AWS Lambda 函数。

该 CLI 命令将创建一个包含handler.py.gitignoreserverless.yaml文件的新目录。handler.py包含一些基本的样板代码。

添加transformers作为依赖项

除了requirements.txt,无服务器框架几乎创建了我们需要的任何东西。我们手动创建requirements.txt并添加以下依赖项。

创建一个 S3 存储桶并上传模型

AWS S3 和 Pytorch 提供了一种独特的方法来处理大于 250MB 的机器学习模型。为什么是 250 MB?Lambda 函数解压缩后的大小限制为 250MB。

但是 S3 允许文件直接从 S3 加载到内存中。在我们的函数中,我们将把来自 S3 的模型squad-distilbert加载到内存中,并作为 Pytorch 中的缓冲区从内存中读取它。

如果您运行 colab 笔记本,它将创建一个名为squad-distilbert.tar.gz的文件,其中包含我们的模型。

要创建 S3 存储桶,您可以使用管理控制台或以下命令来创建。

在我们创建桶之后,我们可以上传我们的模型。您可以手动或使用提供的 python 脚本来完成。

配置serverless.yaml

这次我为我们提供了完整的serverless.yaml。如果你想知道每一节是做什么用的,建议你去看看从零到英雄的缩放机学习。在本文中,我介绍了每种配置,并解释了它们的用法。

colab 笔记本中的BERT模型添加到我们的功能中

典型的transformers型号由pytorch_model.binconfig.jsonspecial_tokens_map.jsontokenizer_config.jsonvocab.txt组成。pytorch_model.bin已经被提取并上传到 S3。

我们将把config.jsonspecial_tokens_map.jsontokenizer_config.jsonvocab.txt直接添加到我们的 Lambda 函数中,因为它们的大小只有几 KB。因此,我们在 lambda 函数中创建了一个model目录。

如果这听起来很复杂,可以查看一下 GitHub 资源库

下一步是在保存我们的模型类ServerlessModelmodel/目录中创建一个model.py

handler.py中,我们创建了一个ServerlessModel的实例,并可以使用predict函数得到我们的答案。

部署和测试功能

为了部署该功能,您只需运行serverless deploy

这个过程完成后,我们应该看到类似这样的东西。

测试和结果

为了测试我们的 Lambda 函数,我们可以使用失眠症、邮差或任何其他 REST 客户端。只需在请求体中添加一个带有contextquestion的 JSON。让我们用 colab 笔记本中的例子来尝试一下。

我们的ServerlessModel83.1正确回答了我们的问题。此外,您可以看到完整的请求花费了 319 毫秒,而 lambda 执行时间大约为 530 毫秒。老实说,这是相当快的。

最棒的是,如果有几个传入请求,我们的 BERT 模型会自动扩展!它可以扩展到数千个并行请求,而不用担心任何问题。

如果您重新构建它,您必须小心第一个请求可能需要一段时间。首先,Lambda 正在解压和安装我们的依赖项,然后从 S3 下载模型。

感谢阅读。你可以在这里找到带有完整代码 GitHub 库,在这里找到 colab 笔记本

感谢阅读。如果你有任何问题,随时联系我或评论这篇文章。你也可以在推特(Twitter)或领英(LinkedIn)上与我联系。

无服务器:构建自己的路由器

原文:https://towardsdatascience.com/serverless-building-your-own-router-c2ca3071b2ec?source=collection_archive---------10-----------------------

如何为基于角色访问的 REST API 开发自己完整的 lambda 路由器

在我的上一篇文章中,我介绍了如何开发一个样板文件来支持 AWS lambda 部署。在本文中,我将展示如何为 REST API 开发一个合适的 lambda 路由器。这是开发可伸缩 AWS lambda 实例的重要一步。

AWS API 网关架构

为什么是路由器,而不是 NodeJS 服务器?

人们通常会在 lambda 中部署一个成熟的 NodeJS HTTP 服务器。然而,在理想的情况下,我们应该避免这样做,因为它会在 lambda 函数内部产生延迟。此外,我们肯定会错过 API 网关的唯一目的和特性,如身份验证和授权。

在这种情况下,我们将实现一个简单的路由器,它不启动单独的服务器,而是利用 lambda 代理实现头将请求导航到我们实现的功能逻辑。通过这种方法,当 lambdas 被调用时,我们将拥有请求的即时路由。

AWS Lambda 代理集成请求事件

使用无服务器框架的默认部署将通过 Lambda 代理集成来部署 lambdas。

Lambda 代理集成 API 示例

lambdas 由带有三个参数 事件上下文、回调 的函数组成。事件对象包含所有有用的信息,包括请求体、路径参数、查询参数、请求路径、源、cookie 信息、头和其他请求参数。在代理集成中,我们的 lambdas 的行为类似于 Nginx 路由器(其中我们有所有的重写规则、转发、静态文件呈现等)。我们将利用来自事件对象的信息来构建我们的路由器。首先,让我们看一下事件对象。

示例请求的事件对象

观察事件对象,我们可以清楚地注意到以下两个主要有用的属性。

- resource
- httpMethod

这基本上是我们纯路由所需要的。哪个method中的哪个path应该被转发给目标function。这简单地类似于开关情况。但是 switch case 应该有更多的功能,包括响应构建和处理不同类型的请求方法。

构建路由器

路由器的输入

路由器必须与 AWS 函数调用一致,即使用 事件上下文回调 作为参数。

创建路由器类或函数

在经典的 javascript 中,类是用函数来模拟的。因此,在这个例子中,我将使用一个考虑到朴素场景的函数(这通常是 Lambdas 中的首选均值)。

我们将实现一个名为Router的函数,它将接受eventcontextcallback作为参数(类似于构造函数属性)。在其中,我们可以有一个函数来调用分配给方法和路径的相关处理程序。让我们看看我们的代码会是什么样子。

路由器实施

你也可以看到我还有另一个功能builResponse。它负责构建响应、字符串化主体和分配状态代码。这将使事情变得简单得多,在下一个关于如何使用路由器的代码片段中,您将会看到这一点。

使用路由器

现在我们已经实现了路由器,让我们看看如何使用它。在下面的代码中,我将展示如何让路由器处理路径datadata/{taskId}上的 GET 请求。如您所见,第二个路径是一个路径模板。路由必须相对于由服务的 service.yml 文件确定的服务来完成。我在之前的文章中已经讨论过这个问题(此处阅读)。如果整个程序只有一个server less . yml文件,可以使用完整路径忽略我前面那句话。

路由器使用

您可以看到,我们可以使用路由器并传递一个处理函数,该函数具有与我们从 lambda 调用中获得的参数相同的参数。我们必须用errorresponse值调用callback函数。但是,我们以 HTTP 状态代码的形式返回错误。因此,error参数将始终为null

授权和认证

如果没有适当的访问控制,应用程序基本上是无用的。认证是授权访问具有用户身份的 API 端点。授权是确保任务由有适当权限的人来完成。最好使用 Cognito 用户池进行身份验证,其中每个用户的头都根据用户池进行验证(从此处了解更多信息)。这将允许带有有效令牌的请求到达 lambda 调用。

角色认知组

当您拥有角色并且角色有权执行特定操作时,需要更细粒度的控制。换句话说,必须对报头进行验证,以检查令牌持有者的权限。这可以通过使用认知用户组来完成。这些可以通过 Cognito 控制台轻松创建。下面是来自真实世界应用程序的几个组。您可以看到一个管理组。

为管理员创建的管理员组

可以创建这些组来向用户分配特定的角色。一个用户可以被分配到多个组。注意,这些组可以使用 AWS SDK 动态创建,不需要访问这个 UI。

验证 Lambda 事件对象的角色

我们分配的这些角色必须在我们的路由器中进行验证,在路由器中我们实际实现了基于角色的访问。我们可以在 AWS 中使用 IAM 角色来执行此操作。但是,这种方法更复杂,更适合限制对 AWS 资源的访问;即 S3 桶、用户池等。因此,我们将在 lambda 内部的路由器级别实现基于角色的访问,以便操纵对数据库和其他资源的访问。

事件对象将在路径event.requestContext.authorizer.claims中具有授权属性。这个对象将有一个名为cognito:groups的属性。这可以是一个数组,也可以是一个值,匹配组或者这个人所属的组。这个值可以用来实现我们的授权。

带角色验证的路由器

这可以简单地作为我们路由器的route功能的扩展。让我们看一下修改情况。

增强型路由器实施

你可以看到我已经检查了cognito:groups是否是一个数组。由于无服务器离线仿真和实际 lambda 行为的不匹配,我不得不这样做。无论如何,它使函数对可能的错误更强。我们的 route 函数调用只需要一个额外的参数,roles 数组。仅此而已!。比如说;

router.route(
    "GET", 
    "/path", 
    (event, context, callback) => { /* Logic + callback */      }, 
    ["Admin", "Some other group", ...]
);

现在你有了一个完整的 lambda 路由器,你可以导入并使用它。lambdas 或重代码处理路由中没有服务器实例。这是一个遵循 【责任链】 设计模式的大开关案例。在每个函数调用中,如果函数调用负责给定的方法路径,处理它们,或者忽略。

这个路由器设计是我们创业时努力的结果,我一直在改进最初设计的一些细节,以适应新的需求。完整的样板文件可以在 GitHub 中找到。

感谢阅读!干杯!

使用 Python 和 AWS Lambda 的无服务器新冠肺炎数据刮刀

原文:https://towardsdatascience.com/serverless-covid-19-data-scraper-with-python-and-aws-lambda-d6789a551b78?source=collection_archive---------8-----------------------

一个重要的 PYTHON 技巧

分步教程:使用 AWS Lambda 调度 Python 脚本

插图作者:金彩云

在数据科学中,获得完整的数据源是最重要的事情之一。在几个项目中,数据源是动态变化的,更新速度很快。对新冠肺炎·疫情来说,病例数一直在变化。大多数可用的开放新冠肺炎源仅在每天的时间间隔内可用;然而,较高分辨率的数据似乎对发现与其他参数如空气质量、环境条件等的关系很重要。通过从实时更新源抓取数据来收集数据是获得您想要的数据的解决方案之一。一些文章已经展示了如何用 Python 轻松做到这一点的例子。然而,安排这样一个 Python 项目需要一台一直运行的服务器。对于一个小项目来说,自己为此目的租用/托管服务器可能不值得。

你好,AWS Lambda!λ

出于这个原因,我想介绍亚马逊的一项计算服务,你可以运行或调度任何 Python 脚本(或其他编程语言,如 Java、Go、Node.js、Ruby、c# …),而无需自己维护服务器。有了 AWS Lambda,我们还可以轻松地与 AWS S3 存储桶中的文件同步。

定价呢?💵

最棒的是, AWS Lambda 处于永远免费层服务中!(截至 2020 年 5 月)它允许我们每月提出多达 100 万个请求!例如,如果我们每 1 分钟从互联网上抓取一次数据集,那么每月只有 43200 个请求(60[请求/小时] 24[小时/天]* 30[天/月])* 。

AWS Lambda 免费领带津贴(作者从 AWS 获取)

本文展示了使用 AWS Lambda 和 AWS S3 桶存储来调度用于抓取新冠肺炎数据的 Python 脚本的分步说明。

我们开始吧

步骤 1:获取新冠肺炎案例的 Python 脚本

首先,我们将准备一个 Python 脚本( covid19scraper.py ),使用RequestsBeautiful Soup库从 Worldometer 中抓取实时全球新冠肺炎数据。总体而言,用于抓取新冠肺炎数据的 Python 脚本如下例所示:

covid19scraper.py (作者举例)

这项技术已经展示过几次了。所以我将只给这个脚本一个简短的介绍。requests用于向 URL 发出 GET 请求,然后BeautifulSoup用于查询 HTML 主体的特定类。在我们的例子中,新冠肺炎案例数据在名为“maincounter-number”的类中,因此调用bsObj.find_all(…)来查找我们感兴趣的所有值。通过调用scrapeGlobalCase(),我们将得到以下结果:

**testResult = scrapeGlobalCase()**testResult: -**{
        ActiveCases: 2302944,
        ConfirmedCases: 3908271,
        Deaths: 270216,
        RecoveredCases: 1335111,
        date: "2020-05-08 00:33:05.775806"
    }**

步骤 2:准备 Python 包

为了在 AWS Lambda 服务上托管我们的 Python 脚本,我们需要用 zip 文件中的脚本准备 Python 模块。首先,我们必须用pip-t ./标签在本地安装所有模块,以指定保存在本地目录中。在我们的示例中,我们需要datetime beautifulsoup4request模块,您可以运行以下命令来本地安装它们:

**$ pip3 install datetime beautifulsoup4 requests -t ./**

然后,使用 zip 命令创建这个 python 文件夹的 zip 文件,或者使用您喜欢的 zip 软件(Winzip,7zip,..).

**$ zip -r python_package.zip ***

步骤 3:准备 S3 桶

在 AWS 上创建 S3 桶(作者从 AWS 控制台捕捉)

因为我们将把我们的结果保存到 AWS S3 存储桶,所以让我们通过 web 浏览器访问您的 AWS 控制台来创建一个存储桶。单击 create a bucket,并为此项目指定一个有意义的名称。您可以根据自己的喜好选择任何地区。我将它命名为“hourlycovid19 ”,用于每小时保存新冠肺炎案例数据。

步骤 4:准备 AWS Lambda 执行角色

在 AWS 身份和访问管理上创建 Lambda 执行角色 (IAM) — 1(由作者从 AWS 控制台捕获)

我们需要为 AWS Lambda 生成一个角色,以便能够访问我们刚刚在上一步中创建的 S3 存储桶。请访问 AWS IAM 控制台。(此处)在菜单中选择“角色”,点击“创建角色”,然后选择“Lambda”用例。找到一个名为“AWSLambdaExecute”的策略,它将允许 Lambda 访问 S3 存储桶。确认后,您可以将此角色命名为“lambda-s3-role”。

在 AWS 身份和访问管理(IAM)上创建 Lambda 执行角色 — 2(由作者从 AWS 控制台捕获)

步骤 5:上传我们的 Python 脚本到 AWS Lambda 层

将我们的 Python 脚本上传到 AWS Lambda 层(作者从 AWS 控制台捕获)

现在,一切都差不多了,是时候将我们的 zip Python 包上传到 Lambda 层,以使我们的 Python 脚本在 Lambda 上可执行。我们可以通过浏览 AWS Lambda 页面,点击“层”菜单,然后点击“创建层”,给出一个名称,选择我们的 zip 文件,然后选择 Python 运行时。

创建 AWS Lambda 层(作者从 AWS 控制台捕捉)

步骤 6:创建 Lambda 函数

创建 AWS Lambda 函数— 1 (作者从 AWS 控制台获取)

现在,让我们创建一个 Lambda 函数来执行我们准备的脚本。浏览到 AWS Lambda 页面,点击“功能”菜单,点击“创建功能”,如上图所示。然后,用“Python 3.x”运行时选择“从头创作”。重要的是选择您在步骤 4 中创建的现有角色“lambda-s3-role ”,以允许此功能访问 s3 时段。您可以遵循下图中的示例设置。

创建 AWS Lambda 函数— 2 (作者从 AWS 控制台获取)

在创建了“covid19scrape”函数之后,然后将我们在步骤 5 中创建的“covidScraper”层附加到这个函数上。该操作将使我们的函数能够读取和调用我们在步骤 1 中创建的 Python 脚本。

将 covidScraper 层(来自步骤 5) 附加到 AWS Lambda 函数(作者从 AWS 控制台捕获)

现在,请转到 lambda 函数中的函数代码部分。在这里,我们将编写一个 Python 脚本,它定义了 Lambda 处理程序,该处理程序从“covid scrape”层的“covid 19 scrape”Python 脚本(如您在步骤 1 中所命名的)中导入“scrapeGlobalCase”函数。我们还导入了“boto3”库来访问 S3 服务。总的来说,用于抓取新冠肺炎数据并保存到 S3 桶的函数代码中的 Python 脚本将如下图所示,或者您可以在此要点查看该脚本。(* 请更改 BUCKET_NAME 以匹配您在步骤 3 中创建的 S3 存储桶)

AWS Lambda 中用于抓取实时新冠肺炎数据并保存到 S3 桶的功能代码。(作者从 AWS 控制台捕捉)

你可以点击“测试”按钮进行测试。有时,可能会出现超时错误,解决这一问题的技巧是调整基本设置以获得更高的 ram/更长的超时时间。对于我来说,我将 ram 设置为 3000 MB,超时时间为 5 秒。

AWS Lambda 功能基本设置。(作者从 AWS 控制台捕捉)

恭喜你!!🎉如果你一直进行到这一步,现在这个 Lambda 函数已经准备好抓取新冠肺炎数据了。

最后一步:调度 Lambda 函数

由于我们的函数已经准备好了,现在让我们使用 CloudWatch 安排我们创建的函数每小时运行一次(或者根据您的喜好)。请转到 AWS CloudWatch 页面并转到事件/规则。在那里,我们可以使用固定的时间比率或使用 Cron 表达式创建一个调度规则,在一天中的特定时间调度作业。如果你是 Cron expression 的新手,请阅读关于如何创建一个 Cron expression 的文档这里。在我们 1 小时计划的例子中,您可以使用这个表达式:0 * * * ? *

使用 AWS CloudWatch 安排 Lambda 函数每小时运行一次(作者从 AWS 控制台获取)

检查结果:

所有结果都作为单独的 JSON 文件保存在“hourlycovid 19”S3 桶中。您可以通过访问 S3 铲斗概述来检查它们。您可以通过 AWS CLI 从 S3 bucket 下载所有 JSON 文件到您的本地机器。如果你想用 easy GUI 从 S3 下载多个文件,我推荐 Cyberduck 🦆工作得很好。

S3 桶中的前三个 JSON 结果(作者从 AWS 控制台获取)

为了展示如何使用该数据集的示例,您可以使用下面的示例脚本来读取输出文件夹中的所有 JSON 文件,并将它们添加到 dataframe 中。

将多个 JSON 文件加载到 Pandas dataframe 的示例 Python 脚本。(作者提供的示例脚本)

每小时一次的新冠肺炎全球病例结果数据帧。(作者截图自 Spyder IDE)

至此,我相信您可以很容易地找到几个教程来继续使用 Python Pandas Dataframe 进行一些非常棒的数据分析或数据可视化。尽情享受吧!!✌

结论

所以,就这样吧!如果你是云计算服务的新手,一开始你可能会觉得这很复杂,但是我相信一旦你让它运行起来,你会爱上它的。我希望你喜欢这篇文章,并且能够在将来应用这个无服务器 Lambda 服务来运行你的工作流。

如果您有任何问题或意见,请随时给我留言。

安全健康健康!💪

感谢您的阅读。📚

无服务器数据集成——绝地大师尤达的十颗智慧珍珠(2020)

原文:https://towardsdatascience.com/serverless-data-integration-jedi-master-yodas-ten-pearls-of-wisdom-2020-fa536cf3724a?source=collection_archive---------65-----------------------

图片来源:flickr.com:atomtetsuwan2002

在无服务器数据集成项目中获得的重要经验

序文

问候爱、和平、健康与和谐!那是 1980 年,我还是个十几岁的少年,正在看我的第一部星球大战电影——《T2》《帝国反击战《T4》【第五集】。它让我难以置信地着迷,留下了不可磨灭的印象。差不多四十年过去了,我还是一个粉丝。绝地大师尤达是《星球大战》三部曲中我最喜欢的角色。

为了更好地阅读这篇文章,我使用了尤达大师的反序演讲格式,这使得分享智慧的珍珠更加有趣。当你大声朗读 10 颗珍珠时,想象它是用大师的声音呈现的:)

这些珍珠是我在第一个无服务器数据集成项目中学到的经验。这相当于绝地第一次用她的光剑做有意义的事。这段经历过去是(现在仍然是)无价的,我希望你能从中获得价值。说到无服务器数据集成,我想起了尤达大师的一句名言— 做…还是不做。没有尝试!我们开始吧。

智慧的结晶

数据集成在企业中创建了“数据真相”的单一版本。它为企业提供高质量的标准化数据,从而实现分析、机器学习和人工智能。无服务器数据集成使组织能够交付大量数据,同时优化运营成本。以下是我学到的经验:

#1 —将您必须的无服务器功能从状态中分离出来!

无服务器微服务本质上是短暂的。它由一个事件触发,并执行一个特定的动作作为响应,然后就完成了。微服务的微容器的内存内容不应该试图在当前调用之外直接共享。强制无服务器应用程序或函数调用直接共享其范围之外的状态,将导致次优设计。这会影响可伸缩性,并引入大量不必要的副作用。当需要时,微服务应该将暂时的状态信息写入数据库( Memcached 或 Redis )。在写入永久日志的情况下,应该使用其他可靠和持久的数据持久性机制。即使对于数据集成中心(Hub)也是如此。

#2 —测量您应该测量的系统安静时间!

并非所有工作负载都真正适合无服务器计算。集线器是无服务器实现的典型代表,它的特点是先有突发的活动,然后是一段安静的时间。它本质上是不可预测的。除了正常操作之外,中心还需要支持不同的每日数据量,在没有预设时间(没有计划的作业)的情况下接收和处理数据,并根据需要执行专门的一次性转换。通常,中心日常处理的这种不可预测性需要动态和即时的计算扩展来实现最佳性能。一旦操作完成,集线器进入安静状态。了解枢纽的安静时间特征,使我们能够准确量化运营成本节约。最后,空闲时间不会对我们造成任何损失,这意味着——无服务器计算的运营成本优化是安静时间的一个功能。

#3 —优化您的函数运行时间,不要因为函数资源分配而分心!

在系统性能优化领域,以下公式被视为圣杯:

响应时间(经过时间)=服务时间+等待时间

响应时间需要成为集线器所有组件的优化目标。每个微服务都需要优化到尽可能短的运行时间。这个概念可能适用于所有计算应用程序,而不仅仅是集线器。

AWS Lambda 中,分配给 Lambda 函数的内存量与其预计成本之间存在直接关联。成本(每秒)与分配的内存量成比例增加。众所周知,内存分配越大,vCPU 内核分配比例越大。 AWS Lambda 根据内存量(最多约 1.75–1.8 GB)分配单个 vCPU 内核。超过此内存阈值,将分配 2 个 vCPU 内核并按比例扩展。

借助双线程微服务设计,可以利用额外调配的资源(CPU 和内存)来提高性能。这直接导致运行时间的减少和成本的降低。请记住,您需要为程序的运行时间付费,运行时间优化应该是您唯一的关注点。不用说,收益递减规律会在资源分配(内存)上发挥作用。目标是在“拐点”之前分配足够的内存。因此,集线器中的大容量数据操作非常适合双线程微服务,这种服务利用 3GB 内存和 2 个 vCPUs。

#4 —不一定是约束,这些函数运行时限制!

一个 AWS Lambda 函数的当前运行时间限制是 900 秒 。这个限制很容易克服(如果需要的话),在一个 AWS 步骤函数中有简单的编排逻辑。使用一个简单的计时器和一个数据处理跟踪器(跟踪处理进度的指针),程序的运行时执行被监控。功能在适当的时间重新启动(比如定时器到期前 10 秒),确保程序持续运行时间超过 Lambda 的 900 秒限制。

说了上面的话,我想提醒我们所有人一个微服务意味着一个轻量级架构和一个短的运行时间(非常谦虚地说——我们没有理解微服务的哪一部分:)).我相信,当一个微服务被优化设计时,它不应该要求运行时间超过 15 分钟。在需要处理大量数据的情况下,可以使用步进功能协调同一个微服务,以启动多个并行执行,所有执行都在 15 分钟内单独完成。

#5 —这些功能延迟和冷启动辩论无关紧要!

函数延迟是用来量化启动一个 AWS Lambda 函数所用时间的术语。它表示重用一个已经配置好的微容器所花费的时间。当在短时间内发生多个独立的执行时,这是一个相关的讨论点。当功能执行频率大于 30 分钟时,微型容器需要重新配置。这被称为冷启动。解决这个问题的方法之一是利用 Lambda 函数配置中的“供应并发”。但是有一个与之相关的固定成本,它否定了安静时间和成本节约的概念。本质上,集线器对功能延迟甚至冷启动不敏感。它不是一个永不停机的应用程序,每小时每分钟每秒都要处理数百个 API 调用。因此,功能延迟和冷启动的问题与集线器无关。

#6 —您必须区分幂等处理和重复处理!

幂等元是计算机科学的一个基本构造,它定义了程序执行的最终状态。幂等执行要求在输入值相同的情况下,无论程序运行多少次,程序的最终状态都保持完全相同。例如,一个将客户地址修改为' 123 Main Street '的程序是幂等的,无论我们运行它多少次。客户地址的最终状态是“123 Main Street”。多次运行这个程序没有负面影响。因此,一个程序是否是幂等的,取决于程序的需求、上下文、设计和操作的数据。

关于为什么 AWS Lambda 不能保证幂等的执行,存在疑问和争论。由于 Lambda 函数如何实现的动态和异步特性(包括在冷启动期间启动微容器),在一些边缘情况下,可以针对单个执行请求同时启动多个容器。作为云计算的实践者,我们需要用一个重要的原则来设计—‘一切可以打破的,都将打破’。因此,需要主动解决上面讨论的AWSλ的环境副作用。这是防止重复数据处理的一个简单例子。

作为数据从业者,我们都赞同保护系统免受同一数据集的任何意外重复处理的设计。这些安全措施建立在程序逻辑的范围内。这是绝对正确的,也是一个枢纽所需要的。重复数据处理的场景类似于消息队列的消费管理。为确保加工的完整性,设计结构如总是一次加工应优先于至少一次加工。当消费结构至少有一次是时,不能责怪队列产生重复数据。因此,λ函数不是幂等的是没有意义的。不管一个程序是否幂等,在一个中枢中为重复数据处理设计安全措施是不可协商的,并且必须合并。

#7 —避免将功能硬连线到您的 VPC 上!

AWS Lambda 的计算资源全部在 Lambda 的服务 VPCs 内运行。 Lambda 调用可以通过 AWS Lambda API发生。没有对函数运行的执行环境的“网络访问”的规定,因此不能仅仅侵入λ调用及其执行微容器。 AWS Lambda (当没有硬连接到你的 VPC 时)的默认行为是,它可以访问公共域中的任何东西,甚至是在 AWS 之外。仅仅因为一个短暂的函数可以访问公共资源,并不自动意味着它会。人们可以不厌其烦地讨论安全角度,但是对于短暂的无服务器计算环境(不访问你的 VPC 资源)VPC——硬连线是不必要的。

当一个λ函数硬连线到你的 VPC 时,它会在你的 VPC 内创建一个弹性网络接口(ENI)* ,允许访问私有资源。这将计入您所在地区的帐户限额(IP 地址、API 费率、网络费率)。当您试图增加和扩展函数调用时,您将面临这些帐户限制的挑战,因为每次调用一个 VPC 连接的函数都需要一个 ENI 。在集线器的情况下,λ功能需要访问 VPC 资源(数据),因此出于安全和隔离的目的,建议通过专用子网进行访问。功能互联网接入通常与集线器无关,但在需要和适用时,应通过 VPC NAT 网关进行控制。*

2019 年 9 月,AWS 推出了一种更高效的方法,让函数使用 AWS 超平面 ENIs 与您的 VPCs 进行通信。这个新的和改进的 VPC 网络,消除了之前在你的 VPC 中创建的众多运行时 ENIs 。使用新方法, Lambda 函数连接到超平面 ENIs* ,超平面 ENIs 反过来管理到您的 VPC ENIs 的连接(每个安全组一个:子网)。这样做,它消除了直接的 ENI 连接,使 VPC 网络更具可伸缩性,并减少了 VPC 有线函数调用的延迟时间。*

# 8——观察无服务器功能的工作方式!

无服务器环境明显缺乏功能可观察性。这是由于计算环境的瞬时性。相反,在基于服务器的环境中,人们总是能够通过各种跟踪方法来观察程序的执行。因此,功能可观察性是观察执行行为和相关细节的行为。

虽然在 AWS 的 CloudWatch 日志中记录了一组默认的标准指标,但是每天有大量函数调用的应用程序会在从 CloudWatch 中挖掘特定于函数的细节时产生问题。这类似于大海捞针。当然还有 AWS X 光进行功能调试和追溯。然而,我认为我们需要更好地控制我们观察到的东西。

在 Hub 中,每个微服务都应该配备一个日志记录功能,写入我们选择的日志表。我们现在控制我们想要在函数执行中观察什么。在日志表的设计上做一点投资就可以走很长的路。以下是日志记录的一些基本属性— 函数名、运行日期、运行时间、总运行时间、对象名、行数和调用参数。这些属性给了我们一个良好的开端,我们可以根据我们不断发展的需求来扩充它。这为您的无服务器中心增加了重要的生产监控价值。以下是亮点:

1)为功能执行日志的持久化量身定制结构,即没有一刀切的标准

2)基于执行标准和日志记录级别的灵活日志记录粒度,即调试/故障排除期间的较高粒度与正常操作期间的较低粒度**

3)易于将日志转换为可操作信息(AWS elastic cache),即清晰了解中心的健康状况

4)定制日志历史记录的保留,由您对性能基线的要求控制,并具有您定义的时间段

因此,功能可观察性,一个中心运营管理的关键方面,是我们需要拥有的东西,而不仅仅依赖于 CloudWatch

#9 —您必须抽象,以避免被云供应商锁定!

给无服务器讨论足够的时间,它将变成云服务提供商(CSP)锁定辩论。诚然,不需要必要的前期设计工作,CSP 锁定也是可能发生的。如果您的无服务器函数中有硬编码的专有 SDK API 调用,您可能会被锁定。即使对于基于服务器的应用程序也是如此——硬编码是一种糟糕的做法!

问题——一个 AWS Lambda 函数,用 Python 3 编程。至少有一个 AWS Python SDK 调用的 x(boto 3 或 botocore* )不能被提升并“按原样”转移到另一个 CSP。这是因为没有任何 CSP 间 SDK。然而,有一种方法可以通过一些“计算抽象”来获得 CSP 独立性。考虑一个简单的微服务,它采用两个参数(storage _ bucket _ name&object _ name)从 CSP 的存储桶中检索和下载一个对象。这个任务的主要 Python SDK API 调用(跨 3 个示例 CSP)如图 1 所示:*

图 1 — Python SDK API 调用 AWS、GCP & Azure 从存储桶下载对象

从图 1 中可以清楚地看到,由于 CSP 拥有专有的 SDK,因此每个 CSP 的微服务都是不同的。您将需要为 3 个不同的 CSP 提供 3 个不同的程序,从而维护 3 个不同的代码库。这对大型代码库来说是痛苦的。

解决方案 —如果微服务和基础程序设计保持简单,那么跨 CSP 的微服务执行和编排将成为现实。这是通过一点 JSON 杂耍和一个简单的代码部署配置完成的。目标是只维护基础程序的一个副本。CSP 特定调用的封装是用 JSON 文档完成的。图 2 提供了一个使用 JSON 的抽象方法,在代码部署时用一个基础程序设计一个特定于 CSP 的微服务:

图 2——使用 JSON 对 GCP AWS 的微服务进行简单的 Python 程序抽象& Azure

如图 2 所示,将每个 CSP 的 SDK API 调用分离到自己的列表中,可以促进基础程序的单一版本,同时保持代码的可移植性。以下是方法:

1.通过 SDK API 调用抽象所有 CSP 的微服务

2.创建一个名为 get_obj_from_bkt 的 JSON 文档,将每个特定于 CSP 的定义封装在一个列表中(如图 2 所示)

3.将 JSON 文档的内容— get_obj_from_bkt 存储在一个 NoSQL 文档集合中— 让我们称这个表/集合为 CodeAbstract

4.创建一个 Python 函数— CodePreProc ,它显式地为所有微服务生成代码。在我们的例子中,我们将为 get_object_from_bkt 微服务生成代码。

5.在代码部署期间(CI/CD 管道),使用运行时参数( aws/azr/gcp )调用 CodePreProc 。比如—CodePreProc(‘AWS’);**

6.基于这个运行时参数, CodePreProcCodeAbstract 表中查询和检索 get_obj_from_bkt JSON 文档。

7.AWS 代码数组( aws_get_obj_from_bkt )选自 JSON 对象{},假定' aws' 传递给了 CodePreProc

8. CodePreProc 然后在给定 CSP 代码数组的元素之间“连接”换行符(“\n”)(使用 join() 函数)并创建适当的 Python 程序—AWS _ get _ obj _ from _ bucket . py 文件

9.特定于 AWS 的 get-obj_from_bkt 微服务现在已经准备好在 CI/CD 管道的下一阶段进行测试和部署。

因此,通过将特定于 CSP 的 SDK API 调用封装在 JSON 文档的列表中,并使用简单的预处理脚本动态生成特定于 CSP 的函数,就有可能解决供应商锁定问题。同样,这种方法不是解决所有代码可移植性问题的灵丹妙药,但它确实为硬编码 CSP SDK API 调用提供了一种可行的替代方案。只有在预先完成了必要的抽象和设计工作,从而提供了跨云代码可移植性的自由时,这才是正确的。上述方法有两个优点:

a)利用单个基础/包装程序的能力,该程序没有特定于 CSP 的函数调用。这允许通过独立的 CSP 专用 SDK API 微服务(功能)支持具有相同代码库的多个 CSP。

b)对 SDK(参数/名称等)的更改。)对于给定的 CSP,只影响 JSON 文档中一个特定 CSP 的代码数组。对其他 CSP 和 orchestrator 计划没有任何影响。如果需要进一步分离,可以修改 JSON 文档的结构,将每个 CSP 的代码分离到一个独立的 JSON 文档中。

总之,特定于 CSP 的 SDK API 调用抽象需要预先设计,并且可能不适用于所有现有项目。然而,对于新的项目,它确实提供了一种将微服务从特定于 CSP 的 SDK API 调用中分离出来的方法。这有助于维护通用基础程序,并使我们摆脱供应商的束缚!

#10 —测试您应该…在本地测试云的这些功能!

好的集成开发环境(IDE)是程序员的工作台。设计良好的 ide 支持高效的程序开发和测试。“本地”测试云功能的需求是您在项目中很快会遇到的一个需求。没有云感知的 IDE,测试变得非常耗时,因为我们将花费更多的时间通过 CSP 的代码管理管道推送代码,而不是实际的测试。因此,本地测试大大提高了生产率。幸运的是,有一些云友好的 ide 可以拯救程序员。这种 IDE 的一个很好的例子就是 Stackery

结论

无服务器数据集成中心以尽可能低的运营成本提供企业数据真相的单一版本。持续学习、适应和成长的重要性需要在我们生活的各个方面成为一种长期的习惯。无服务器数据集成也不例外。我将带着尤达大师著名的智慧之珠离开你,它让我保持谦逊和脚踏实地——你还有很多要学的!

领先云平台上的无服务器机器学习架构

原文:https://towardsdatascience.com/serverless-machine-learning-architecture-on-leading-cloud-platforms-c630dee8df15?source=collection_archive---------47-----------------------

亚马逊网络服务(AWS)、谷歌云平台(GCP)和微软 Azure 上的机器学习架构

云平台 GCP、AWS、Azure

云平台本身有各种各样的服务,这些服务可以混合和匹配,以满足任何具有分配预算的业务案例的需求。在这里,我将挑选一个这里提到的通用示例,并讨论上述云平台上的架构。

因为架构是无服务器的,所以有一堆功能可以确保事物在服务之间向前移动。

要求:

这项业务有源源不断的支持票。支持代理从客户那里获得的信息很少,因此他们会花更多的时间来了解客户的需求。

在代理开始处理问题之前,他们需要完成以下工作:

  • 理解支持票的上下文。
  • 确定问题对客户的严重程度。
  • 决定使用多少资源来解决问题。

通常,与客户的几次来回交流会获得更多的细节。如果您添加基于票证数据的自动化智能,您可以帮助代理在处理支持请求时做出战略性决策。

通常,用户在填写包含几个字段的表单后,会记录一个票据。对于这个用例,假设没有一个支持票已经被机器学习丰富。另外,假设当前的支持系统已经处理票据几个月了。

要开始丰富支持票证,您必须训练一个使用预先存在的标签数据的 ML 模型。在这种情况下,训练数据集包含在已关闭的支持票证中找到的历史数据。

谷歌云架构

  1. 基于 Firebase 的数据库更新创建一个云函数事件。
  2. 客户端向 Firebase 数据库写一张票。
  3. 云函数触发器执行一些主要任务:
  • 使用部署的机器学习算法运行预测。
  • 用丰富的数据更新 Firebase 实时数据库。
  • 使用整合的数据在您的帮助台系统中创建票证。

无服务器技术和基于事件的触发

  • “无服务器技术”可以有多种定义方式,但大多数描述都包含以下假设:
  • 服务器应该是一个遥远的概念,对客户来说是看不见的。
  • 动作通常由事件触发的功能来执行。
  • 函数运行的任务通常是短暂的(持续几秒或几分钟)。
  • 大多数时候,函数只有一个目的。

Firebase 和云功能相结合,通过最大限度地减少基础架构管理来简化开发运维。操作流程如下:

  • 基于 Firebase 的数据库更新创建一个云函数事件。
  • 客户端向 Firebase 数据库写一张票。
  • 云函数触发器执行一些主要任务:
  • 使用部署的机器学习算法运行预测。
  • 用丰富的数据更新 Firebase 实时数据库。
  • 使用整合的数据在您的帮助台系统中创建票证。

https://cloud . Google . com/solutions/architecture-of-a-a-server less-ml-model

Firebase 本身是一个大规模的服务,并且该架构使用了给定的上下文:

  • Firebase 是一个客户端可以更新的实时数据库,它向其他订阅的客户端显示实时更新。
  • Firebase 可以使用云功能来调用外部 API,比如您的帮助台平台提供的 API。
  • Firebase 可以在桌面和移动平台上工作,可以用各种语言开发。当 Firebase 遇到不可靠的互联网连接时,它可以在本地缓存数据。

AWS 云架构

  • 亚马逊 S3 的结构化数据湖,用于保存原始数据、建模数据、增强数据和转换数据。
  • 该功能的暂存桶设计和转换的数据将被纳入 Amazon SageMaker。
  • AWS Lambda 上托管的数据转换代码,用于为消费和 ML 模型培训准备原始数据,并转换数据输入和输出。
  • Amazon SageMaker automation 通过 Lambda 函数为新模型构建、管理和创建 REST 端点,基于一个时间表或由数据湖中的数据变化触发。
  • API 网关端点托管公共 API,使开发人员能够获得其应用程序的历史数据或预测。
  • Amazon Kinesis 数据流,支持在接收、建模、增强和转换阶段实时处理新数据。
  • 亚马逊 Kinesis Data Firehose 将模型和增强阶段的结果传送到亚马逊 S3 进行持久存储。
  • AWS IAM 在每个处理组件上执行最小特权原则。IAM 角色和策略只限制对必要资源的访问。
  • 一个为每日亚马逊弹性计算云(Amazon EC2)现货定价构建和更新预测模型的演示场景。

来源:https://D1 . AWS static . com/partner-network/quick start/datasheets/pari veda-data-lake-sage maker-on-AWS-architecture . 50175 e 74 B2 b 654 a 12 a B2 CBE 933 f 47 a3 a 018 f0d 12 . png

蔚蓝建筑

该架构由以下组件组成:

  • 天蓝色管道。这个构建和测试系统基于 Azure DevOps ,用于构建和发布管道。Azure Pipelines 将这些管道分成称为任务的逻辑步骤。例如, Azure CLI 任务使得使用 Azure 资源变得更加容易。
  • Azure 机器学习。Azure Machine Learning 是一个云服务,用于大规模培训、评分、部署和管理机器学习模型。这个架构使用用于 Python 3 的 Azure 机器学习 SDK 来创建工作空间、计算资源、机器学习管道和评分图像。Azure 机器学习工作区提供了实验、训练和部署机器学习模型的空间。
  • Azure Machine Learning Compute是一个按需虚拟机集群,具有自动扩展和 GPU 及 CPU 节点选项。训练作业在该集群上执行。
  • Azure 机器学习管道提供可重用的机器学习工作流,可以跨场景重用。对于这个用例,训练、模型评估、模型注册和图像创建发生在这些管道中的不同步骤中。管道在构建阶段结束时发布或更新,并在新数据到达时触发。
  • Azure Blob 存储。Blob 容器用于存储来自评分服务的日志。在这种情况下,将收集输入数据和模型预测。经过一些转换后,这些日志可以用于模型再训练。
  • Azure 容器注册表。计分 Python 脚本打包为 Docker 映像,并在注册表中进行版本控制。
  • Azure 容器实例。作为发布管道的一部分,通过将评分 web 服务映像部署到容器实例来模拟 QA 和暂存环境,这提供了一种简单、无服务器的方式来运行容器。
  • 蔚蓝库伯内特服务。一旦评分 web 服务映像在 QA 环境中经过全面测试,它就会被部署到受管 Kubernetes 集群上的生产环境中。
  • Azure 应用洞察。该监控服务用于检测性能异常。

来源:https://docs . Microsoft . com/en-us/azure/architecture/reference-architectures/ai/m lops-python

希望这篇文章能帮助我们从高层次上了解在给定的业务案例中哪些服务在起作用。必须记住,这还不是一成不变的,因为有几个假设,最重要的是没有考虑预算限制。

参考资料和来源:

[## 无服务器机器学习模型的架构|解决方案

这一系列文章探索了无服务器机器学习(ML)模型的架构,以丰富支持票…

cloud.google.com](https://cloud.google.com/solutions/architecture-of-a-serverless-ml-model) [## 使用 Azure 机器学习的 Python 模型的 mlop-Azure 参考架构

该参考体系结构展示了如何实施持续集成(CI)、持续交付(CD)和…

docs.microsoft.com](https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/ai/mlops-python) [## 亚马逊 SageMaker 的预测数据科学和 AWS 上的数据湖-快速入门

存储和转换数据以构建预测性和规范性应用程序这一快速入门构建了一个数据湖…

aws.amazon.com](https://aws.amazon.com/quickstart/architecture/predictive-data-science-sagemaker-and-data-lake/)

无服务器 ML:大规模部署轻量级模型

原文:https://towardsdatascience.com/serverless-ml-deploying-lightweight-models-at-scale-886443d88426?source=collection_archive---------54-----------------------

理解大数据

UnsplashZbynek Burival 拍摄的照片

部署难题

将机器学习(ML)模型部署到生产中有时会成为数据科学(DS)团队的绊脚石。一种常见的部署模式是找到一个地方来托管您的模型,并通过 API 公开它们。在实践中,这可以让您的最终用户轻松地将您的模型输出直接集成到他们的应用程序和业务流程中。此外,如果客户信任你的 API 的输出性能的有效性,这可以驱动巨大的商业价值:你的模型可以对目标商业问题产生直接持久的影响。

但是,如果您无法获得 DevOps 或 MLOps 团队形式的持续技术支持,那么就要费力地通过云服务来设置负载平衡器、API 网关、持续集成和交付管道、安全设置等。开销会很大。此外,除非你对这些概念非常有信心,否则交付(和监控)一个 ML API 来保证大规模的安全性和性能,从而赢得用户的信任是很有挑战性的。

当然,有越来越多的服务可以帮助你完成这个过程。也许你的第一站会是主要云提供商的托管模型部署服务(比如 SageMaker )。或者,你可能会关注一个蓬勃发展的 MLOps 工具/平台,如 CortexSeldon ,或者甚至你可能会选择一头扎进类似 KubeflowTensorFlow Serving 的东西。当你开始工作时,可能会有点困惑。

如果你想大规模地部署模型,你将不得不花费大量的时间学习一些技术,并且熟悉一些软件工程概念。

这里还有另一个问题。虽然这些工具和平台自动化了许多特定于 ML 的任务,并且通常减少了部署 ML 模型的认知负担,但是它们仍然涉及大量的开销:在您可能有信心在实践中使用这些工具之前,您仍然需要花费相当多的时间来阅读文档和使用示例。事实上,一般来说,如果您想要大规模地部署模型,您将不得不花费大量的时间来学习相当多的技术,并且熟悉相当多的软件工程概念。即使有了这些新工具,也没有捷径可走。

虽然这都是事实,但当然总会有特例。在这些特殊情况下,你可以走一些捷径,帮助你以最小的开销快速地将一个 ML 模型投入生产。这就是这篇文章的内容:它将给出一个关于什么是特例的高层次概述;简要介绍无服务器计算的概念;然后介绍一个代码例子(带回购!)来部署一个特例 ML 模型作为 Google Cloud 函数,只需要几行代码。

特殊情况

有一种说法由来已久,经常被引用,但偶尔会被误用(被忽略?)DS、软件工程和其他领域的概念,从小、干净、简单开始,然后随着时间的推移增加复杂性。从 ML 模型的角度来看,这意味着从最简单的 ML 模型开始(即产生有用的商业价值),并从那里开始。例如,这可能意味着——如果给定的业务问题允许的话——在达到一个巨大的梯度提升树或深度神经网络之前,你可能想尝试玩一些简单的线性模型

这些更复杂的建模方法自然对 DS/ML 领域的人有吸引力:它们在许多应用程序中显然非常强大。但是也有不利的一面。对一个人来说,解释可能很快变得困难。在某些情况下,对小数据集的不良概括也是一种真正的危险。从部署的角度来看,也存在一些潜在的问题。首先:提供这些功能的包和库通常很重。它们通常有很大的二进制文件(即占用大量磁盘空间),它们有很高的内存和 CPU(还有 GPU/TPU)需求,它们有时会有(相对)差的推理性能,并且通常有臃肿的图像(例如,如果使用 Docker 这样的技术)。

相比之下,简单的线性模型通常具有最小的依赖性(如果需要,还需要几十行纯 NumPy 代码来从头实现一个轻量级的线性模型),训练后几乎为零的资源需求,以及闪电般的推理性能。冒着听起来过时的风险:你可以用一堆设计良好的线性模型走很长的路。

冒着听起来过时的风险:你可以用一堆设计良好的线性模型走很长的路。

所有这些都是在说:如果你能用线性模型很好地解决一个商业问题,你最好至少从那里开始。如果你从那里开始(并且使用 Python——无服务器的限制,而不是部落的东西!),那你就是特例之一。恭喜你!将轻量级模型部署为无服务器功能可能会为您节省大量时间和痛苦,并且可能是您的用例的理想选择。

走向无服务器

在过去的几年里,无服务器计算的概念已经在软件工程领域得到了迅速发展。其基本思想是,通过在很大程度上消除工程师手动配置其服务器、负载平衡器、容器等的需求,云提供商可以在抽象出(隐藏)将应用部署到生产环境中的复杂性方面大有作为。能够产生任何商业价值之前。

在某些方面,这类似于上面概述的一些数据科学家面临的问题:在稳定的服务中获得一个模型并最终产生商业价值通常需要大量的开销。无服务器计算旨在消除大部分这种开销:原则上,目标是让您,即开发人员,编写一个简单的函数,并立即以理论上无限可扩展和安全的方式将其部署到“生产”中。

…我们的目标是让开发人员编写一个简单的功能,并立即以理论上无限可扩展和安全的方式将其部署到“生产”中。

此外,无服务器计算明确旨在支持“事件驱动”应用。例如,如果您需要一个函数(模型)在每次云存储中的特定文件发生变化时运行,或者在每天的特定时间运行,或者在每次新客户注册您的服务时运行,您可以轻松地配置您的函数。你可以免费获得这种功能。听起来很酷,对吧?

除了这里的讨论之外,这篇文章不会涉及无服务器的基础知识。如果您想更深入地了解无服务器的工作方式,以及它的相对优势和劣势,那么您应该看看以前的一篇帖子:

[## 无服务器计算简介

这篇文章介绍了无服务器计算的一些基本概念,并帮助您将无服务器应用程序部署到 GCP。

medium.com](https://medium.com/@mark.l.douthwaite/a-brief-introduction-to-serverless-computing-e867eb71b54b)

现在举个例子!

编码时间到了

这个例子将向您展示如何构造和构建一个简单的 ML 管道,用于训练一个 Scikit-Learn 模型(在本例中是一个简单的LogisticRegression模型)来使用 UCI 心脏病数据集预测心脏病,然后将其部署为谷歌云功能。这不是数据分析的练习,所以不要期望对数据探索和建模决策进行太多的讨论!如果你想深入研究代码,可以这样做:

[## markdouthwaite/无服务器-scikit-learn-demo

一个提供演示代码的存储库,用于部署基于轻量级 Scikit-Learn 的 ML 管道心脏病建模…

github.com](https://github.com/markdouthwaite/serverless-scikit-learn-demo)

对于其他人,请继续阅读!

开始之前…

你需要注册一个谷歌云账户,并确保你已经阅读了上一篇介绍无服务器计算的文章。谷歌目前提供 300 美元的“免费”积分,这对于本教程和你自己的一些项目来说已经足够了。只是记得当你完成后禁用你的帐户!声明:这篇文章与谷歌没有任何关系——它只是一个慷慨的提议,对于那些想增长云服务知识的人来说可能很方便!

[## GCP 免费等级免费扩展试用和永远免费|谷歌云

20 多种免费产品免费体验热门产品,包括计算引擎和云存储,最高可达…

cloud.google.com](https://cloud.google.com/free)

此外,您需要在系统上安装 Python 3.7,并访问 GitHub。如果你经常使用 Python 和 GitHub,应该没问题。如果没有,您可以检查您安装的 Python 版本:

python --version

如果你没有看到Python 3.7.x(其中x将是一些次要版本),你需要安装它。您可能会发现pyenv对此很有帮助。下面是用 pyenv 安装特定版本 Python 的指南。你可以通过 GitHub 的“Hello World”指南了解如何开始使用 GitHub。

克隆存储库

首先:您需要存储库。您可以通过以下方式克隆存储库:

git clone [https://github.com/markdouthwaite/serverless-scikit-learn-demo](https://github.com/markdouthwaite/serverless-scikit-learn-demo)

或者你可以直接从 GitHub 克隆这个库

盒子里面是什么?

现在,导航到这个新克隆的目录。存储库提供了一个简单的框架,用于构建您的项目和代码,以便将其部署为云功能。有几个文件你应该熟悉一下:

  • Python 捕捉项目依赖关系的古老(如果有缺陷的话)惯例。在这里,您可以找到运行云功能所需的软件包列表。Google 的服务会查找这个文件,并在运行您的功能之前自动安装其中列出的文件。
  • steps/train.py -这个脚本训练你的模型。它构建了一个 Scikit-Learn 管道,提供了一种简洁的“规范”方式将您的预处理和后处理绑定到您的模型,作为一个单独的可移植块。这使得将它部署为云功能(以及一般的 API)变得更加容易和干净。).当它完成训练后,它将对模型进行简单的评估,并将一些统计数据打印到终端。生成的模型将用 joblib 进行酸洗并作为pipeline.joblib保存在artifacts目录中。实际上,你可能会发现将这些文件保存在谷歌云存储中很有用,但现在将它们存储在本地也可以。
  • main.py -这个模块包含你的“处理程序”。这是用户在部署服务时调用您的服务时将与之交互的内容。您可能会注意到init_predict_handler函数的结构有点奇怪。这是因为函数需要在第一次加载main模块时加载您的模型,并且您的函数需要维护一个对已加载模型的引用。当然,您也可以简单地将它加载到函数范围之外,但是所示的结构通过将模型的“可见性”仅限于函数本身,而不是您可能编写的访问该模块的任何其他代码,缓解了我的强迫症。
  • app.py -该模块提供了一个最小的Flask应用程序设置,用于在本地(即在部署之前)测试您的云功能。你可以用python app.py启动它,然后像平常一样调用它。
  • datasets/default.csv -本例的“默认”数据集。这是 CSV 格式的 UCI 心脏病数据集。
  • resources/payload.json -一个示例负载,当它被部署时,你可以发送给 API。方便,嗯?
  • notebooks/eda.ipynb -一个虚拟笔记本,用于说明在模型开发过程中您可能需要存储探索性数据分析(EDA)代码的位置。

如果你已经阅读了上一篇关于无服务器概念的文章,这种结构应该对你有所帮助。无论如何,现在是有趣的部分,实际运行代码。

训练模型

自然,要部署一个模型,您首先需要一个模型。为此,您需要使用train.py脚本。这个脚本使用 Fire 来帮助您从命令行配置输入、输出和模型参数。您可以使用以下命令运行该脚本:

python steps/train.py --path=datasets/default.csv --tag=_example --dump

这是在做什么?它告诉脚本从datasets/default.csv加载数据,用标签example标记输出模型,并将模型文件转储(写入)到目标位置(应该是artifacts/pipeline_example.joblib)。您应该会看到如下输出:

Training accuracy: 86.78% Validation accuracy: 88.52% ROC AUC score: 0.95

不是一款可怕的车型呃?全都来自老派的逻辑回归。现在是派对部分:部署模型。

部署模型

现在您已经有了模型,您可以部署它了。你需要安装谷歌云的命令行工具。您可以使用他们的指南为您的系统执行此操作。完成后,在项目目录内的终端中,您可以使用以下命令部署您的新模型:

gcloud functions deploy heart-disease --entry-point=predict_handler --runtime=python37 --allow-unauthenticated --project={project-id} --trigger-http

您需要用{project-id}替换您的项目 ID(您可以从您的 Google Cloud 控制台获得)。几分钟后,您的模型应该是活动的。您可以在以下网址查询您的新 API:

[https://{subdomain}.cloudfunctions.net/heart-disease](https://{subdomain}.cloudfunctions.net/heart-disease)

当您的模型被部署时,终端输出将给出您可以调用的特定 URL(替换您的{subdomain})。简单吧?您新部署的模型基本上可以无限扩展,这很好。

查询模型

最后,是时候做一些预测了。您可以发送:

curl --location --request POST 'https://{subdomain}.cloudfunctions.net/heart-disease' --header 'Content-Type: application/json' -d @resources/payload.json

您应该得到:

{"diagnosis":"heart-disease"}

作为回应。就这样,你有了一个活的 ML API。恭喜你!

要记住的事情

正如您所看到的,将您的 ML 模型部署为无服务器功能可能是获得一个稳定的、可伸缩的 ML API 的最快、最简单的途径。但一如既往,这是有代价的。以下是一些需要记住的事情:

  • 无服务器功能(如 Google Cloud 功能)通常会受到资源(CPU、RAM)的限制,因此在无服务器功能中加载和使用“大”模型通常会有问题。
  • 无服务器函数在高响应性时工作得最好(例如,在 ML 情况下推理时间非常快)。如果您的模型有点慢,或者依赖于其他慢的服务(例如,慢的 SQL 查询),这可能也不是最佳选择。
  • 无服务器功能通常被设计用来处理大量的小请求。如果您的用例涉及大的、批量的查询,它们可能不是一个很好的选择——通常对请求有严格的超时限制。
  • 一段时间未使用的无服务器功能会关闭。你一打电话给它们,它们就会转回来。当功能“预热”时,这会产生短暂的延迟。此外,例如,如果您正在使用 Python,Python 解释器众所周知的缓慢启动时间可能会成为问题
  • 无服务器功能通常对常见的“基础设施”语言如 Node JS 和 Python 有一流的支持。如果你用的是 R,MATLAB,Julia 等。(包括通过rpy2作为 Python 的依赖项)支持从不存在到很差不等。有种变通方法,但是这些方法通常会带来性能损失和复杂性增加(在某种程度上降低了“无服务器”概念的价值)。

原载于 2020 年 8 月 13 日https://mark . douthwaite . io

无服务器:调整 Lambdas

原文:https://towardsdatascience.com/serverless-tweaking-the-lambdas-de13507793e4?source=collection_archive---------34-----------------------

调整 lambdas 以确保不可伸缩资源的高可伸缩性

图片由来自 PixabayRyan McGuire 拍摄

无服务器编程很容易部署。无服务器的可伸缩性只受您指定的上限的限制(至少文档是这么说的)。然而,除非你做了正确的设计,否则整个系统可能会立刻失效。这是因为我们插入到 AWS 部署中的大部分外部资源不像 lambda 函数那样可伸缩。此外,您的设计应该基于您正在为无服务器环境编写程序的想法。

在这篇文章中,我将分享我在一个具有大并发性的大中型项目中工作时所面临的困难。我将使用节点。JS 作为编程环境。

基础知识

有几个事实你应该记住。

  • 您永远不应该假设同一个实例将用于处理请求,尽管我们可能会利用这种可能性来提高性能。
  • 没有用于数据序列化的永久存储。然而,您可以访问一个小的 /tmp 路径来在单个调用中进行序列化。因此,确保使用唯一的文件名以避免冲突,并在同一次调用中完成。
  • 不应对服务请求的顺序做出任何假设。
  • 根据 CPU 小时数(和 RAM)收取使用费。所以要确保你的代码运行得很快,没有太多的颠簸。

处理瓶颈资源

几乎在所有场景中,web 应用程序都希望连接到数据库并读取/写入数据。然而,数据库的并发连接数是有限的,可以通过 lambda 函数的并发级别轻松通过。此外,您可以拥有多个独立的函数,这些函数都有数据库连接。例如,如果几乎同时调用 10 个函数,那么最少需要 10 个连接。然而,在高峰场景中,这很容易被乘以一个大到足以使数据库达到极限的因子。

降低可扩展性

大多数情况下,您不会达到希望有 1000 个并发调用的程度。您可以从 AWS 控制台或在 serverless.yml 中更改此设置。(看看我的无服务器样板文章,了解更多关于组织无服务器项目的信息)。

functions:
  hello:
    handler: handler.hello
      events:
        - http:
            path: /hello
          method: get
    provisionedConcurrency: 5
    reservedConcurrency: 5

保留的并发性将确保函数总是可以伸缩那么多倍,而提供的并发性决定最初将有多少实例是活动的。这确保了扩展时间不会增加服务延迟。在一个示例场景中,您可能希望在主页上设置多一点的并发性,而在用户管理服务上设置很少的并发性,因为它们不能应对高需求。

缓存数据并避免数据库连接

在某些情况下,不要求数据一致。例如,博客网站可能不希望总是从数据库中获取数据。用户可能很乐意阅读一些陈旧的数据,但他们永远不会注意到。看看下面的函数。

exports.main = (event, context, callback) => {
    // connect to database, send data in callback(null, data);
}

这将始终与数据库通信。然而,可以这样做。

// cache data in a variable and close DB
exports.main = (event, context, callback) => {
    // send data if event.queryParameters are same
    // else: fetch data and send over
}

通过这种修改,很可能不再从数据库中一次又一次地寻找冗余数据。甚至可以使用时间戳来检查数据是否太陈旧。通过使用一个 chron 作业调用函数,可以有更多的技巧来保持函数的热度。如果负载分布随时间不均匀,则不应这样做。

保持功能温暖

这是 AWS 自己提出的一个著名的保持功能温暖的建议。我们可以简单地通过回调发送数据来做到这一点,而不必完成事件循环。

exports.main = (event, context, callback) => {
    context.callbackWaitsForEmptyEventLoop = false;
}

可以在上下文对象中将callbackWaitsForEmptyEventLoop设置为假。这有助于维护数据库连接,同时在关闭数据库连接之前处理请求。这类似于在全局变量中缓存数据,但在这里,我们缓存整个连接。确保检查连接是否处于活动状态,因为它可能会被数据库服务本身中断。

在这种方法中,有可能超出数据库连接限制。但是这可能是一个方便的技巧,因为建立数据库连接本身可能会增加一些延迟。

处理 CPU 密集型任务

CPU 密集型任务主要是矩阵计算。然而,我们可以把 水印 图像看作是这样一个任务。让我们看看下面的例子。

const Jimp = require('jimp');create_watermarks = async (key) => {
  // get the images from s3
  const s3Obj = await s3.getObject(params).promise();
  // read watermark image
  // for each image from s3
      watermarkImage = await Jimp.read(__dirname + '/wm.png');
      const img = await Jimp.read(s3Obj.Body);
      // add watermark
}

在这个函数中,我们多次读取图像。但是,添加以下内容可以节省大量时间,加快一切。

const img = await Jimp.read(watermark);
watermarkImage = await Jimp.read(__dirname + '/wm.png');
// for each image from s3
    const watermarkCopy = watermarkImage.clone();
    // add watermakr

这可以通过在全局变量中缓存已经读取的水印图像来进一步优化。

const Jimp = require('jimp');
watermarkCache = null;create_watermarks = async (key) => {
    if watermarkCache==null <- read and set variable
    // copy watermark and add to each image
}

管理函数内部的并发性

节点。JS 有事件循环架构。在这种情况下,所有项目都在单个线程中调度和运行。这就是为什么我们在节点没有观察到任何竞争情况。JS 并发。事件循环不断轮询异步任务以获得结果。所以有太多的并发任务会使事件循环更长。此外,如果并发任务使用衍生的进程,系统可能会被不必要的颠簸淹没。

add_watermark (img, wm) => {add watermark, return new image}

现在,如果你用下面的函数从 S3 和水印中加载 100 个潜在的图像键,会发生什么?

s3keys_list = [...100 keys...]
await Promise.all(map(add_watermark, s3keys_list))

事件循环将发出 100 个并发的 S3 对象请求。这可能会使您超过内存限制,甚至可能会在 S3 或其他地方产生并发费用。我们如何解决这个问题?一个简单的解决方案如下。

s3keys_list = [...100 keys...]
tmp_list = []
for(x = 0; x < s3keys_list.length; x++)
{
   // s3keys_list[x] to tmp_list
   // if tmp_list.length == 5
   // await Promise.all(map(add_watermark, tmp_list))
   tmp_list = []
{
// process any remaining items in tmp_list the same way

使用这种方法,可以保证有特定的并发性。你不会有一大群超过 RAM 的克隆水印。

除了我讨论的上述技巧之外,我们还可以根据领域和应用程序的知识使用许多其他的优化。此外,我们可以简单地观察日志,并使用它们来进一步调整并发性需求。有时,以牺牲并发性为代价增加一点内存甚至是值得的。这是因为很多人很少使用站点维护端点。

我希望你喜欢阅读这篇文章。这些是我们在开发有许多用户的平台时使用的一些技巧。这有助于我们应对大范围促销活动期间的一次性高需求,在该活动中,许多用户进行了注册。

通过 REST API 服务于机器学习模型

原文:https://towardsdatascience.com/serving-a-machine-learning-model-via-rest-api-5a4b38c02e90?source=collection_archive---------22-----------------------

利用 Flask 服务于机器学习模型

照片由 Lefteris kallergisUnsplash 拍摄

对于那些不熟悉我的作品的人,在过去一篇题为“ 使用机器学习检测欺诈 ”的帖子中,我们开始制造我们机器学习包的第一部分。

现在,包装完成了,但是我们下一步做什么呢?我们如何将它集成到我们需要使用它的任何地方——Github 上的包存储库。

[## kurtispykes/信用卡欺诈检测

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/kurtispykes/credit-card-fraud-detection/tree/master/packages/random_forest_model)

在此向大家介绍一下 REST API。

注意:这个项目很大程度上受到 Udemy 上的“部署机器学习模型”课程的启发,因此会有来自那个项目的源代码片段。

什么是 REST API?

APIA 应用 P 编程 I 接口的缩写。从本质上讲,它是一个软件中介,允许两个应用程序相互对话。如果你不熟悉 API,那么你就不会知道你很可能每天都在使用它。不相信我?你上一次发即时短信是什么时候?你当时用的是 API。

REST 缩写代表REpresentationSstateTtransfer,它决定了 API 的外观。像任何其他的架构风格一样,REST 有它自己的指导约束,如果一个接口被称为 RESTful,那么应该满足这些约束——关于 REST 的更多信息,请参见“ 什么是 REST ”。

简单地说,REST API 将被请求资源的状态传输给客户机。在我们的例子中,请求的资源将是来自我们的机器学习模型的预测。因此,我们的服务器将把预测传递给客户端,客户端可能是从 web 应用程序到移动设备的任何东西。

为什么要使用 REST API?

这样设计我们的系统有很多好处。例如,通过 REST API 服务我们的模型也允许我们这样做;

  • 即时提供预测以增加客户数量
  • 可能在不同的 API 端点组合多个模型
  • 通过在负载平衡器后添加更多应用程序实例来进行扩展
  • 将我们的模型环境从面向客户的层中分离出来——团队可以独立工作

烧瓶介绍

为了构建我们的 API,我们将利用 Flask 微框架。由于各种原因,例如极其强大、易于使用和非常好的文档,Flask 是 Python 中微服务的流行选择——参见文档

“微型”并不意味着您的整个 web 应用程序必须适合一个 Python 文件(尽管它确实可以),也不意味着 Flask 缺乏功能。微框架中的“微”意味着 Flask 旨在保持核心简单但可扩展。

来源 : 烧瓶文件

我们的 REST API

基本结构

让我们先来看看我们的目录结构…

图 1: 回购目录结构

最顶层的目录是ml_api,在这个目录中有requirements.txtrun.pyrequirements.txt就是我们在虚拟环境中需要的产品包。

图 2:requirements . txt 的内容—我们正在安装 flask 版本 1.1.2 和我们做了包的 random _ forest _ model 因此,我们将能够执行导入语句来调用包。

因此,我们开始用pip install -r path\to\requirements.txtrequirements.txt文件安装到我们的虚拟环境中,这将安装flask并找到我们的random_forest_model包的发行版。

run.py文件是一个入口点,我们将使用在app.py模块中定义的create_app()函数来启动 flask。

图 3 :启动砂箱的入口点。

让我们看看app.py模块。从图 1 我们可以看到,我们可以通过api子目录导航到该文件。

图 4

app.py中,我们有自己的工厂函数,它创建了我们的 flask API 并设置了蓝图,蓝图创建了一个位于controller.py中的端点。

图 5

控制器是一个简单的健康端点,在 HTTP GET 请求期间出现,它返回“工作正常”。

在我们启动这个实例之前,在命令提示符下设置 flask 应用程序的入口点是很重要的。在命令提示符下导航到我们的ml_api目录,然后简单地输入set FLASK_APP=run.py就可以了。当我们完成后,我们只需输入python run.py,结果如下…

图 6 :终点

太好了,我们的终点也如我们所希望的那样工作了。现在我们有了基本的框架,我们可以添加一些更复杂的东西。

注意:添加配置和日志超出了本文的范围,但是在更新的存储库中,你会看到它们存在。因此,下一节将讨论添加预测端点。

下一步是在controller.py中为我们的健康端点添加一个推理端点

图 7 :追加预测终点

我们已经从我们的random_forest_model包中调用了predict函数来从我们的模型中获取结果。任何软件工程项目的一个非常重要的部分是测试,所以让我们测试我们的端点,看看它是否如我们所期望的那样工作。

图 8 :测试我们的预测终点是否按预期工作

PyTest 超出了本文的范围,但是为了运行我们的测试,我们必须运行pytest path\to\test_dir,这将运行我们的测试目录中的所有测试——如果我们通过了测试,那么我们的预测端点是健康的并且正在运行。

图 9 :端点通过测试!

现在你知道了!

谢谢你看完,我们在 LinkedIn 上连线吧…

[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn

在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)

将深度学习算法作为服务运行

原文:https://towardsdatascience.com/serving-deep-learning-algorithms-as-a-service-6aa610368fde?source=collection_archive---------12-----------------------

现实世界中的 DS

如何将深度学习算法作为服务

所以,你想把深度学习算法作为服务来服务。

马里乌斯·马萨拉尔在 Unsplash 上的照片

你有一个用 Python 和 tensor flow/Keras/一些其他平台编写的非常酷的算法库,它需要在 GPU 上运行工作负载,你希望能够大规模地服务它,并让它快速运行。

芹菜是基于分布式消息传递的开源异步任务队列。在阅读了所有可能的博客帖子和 Youtube 上所有关于芹菜的视频后,我决定这是手头任务的正确解决方案。

有请我们的剧情主角:

  1. API :获取一个请求,创建一个 Celery 异步任务,并将其放入一个队列中。(我推荐使用 flask 来完成这项任务,它很轻,但是可以扩展)
  2. 消息队列:又名芹菜的经纪人。将 API 创建的任务存储在队列中。最好的做法是选择 RabbitMQ。
  3. Workers :我们将在 GPU 上运行的 python/celery 进程,它将从队列中获取任务。这是完成所有繁重工作的地方。
  4. 结果的后端:将存储任务返回值。最佳实践是使用 redis,它支持复杂的工作流(一个任务依赖于另一个任务)而无需轮询。

最佳实践是使用 Celery,用 RabbitMQ 作为消息的代理,用 redis 作为结果的后端,以便使用 Celery 能够提供的所有独特特性。我们知道软件需求的变化经常比我们预期的要快,这应该给我们提供最大的灵活性,这样我们甚至可以使用芹菜最复杂的特性。当选择 RabbitMQ 和 redis 时,每个新任务都被转换成一条消息,然后 Celery 将这条消息发送到 RabbitMQ 中的一个队列,一个工人执行的任务的每个返回值都会自动写回 redis(您可以使用" click to deploy "在 GCP 上轻松托管 RabbitMQ,使用 AWS Elastic Cache 托管 redis)。

一旦表示任务的消息在队列中,我们需要一个 GPU 工作器来计算它。GPU 工作器将从队列中读取一条消息并执行任务。例如,如果这是一个计算机视觉算法,一名工作人员将从 S3 自动气象站下载原始图像,对其进行处理,然后将新图像上传回 S3。图像的 URL 将作为任务的一部分被传递。

但是等等,有个问题。

总有一个陷阱。

GPU 是非常昂贵的机器。P2 的一个例子。AWS 中的 Xlarge 每月花费超过 2,000 美元(在写这几行的时候, 3.06 美元一小时),如果是 spot 实例,大约 600 美元。这显然意味着,如果没有必要,我们不希望它们一直处于运行状态。它们必须按需开启,然后关闭。事实是,Elastic Beanstalk 没有根据 RabbitMQ 队列指标自动伸缩的特性。

我们该怎么办?

我们必须编写自己的自定义自动缩放器。这是一个小 Python 脚本的大名,它每 30 秒运行并轮询 RabbitMQ 队列中的任务数。如果队列中有消息,它会调用 AWS API 并相应地启动 GPU workers。

每个工人都是用算法库的 docker 容器引导的(存储在 ECR,弹性容器注册表中)。一旦容器启动并运行,它就连接到 RabbitMQ 和 redis。然后,它从队列中取出一个任务并计算它。输出由工人写给 S3。如果任务成功完成,那么芹菜任务的返回值是一个 json,包含保存到 S3 的输出的 URL 及其元数据。Celery 会自动将返回值保存到 redis 中,也会保存到 Postgres DB 中。如果任务未能完成,异常将保存到 redis。

查看下图,了解上面解释的架构:

Nir Orman 将深度学习算法作为服务运行

听起来很轻松?使用芹菜的一个主要挑战是如何正确配置它。

这里有一个很好的配置,当你试图大规模执行深度学习任务时,它可以节省你的时间和眼泪。请查看以下内容,然后我们将深入了解它的每个细节:

from celery import Celery
from api.celery_jobs_app.celery_config import BROKER_URI, BACKEND_URI

APP = Celery(
    'celery_app',
    broker=BROKER_URI,
    backend=BACKEND_URI,
    include=['api.celery_jobs_app.tasks']
)

APP.conf.update({
    'imports': (
        'api.celery_jobs_app.tasks.tasks'
    ),
    'task_routes': {
        'calculate-image-task': {'queue': 'images-queue'}
        }
    },
    'task_serializer': 'json',
    'result_serializer': 'json',
    'accept_content': ['json'],
    'worker_prefetch_multiplier': 1,
    'task_acks_late': True,
    'task_track_started': True,
    'result_expires': 604800,  # one week
    'task_reject_on_worker_lost': True,
    'task_queue_max_priority': 10
})

:为了更容易理解,对配置进行了简化。

我们来分解一下。

打破它!

片段中的第一段只是一些导入,微不足道。

第二段定义了芹菜 app 本身,它有一个代理和后端(如前所述,最佳实践是使用 RabbitMQ 和 redis)。

第三段更新了芹菜的配置,这是有趣的部分。

导入”部分说明了芹菜应该在我们的哪个 python 包中寻找任务。

' tasks_routes '部分在任务名称和它应该被存储的队列之间进行映射。在上面的代码片段中,所有类型为“计算-图像-任务”的任务将被推入一个名为“图像-队列”的队列中。如果你不写你的任务应该被路由到哪个队列,它将默认地被路由到名为‘celery’的默认队列。顺便说一句,如果你愿意,可以通过定义“task_default_queue”属性来更改默认队列的名称。

仅供参考:一旦第一个任务被路由到 RabbitMQ 上,队列本身就会自动创建。酷:)

酷毙了。

task _ serializer’:这是任务一旦被放入队列后将被序列化的方式,也是任务到达工作线程后被反序列化的方式。在图像处理的情况下,我们不希望图像本身被序列化和反序列化,最佳实践是存储它并只传递它的位置或 URL。我们将使用 json 作为序列化器。

result _ serializer’:请记住,如果您将序列化类型声明为 json 并返回一个对象或异常的结果(这是在出现未被捕获的异常的情况下的返回类型),那么您的结果序列化将会抛出一个异常,因为任何不是 json 的对象都会抛出一个未能序列化的异常。你可以在这里阅读更多关于连载器的内容。

'accept _ content':允许的内容类型/序列化程序的白名单。

提示:不推荐使用‘pickle’序列化器,因为它存在安全问题。从芹菜 4.0 版开始,json 其实就是序列化的默认选项,但是“显式比隐式好”(Python 的禅宗)。

Python 的禅

worker _ prefetch _ multiplier’:Celery 的缺省值是每个 worker 接受 4 个任务,并在返回进行下一个任务之前计算完所有任务。他们的想法是优化网络往返。在我们的情况下,深度学习任务往往很长(比网络时间长得多)。这意味着我们不希望一个工人拿着一堆任务,一个接一个地执行它们。我们希望每个工人一次接受一个任务,然后在前一个任务完成后回来接受下一个任务。这样,如果一个任务需要很长的计算时间,其他工作人员可以同时处理下一个任务,因为只要第一个工作人员没有处理它们,它们就会被保留在队列中。

'task _ acks _ late':默认情况下,当工人接受一个任务时,该任务会在 执行前 被“确认”。在深度学习任务的情况下,这需要很长时间来计算,我们希望它们只在计算完 之后 被“确认”。这在我们使用 spot 实例时特别有用,它降低了我们的平均任务价格,但如果 GPU 实例短缺,并且我们的投标价格不够有竞争力,也可能会失去它。

task _ track _ started’:有助于跟踪任务已经开始,因为当您的任务长时间运行时,您希望知道它不再在队列中(它将被标记为“pending”)。)我推荐使用 Flower 作为芹菜的监控解决方案,它可以让你确切地看到每个任务的状态。

result _ expires’:默认情况下,芹菜在 redis 上只保留你的结果 1 天。如果您希望保留更长时间,请在配置文件中以不同方式定义“result_expires”。我建议最多保留 1 周,并将结果写入一个更有组织的数据库,比如 PostgreSQL。

【task _ reject _ on _ worker _ lost’:我们将此设置为 True。当我们使用 spot 实例时,当一个 spot 实例从我们身边拿走时,有可能会丢失一个工人。我们希望将任务放回队列中,由另一个工作者来计算。小心,如果一个工人丢失是由于硬件错误,如“内存不足”等。,那么任务将在一个循环中一次又一次地被部分计算,因为工作者将在每次试图计算它时丢失。如果您看到一个无限循环的任务,这就是您应该怀疑的配置。

task _ queue _ max _ priority’:这是你可以确保重要任务先完成的地方。您可以为每个 Celery 任务设置一个优先级(通过给它分配一个表示其优先级的 int)。如果设置该属性,还必须将其设置到 RabbitMQ 队列中,它不会自动设置。如果具有优先级的任务进入没有 priority 属性的队列,将会引发异常,并且该任务不会进入队列。如果您有一个任务应该首先计算的高级客户,则此属性很有用。

如果您正在考虑使用该属性,以便将快速运行的任务优先于慢速任务(例如长 GPU 计算任务),那么可以考虑添加另一组工作人员,即 CPU 工作人员,而不是昂贵的 GPU 工作人员。这会更便宜也更快。

正如您在顶部的架构图中看到的,您也可以让工作人员在完全不同的云上运行。

完全不同的云

例如,您可以在 Azure AKS 上运行您的员工,这是 Azure 的 Kubernetes。但那是一篇完全不同的博文。

祝你用芹菜服务你的深度学习算法好运,如果你有任何问题,请随时在 LinkedIn 上联系我。

如何使用 gRPC API 服务一个深度学习模型?

原文:https://towardsdatascience.com/serving-deep-learning-model-in-production-using-fast-and-efficient-grpc-6dfe94bf9234?source=collection_archive---------18-----------------------

理解什么是 gRPC 以及如何使用 gRPC API 服务深度学习模型的快速简单指南。

在本帖中,你将学习什么是 gRPC,它是如何工作的,gRPC 的好处,gRPC 和 REST API 的区别,最后用 Tensorflow Serving 实现 gRPC API 来服务生产中的一个模型?

gRPC 是 Google 开发的远程过程调用平台。

GRPC 是一个现代的开源、高性能、低延迟和高速吞吐量的 RPC 框架,它使用 HTTP/2 作为传输协议,使用协议缓冲区作为接口定义语言(IDL)以及它的底层消息交换格式

gRPC 是如何工作的?

灵感来源:https://www.grpc.io/docs/what-is-grpc/introduction/

创建了一个 gRPC 通道,该通道在指定的端口上提供到 gRPC 服务器的连接。客户端调用存根上的方法,就好像它是本地对象一样;服务器被通知客户端 gRPC 请求。gRPC 使用 协议缓冲区在客户端和服务器之间交换消息。协议缓冲区是一种以高效、可扩展的格式对结构化数据进行编码的方式。

一旦服务器接收到客户端的请求,它就执行该方法,并将客户端的响应连同状态代码和可选元数据一起发回。gRPC 允许客户端指定等待时间,以允许服务器在 RPC 调用终止之前做出响应。

使用 gRPC 有什么好处?

  • gRPC 使用二进制有效负载,这对于创建和解析是有效的,因此是轻量级的。
  • 双向流在 gRPC 中是可能的,但在 REST API 中却不是这样
  • gRPC API 建立在 HTTP/2 之上,支持传统的请求和响应流以及双向流
  • 消息传输速度比 REST API 快 10 倍,因为 gRPC 使用序列化协议缓冲区和 HTTP/2
  • 客户机和服务器之间的松散耦合使得修改变得容易
  • gRPC 允许集成用不同语言编程的 API

gRPC 和 REST API 有什么区别?

  • 有效载荷格式 : REST 使用 JSON 在客户端和服务器之间交换消息,而 gRPC 使用协议缓冲区。协议缓冲区比 JSON 压缩得更好,从而使 gRPC 更有效地通过网络传输数据。
  • 传输协议 : REST 大量使用 HTTP 1.1 协议,这是文本的,而 gRPC 是建立在新的 HTTP/2 二进制协议之上的,这种协议通过高效的解析来压缩报头,并且安全得多。
  • 流与请求-响应 : REST 支持 HTTP1.1 中可用的请求-响应模型。 gRPC 使用 HTTP/2 中可用的双向流功能,其中客户端和服务器使用读写流相互发送一系列消息。

深度学习模型如何用 Python 实现 gRPC AI?

使用 TF 服务为深度学习模型创建 gRPC API 的步骤

  1. 创建从客户端到服务器的请求负载作为协议缓冲区(。原型)文件。客户端通过存根调用 API。
  2. 运行 docker 映像,公开端口 8500 以接受 gRPC 请求并将响应发送回客户端
  3. 运行服务器和客户端。

实现 gRPC API

要使用 Tensorflow 服务实现 REST API,请关注这个博客

对于 Windows 10,我们将使用 TensorFlow 服务图像。

第一步:安装 Docker App

步骤 2:提取 TensorFlow 服务图像

**docker pull tensorflow/serving**

一旦你有了张量流服务图像

  • 为 gRPC 显示端口 8500
  • 可选环境变量**MODEL_NAME**(默认为model)
  • 可选环境变量**MODEL_BASE_PATH**(默认为/models)

步骤 3:创建并训练模型

这里,我从张量流数据集中提取了 MNIST 数据集

#Importing required libraries
**import os
import json
import tempfile
import requests
import numpy as np
import tensorflow as tf
import tensorflow_datasets as tfds**#Loading MNIST train and test dataset
#as_supervised=True, will return tuple instead of a dictionary for image and label
**(ds_train, ds_test), ds_info = tfds.load("mnist", split=['train','test'], with_info=True, as_supervised=True)**#to select the 'image' and 'label' using indexing coverting train and test dataset to a numpy array
**array = np.vstack(tfds.as_numpy(ds_train))
X_train = np.array(list(map(lambda x: x[0], array)))
y_train = np.array(list(map(lambda x: x[1], array)))
X_test = np.array(list(map(lambda x: x[0], array)))
y_test = np.array(list(map(lambda x: x[1], array)))**#setting batch_size and epochs
**epoch=10
batch_size=128**#Creating input data pipeline for train and test dataset
# Function to normalize the images**def normalize_image(image, label):
  #Normalizes images from uint8` to float32
  return tf.cast(image, tf.float32) / 255., label**# Input data pipeline for test dataset
#Normalize the image using map function then cache and shuffle the #train dataset 
# Create a batch of the training dataset and then prefecth for #overlapiing image preprocessing(producer) and model execution work #(consumer)**ds_train = ds_train.map(
    normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(ds_info.splits['train'].num_examples)
ds_train = ds_train.batch(batch_size)
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE)**# Input data pipeline for test dataset (No need to shuffle the test #dataset)
**ds_test = ds_test.map(
    normalize_image, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(batch_size)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)**# Build the model
**model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
  tf.keras.layers.Dense(128,activation='relu'),
  tf.keras.layers.Dense(196, activation='softmax')
])**#Compile the model
**model.compile(
    loss='sparse_categorical_crossentropy',
    optimizer=tf.keras.optimizers.Adam(0.001),
    metrics=['accuracy'],)**#Fit the model
**model.fit(
    ds_train,
    epochs=epoch,
    validation_data=ds_test,
    verbose=2)**

步骤 4:保存模型

通过将 save_format 指定为“tf”将模型保存到协议缓冲文件中。

**MODEL_DIR='tf_model'
version = "1"
export_path = os.path.join(MODEL_DIR, str(version))**#Save the model 
**model.save(export_path, save_format="tf")
print('\nexport_path = {}'.format(export_path))
!dir {export_path}**

您可以使用saved _ model _ CLI命令检查模型。

**!saved_model_cli show --dir {export_path} --all**

对输入和输出及其数据类型和大小进行建模

步骤 5:使用 gRPC 服务模型

为 gRPC 实施导入库

**import grpc
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2_grpc
from tensorboard.compat.proto import types_pb2**

使用 gRCP 端口 8500 在客户端和服务器之间建立通道。为客户机创建客户机存根,以便与服务器通信

**channel = grpc.insecure_channel('127.0.0.1:8500')**
**stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)**

通过指定模型名称和模型输入、数据类型以及数据大小和形状,为服务器创建请求负载作为协议缓冲区。

**request = predict_pb2.PredictRequest()
request.model_spec.name = 'mnist'
request.inputs['flatten_input'].CopyFrom(tf.make_tensor_proto(X_test[0],dtype=types_pb2.DT_FLOAT,  shape=[28,28,1]))**

如果数据类型和数据大小与模型输入不匹配,您将得到错误“输入大小与签名不匹配”。

要解决此错误,请检查模型输入数据的类型和大小,并将其与发送给 gRPC 的请求进行匹配。

运行 docker 镜像,展示端口 8500 以接受 gRPC 请求

**docker run -p 8500:8500 --mount type=bind,source=C:\TF_serving\tf_model,target=/models/mnist/ -e MODEL_NAME=mnist -t tensorflow/serving**

源应该是绝对路径。

服务器现在准备好接受客户端请求

为了预测请求的结果,从存根调用 predict 方法

**result=stub.Predict(request, 10.0)
result**

来自 gRPC 服务器的结果响应

**res=np.argmax(result.outputs['dense_1'].float_val)
print(" predicted output :", res)**

使用 matplotlib 显示输入图像

**import matplotlib.pyplot as plt
%matplotlib inline
img = X_test[0].reshape(28,28)
plt.title(res)
plt.imshow(img, cmap="gray")**

结论:

gRPC 是 Google 新的远程过程调用 API,比 REST API 快大约 10 倍。gRPC 建立在 HTTP/2 之上,它使用协议缓冲区在客户机和服务器之间高效地交换双向消息。

参考资料:

https://grpc.io/docs/what-is-grpc/core-concepts/

使用 tensor flow Serving-TF 2 . x 部署 Keras 模型

原文:https://towardsdatascience.com/serving-keras-models-locally-using-tensorflow-serving-tf-2-x-8bb8474c304e?source=collection_archive---------13-----------------------

如何使用 TensorFlow Serving 和 Docker 在本地主机上部署自己的 Keras 模型

张量流— 2.1.0

概观

创造了一个很棒的深度学习模型?恭喜你!

不知道如何使用 Keras 创建深度学习模型?别担心!

我将介绍如何创建一个基本的和超级简单的 Keras 模型,以及如何在您的本地机器上部署它。这个模型肯定比您计划部署的任何模型都要简单(嗯,我希望如此!).但是由于这篇文章的目标是使您能够部署您的 Keras 模型,所以我想确保我们不会偏离我们的目标。

现在,我们为什么需要在本地服务器上部署它呢?验证我们用模型想要解决的任何问题都可以在现实世界中得到解决。您会期望您的模型以相同的方式工作,并在真实世界的数据上提供与您在本地 IDE 或笔记本上的测试输入相同的性能。但事实是,它很难做到这一点。如果是的话,太好了!但是,在您部署了供消费的模型之后,您不会希望意识到您的测试数据和真实世界数据之间的差距。

如果真实世界的图像不同于您用来训练、验证和测试模型的白色背景工作室图像,该怎么办?如果由于延迟问题,在网络调用中处理数据的时间比在 IDE 中长,该怎么办?尽早发现这些问题是将你的模型从舒适的笔记本电脑成功过渡到现实世界的关键。

张量流服务

TensorFlow 提供的是什么?

TensorFlow Serving 是一个面向机器学习模型的灵活、高性能的服务系统,专为生产环境而设计。TensorFlow 服务可以轻松部署新的算法和实验,同时保持相同的服务器架构和 API。TensorFlow 服务提供了与 TensorFlow 模型的现成集成,但可以轻松扩展为服务于其他类型的模型和数据。

为什么 TensorFlow 服务?

如果您习惯于使用 TensorFlow 或 Keras 构建模型,那么部署模型最简单的方法就是使用 TensorFlow 服务器。

大多数 TensorFlow 文档是为 TensorFlow-1.0 编写的,遗憾的是,它不能像 TensorFlow-2.0 那样工作。因此需要这个博客。

构建一个超级简单的 Keras 模型

你可以在这里找到我的笔记本:(你也可以在谷歌实验室运行)

[如果您已经以 SavedModel 格式准备好了模型,请跳过这一部分。]

在这里,我将创建一个预测线性关系的模型:

y = 2x + 1

我使用了 Google Colab,但是你可以使用你选择的任何工具,只要生成的模型保持不变。

让我们开始吃吧。

我们首先加载必要的库

然后我们创建数据集

然后我们建立我们的模型。既然是简单的线性关系,单个神经元就够了。

我们现在为我们的模型训练 20 个纪元。经过 20 个时期后,我们的模型在训练和验证时的损失约为 2e-12。然后,我们在测试数据上评估我们的模型。我们的测试损失大约是 2e-12。你可以尝试预测一些值来验证结果,就像我在这里做的那样。我收到的输出是 15.866。

一切看起来都很棒。现在让我们以 SavedModel 格式保存并下载我们的模型。

从这一步开始,该过程将独立于所使用的输入和输出数据的类型。它可以是数字数组、文本、图像、音频或视频。在 Colab 中,您应该能够看到在您的目录中创建了一个名为“linear_model”的文件夹。这里的“export_path”变量表示我们的模型被命名为“linear_model ”,这是它的第一个版本。使用 TensorFlow 服务进行部署时,必须有版本号,因此请确保您的“export_path”采用{MODEL}/{VERSION}的形式,其中版本是不带任何字母或特殊字符的数字。

现在要下载这个模型,我们将压缩这个文件夹,然后使用“google.colab.files”来下载压缩文件。

一旦您在本地机器上解压缩这个 zip 文件,您应该能够看到一个名为' linear_model '的文件夹,其中包含一个名为' 1 '的文件夹,该文件夹包含您的变量和模型架构。

设置您的机器

这是一次性设置活动。

要启动本地服务器,我们需要在本地机器上安装一个 TensorFlow 服务实例。我们将使用推荐的 Docker 使用方式,而不是下载并安装所有必要的库。

你可以在指南这里阅读更多细节。

我们不会遵循指南中提到的所有步骤,因为有些事情是特定于 TF 1.0 的,有些事情是特定于重用已经可用的模型的。

一旦你从这里下载 Docker 到你的系统上,继续完成安装步骤。您需要重新启动系统,以便保存您的所有工作。

安装成功完成后,进入命令提示符(Mac 和 Linux 用户,请使用适当的工具)并键入

docker pull tensorflow/serving

就是这样!现在让我们开始部署我们的模型。

在本地主机上部署 Keras 模型

如果我告诉您,部署模型只是一行命令脚本,会怎么样呢?

你所需要的是到你的“线性模型”文件夹的绝对路径。不要忘记使用绝对路径,因为这将导致错误,你需要花时间和打破你的头来解决。

我的“线性模型”保存在“D:/my_own_models/”中。所以我的命令看起来像:

docker run -p 8038:8501 — mount type=bind,source=D:/my_own_models/linear_model,target=/models/linear_model -e MODEL_NAME=linear_model -t tensorflow/serving

这都是一条线。对于您的后续模型,您只需要更改您的“源”路径。更改您的“目标”和 MODEL_NAME 是可选的,但是,根据上下文,这当然是必要的。

现在,让我们试着理解上面的命令脚本意味着什么。这个脚本的一般形式是

docker run -p {LOCAL_PORT}:8501 — mount type=bind,source={ABSOLUTE_PATH},target=/models/{MODEL_NAME} -e MODEL_NAME={MODEL_NAME} -t tensorflow/serving

{LOCAL_PORT}:这是您机器的本地端口,所以请确保您没有在那里运行任何其他程序。我们将它映射到 TensorFlow Serving 为 REST API 调用公开的 8501 端口

{绝对路径}:这是模型的绝对路径。这告诉 TensorFlow 服务你的模型位于哪里(很明显)。

{MODEL_NAME}:这是带有前缀“/models/”的 REST API 调用的服务端点。不要更改目标变量中的“/models/”前缀,只根据您的需要更改{MODEL_NAME}部分

当您在命令窗口中看到以下消息时,您的模型已成功托管。您还可以在 Docker 仪表板中看到一个成功运行的容器。

[evhttp_server.cc : 238] NET_LOG: Entering the event loop …

测试我们的模型

我使用 Postman 来测试我的查询,但是您可以使用任何形式的 API 调用。

[注意:您将无法从浏览器或任何其他主机直接调用您的 REST API,因为 TensorFlow 服务不支持 CORS。然而,有一些方法可以实现从浏览器到您的模型的调用,我将在另一篇文章中介绍。]

您需要一个 POST 查询来测试我们的模型。我们的请求 URL 看起来像:

[http://localhost:8509/v1/models/linear_model:predict](http://localhost:8509/v1/models/linear_model:predict)

同样,一般形式是:

[http://localhost:{LOCAL_PORT}}/v1/models/{MODEL_NAME}:predict](http://localhost:{LOCAL_PORT}}/v1/models/{MODEL_NAME}:predict)

在标题中添加“内容类型”作为“应用程序/json ”,在正文中添加:

{
     "instances": [[
          0
     ]]
}

请确保您的 JSON 键是“instances ”,并且您的值在一个数组中。因为我们的输入是[0],所以我们把它写成[[0]]。

请记住,我们创建了一个模型来预测 y = 2x + 1 ,这意味着对于输入值 0,我们的预测值应该为 1(或接近 1)。

让我们发送我们的查询。响应看起来像:

{
     "predictions": [[
          0.999998748
     ]]
}

对我来说这看起来很像 1。通过进行 POST 查询来摆弄您的模型。

结论

我们能够从头开始创建一个模型,并将其部署在本地服务器上。这是一个很好的方法,可以看看您的模型在真实世界中的工作方式是否和在您的 IDE 中一样。

然而,正如我前面提到的,除了 Postman(或类似的工具),您将无法调用这个模型。如何克服这一点?我将在另一篇文章中讨论这个问题,因为这篇文章已经太长了。

如果您已经到达这里,感谢您的阅读。如果你有任何疑问,建议或意见,请随时评论这篇文章。这是我第一个关于机器学习的博客,我会很高兴地感谢所有的反馈。

服务化和排队论:导出 M/M/1 模型

原文:https://towardsdatascience.com/servitization-and-queueing-theory-deriving-m-m-1-model-589175b23054?source=collection_archive---------19-----------------------

注意到两者的共同点了吗?两个都是队列!图片来源:https://www.flickr.com/photos/psit/5605605412https://www.geograph.org.uk/photo/5831116

服务化是制造企业从销售纯产品转向提供解决方案(服务)的一种现象。 Neely (2013) 简要介绍了各行各业的公司如何采用这种商业模式。

有趣的是,服务化也导致制造企业和服务企业之间的界限变得不那么清晰。事实上,我们可以看到,制造业和服务业的某些方面可以抽象成类似的数学概念。比如,把一条流水线比作一群排队买食物的人。请注意,两者基本上都是队列,并且通常具有相似的特征(吞吐量或卖家服务客户的速度、队列长度或有多少人在等待,等等)。

我最近了解到数学中有一个分支专门研究这个问题,叫做排队论。根据理论,任何队列都可以用这 6 个参数建模: A | B | c | D | E | F 。a 是到达过程,B 是服务者过程,c 是服务者数量,D 是队列容量,E 是群体大小,F 是排队规则。在这篇博文中,我们将关注最简单的队列类型 M|M|1|∞|∞|FIFO 或者通常缩写为 M|M|1

M|M|1 型号

想象一个无限容量的队列( ),也就是说,等待的长度没有限制。假设人口规模也是无限的(∞),即潜在客户的数量是无限的。顾客是在先进先出( FIFO )的基础上得到服务的。让我们假设我们正在运行一条只有一个服务器的生产线( 1 ),例如,想象一辆有一条队列的基本食品卡车。然后,我们可以用速率为λ ( M )的泊松过程对客户到达率进行建模。我们还假设我们的服务时间是指数分布的,因此也可以用速率为μ ( M )的泊松过程建模。

我们把这个过程表示为马尔可夫链。状态(节点)表示队列中有多少物品,而转移率表示接收/服务客户的概率。例如,S2 表示在该州的队列中有 2 个项目。因为只有一台服务器,所以只能一个接一个地顺序处理项目。λ的到达率意味着平均在 1 个时间单位内,将有λ个项目到达队列。μ的服务率意味着平均来说,在 1 个时间单位内,μ个项目将被服务并因此从队列中移除。

M/M/1 排队马尔可夫链

假设到达和服务同步发生,即我们在 h 的同一时间窗内从一个状态移动到另一个状态,马尔可夫转移概率可以这样写。

我们的目标是只根据λ和μ(不考虑初始状态是什么),计算长期处于任何状态 Sn 的概率。

要做到这一点,我们必须首先对 n = 0 的 P(Sn)进行边缘化。我们可以用两种方式边缘化 P(Sn ),要么是相对于先前的状态,要么是相对于随后的状态。请注意,S0 有 1 个前一状态(s 1)和 1 个后一状态(S1)。只有从长远来看,这才是正确的。

经过替换和重新排列,我们得到了 P(S1)和 P(S0)之间的关系。对于其他 n > 0,我们现在对 P(Sn)执行相同的边缘化。在这种情况下,Sn 具有 2 个先前状态(Sn-1,Sn+1)和 2 个后续状态(Sn-1,Sn+1)。

我们现在有了一个关于 P(Sn+1),P(Sn)和 P(Sn-1)的等式。我们可以计算出 n=2 时的这个值。用我们以前得到的结果代替 P(S1)得到下面的等式。

现在我们可以对更高的 n 值做同样的替换和重排,得到如下迭代方程(需要更严格的证明;我们将在本帖中跳过这一点)。

我们快到了!唯一的问题是我们还有一个未知项 P(S0)。好消息是,我们也可以基于λ和μ来表征 P(S0)。为此,我们将利用概率的和性质,即所有状态的概率之和等于 1。因为我们有无限多的可能状态,求和项趋于无穷大。

该等式表明,只有当到达率小于服务率时,和的收敛才成立。直观地说,这意味着只有当我们能够以比客户到达速度更快的速度服务客户时,我们才会有一个正常工作的队列。否则,队列将无限增长。

我们现在可以根据λ和μ来刻画 P(S0)的特征。将该值代入 P(Sn)的迭代方程,得到以下结果。

我们已经实现了最初的目标,即仅根据到达率和服务率来衡量处于任何状态的概率。

那又怎样?

有了这个模型,我们可以回到我们最初的问题,并试图回答它们。举个例子,

假设我们每周三开一辆快餐车。在过去的几个月里,我们已经大致了解了顾客来的频率以及我们能以多快的速度为他们服务。使用我们新学到的排队论知识,我们现在可以估计我们的队列平均有多长。然后,我们可以将这个数字与我们操作的场地大小进行比较,看看是否有足够的空间让人们排队。我们还可以决定我们应该在加快服务时间以减少排队长度方面进行多少投资。

这个用例在数学上等同于计算队列 n 中的预期项目数。

不幸的是,等式中有一个无穷和项。为了找出这相当于什么(再次假设λ < μ), we’ll make use of the derivation of a geometric series sum.

We can now substitute this to the original equation, resulting in an expected value that is characterised based on λ and μ alone.

Let’s return to our food truck example. Suppose 4 customers arrive per hour to our food truck and we have enough capacity to serve 6 of them per hour. Using the above equation, we can calculate the expected number of people in our queue across time.

On average, we expect 2 people to queue in our waiting line. We can calculate also calculate 更多的 KPI如服务器利用率、平均等待时间、平均排队时间都基于λ和μ)。

结论

我们已经看到了排队论是如何帮助我们描述排队等候的特点的。制造业和服务业都可以使用这种数学抽象。在实践中,我们可能希望用更现实的参数来建模我们的队列,例如,我们可以有多个服务器,而不是一个服务器;或者我们可以假设容量有限而不是无限。然后,该模型可以提供关于如何改进排队系统的管理见解。

主要的限制是对到达和服务过程有很强的假设。在这种情况下,我们假设泊松过程,但更好的方法是更加数据驱动,看看哪个分布更适合。请记住,使用参数分布(无论是泊松分布还是其他分布)需要完全理解每个模型假设的潜在前提。

用于时间序列分类的集合注意模型

原文:https://towardsdatascience.com/set-attention-models-for-time-series-classification-c09360a60349?source=collection_archive---------27-----------------------

ICML2020

真实世界时间序列数据的深度学习算法

Fabrizio VerrecchiaUnsplash 上拍摄

作为一名主要处理业务数据(有时也称为“表格数据”)的数据科学家,我总是在寻找数据科学领域的最新发展,以帮助处理更现实的数据。其中一个领域解决了这样一个事实,即业务数据很少是“表格”形式的,而通常本质上是关系型的。我已经在另一篇博文的中讨论了使用关系数据。深度集算法帮助您从不具有矩形形状的数据中学习,但可以表示为表的集合或图形。因此,在今年 7 月参加 ICML 2020 大会时,我特别关注了那些使用深度集合学习的论文。

其中一篇论文是 Max Horn 等人的《时间序列的集合函数》[1]:

[## 为时间序列设置函数

尽管深度神经网络取得了显著的成功,但许多架构通常很难移植到…

arxiv.org](https://arxiv.org/abs/1909.12064)

在我看来,这是会议的最佳文件。如题,这篇论文是关于学习时间序列的集合函数。在继续之前,让我提醒你什么是 set 函数。

设置功能

集合函数是对一组数据的函数,可以包含零到无穷大的元素。集合函数的例子有 count()、min()、max()、sum()、mean()、std()等。在 SQL 中,我们称之为聚合函数。集合中的元素也可以是复杂的,例如,表示一行数据。集合函数不同于机器学习中常见的表格函数。相比之下,表格函数将一行固定数量的变量作为参数。处理潜在大型集合的方法是使用两个辅助函数和一个聚合函数来表示集合函数[2,3]:

来源:https://arxiv.org/abs/1909.12064

函数 h()应用于集合中的单个元素(假设是一行数据),并将集合中的元素映射到一个高维向量空间。聚合函数将一个集合中的所有这样的向量组合成一个向量,从而处理不定数量的元素。然后,一个新的函数 g()将向量映射到最终结果。这里的聚合函数是 mean(),但也可以使用其他聚合函数,例如 sum()。函数 f()和 g()可以被训练为神经网络,并且整个模型在所有可用的集合上被训练。

不规则和错位的时间序列

经典的时间序列分析总是假设测量是以固定的时间间隔进行的,如果进行了几次测量,它们是对齐的。使用插补技术来填补偶然缺失的测量值。

实际上,时间序列经常是不对齐的,测量是以不规则的间隔进行的。电子病历(EMR)和其他类型的医疗数据就是一个很好的例子。看看这张报纸海报上的图表:

来源:https://slides live . com/38928275/set-functions-for-time-series

这四次测量以不同的频率和不规则的时间进行。是的,您仍然可以使用插补,但是因为这里您需要插补大量数据,所以预测的方差会非常高。

主要思想

文献[1]的主要思想是把时间序列看作一个集合。如果你这样做,你可以使用集合函数学习算法,而不必估算任何数据。整个时间序列是一组元组(t,z,m),其中 t 是时间,z 是测量值,m 是模态。在我们的例子中,m 取血压、心率、体温和葡萄糖的值。请注意,时间仍然是一个变量,但是模型失去了下一个度量对上一个度量的显式依赖性。

这种范式的转变类似于由论文引发的变形金刚革命【4】。此外,作为递归神经网络的显式序列建模被表示为集合的序列和使用注意机制的学习所取代。

立正

如果你再看一下文章开头的等式,你会发现集合中的所有元素对结果的贡献是相等的。实际上,情况可能并非如此。例如,与超过 6 小时的平均血压相比,血压的突然变化是败血症发作的更好指标。正如我已经提到的,聚合函数不一定是 sum()或 mean(),事实上可以是任何接受一组向量并返回单个向量的函数。您可以尝试手工制作聚合函数,但是如果神经网络可以学习该函数,岂不是很酷?

同样,受[4]的启发,作者引入了集合注意力作为权重,决定集合中每个元素对整体结果的贡献。

来源:https://arxiv.org/abs/1909.12064

因此,您有一个加权集合函数,而不是普通的集合函数:

来源:https://arxiv.org/abs/1909.12064

权重α(S,s_j)取决于整个集合以及特定的集合元素。这张幻灯片示意性地展示了完整的模型:

来源:https://slides live . com/38928275/set-functions-for-time-series

索引 I 表示几个注意头。索引 j 表示集合中的一个元素。密钥矩阵表示为:

来源:https://arxiv.org/abs/1909.12064

这里 f '(S)是第二个集合函数,它使用 mean 作为聚合函数。这意味着多了两个学习 f '()的神经网络。所得向量与 s_j 连接,并乘以权重矩阵 W。注意,W 的维数不取决于集合中元素的数量,而是由神经网络架构定义。

来源:https://arxiv.org/abs/1909.12064

这里 d 是潜在层的尺寸。查询矩阵还定义了维度:

来源:https://arxiv.org/abs/1909.12064

和[4]一样,权重使用 softmax 定义:

资料来源:https://arxiv.org/abs/1909.12064

完整的神经网络架构图如下:

来源:https://arxiv.org/abs/1909.12064

时间的位置编码

受[4]启发的另一件事是时间的位置编码。

我们这些处理表格数据的人习惯于从日期/时间变量中提取特征。通常我们提取日期/时间成分,比如一天中的小时,一周中的天,等等。然后应用 sin()和 cos()等周期性函数来确保平滑度。当[4]的作者在研究 Transformer 体系结构时,他们决定使用这种技术对单词位置进行编码。这一思想被带到[1]没有太大的变化。时间编码如下:

来源:https://arxiv.org/abs/1909.12064

这里粗体的 t 是最大时标(实际上是一个超参数), k 是整数

来源:https://arxiv.org/abs/1909.12064

您可以使用一个简单的 python 脚本轻松实现这一点。

使用上面的脚本生成的位置编码函数图。

如你所见,时间有几个周期函数,有几个频率值。我相信位置编码是[4]和[1]成功的主要因素之一。然而,当处理实时而不是单词的位置时,编码对时间缩放非常敏感,因为与 NLP 中的位置相反,时间是连续变量。它还添加了额外的超参数来调整模型。虽然它对 NLP 很有效,但没有讨论其他类型的编码对时间序列是否更有效。这让我想起了手动卷积滤波器,尤其是计算机视觉系统。有没有可能增强这种神经网络架构,让它自动学习时间编码,而不是手动设置?也许一维卷积可以解决这个问题。

结论

Set functions 提供了一个关于时间序列数据的新视图,允许将它们视为独立的观测值,这简化了不规则和非对齐测量情况下的数据预处理。注意力机制允许模型学习对结果至关重要的观察结果(从而提高模型的可解释性)。实验研究表明,该算法是有竞争力的最先进的,而更快,更容易解释。所有代码都可以在作者 github repo 中找到。

参考

[1]马克斯·霍恩等人 al,为时间序列设置函数, arXiv:1909.12064

[2]曼齐尔·扎希尔等人。艾尔,深套, arXiv:1703.06114

[3]彼得·巴塔格利亚等人。al,关系归纳偏差、深度学习和图网络, arXiv:1806.01261

[4]阿希什·瓦斯瓦尼等人。艾尔,你所需要的只是关注, arXiv:1706.03762

Set-TSP 的动态规划方法

原文:https://towardsdatascience.com/set-tsp-because-there-is-more-than-one-place-to-get-bread-712fdb5b381?source=collection_archive---------32-----------------------

因为有不止一个地方可以买到面包

旅行推销员问题 (TSP)提出了一个简单的难题:你想要访问一组地方,例如,你在镇上的差事,并且想要以最有效的方式这样做。这个问题已经用无数不同的方法解决了,既有最优也有启发式

你会问,我们今天在这里做什么?嗯,生活的事实是,有不止一个地方可以买到面包,或者意大利面,或者你的差事单上的任何东西。在生活中,很多时候我们想要完成一组任务,而不太关心每项任务是如何完成的。

想象一个星期五的早晨,我想(a)从我所在地区的三家面包店之一买面包,(b)从我所在地区的三家商店之一买蔬菜,(c)在镇中心的两家酒吧之一喝杯啤酒。

既然有人问我,我就分享一下:想知道我是如何制作这些插图的吗?我从 s2map 中拍摄了一张快照,并在稍后使用 Google Slides 添加了这些图像。是的,那是我懒惰的秘密;)

那么,完成这三项任务的最快方法是什么呢?
这正是 Set-TSP (Set -旅行推销员问题)的动机——完成所有任务,每个任务只完成一次,这样每个任务就有几个选项可以完成。

在这篇文章中,我们将使用动态规划 (DP)构建一个解决方案,这将为我们提供一个最优的解决方案,并且在未来我们还将找到一个启发式的解决方案,它可以用于更大的输入,而不会在最优性上损失太多(或者是这样吗???敬请期待一探究竟!).

关于这篇文章后面的完整代码,你可以去 这里

奠定基础

为了解决我们的问题,我们需要决定一种表示输入数据的方式,并从中导出用于计算所需最短路径的距离度量。

在处理地理数据时,正如我们在这里所做的,习惯上使用经纬度坐标来标识位置。令我们沮丧的是,这些是非欧几里得坐标,因此计算简单的欧几里得距离大多是错误的。

声明:在之前的一篇帖子中,我确实使用了欧几里德距离来表示非欧几里德坐标,但是……这是一篇介绍性的帖子,我不想跑题;)

所以——让我们来谈谈房间里的大象吧!我们如何计算距离?

很高兴,这个世界已经为我们搭好了舞台——我们可以使用哈弗辛公式,并从这个得到一些帮助:

现在我们可以正确计算距离,我们可以建立我们的解决方案。

构建 DP 树

构建动态规划(DP)算法需要了解我们希望如何遍历解空间,以及我们希望如何跟踪我们的当前状态。

就我个人而言,我发现直接进入集合-TSP 问题相当令人困惑,因此决定先解决一个更简单的问题——“只是”TSP,没有“集合”。

我现在将描述使用 DP 的 Set-TSP 解决方案的整个管道,但是如果你发现自己有些困惑,就像我一样,我建议首先阅读这个

类似于许多经典的 DP 算法,我们将使用一个字典存储器,其关键字是状态,值是到达该状态的最佳方式的“方向”。更准确地说,该值是一个到键的最短路径中的直接前任。让我们举例说明一下,以便更好地理解这个过程:

这里,关键字([s1,s2,s3,s4],s4,v9)表示已经访问了所有集合的状态,使得 s4 是最后访问的集合,而 v9 是该集合中访问的点。该键的值是(s2,v4,1.5),因为以步骤 v4->v9 结束的路径最短。

代码可能看起来很混乱,而且充满了变量,但是一旦你理解了 DP 的一般方法,并且理解了你想要使用的备忘录的逻辑,它就“只是”另一个 DP 实现。

回溯最短路径

一旦我们到达了树的末端,意味着我们在备忘录中保存的路径是完整的,那么“剩下的一切”就是折回我们的步骤以找到最佳路径。

幸运的是,我们记住了每个部分路径中的最后一个和倒数第二个集合和点!

我们的红色最优路径:[(s1,v3),(s4,v9),(s2,v4),(s3,v6)]

因此,第一步将是查看最终图层,包括所有完整的路径,并选择总成本最低的最后一个集合和点。

从那里,我们可以使用倒数第二个集合和点来追溯我们的步骤。

宝贝,不画出来就不会结束

在我为这篇文章准备的 jupyter 笔记本中,你可以找到一个有用的绘图功能,让你在 geojson.io 上绘制你的解决方案:

在同一个笔记本里,你还可以找到一个输入量大得多的例子。由于集合 TSP 的复杂度在集合数量上是指数,在每个集合中的点的数量上是多项式,所以我们可以得到相当大的输入的最优解:

收场白

当我第一次了解 Set-TSP 时,关于这个问题的结构的一些东西向我尖叫,它应该有一个使用动态编程(DP)的优雅的解决方案。的确,这篇文章中的算法让我相信我的直觉是正确的。

老实说,这个算法对我来说并不容易。因此,我的过程的一部分是首先解决一个类似的,但更简单的问题。我决定先找到 TSP 的 DP 解,然后才把解扩展到 Set-TSP。这对我来说是一个巨大的成功,因为我没有一次绞尽脑汁,而是获得了两次轻松的胜利!而且,两次解决几乎同一个问题的经历,帮助我更好地“铭记”了 DP 技能,给了我“我得到了这个”的定心丸。

所以下次你手头有一个棘手的任务时,试着先解决一个简单的。你很可能会更快地找到解决方案,而且你也会从第二次更好的成功中获得信心💪🏿

希望你喜欢我的旅程,并在下一篇文章中看到,我们将找到一个启发式的解决方案来设置 TSP,并比较结果🤓

这篇文章后面的完整代码你可以去 这里

为分布式机器学习建立一个 Dask 集群

原文:https://towardsdatascience.com/set-up-a-dask-cluster-for-distributed-machine-learning-31f587b1b553?source=collection_archive---------12-----------------------

使用 Python 和 Dask 的分布式机器学习

通过使用 SSH 连接机器来创建 Dask 环境

Pablo Salvador LopezAadarsh Vadakattu 合作撰写

如果你知道 Dask 有什么能力,以及它如何分发你的机器学习过程,那你就来对地方了!本文将解释如何创建一个简单的 SSH 集群,您可以使用它作为实现 Dask 环境的基础,该环境可以分发您的机器学习工作流。

顺便问一下,我们可以用多少种方法来加速 Dask 集群?

Dask 集群可以通过多种方式加速:

  1. 使用 SSH 连接
  2. 在 Hadoop 集群上,本质上是借助 HDFS 和 YARN 的力量运行
  3. 在 Kubernetes 和一堆 Docker 容器的帮助下
  4. 在超级计算机上
  5. 在像 AWS 或 Azure 这样的云环境中

在本文中,我们将展示如何通过使用 SSH 连接构建一个工作的 Dask 测试环境。

这是最好的方法吗?

使用 SSH 连接建立 Dask 集群似乎是最容易的,但是它也是最不稳定、最不安全和最乏味的。这种方法仅用于测试目的,不用于生产中的某个地方。基于您的生产环境,您可以尝试使用 Hadoop、Kubernetes 或云解决方案来实现 Dask,因为它们更有组织性和稳定性。

应该建什么?

Dask 运行在调度器-工作器网络上,调度器分配任务,节点相互通信以完成分配的任务。因此,网络中的每台机器都必须能够相互连接和联系。Dask 有时也会尝试从一个源节点连接到同一个源节点,所以我们应该确保所有机器上的每个连接网关都可用,包括到自身的连接。

在您找到一堆可以用来实现分布式集群的机器之后,

  • 必须设置防火墙规则,使连接成为可能
  • 必须使用 SSH 设置无密码登录
  • 必须在所有机器上建立一个唯一的安装目录,该目录将包含我们的训练/测试数据,并提供给 Dask
  • Python 必须安装在所有要安装相同版本库的机器上。

下面的测试设置是在一堆运行 Red Hat Enterprise Linux 7 (RHEL 7)的机器上实现的。您可以在任何地方开发或部署这种架构,方法是在本地或云中启动一组虚拟机,或者在可通过网络访问的真实机器上启动。

设置防火墙

  • 确保关闭防火墙或允许通过防火墙访问所有其他机器。
  • 如果您想使您的测试设置安全,允许从每台机器到每台机器的访问,包括它自己。假设您正在从任何其他机器上访问 IP 10.10.10.10,执行如下命令。在这里,24 决定了通用的 TCP 端口,8786 是 Dask 通常需要进行通信的端口。通过使用相同的命令并更改端口号,您可以根据需要打开任何其他端口。
firewall-cmd --permanent --zone=public --add-source=10.10.10.10/24
firewall-cmd --permanent --zone=public --add-source=10.10.10.10/8787

如果您的防火墙连接规则被添加,您将看到如下消息。

您可以使用ping命令确认您的连接没有被阻塞。如果您没有通过 ping 收到传输的数据包,则说明您的网络有问题。

您的 ping 应该返回传输的数据包,如上所示。如果没有,您将看到收到 0,这确定您的网络可能有问题。

如果安全性对您的测试设置不重要,您可以禁用防火墙以减少一些麻烦。为此,请在所有计算机上运行此命令。这将关闭您运行的计算机上的防火墙。

systemctl stop firewalld

您可以通过运行以下命令来检查防火墙状态:

systemctl status firewalld

如果您有活动的防火墙,您可以看到状态为活动。

如果您停止了防火墙,防火墙的状态将变为非活动。

设置无密码 SSH

当您的所有机器都可以被其他机器发现后,您需要让它们使用 SSH 连接,以便它们可以通信和传输数据。

通常,登录到一台机器需要一个系统的 IP 和一个认证密码。这种类型的登录可以手动完成,但是如果目标机器请求密码,Dask 不知道如何以及在哪里输入密码。为了克服这个问题,我们可以将计划的集群中所有其他可能的目的地机器作为 SSH 已知主机,使登录安全且无需密码。

如果您以前没有创建过 SSH 密钥,运行如下所示的ssh-keygen命令。如果需要,您可以输入密码,也可以留空。

这将创建一个 SSH 密钥,您可以使用它跨设备进行身份验证,从而使您的登录更加安全且无需密码。

现在运行下面的命令来复制目标机器的 SSH ID。假设是10.1.1.93

ssh-copy-id 10.1.1.93

运行上面的命令可能会显示类似如下的输出:

添加密钥后,您无需输入密码即可从当前机器登录到该机器。

您还可以通过检查~/.ssh/known_hosts文件来确认集群中所有可能的目的地是否都被设置为主机。

在您复制了所有机器的 id 之后,您应该在这个文件中看到所有机器的 id 以及它们的 IP。

确保对计划包含在集群中的每台计算机运行此步骤(包括您可能正在使用的当前计算机的 IP)。如前所述,Dask 有时会尝试连接到自己,但会失败,因为没有 SSH 授权。)

在所有机器上运行这些程序后,您应该能够不使用密码无缝地从一台机器登录到另一台机器。下面的例子显示了两台机器,其中10.1.1.107没有复制 SSH ID,而10.1.1.93在当前工作的机器上复制了它的 ID。

SSH 请求密码,因为它没有找到 id 令牌。您必须在此输入密码才能登录机器。

复制 ID 后的 SSH。在这里,您无需密码即可登录,因为登录是通过您之前复制的 ID 进行身份验证的。

跨集群设置挂载目录

现在,您可以设置一个地方,让 Dask 可以访问您的数据。您可以在一个名为 SSHFS 的应用程序的帮助下完成这项工作,该应用程序会在您在任何机器上指定的目录下创建挂载点。当您在目标计算机上指定装载源时,这会将数据从源传输到目标,并从目标传输到源,以保持该特定目录中的所有文件和文件夹在计算机之间同步。这种方法的好处是—它从两个位置拷贝和同步数据,而不仅仅是在创建装载点源的位置。

如果您将要处理的数据放在机器上不同的目录路径中,Dask 有时会感到困惑。因此,请确保选择一个跨机器通用的特定目录。简单的例子可以是/tmp/daskdata/

要将该目录指定为挂载点,

  • 在所有机器上创建公共目录
  • 使用以下命令在所有机器上安装 SSHFS(如果您在 RHEL 上)
wget [https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-12.noarch.rpm](https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-12.noarch.rpm)yum install fuse-sshfs
  • 登录到所有机器,并在该目录下创建一个挂载点,将其指向源机器的目录。假设您的源机器是10.10.10.10,输入如下命令:
sshfs 10.10.10.10:/tmp/daskdata /tmp/daskdata

上面的命令假设您已经登录到一台机器,并且您正在将这台机器上的/tmp/daskdata/指向10.10.10.10上的/tmp/daskdata/,这可能是源。

正确实现挂载点后,通过在任何机器的挂载目录中创建一个文件来确保它正在运行。您可以使用touch dummy轻松创建一个测试文件,它会创建一个名为“dummy”的空文件。在任何一个位置创建这个文件都必须将文件复制到所有位置,这意味着它应该可以在所有机器的/tmp/daskdata/目录中找到。

在集群中匹配 Python 库的版本

最后,您必须确保您需要的所有 Python 库都在所有集群上以相同的版本运行。为此,

  • 尝试使用调度器在本地运行和调试一个简单的 Dask 分布式程序。如果这行得通,您就可以确定 Dask 需要运行的特定库版本集。通常,这一步会失败,因为 Dask 需要安装其他版本的库。根据这个程序抛出的错误获取必要的库,并尝试安装它们。
from dask.distributed import Client
import dask# Import a sample dataset
df = dask.datasets.timeseries()# Connect to distributed cluster. To run locally, pass no arguments # in the Client function.
client = Client()# This now runs on the distributed system
df.groupby('name').x.mean().compute()
  • 这里有一个链接指向 Dask 可能需要的依赖项,以及支持的最低版本。检查这个,确保你已经满足所有要求。
  • 有了库的版本后,您可以使用pip freeze命令收集所有已安装的版本,并安装所有这些需求,如下所示:
pip freeze > requirements.txt #on a machine where all libraries are #installedpip install -r requirements.txt #on another machine where all #libraries should be installed

现在,您可以将数据放入挂载的文件夹中,并编写 Dask 应用程序了!

为 Dask 构建 SSH 集群的利弊是什么?

优点:

  • 这是一个完全从零开始构建的集群,可以在不安装 HDFS 的情况下运行,这可能很繁琐。如果您有一个包含许多机器的小型集群,可以使用这种方式快速测试 Dask。

缺点:

  • 挂载点需要精确地位于所有机器上的相同位置。HDFS 在这里大获全胜,因为如果以这种方式实现,Dask 只需要知道文件在 HDFS 的什么地方。
  • 大量文件会破坏每台机器上的磁盘,并且会破坏网络上的 SSHFS 连接。
  • SSHFS 挂载可能很难跟踪,并且 SSHFS 应用程序在跟踪正在运行的挂载点方面做得不好。

请继续关注有效运行 Dask 的其他方式,包括通过 HDFS 和 YARN 设置的,使用 Kubernetes 设置的和在 Azure Cloud 设置的

非常感谢你的阅读!既然您已经设置了集群,那么您可以创建并运行 Dask 程序,并在 Dask 仪表板中查看所有运行统计数据!

使用 Ubuntu 20.04 设置用于机器学习的个人 GPU 服务器

原文:https://towardsdatascience.com/set-up-of-a-personal-gpu-server-for-machine-learning-with-ubuntu-20-04-100e787105ad?source=collection_archive---------2-----------------------

TensorFlowGPU,JupyterLab,CUDA,cuDNN,端口转发,DNS 配置,SSHFS,bash

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片。奶昔是可选的 GPU 设置。

在你的 ML 工作流程中使用 GPU 的好处已经在前面讨论过了。本文的目标是总结为个人 ML 项目设置机器的步骤。我从 2017 年开始遵循一个类似的指南,发现从那时起到 2020 年,很多步骤都变了——变得更好。此外,根据我在攻读博士学位期间使用 DAQ 系统的经验,我将建议一些程序,使您的远程工作流程更简单、更安全。

到本文结束时,您将能够从您的笔记本电脑启动运行在 GPU 主机上的远程 JupyterLab 会话。此外,您将能够从任何地方远程打开机器,并将它的文件系统直接安装到您的笔记本电脑上。

大纲:

  1. 安装和设置 Ubuntu 20.04 (独立/双引导/WLS2)
  2. 设置远程访问( ssh 、WOL、DNS 配置、端口转发)
  3. 照顾 NVIDIA 驱动程序和库(CUDA,cuDNN)
  4. 为 ML 创建 Python 环境
  5. 易用工具:用 SSHFS 挂载远程目录,将一些常用命令设置为 bash 别名

要求:

  1. 您通常在其上工作的笔记本电脑/台式机。我用的是运行 macOS 10.15 的 MacBook Pro 2015。

  2. 一台带有 GPU 的机器,例如,这可以是你当前的游戏 PC。你不需要花费预算在昂贵的 GPU 上来开始训练你的 DNNs!我的硬件目前比较一般:
    CPU: AMD 锐龙 5 2600X (3.6 GHz,六核)
    GPU: 英伟达 GTX 1660(6GB VRAM)
    RAM:16gb(DDR 4 3200 MHz)
    存储: 512 GB NVMe M.2 (SSD)、512 GB HDD

  3. 对路由器设置的管理员级访问权限(可选)

  4. 熟悉 Linux 和终端

1.安装和设置 Ubuntu 20.04

在我和其他人看来,Windows 操作系统都不适合做任何 ML 开发或网络工作。因此,我们将为此目的设置一个 Linux 操作系统。Ubuntu Desktop 20.04 ( 在这里下载)是一个理想的选择,因为许多功能都是现成的,与其他 Linux 发行版相比,它允许我们节省设置时间。您有三种选择:

  1. 只安装 Ubuntu
  2. 双启动 Ubuntu 和现有的 Windows 操作系统。此处按照 i** 指令 (推荐选项)。**
  3. 使用 WSL2 (Windows 子系统 for Linux);这就是这里讨论的。警告:我从来没有测试过这个选项(这里你自己看吧!).

我推荐选项#2 ,保留对窗口的访问(例如,出于游戏相关的目的)。确保在安装期间将您的计算机连接到互联网,以获取最新的更新和驱动程序。

安装后,登录并更新和安装必要的软件包,例如

sudo apt-get update &&
sudo apt-get -y upgrade &&
sudo apt-get -y install build-essential gcc g++ make binutils &&
sudo apt-get -y install software-properties-common git &&
sudo apt-get install build-essential cmake git pkg-config

2.设置远程访问

在本节中,我们将设置一种安全的远程登录机器的方式。还讨论了从任何网络访问 GPU 机器的选项。

现在,登录 Ubuntu,打开终端并安装 ssh-server:

sudo apt update &&
sudo apt install openssh-server

之后,验证 ssh-server 安装是否正确

sudo systemctl status ssh

打开防火墙

sudo ufw allow ssh

通过从您的笔记本电脑 (假设与您的 GPU 机器连接到同一个网络)运行 来测试您的 ssh 连接

ssh **user**@<**local-ip-address**>

其中 用户 是你的 Ubuntu 用户名,而你在 Ubuntu 上的本地 IP 地址(如 172.148.0.14)可以用ip add找到,产生(如)

*link/ether* ***b3:21:88:6k:17:24*** *brd ff:ff:ff:ff:ff:ff
inet* ***172.148.0.14****/32 scope global noprefixroute* ***enp7s3***

记下您的 MAC 地址(如 b3:21:88:6k:17:24 )和网卡名称(如 enp7s3 ),以备后用。

接下来,按照此处 描述的 设置无密码登录的 ssh 密钥。之后,假设你只想从这台笔记本电脑登录到你的机器,禁用使用密码登录的选项。这将只允许来自已经交换了 ssh-key 对的设备的 ssh 连接,提高了安全性。在 Ubuntu 上编辑/etc/ssh/sshd_config(使用 sudo 权限)以添加

#only ssh-key logins 
PermitRootLogin no
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
AllowUsers user
PubkeyAuthentication yes# keep ssh connection alive 
ClientAliveInterval 60
TCPKeepAlive yes
ClientAliveCountMax 10000

不要忘记重新启动 ssh-service,让它通过

sudo restart ssh

域名服务器(Domain Name Server)

如果您想从家庭网络之外通过 ssh 连接到您的计算机,您需要建立一个永久的 DNS“主机名”,它独立于您的计算机的全局 IP 地址,您的 ISP 可以随时更改该地址。我个人使用过 no-IP 的免费服务(链接此处,从 Ubuntu 的浏览器 )开始使用“立即创建你的免费主机名”);存在替代 DNS 服务,如 FreeDNS、Dynu 等。请创造性地使用您的主机名;我真不敢相信 mlgpu.ddns.net 还没被录取。这个主机名将在本文中作为一个例子。****

之后,按照此处描述的安装动态更新客户端(DUC)。这可以确保当您的全局 IP 发生变化时,它会重新链接到您的主机名(即mlgpu.ddns.net)。为了确保每次使用 Ubuntu 都能启动 DUC,添加一个新的 cronjobsudo crontab -e(即在文件末尾添加这一行)

@reboot su -l **user** && sudo noip2

重启你的机器。

端口转发

默认情况下,ssh 使用端口 22 进行连接。我们需要通过路由器打开这个端口(TCP 和 UDP 协议),以便能够从外部网络 ssh 到机器(您仍然希望从咖啡店提交那些 GPU 密集型作业,对吗?).此设置通常位于“高级/安全”选项卡下。下面是我的路由器设置的截图

UDP 和 TCP 协议都允许通过 Ubuntu 网卡的端口 22。

可选:在挖掘你的路由器设置时,将你的 Ubuntu 的网卡 MAC 地址本地 IP** 添加到保留列表(“添加保留规则”),并将你的路由器设置保存到一个文件中(以防你日后需要重新加载)。**

最后,在你的笔记本电脑,编辑~/.ssh/config用你的 Ubuntu 用户名替换用户,用你的 DNS 主机名替换主机名****

# keep ssh connection alive
TCPKeepAlive yes
ServerAliveInterval 60# assign a 'shortcut' for hostname and enable graphical display over ssh (X11) 
Host                 **mlgpu**
HostName             **mlgpu.ddns.net**
GSSAPIAuthentication yes
User                 **user**
ForwardX11Trusted         yes
ForwardX11                yes
GSSAPIDelegateCredentials yes

这将允许您快速 ssh 到您的机器,并测试 DNS 和端口转发正在工作

ssh mlgpu

这应该不会要求您输入密码,您现在可以从任何网络 ssh 到您的 GPU 机器!

局域网唤醒

想象一个场景,你正在参加一个会议(在 2020 年之前,这些会议在远离你家的地方举行——我知道这很奇怪!)并且你想在你的 GPU 机器上训练你的 DNN。但是等等,你在离开家之前把它关掉了——哦,天哪!

这就是 沃尔和 的神奇之处!

在 Ubuntu 上,编辑/etc/systemd/system/wol@.service

[Unit]
Description=Wake-on-LAN for %i
Requires=network.target
After=network.target[Service]
ExecStart=/sbin/ethtool -s %i wol g
Type=oneshot[Install]
WantedBy=multi-user.target

之后,通过以下方式启用 WOL 服务

sudo systemctl enable wol@enp7s3 && 
systemctl is-enabled wol@np7s3

这将返回“enabled”; enp7s3 是用ip add命令返回的网卡名称。最后,检查您的 BIOS 设置“wake-on-LAN”= enabled。

现在,在你的笔记本电脑上,通过

brew install wakeonlan

要测试 WOL 是否正常工作,请关闭 Ubuntu,并使用您的 DNS 主机名(或 IP 地址)和 MAC 地址从您的笔记本电脑发出以下命令

wakeonlan -i **mlgpu.ddns.net** -p 22 **b3:21:88:6k:17:24**

这将唤醒你的 GPU 机器从睡眠或关机状态(当然,确保它仍然连接到电源!).如果你选择了双引导选项,并且 Ubuntu 不是引导菜单中的第一个操作系统,GRUB 调整它。

就是这样:从你的 GPU 机器上拔下你的显示器、键盘和鼠标,从这里我们将从你的笔记本电脑上运行的远程 ssh 会话中发出所有命令——太棒了!

3.管理 NVIDIA 驱动程序和库

更多好消息在前方。Ubuntu 20.04 应该会自动为你安装 Nvidia 驱动(而不是新出的那些)。让我们用nvidia-smi来验证一下

确认检测到您的 GPU 后,使用正确数量的 VRAM,记下驱动程序和 CUDA 版本。

这不是最新版本的驱动程序。然而,我们可能想让他们从标准的 Ubuntu 库安装 CUDA 和 cuDNN。

库达

只需安装 CUDA

sudo apt update &&
sudo apt install nvidia-cuda-toolkit

nvcc --version验证

CUDA toolkit (v10.1)是从 Ubuntu 库获得的。

最后,使用这里的文件构建您的第一个 CUDA“Hello World”示例

nvcc -o hello hello.cu &&
./hello

“最大误差:0.000000”意味着您的 CUDA 库工作正常!

cuDNN

最后,为 CUDA 10.1 (或为您从nvcc --version发布的 CUDA 版本)下载cud nn v 7 . 6 . 5(2019 年 11 月 5 日)。你需要注册一个 NVIDIA 开发者计划的免费帐户来下载 cuDNN。

使用以下命令从解压缩的 tarball 中复制库:

sudo cp cuda/include/cudnn.h /usr/lib/cuda/include/ &&
sudo cp cuda/lib64/libcudnn* /usr/lib/cuda/lib64/ &&
sudo chmod a+r /usr/lib/cuda/include/cudnn.h  /usr/lib/cuda/lib64/libcudnn*

并将库导出到$LD_LIBRARY_PATH

echo 'export LD_LIBRARY_PATH=/usr/lib/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc &&
echo 'export LD_LIBRARY_PATH=/usr/lib/cuda/include:$LD_LIBRARY_PATH' >> ~/.bashrc &&
source ~/.bashrc

任务完成了。

4.为 ML 创建 Python 环境

在 Linux 和 macOS 上,我个人的偏好是使用 pip 而不是 conda 来管理 Python 包和环境。下面是设置 ML Python3 环境的说明:

首先,获取最新的 Python3

sudo apt update &&
sudo apt install python3-pip python3-dev

然后,升级 pip 并安装环境管理器

sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv

接下来,我们将为基于 GPU 的项目创建一个新目录

mkdir ~/gpu_ml &&
cd ~/gpu_ml

并在那里实例化一个新的 Python 环境

virtualenv gpu_ml_env

这将允许我们直接在那个环境中安装软件包,而不是“全局”安装。该环境需要用以下命令激活(每次登录)

source ~/gpu_ml/bin/activate

你应该在你的终端里看到(gpu_ml_env)。现在,让我们在那个环境中安装 Python 包(在那个环境中 pip == pip3)

pip install jupyterlab &&
pip install tensorflow &&
pip install tensorflow-gpu

您需要的任何其他 Python 包都可以类似地安装。

5.易用的工具

尝试

我推荐你在 Ubuntu 的~/.bash_aliases中添加一些命令。他们会在每次登录时激活gpu_ml环境,以及添加一些有帮助的“终端快捷方式”(人生苦短,不能键入‘jupyter lab’而不是‘jlab’,对!?).命令如下(替代链接)

****在您的笔记本电脑上,您可能希望将这些行添加到您的~/.profile, 中,用您的 DNS 主机名(或 IP 地址)替换 ML,并使用步骤#2 中的 MAC 地址。这些命令如下(替代链接)

SSHFS

从这里安装 macOS 的 FUSE,调整下面的脚本,其中remotedir="user@$ML:/home/user/",和mountdir="/Users/user/Documents/Ubuntu_mount"是你的 macOS 上的目录,Ubuntu 上的文件将被挂载到这个目录。脚本如下(备选链接)

使用运行脚本

. ./mount.sh

在你的 macOS 上导航到/Users/user/Documents/Ubuntu_mount(或者简单地输入cd_ML)来查看作为“本地文件”的 Ubuntu 文件。你现在可以在你的笔记本电脑上用你最喜欢的编辑器打开和编辑远程 Ubuntu 文件,等等——太棒了!

让我们做这个设置的最后测试(手指交叉!).从您的笔记本电脑上****

sg

在我们的“bash shortcuts”中,它代表ssh -L 8899:localhost:8899 mlgpu.ddns.net。这应该会在端口 8899 上打开一个 ssh 隧道,并从该会话类型登录到 Ubuntu

jlab

哪个是jupyter lab --port=8899的 bash 快捷键?

现在,在笔记本电脑上打开您最喜欢的网络浏览器,导航至[http://localhost:8899/lab](http://localhost:8899/lab)。第一次,您需要将令牌从终端粘贴到浏览器中(例如The Jupyter Notebook is running at:http://localhost:8899/?token=**583049XXYZ…**)

在 JupyterLab 中,检查我们确实是从 Linux 运行这台笔记本

import platform
platform.system()

张量流检测 GPU

import tensorflow as tf
tf.config.list_physical_devices(‘GPU’)

我们通过笔记本电脑在远程 GPU 服务器上运行 JupyterLab 笔记本。不太令人兴奋的输出#2 实际上是一个好消息,TensorFlow 检测到了我们的 GPU。

从这里开始,你就可以实施你的 DNN 培训等。使用图形处理器。如果您遵循了第 1 节到第 5 节中的所有步骤,那么您的工作流程相当简单:

1.用sg
2 打开一个到你的 GPU 服务器的 ssh 隧道。用jlab
3 在 GPU 服务器上启动 JupyterLab。在笔记本电脑上打开网络浏览器,并转至[http://localhost:8899/lab](http://localhost:8899/lab)
4。快乐训练——真正的工作从这里开始!

编后记

我希望这篇文章对帮助你设置远程 GPU 服务器以满足你的 ML 需求有所帮助。如果您发现本文中的过程有任何改进,请告诉我,我会尽我所能在这里添加它们。

在 R: Grid search 与 auto.arima()中设置 ARIMA 模型参数

原文:https://towardsdatascience.com/setting-arima-model-parameters-in-r-grid-search-vs-auto-arima-19055aacafdf?source=collection_archive---------22-----------------------

让最佳模型适合您的时间序列数据。

概观

表示和预测时间序列数据的最流行的方法之一是通过自回归综合移动平均(ARIMA)模型。这些模型由三个参数定义:

  • p :滞后阶数(包括滞后观测数)
  • d :平稳性所需的差分程度(数据被差分的次数)
  • q :均线的顺序

如果你是 ARIMA 模特界的新手,有很多很棒的指导网页和分步指南,比如来自 otexts.com 的和来自 oracle.com 的,它们给出了更全面的概述。

然而,这些指南中的绝大多数都建议使用 auto.arima()函数或手动使用 ACF 和 PACF 图来设置 p、d 和 q 参数。作为一个经常使用 ARIMA 模型的人,我觉得我仍然需要一个更好的选择。auto.arima()向我推荐的模型通常具有较高的 AIC 值(一种用于比较模型的方法,最好的模型通常是 AIC 最低的模型)和显著的滞后,这表明模型拟合度较差。虽然我可以通过手动更改参数来实现较低的 AIC 值并消除显著的滞后,但这个过程感觉有些武断,我从来没有信心为我的数据真正选择了最好的模型。

我最终开始使用网格搜索来帮助我选择参数(借用本指南中的一些代码)。虽然对数据进行探索性分析、测试假设和批判性思考 ACF 和 PACF 图总是很重要,但我发现有一个数据驱动的地方来开始我的参数选择非常有用。下面我将通过示例代码和输出来比较 auto.arima()和 grid 搜索方法。

代码和输出比较

首先,您需要加载 tidyverse 和 tseries 包:

library('tidyverse')
library('tseries')
library('forecast')

还需要使用您的训练数据创建移动平均对象:

training_data$hits_ma = ma(training_data$seattle_hits, order = 7)hits_ma = ts(na.omit(training_data$hits_ma), frequency = 52)

auto.arima()

创建和查看 auto.arima()对象非常简单:

auto_1 = auto.arima(hits_ma, seasonal = TRUE)
auto_1

使用 auto.arima()选择的参数为( 0,1,0 ) ,该模型的关联 AIC 为 234.99。寻找 ACF 和 PACF 图中的显著滞后也很重要:

tsdisplay(residuals(auto_1), lag.max = 45, main = '(0,1,0) Model Residuals')

显著的滞后延伸到蓝色虚线之外,表明模型拟合不佳。两个图在 7 处显示出显著的滞后,ACF 图在 14 处具有额外的显著滞后。

网格搜索

首先,您必须指出您想要在网格搜索中测试哪些参数。鉴于这些值的显著滞后,我决定考虑 0 到 7(p 和 d)和 0 到 14(q)之间的所有参数。最终结果是一个名为“orderdf”的数据帧,包含所有可能的参数组合:

order_list = list(seq(0, 7),
                   seq(0, 7),
                   seq(0, 14)) %>%
    cross() %>%
    map(lift(c))orderdf = tibble("order" = order_list)

接下来,绘制该数据帧,确定 AIC 最低的型号:

models_df = orderdf %>%
    mutate(models = map(order, ~possibly(arima, otherwise = NULL)(x = hits_ma, order = .x))) %>% 
    filter(models != 'NULL') %>% 
    mutate(aic = map_dbl(models, "aic"))best_model = models_df %>%
    filter(aic == min(models_df$aic, na.rm = TRUE))

我已经将具有最低 AIC 的模型提取为“best_model ”,以便我稍后可以使用该对象,但是您也可以通过最低 AIC 对数据进行排序,以便探索最佳的几个选项。

查看“最佳模型”对象会显示网格搜索方法选择的参数:

网格搜索已经确定( 7,1,0 )为最佳参数,并且与该模型相关联的 AIC 208.89 远低于来自 auto.arima()方法的 234.99。

此外,在 ACF 或 PACF 图中不再出现任何显著的滞后,并且残差更小。这个模型似乎比使用 auto.arima()生成的模型更适合我的数据。

与使用 auto.arima()函数或手动选择相比,我一直使用网格搜索获得更好的结果,我强烈建议在将 arima 模型拟合到您的数据时使用这种方法。

为阿帕奇·卡夫卡设定场景

原文:https://towardsdatascience.com/setting-the-scene-for-apache-kafka-f4c051f08ecd?source=collection_archive---------72-----------------------

此高级事件流平台的简介和关键概念解释。

(图片来自 Photogenica Sp。授权给 Wojciech Nowak)

简介

据说卡夫卡是一个信息系统。许多人认为它是将消息从一个地方移动到另一个地方的消息总线。这当然是真的,但事实上远不止如此。

Kafka 是一个开源的分布式事件流平台,可以处理整个系统中的所有数据和所有事件。这是一个可以构建实时应用程序的平台,它可以通过事件的力量将不同的系统集成在一起。

它以容错、持久的方式传输记录,提供背压、集成点,并将源系统与接收系统分离。这些特性与灵活的架构相结合,使 Kafka 成为保证高性能和低延迟的强大工具。

Kafka 是基于发布-订阅模式构建的,这种模式使应用程序能够向多个感兴趣的消费者异步发布消息,而无需将发送者与接收者耦合起来。Kafka 是作为一个集群在一个或多个服务器上运行的,这使得满足 Kafka 的创造者给出的保证变得容易。

卡夫卡建筑的这种(某种)正式/普遍的概念可能看起来势不可挡。因此,卡夫卡的核心概念已在下一章介绍。

核心理念

过去,信息存储在数据库中。这种方法使得开发人员从事物的角度来理解编程(例如,票、卡车、照相机)。每一件事物都有它自己的状态,并存储在数据库中。

最近,一些人提出用事件来理解编程。每个事件都有其状态(就像存储在 DB 中的“事情”),但也有对发生的事情的描述和“事情”发生的时间指示。

将事件存储在数据库中似乎是过去和现在的一个很好的调和,然而这有点不方便。取而代之的是被称为“日志”的结构。一旦事件发生,就写入日志。这意味着日志是事件有序序列。

日志很容易思考。它们也很容易大规模构建,这在历史上对数据库来说并不完全正确。Apache Kafka 是一个用于管理这些日志的系统(或平台),具有一系列高级功能,其中一部分已经提到过。

在过去,当数据库统治编程世界时,构建一个使用单个数据库的巨大应用程序是非常流行的。出于许多原因,这种方法是合理且常见的。然而,随着时间的推移,这些应用程序的复杂性也在增加。他们变得难以思考,难以理解,最终难以改变。

目前,有一种趋势是编写大量的小程序,每一个程序都小到足以思考、改变和进化。这些程序可以通过面向日志的代理相互通信。

过去与现在(作者图片)

每个服务都可以使用给定日志中的一条消息,执行一些计算或处理一条消息,并将结果生成一个日志(或数据库)。输出可以持久地(甚至永久地)记录在那里,用于系统中的其他应用。

现在你应该对卡夫卡背后的关键概念有了一个不错的想法。此外,你不仅应该真正理解 kafka 是什么,还应该真正理解 kafka 倾向于提出的构建软件的方法。

消息,话题&分区

您已经知道 kafka 有助于在源系统和接收系统之间移动数据。让我们深入了解阿帕奇卡夫卡的一些要点。

一个单独的数据片段被称为消息。当信息被发送时,卡夫卡对其进行索引,并将其放入适当的 T4 主题 T5。

主题是特定的数据流(你可以把它们想象成 RDBMS 中的一个表,但是没有关系和约束)。每个主题由其名称标识,并被分成个分区。每个分区都有标识号。这些数字从 0 开始,一直到 n-1,其中 n 是给定主题内的分区数量。

主题剖析(图片由作者提供)

分区是有序且不可变的消息序列。每个分区独立于所有其他分区,这意味着在一个主题内创建的分区之间没有顺序。当需要平衡负载时,它们也可以作为一个并行单元工作。分区中的每条消息都有一个称为 offset 的顺序 id 号,它唯一地标识分区内的每条消息。

深入了解分区(图片由作者提供)

总结

现在,当你知道卡夫卡是什么,它是如何工作的,幕后是什么,你能做的最好的事情就是在实践中使用这些知识。此外,了解了一些关键定义,如消息主题分区偏移,您可以了解 kafka 更高级的方面,如生产者、消费者、交付语义或 kafka 集群的内部。

本文附有一些可能有助于你探索卡夫卡的资料。如果你想了解更多关于卡夫卡的知识,它的文档是最好的地方。当你想获得更详细的信息时,《卡夫卡——权威指南》应该能满足你的需求。最后,如果你的目标是找到更多关于日志概念的第三个位置——“我心日志:事件数据、流处理和数据集成”将是最好的知识来源。

继续前进,祝你好运!

WN。

来源

[1]阿帕奇卡夫卡 2.3 文档【https://kafka.apache.org/documentation/

[2]卡夫卡:权威指南|尼哈·纳克赫德、格温·沙皮拉、托德·帕利诺|奥莱利媒体公司| 2017 年 11 月 1 日

[3] I Heart Logs:事件数据、流处理和数据集成| Jay Kreps | O'Reilly Media,Inc . | 2014 年 9 月 23 日

使用 LibTorch 1.6 在 Visual Studio 2019 中设置 C++项目

原文:https://towardsdatascience.com/setting-up-a-c-project-in-visual-studio-2019-with-libtorch-1-6-ad8a0e49e82c?source=collection_archive---------8-----------------------

关于如何使用 python 在 PyTorch 中训练模型,如何使用 flask 或者 Amazon SageMaker 部署模型等等的教程数不胜数。然而,关于如何在 C++中工作的资源是有限的,对于 Visual Studio 项目设置来说更是如此。当你想在现实世界的应用程序中使用你的模型时,速度是你关心的问题,并且由于隐私/安全的考虑,你不想把模型存储在云上,那么你需要求助于我们的老朋友 C++。

Pytorch 现在对 C++有了很好的支持,从 v1.3.0 开始就有了。他们有很好的关于如何使用 C++前端的教程,可以在这里找到:https://pytorch.org/tutorials/advanced/cpp_frontend.html

他们利用 cmake 来构建他们的应用程序,并且没有针对广泛用于 C++开发的 Visual Studio 的官方文档。在本教程中,我将解释如何在最新的 Visual Studio 2019 版本上以发布和调试模式设置 torchlib 项目。

第一步

从这个链接下载安装 Visual Studio 2019 社区版。安装时选择“使用 C++进行桌面开发”,这将安装所有必需的组件。

第二步

你必须从 PyTorch 下载页面下载 LibTorch 压缩文件。我选择了不支持 Cuda 的 Windows 版本。如果您有 GPU,可以选择安装在您机器上的 Cuda 版本。下载链接出现在“运行此命令”行中。我已经把 CPU 版本的贴在这里了。

您必须解压缩这两个文件,然后有选择地移动到存储库文件夹。

来源:https://pytorch.org/get-started/locally/

第三步

先说 Visual Studio 中的 C++项目。创建新项目

来源:作者

第四步

项目设置中需要为项目正常工作而设置的设置很少。文件夹结构如下。

来源:作者

我们从 C/C++设置下的附加包含目录开始。请注意,您可以用提取 LibTorch 库的绝对路径来替换它们。您需要添加以下两个条目:

发布配置:

  • $(项目目录)......\ lib torch-win-shared-with-deps-1 . 6 . 0+CPU \ lib torch \ include
  • $(项目目录)......\ lib torch-win-shared-with-deps-1 . 6 . 0+CPU \ lib torch \ include \ torch \ CSRC \ API \ include

调试配置:

  • $(project dir)……\ lib torch-win-shared-with-deps-debug-1 . 6 . 0+CPU \ lib torch \ include
  • $(project dir)……\ lib torch-win-shared-with-deps-debug-1 . 6 . 0+CPU \ lib torch \ include \ torch \ CSRC \ API \ include

$(ProjectDir)是一个扩展到项目目录路径的 visual studio 宏。我们返回三个目录以获得 LibTorch 文件夹,然后指定相对路径。

来源:作者

接下来,我们将 C/C++ →语言→一致性模式下的一致性模式设置设置为 No。或者选择所有配置并更改此设置。

来源:作者

接下来,是链接器设置。我们从 General 选项卡下的附加库目录开始。

发布配置:

  • $(project dir)……\ lib torch-win-shared-with-deps-1 . 6 . 0+CPU \ lib torch \ lib

调试配置:

  • $(project dir)……\ lib torch-win-shared-with-deps-debug-1 . 6 . 0+CPU \ lib torch \ lib

来源:作者

接下来是输入选项卡。我们需要在这里指定附加的依赖项。

来源:作者

最后,我们需要将 DLL 文件复制到项目中。您可以手动执行此操作,或者将这些 xcopy 命令添加到构建事件→后期构建事件→命令行中。我已经编写了复制所有 dll 的命令。但是,您可以只选择和复制您需要的那些。

xcopy $(ProjectDir)..\..\..\libtorch-win-shared-with-deps-1.6.0+cpu\libtorch\lib\*.dll $(SolutionDir)$(Platform)\$(Configuration)\ /c /y

来源:作者

这就完成了在 Visual Studio 2019 中设置您的 LibTorch 1.6 项目。

最后,为了测试您的项目是否有效,让我们添加一个来自 PyTorch repo examples for c++的示例项目

你必须从这个链接下载 MNIST 数据集。请下载所有四个文件,并将它们解压缩到之前结构中显示的数据文件夹中。只要确保提取工具没有用点替换其中一个连字符,因为那会导致代码抛出异常。我已经在这个资源库中提供了解决方案文件和代码:https://github . com/msminhas 93/lib torch-Mn ist-visual-studio/tree/main/learning lib torch。输出应该如下所示:

希望这有用。欢迎您的建议、反馈和评论。

参考

[1]https://medium . com/@ boontongbuasirilai/building-py torch-c-integration-lib torch-with-ms-visual-studio-2017-44281 f 9921 ea

[2]https://github.com/pytorch/examples/tree/master/cpp/mnist

http://yann.lecun.com/exdb/mnist/

[4]https://github . com/py torch/py torch/issues/31611 # issue comment-594383154

使用 dbt 云和雪花设置配置项

原文:https://towardsdatascience.com/setting-up-a-ci-using-dbt-cloud-and-snowflake-f79eecbb98ae?source=collection_archive---------27-----------------------

融合到大师,晚上睡觉

照片由 Kian LemUnsplash 上拍摄

HousingAnywhere ,我们正在使用 dbt 和雪花对我们的数据进行建模,以便为我们的业务分析师和数据科学家提供有意义的视图和物化。我们的数据仓库充满了来自各种不同来源的原始结构化数据,其中大部分是通过 Stitch 复制的;一个简单且可扩展的即插即用的托管 ETL 工具。其他人需要更多的个人接触,并使用气流与临时定期任务相结合。在这两种情况下,从这些来源提取有意义的见解可能会令人沮丧,因为普遍存在肮脏、不一致和/或存储在过度设计的结构中的数据,这些结构在设计时没有考虑到易于访问和信息提取。

HousingAnywhere 的 ETL 架构的简化表示

dbt 本身是一个命令行工具,允许数据工程师高效地转换他们数据仓库中的数据。当需要更复杂的逻辑或访问关于作业执行或目标模式/表的信息时,它使用用 Jinja 模板丰富的 SQL。数据仓库被用作一个数据源,数据从这个数据源被转换并推回到同一个仓库中,尽管是在不同的位置。dbt 的结果通常更容易理解和维护,通常由可能来自不同数据源的表的多个连接组成。BI 工具(如 Mode、Looker 等)通常只能看到这些结果表,而不是原始的原始数据源。

dbt 的结果通常更容易理解和维护,通常由可能来自不同数据源的表的多个连接组成。

举一个例子:假设有一个表,包含关于一个属性的各种信息,用纬度和经度来描述它的位置。查询这种数据不容易。我们使用 dbt 创建了一个模型,该模型添加了一个“城市”列,通过计算从酒店位置到我们业务感兴趣的城市的 haversine 距离来检索。计算这些距离,并将最近的城市分配给该物业,以用于报告目的。业务分析师可以简单地查询第二个表,而不必担心幕后复杂的逻辑。

dbt 是分布在 pypi 上的 Python 模块,可以部署在任何运行 Python 的机器上。也就是说,使用 dbt Cloud 肯定更方便,它允许您免费进行高效的 dbt 部署(当然,最初是随增长付费的模式)。dbt Cloud 还为核心产品添加了许多有趣的功能,用户友好的 web 界面使其成为在生产环境中实现 dbt 的最佳方式。由于与 Github 的无缝集成,所有的模型和配置都可以使用 git 进行代码版本化,开发过程可以像任何其他经典软件工程项目一样进行,并行打开多个分支,并通过 pull requests (PR)合并 master 上的更改。在预定的时间,dbt Cloud 选取主分支,并针对生产数据运行所选的模型,按照代码中的定义转换它们,并交付更改。

由于与 Github 的无缝集成,所有模型和配置都可以使用 git 进行代码版本化,开发过程可以像任何其他经典软件工程项目一样进行。

这允许一个高效、可观察且易于维护的环境,尽管让 master 直接连接到生产仓库并不是最可靠的做法。dbt 语法很容易出错,即使理想情况下可以在本地编译(Jinja 模板必须翻译成 SQL),也不容易评估这些变化是否破坏了数据中的一些语义约束。在一个简单的实现中,没有什么可以阻止您通过一个破坏某些东西的 commit 来合并到 master,只是当计划的任务在晚上某个时候运行时,您会发现您的方法中的错误。不理想。

dbt 云上的“请求时运行”功能

幸运的是,dbt Cloud 来帮忙了,当从连接的存储库上打开的 PR 触发时,允许针对自定义分支运行作业。换句话说:生产作业的精确副本可以使用每次打开 PR 时在分支上找到的模型来运行,在相同的生产环境中根据临时模式来具体化。当 PR 关闭或合并时,临时模式被删除,但是当 PR 打开时,它可以像数据库上的任何其他模式一样被访问,以运行测试或手动检查东西——如果需要的话。这个特性对于检查分支内容的语法和高级一致性特别有用,可以防止参与者合并重大变更。如果生产中的 dbt 管道已经包含测试,那么这些测试也将针对临时模式运行,以便在语义级别上检查其内容。

CI 检查失败,阻止开发人员合并

然而,尽管在临时模式上复制整个生产环境在理论上很有吸引力,但是实现每次提交都有数亿行的表是不可行的。拥有 CI 的主要目的是为开发人员提供对他们工作的快速检查,而一些表的完全重新填充在最好的情况下可能需要几个小时。在执行 dbt 作业时,很容易区分生产运行和 CI 运行,考虑到严格的命名模式和用于此目的的临时模式(本文发布时的 dbt_cloud_pr_xx)。在 dbt 模型中克服对原始表的引用,并在执行 CI 作业时减少被引用的临时实例的大小,这样就可以让 CI 运行使用一小部分生产数据,从而大大减少对每个 PR 进行可靠检查所需的时间。

第一步:删除 dbt 模型中对原始表的硬编码引用

从语法上来说,缩小表的范围以避免篡改数据结构的外部引用是一项简单的工作,没有任何经验法则可以正确地完成这项工作。我们决定在一个主表上限制时间范围,并填充其他表,以便保留连接和引用。

第二步:在针对 CI 模式运行时,缩小原始表的范围

这里有一个离现实不远的例子:想象一个数据库模式,其中有租户和广告商之间关于一些房屋属性(列表)的对话。最合乎逻辑的决定是只选择在特定时间间隔内创建的对话(例如,2019 年 1 月,大约数万个样本),以强制存在与这些对话相关的列表,当然还有双方涉及的用户。产生的模式大小减小了,但仍然一致。按照这个方向推理,我们可以关闭与模式的这一部分相关的所有可传递的依赖关系,可能的话,在同一时期对与这些没有直接依赖关系的其他表进行时间约束。

感谢 Julian SmidekStephen O' Farrell 对这个项目和这个职位的贡献。

建立新的 PyTorch 深度学习环境

原文:https://towardsdatascience.com/setting-up-a-new-pytorch-deep-learning-environment-313d8d1c2df0?source=collection_archive---------11-----------------------

照片由阿齐兹·阿查基Unsplash 上拍摄

无论您是开始一个新项目,还是在远程机器上运行,您都不想浪费时间去寻找依赖项和安装软件库。

本教程将提供一种从空白开始设置的最快方法。

我测试了这种方法,在 Amazon Web Services 上运行的一个简单的 EC2 实例上完成。

管理您的包

PyTorch 中的深度学习工作流是用 Python 编程语言编写的,您会发现自己需要安装许多额外的 Python 包才能获得作为数据科学家所需的所有功能。

为了保持整洁,您需要一个工具来帮助您管理 Python 环境。Conda 是管理软件包、依赖项和环境的强大工具。我们将首先安装它。

Miniconda 是 conda 的免费极简安装程序。为您的操作系统找到正确的 Miniconda。

请注意,虽然我是在 Mac 上工作,但我是在 AWS 上运行的 Linux 实例上安装 Miniconda 的。

我在 64 位 Linux 上使用 Python 3.8:

$ wget [https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh](https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh)

上面的命令下载了一个 bash 脚本,我们现在运行它:

$ bash Miniconda3-latest-Linux-x86_64.sh

您需要查看许可协议。按下翻到底部,在那里你将键入yes同意它的条款。

接受并安装。在安装过程中,您可能需要接受或修改一些设置,但这应该很简单。您可能会收到此警告:

WARNING:You currently have a PYTHONPATH environment variable set. This may cause unexpected behavior when running the Python interpreter in Miniconda3.For best results, please verify that your PYTHONPATH only points to directories of packages that are compatible with the Python interpreter in Miniconda3: /home/klassm/miniconda3

PYTHONPATH环境变量告诉您的系统在哪里寻找 Python 和适用的包。你可以检查这个被设置到什么目录。在 Linux 上:

$ echo $PYTHONPATH

列出该目录的内容后,我发现它只用于少量系统范围的站点包。我认为不重新分配我的PYTHONPATH变量是安全的。

退出并返回以重置外壳。康达已经把你安置在它的“基础”环境中。

请注意命令行前面的“(base)”。

现在conda应用程序已经安装好了,可以从命令行使用了。我可以通过键入以下内容来验证这一点

$ conda

在命令行中。您应该会看到如下所示的输出:

usage: conda [-h] [-V] command ...conda is a tool for managing and deploying applications, environments and packages.Options:positional arguments:...

创建虚拟环境

现在我们来创建一个深度学习的虚拟环境。最佳实践是为每个项目创建一个虚拟环境。这样,您可以分离每个项目的所有依赖项。即使您认为您将重用相同的 Python 包,有时您将需要相同库的不同版本。事情会很快失去控制。帮你自己一个忙,创造一个虚拟的环境。

当你不在虚拟环境中运行 Python 代码时,我的反应是。

以下内容指导 Conda 创建一个名为“pytorch”的虚拟环境:

$ conda create -n pytorch

Conda 会让你知道它计划做什么,并询问你是否同意。同意继续。您应该会看到类似这样的内容:

## Package Plan ##environment location: /home/ec2-user/miniconda3/envs/pytorchProceed ([y]/n)? yPreparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate pytorch
#
# To deactivate an active environment, use
#
#     $ conda deactivate

使用以下命令激活 pytorch 环境

conda activate pytorch

您将注意到命令行中的“(base)”如何变成了“(pytorch)”,通知您现在处于新的虚拟环境中。

安装 CUDA(可选)

下一步是可选的。如果不打算在 GPU 上运行,可以直接跳到前面。

如果你计划在大型数据集上训练大型神经网络,GPU 几乎是必不可少的。由于其架构与 CPU 的不同,GPU 是运行大型并行矩阵计算的理想选择。顺便说一下,训练一个神经网络主要是矩阵计算。

CUDA 是 Nvidia 的一个库,允许开发人员与 GPU 进行交互。由于安装说明会因操作系统而异,请遵循 Nvidia 的安装指南中的说明。

安装软件包

现在安装您需要的 Python 包。Matplotlib 对于创建数据图很有用,但不是绝对必要的。

以下命令将安装这些包及其依赖项。这在我的机器上占用了大约 1 GB 的空间。

conda install -c conda-forge matplotlib pytorch torchvision

根据您的项目,您可能需要一些其他的 Python 库,如 scikit-learn 或 pandas。这些你可以用同样的方法轻松安装。

确认

让我们确保一切安装正确。打开 Python shell 并键入:

>>> import torch
>>> x = torch.rand(5,3)
>>> print(x)

这创建了一个填充了随机值的 5x3 维张量。输出应该如下所示:

tensor([[0.1279, 0.4032, 0.7045],
        [0.2979, 0.1128, 0.7660],
        [0.9651, 0.1172, 0.2716],
        [0.9355, 0.1351, 0.3755],
        [0.3469, 0.9118, 0.0110]])

全部完成

恭喜你!您已经为在 PyTorch 中运行深度学习工作负载做好了准备。

当然,现在由你来设计一个神经网络并训练它。注意你的计算成本。

警告

所以这个教程给人的印象是建立一个深度学习环境很容易,而且可以做到。然而,困难/冗长的部分是正确设置 CUDA。

避免任何头痛的最简单方法是从预配置的深度学习环境开始。有一些很好的资源可以帮你完成繁重的工作。

在 AWS 上,您可以从预先构建了所有必要的深度学习库和 CUDA 的 Amazon 机器映像启动 EC2 实例。选择 AMI 时只需搜索“深度学习”,你会发现几个选项。

为您的 EC2 实例选择 AMI 时,只需搜索“深度学习”。

为深度学习而预先配置的虚拟机也可以在谷歌的云和微软 Azure 上使用。使用你最喜欢的云。

当选择在哪种类型的机器上运行时,如果您打算利用 GPU,请记住选择一个连接了 GPU 的实例。使用完实例后,不要忘记关闭它们!这些机器运行起来往往很昂贵。

如果您只想在自己的机器上运行,另一个选择是使用一体化的预构建 Docker 映像。查看 Deepo 的一些例子。如果你家里有一个强大的钻机,这可能是更划算的选择。

在云上设置 PostgreSQL 实例,免费⛅

原文:https://towardsdatascience.com/setting-up-a-postgresql-instance-on-the-cloud-4ec4cf168239?source=collection_archive---------13-----------------------

比较 AWS、GCP 和 Heroku 的“免费层”产品,以建立一个云 Postgres 实例。

图片由穆罕默德·哈桑拍摄,来自皮克斯拜

最近的一篇文章中,我详细介绍了如何开始使用本地安装的 PostgreSQL,使用 pgAdmin 和 SQLAlchemy 来建立数据库,加载数据并从 Python 脚本中查询数据。然而,有时候,仅仅有一个本地安装是不够的。如果我们想将一个 web 应用程序连接到我们的数据库,该怎么办?或者设置一个 ETL 过程,按照计划将数据从 API 提取到我们的数据库?

本文旨在向您展示任何人都可以完全免费地建立自己的云托管 Postgres 实例。我们将比较三大云提供商的产品:AWS、GCP 和 Heroku。

如果你想在继续之前看看我以前的文章,你可以在这里找到它:

[## PostgreSQL 入门实用指南🐘

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

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

亚马逊网络服务

卢卡斯·坎波伊在 Unsplash 上的照片

AWS 自由层

AWS 可能是目前云计算领域最大的名字,它提供了一个丰富的“免费层”,非常适合想要学习和尝试预算的爱好者。在 12 个月里,我们可以免费使用所有这些。本文特别感兴趣的是,我们每月被提供 750 小时的 RDS,这是亚马逊的托管关系数据库服务。要访问 AWS 免费层,我们只需要注册一个帐户,并用信用卡验证;我们为期 12 个月的“免费层”访问将从此开始。

设置 RDS Postgres 实例

一旦您设置了 AWS 帐户并通过信用卡验证,要在 AWS RDS 上设置 Postgres 实例,我们只需从管理控制台导航到 RDS 页面,并填写简单的配置表单。

我们可以选择一个 Postgres 实例,然后选择“自由层”模板来开始。其他需要配置的重要选项有''和' 备份' ,,这两个选项都应该禁用,以防止我们超出可能会产生费用的限制。我们还需要导航到' 附加连接配置 ' ,并确保我们将' 公共访问 ' 设置为' 是' ,以允许我们从 EC2 实例外部访问数据库,即在我们的本地机器上。

为了连接到我们已经建立的数据库,我们首先需要从我们的 IP 地址启用入站流量。为此,我们可以编辑分配给 RDS 实例的安全组的' 入站规则 ' ,以允许来自'My IP'的流量。

一旦这一步完成,我们可以使用 pgAdmin 或 Python 连接到我们的数据库,正如我在之前的帖子中所解释的。我们所需要的是实例的端点和端口,这在我们的数据库页面的' 连接性和安全性 ' 部分中提供。

优势

  • 免费一年(只要我们不超过使用限制)。
  • 访问大量其他"免费层"云解决方案。

不足之处

  • 如果你不小心,很容易超过使用限制。
  • 需要信用卡详细信息才能注册。

GCP(谷歌云平台)

Pero KalimeroUnsplash 上拍摄的照片

GCP 免费试用

谷歌云平台还有一个“免费试用”选项,相当于 AWS 免费层。尽管这里我们结合了两种产品:

首先,在注册和验证信用卡后,我们有资格在前 3 个月内获得 300 美元的固定预算。这样做的好处是,我们可以访问全套的谷歌云产品,因为我们只受限于我们账户上剩余的点数,而不是特定的产品。我们在这里还增加了安全性,我们不能在不知不觉中超过使用限制,因为我们必须明确地将我们的帐户升级到要收费的“付费帐户”(见此处)。

除此之外,如果我们升级到“付费账户,谷歌还提供几个“永远免费的产品。这些以类似于 AWS 免费层的方式运作,每月有津贴。只要我们保持在使用限制范围内,我们就不会被收费,而且我们还有一个额外的好处,那就是这项服务没有截止日期;与 AWS " 免费层"不同,我们的访问权限永远不会过期,我们可以无限期地继续使用我们的配额。然而不幸的是,Postgres 不包括在 Google 提供的“永远免费的”产品中,因此,为了本文的目的,我们将限于 3 个月的“免费试用”选项。

设置云 SQL Postgres 实例

要启动并运行 Postgres,我们只需创建一个新项目,在导航菜单中选择“ SQL ”,并选择一个 Postgres 实例。和以前一样,我已经禁用了自动备份功能以降低成本。

同样,我们需要允许访问我们的 IP 地址,以便我们可以在本地连接到这个实例。为此,我们可以导航到“ 连接” ,在“ 公共 IP ”下,我们可以添加我们希望允许访问的 IP 地址。

我们可以在实例页面的"【Connect to this instance】 下的" Overview" 部分中找到实例的公共 IP 地址,它与端口一起允许我们以通常的方式连接到数据库。

优势

  • 没有不必要费用的机会(除非我们明确升级到“付费账户”)。
  • 获得全套 GCP 产品。

不足之处

  • 试用仅持续 3 个月。
  • 一旦我们的信用没了,就永远没了。

赫罗库

图片来自 PixabayBessi

Heroku 自由层

Heroku 与我们之前讨论的两个例子略有不同,它更像是一个 PaaS(平台即服务),而不是一个云服务提供商。它倾向于提供更多可管理的、低配置的服务,如果你刚开始接触云技术领域,这很好,但是如果你是一个经验丰富的开发人员,这就有点限制了。对于给定的任务,Heroku 通常也会比 AWS/GCP 更昂贵,尽管它的简单性使它非常容易启动和运行——消除了 AWS 和 GCP 服务的广度有时可能带来的选择悖论。Heroku 还有一个额外的好处,它的“免费层”不需要信用卡验证,因此如果你担心产生费用,它提供了一个安全的赌注。也就是说,Heroku 在其" Free Tier " Postgres 实例中的 10,000 行限制对我们实际上可以用它做什么造成了很大的限制,使得它不太可能在项目中有用,除了简单的实验。

设置 Heroku Postgres

建立一个 Heroku Postgres 数据库。

建立一个 Heroku Postgres 数据库再简单不过了。首先,我们需要在 Heroku 建立一个账户(不需要信用卡验证,但如果我们这样做,我们会得到额外的好处)。我们可以创建一个新的应用程序来存放我们的数据库,并导航到data.heroku.com,在那里我们可以指定我们想要设置一个 Heroku Postgres 实例。然后,我们可以安装,将我们的数据库分配给我们创建的应用程序,并检查“ 设置 ”选项卡以显示我们的数据库凭证。

从这一点开始,与 pgAdmin 连接并查询我们的数据库的过程与 GCP 和 AWS 相同(在我以前的文章 中解释过,这里 )。这里唯一的警告是,我们需要将数据库访问限制到我们凭证中的特定数据库名称,否则我们将会看到许多其他数据库以及我们自己的数据库。

正在连接 Heroku Postgres 并使用 pgAdmin 限制 DB。

优势

  • 不需要卡验证。
  • 不可能被收费,除非我们特别选择付费选项。

不足之处

  • 限于 10,000 行
  • Heroku 只提供 GCP 或 AWS 上可用服务的一小部分。

结论

图片来自 Pixabay

现在我们已经看到了三种方法,通过这三种方法我们可以建立一个云托管的 Postgres 实例,根据您的需求和舒适程度,这三种方法各有利弊。

总的来说,如果你愿意遵守使用限制,我会推荐 AWS,因为我们有全年访问 RDS 和一套其他“免费层”服务的优势。如果你想在收费上更安全一点,但又拥有 AWS 提供的同等灵活性和成套服务,GCP 可能是一个不错的中间选择。最后,如果你是一个完全的初学者,或者想在没有信用卡验证承诺的情况下使用云 Postgres 数据库,Heroku 可能是一个很好的起点。

感谢阅读!

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

* [## PostgreSQL 入门实用指南🐘

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

towardsdatascience.com](/a-practical-guide-to-getting-set-up-with-postgresql-a1bf37a0cfd7) [## 聪明的方法是找到一个杂货递送点

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

towardsdatascience.com](/finding-a-grocery-delivery-slot-the-smart-way-f4f0800c4afe) [## 使用 GitHub 页面,通过 5 个简单的步骤免费创建一个网站

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

towardsdatascience.com](/launch-a-website-for-free-in-5-simple-steps-with-github-pages-e9680bcd94aa)*

设置一个独立的 HBase 本地实例,并使用 Python Happybase 连接到它

原文:https://towardsdatascience.com/setting-up-a-standalone-hbase-local-instance-and-connect-to-it-with-python-happybase-9751c9fe6941?source=collection_archive---------24-----------------------

最近,在我作为数据科学顾问开始的冒险中,我参与了一个项目,我们从中获取数据的数据库是著名的 Apache HBase。

HBase 是一个分布式的 Hadoop 非关系数据库,在处理海量数据方面非常强大。

在 HBase 数据模型中,行由行键标识,行键或多或少相当于关系主键,它们按行键排序。

列被分组到所谓的列族中,列族是列的物理和逻辑分组,一个族中的列与另一个族中的列分开存储,以便只能对您需要的数据执行查询。

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

我决定安装 HBase 本地实例的原因是,我必须带着无尽的好奇心生活,我喜欢尝试。

步骤 1:设置 Linux 虚拟机

我做的第一件事是用 Alpine Linux 创建一个 Linux 虚拟机,挂载在 VMWare 上。虚拟机运行后,我通过键入以下命令登录安装程序:

localhost login: root
setup-alpine

我按照 shell 指令操作,最后,我重启了系统。我需要 Java 支持才能让 HBase 工作,所以我安装了 openjdk8:

apk add openjdk8-jre

之后,为了方便起见,我在 /home 中创建了几个文件夹:

cd home
mkdir downloads
mkdir andrea
cd downloads

现在我在 /home/downloads 中,我可以下载 HBase 压缩文件夹,解压缩并更改目录:

wget [https://www.apache.org/dyn/closer.lua/hbase/2.2.3/hbase-2.2.3-bin.tar.gz](https://www.apache.org/dyn/closer.lua/hbase/2.2.3/hbase-2.2.3-bin.tar.gz)tar xzvf hbase-2.2.3-bin.tar.gzcd hbase-2.2.3

这个文件夹里面有两个重要的文件夹: binconf

我走进了 conf :

然后将h base _ env . sh内的 JAVA_HOME 环境变量修改为/usr/lib/JVM/open JDK 8-JRE(文件夹可能不同):

export JAVA_HOME=/usr/lib/jvm/openjdk8-jre

此外,对于独立的 hbase,我用示例 1 中的这里的报告了文件 hbase-site.xml 的内容。

然后,我向上导航一个文件夹,回到 Hbase 主文件夹,转到 bin 目录:

要检查 HBase 是否正常工作:

./start-hbase.sh./hbase shell

瞧啊!

要查看表格,请键入 list:

当然,这里没有表,但是我们可以按照以下约定创建一个表:

create 'table_name','columnFamily1',...,'columnFamilyN'

在外壳中:

现在让我们添加两行:

要检索该表,让我们运行一次扫描:

现在,表就在那里,我们可以使用 Python 包 Happybase 连接到它,这个包是使用 Python Thrift 构建的。

首先,停止 HBase 实例,安装 Python 3Happybase 包:

apk add python3pip install happybase

然后,启动节俭服务器:

和 HBase:

现在,我们打开一个交互式 Python 会话,并连接到 HBase,以查看使用 Happybase APIs 时一切正常:

感谢您的阅读,有任何问题请联系我!

在本地机器上设置 Amazon SageMaker 环境

原文:https://towardsdatascience.com/setting-up-amazon-sagemaker-environment-on-your-local-machine-7329e0178adc?source=collection_archive---------10-----------------------

埃里克·马塞利诺在 Unsplash 上的照片

亚马逊 SageMaker 不仅仅是托管的 Jupyter 笔记本电脑,它是一种完全托管的服务,使您能够构建、训练、优化和部署机器学习模型。一个常见的误解是,为了使用这些服务,您需要一个 SageMaker Notebook 实例或 SageMaker (Studio)笔记本,特别是当您开始使用 SageMaker 时。事实上,您可以直接从您的本地机器或者甚至从您喜欢的 IDE 中启动所有这些服务。

在我们继续之前,让我们考虑一下如何与 Amazon SageMaker 服务交互。您有两个 API

SageMaker Python SDK —这是 Python 中的一个高级 API,它抽象了构建、训练和部署机器学习模型的代码。具体来说,它提供了第一类或内置算法的估计器以及支持的框架,如 TensorFlow、MXNET 等。在大多数情况下,您将使用它来与您的交互式机器学习任务进行交互。

AWS SDK —这是一个低级 API,用于与所有受支持的 AWS 服务进行交互,并不特定于 SageMaker。AWS SDK 可用于大多数流行的编程语言,如 Java、Javascript、Python (boto)等。在大多数情况下,您将使用这个服务级 API 来为自动化创建资源,或者与 SageMaker Python SDK 不支持的其他 AWS 服务进行交互。

为什么是本地环境

成本可能是第一个出现的问题,但它也是使用自己的 IDE 的灵活性,以及离线工作的能力,并在您准备好的时候启动 AWS 云上的工作。

本地环境如何工作

您像平常一样编写代码来构建您的模型,但不是 SageMake Notebook 实例(或 SageMaker Studio Notebook ),而是在运行 Jupyter 的本地机器上或从您的 IDE 中完成。当您准备好了,就可以开始在 AWS 上进行 SageMaker 实例的培训了。一旦训练完成,模型就存储在 AWS 中。然后,您可以从本地机器开始部署或运行批处理转换作业。

使用 conda 的环境设置

建议您将其设置为 Python 虚拟环境。在我们的例子中,我们使用conda来管理我们的虚拟环境,但是您也可以使用virtualenv。亚马逊 SageMaker 也使用conda来管理环境和包。假设你已经有了conda的设置,如果没有,这里头

创建新的 conda 环境

conda create -n sagemaker python=3

激活并验证环境

作者图片

安装标准数据科学包。

您可以使用condapip来安装软件包。我们会坚持conda

conda install -y pandas numpy matplotlib

安装 AWS 软件包

安装 AWS SDK for Python (boto),awscli 和 SageMaker Python SDK。SageMaker Python SDK 不作为conda包提供,所以我们在这里将使用pip

pip install boto3 awscli sagemaker

如果您是第一次使用awscli,您必须对其进行配置。关于如何配置awscli请参见这里的

默认情况下,将安装 SageMaker Python SDK 的版本 2。请务必检查 SDK 版本 2 中的更改,特别是这里的重大更改。

安装 Jupyter 并创建一个内核

conda install -c conda-forge jupyterlab
python -m ipykernel install --user --name sagemaker

验证环境并检查版本

通过发出一个jupyter lab来启动 Jupyter,并选择上面创建的 sagemaker 内核

作者图片

接下来验证笔记本中的版本,以确保一切如预期。

作者图片

建造和训练

现在,您可以开始在本地构建您的模型,并在准备就绪后开始 AWS 培训

进口包装

导入必要的包并指定角色。这里的关键区别是直接指定角色的arn而不是get_execution_role()。因为您是使用您的 AWS 凭证从您的本地机器运行它,而不是使用一个附加了角色的笔记本实例,所以 get_execution_role()将不起作用。

创建评估者

像平常一样创建估计器并设置超参数。在下面的例子中,我们使用内置的图像分类算法训练一个图像分类器。您还可以指定 SageMaker 实例的类型以及希望用于训练的实例数量

培训渠道

指定培训渠道,同样,与您在笔记本实例上的操作相比,这里没有任何变化

开始培训工作

在 SageMaker 上启动培训作业,调用 fit 方法,该方法启动 AWS 上 SageMaker 实例上的培训作业

classifier.fit(inputs=data_channels, logs=True)

作者图片

您可以使用[list-training-jobs](https://docs.aws.amazon.com/cli/latest/reference/sagemaker/list-training-jobs.html)来检查培训工作的状态

就是这样。在这里,我们看到了如何在本地设置 SageMaker 环境,并使用 Jupyter 在本地机器上构建机器学习模型。除了使用 Jupyter,您还可以从您的 IDE 中做同样的事情。

快乐训练!

在 AWS 上设置 Jupyter

原文:https://towardsdatascience.com/setting-up-jupyter-on-aws-6b3018dff41f?source=collection_archive---------21-----------------------

一个可脚本化的命令行列表,用于在 AWS 中安全、经济高效地部署 Jupyter,并增加了练习

图片来源:commons.wikimedia.orgaws.amazon.com

在我之前的帖子中,我给出了在 Google Cloud 上设置 Jupyter 的相同说明——如果你更喜欢 Google Cloud,可以去看看那篇文章。

AWS 是三巨头之一(猜猜,其他是谁?)强大的当代云环境,为数据科学家和数据工程师提供了大量很酷的服务和工具。作为一名数据科学家,当您在本地笔记本电脑上运行分析项目时,您经常会面临技术资源方面的挑战,比如下载大型数据集的网络速度、磁盘大小限制、CPU 能力限制或内存限制。在当代的云环境中,对于这些障碍,您基本上都有简单的解决方案。您的网络连接速度很快。你总是可以用小的、精益的和吝啬的资源开始任何任务。每当你面临磁盘存储问题时,你只需点击几下鼠标,就可以租用一个更大的磁盘。或者你可以将数据集加载到 S3,然后通过 Amazon Athena 查询。或者使用一些其他合适的存储服务来进行成本有效的处理。CPU 能力太小?不用担心,将您的实例类型更改为具有更多 CPU 的类型(当您不再需要它时,可以立即缩减)。内存不足?几次点击之后,你就有了更多的内存,同样,如果你不再需要它,你可以把它拿回来。对于分布式计算来说,任何类型的集群形成通常也只需点击几下鼠标,这时您只需知道要做什么:启动集群以执行更繁重的计算任务,将结果保存在集群外部的某个存储服务中,并关闭集群以防止其闲置(并产生不必要的成本)。

如果你有使用 Jupyter Notebook 的经验,并且对类似 Debian 的环境感到舒适,那么你可能会发现下面的说明很有帮助。

安装并设置 AWS CLI v2(如果尚未安装)

如果您还没有设置 AWS 命令行界面(CLI ),请进行设置。安装 CLI 并为其设置访问密钥,使其能够正常工作。其余说明假设您已经设置了 CLI 和访问密钥。

说明如下:

1.安装 CLI

2.设置访问键

从这一点开始,一切都可以从本地计算机的命令行 shell 界面进行。对我来说,下面提供的说明既适用于 Windows 上的 Git Bash,也适用于 Debian Linux。

创建一个密钥对(如果还没有)

3.根据需要调整密钥名、区域和输出文件名(区域必须与您计划的 Jupyter VM 位置相匹配,并且需要 chmod 400,否则 Debian ssh 客户端会阻止它的使用):

aws ec2 create-key-pair \
        --key-name my-jupyter-kp \
        --region eu-north-1 \
        --query 'KeyMaterial' \
        --output text \
    > my_jupyter_private_key.pemchmod 400 my_jupyter_private_key.pem

启动并设置合适的虚拟机

3.创建并运行虚拟机。我在这里使用t3.micro作为实例类型,因为在编写这些指令时,t3.micro是符合自由层条件的(您可以根据自己的使用需求随意切换,但要注意成本):

IMAGE_ID=`aws ec2 describe-images \
        --owners aws-marketplace \
        --filters "Name=name,Values=debian-10-amd64*" \
        --query 'sort_by(Images, &CreationDate)[-1].ImageId' \
        --output text`AWS_MY_JUPYTER_INSTANCE_ID=`aws ec2 run-instances \
        --image-id $IMAGE_ID \
        --count 1 \
        --instance-type t3.micro \
        --key-name my-jupyter-kp \
        --tag-specifications 'ResourceType=instance,\
                Tags=[{Key=Name,Value=my-jupyter-vm}]' \
        --query 'Instances[0].InstanceId' \
        --placement AvailabilityZone=eu-north-1a \
        --output text`

4.等待虚拟机准备就绪。在我的例子中,在状态检查开始在新创建的虚拟机的 EC2 仪表板 UI 上显示“2/2 检查通过”之前,花了 2 分多钟。

5.注意:从这里开始,我们假设AWS_MY_JUPYTER_INSTANCE_ID变量成立。如果出于某种原因,您的 shell 终端关闭了,然后您重新打开它,您需要重新初始化该变量,以便下面的命令能够工作。我建议您备份您的实例 ID(这样,如果需要,您可以稍后用AWS_MY_JUPYTER_INSTANCE_ID=<your instance id>重新初始化它):

# Take a backup note of the value of this variable:
echo $AWS_MY_JUPYTER_INSTANCE_ID

6.我们需要设置适当的安全组(防火墙规则)来启用 ssh 连接:

VPC_ID=`aws ec2 describe-instances \
        --instance-ids $AWS_MY_JUPYTER_INSTANCE_ID \
        --query 'Reservations[0].Instances[0].VpcId' \
        --output text`SG_ID=`aws ec2 create-security-group \
        --group-name my-jupyter-sg \
        --description "My Jupyter security group" \
        --vpc-id $VPC_ID \
        --query ‘GroupId’ \
        --output text`aws ec2 authorize-security-group-ingress \
        --group-id $SG_ID \
        --protocol tcp \
        --port 22 \
        --cidr 0.0.0.0/0aws ec2 modify-instance-attribute \
        --instance-id $AWS_MY_JUPYTER_INSTANCE_ID \
        --groups $SG_ID

7.测试 ssh 连接是否正常工作(对 ssh 指纹问题回答“是”):

DNS_NAME=`aws ec2 describe-instances \
        --instance-ids $AWS_MY_JUPYTER_INSTANCE_ID \
        --query 'Reservations[0].Instances[0].PublicDnsName' \
        --output text`ssh -i my_jupyter_private_key.pem admin@$DNS_NAMEexit # to get back to your local compyter prompt

8.为了能够在以后方便地重新启动虚拟机(这里我们假设我们上面创建的私钥文件在当前工作目录中,并且一直在那里—如果密钥文件的位置不同,那么适当地调整这里构造的别名):

echo >> ~/.bashrcecho "AWS_MY_JUPYTER_INSTANCE_ID=$AWS_MY_JUPYTER_INSTANCE_ID" \
    >> ~/.bashrcecho "AWS_MY_JUPYTER_KEY=\"`pwd`/my_jupyter_private_key.pem\"" \
    >> ~/.bashrcecho "alias aws_start_my_jupyter_vm=\"aws ec2 start-instances \\
        --instance-ids \$AWS_MY_JUPYTER_INSTANCE_ID\"" \
    >> ~/.bashrcecho "alias aws_connect_my_jupyter_vm=\"
        DNS_NAME=\\\`aws ec2 describe-instances \\
            --instance-ids \$AWS_MY_JUPYTER_INSTANCE_ID \\
            --query 'Reservations[0].Instances[0].PublicDnsName' \\
            --output text\\\`
        ssh -i \\\"\$AWS_MY_JUPYTER_KEY\\\" admin@\\\$DNS_NAME\"" \
    >> ~/.bashrc

9.测试新创建的别名:

aws ec2 stop-instances --instance-ids $AWS_MY_JUPYTER_INSTANCE_ID

等到实例正确停止。您可以从 AWS EC2 仪表板检查它——实例状态必须显示“已停止”。我用了不到一分钟。

exit

重新打开本地 shell 命令提示符(让它重新加载~/.bashrc文件)。输入以下命令:

aws_start_my_jupyter_vm

您应该在 json 中看到一条消息(取决于您的 AWS CLI 配置),说明您的 VM 的当前和以前的状态。

等待虚拟机启动。这可能需要大约 2 分钟,您可以从 AWS EC2 仪表板上看到:当状态检查显示“2/2 检查通过”时,实例准备好执行下一个命令:

aws_connect_my_jupyter_vm

这将通过 ssh 将您带到 VM 命令提示符。

10.您的 VM 现在已经准备好了,您现在可以随时从本地计算机的命令行轻松地重新启动它,以便继续您的工作。

设置 Jupyter

我们将安装 JupyterLab,Jupyter 笔记本的新版本。

11.连接到您的虚拟机(如果您在上面的命令后退出):

aws_connect_my_jupyter_vm

12.在虚拟机命令提示符下运行以下命令:

sudo apt update
sudo apt upgrade **# Hit 'Y' and Enter key when asked**
sudo apt install python3-pip **# Hit 'Y' and Enter key when asked** sudo pip3 install --upgrade jupyterlab boto3
sudo mkdir -p /opt/my_jupyterlab/bin
sudo sh -c \
    'echo "#!/bin/bash" > /opt/my_jupyterlab/bin/run_jupyterlab'
sudo chmod a+x /opt/my_jupyterlab/bin/run_jupyterlab

重要!!!!在下一个命令中,出于安全原因,需要使用-IP = 127 . 0 . 0 . 1 来阻止任何外部访问尝试,特别是因为我们在这里关闭了密码和安全令牌,以方便使用。

sudo sh -c 'echo "jupyter lab \\
        --ip=127.0.0.1 \\
        --NotebookApp.token=\"\" \\
        --NotebookApp.password=\"\" \\
        --NotebookApp.allow_origin=\"*\"" \
    >> /opt/my_jupyterlab/bin/run_jupyterlab'exit

13.带有 Jupyterlab 的虚拟机现在已经配置好了,您现在回到了本地计算机的命令行。让我们将使 JupyterLab 易于启动和使用的要点联系起来:

echo "alias aws_connect_my_jupyterlab=\"
        DNS_NAME=\\\`aws ec2 describe-instances \\
            --instance-ids \$AWS_MY_JUPYTER_INSTANCE_ID \\
            --query 'Reservations[0].Instances[0].PublicDnsName' \\
            --output text\\\`
        ssh -i \\\"\$AWS_MY_JUPYTER_KEY\\\" admin@\\\$DNS_NAME \\
            -L 8888:localhost:8888 \\
            -t '/opt/my_jupyterlab/bin/run_jupyterlab'\"" \
    >> ~/.bashrcexit

14.再次打开本地命令提示符(让它重新加载~/.bashrc文件),测试我们刚刚创建的命令行别名:

aws_connect_my_jupyterlab

15.打开浏览器,在地址栏中输入 http://localhost:8888/

16.瞧!你在 JupyterLab!您已经安装了 AWS python API(参见上面的 pip 3 install-upgrade 命令)。您的 JupyterLab python 环境已经设置好,并且能够与 AWS 服务进行交互(在一定程度上,您已经通过 CLI 访问密钥向正在使用的帐户授予了权限)。

停止虚拟机以避免不必要的云成本

17.每当您停止使用笔记本电脑时,不要忘记关闭虚拟机,以避免不必要的云成本。要从本地计算机命令行停止虚拟机,请执行以下操作:

aws ec2 stop-instances --instance-ids $AWS_MY_JUPYTER_INSTANCE_ID
exit

重新启动已经设置好的 Jupyter 虚拟机

18.当您稍后回到笔记本上工作时,打开本地命令提示符,使用以下命令重新启动虚拟机:

aws_start_my_jupyter_vm

19.等待虚拟机启动。这可能需要大约 2 分钟—您可以从 AWS EC2 仪表板上看到:当状态检查显示“2/2 检查通过”时,该实例准备好执行下一个命令:

aws_connect_my_jupyterlab

20.打开浏览器,在地址栏中输入 http://localhost:8888/

如果您不想启动 JupyterLab,而只是一个到 VM 的 shell 连接,那么您可以使用另一个命令行别名:aws_connect_my_jupyter_vm

添加额外磁盘

虚拟机根文件系统链接到的默认卷大小为 8gb。我建议让它保持原样,只有当您需要处理更大的数据集时,才向虚拟机添加额外的 EBS 卷。如果您已经完成了项目,将额外的空间作为单独的磁盘可以让您放下并删除它(在删除磁盘之前,将您想要保留的文件备份到 S3)。根据官方记录,AWS 免费层包括 30GB 的存储空间,但超出免费层的服务在典型的个人预算水平下可能会相当昂贵,所以让它们闲置,让你按月付费是没有意义的。同样,由于同样的成本原因,在创建另一个持久磁盘之前,考虑一下您实际需要多大的磁盘。确切的定价取决于您在创建 EBS 卷时可以调整的多个参数,但是 200GB 卷(带每日快照)的价格可能会超过每月 30 美元,而 25GB 对于您当前的项目来说可能已经足够大了(每月 6 美元)?

家庭作业的附加练习

以上内容足以让您开始使用 AWS 中的 Jupyter 环境。但是,为了迫使你思考,练习一些 AWS 修补程序,并增强你对环境的信心,这里有一些额外的练习,可以让你的生活更加轻松,我建议你尝试自己解决。请随意在下面张贴您的解决方案描述或您可能得到的问题作为回应,我将尝试对它们进行评论以获得您的反馈。

练习 1

使 Jupyter 虚拟机的启动更加方便。改进本地命令行别名检查虚拟机是否已经运行的方式——如果没有,则自动启动虚拟机,等待它启动并准备好,并在其中启动 Jupyter。这样,您将消除启动虚拟机并手动等待其准备就绪的单独手动步骤。

练习 2

改进您的本地命令行别名,在使用 ctrl+c 停止 Jupyter 服务后,它还会让您停止虚拟机(默认操作是停止虚拟机),这样您可以避免因意外忘记关闭虚拟机而导致的不必要的云成本。

练习 3

自动部署新的 Jupyter VM,避免每次创建时手动复制粘贴上面的所有命令。如果您想为不同的项目维护单独的环境,这种方式会使您的生活更加灵活和敏捷。有几种方法可以做这件事。这里有几个想法(选择你的选择并实现它)。

Ex。4 备选方案 1。编写上述指令中的所有内容,以便从一个命令行命令中触发。

例如。4 备选方案 2。创建一个 Jupyter 虚拟机映像,当您想要启动另一个独立于其他项目的干净的 Jupyter 环境时,可以将它用作模板。

尽情享受吧!

在 Google Cloud 上设置 Jupyter

原文:https://towardsdatascience.com/setting-up-jupyter-on-google-cloud-6ad75562ac1c?source=collection_archive---------23-----------------------

一个可脚本化的命令行列表,用于在 Google Cloud 中安全、经济地部署 Jupyter,并增加了练习

图片来源:commons.wikimedia.org 的 Jupyter 和谷歌云的标志

更新: 在我的下一篇文章中,我给出了关于 在 AWS 上设置 Jupyter 的等效说明——如果你对 AWS 更感兴趣,可以去看看那篇文章。

Google Cloud 是一个伟大、强大和快速发展的当代云环境,它为数据科学家和数据工程师提供了大量很酷的服务和工具。作为一名数据科学家,当您在本地笔记本电脑上运行分析项目时,您经常会面临技术资源方面的挑战,比如下载大型数据集的网络速度、磁盘大小限制、CPU 能力限制或内存限制。在当代的云环境中,对于这些障碍,您基本上都有简单的解决方案。您的网络连接速度很快。你总是可以用小的、精益的和吝啬的资源开始任何任务。每当你面临磁盘存储问题时,你只需点击几下鼠标,就可以租用一个更大的磁盘。或者,您可以将数据集加载到 BigQuery 或其他合适的存储服务中,以便进行经济高效的处理。CPU 能力太小?别担心,给你的虚拟机增加更多的 CPU(当你不再需要它的时候,你可以立即缩减)。内存不足?几次点击之后,你就有了更多的内存,同样,如果你不再需要它,你可以把它拿回来。对于分布式计算来说,任何类型的集群形成通常也只需点击几下鼠标,这时您只需知道要做什么:启动集群以执行更繁重的计算任务,将结果保存在集群外部的某个存储服务中,并关闭集群以防止其闲置(并产生不必要的成本)。

Jupyter vs 谷歌云数据实验室

由于目前大多数数据科学家都习惯于使用 Jupyter Notebook 或 Jupyter lab(Jupyter Notebook 的新版本),任何数据科学家在开始使用 Google Cloud 时面临的首要问题之一是如何以一种合理方便的方式设置它,并避免不必要的云成本。谷歌云吸引你注意的一点是他们的 Datalab 产品,这基本上是谷歌对 Jupyter 笔记本电脑的翻新,部署在一个专用的虚拟机中,添加了额外的持久磁盘和一些额外的服务(如自动备份和 Ungit)。

使用 GC Datalab 而不是您自己部署的 Jupyter 的一个主要优点是,它的部署是为您准备好的,并且是自动化的——您只需在云外壳中键入特定的命令行,等待一段时间进行配置,然后您就可以通过 GC Cloud Shell Web Preview 功能、SDK-s(用于与已部署的不同云服务轻松集成)轻松访问整个 UI 环境。因此,快速使用气相色谱数据实验室非常容易。

然而,这种快速入门的便利性也带来了一些缺点,如 Linux 底层环境和设置过于受限和定制化(不是一个熟悉的 Debian 系列——没有基于 apt*的工具来安装额外的包),以及一些其他意想不到的不必要的麻烦,至少对我来说是这样。因此,我想出了一种建立 Jupyter Lab(Jupyter 笔记本的新版本)的方法,这种方法实现了类似的(甚至更好的)易用性和云集成,并且成本更低(通过避免 Datalab 附带的强制性额外持久磁盘,而实际上并不总是必要的)。从那以后,在谷歌云环境下工作时,我更喜欢使用 Jupyter Lab 而不是 Datalab。

如果你有使用 Jupyter Notebook 的经验,并且对类似 Debian 的环境感到舒适,那么你可能会发现下面的说明很有帮助。

Jupyter 安装说明

出于可脚本化/可自动化的目的,以下指令依赖于 Google Cloud Shell 命令行,即我们避免通过云控制台 UI 做同样的事情。

1.创建或者选择一个想要部署 Jupyter 虚拟机的云项目。

2.打开 Google 云控制台,从云控制台激活云壳。您可以通过云控制台右上角的工具栏按钮来完成此操作:

单击以启动云壳

3.在 Cloud Shell 命令提示符下,输入以下命令(根据需要调整项目名称、实例虚拟机名称、区域和机器类型——我建议保留这里的其他选项,除非您知道自己要做什么):

PROJECT_NAME=my-project-name **#change this to actual project name**
VM_NAME=my-jupyterlab
ZONE=europe-west1-b
MACHINE_TYPE=n1-standard-1gcloud compute --project=$PROJECT_NAME \
    instances create $VM_NAME \
        --zone=$ZONE \
        --machine-type=$MACHINE_TYPE \
        --maintenance-policy=MIGRATE \
        --image-family=debian-10 \
        --image-project=debian-cloud \
        --scopes=cloud-platformgcloud compute ssh my-jupyterlab --zone europe-west1-b

4.上面的最后一个命令会将您带到新创建的虚拟机的命令提示符下。在那里输入以下命令:

sudo apt update
sudo apt upgrade **# Hit 'Y' and Enter key when asked**
sudo apt install python3-pip **# Hit 'Y' and Enter key when asked**
sudo pip3 install --upgrade jupyterlab google-api-python-client
sudo mkdir -p /opt/my_jupyterlab/bin
sudo sh -c \
    'echo "#!/bin/bash" > /opt/my_jupyterlab/bin/run_jupyterlab'
sudo chmod a+x /opt/my_jupyterlab/bin/run_jupyterlab

重要!!!在下一个命令中,出于安全原因,--ip=127.0.0.1是必需的,以阻止任何外部访问尝试,特别是因为我们在这里关闭了密码和安全令牌,以实现与 Datalab 相同的使用便利性。当您以后更加熟悉 Google Cloud 并了解如何配置网络时,为了增加安全性,您可以完全关闭虚拟机的外部 IP,并创建防火墙设置,以便虚拟机仍然能够与外部世界通信(安装软件包和下载数据集需要)。然而,为了不使防火墙功能的当前说明过于复杂,这是已经实现的设置,您可以通过 GC 帐户验证访问您的笔记本电脑,而无需 Jupyter 进行额外的密码交互,同时不会将您的笔记本电脑暴露给公众:

sudo sh -c 'echo "jupyter lab \\
        --ip=127.0.0.1 \\
        --NotebookApp.token=\"\" \\
        --NotebookApp.password=\"\" \\
        --NotebookApp.allow_origin=\"*\"" \
    >> /opt/my_jupyterlab/bin/run_jupyterlab'exit

5.带有 JupyterLab 的虚拟机现在已经配置好了,使用上面最后的exit命令,您可以返回到云 Shell 命令行。让我们将使 JupyterLab 易于启动和使用的要点联系起来:

echo "" >> .bashrc
echo "alias my_jupyterlab=\"gcloud compute ssh my-jupyterlab \\
        --zone europe-west1-b \\
        -- -L 8080:localhost:8888 -4 \\
        '/opt/my_jupyterlab/bin/run_jupyterlab'\"" \
    >> .bashrcexit

6.上面最后的exit命令关闭了云外壳。再次打开云 Shell,输入以下命令来测试我们刚刚创建的命令行别名:

my_jupyterlab

7.上面的最后一个命令打开了到新创建的虚拟机的 ssh 连接,创建了云控制台 Web 预览特性所需的隧道,并在虚拟机内部启动了 JupyterLab 服务——您应该可以在控制台 Shell 终端输出中看到 JupyterLab 的日志输出。如果您在这里按 Ctrl+C 并终止 JupyterLab 服务,连接将关闭,您将返回到控制台 Shell 命令行提示符。但是,如果您希望下一步也能成功,请不要这样做(即不要按 Ctrl+C——如果您按了,请再次输入上面的命令:)。

8.要打开 JupyterLab UI,请单击云壳工具栏上的“Web 预览”按钮,然后单击“在 8080 端口上预览”

1.单击打开 Web 预览菜单

2.单击“在端口 8080 上预览”

9.瞧!你在 JupyterLab!您已经安装了谷歌云的 python API(参见上面的pip3 install --upgrade命令),并且它可以访问谷歌云服务(参见上面创建虚拟机时的--scopes=cloud-platform选项)。您的 JupyterLab python 环境与所有 Google 云服务完全集成,并且能够以与 Datalab 相同的方式与这些服务进行交互。

从这里开始,你可以创建和编辑笔记本,与底层的 Debian 平台交互(通过笔记本命令行 magic 或者从 JupyterLab 启动一个终端),或者在基于 Debian 的 Jupyter 环境中做任何你觉得舒服的事情。添加任何你觉得有必要的包(apt install gitpip3 install pandas;等等)。

重新启动已经设置好的 Jupyter 虚拟机

每当您停止使用笔记本电脑时,不要忘记关闭虚拟机,以避免不必要的云成本。当您稍后回到笔记本上工作时,请执行以下操作:

1.重新启动虚拟机。

2.打开云控制台命令提示符。

3.输入以下命令:

my_jupyterlab

4.点击云壳工具栏上的“Web 预览”按钮,然后点击“8080 端口预览”。

添加额外的永久磁盘

默认虚拟机主磁盘大小为 10GB。我建议让它保持原样,只有当您需要处理更大的数据集时,才向 VM 添加一个额外的持久磁盘。如果您已经完成了项目,将该额外空间作为额外的磁盘让您有机会丢弃并删除它(在删除磁盘之前,将您想要保留的那些文件备份到云存储中)。在典型的个人预算水平下,永久磁盘是一项相当昂贵的服务,因此让它们闲置,让您按月付费是没有意义的。同样,由于同样的成本原因,在创建另一个持久磁盘之前,考虑一下您实际需要多大的磁盘。默认情况下,Datalab 会为您创建一个 200GB 的磁盘(在撰写本文时,普通 200GB SSD 的欧洲-西方 1 价格为€31.30 英镑/月),但也许 25GB 对于您当前的项目已经足够大了(€3.91 英镑/月)?

你可以在这里找到给虚拟机添加持久磁盘的说明。

解决纷争

基于 Google Cloud Web Preview 的 web UI 隧道可能会发生的一件事情是,您突然看到 Jupyter web UI 失去了与 Jupyter 服务的连接(顺便说一下,同样的事情可能也会发生在 Datalab 上)。在这种情况下,请检查您的云 Shell 是否仍然连接着,并在必要时重新连接它。这种情况下的原因是,云外壳拥有隧道,如果云外壳以某种方式断开连接,它会带走隧道,并导致 Jupyter web UI 失去与后端的连接。如果这种断开是由于临时网络连接而发生的,那么单击 Cloud Shell 工具栏上的“reconnect”链接可能足以恢复 JupyterLab 连接,甚至不会丢失会话状态。但是,如果 Cloud Shell 和 Jupyter VM 之间的连接已经丢失(即,这不仅仅是您的浏览器和 Google Cloud Console 服务之间的网络连接问题),那么您必须从 Cloud Shell 再次输入my_jupyterlab命令,以再次启动 Jupyter 服务。

家庭作业的附加练习

以上内容足以让您开始使用 Google Cloud 中的 Jupyter 环境。但是,为了迫使你思考,练习一些谷歌云修补程序,并增强你对这种环境的信心,这里有一些额外的练习,可以让你的生活变得更加轻松,我建议你尝试自己解决。请随意在下面张贴您的解决方案描述或您可能得到的问题作为回应,我将尝试对它们进行评论以获得您的反馈。

练习 1

使 Jupyter 虚拟机的启动更加方便。改进my_jupyterlab云外壳别名,它检查虚拟机是否已经在运行——如果没有,那么自动启动虚拟机,等待它启动并准备好,并在其中启动 Jupyter。这样,您将消除启动虚拟机的单独手动步骤。

练习 2

改进my_jupyterlab云外壳别名,在使用 ctrl+c 停止 Jupyter 服务后,它还会让您停止 VM(默认操作是停止 VM)——这样您可以避免由于意外忘记关闭 VM 而导致的不必要的云成本。

练习 3

将 Cloud SDK 安装到您的本地台式机或笔记本电脑中,并尝试实现这样的设置:您可以将 ssh 隧道连接到云托管的 Jupyter VM,并从您的本地台式机或笔记本电脑启动 Jupyter 服务,而不是使用云 Shell 和 Web Preview。这样,您就可以从日常工作流程中消除另一个额外的步骤(打开云控制台并启动控制台 Shell)。

练习 4

自动部署新的 Jupyter VM,避免每次创建时手动复制粘贴上面的所有命令。如果您想为不同的项目维护单独的环境,这种方式会使您的生活更加灵活和敏捷。有几种方法可以做这件事。这里有几个想法(选择你的选择并实现它)。

例如。4 备选方案 1。编写上述指令中的所有内容,以便从一个命令行命令中触发。

Ex。4 备选方案 2。创建一个 Jupyter 虚拟机映像,当您想要启动另一个独立于其他项目的干净的 Jupyter 环境时,可以将它用作模板。

尽情享受吧!

在 Atom 编辑器上设置 LaTeX

原文:https://towardsdatascience.com/setting-up-latex-on-your-atom-editor-7ea624571d50?source=collection_archive---------5-----------------------

编辑、生成和预览 TeX 文件,全部在 Atom 编辑器中完成

Atom 上的 LaTeX 编辑器

在本教程中,我将指导您在 Atom 上设置 LaTeX 编辑器,以下是这样做的一些原因和好处:

  • 保存工作时并排预览您的工作
  • 快速,在 3 秒钟内生成预览
  • 单击预览会将光标带到语法的位置
  • Dropbox 和 GitHub 集成,用于备份和与合作者协作
  • 自由的

什么是乳胶

LaTeX 是一个文档准备系统,在学术界广泛用于发布科学文档。作者使用标记语法来定义文档的结构、设置文本样式、插入图像、添加引用和交叉引用。

因为出版商那么多,各有各的设计标准。例如,标题为 18pt 乘以 Roman,名称为 12pt 乘以 Italic,依此类推。LaTeX 的目的是让作者专注于写作,而不是浪费时间遵循出版商的文档设计指南。作者只需下载出版商的 LaTeX 模板并开始写作。

如果你是 TeX 新手,或者只是想用 LaTeX 做一个一次性项目,最快的入门方式是使用在线服务,比如 PapeeriaOverleafLaTeX base 。它们提供了编辑、预览和下载 PDF 格式作品的能力。

既然有在线解决方案,那么为什么要在你的机器上设置 LaTeX 编辑器呢?

除非你为他们的计划付费,否则免费层有一些限制,让我列举几个:

  1. 有限的私有文档[Papeeria],或者没有私有文档[Latex base]
  2. 没有 GitHub 集成[下页],或者只有公共存储库[Papeeria]
  3. 没有合作者[背页]
  4. 需要在线。

就我个人而言,我选择在本地安装 LaTeX,这样我和我的合作者就可以处理同一个 LaTeX 文档,并与私有的 GitHub 库同步。

其次,与在线服务不同,在本地机器上生成预览也要快得多。当我点击 Cmd+S 时,预览将在不到 3 秒的时间内生成。

在 Atom 上设置 LaTeX 编辑器

在本节中,我将指导您在 macOS 上的 Atom 上设置 LaTex 编辑器。该设置由 4 部分组成:

  • 设置纹理分布
  • 设置原子
  • 安装 Latexmk
  • 在 Atom 中安装包

特克斯分布

在 OS X,下载 MacTeX 。截至 2020 年 4 月,分布为 MacTeX-2020。可以选择下载完整包,4GB。它包含大多数用户需要的所有文件,您不必面对搜索缺失组件的艰巨任务。强烈推荐。

如果你不想安装整个 MacTeX 发行版——它很大,如果你像我一样喜欢选择安装什么,你可以下载 BasicTeX ,它只有 80MB。BasicTeX 包含了满足从生成 PDF 的需求的 TeX Live 发行版。tex 文件;它不包括 GUI 应用程序、Ghostscript 和其他库。但这意味着你必须搜索并下载你可能需要的所有软件包。我稍后会谈到这一点。

BasicTeX 安装

MacTeX 是针对 OS X 的,但是如果你在 Linux 或者 Windows 上,下载 TeX Live

原子

https://atom.io/

Atom 是一个漂亮的文本编辑器,可以在 OS X、Windows 和 Linux 上使用。它有一个包管理器,允许你安装数千个开源包,为你的编辑器增加新的特性和功能。您可以在单一界面上轻松浏览项目文件。您可以将界面分成多个窗格,以便在文件间编辑/引用代码。下载并安装 Atom

Latexmk

Latexmk 用于自动生成 LaTeX 文档。这里没什么好解释的,我们需要它来工作。安装很简单,从终端输入:

sudo tlmgr install latexmk

这将提示您输入密码并安装 latexmk 软件包。

Atom 包

这些包使您能够将 Atom 用作 LaTeX 编辑器。

  • 编译Latex 包从 Atom 内部编译 Latex 文档。它将执行 Latexmk 来构建您的工作。
  • 预览 PDF 文件。 PDF 查看包使您能够在 Atom 中查看 PDF 文件。这允许您并排预览您的工作。单击预览会将光标带到语法的位置。
  • 语法高亮Language-LaTeX package 在 Atom 中突出显示 LaTeX 语法。这对于帮助您检查语法是否具有有效的 LaTeX 语法特别有用。

已安装的 Atom 包

你做到了!

此时,您的 Atom 上应该有一个可以工作的 LaTeX 编辑器。我建议对配置进行一些更改。进入Atom->Preferences->Packages。转到乳胶包的设置,并:

  • [检查]保存时构建(或使用build快捷键保持默认)
  • [取消选中]成功构建后打开结果
  • [取消选中]在后台打开结果
  • 在输出目录下,键入" build "

乳胶包的配置

语言-乳胶包中:

  • [检查]软包装

附加乳胶包

如果你有下载 BasicTeX,你可能不得不下载出版商在他们的模板中使用的包。最简单的方法是谷歌搜索丢失的包,或者搜索综合特克斯档案网(CTAN)

例如,算法是常用的包之一,我们可能会在文档中看到这一点。

\usepackage{algorithmic}

要安装软件包,请打开终端,键入:

sudo tlmgr install algorithms

这就对了。我希望你喜欢你的 LaTeX 编辑器,并且更加热爱 Atom。要感谢所有开源的贡献者 Atomatom-latexatom-pdf-viewlanguage-latex

为您的分析堆栈设置雪花

原文:https://towardsdatascience.com/setting-up-snowflake-for-your-analytics-stack-b252b063f20c?source=collection_archive---------39-----------------------

本学长在 Unsplash 上的照片

雪花是一个基于云的分析数据仓库,由于其无需维护、易于使用和灵活的服务而变得越来越受欢迎。通过基于使用的定价模式将计算和存储分开,雪花能够根据不断变化的数据、工作负载和并发需求轻松扩展。

如果您刚刚开始使用 Snowflake,请稍等片刻,然后再开始部署一些特定的资源并构建您的分析应用程序。要充分利用雪花的每秒成本结构和出色的安全模型,需要从一开始就考虑配置,而不是 6 个月以后。

在这里,我们将总结来自 dtb 的团队的建立雪花环境的最佳实践,以及我们从实践中学到的东西。

有用的东西

首先,让我们熟悉一下《雪花》中的所有主要概念。

数据库:在传统的本地数据仓库中,您可能有多台服务器为各种数据源的多个数据库提供服务,而在雪花中,最高级别的抽象是一个数据库,您可以在每个帐户中拥有多个数据库。每个数据库中的数据被拆分成压缩文件,存储在云存储中,只有雪花专有的 SQL 引擎才能查询。这使得数据存储非常便宜,而且几乎是无限的。

仓库:仓库为雪花提供了在任何数据库上执行查询的计算能力。每个仓库都是一个 MPP 计算集群,基本上是一组执行实际数据处理的虚拟计算机。仓库是根据它们的大小和运行时间来收费的。

用户:可以用登录名和密码连接到雪花的单个用户。通过分配角色,用户被授予雪花资源的特权和权限。

角色:一个对象,为角色所分配到的任何用户定义一组雪花资源的特权和权限。

雪花让所有与帐户关联的用户及其所有资源使用一个如下所示的连接:

**Account =** [**host.region.cloud_service**](https://wh31430.ca-central-1.aws.snowflakecomputing.com/)**Url =** [**https://host.region.cloud_service.snowflakecomputing.com/**](https://wh31430.ca-central-1.aws.snowflakecomputing.com/)

默认情况下,雪花允许访问所有 IP 地址,但可以通过在帐户或用户级别将某些 IP 地址列入白名单来阻止流量。查看网络政策页面。

配置您的数据库

根据您的团队的数据加载和暂存策略以及您希望如何设置开发和生产环境,有多种方法可以设置数据库。但是,如果你不确定,那么这个有两个数据库的例子非常适合分析用例。

原始:

在基于 ELT 的转换工具对原始数据进行查询以进行清理、反规范化和建模,并进行分析之前,该数据库可作为一个登陆区。该数据库具有严格的权限,因此不能被 BI 和报告工具等最终用户访问。

批量数据可以使用内部阶段从本地机器复制到原始数据库,或者使用外部阶段从云存储(如 S3)复制到原始数据库。您还可以使用 Snowpipe 从 stages 加载连续数据,snow pipe 是雪花的连续数据摄取服务。

这是创建数据库的方法:

USE ROLE SYSADMIN;CREATE DATABASE IF NOT EXISTS RAW;

分析:

该数据库包含为分析师、报告工具和其他分析用例准备的转换数据。这个数据库中的所有表都是由 ELT 工具创建和拥有的,ELT 工具从原始数据库中提取数据。分析数据库中的表和视图可以根据特定用途组织成模式,然后可以将粒度权限分配给用户角色,以便对特定模式进行操作。例如,可以为审计员分配只允许访问模式视图的角色,这些视图可以通过对个人信息进行适当的转换和散列来准备。

设置您的仓库

雪花仓库是按大小和每分钟的活动收费的,所以重要的是要考虑你将使用每个仓库做什么,并相应地进行配置。仓库在不使用时可以手动或自动挂起,但在使用它们运行查询时会非常快地加速运行,因此建议在几分钟后将它们配置为 auto_suspend。您为仓库选择的规模取决于它们将要执行的工作负载的规模,我们建议从小规模开始,然后根据需要增加规模。对于分析用例,三个仓库的设置会很好。

加载:

这是将用于处理数据加载到雪花的仓库。像 Fivetran 或 Stitch 这样的工具或特定用户将被分配角色,以授予使用该仓库加载作业的权限。为这个特定的任务分离这个仓库是理想的,因为数据负载可以改变,给仓库带来压力,并且我们不希望其他工具因为使用同一个仓库而变慢。

这就是创建仓库的方式:

USE ROLE ACCOUNTADMIN;CREATE WAREHOUSE LOADING WITH
WAREHOUSE_SIZE = SMALL
MAX_CLUSTER_COUNT = 2
SCALING_POLICY = ECONOMY
AUTO_SUSPEND = 120
ALTER RESUME = TRUE
COMMENT = ‘Warehouse for performing data loads’;

转换:

您的 ELT 工具(如 dbt)从原始数据库执行数据转换,并将其保存到分析数据库,这些工具将与有权使用此仓库的角色连接。仓库只会在 ELT 作业被执行时运行,所以你只需在那段时间付费。

报告:

这是您的 BI 工具(如 Looker 或 Chartio)将使用的数据仓库。仓库查询数据的频率取决于 BI 工具的设置。

仓库中意想不到的高负荷会导致比预期更高的成本。雪花提供了资源监视器,可以用来限制你的仓库在特定时间内使用的信用数量。我们强烈建议设置资源监视器来指定每个仓库的限制,以及当达到限制时应该采取什么措施。下面是如何创建一个:

USE ROLE ACCOUNTADMIN;CREATE RESOURCE MONITOR ACCOUNT_LIMIT_250
WITH CREDIT_QUOTA = 250
FREQUENCY = MONTHLY
START_TIMESTAMP = IMMEDIATELY
TRIGGERS ON 100 PERCENT DO NOTIFY;

定义您的角色

设置角色可能是早期最重要的任务。确定层次结构将指导您分配角色。雪花角色可以授予其他角色,并且与角色相关联的特权由层次结构中的父角色继承。有许多系统定义的角色,如 accountadmin、securityadmin、useradmin、sysadmin 和 public。Public 是分配给每个用户的默认角色,其他角色根据用户需要的权限添加到用户中。以下是我们将设置的角色。

装载机:

该角色被授予原始数据库中所有模式的权限。它连接到装载仓库以执行所有数据装载任务。sysadmin 角色可用于创建此角色,并授予装载仓库和原始数据库的权限。

以下是创建角色的方法:

USE ROLE SYSADMIN;CREATE OR REPLACE ROLE LOADER 
COMMENT=’role holds privileges for loading data to raw database’;GRANT ALL ON WAREHOUSE LOADING TO ROLE LOADER;GRANT ALL ON DATABASE RAW TO ROLE LOADER;

变压器:

该角色被分配给使用 ELT 工具进行连接的用户。它被授予查询原始数据库的权限和拥有分析数据库上的表的权限。

记者:

该角色将分配给与 BI 工具连接的分析师和用户。该角色将只对分析数据库拥有权限。

创建您的用户

由于我们在角色级别分配权限,因此我们可以将这些角色分配给新用户,并为每个独立的工具和人员创建用户。这意味着您团队中的每个成员以及您的分析堆栈中与雪花集成的每个工具都将拥有自己的用户凭证。通常,您会希望用户身份由您的身份管理解决方案来管理,比如 OKTA。一旦完成,你就可以创建你的用户了。

管理账户:

在我们前面提到的系统定义的角色中,accountadmin 是顶级角色。root 用户—创建帐户的人将有权访问所有这些角色。这些角色非常强大,不应该分配给执行日常分析的用户。根用户将由您的 DBA 或 CTO 担任。

分析师:

分析师将通过各种方式连接到雪花,并执行各种任务。他们可能正在运行 SQL、python 脚本,或者使用 jupyter 笔记本和其他 ELT 工具对数据进行建模。可以为这些用户分配加载者、转换者或报告者角色,或者多个角色,具体取决于他们的功能。

要创建用户,您需要作为管理用户进行连接。以下是创建用户并为其分配角色的方法。

USE ROLE USERADMIN;CREATE USER <USER>
PASSWORD = ‘’
EMAIL = ‘’
MUST_CHANGE_PASSWORD = TRUE;USE ROLE SECURITYADMIN;GRANT ROLE LOADER TO USER <USER>;

然后,用户可以使用这些用户凭据登录并更改密码。

数据加载工具:

一些用户将被分配 loader 角色,按照角色权限的指定在原始数据库上执行数据加载。这些用户是为 Fivetran 和 Stitch 等数据集成工具创建的。

ETL 工具:

这些用户将被分配 transformer 角色,执行从原始数据库到分析数据库的转换工作。这适用于像 dbt 这样的 ELT 工具。

商务智能工具:

这些用户将被分配为报告者角色,以连接到分析数据库来使用数据。这些用户将成为你的商业智能和报告工具,如 Looker 和 Chartio。

保护用户帐户对于确保数据的最高安全级别也很重要。雪花有许多用于账户认证的安全特性。我们建议对管理帐户使用多因素身份认证,您可能也想为您的分析师设置它。对于您的云工具,OAuth 也是一个选项。

就这样…

我们已经为您如何为您的分析团队设置雪花提供了很好的指导。这样做不会花你很长时间,但会让你有条理地前进。现在,您可以继续处理更令人兴奋的问题,并实际推出分析解决方案来推动您的公司向前发展。

Waterfront Analytics 帮助公司建立他们的分析堆栈并构建分析用例。如果你需要更多关于雪花的帮助,或者想聊聊你的项目,请通过我们的网站联系。

在 Windows 10 上设置 TensorFlow (GPU)

原文:https://towardsdatascience.com/setting-up-tensorflow-on-windows-gpu-492d1120414c?source=collection_archive---------2-----------------------

就我个人而言,我讨厌花费数小时来设置机器学习工具进行培训——尤其是在 Windows 上。

在过去几年的多次尝试和错误之后(即 Googling 和 StackOverflow-ing),我决定分享一个我想出的设置 TensorFlow 的方法。

我将这篇文章献给其他数据科学家,他们一直在查看充满错误消息的命令提示符。

警告:你必须有一个支持 CUDA 的 GPU 卡

1)安装所需的软件

概观

安装(按顺序):

  • 可视化工作室
  • 蟒蛇
  • NVIDIA CUDA 工具包+ cuDNN

可视化工作室

首先,在这里安装来自的 Visual Studio。安装社区版,因为专业版和企业版需要订阅。

注意: Visual Studio 是不是跟 VS 代码 IDE 一样!

Visual Studio 下载页面

蟒蛇

这里下载并安装 Anaconda。

您不需要在安装过程中向 PATH 环境变量添加 Anaconda。

蟒蛇装置

英伟达软件

安装 Visual Studio 后,安装 NVIDIA CUDA Toolkit 和 cuDNN。

来自https://www.tensorflow.org/install/gpu的软件要求

到当前日期(2020 年 10 月),必须安装 CUDA 10.1 和 cuDNN SDK 7.6 ( 这个极其重要)。

警告:支持的版本可能会改变,因此请务必查看官方 TensorFlow 文档

最新的 CUDA 版本是 11——请访问 CUDA 档案库cuDNN 档案库获取更早的版本。

安装 CUDA 只需运行可执行文件。exe)。

CUDA 10.1。可执行程序的扩展名

解压 cuDNN 库,将所有文件移动到 CUDA 目录下。如果您没有更改安装目录,您的 CUDA 将位于以下位置:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA

解压 cuDNN 下载并移动文件到 CUDA

2)安装张量流

打开 Anaconda 提示符并检查 Python 的版本。

Anaconda 提示

您可以输入下面的命令来检查您当前运行的 Python 版本。

python --version

然后,创建一个新的 Anaconda 虚拟环境:

conda create -n tf python=PYTHON_VERSION
  • tf 可以改为任何其他名称(如 python_tensorflow
  • 记得用你的 PYTHON 版本替换 PYTHON_VERSION (例如 3.8.5 )

然后,激活您刚刚创建的环境:

conda activate tf

最后安装 TensorFlow:

pip install tensorflow

Do not pip 安装 tensorflow-GPU因为它将安装 tensor flow 的旧版本(YouTube 上的旧教程使用此命令)。**

3)测试张量流(GPU)

通过运行以下命令,测试 TensorFlow 是否已正确安装,以及是否可以检测到 CUDA 和 cuDNN:

**python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"**

如果没有错误,那么恭喜您,您已经成功安装了 TensorFlow。

4)安装必要的库/包

我个人经常使用 Jupyter Notebook、Seaborn 和 Matplotlib,所以我确保通过运行以下命令来安装这些库:

**pip install jupyter ipykernel seaborn matplotlib**

5)蟒蛇和朱庇特

将您之前创建的 Anaconda 环境添加到 Jupyter Notebook 中。

**python -m ipykernel install --user --name ENVIRONMENT_NAME --display-name "KERNEL_DISPLAY_NAME"**

6)最终测试

返回到基本 conda 环境,打开 Jupyter 笔记本:

**conda activate base
jupyter notebook**

创建一个新的 Jupyter 笔记本并打开它:

Jupyter 笔记本上的 Anaconda 环境

新创建的笔记本

Jupyter 笔记本

运行下面这三行代码:

**!python --versionimport tensorflow as tfprint("Num GPUs Available", len(tf.config.experimental.list_physical_devices('GPU')))**

如果它能检测到你的 Python 和你的 GPU,你就成功安装了 TensorFlow (GPU)和机器学习必备工具!

使用 scikit-learn 和 spaCy 设置文本预处理管道

原文:https://towardsdatascience.com/setting-up-text-preprocessing-pipeline-using-scikit-learn-and-spacy-e09b9b76758f?source=collection_archive---------5-----------------------

了解如何使用 sklearn 管道进行标记化、词条化、删除停用词和标点符号

文本预处理是将原始文本转换成可矢量化的形式,随后由机器学习算法用于自然语言处理(NLP)任务,如文本分类、主题建模、命名实体识别等。

原始文本由所有文本分析 API 进行广泛预处理,如 Azure 的文本分析 API或我们在 Specrom Analytics 开发的 API,尽管预处理的程度和类型取决于输入文本的类型。例如,对于我们的历史新闻 API,输入由抓取的 HTML 页面组成,因此,在将文本输入到 NLP 算法之前,从文本中去除不需要的 HTML 标签是很重要的。然而,对于一些新闻媒体,我们从他们的官方 REST APIs 获得 JSON 格式的数据。在这种情况下,根本没有 HTML 标记,对这样一个干净的文本运行基于正则表达式的预处理程序是浪费 CPU 时间。因此,根据数据源对文本进行不同的预处理是有意义的。

如果您想要创建如下所示的词云,那么通常建议您删除停用词。但是在诸如名称实体识别(NER)的情况下,这并不是真正必需的,您可以安全地将语法完整的句子添加到您选择的 NER 中。

从搜集的新闻语料库中生成的词云(2016-2020)。杰伊·帕特尔

有许多好的博客文章开发了文本预处理步骤,但是为了完整起见,让我们在这里浏览一下。

1.标记化

将段落或句子中包含的文本转换为单个单词(称为标记)的过程称为标记化。在我们将文本转换成充满数字的向量之前,这通常是文本预处理中非常重要的一步。

直观而又相当天真的是,对文本进行标记的一种方法是简单地在空格处断开字符串,python 已经提供了非常好的字符串方法,可以轻松地完成这一任务,让我们将这种标记方法称为“空白标记化”。

然而,空白标记化无法理解单词缩写,例如当我们将两个单词“can”和“not”组合成“can”、don(do+not)和 I ve(I+have)时。这些都不是无关紧要的问题,如果我们不把“不能”分成“能”和“不能”,那么一旦我们去掉标点符号,我们将只剩下一个单词“cant”,它实际上不是一个字典单词。

Python 中用于文本处理的经典库 NLTK 附带了其他标记化器,如 WordPunctTokenizer 和 TreebankWordTokenizer,它们都按照不同的约定运行,试图解决单词缩写问题。对于高级标记化策略,还有一个 RegexpTokenizer,它可以根据正则表达式拆分字符串。

所有这些方法基本上都是基于规则的,因为没有真正的“学习”发生,所以作为用户,您必须处理所有可能因令牌化策略而出现的特殊情况。

Spacy 和 Apache Spark NLP 等下一代 NLP 库在很大程度上解决了这个问题,并在语言模型中使用标记化方法处理常见缩写。

1.1 NLTK 标记化示例

# Create a string input 
sample_text = "Gemini Man review: Double Will Smith can't save hackneyed spy flick U.S.A"from nltk.tokenize import WhitespaceTokenizer
tokenizer_w = WhitespaceTokenizer()# Use tokenize method 
tokenized_list = tokenizer_w.tokenize(sample_text) 
tokenized_list# output['Gemini',
 'Man',
 'review:',
 'Double',
 'Will',
 'Smith',
 "can't",
 'save',
 'hackneyed',
 'spy',
 'flick',
 'U.S.A']

WordPunct Tokenizer 将在标点符号上拆分,如下所示。

 from nltk.tokenize import WordPunctTokenizer 
tokenizer = WordPunctTokenizer()
tokenized_list= tokenizer.tokenize(sample_text)
tokenized_list# Output['Gemini',
 'Man',
 'review',
 ':',
 'Double',
 'Will',
 'Smith',
 'can',
 "'",
 't',
 'save',
 'hackneyed',
 'spy',
 'flick',
 'U',
 '.',
 'S',
 '.',
 'A']

NLTK 的 treebanktokenizer 将单词缩写拆分成两个标记,如下所示。

from nltk.tokenize import TreebankWordTokenizer
tokenizer = TreebankWordTokenizer()
tokenized_list= tokenizer.tokenize(sample_text)
tokenized_list
#Output['Gemini',
 'Man',
 'review',
 ':',
 'Double',
 'Will',
 'Smith',
 'ca',
 "n't",
 'save',
 'hackneyed',
 'spy',
 'flick',
 'U.S.A']

1.2 空间标记化示例

在 SpaCy 中执行标记化也很简单,在后面关于词条化的部分,您会注意到为什么标记化作为语言模型的一部分可以解决单词缩写的问题。

# Spacy Tokenization example
sample_text = "Gemini Man review: Double Will Smith can't save hackneyed spy flick U.S.A"from spacy.lang.en import English
nlp = English()
tokenizer = nlp.Defaults.create_tokenizer(nlp)
tokens = tokenizer(sample_text)
token_list = []
for token in tokens:
    token_list.append(token.text)
token_list
#output
['Gemini',
 'Man',
 'review',
 ':',
 'Double',
 'Will',
 'Smith',
 'ca',
 "n't",
 'save',
 'hackneyed',
 'spy',
 'flick',
 'U.S.A']

2.词干化和词汇化

词干化和词汇化试图为不同的词形变化(raining,rained 等)获得词根(例如 rain)。Lemma algos 给你的是真正的词典单词,而词干法只是简单地去掉了单词的最后部分,所以速度更快,但不太准确。词干分析返回的单词并不是真正的字典单词,因此你将无法在 Glove、Word2Vec 等中找到它的预训练向量,这是取决于应用程序的一个主要缺点。

然而,使用像波特和更高级的雪球词干分析器这样的词干算法是非常流行的。Spacy 没有附带任何词干算法,所以我们将使用 NLTK 来执行词干;这里我们将展示两种词干提取算法的输出。为了便于使用,我们将把空白符号化器封装到一个函数中。如你所见,两位词干学家都将动词形式(raining)简化为 rain。

2.1 NLTK 的词干示例

sample_text = '''Gemini Man review: Double Will Smith can't save hackneyed spy flick U.S.A raining rained ran'''from nltk.tokenize import WhitespaceTokenizerdef w_tokenizer(text):

    tokenizer = WhitespaceTokenizer()   
# Use tokenize method 
    tokenized_list = tokenizer.tokenize(text) 
    return(tokenized_list)from nltk.stem.snowball import SnowballStemmerdef stemmer_snowball(text_list):
    snowball = SnowballStemmer(language='english')
    return_list = []
    for i in range(len(text_list)):
        return_list.append(snowball.stem(text_list[i]))
    return(return_list)
stemmer_snowball(w_tokenizer(sample_text))#Output['gemini',
 'man',
 'review:',
 'doubl',
 'will',
 'smith',
 "can't",
 'save',
 'hackney',
 'spi',
 'flick',
 'u.s.a',
 'rain',
 'rain',
 'ran']

你可以从 NLTK 的波特·斯特梅尔那里得到同样的结果,这个也可以把单词转换成非字典形式,比如 spy -> spi 和 double -> doubl

from nltk.stem.porter import PorterStemmerdef stemmer_porter(text_list):
    porter = PorterStemmer()
    return_list = []
    for i in range(len(text_list)):
        return_list.append(porter.stem(text_list[i]))
    return(return_list)
stemmer_porter(w_tokenizer(sample_text))#Output['gemini',
 'man',
 'review:',
 'doubl',
 'will',
 'smith',
 "can't",
 'save',
 'hackney',
 'spi',
 'flick',
 'u.s.a',
 'rain',
 'rain',
 'ran']

2.2 SpaCy 的引理化示例

如果您使用 SpaCy 进行标记化,那么它已经为每个标记存储了一个名为.lemma_的属性,您可以简单地调用它来获得每个单词的词汇化形式。请注意,它不像词干分析器那样具有攻击性,它将单词缩写(如“不可以”)转换为“可以”和“不可以”。

# [https://spacy.io/api/tokenizer](https://spacy.io/api/tokenizer)
from spacy.lang.en import English
nlp = English()tokenizer = nlp.Defaults.create_tokenizer(nlp)
tokens = tokenizer(sample_text)
#token_list = []
lemma_list = []
for token in tokens:
    #token_list.append(token.text)
    lemma_list.append(token.lemma_)
#token_list
lemma_list
#Output['Gemini',
 'Man',
 'review',
 ':',
 'Double',
 'Will',
 'Smith',
 'can',
 'not',
 'save',
 'hackneyed',
 'spy',
 'flick',
 'U.S.A',
 'rain',
 'rain',
 'run']

3.停止单词删除

上面有一些特定的词,如“它”、“是”、“那个”、“这个”等。这对基本句子的意思没有多大帮助,实际上在所有英语文档中都很常见;这些词被称为停用词。在通过计数矢量化器对记号进行矢量化之前,通常需要移除这些“常用”单词,以便我们可以减少向量的总维数,并减轻所谓的“维数灾难”。

基本上有三种方法可以删除停用字词:

  • 第一种方法是最简单的,您可以创建一个列表或一组单词来从令牌中排除;比如 list 已经是 sklearn 的 countvectorizer、NLTK 以及 SpaCy 的一部分。这种去除停用词的方法已经被接受了很长时间,然而,在研究人员和工作专业人员中有一种意识,即这种一刀切的方法实际上对学习文本的整体含义是非常有害的;有篇论文指出反对这种方法。
# using hard coded stop word listfrom spacy.lang.en import English
import spacy
spacy_stopwords = spacy.lang.en.stop_words.STOP_WORDS
# spacy_stopwords is a hardcoded set
nlp = English()
tokenizer = nlp.Defaults.create_tokenizer(nlp)
tokens = tokenizer(sample_text)
#token_list = []
lemma_list = []
for token in tokens:
    if token.lemma_.lower() not in spacy_stopwords:
    #token_list.append(token.text)
        lemma_list.append(token.lemma_)
#token_list
lemma_list
#Output['Gemini',
 'Man',
 'review',
 ':',
 'Double',
 'Smith',
 'save',
 'hackneyed',
 'spy',
 'flick',
 'U.S.A',
 'rain',
 'rain',
 'run']

不出所料,单词“will”和“can”等被删除了,因为它们出现在 SpaCy 中可用的硬编码停用词集中。让我们将它封装到一个名为 remove_stop_words 的函数中,这样我们就可以在第 5 节中将它用作 sklearn 管道的一部分。

import spacy
def remove_stopwords(text_list):
    spacy_stopwords = spacy.lang.en.stop_words.STOP_WORDSreturn_list = []
    for i in range(len(text_list)):
        if text_list[i] not in spacy_stopwords:
            return_list.append(text_list[i])
    return(return_list)
  • 第二种方法是让语言模型判断给定的标记是否是停用词。Spacy 的标记化已经为此提供了一个名为 is .is_stop的属性。现在,有些时候,spacy 的标志不会排除常见的停用词,但这仍然比要排除的硬编码单词列表要好。仅供参考,在一些 SpaCy 模型[ 1 ][ 2 ]中有一个记录良好的错误,它避免了在第一个字母大写的情况下检测停用词,因此如果它不能正确检测停用词,您需要应用变通方法。
# using the .is_stop flagfrom spacy.lang.en import Englishnlp = English()
tokenizer = nlp.Defaults.create_tokenizer(nlp)
tokens = tokenizer(sample_text)

lemma_list = []
for token in tokens:
    if token.is_stop is False:

        lemma_list.append(token.lemma_)

lemma_list#Output['Gemini',
 'Man',
 'review',
 ':',
 'Double',
 'Will',
 'Smith',
 'not',
 'save',
 'hackneyed',
 'spy',
 'flick',
 'U.S.A',
 'rain',
 'rain',
 'run']

这显然做得更好,因为它检测到这里的“Will”是一个人的名字,只是从示例文本中去掉了“can”。让我们将它封装在一个函数中,以便在最后一节中使用。

# 
from spacy.lang.en import Englishdef spacy_tokenizer_lemmatizer(text):

    nlp = English()
    tokenizer = nlp.Defaults.create_tokenizer(nlp)
    tokens = tokenizer(text)

    lemma_list = []
    for token in tokens:
        if token.is_stop is False:
            lemma_list.append(token.lemma_)

    return(lemma_list)
  • 对抗停用词的第三种方法是排除在给定语料库中出现太频繁的词;sklearn 的 countvectoriser 和 tfidfvectorizer 方法有一个名为“max_df”的参数,它让您可以忽略文档频率严格高于给定阈值的标记。您也可以通过“max_features”参数指定标记总数来排除单词。如果您打算在 count vectorizer 之后使用 tf-idf,那么与对句子的整体含义有贡献的单词相比,它会自动为停用词分配一个低得多的权重。

4.删除标点符号

一旦我们标记了文本,转换了单词的缩写,文本中的标点符号和特殊字符就不再有用了。当然,当我们处理可能有 twitter 句柄、电子邮件地址等的文本时,这是不正确的。在这些情况下,我们改变我们的文本处理管道,只从令牌中去除空白,或者完全跳过这一步。我们可以使用 regex ' ]* > '清除所有的 HTML 标签;所有非单词字符都可以用“[\W]+”删除。不过,在单词缩写被 lemmatizer 处理之前,您应该小心不要去掉标点符号。在下面的代码块中,我们将修改我们的空间代码,以考虑停用词,并从令牌中删除任何标点符号。如下面的例子所示,我们已经成功地删除了特殊字符标记,例如“:”,它们在单词矢量化的包中实际上没有任何语义贡献。

import re
def preprocessor(text):
    if type(text) == string: text = re.sub('<[^>]*>', '', text)
    text = re.sub('[\W]+', '', text.lower())
    return textfrom spacy.lang.en import English
nlp = English()
tokenizer = nlp.Defaults.create_tokenizer(nlp)
tokens = tokenizer(sample_text)lemma_list = []
for token in tokens:
    if token.is_stop is False:
        token_preprocessed = preprocessor(token.lemma_)
        if token_preprocessed != '': lemma_list.append(token_preprocessed)
lemma_list
#Output:['gemini',
 'man',
 'review',
 'double',
 'will',
 'smith',
 'not',
 'save',
 'hackneyed',
 'spy',
 'flick',
 'usa',
 'rain',
 'rain',
 'run']#A more appropriate preprocessor function is below which can take both a list and a string as inputdef preprocessor_final(text):
    if isinstance((text), (str)):
        text = re.sub('<[^>]*>', '', text)
        text = re.sub('[\W]+', '', text.lower())
        return text
    if isinstance((text), (list)):
        return_list = []
        for i in range(len(text)):
            temp_text = re.sub('<[^>]*>', '', text[i])
            temp_text = re.sub('[\W]+', '', temp_text.lower())
            return_list.append(temp_text)
        return(return_list)
    else:
        pass

另一个常见的文本处理用例是当我们试图从社交媒体评论、推文等 web 数据中执行文档级情感分析时。所有这些都广泛使用表情符号,如果我们简单地去掉所有特殊字符,我们可能会错过一些非常有用的符号,这些符号对文本的语义和情感有很大的贡献。如果我们计划使用一包单词类型的文本矢量化,那么我们可以简单地找到所有这些表情符号,并将它们添加到标记化列表的末尾。在这种情况下,作为标记化之前的第一步,您可能必须运行预处理器。

# find emoticons functionimport re
def find_emo(text):
    emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)',text)
    return emoticons
sample_text = " I loved this movie :) but it was rather sad :( "
find_emo(sample_text)
# output
[':)', ':(']

5.Sklearn 管道

正如您在上面看到的,文本预处理很少是一刀切的,大多数真实世界的应用程序要求我们根据文本源和我们计划做的进一步分析使用不同的预处理模块。

有许多方法可以创建这样的自定义管道,但一个简单的选择是使用 sklearn 管道,它允许我们顺序组装几个不同的步骤,唯一的要求是中间步骤应该已经实现了 fit 和 transform 方法,并且最终的估计器至少有一个 fit 方法。

现在,这对于许多小函数来说可能是一个过于繁重的要求,比如预处理文本的函数;但幸运的是,sklearn 还附带了一个 functionTransformer,它允许我们将任意函数包装成一个 sklearn 兼容的函数。不过有一个问题:函数不应该直接对对象进行操作,而是将它们包装成列表、pandas 系列或 Numpy 数组。不过这并不是主要的障碍,您可以创建一个助手函数,将输出打包成一个列表理解。

# Adapted from [https://ryan-cranfill.github.io/sentiment-pipeline-sklearn-3/](https://ryan-cranfill.github.io/sentiment-pipeline-sklearn-3/) from sklearn.preprocessing import FunctionTransformerdef pipelinize(function, active=True):
    def list_comprehend_a_function(list_or_series, active=True):
        if active:
            return [function(i) for i in list_or_series]
        else: # if it's not active, just pass it right back
            return list_or_series
    return FunctionTransformer(list_comprehend_a_function, validate=False, kw_args={'active':active})

最后一步,让我们构建一个 sklearn 管道,它使用 NLTK 的 w_tokenizer 函数和 2.1 节中的 stemmer_snowball,并使用第 4 节中的预处理函数。

from sklearn.pipeline import Pipelineestimators = [('tokenizer', pipelinize(w_tokenizer)), ('stemmer', pipelinize(stemmer_snowball)),('stopwordremoval', pipelinize(remove_stopwords)), ('preprocessor', pipelinize(preprocessor_final))]pipe = Pipeline(estimators)

pipe.transform([sample_text])Output:[['gemini',
  'man',
  'review',
  'doubl',
  'smith',
  'cant',
  'save',
  'hackney',
  'spi',
  'flick',
  'usa',
  'rain',
  'rain',
  'ran']]

您可以很容易地更改上面的管道来使用如下所示的 SpaCy 函数。请注意,第 3 节中介绍的标记化函数(spacy_tokenizer_lemmatizer)返回不带任何停用词的标记化标记,因此这些步骤在我们的管道中是不必要的,我们可以直接运行预处理器。

spacy_estimators = [('tokenizer', pipelinize(spacy_tokenizer_lemmatizer)), ('preprocessor', pipelinize(preprocessor_final))]
spacy_pipe = Pipeline(spacy_estimators)
spacy_pipe.transform([sample_text])# Output:[['gemini',
  'man',
  'review',
  'double',
  'will',
  'smith',
  'not',
  'save',
  'hackneyed',
  'spy',
  'flick',
  'usa',
  'rain',
  'rain',
  'run']]

我希望我已经展示了使用 Sklearn 管道和基于空间的预处理工作流来有效地执行几乎所有 NLP 任务的预处理的巨大优势。

在 Python 中设置数据科学和机器学习功能

原文:https://towardsdatascience.com/setting-up-your-data-science-machine-learning-capability-in-python-c16a9099d3fc?source=collection_archive---------55-----------------------

对所涉及的隐藏和明显因素的概述

为什么是 Python?

Python 是数据科学&机器学习(DSML) 中明显胜出的编程语言。凭借其丰富和动态的开源软件生态系统,Python 在可采用性、可靠性和功能性方面无与伦比。如果你不同意这个前提,那么请快速绕道这里

Python 拥有超过 800 万用户(SlashData)。照片由查尔斯德鲁维奥在 Unsplash。

你数据科学的目的&机器学习能力

作为 DSML 团队的领导者,你的目标是为企业带来最佳投资回报。企业通过人员和资源预算投资于 DSML 功能,而您的工作是尽可能实现最大的业务影响。

您的业务影响可以通过多种方式来衡量。最高级的目标是成本优化、风险优化和收入增长。您可以关注每个目标中的各种具体指标,如客户获取成本优化、流失预测、欺诈检测、患者健康结果或个性化产品建议。

来源:土星云

任何偏离目标设定、预算和执行的事情都会降低你的团队所能实现的投资回报率。引用一位自我提升大师的话,注意力到哪里,能量就流向哪里。

租赁与拥有

这是经典的购买与构建讨论的重新框架,在许多 DSML 平台提供“现收现付”定价的背景下,很像亚马逊网络服务。我觉得有必要改变讨论的措辞,因为不像“购买”,不管你是否使用它,你都要支付固定的费用;“租用”意味着你只在使用时付费。这对最终用户来说更方便。

当您开始用 Python 建立 DSML 平台时,您可以拥有内部架构,也可以从供应商那里租用。我将使用 Saturn Cloud 作为主要供应商,因为我预计会有所偏向。

拥有的隐性成本

拥有 DSML 功能会带来固有的“范围蔓延”问题,这些问题从一开始就不明显。很容易期望拥有将您最喜欢的开源工具集成在一起的能力:Jupyter、Dask 或 PySpark、Prefect 或 Airflow、Kubernetes、NVIDIA RAPIDS、Bokeh、Plotly、Streamlit 等。

以下是我们从以前试图拥有 DSML 功能的客户那里听到的“范围蔓延”交易破坏者的简短列表:

  • 为 AWS、Azure、GCP 或内部部署设置和管理云托管和支持
  • 确保代码和数据的企业级安全性;如果你在一个高度管制的行业,负担会更重
  • 配置:在适当的基础设施上执行工作,为手头的任务公开适当的资源和库
  • 监控,例如确保最短的停机时间
  • 用户管理:管理员工对系统和信息的访问
  • 访问控制:控制用户在应用程序中能做什么和能看到什么
  • 管理现有 OSS 包版本和集成新的 OSS 包
  • 对最终用户的支持;管理与开放源码软件专家的磋商

每一个要点都列出了一系列可能并不吸引人的额外负担。事实上,其中一些是如此痛苦,以至于我们的土星云联合创始人兼 CTO Hugo Shi 在 Kubernetes 上写了一篇文章,只是为了发泄。

明显的拥有成本

以下是您在构建 DSML 功能时需要考虑的拥有成本构成。

示例 1:拥有导致更高的总成本

你的团队的任务是开发一个客户流失模型。如果您能够预测客户流失,销售人员就可以采取主动措施来留住更多客户。你的公司年销售额为 1 亿美元,有机会将流失率从 10%降低到 5%,或者每年减少 500 万美元。为了简单起见,我们假设你是一家毛利率为 100%的 SaaS 公司。

图 1: 租赁=自动化开发

假设 FTE 成本为 15 万美元

考虑到自动化开发运维的成本节约,租赁场景由于总支出减少而产生更高的投资回报率。

例子 2:拥有带来高机会成本

现在,让我们假设在这两个场景中,您的团队有 9 名全职员工,但是在租赁场景中,所有 9 人都致力于数据科学和 ML。一个 9 名全职员工的团队可以比一个 6 名全职员工的团队多生产 50%的产品,因此,有了多余的产能,你就可以围绕客户个性化开展第二个项目。让我们假设这个项目可以在第一年提高 5%的软件销售额。

图二:租借= 力量倍增

假设 FTE 成本为 15 万美元

请注意,在租赁场景中,您实际上花费了更多的钱,但是在团队规模相同的情况下,您可以获得更高的 ROI。通过将人力支出从 DevOps 转移到 Data Science & ML,您的团队效率更高,并且可以在相同的时间内处理更多积极的 ROI 项目。自有方案具有内在的机会成本,这在租赁方案中是不存在的。

在这两种情况下,租赁的投资回报都超过了拥有 DSML 功能的投资回报。还值得注意的是,云计算定价在过去十年中大幅下降,而数据科学、机器学习和 DevOps 的劳动力成本却大幅上升。

前车之鉴

不是每个组织都需要租用 DSML 建筑。但是,在你拥有自己的房子之前先租出去更容易,风险也更小。

“先租后买”

在过去的几年里,我和数百名 DSML 领导人交谈过。他们中的很大一部分人带领他们的团队在没有租赁的情况下拥有 DSML 建筑,也没有评估拥有建筑的明显和隐藏的成本。太多时候,他们半途而废,意识到租房更便宜、更容易、更灵活,并让他们保持专注。此外,团队中的许多开发人员预计他们将只是构建架构前期的一部分,但后来不得不担任全职支持角色,花在他们加入公司的有趣科学项目上的时间要少得多!

现在是人家的问题了

…这是您在租赁该体系结构时会说的话。是的,所有开源工具的集成、开源版本管理、围绕数据和代码构建最先进的安全性、构建企业管理架构、云托管、支持服务、开源专家咨询——跟我一起说——👏有人👏else 的👏问题!

不仅仅是卸载,你还可以从一个致力于此的团队那里获得很多好处。

  • 更好的性能:Saturn 的工具提供了比 Apache Spark、Pandas 和其他数据处理工具快 100 倍的运行时间
  • 即时交付:您订阅后,它会立即出现在您的虚拟私有云上
  • 专家支持:Python OSS 的主要成员可以为您提供支持。
  • 流畅的体验:即时集成和更新开源工具
  • 原生集成:亚马逊网络服务、雪花和其他云服务
  • 无缝团队协作工具:交互式和协作式 DSML 功能
  • 自动化:数据管道和工作流程编排
  • 漂亮:直观、先进的用户界面
  • 灵活性:现收现付,随时取消

总结:你的蟒 DSML 能力

所有权模式:团队和预算分为利用 DSML 能力创造价值和支持 DSML 能力。

来源:土星云

租用模式:整个团队和预算都朝着使用租用的 DSML 能力来创造价值的方向进行了精简。

来源:土星云

您的 DSML 功能的目的是最大化其投资回报率。您希望将尽可能多的预算用于该目标:终点是否是更快的股票市场交易决策、推荐新的营销投资、运行更多的药物发现模型,等等。

我的建议是:

  • 选择 Python 是因为它无与伦比的开源生态系统
  • 先租后买

祝你好运,如果你对土星云感到好奇,请在这里查看我们的

设置您的数据科学工作台

原文:https://towardsdatascience.com/setting-up-your-data-science-work-bench-4a8d3a28205c?source=collection_archive---------12-----------------------

Unsplash 上拍摄的 ThisisEngineering RAEng

让您的计算机准备好学习数据科学

在我的上一篇帖子中,我介绍了数据科学工作所需的核心工具。在这篇文章中,我将一步一步地指导您设置计算机来执行典型的数据科学和机器学习任务。

我个人在 mac 上工作,所以大部分设置指令都是为这个操作系统设置的。

安装 python

正如我在上一篇文章中所讨论的,python 现在是数据科学从业者最流行的编程语言。因此,配置计算机的第一步是安装 python。

要在您的计算机上安装和配置 python,您需要使用终端。如果你还没有设置,你需要下载并安装 Xcode (苹果的集成开发环境)。

Mac OS X 已经安装了 python 2.7。然而,对于许多数据科学项目,您需要能够使用各种不同的 python 版本。

有许多工具可以用来安装和管理不同的 python 版本,但是 pyenv 可能是最简单易用的工具之一。Pyenv 支持在用户和项目级别管理 python 版本。

要安装 pyenv,你需要先安装 homebrew ,这是一个 Mac 的软件包管理器。一旦你有了这个,你可以用这个命令安装 pyenv(对于 Windows 安装,参见这些指令)。

brew install pyenv

然后,您需要将 pyenv 初始化器添加到您的 shell 启动脚本中,并通过运行以下代码来重新加载 bash_profile。

echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile

要查看系统上安装的 python 版本,请运行以下命令。

pyenv install --list

要安装 python 的新版本,只需运行。

pyenv install <python-version>#e.g.pyenv install python-3.7

安装 python 包

Pip 是安装 python 包的首选安装程序,默认情况下包含在 python 3.4 及更高版本中。您将需要它来安装任何开源 python 库。

要使用 pip 安装软件包,只需运行以下命令。

pip install <package>#e.g.pip install pandas

虚拟环境

不同的 python 项目将需要不同的依赖项和 python 版本。因此,为每个项目创建隔离的、可重复的环境是非常重要的。虚拟环境实现了这一点。

有很多工具可以创建 python 虚拟环境,但我个人使用的是 pipenv

Pipenv 可以用自制软件安装。

brew install pipenv

使用特定版本的 python 创建新环境。创建一个新目录,然后从新目录运行以下命令。

mkdir pip-test
cd pip-test
pipenv --python 3.7

要激活环境运行pipenv-shell,您现在将进入一个名为“pip-test”的新环境。

如果我们检查目录的内容,您将看到 pipenv 已经创建了一个名为Pipfile的新文件。这是需求文件的 pipenv 等价物,包含环境中使用的所有包和版本。

要将软件包安装到 pipenv 环境中,只需运行以下命令。

pipenv install pandas

任何安装的软件包都将反映在 pip 文件中,这意味着可以使用该文件轻松地重新创建环境。

Jupyter 笔记本

Jupyter Notebooks 是一款基于网络的代码编写应用。它们特别适合数据科学任务,因为它们使您能够直接根据您的代码呈现文档、图表、表格和图表。这为开发数据科学项目创造了一个高度互动和可共享的平台。

要安装 Jupyter 笔记本,只需运行pip install notebook,或者如果你正在使用 pipenv shell pipenv install notebook

由于这是一个基于 web 的应用程序,您需要启动笔记本服务器来开始编写代码。您可以通过运行以下命令来完成此操作。

jupyter notebook

这将在您的网络浏览器中打开应用程序,默认网址是http://127.0.0.1:8888

在浏览器中运行的笔记本应用程序

Jupyter 笔记本电脑能够在虚拟环境中工作,因此您可以在正确的项目环境中运行项目笔记本电脑。要使 pipenv 环境在 web 应用程序中可用,您需要运行以下命令。

python -m ipykernel install --user --name myenv --display-name "Python (myenv)"#e.g.python -m ipykernel install --user --name jup-test --display-name "Python (jup-test)"

如果您现在重启 web 应用程序并到达new,您将看到您的 pipenv 环境可用。选择此项将启动一个新的笔记本,它将运行您在 pipenv shell 中设置的所有依赖项。

运行在 Python(jup-test)环境中的笔记本

Python IDE

Jupyter 笔记本非常适合探索性的数据科学项目和编写只使用一次的代码。然而,为了提高效率,将常用的代码段编写到可以跨项目导入和使用的模块内的函数中是一个好主意(这被称为模块化生成您的代码)。

笔记本不是特别适合写模块。对于这个任务,最好使用 IDE(集成开发环境)。有很多可用的,但我个人使用 Pycharm。使用 IDE 的好处是它们包含了内置的工具,比如 Github 集成和单元测试。

Pycharm 既有付费专业版,也有免费社区版。要下载并安装 Pycharm,请访问此网站,并按照安装说明进行操作。

版本控制

您在数据科学项目中需要使用的最后一个工具是 Github。这是版本控制最常用的工具。版本控制本质上涉及到在线存储项目的版本。然后从分支本地执行开发。分支本质上是项目的一个副本,可以在其中进行不会影响主版本的更改。

一旦在本地进行了更改,您可以将更改推送到 Github,它们可以在一个称为“拉”请求的受控过程中合并到主分支中。

使用 Github 可以让你追踪项目的变化。在将它们集成到最终版本之前,您还可以进行更改并测试它们的影响。Github 还支持与他人的协作,因为他们可以安全地进行更改,而不会影响主分支。

要使用 Github,你首先需要按照这些指令安装它。然后你需要访问 Github 网站并创建一个账户。

拥有帐户后,您可以创建新的存储库。

创建新的存储库

要在本地处理项目,您需要克隆存储库。

cd my-directory
git clone [https://github.com/rebeccavickery/my-repository.git](https://github.com/rebeccavickery/my-repository.git)

本文是设置您的计算机以准备从事数据科学项目的指南。我列出的许多工具都是我个人喜欢的工具。然而,在大多数情况下,有几种选择。探索不同的选项以找到最适合您的工作方式和项目是值得的。

感谢阅读!

我每月都会发一份简讯,如果你想加入,请点击此链接注册。期待成为您学习旅程的一部分!

为深度学习设置您的 PC/工作站:Tensorflow 和 py torch-Windows

原文:https://towardsdatascience.com/setting-up-your-pc-workstation-for-deep-learning-tensorflow-and-pytorch-windows-9099b96035cb?source=collection_archive---------1-----------------------

到目前为止,配置新的(或不太新的)装备来处理一些神经元的最简单的方法。

作者图片

本文将指导您在 windows 机器上设置深度学习所需的工具和安装驱动程序的整个过程。令人惊讶的是,即使是建立深度学习的环境也不是那么容易。在这个过程中,你打碎东西的几率其实很高。我经历过多次从零开始设置深度学习所需的一切,尽管是在一个不同的、对程序员更友好的 Linux 操作系统中。(接下来是相关指南)

目前很少有文章解释 Windows 的相同过程。所以我决定试一试。最近坏了几次事,终于找到了妥善解决这个问题的办法。这种方法不仅能成功设置,而且比我见过的大多数其他方法都要简单得多。

本教程面向谁,更重要的是为什么是 Windows?

相信我,我也不太喜欢在 Windows 上玩 CUDA。但是,作为开发人员,更多的时候,我们最终会在笔记本电脑或功能强大的设备上工作,这些设备不仅用于深度学习或编程。在这种情况下,你无法完全摆脱 Windows。如果你是这些人中的一员,或者只是一个拥有 Windows 机器的普通读者,对 Linux 不太熟悉,那么这篇指南就是为你准备的。

下面是我们将在本文中涉及的一些内容,

  • 最低硬件和软件要求
  • 安装 Python 和所需工具
  • 一些 GPU 术语
  • 安装 GPU 驱动程序
  • 安装 Tensorflow (CPU 和 GPU)
  • 安装 PyTorch (CPU 和 GPU)
  • 验证您的安装
  • 我的个人经验和替代方法
  • 结论

最低硬件和软件要求

如果你打算设置 GPU 支持,你肯定需要一个 Nvidia GPU。

开发深度学习应用程序涉及训练神经网络,这些网络天生就需要计算。它本质上也越来越有利于并行化,这让我们越来越倾向于擅长并行化的 GPU。这就是 GPU 派上用场的原因,绝大多数深度学习框架都支持开箱即用的 GPU 加速,因此开发人员和研究人员可以在几分钟内提高工作效率,而无需进行任何可能会阻碍他们的 GPU 编程。

这些框架中的大多数(只)支持称为 CUDA 的东西——它只能与 Nvidia GPUs 一起工作,这就是为什么你特别需要 Nvidia 的一个。然而,在 AMD 的卡上也不是不可能,更多信息请访问这一页

如果你不打算安装 GPU,没问题,你仍然可以跟着做。

但当然,你应该有一个像样的 CPU,RAM 和存储,以便能够进行一些深度学习。

我的硬件——我在我的个人笔记本电脑上进行设置,配置如下:

CPU —睿频上 AMD 锐龙 7 4800HS 8C -16T@ 4.2GHz。

内存— 16 GB DDR4 内存,3200MHz

GPU—Nvidia GeForce RTX 2060 Max-Q @ 6GB gddr 6 内存

对于任何有兴趣了解配置的人,我推荐一个至少 4 核、2.6GHz 的像样的 CPU,至少 16GB 的 RAM 和至少 6GB VRAM 的 Nvidia GPU。

对于这个教程,你显然需要在 Windows 10 上。我假设对 Python 包和环境有一些基本的了解。尽管如此,一切都会得到解释。

建议您使用 64 位 Windows 10 的最新稳定版本。

本教程还假设您在新安装的操作系统上开始安装过程。如果你真的知道你在做什么,你仍然可以跟着做。

安装 Python 和所需工具

当然,第一步是安装 Python。我推荐通过 Mini-Conda 安装 Python。对于绝对初学者,我简单说明一下原因。

Conda 是一个软件包管理器,可以帮助你安装、管理和删除所有不同的软件包。但这不是唯一的一个,还有 pip——python 的默认包管理器,我非常喜欢。这里我们使用 conda,因为它在 Windows 中设置起来更加直接和简单。

Anaconda 和 Mini-Conda 是软件发行版,预装了一些非常有用的 Data Science/ML 包来节省您的时间。Anaconda 包含 150 多个有助于进行数据科学和机器学习的包,其中包括您可能需要的一切,而 Mini-Conda 只附带了少数真正必要的工具和包。

我推荐使用 Mini-Conda,因为我喜欢(几乎)完全控制安装什么软件包。保持事物的清淡确实不是一件坏事。它可以为你节省一些存储空间,当然,你也不会有 50 多个你可能从来没有用过的包。

要安装迷你康达,请点击下面的链接,https://docs.conda.io/en/latest/miniconda.html

下载 python 3 Windows 64 位安装程序,并像安装任何其他 Windows 软件一样安装它。确保勾选询问您是否希望将 conda 和 python 添加到路径的复选框。

现在,您可以通过运行以下命令来检查是否安装了 python 和 conda。它们应该显示版本号,否则您可能需要正确安装 mini-conda 并将其添加到 PATH 中。

> python --version
Python 3.8.3> conda --version
conda 4.8.4

下一步是安装 jupyter-notebook ,在你的命令行界面粘贴以下命令,

> conda install -y jupyter

您可以通过运行 jupyter 笔记本来验证您的安装,这将在浏览器上为您打开 jupyter 笔记本。

> jupyter notebook

设置您的开发环境

这是很多人经常错过的重要一步。使用包含所有已知包的东西(如 Anaconda)是可以理解的,但要处理您的项目并实际构建东西,您可能需要一个特定于该项目或您所做工作性质的定制环境。使用专用虚拟环境的另一个巨大优势是,您可以隔离您的软件包与全局设置的交互,这意味着如果您在您的环境中弄乱了软件包,您可以随时丢弃它,而不会影响任何全局软件包。

它还可以让您灵活地创建任何 python 版本的环境。所以你可以暂时远离所有新的不稳定的东西,以后基于支持进行升级。

创建一个 conda 环境相当简单,为了便于解释,我用 tensorflow 这个名字来创建它,你可以把它设置成你想要的任何值。我打算用 python 3.7,因为我知道 Tensorflow 很好地支持它。你可以通过他们的文档来验证这一点。顺便说一下,我们将在这里安装 Tensorflow 并创建一个类似的名为 torch 的环境,PyTorch 将安装在这里。

> conda create --name tensorflow python=3.7

创建环境后,您可以使用下面的命令进入,这里 tensorflow 只是我们之前给这个环境起的名字。

> conda activate tensorflow

一旦你进入这个环境,你就能在提示符的左边看到类似这样的东西

如果您碰巧在 Powershell 上没有看到这一点,您可能希望事先在 Powershell 中只初始化 conda 一次,

> conda init powershell

之后,当您不在任何环境中时,您可能会在左侧看到(base ),如上图所示。在此之后,每当您输入一个 env 时,您都会看到 env 名称。

此外,您还可以在这个环境中安装 nb 工具,并将其与我们之前安装的 jupyter notebook 链接

> conda install nb_conda

要使用 Jupyter 笔记本注册环境,请在不换行的情况下运行该命令,

> python -m ipykernel install --user --name tensorflow --display-name “Python 3.7 (tensorflow)”

要退出康达环境…

> conda deactivate

现在按照相同的步骤创建一个名为 torch 的环境

> conda create --name torch python=3.7> conda activate torch> conda install nb_conda> python -m ipykernel install --user --name torch --display-name “Python 3.7 (torch)”

如果环境设置成功,您将能够在列出环境时看到这一点,

> conda env list

要验证各个包是否实际安装在每个环境中,您可以进入该环境并执行conda list,这将显示该环境中安装的所有包的列表。

如果清单很长,不要担心。Conda 已经处理了基本的东西和依赖关系

一些 GPU 术语

在开始安装一些与 GPU 相关的东西之前,有必要了解什么是什么以及为什么你需要这些东西。

GPU 驱动— 顾名思义 GPU 驱动是一个软件,它允许你的操作系统及其程序使用 GPU 硬件。游戏玩家当然更清楚这一点,如果你喜欢游戏,那么你可能需要更新这个软件以获得最佳体验。

CUDA — 简单来说它是由 Nvidia 开发的一个编程接口层,可以访问 GPU 的指令集及其并行计算单元。

自 2010 年代末的 GeForce 8 系列 GPU 以来,几乎所有的 GPU 都支持 CUDA。

要了解更多信息,您可以访问 Nvidia 网站的这个页面,了解您的 GPU 是否支持 CUDA。

例如,如果你有一个消费级 GPU,比如 GeForce 系列或 Titan 系列的产品,你可以在下图中看到支持和不支持的内容,

截至 2020 年 9 月(这只是名单的上半部分)

如果你有一台笔记本电脑,你应该检查笔记本产品列表,如果你有一个成熟的桌面 GPU,你显然必须寻找左手边的其他阵容。

如前所述,我有一辆 RTX 2060 Max-Q,列于右侧。顺便说一句,你不必担心你的卡的标题与网页中列出的内容完全匹配,Max-Q 和 Super 都只是共享相同底层架构的设计,只是在 TDP,CUDA 核心数量和张量核心数量上有所不同。

例如,如果你拥有一辆 RTX 2080 Super 或 2080 Max-Q,甚至是一辆 2080 Super Max-Q——如果你能在列表中找到 RTX 2080,那完全没问题。但是,如果您拥有一台 RTX 2080Ti 或末尾带有 Ti 的产品,这仅仅意味着您拥有该特定系列的最高端版本,因此您很可能会发现它在 VRAM 和 CUDA 数量以及张量内核方面具有更大的能力。

截至 2020 年 9 月,

要使用 Tensorflow 2.0,您的卡的计算能力必须高于 3.5,但为了获得更好的体验,建议您至少拥有 6。Tensorflow 2.0 还需要 CUDA 版本 10,这反过来要求您的驱动程序版本为 418.x 或更高。

PyTorch 要求你的 CUDA 版本至少是 9.2 或更高,它也支持 10.1 和 10.2。计算能力必须至少高于 3.0

CuDNN — CUDA 深度神经网络库(CuDNN)是一个 GPU 加速的深度神经网络原语库。cuDNN 为标准例程提供了高度优化的实现,例如前向和后向卷积、池化、规范化和激活层。

(可选)TensorRT—NVIDIA TensorRT是一款用于高性能深度学习推理的 SDK。它包括一个深度学习推理优化器和运行时,为深度学习推理应用程序提供低延迟和高吞吐量。

安装 GPU 驱动程序

在做任何事情之前,你需要确定你正在使用的 GPU。它必须是一个支持 CUDA 的 GPU。

如果您还没有安装驱动程序,您可能需要运行 Windows Update,它会自动处理有用软件的安装,如 Nvidia 控制面板。这将有助于您了解更多关于 GPU 的信息,以及一些与本文无关的设置。

如果您有 Nvidia 控制面板,您可以从开始菜单打开它,或者右键单击桌面并选择 Nvidia 控制面板。

一旦你打开它,你可以通过点击帮助->系统信息来验证 GPU 驱动程序的版本。驱动程序版本将列在详细信息窗口的顶部。

GIF 流程图

如上面的 GIF 所示,我的驱动版本是 456.x,远远高于 418.x 的最低要求,所以我不用担心安装任何新的驱动程序。

对于你来说可能不是这样,要安装最新的驱动程序,你可以去这个网站并输入关于你的 GPU 的正确信息来下载所需的正确驱动程序。

下载 Nvidia 驱动程序— GIF

下载驱动程序后,运行安装程序并选择快速安装以获得更轻松的体验。安装驱动程序后,您可以使用 Nvidia 控制面板进行验证。

另一种安装驱动程序的方法是使用 Nvidia 的 GeForce Experience 应用程序,如果你拥有一台原本用于游戏的消费类计算机。这个过程非常简单。

这一步是可选的。如果您已经按照上述步骤安装了驱动程序,或者您的不是游戏机,您可以安全地忽略这一点。

页面下载申请。按照安装程序在您的机器上安装应用程序。完成后,您可以打开应用程序并转到驱动程序选项卡,检查更新并安装新的驱动程序。您也可以在应用程序中验证驱动程序版本。

GeForce 体验演示

既然安装驱动程序最重要的部分已经完成,你可以手动安装 CUDA toolkit,或者让 conda 来处理 TF 或 PyTorch 安装期间的所有事情,我强烈推荐这样做。

如果你决定手动安装,你可以从这个网站获得安装程序,并按照那里的说明进行操作。

安装 CUDA 工具包

一旦安装了 CUDA 工具包,就可以通过在 cmd 或 Powershell 中运行nvidia-smi 命令来验证它。

nvidia-smi 输出

安装 Tensorflow

现在终于到了本教程的关键。如果你已经做了前面提到的所有事情,这一步将会非常简单。

我们将通过康达安装 Tensorflow 2.x。

进入我们之前创建的张量流环境并跟随它是非常重要的,

> conda activate tensorflow

如果您计划在 GPU 支持下安装,请运行以下命令

> conda install -c anaconda tensorflow-gpu

这将通过 anaconda 通道安装 TensorFlow GPU。使用 conda 而不是 pip 安装 TensorFlow 的一个主要好处是 conda 包管理系统。当使用 conda 安装 TensorFlow 时,conda 也会安装软件包的所有必需和兼容的依赖项。这是自动完成的,用户不需要通过系统软件包管理器或其他方式安装任何额外的软件。

这还包括 Tensorflow 或 PyTorch 所需的 CUDA 工具包的正确版本,这使得该过程更加轻松。

安装的 CUDA 工具包仅在我们安装 tensorflow GPU 的环境中可见,这是一个巨大的优势。想象一下这个版本的 CUDA 工具包搞乱了你的全球系统的 CUDA 版本,PyTorch 甚至需要一个完全不同的 CUDA 版本才能运行。这是使用虚拟环境的最大优势。它提供了所有虚拟环境之间的完全隔离。

如果一切顺利,你不会在安装过程中得到任何错误信息。

要验证 tensorflow 和所需的包是否已成功安装,您可以执行conda list,它会显示已安装包的列表,您将在其中找到 tensorflow 相关包以及 CUDA 工具包。

您可以打开 Python 提示符并验证是否安装了 tensorflow,

>>> import tensorflow as tf
>>> tf.__version__
'2.1.0'

如果你拿回了版本号,恭喜你!你做到了!Tensorflow 安装成功。

在 Python 提示符下验证 TF 安装

在 Python 提示符下使用 Tensorflow 时,您可能会得到这样的消息——“打开了动态库”,这并不意味着什么不好的事情,它只是一个日志消息,是 tf 能够打开这些库的好迹象。

稍后将介绍如何验证 GPU 上的安装。

要安装仅用于 CPU 的 Tensorflow,您只需对安装命令进行简单更改

> conda install -c anaconda tensorflow

这将在没有 CUDA 工具包和 GPU 支持的情况下安装 Tensorflow。

安装 PyTorch

既然我们已经介绍了如何安装 Tensorflow,安装 PyTorch 也没什么不同。康达让整个过程出奇的简单。

首先,你应该进入我们为 torch 创建的 conda 环境。

> conda activate torch

如果您想安装支持 CUDA 的 PyTorch,请使用下面的命令,

> conda install pytorch torchvision cudatoolkit -c pytorch

上面的命令将通过 Conda 中的 PyTorch 通道安装带有兼容 CUDA 工具包的 PyTorch。

要安装仅用于 CPU 的 PyTorch,可以从上面的命令中删除 cudatookit

> conda install pytorch torchvision cpuonly -c pytorch

这将在没有任何 CUDA 支持的情况下安装 PyTorch。

如前所述,您可以使用> conda list来验证安装。要在 Python 上验证它,请使用下面几行代码

>>> import torch
>>> torch.__version__
'1.6.0'

如果它返回版本号,您就完成了 PyTorch 的安装。

验证您的安装

你可能认为一切都是正确的,并开始使用这些工具,但突然当你这样做时,你会开始看到一些致命的错误。如果您碰巧遇到这种情况,可能是因为您的机器和您的设置方式的原因,在实际了解更多与您的情况相关的信息之前,我无法在此一一介绍。

因此,我提供了几个笔记本,至少可以帮助您更好地验证安装,并确保 TF 或 PyTorch 使用了预期的硬件。

你可以在这个资源库dl-setup-win 文件夹下找到笔记本。克隆笔记本和运行单元取决于您。如果它显示正确的信息,那么你就可以开始了。

我在下面嵌入了相同笔记本的要点版本。

注意:如果没有从正确的环境启动 jupyter 笔记本,您可能会遇到一些错误。例如,如果您想使用 tensorflow 环境,您可以从 base env 启动笔记本,并将您的内核更改为 tensorflow env,但我在执行此操作时遇到了错误。因此,要运行 TF,请从 tensorflow 环境启动您的笔记本,要运行 PyTorch,请从 Torch 环境启动您的笔记本,而不是从 base 或其他地方。

如果你知道这个问题的解决方案,请在下面的评论中告诉我。

我的个人经验和替代方法

我一直在使用这种设置来处理一些轻度的深度学习工作负载,对于这些工作负载,我的本地硬件已经足够了。已经过了几个星期了,到目前为止,在这个设置中,一切都按预期运行。然而,我以前试过其他几种方法,结果都很糟糕。

我尝试的一种方法是这里的,它涉及到让 WSL 内部的 CUDA 和 Nvidia 驱动程序利用 GPU 进行深度学习。目前,这仍处于预览阶段,但一旦正式发布,这将是 DL 从业者真正的游戏规则改变者。它汇集了令人惊叹的 WSL2 和 CUDA/GPU 驱动程序。

但是和往常一样,这里有一个陷阱。您必须是 Windows Insider 计划的成员才能使用此功能。当然,从我的经验来看,内部预览版也有很多问题。对我来说,它有时会导致所有 Windows 应用程序完全失败,GSOD(绿屏死机)错误,无法正常启动,以及驱动程序故障等等。我个人不喜欢处在一个不稳定的环境中,所以我决定一劳永逸地选择退出只是时间问题。

你仍然可以使用带有所有这些特性的预览版,没有任何问题,只是我对预览版的体验很糟糕,不推荐任何人。

另一种选择是完全放弃 Windows,选择基于 Linux 的操作系统,这样事情会顺利得多。只是你没有像在 Windows 中那样的漂亮的 GUI 安装程序来处理所有的事情。

在我的下一篇文章中,我将讨论如何在没有 conda 的情况下,在 Linux 中从头开始设置您的深度学习环境。

关于数据科学和机器学习的其他包的想法:

在这篇文章中,我只介绍了 Tensorflow、PyTorch 和 Jupyter 工具的安装。您可能需要安装工作流程所需的所有其他组件。

结论

我希望这篇文章对你有用。希望这有助于你毫无问题地建立你的深度学习环境。如果你遇到任何问题,我强烈建议你去 StackOverflow 和 Nvidia 论坛看看。还有关于 PyTorch 和 Tensorflow GitHub 库的讨论。

我也会在未来写更多的教程和安装指南。你可以在 Medium 上关注我,不会错过任何事情。你也可以跟着我,

推特——LinkedIn——GitHub——Kaggle

非常感谢一路阅读。祝您愉快!

通过行为细分让您的企业走向成功

原文:https://towardsdatascience.com/setting-your-business-up-for-success-with-behaviour-segmentation-74cf675ef18b?source=collection_archive---------36-----------------------

查尔斯·德鲁维奥在 Unsplash 上拍摄的照片

数据是任何组织的宝贵资产之一。它真的有可能成为下一个石油。然而,拥有大量数据并不总是意味着商业成功。拥有相关数据并知道如何使用它才是有效的。

大多数企业的增长都依赖于客户。人们可能会认为,企业将围绕与客户相关的数据制定计划和战略。与客户相关的数据是企业成功的关键。令人惊讶的是,一些商业目标和指标不包括客户行为。他们考虑的是其他不同领域的增长,而忽略了一个决定他们业务成败的因素。这使得团队将精力花费在收效甚微的活动上。因此,管理层无法实现其目标。

在本文中,我们探讨了客户行为细分的重要性。我们讨论易于遵循的策略,并探索行为细分系统。我们还研究了行为细分如何推动业务增长和成功。

关键外卖

阅读本文后,您将能够:

定义你最初的 6 个 KPI,这样你可以让你的团队保持专注。

了解如何确定是什么增加了你的活跃用户数量。

确定什么能帮助你的营销、产品和开发团队。

开始创建细分市场的具体内容,最大限度地发挥您的营销努力。

通过数据驱动的、针对具体细分市场的增长实验,搞清楚什么行得通,什么行不通。

帮助您摆脱盲目创建内容或活动。

“知道谁是你的客户固然很好,但知道他们的行为更好。” —乔恩·米勒。

定义问题

了解客户应该是每一个以客户为中心的企业的目标。企业应该在理解客户行为、动机因素和影响的基础上茁壮成长。这有助于企业了解客户如何与他们的产品互动。有了这些知识,企业可以影响客户的旅程,衡量成功,同时推动业务增长。适应客户观点的数据驱动方法可以影响客户旅程。

企业在收集和使用数据时会遇到一些挑战。一些组织拥有有效的数据收集策略和系统。在某些情况下,这些组织缺乏利用这些数据的工具。集成大量不同的数据成为这些组织的一个棘手问题。因此,他们坐在有用的数据,对他们来说是无用的。其他组织缺乏收集足够有用数据的方法。由于分散的努力,这两种情况都可能导致增长不佳。

增长和扩展依赖于许多不同的因素。一些组织关注除客户行为之外的一些因素。他们把顾客的行为留给机会和假设。对客户行为做出假设是一个巨大的谬误。以客户为中心的历史数据应该是衡量进展的工具。它应该有助于组织分析什么可行,什么不可行。这指导了组织的决策,例如,在新产品开发中。利用这类数据的组织往往会获得成功。

作者的不同客户群/图片

除了数据管理,还有目标和指标的问题。关键绩效指标(KPI)衡量组织或产品的表现。KPI 可以帮助组织确定其成就和衡量增长。这些指标依赖于有限的数据,这排除了客户行为的关键方面。一些组织关注这些和其他指标,忽视客户行为。这可能会导致注意力分散,让团队非常忙碌,但无法达成目标。此外,过多的 KPI 可能会将公司的关注点从以客户为中心的角度转移到团队管理的角度。

有很多关于客户细分和个性化的讨论。企业寻求增强客户体验的方法,同时以组织发展为目标。培养客户参与度和忠诚度并不是一件容易的事情。这些函数中的大多数都是数据相关的。

定义行为细分

根据 Jan Teichmann 的说法,“行为细分是指利用从客户行为中获得的洞察力,通过他们的行为而不是他们是谁来理解客户。他继续将行为细分定义为“一种客户细分形式,它基于客户在与公司/品牌互动或做出购买决定时表现出的行为模式。”(Designandtechnologydepartment,Bronhiggs and Follow,2020)。行为细分根据客户与组织的互动对客户进行分类。

Deasi (2020)在一篇名为 10 种了解客户的有效行为细分方法的文章中列出了 10 种行为细分方法,简要讨论如下:

  1. 购买行为

购买行为研究顾客购买时的各种趋势和行为。顾客决策和购买行为模式的动机有助于预测未来的购买。组织可以识别购买障碍,并努力消除购买障碍。

2。 谋取利益

处理理解顾客寻求什么好处。识别重要的好处对组织来说是很有帮助的。

3。 客户旅程阶段

客户可能处于与组织互动的不同阶段。这确保了更好的营销和产品定位。

4。 用法

客户使用产品的时间和互动的频率。

5。 时机或时机

客户最有可能购买或参与产品或服务的时间。星期几、一周的时间等。可能是一个重要的因素。了解购买之间的时间间隔也很重要。

6。 顾客满意度

顾客对产品的态度很大程度上反映了他们的满意度。满意率可以帮助组织更好地制作他们的销售和营销信息。知道满意的顾客和不满意的顾客是有用的。不满意的客户比他们提供的改进信息重要两倍。

7。 顾客忠诚度

当一个组织知道哪些客户是忠诚的,它就可以想办法确保他们保持忠诚。留住现有的忠诚客户比寻找新客户更有益。向这些客户提供特殊服务和特权可以让他们开心。组织还可以识别不忠诚的客户以及不忠诚背后的原因。

8。 利益

识别不同的客户兴趣可以帮助组织打造个性化的体验。此外,组织可以确定潜在的兴趣领域。

9。 参与度

这比使用水平要宽泛得多。它定义了客户对产品或服务的参与程度。

10。 用户状态

这是客户参与产品或服务的水平。例如,客户端可以被分类为非用户、预期用户、首次用户、常规用户或叛逃者/被搅动的用户。这样,就更容易确定是什么触发了客户端从一种用户状态转换到另一种用户状态。有了这些知识,组织可以更好地优化其工作和资源。

由于技术进步,处理大量不同的数据成为可能。。在 Jan Teichmann 的文章中, AI 符合市场细分模型,他指出

“在数据驱动的个性化兴起之前,大多数系统只能处理少量的细分市场,因此目标定位仅限于一般的受众细分。”

行为细分的好处

它帮助组织识别和认可客户行为。

组织可以了解客户如何与他们的业务或产品进行交互。

它提供了衡量成功和影响的准确指标。

通过将目标与关键结果分离,组织可以更好地管理进度。精简、规划和时间框架变得易于管理。

行为细分有助于阐明组织希望实现的目标。

它帮助 OKRs 适应现有的实践、敏捷流程和客户开发。

它有助于澄清和重新定义成功的衡量。

当团队清楚他们在做什么时,这就减少了计划周期。

它有助于激活和留住客户。

帮助组织关注重要的事情。

实施行为细分

规划用户生命周期是实施行为细分的关键组成部分。这不是一次性的过程。持续研究和将用户或客户行为重新应用到生命周期定义中是至关重要的。这些生命周期定义成为行为部分。大多数公司都犯了依赖人口统计细分的错误。他们错过了可能决定或破坏其产品增长的关键因素,或对其业务扩展至关重要的关键因素。平衡客户行为数据与其他商业目标并不总是容易的。然而,将 KPI 与客户旅程生命周期保持一致可能会带来业务成功。

一些工具有助于实现上述目标。旅程分析就是这些工具之一。旅程分析是帮助理解和转变客户旅程的解决方案。虽然它们有助于扩展,但对于客户的成功也至关重要。旅程分析帮助组织从多个维度看待客户。客户互动被视为旅程的终点,而不是一次性的互动。使用旅程分析,组织可以识别和预测客户行为。跟踪和分析客户如何在每一点上与组织互动变得更加容易。通过绘制全面的数据,组织可以监控和评估哪些可行,哪些不可行,从而重新设计客户旅程并改善客户体验。

先认识自己

准确的知识是无可替代的。知己知彼,百战不殆。”——李·艾柯卡

了解组织所处的阶段对于理解最重要的指标至关重要。这有助于直接关注重要的指标。

创业公司由于数据有限,尤其有几个未知数。这使得有效利用数据和分析变得困难。从本质上来说,初创企业的特点是高风险,并带有潜在的代价高昂的教训。因此,对初创公司来说,明确自己所处的阶段非常重要。这样,it 可以专注于最重要的指标。

以下是精益分析的 5 个阶段。

第一阶段: 感同身受

在这个阶段,组织已经确定了值得解决的问题。将会生产出一种产品或服务来解决这些确定的问题。在这个阶段,组织可能会密切关注对其产品或服务的反应。

第二阶段: 粘性

这是当一个产品被创造和使用的时候。有持续的客户参与和相当数量的活跃用户。

第三阶段: 病毒式

这是在一个工作产品被开发出来之后,并且这个企业正在逐渐扩大它的用户基础以及它的忠实客户。满意的顾客可能会开始传播消息,分享更多关于业务、产品或服务的信息。

第四阶段:收入

在这个阶段,企业的经济学将开始变得有意义。关注更多的是价值创造和收入增长。

第五阶段: 规模

这个阶段是关于业务增长的。企业必须建立足够大的客户群。该行业的经济学也开始变得有意义。它可以继续探索扩大规模的渠道。

了解组织所处的阶段有助于识别重要的度量标准。

减少关键绩效指标的数量

KPI 的数量应该最少。平均六个 KPI 被认为是理想的。然后,这六个 KPI 可以分解为由具体活动组成的团队目标。然后,这些活动被轻松地分配给每个团队成员。每个人都应该意识到自己的角色,以及如何衡量他们的投入和成功。

在这个阶段,如何衡量成功的明确定义是至关重要的。理解和规划用户的生命周期也很重要。特定事件定义了生命周期的每个阶段。这些共同构成了行为部分。开发生命周期图可以更容易地表达客户体验。

确保每个人都在同一页上

绘制出这些细分市场后,就可以建立 KPI 了。确保所有相关人员意见一致是很重要的。这样,每个人都可以根据目标和关键成果(okr)制定成长战略。当整个团队都致力于实现他们特定的 KPI 时,组织就可以享受巨大的成功。让团队参与制定最终实现六个 KPI 的任务可能会促进更大的合作。这样,所有团队都会知道他们在做什么,并满怀热情地将他们的活动集中在特定的 KPI 上。

设定总体目标

整体目标应该是团队/公司中每个人的焦点。所有团队成员都应该以此为目标。从人力资源、UX、发展等等,所有的角色都必须以某种方式导向这些目标。每个人的日常任务和个人目标都应该与这些目标保持一致。一些人称之为北极星度量(NSM)。一个应用程序的总体目标可以是:-持续增加活跃用户的数量。

制定并更新跟踪计划

跟踪计划列出了当前事件、它们的属性和定义。必须定期更新跟踪计划。需要设计的事件可以动态添加。下面的链接包含一个跟踪计划的例子。

追踪计划举例

识别核心事件

核心事件是那些与用户生命周期相关联并构成行为细分的事件。当访问软件商店登录页面时,核心事件可能如下所示。

图片作者作者

这些事件定义了从匿名领导到试用者的变化。正如成长型营销人员所说,“他们已经在漏斗中向下移动了一步。”

a.商店/登陆页面访问

有一个单独的登录页面是有益的,因为它可以提供一个更详细的线索是谁。另一方面,也很难获得和店内页面一样多的流量。此时,有一个可以重新定位的活动销售线索。

b. APP 下载

这是指用户从商店下载应用程序。鉴于消费者受到大量应用程序的轰炸,应用程序下载对组织来说是一个很好的机会。顾客会喜欢这些功能吗?他们会继续在他们的设备上安装它吗?

c. APP 安装

安装是下载后的一个事件,构成用户第一次打开应用程序。这是决定性的一点。根据他们的体验,客户可以决定使用或不使用该应用程序。

d.登记

注册是指某人注册他们的详细信息,并成为试用者。

这是怎么发生的?

一个用户开始作为一个匿名的线索。通常情况下,他们是通过登录页面来实现的。登录页面可能会有一个对应用程序或产品进行简要描述的页面,并且通常会有一个行动号召(CTA)。行动号召可能是注册一份时事通讯或注册成为用户。一旦他们注册成为用户,这就是一个黄金时刻。他们突然从一个匿名的领导者或者仅仅是一个网站访问者变成了一个试用者!该组织现在在注册过程中收集其详细信息。焦点可以指向在用户生命周期的不同阶段移动这个特定的客户端。这些用户的反馈也很有帮助。

设置事件组。

事件组是构成特定行为段或生命周期阶段的事件集合。例如,构成活动用户的事件有:

o 查看事件

o 编辑事件

o 导出事件

o 回顾事件

定义用户生命周期

一旦制定了事件、核心事件、事件组和活动用户事件,就该定义用户生命周期了!下面的图 3 展示了一个简单的用户生命周期。

图片由作者

1。 匿名线索

这可能是一个已经与该产品互动过的人,可能还没有决定使用它。这可以是网站访问者。

2。 试用者

试用者可以是实际下载了应用程序并正在使用它的人。

3。 用户

一个用户已经不再是试用者。他们可能已经购买了该应用程序的完整版本,并且正在使用它的大部分功能。

4.被搅动的用户

流失的用户是已经停止使用该企业的产品和/或服务的先前用户。

通常情况下,我们会停留在上述 4 个阶段。上述细分不足以区分不同的客户行为。例如,活跃的试验者和不活跃的试验者之间没有区别。

试用者可能是曾经下载过应用程序但发现它不合适的人。将他们转化为积极的试用者或用户并不容易。积极的试用者——下载了应用程序,觉得它很有趣的人。他们继续使用许多功能,并继续尝试使用锁定功能。他们可能会向支持部门询问问题,也可能会进行某种交易。出于某种原因,他们没有迁移到付费版本的应用程序上。他们没有进入生命周期的下一个阶段,也没有转化为用户。要了解走向市场、内容和数字营销、产品/功能开发战略和计划是否奏效,我们需要看到更多积极的试用者。将行为方面添加到上述部分可以提供一个前沿。

初创企业和扩大规模的企业犯了一个错误,那就是将增长建立在注册和在线访客数量的基础上。有时,这些是试用者、随机访问者和匿名线索。举例来说,这一大堆数据并没有显示这些试验者中有多少人实际上是活跃的。通过将不同的用户放入一个桶中,以下相关问题仍然没有答案:

1.是什么阻碍了试用者和匿名线索成为活跃的试用者?

2.如何增加积极试用者的数量?如果我们做一个更好的登陆页面作为成长实验呢?

3.我们应该在免费/试用版的应用程序中包含一个付费功能,作为另一个增长实验吗?

4.事实上,什么会增加积极试用者的数量?

如果不了解用户行为,就不可能有有效的增长战略。因此,重新定义这些包含行为的部分至关重要。

定义行为细分

行为细分是由用户触发的事件定义的用户组。这是下一个层次的用户细分,例如,匿名线索试用者。

  1. 匿名线索

2。用户

3。试用者

4。被搅动的用户

图片由作者

上面的图 4 显示,四个细分市场包含一些行为细分市场,其定义比图 3 更广泛。这种更广泛的细分允许理解不同阶段的用户行为。更容易解决与增长和扩展相关的问题。理解行为有助于理解顾客喜欢或讨厌的特征。这可以帮助组织进行必要的改进。请记住,不满意的用户在提供关键的改进信息方面也是至关重要的。常言道,“所有的反馈,无论好坏,都有利于业务增长。”识别这些不同的用户,就更容易识别应用程序中的缺点。

将试用者与活跃试用者分开,将有助于创建符合市场需求的内容和产品功能。

转化率的增加——试用者转化为活跃试用者,然后用户转化为活跃用户——是一个很好的指标,表明产品或应用程序符合产品市场。这也有助于理解公司是否在增长。根据行为创建分段,将触发事件附加到分段,并将活动事件与非活动事件区分开,而不是简单的用户分段,这是更有益的。简单的用户细分将试用者和活跃试用者放在同一个细分市场中。很难确定一个人是否在正确的轨道上。如何判断自己是否走对了路?

下一步是根据核心事件设置生命周期定义。核心事件显示您的应用程序或产品的使用程度。基于这种用法,它们属于特定的生命周期。生命周期的每个阶段都包括行为相似的用户群。行为细分就是这样诞生的。

制定 6 个关键绩效指标

明确公司在客户行为方面的发展方向,下一步是制定 6 个关键绩效指标。一个应用程序的简单 KPI 图如下图 5 所示。KPI 是所有团队成员和相关部门的参考点。

与应用程序用户行为一致的 KPI 地图——图片由作者提供

6 KPI—仪表盘

这是整个团队,无论是财务、产品开发、市场营销、增长、销售等等。查看他们的活动是否对上述任何 KPI 产生了影响。

制定增长战略

图片作者作者

每个商人都会重申发展一个企业有多难。规划业务增长需要大量的努力。实施增长战略可能是成功与失败的区别。将 6 个关键绩效指标与行为细分相结合后,下一步是制定增长战略这包括以下计划或战略。

1.去市场

这方面指的是公司如何将产品推向市场。它概述了商业计划和营销计划等方面。它涉及产品或服务的交付和到达目标市场。走向市场计划可能有助于推出新产品或重新上市。它包括市场定义、客户、分销模式、产品信息、定位和定价。

2.内容

内容作者需要知道他们在给谁写内容。当作者知道他们为谁写作时,他们可以使用适当的语气和信息。当向活跃用户介绍一个新功能时,写作将不同于针对匿名线索。

3.数字营销

如今,数字营销是一种至关重要的营销工具。有许多数字营销策略可以考虑。技术范围从使用搜索引擎,社会媒体营销等。

4.产品路线图

产品路线图概述了组织的产品将如何满足业务目标。它有助于确定产品的发展方向,以及如何实现这一目标。在功能上,它使产品开发与业务目标相一致。产品路线图信息在协调工作中至关重要。

5.UX 研究

用户体验(UX)研究确定用户的需求、行为和动机因素。UX 研究揭示了客户的有用信息。

增长战略包括包含上述所有方面的增长实验。每个实验都列出了目标 KPI,并记录了成功目标的百分比增长,同时设置了对照组进行比较。这使得衡量什么可行,什么不可行成为可能。一个很好的例子是分析内容的影响,以及针对活跃试用者的数字活动,以转化为用户。如果 KPI 3 没有增加,那么下一步将是探索不同的方法或尝试其他方法。人们可以探索 KPI3 的另一个增长实验。将以前付费的功能添加到试用版可能是一种选择。可以监控结果,并确定对 KPI3 的影响。

设定成长日历

这是生长实验被绘制在日历上的地方,使用颜色代码来绘制活动。颜色代码的使用示例如图 5 所示。

图解生长日历彩色编码。—图片作者作者

成长日历 :

1.告知组织中的所有团队正在进行的工作。

2.通知团队每个项目的状态。

3.充当交叉参考点。如果任何 KPI 出现峰值/下降,可以参考增长日历来检查该周发生了什么。

理想情况下,实验应该提前 3 周计划好。

持续不断地研究和重新应用。

作为产品的新功能和集成,您可以将新事件设计到您的跟踪计划中,后端您的事件组以及活动用户和所有其他行为细分市场的事件列表将会发生变化。这是一个好的变化,一个有利于业务增长的动态变化。KPI 和细分市场将保持不变,但都得到了极大的优化。

持续一致的 UX(用户体验)研究的结合对于 BI 战略的成功至关重要,因此也是成功和发展的关键。

结论

传统的客户细分方法忽略了客户行为的关键方面。行为细分是商业成功战略的一部分。这使得企业能够了解他们的客户行为,并识别客户在任何给定时间的行为类别。企业可以为个别客户群定制通信、产品和行动。

一个企业的成长依赖于它的客户和团队。将 KPI 和目标与行为细分数据相结合应该是业务的重点。这确保了企业关注最重要的事情。将团队努力与客户行为结合起来是一个伟大的商业成功公式。

参考书目

Deasi,b . g .(2020)‘了解你的客户的 10 种强有力的行为细分方法什么是行为细分?“为什么要按行为划分客户?”,第 1–25 页。

Designandtechnologydepartment,f .,Bronhiggs,w .和 Follow,J. T. (2020)“人工智能符合营销细分模型”,第 1-14 页。

使用 Label Studio 建立高内容放映影像平台

原文:https://towardsdatascience.com/setup-a-high-content-screening-imaging-platform-with-label-studio-b7e5a6ebb13c?source=collection_archive---------47-----------------------

对于 HCS 来说,拥有一个注释图像数据的平台是必不可少的。在这里,我将演示如何从 Broad 注释 C Elegans 图像。

几年来,我一直在寻找一个我真正喜欢的工具,使用 web 界面来注释 HCS 图像。我用过几个工具,包括一个叫做 LabelImg 的桌面应用,我终于找到了一个检查所有叫做 LabelStudio 的盒子的工具!

Label Studio 是一个用于图像、音频和文本的注释工具。在这里,我们将专注于图像作为我们选择的媒介。

我在这个视频中讲述了这个过程。

获取数据

当然,您可以使用您自己的数据,但是对于本教程,我将使用来自Broad bio image Benchmark Collection的公开可用的 C. elegans 数据集。

mkdir data
cd data
wget https://data.broadinstitute.org/bbbc/BBBC010/BBBC010_v2_images.zip
unzip BBBC010_v2_images.zip

在系统查看器中打开时,HCS 图像通常非常暗。为了将它们用于管道的其余部分,我们必须进行两步转换过程,首先使用 bftools 从 tif - > png 转换,然后使用 Imagmagick 进行色阶校正。

cd .. # be in your project root here
# Use the bftools docker image and drop into a shell
mkdir data/tif
mkdir data/png
mkdir data/corrected-png
docker run -it -v $(pwd)/data:/home/bf/data openmicroscopy/bftools bash
cd /home/bf/data
find $(pwd) -name '*tif' | sed 's/\.tif//g' | xargs -I {} bfconvert -nogroup {}.tif {}.png
# ctrl+d to exit the container

现在,我们将使用 ImageMagick 来应用自动水平校正,以便我们可以看到我们正在标记的内容!

docker run -it --rm -v $(pwd)/data:/data \
    continuumio/miniconda3 bash
# On the image
conda install -c conda-forge -y imagemagick
cd /data
find $(pwd) -name '*tif' | xargs -I {} basename {} | sed 's/\.tif//g' | xargs -I {} convert -auto-level /data/{}.png /data/{}-autolevel.png
mv *.tif tif/
mv *auto*.png corrected-png/
mv *.png png/
# Ctrl+D to exit

如果你像我一样,收集 docker 图片作为避免在你的电脑上安装东西的一种方式,你需要偶尔清理它们。

# This will remove ALL DOCKER containers from your system
# Use with caution!
docker container stop $(docker container ls -aq)
docker system prune -f -a

如果您需要清理图像,请移除data/pngdata/tif文件夹。我们不会使用它们。

启动 LabelStudio

LabelStudio 基于项目工作,每个项目都包含任务。在这种情况下,任务是标记图像。因此,我们需要做的是将它指向一个图像目录,它将为我们配置项目。

不同的标签配置

LabelStudio 可以容纳几种不同的图像注释类型。了解更多信息的最佳途径是访问他们的模板页面,开始探索他们的游乐场。

我将假设您正在使用语义分割、多边形标记或包围盒。作为一个快速的免责声明,语义分割界面在我试用时有点小故障。在撰写本文时,它被标记为“新的”,正在积极开发中。也许当你读到这封信的时候,事情已经解决了。

这对我来说不是问题,因为我个人发现我可以使用多边形标注工具来勾勒形状,从而获得相同的功能。我还发现多边形工具更容易使用,一旦你有了多边形轮廓,你就可以把它转换成一个遮罩。

语义分割与包围盒

语义分割是指将图像中的每一个像素指定为你想要标记的东西。标注更加耗时,并且需要更多的计算资源来训练模型,但是精度会更高。

使用边界框来标记和开始使用要快得多,但是你会失去准确性,特别是当你有许多重叠的对象时。

下面的例子可以更好地解释这一点:

多边形标签

语义标签

边界框

初始化并启动脚本

抓住这个,命名为init-labelproject.sh

#!/usr/bin/env bash

# init-labelproject.sh

docker run --rm -it \
    -e PORT=${PORT} \
    -v $(pwd)/${TYPE}:/label-studio/${TYPE} \
    -v $(pwd)/data:/label-studio/data \
    -v $(pwd)/conf:/label-studio/conf \
     --name label-studio-${TYPE} \
     heartexlabs/label-studio:latest label-studio \
        init ${TYPE} --force \
        --port ${PORT} \
        --input-path=/label-studio/data/corrected-png \
        --label-config=/label-studio/conf/${TYPE}-config.xml \
        --input-format=image-dir

抓住这个,命名为run-labelstudio.sh

#!/usr/bin/env bash

# run-labelstudio.sh

docker run --rm -it \
    -p ${PORT}:${PORT} \
    -e PORT=${PORT} \
    -v $(pwd)/${TYPE}:/label-studio/${TYPE} \
    -v $(pwd)/data:/label-studio/data \
    -v $(pwd)/conf:/label-studio/conf \
     --name label-studio-${TYPE} \
     heartexlabs/label-studio:latest label-studio \
        start ./${TYPE} --port ${PORT}

一旦你有了这些运行chmod 777 *sh,让我们来标记一些蠕虫!

设置您的项目并启动 Web 界面

在下面找到您想要的配置,并启动 web 界面。

mkdir conf
# Make sure each of the xml files are in the conf dir!
cd conf

包围盒配置

抓住这个放在conf/object-config.xml里。

<View style="display: flex">
  <View style="width: 100px">
    <Header value="Pick label" />
    <RectangleLabels name="tag" toName="img">
      <Label value="Alive" background="blue"></Label>
      <Label value="Dead" background="orange"></Label>
    </RectangleLabels>
    </View>
  <View>
    <Image name="img" value="$image" showMousePos="true" zoom="true" zoomControl="true" />
  </View>
</View>

多边形配置

抓住这个,把它放在conf/polygon-config.xml

<View style="display: flex">
  <View style="width: 100px">
    <Header value="Pick label" />
    <PolygonLabels name="tag" toName="img" strokewidth="2" pointstyle="circle" pointsize="small" showInline="false">
      <Label value="Alive" background="blue"></Label>
      <Label value="Dead" background="orange"></Label>
    </PolygonLabels>
    </View>
  <View>
    <Image name="img" value="$image" showMousePos="true" zoom="true" zoomControl="true" />
  </View>
</View>

语义配置

抓住这个放在conf/semantic-config.xml里。

<View style="display: flex">
  <View style="width: 100px">
    <Header value="Pick label" />
    <BrushLabels name="tag" toName="img">
      <Label value="Alive" background="blue" />
      <Label value="Dead" background="orange" />
    </BrushLabels>
    </View>
  <View>
    <Image name="img" value="$image" showMousePos="true" zoom="true" zoomControl="true" />
  </View>
</View>

包围盒

要运行边界框界面,使用以下命令-

export TYPE="object"
export PORT="8080"
mkdir $TYPE
# you only need to run the init script once for setup
./init-labelproject.sh
./run-labelstudio.sh

并在浏览器中打开localhost:8080

多边形

要运行多边形界面,请使用以下命令-

export TYPE="polygon"
export PORT="8081"
mkdir $TYPE
# you only need to run the init script once for setup
./init-labelproject.sh
./run-labelstudio.sh

并在浏览器中打开localhost:8081

语义分割(画笔)

要运行语义界面,请使用以下命令-

export TYPE="semantic"
export PORT="8082"
mkdir $TYPE
# you only need to run the init script once for setup
./init-labelproject.sh
./run-labelstudio.sh

并在浏览器中打开localhost:8082

定制标签界面

LabelStudio 给了你很多对标签界面的控制。您也可以使用控制标签直接通过配置添加简单的表单。

我想要的是将图像标记为完整的能力,这意味着所有的蠕虫都被标记,或者无效以将其从训练中排除。我可以用下面的配置添加它。

<View>

    <!--    Begin Display the image-->
    <View style="padding: 25px;
               box-shadow: 2px 2px 8px #AAA;">
        <Image name="img" value="$image" showMousePos="true" zoom="true" zoomControl="true"/>
    </View>
    <!--    End Display the image-->

    <!--    Begin display labels-->
    <View style=" padding: 25px;
               box-shadow: 2px 2px 8px #AAA;">
        <View style="">
            <Header value="Choose Phenotype"/>
            <PolygonLabels name="tag" toName="img" strokewidth="2" pointstyle="circle" pointsize="small"
                           showInline="false">
                <Label value="Alive" background="blue"></Label>
                <Label value="Dead" background="orange"></Label>
            </PolygonLabels>
        </View>

        <View style="">
            <Header value="Check when the image is complete. If the image is not suitable for training choose invalid instead."/>

            <Choices name="complete" toName="img" choice="single">
                <Choice alias="complete" value="Complete"/>
                <Choice alias="invalid" value="Invalid"/>
            </Choices>
        </View>
    </View>
    <!--    End display labels-->

</View>

为了得到你想要的精确布局,你可以在这上面多下功夫。宽度、高度和其他 CSS 变量都可以通过配置进行配置。确保重新启动服务器以查看您的新配置!

每个控件都有一个名称name,它必须是唯一的,还有一个目的地toName

<Choices name="complete" toName="img" choice="single">
# ...
<Image name="img" value="$image"
# ...
<PolygonLabels name="tag" toName="img"

处理标签输出

每个输出都在您的project-dir/completions中,在那个目录中,每个图像都有一个 json 文件。你会看到路径completions,然后会有一个results的数组。输出格式和具体规格可能会因您的配置而异,因此请务必使用您自己的配置进行验证。

以下是一个面标注输出示例。我已经添加了注释,它不再是有效的 json,所以不要试图解析它。;-)

{
## Corresponds to the name on the Polygon Control
    "from_name": "tag",
## Randomly generated ID 
    "id": "bUgnJpbBgC",
## Height and Width of the Image
    "original_height": 520,
    "original_width": 696,
## Task Variable
    "source": "$image",
## The to portion of the control
    "to_name": "img",
## Control Type
    "type": "polygonlabels",
    "value": {
## Points of the polygon
## These can be read into a matplotlib.Path object for parsing
        "points": [
            [
                71.25434944790884,
                27.052753770458885
            ],
            [
                68.9321022931952,
                28.148466100859682
            ],
            ... More labels
        ],
        "polygonlabels": [
        ## ITS ALIVE!
        ## This is one of the phenotypes
        ## The phenotypes were either alive or dead
            "Alive"
        ]
    }
},

这是我们用完全/无效创建的“表单”的一个示例。

{
# This is the name from the control
    "from_name": "complete",
    "id": "PZru1lZMeo",
    "to_name": "img",
    "type": "choices",
    "value": {
        "choices": [
        ## This image as marked as invalid!
        ## Don't use it for training!
            "invalid"
        ]
    }
}

这是事情变得有趣的时候,因为现在您有了一个带有可解析输出的可配置接口,您可以开始为训练创建健壮的管道。

进一步的想法

当您旋转界面并开始标记时,您会看到 LabelStudio 将您的数据发送到{polygon,object,semantic}/completions/*.json。这些只是数据文件,然后您可以使用它们为 Tensorflow、PyTorch 或 Keras 训练模型。

假设您使用的是 Tensorflow MaskRCNN 模型。您可以使用 LabelStudio 来标记您的图像,将 JSON 文件转换成一个 TFRecord ,并进行训练。然后你可以拿起你不完美的模型,让它标记一个图像集,然后手动清理新的图像,冲洗并重复。

如果你有任何问题,请不要犹豫与我在 jillian@dabbleofdevops.com 联系。

引文

[## BBBC010:秀丽隐杆线虫活/死分析

登录号 BBBC010 第 1 版这一选择的图像是控制选择从一个屏幕上找到新的…

data.broadinstitute.org](https://data.broadinstitute.org/bbbc/BBBC010/)

“我们使用了由 Fred Ausubel 提供的秀丽隐杆线虫感染活/死图像集版本 1,可从 Broad bio image Benchmark Collection 获得[ Ljosa 等人, Nature Methods ,2012 ]。”

最初发表于【https://www.dabbleofdevops.com】

设置版本增量和自动发布流程

原文:https://towardsdatascience.com/setup-version-increment-and-automated-release-process-591d87ea1221?source=collection_archive---------5-----------------------

我将向您展示发布过程和版本增量的自动化有多容易

照片由扬西·敏Unsplash 上拍摄

我热衷于过程自动化,并且我坚信在开发阶段对过程自动化的时间和金钱投资是首要需求,无论项目持续多长时间。当您投资于流程自动化时,您将进一步大幅降低维护费用。

我认为 ML 文章中没有适当涉及的一个主题是发布过程自动化和项目版本增量。我不想在这个帖子中讨论可能的发布选项,这不是关于它的。在这里,我们将讨论如何设置 CI/CD 工具的发布流程(Bitbucket 管道、Gitlab 管道等)。)我认为可以肯定地说,在大多数情况下,release 是一个文件或一组文件,它们将以某种方式集成到客户端现有的解决方案中(无论它是一个包含 spring boot 应用程序的 jar 文件,一组用于模型训练和预测的 python 脚本,还是一个运行核心应用程序的 docker 映像)。问题陈述:我们希望管理产品版本,我们希望能够返回到具体的版本,以便能够测试和诊断生产中发生的问题。

版本控制

首先,让我们定义版本字符串中的数字是什么意思。

版本字符串

从语义版本定义(【https://semver.org/】T4)

给定一个版本号少校。MINOR . PATCH-pre _ release-label,递增:

  1. 主要版本当您做出不兼容的 API 更改时
  2. 以向后兼容的方式添加功能时的次要版本
  3. 补丁版本当你做向后兼容的 bug 修正。

预发布标签是版本的占位符,在发布前保留。

这是一个最佳实践定义,但是当然,您可以选择自己的版本化方案。所以根据这个定义,我们需要定义三个任务:

  1. 发布并增加主要版本
  2. 释放并增加次要版本
  3. 发布并增加补丁版本

下一步是定义除了 git 标记之外,如何在 GIT 历史中表示发布。有几种技术可以实现这一点,最流行的是分离发布分支或分离提交。在本帖中,我们将讨论分离提交,因为它更容易自动化(不需要合并)。

分离提交

让我们从理论开始。分离提交不属于任何分支,只能直接指向。在不知道提交散列的情况下,如何在 git 历史中搜索它?你只需要给它分配一个 git 标签。然后,您可以在任何 VCS UI 中通过标签过滤 git 历史。

版本文件

不知何故,你必须保持实际的版本字符串。最简单的方法是将它保存在存储库根目录下的文本文件中。版本文件的策略:

  1. 不能手动更改文件内容
  2. 它不能在特征分支中改变(最佳实践是创建一个流水线步骤,它与主步骤进行比较)
  3. 文件仅在发布后更改,并自动直接提交到主分支。

设置 CI/CD 管道

对于您的 CI/CD 管道文件,您必须添加三个定制/手动步骤/作业,它们将执行 release 和适当的增量。并选择性地添加步骤/作业,该步骤/作业仅在功能分支上运行,并检查版本文件是否根据主文件进行了更改。

Bash 脚本检查版本文件是否相对于主文件发生了更改:

git diff --exit-code VERSION

现在是最有趣的部分:

  1. 我们必须创建一个脚本来管理版本文件的功能:获得版本,获得版本与占位符,增加版本主要/次要/补丁
  2. 我们必须定义发布分支限制策略(发布只能在主分支上进行)并创建分离的提交推送流。
  3. 定义 CI/CD 释放步骤(这里我们将为 Bitbucket 管道和 Gitlab 管道定义它)

我讨厌写 bash 脚本。我只使用 bash 来定义高级步骤并从中运行 python 脚本,因为我坚信 bash 脚本具有难看的符号,对于经验较少的 Linux 用户来说不可读,并且从长期角度来看不可维护。fire库可以帮助你轻松编写好的 CLI-runnable python 脚本。查看我之前的帖子:

[## 创建 python CLI 应用程序的简单方法

将机器学习应用程序包装到命令行界面的简单示例

towardsdatascience.com](/a-simple-way-to-create-python-cli-app-1a4492c164b6)

版本文件管理脚本(没什么有趣的讨论,只是文件写操作):

#!/usr/bin/env python
import os
import re

import fire

pre_release_placeholder = 'SNAPSHOT'
version_filepath = os.path.join('.', 'VERSION')
version_pattern = re.compile(fr'^\d+.\d+.\d+(-{pre_release_placeholder})?$')

def get(with_pre_release_placeholder: bool = False):
    with open(version_filepath, 'r') as version_file:
        version_lines = version_file.readlines()
        assert len(version_lines) == 1, 'Version file is malformed'
        version = version_lines[0]
        assert version_pattern.match(version), 'Version string is malformed'
        if with_pre_release_placeholder:
            return version
        else:
            return version.replace(f'-{pre_release_placeholder}', '')

def write_version_file(major: int, minor: int, patch: int):
    version = f'{major}.{minor}.{patch}-{pre_release_placeholder}'
    with open(version_filepath, 'w') as version_file:
        version_file.write(version)

def inc_patch():
    version = get()
    major, minor, patch = version.split('.')
    write_version_file(major, minor, int(patch) + 1)

def inc_minor():
    version = get()
    major, minor, patch = version.split('.')
    write_version_file(major, int(minor) + 1, patch)

def inc_major():
    version = get()
    major, minor, patch = version.split('.')
    write_version_file(int(major) + 1, minor, patch)

if __name__ == "__main__":
    fire.Fire({
        'get': get,
        'inc-patch': inc_patch,
        'inc-minor': inc_minor,
        'inc-major': inc_major
    })

现在让我们开发发布脚本。首先,我们必须检查发布脚本是否运行在正确的分支上:

# Bitbucket
commit=${BITBUCKET_COMMIT:-$(git rev-parse HEAD)}# Gitlab
commit=${CI_COMMIT_SHA:-$(git rev-parse HEAD)}# Define ALLOWED_RELEASE_BRANCH in VCS pipelines secret variables.
branch=${ALLOWED_RELEASE_BRANCH:-master}

if ! git branch -a --contains "${commit}" | grep -e "^[* ]*remotes/origin/${branch}\$"
then
  echo -e "###\n### Not on ${branch}. Only ${branch} commits can be released.\n###"
  exit 1
else
  echo -e "###\n### Releasing of ${commit} on ${branch}\n###"
fi

然后你必须写一些释放的东西,如:发布 docker 图像或复制到 S3 水桶或任何你需要的。不要忘记使用正确的版本文件:

version=$(./scripts/version.py get)
version_file=VERSIONecho ${version} > ${version_file}

然后,我们必须在之前的步骤版本文件中使用 modified 推送一个分离的提交:

# Define some cool release pusher to ditinguish from amnual commits :)
git config user.name "Elon Musk"
git config user.email "elon.musk@spacex.com"

echo "Pushing detached tag of new version"
git add ${version_file}
git commit -m "Release version ${version}"
git tag  -a ${version} -m "Release version ${version} tag"
git push origin ${version}

取回主分支并使用预发布占位符增加版本:

echo "Pushing new version to ${branch}"
git fetch origin "${branch}:${branch}" || git pull
git checkout "${branch}"# Parameter of the script
release_type=${1}
./scripts/version.py inc-${release_type}

next_working_version=$(./scripts/version.py get --with-pre-release-placeholder)
git add ${version_file}
git commit -m "Incrementing working version to ${next_working_version} after ${version} release."
git push origin ${branch}

仅此而已。我们已经创建了一个干净的发布脚本。现在让我们开发 Bitbucket 和 Gitlab 管道步骤片段。

比特桶:

image:
  name: python:3.7.6-slim-buster

pipelines:
  default:
    - step:
        - name: Test version file not changed
        - script:
            - git diff --exit-code VERSION

  custom:
    release-inc-patch:
      - step:
          caches:
            - pip
          name: Release current version and increment patch version
          script:
            - apt-get update && apt-get install -y git
            - pip install fire==0.2.1
            - ./scripts/release.sh patch

    release-inc-minor:
      - step:
          caches:
            - pip
          name: Release current version and increment minor version
          script:
            - apt-get update && apt-get install -y git
            - pip install fire==0.2.1
            - ./scripts/release.sh minor
    release-inc-major:
      - step:
          caches:
            - pip
          name: Release current version and increment major version
          script:
            - apt-get update && apt-get install -y git
            - pip install fire==0.2.1
            - ./scripts/release.sh major

运行自定义管道步骤:https://confluence . atlassian . com/bit bucket/run-pipelines-manually-861242583 . html

Gitlab :

test-version-changed:
  stage: test
  name: Test version file not changed
  script:
    - git diff --exit-code VERSION

release-inc-patch:
  stage: deploy
  image: python:3.7.6-slim-buster
  caches:
    - pip
  name: Release current version and increment patch version
  script:
    - apt-get update && apt-get install -y git
    - pip install fire==0.2.1
    - ./scripts/release.sh patch
  when: manual
  only:
    - master

release-inc-minor:
  stage: deploy
  image: python:3.7.6-slim-buster
  caches:
    - pip
  name: Release current version and increment minor version
  script:
    - apt-get update && apt-get install -y git
    - pip install fire==0.2.1
    - ./scripts/release.sh minor
  when: manual
  only:
    - master

release-inc-major:
  stage: deploy
  image: python:3.7.6-slim-buster
  caches:
    - pip
  name: Release current version and increment major version
  script:
    - apt-get update && apt-get install -y git
    - pip install fire==0.2.1
    - ./scripts/release.sh major
  when: manual
  only:
    - master

运行手动作业:https://forum . git lab . com/t/git lab-ci-run-pipeline-manually/13797

就是这样!你能在我的 GitHub 上找到的所有资源:【https://github.com/mbalatsko/release-version-increment】

我希望这篇文章将是有用的和信息丰富的。期待您的反馈!

在 Visual Studio 代码中设置 Vue.js Hello World

原文:https://towardsdatascience.com/setup-vue-js-hello-world-in-visual-studio-code-15d4edccd6e2?source=collection_archive---------12-----------------------

在 Vue.js 中快速启动 Hello World 应用程序

Unsplash 上由 Austin Distel 拍摄的照片

目标

在设置好本地开发环境之后,启动一个简单的 Vue 应用程序。

这些是您将在本教程中安装的工具:

  • Visual Studio 代码(VS 代码):这当然不是创建 Vue 应用程序的要求,但它是我推荐的文本编辑器。我相信它使软件开发变得更加愉快和高效。
  • Git Bash : Git 是一个非常流行的管理源代码的工具,尤其是当你在一个大型开发团队中工作的时候。VS 代码允许您集成 Git Bash 终端,这使得将您的代码推送到 Git 存储库非常方便。此外,它允许您在模拟 Bash 环境时使用大多数标准的 UNIX 命令。
  • JavaScript 运行时环境
  • npm:节点包管理器。这与 Node.js 一起使用,以便我们可以轻松地共享打包的代码模块。

下载 VS 代码

Visual Studio 代码下载稳定版本。

这是一个非常简单的下载。微软在简化这个应用程序的安装过程方面做得很好。

在 VS 代码中使用 Git Bash

https://git-scm.com/downloads下载适用于您特定操作系统的 Git Bash。

当你点击 Git 安装程序时,我建议使用所有默认的安装设置,除非你真的知道你在做什么。

我们现在将 Git Bash 作为一个集成终端添加到 VSCode 中。

  • 在 VS 代码中打开一个新的终端(Ctrl + Shift +`)或者终端→新终端。
  • 打开命令选项板(Ctrl + Shift + P)或视图→命令选项板。
  • 键入“终端:选择默认外壳”。
  • 您应该会看到下面的选项:

  • 选择 Git Bash。
  • 在终端窗口中选择+按钮。

您应该会看到类似这样的内容。

检查点 : 输入下面的命令,确保已经正确安装了 Git。

git --version

根据您安装的版本,这应该会出现。

安装 Node.js

去这个链接下载: Node.js

我选择了“推荐给大多数用户”选项,然后使用 Node.js 设置中的所有默认设置。

检查点:安装完成后,在命令行中输入:

node -v && npm -v

它应该是这样的(你的版本可能比我的更新):

如果您成功安装了 Node 和 npm,请跳到下一节。

如果它没有出现在你的 Git Bash 中,不要烦恼!重新启动计算机。

如果这不起作用,请在 PowerShell 中键入相同的命令,或者只在 Windows 命令行中键入,您应该会在那里看到它。

要使用 Git Bash,您需要将它添加到您的路径中。该路径告诉您的操作系统在哪里寻找可执行文件,以响应来自用户的命令。下面是在 Windows 上如何做到这一点:

  • 打开“查看高级系统设置”。
  • 单击“环境变量”。
  • 在系统变量下,选择路径,然后选择编辑按钮。
  • 添加这个 C:\Program Files\nodejs\。
  • 如果上述文件路径不正确,您可以通过在 Windows 命令行中键入以下命令来轻松找到它:
where node
  • 在检索到节点目录的正确路径并将其添加到 path 系统变量后,选择“确定”。
  • 重新启动计算机。

检查点:现在,尝试在 Git Bash 中键入以下命令:

node -v && npm -v

安装 Vue

在命令行中键入以下命令。

npm i -g @vue/cli

完成后,我们将创建我们的项目:

vue create hello-world

我选择了预设

接下来,将目录切换到新项目中,并启动它!

cd hello-world && npm run serve

导航到 localhost:8080,您应该会看到类似这样的内容:

就是这样!我们做到了。

回顾

您已经安装了以下工具,可以开始创建 Vue.js 应用程序。

  • 虚拟代码
  • 饭桶狂欢
  • 节点. js
  • npm
  • Vue CLI

恭喜你。

赖安·格里森的更多故事

[## Node.js 与 Spring Boot——你该选择哪一个?

轻松点。Spring Boot。对吗?没那么快…

medium.com](https://medium.com/better-programming/node-js-vs-spring-boot-which-should-you-choose-2366c2f76587) [## 是时候忘记反应,加入苗条的潮流了吗?

一场真正的泰坦之战(苗条还能算泰坦吗?)

medium.com](https://medium.com/better-programming/is-it-time-we-forget-react-and-jump-on-the-svelte-bandwagon-4848bb5d0839) [## 我如何使用 AWS Lambda 让我的女朋友微笑

开始这个有趣的小项目来提升你周围人的精神

towardsdatascience.com](/how-i-used-aws-lambda-to-make-my-girlfriend-smile-61194596f2d)

在树莓派上设置您的家庭 JupyterHub

原文:https://towardsdatascience.com/setup-your-home-jupyterhub-on-a-raspberry-pi-7ad32e20eed?source=collection_archive---------5-----------------------

从家中的任何设备启动笔记本。一个家庭中心。

作为一名数据科学家,我每天都使用 Jupyter 笔记本。有时在本地我的笔记本上,有时通过 JupyterHub 在服务器上。但是为什么不把两者结合起来,在树莓派上运行 JupyterHub 呢?这样,家庭中的每个人都可以通过浏览器从每台设备启动笔记本电脑。数据总是留在家里,随着 Raspberry Pis 变得越来越强大,我们实际上可以在它上面进行真正的数据科学。

我平板电脑上的一点机器学习。旁边:树莓派和咖啡。

目录

  1. 准备 Python 环境
  2. 安装 JupyterHub
  3. 设置为系统服务
  4. 使用 JupyterLab
  5. 安装 Python 库
  6. 用户管理

准备 Python 环境

有许多文章描述了如何设置 JupyterHub,但是大多数都使用了 Anaconda。不幸的是,Anaconda 不支持像 Raspberry Pi 和 Miniconda 这样的 ARM 系统,而这两个系统通常被认为是一种替代方案,显然没有得到进一步的维护。所以让我们和皮普一起去。

我做错什么了吗?当我在新安装的 Raspbian Buster 中输入“python”时,它打开了“python2”。真的吗?不是 2020 年吗?所以让我们快速地将系统重定向到 python3:

sudo rm /usr/bin/python 
sudo ln -s /usr/bin/python3 /usr/bin/python

并安装 python 包管理器 pip:

sudo apt-get update 
sudo apt-get install python3-pip 
sudo pip3 install --upgrade pip

安装 JupyterHub

JupyterHub 由三个组件组成:

  • 一个单用户笔记本服务器,当系统上的每个用户登录时启动。这基本上就是你已经安装在笔记本电脑上的东西,从jupyter notebook开始。
  • 管理用户账户、认证和协调单用户笔记本服务器的中枢
  • 一个代理,它将用户请求路由到集线器和笔记本服务器。

相应地,我们需要安装这三个组件。让我们从代理开始:

sudo apt-get install npm 
sudo npm install -g configurable-http-proxy

现在,我们可以使用 pip 安装 JupyterHub 和 Jupyter Notebook。因为我们想让多个用户使用 JupyterHub,所以我们需要确保安装是系统范围的:

sudo -H pip3 install notebook jupyterhub

JupyterHub 是使用 python 脚本配置的。您可以使用以下命令生成模板。然后,将其移动到主目录之外的位置:

jupyterhub --generate-config 
sudo mv jupyterhub_config.py /root

在下面的步骤中,当我们在配置文件中进行更改时,我们需要修改这个文件/root/jupyterhub_config.py。由于它位于/root,我们需要使用 sudo。

例如,默认情况下,JupyterHub 运行在端口 8000 上。可能我们已经在使用这个端口了,所以我们把它改成 8888 吧。为此,取消配置文件中以下语句的注释,并调整端口:

c.JupyterHub.bind_url = 'http://:8888'

设置为系统服务

我们的 JupyterHub 已经准备好了。我们可以从jupyterhub -f /root/jupyterhub_config.py &开始(其中-f指向我们刚刚创建的配置文件)。但是,集线器只能存活到下一次系统重启。第一次尝试还好,但是如果我们经常使用它,当然最好将 JupyterHub 设置为系统服务,这样它会在系统启动时自动启动。

要将 JupyterHub 注册为系统服务,创建文件/lib/systemd/system/jupyterhub.service,并用以下内容填充它:

[Unit] 
Description=JupyterHub Service 
After=multi-user.target [Service] 
User=root 
ExecStart=/usr/local/bin/jupyterhub --config=/root/jupyterhub_config.py 
Restart=on-failure [Install] 
WantedBy=multi-user.target

确保以ExecStart开头的行包含 JupyterHub 二进制文件和配置文件的正确位置,或者进行相应的调整。

然后,运行以下命令:

sudo systemctl daemon-reload 
sudo systemctl start jupyterhub 
sudo systemctl enable jupyterhub 
sudo systemctl status jupyterhub.service

JupyterHub 将在系统启动时启动。最后一个命令显示了状态,希望是“active (running)”。

如果是这种情况,请前往http://<address of your raspi>:8888。您应该会看到 JupyterHub 的登录页面。Raspberry Pi 的每个系统用户现在都可以登录并启动他们自己的笔记本服务器!

使用 JupyterLab

JupyterLab 是 Jupyter 项目的下一代基于网络的用户界面。它允许您以非常灵活的方式处理文档和笔记本。如果你还不相信:它甚至有一个黑暗模式…

要使用 JupyterLab 而不是传统的笔记本,我们首先必须使用 pip 安装它,然后启用扩展(使用 sudo 在系统范围内完成):

sudo -H pip3 install jupyterlab  
sudo jupyter serverextension enable --py jupyterlab --system

现在,我们必须在配置文件中添加(或取消注释并调整相应的行)以下内容:

c.Spawner.default_url = '/user/:username/lab'

安装 Python 库

为了进行实际的数据科学,我们当然需要比 python 标准库更多的东西。我们基本上有两种可能性:我们可以在系统范围内安装它们。或者,每个用户都可以将它们安装在自己的主目录中。

一个合理的方法是在系统范围内安装最常用的包,让用户自己安装其他的包。下面是如何在系统范围内安装 numpy 的一个例子。要使 numpy 工作,您还必须安装以下系统软件包:

sudo apt-get install libatlas-base-dev 
sudo -H pip3 install numpy

没有 sudo 权限的用户可以在他们的主目录中安装软件包,例如:

pip3 install seaborn

您实际上可以从 JupyterLab 中打开一个终端,因此没有必要为“普通”用户设置 ssh 连接。只需转到启动窗口,打开一个终端。

首先打开启动窗口。从那里,您可以打开一个新的笔记本或终端。

用户管理

在我们当前的设置中,用户由操作系统管理。这意味着每一个 Raspberry Pi 的用户也可以启动他们自己的笔记本服务器。

管理员有额外的权利。例如,他们可以访问管理面板,在那里他们可以看到哪些用户登录,并启动和停止他们的服务器。管理员权限通过组来处理。例如,如果我们想指定用户“gerold”为 admin,我们将首先创建一个组(我们也可以使用一个预先存在的组)并将用户添加到其中。这在 Unix 系统中通常是这样做的:

sudo addgroup jupyter_admin 
sudo usermod -aG jupyter_admin gerold

然后,我们需要在配置文件中将该组添加为 admin-group:

c.PAMAuthenticator.admin_groups = {'jupyter_admin'}

可以在http://<address of your raspi>:8888/hub/admin下找到管理面板。

JupyterHub 管理面板。

参考

设置您自己的深度学习沙盒:快速指南

原文:https://towardsdatascience.com/setup-your-own-deep-learning-sandbox-quick-guide-9f09e140baef?source=collection_archive---------42-----------------------

如何使用 Google Cloud、Jupyter 和 Visual Studio 代码轻松设置一个强大的深度学习沙盒,并将成本控制在每月几美元(第一笔 300 美元在 Google 上)。

摄影:卡斯帕·卡米尔鲁宾在 Unsplash

像许多数据科学爱好者一样,我投身于这一领域,利用每一分钟的空闲时间学习 DS 生态系统——即 Python、Jupyter、NumPy、Pandas、Scikit-learn、Matplotlib 和少量 Seaborn。以及所有强大的 Unix 工具——VI、less、sort、cut、grep、cat、tail、head 等。–您拥有一个极其高效的框架来获取、清理和分析数据集、设计功能、运行回归模型以及构建专业视觉效果。然而,一旦你的好奇心(或工作)将你拉向“机器学习”世界的“深度学习”一端,你会很快发现——就像我一样——即使是高端的 Macbook Pro 也没有足够的肌肉来运行哪怕是最基本的卷积神经网络模型(简称 CNN)。通过学习杰瑞米·霍华德和瑞秋·托马斯的 fast.ai 课程,我很快就明白了这一点。如果您像我一样,并且您的数据科学培训资金来自您自己的口袋,那么我有一个便宜、简单但功能强大的解决方案供您使用。

首先,我承认我喜欢在我的笔记本电脑上运行所有我能运行的东西。然而,对于一些事情,我的笔记本电脑就是不行,例如,对于我的音乐创作爱好,我在我的地下室有一个增强的英特尔 i7 盒子,它运行一个音乐库服务器。但是对于训练 DL 模型来说,i7 和大量内存对你来说没什么用。你需要 GPU。而 GPU 又很贵。但是租起来不贵。有了现在市面上可以买到的云选项自助表,我的新 MO 就变成了, 不买,租

通过谷歌搜索和反复试验,我建立了一个基于 Jupyter 的客户端-服务器沙箱,使用我的 Macbook Pro 和 Visual Studio 代码作为客户端,Jupyter 服务器运行在谷歌云上的高端 Linux 实例上。结果呢?我的 DL 模型训练现在可以在几秒钟内完成。在我的 Macbook Pro 上?嗯,运行 30 分钟后,风扇不停地运转,我结束了这个过程。你明白了吗?

注: 这种方式在 Google cloud 中使用完整的 Linux 服务器。还有其他成本更低的途径,例如 Google Colab 和 Kaggle 内核。然而,通过这种方法,你获得了配置的灵活性,300 美元的信用(如果节省使用将持续一段时间),以及一些使用 Google 云平台和命令行界面的经验。

安装服务器

创建 GCP 帐户并获得 300 美元

第一步是在谷歌云平台(GCP)上创建一个账户。我将假设你已经明白了这一点,并登录到 GCP 控制台。接下来,检查以确保您获得了 300 美元的信用。在左上角点击菜单,选择计费→T5总览。在概览的右下角,您应该会看到促销积分余额。应该是 300 美元。**

创建您的虚拟机服务器

GCP 现在有一项专门为运行 Jupyter 笔记本电脑配置虚拟机服务器的服务。点击 GCP 菜单(左上角)并向下滚动到人工智能部分。然后选择 AI 平台→笔记本

从笔记本实例屏幕选择顶部的新实例。这个菜单有许多选项,包括一些测试和实验选择。我会选择 PyTorch 1.4 和一个 NVIDIA Tesla T4 GPU。

下一个屏幕显示选项。在这个练习中,我将使用默认值。自定义按钮允许您向引导驱动器添加更多磁盘空间,添加 GPUs RAM 等。默认费用为每小时 0.382 美元。Google E2 实例在使用一分钟后按秒计费。这个默认配置每小时运行 38.2 美分。那是 785 小时的免费使用。

一旦你点击 Create, Google 将花费几分钟来配置你的虚拟机实例。完成后,您将看到如下屏幕。

现在,您拥有了一个功能齐全的 Jupyter 笔记本,它具有强大的 GPU 来支持 DL 模型构建。点击实例名称旁边的打开 JUPYTERLAB 。您的浏览器中将会打开一个新标签页,并打开一个 Jupyter 笔记本。界面非常简单。您可以浏览文件系统、创建 Git 存储库或启动终端会话。

在这个阶段,你已经有了一个功能齐全、功能强大的 DL 沙箱。然而,这不是一种经济有效的工作方式。您的新虚拟机实例每秒钟都在消耗您运行该实例的 300 美元。我更喜欢在我的 macbook 上本地完成我所有的数据收集、特征工程和初始回归工作。然后,当我清理和准备好我的数据集,并且我正处于尝试和适应 DL 模型的阶段时,我启动我的虚拟机实例,连接,运行我的模型,获得我的结果,然后关闭实例。为了有效地执行这个工作流,我现在将介绍几个步骤。

停止并启动您的虚拟机实例(在继续之前执行此步骤)

返回笔记本控制台并关闭您的实例。

T ip: 转到账单部分,在 预算&提醒 下创建一个预算,当你达到 1 美元的使用量时,它会向你发送电子邮件。

为远程 HTTP/HTTPS 访问配置虚拟机实例

要打开对 VM 实例的远程访问,您需要做两件事。

第一步。打开对虚拟机实例的 HTTP 访问。从主控制台菜单中的计算部分,选择计算引擎→虚拟机实例

然后从列表中单击您的实例。将显示您的实例的详细信息。我们需要在这里做两个改变。点击顶部的编辑,向下滚动并选中防火墙部分的两个 HTTP 框,然后滚动到底部并点击保存

第二步。遵循下面的菜单,然后单击防火墙控制台顶部的创建防火墙规则

在以下两个屏幕中输入注释字段。

您的防火墙规则现在应该处于活动状态。如果不是,您将在接下来的步骤中知道。

第三步。停止您的虚拟机实例。返回笔记本控制台,点击实例旁边的复选框,并点击停止

使用 Google Cloud SDK 管理虚拟机实例

步骤一。第一步是在你的本地计算机上安装 SDK。下面是谷歌为 MacOS、Windows 和 Linux 下载和安装 SDK 的说明。确保您遵循所有步骤,包括将 SDK 放在您的路径中。

第二步。从终端运行以下命令,初始化 SDK。

> gcloud init
...> You must log in to continue. Would you like to log in (Y/n)?

系统将提示您登录。当您按下 Y回车键 时,您将被重定向到一个谷歌网站以登录您的帐户。成功登录后,您应该会返回到终端会话,系统会提示您选择一个计算区域。

> Do you want to configure a default Compute Region and Zone? (Y/n)?

选择 Y 。在前面的一个屏幕截图中,我建议记下您的实例名和创建它的地区。在列表中找到显示的区域,并输入其索引号。完成后,运行以下命令。

> gcloud config list

您应该会在终端窗口中看到如下内容。

第三步。在我们离开虚拟机实例之前,我们将其关闭。现在让我们使用 SDK 重新启动它。下面是命令。用实例名替换实例名

> gcloud compute instances start **inst_name**

现在让我们练习停止实例。下面是命令。

> gcloud compute instances stop **inst_name**

这可能需要几分钟,所以让它运行吧。在小旋转完成后,你应该得到这个结果。

一旦你看到 …done 然后再次启动你的实例,让我们继续。

第四步。连接到实例并完成服务器端设置的时间。输入以下命令并用您的实例替换 inst_name

> gcloud compute ssh **inst_name**

系统将提示您输入密码。这是您最初创建的帐户密码。接下来,您将看到如下屏幕。

好了,我们快到了。只需对 Jupyter 进行一些配置更改,然后我们将能够连接 Visual Studio 代码并运行模型。耶!😎

配置 Jupyter 笔记本服务器

第一步。为笔记本创建文件夹。这是 Jupyter 存储笔记本文件的地方。我还建议创建两个子文件夹,当我们运行下面的示例模型时,它们的用途就变得很清楚了。

> mkdir jnotebooks
> mkdir jnotebooks/data
> mkdir jnotebooks/pics

第二步。创建 Jupyter 配置。这就产生了一个。jupyter 文件夹下你的根目录。

> jupyter notebook --generate-config

现在是一个有点棘手的部分。我们需要在文件中配置一些 Jupyter 参数。jupyter/jupyter _ notebook _ config . py。我推荐使用 vim 。在编辑文件之前,通过执行 pwd 记下你的根路径。这是参数。所有这些参数都已经在文件中。但是,它们被注释掉了。它们需要取消注释和修改。

c.NotebookApp.ip = '*'
c.NotebookApp.port = 8888
c.NotebookApp.notebook_dir = '/home/username/jnotebooks'
c.NotebookApp.open_browser = False

记得我们创建了 jnotebooks 文件夹。输入 notebook_dir 参数的完整路径。

这里有一个简短的你需要的命令清单。

第三步。设置一个 Jupyter 密码。这是可选的,但是强烈推荐,因为我们刚刚打开了 HTTP 访问。从命令行输入以下内容,然后输入您的密码。你必须在每次从 VSC 访问这个服务器时输入这个,所以我建议不要在这里走极端。

> jupyter notebook password

第四步。这里是最后一步。让我们启动 Jupyter 笔记本服务器。下面是命令。

> jupyter-notebook

还有哒哒!您应该会看到如下所示的内容。

如果你的屏幕与此不太相似,那么按下 Control-c 终止这个过程,并返回检查 Jupyter 配置文件中的四个参数。

安装客户端

我是 Visual Studio 代码的忠实粉丝。微软在一段时间前开源了它,从那以后它迅速发展成为一个非常用户友好和功能强大的编辑器。我觉得很酷的是,它现在完全支持 Jupyter 笔记本。我个人不喜欢在工作模式下用浏览器运行笔记本。我更喜欢我用于 Python 和 Java 的真正的代码编辑器(希望 Swift 很快会得到支持)。在 VSC,我可以在笔记本上建立我的模型,然后轻松地导出到 Python 文件中,开始将我的项目生产化,所有这些都在同一个编辑器中完成。闲话少说。让我们连接到我们的服务器并训练一个模型。

第一步。安装和设置 Visual Studio 代码。如果您使用的是 Anaconda 发行版,那么您就万事俱备了。蟒蛇和 VSC 合作得很好。否则,单击此处的获取您的操作系统的最新版本。VSC 本机支持 Jupyter,所以没有什么额外的需要安装。

第二步。打开 VSC,创建一个新的 Jupyter 笔记本。最简单的方法是使用命令浏览器。在 MacOS 上命令是 shift+command+p 。然后输入Python: Create New Blank Jupyter Notebook

第三步。连接到您的服务器。当你启动你的服务器时,你记下你的外部 IP 地址了吗?你在这里会需要它。再次通过 shift+command+p. 进入命令浏览器,然后输入命令Python: Specify local or remote Jupyter server for connections

你接下来会看到这个。选择现有的。

这里是您需要虚拟机实例的外部 IP 地址的地方。

在上面输入你的 http 地址并按下回车键后,VSC 有可能需要重启。如果发生这种情况,则关闭 VSC,再次启动它,然后按照此步骤 3 返回至此。键入一些测试 Python 代码并执行单元。VSC 将代码发送到服务器,并显示返回的结果。然后你会在右上角看到你的 Jupyter 服务器地址,如下图所示。

成功了!现在是时候享受真正的乐趣了!

有趣的时间——训练一个 DL 模型

我相信每个数据科学黑客、程序员和专业人士都熟悉 Kaggle 的庞大数据集。这就像数据科学的“你好世界”。我也摆弄过这个数据集。我只是运用了基本的推理,比如“假设所有的人都会死”。只用几行代码就能得到一个普通的分数。为了好玩,我做了很多特性工程,然后应用了所有的 Scikit-learn 模型和 Xgboost。然后,为了真正的乐趣,我想我会应用一个 DL 模型。我的型号在 Github 上有。我建议跟随查看工作流程。

第一步。从 Github 这里获取模型。

第二步。将 VSC 切换到本地 Python 实例。 shift+command+p 后跟Python: Specify local or remote Jupyter server for connections然后从菜单中选择默认。这将强制重新加载 VSC (希望这种重新加载的需求在未来会消失)

第三步。在 VSC 打开文件titanic _ feature _ creation . ipynb,执行每个单元格。最后一个单元格将把文件titanic _ train _ wrangled . CSVtitanic _ test _ wrangled . CSV写出到名为 data 的子文件夹中。这两个文件必须复制到您的虚拟机实例中。

步骤四。将数据文件复制到虚拟机实例。在从 Github 获取的 titanic 文件夹中,执行以下命令。用实例名替换 inst_name

> gcloud compute scp ./data/*.csv **inst_name**:~/jnotebooks/data/

第五步。将 VSC 连接到您的服务器。sshift+command+p后跟Python: Specify local or remote Jupyter server for connections然后从菜单中选择您的服务器。这将迫使 VSC 重装上阵。

第六步。打开文件titanic _ model _ evaluation _ CNN . ipynb。请注意,在第一个单元格中,读取的数据文件。您在本地创建了它们,然后将它们转移到您的 VM 实例。

第七步。执行所有单元格,生成一个 submission.csv 文件。

注意事项

免责声明:标题为的单元格将特征转换为方形 PNG,只是将两个数据文件的每一行(或记录)转换为图像的一种简单方法。有许多更好的方法来翻译 DL 模型的数据。在这次演示中,我想保持最基本的简单。所有创建的图像都存储在服务器上名为 images_titanic 的子文件夹中。

看看我们的排名吧!

步骤 1。现在让我们检索在下面显示的最后一个单元格中创建的文件 submissions.csv

下面是命令。再次用实例名替换 inst_name。

> gcloud compute scp **inst_name**:~/jnotebooks/data/submission.csv .

第二步。访问 Kaggle 的泰坦尼克号网站在这里提交你的作品。

我们表现如何?

78%没问题。还不错。然而,如果你是一个真正的 DS 实践者,你会对此一笑置之。这是过度工程化的一个极端例子。但这不是最佳深度学习模型工程中的一项练习。这都是关于如何建立一个沙箱,这样你然后就可以专注于构建最佳模型。

最后一件事。

让我成为更好的数据分析师的七本有趣的书

原文:https://towardsdatascience.com/seven-fun-books-which-made-me-a-better-data-analyst-4f3ea514fc00?source=collection_archive---------12-----------------------

数字中有幽默,利用它

Unsplash 上的 CHUTTERSNAP 拍摄,作者编辑

正如历史学家尤瓦尔·诺亚·哈拉里所说,电视剧《黑镜》比杰弗里·辛顿的图灵奖获奖论文更接近公众。

上周,我向我的老板做了一个关于工厂(秘密)的一些关键见解的短小精悍的演示,他在分析领域没有经验,但在规划如何运营工厂方面有经验。

他的表情告诉我“我百分之百在听,这个曲线非常有意义,这个演示一点也不无聊”。

事实证明,分析领域不仅仅是真正擅长数学和理解数据。对于数据分析师来说,将结果归纳给非数据科学专家是很重要的,这可以让有决策权的人使用这些见解。

关于那次演讲的结构和基调的许多想法来自于我在过去几年里读过的书,这些书使得数据的许多观点更容易理解。

因此,这里有一些数据科学方面的教育和娱乐书籍,会逗得每一位分析师发笑。(订单不代表任何东西)

1.如何不犯错

乔丹·艾伦伯格

与这份名单上的其他书籍相比,《如何不犯错》讲述了许多日常生活统计数据中隐藏的数学,有时还附有合理的数学公式和定理。

政治、制造恐惧的电视和“科学杂志”起初看起来是正确的,但实际上只是愚弄你的工具。

它详细讲述了概率和可能性的各种测量方法,比较术语,统计解释中的各种偏差,大数定律,以及从各种现实生活场景中带回的数字的意义。

2.被随机性愚弄

纳西姆·尼古拉斯·塔勒布

这是一本相对难读的书,除非你想在股市上赚很多钱。纳西姆·塔勒布让你和市场上的其他人意识到他们真的很愚蠢,预测股市是傻瓜的努力。

他傲慢而又滑稽地揭示了日常世界是如何充满随机性的,以及你能真正确定的事情是多么少。塔勒布列举了大量依赖随机性失败的例子,以及一个成功的预测可能是多么微不足道,他成功地让你相信,先生,你是一个白痴。

Unsplash 上的 Cathal Mac an Bheatha 拍摄,作者编辑

3.真实性

作者汉斯·罗斯林

真实是一个以此为毕生事业的人的计划。汉斯·罗斯林临终时写的。这是他离开这个星球前选择做的最后一件事。

它将矛头指向所有制造恐惧的新闻频道和制造仇恨的政治,并通过显示数字证明他们是错误的,这些数字实际上表明我们作为一个星球和物种做得相当好。

有希望。事实上,不仅有希望,还有无数值得庆祝的理由。你将在这里学习如何向统计数据的观众展示完整的画面,这样人们就可以决定对发生的事情是高兴还是悲伤。在全球范围内,什么是“好”并不那么明显。

4.快速思考和慢速思考

丹尼尔·卡内曼

《思考的快与慢》是一本关于认知偏见的杰出著作,作者是诺贝尔经济学奖得主丹尼尔·卡内曼。

作为一名分析师,光知道数字是不够的,还要知道你的客户在所有选项中会选择什么,因此如何包装信息而不仅仅是报告它。

它告诉了我们作为灵长类动物的很多情感倾向,这明显超过了我们的逻辑半脑。如果这能给你一些安慰的话,你会在下一次做出不合逻辑的选择时明白,你是由进化决定这样做的,如果你足够聪明,你可能会做出不同的选择。

5.每个人都会撒谎

塞斯·史蒂文斯·达维多维茨

当人们在看和不看的时候,我们的行为是不同的。这本书的基调是直截了当的“吐槽你的饮料好笑!”。仅仅从大卫·多维茨选择写的主题来看,比如人们在谷歌上输入的非常诚实的问题。

这可能会强化一些刻板印象,比如男性还是女性更有兴趣口头取悦异性(嗯,如果你知道我的意思),我们是否像自己说的那样投票,以及不同年龄组在人生不同阶段的优先事项中表现如何。这本书纯粹是伪装成科学的幽默。

6.魔鬼经济学

史蒂芬·列维特和史蒂芬·都伯纳

莱维特是一个古怪的经济学家,而杜布纳是一个机智的记者。不用说,《魔鬼经济学》是一本充满争议但令人愉悦的书。莱维特选择了地球上最随机的主题来应用数据科学。为什么?用乔治·马洛里的话说,“因为它在那里”。

这本书谈到了毒贩子资金链的经济学,有或没有荣誉的学校对你孩子职业生涯的影响,名字的“颜色”是否对你的未来有影响,相扑运动员与美国教师的较量,以及其他你在醒着的时候做梦都不会想到的事情。如果你想知道如何问正确的问题,那就看看这个。

7.极端值

作者马尔科姆·格拉德威尔

马尔科姆·格拉德威尔从不让人失望。他是一个好记者,也是一个伟大的故事讲述者。在读完一本格拉德威尔的书后,你可能会也可能不会学到新的东西,但你肯定会为你已经知道的东西收集一些证据。

他将门外汉的数据分析应用于数十种社交场合,直到你只能点头表示同意。它让你相信你不够好,但很棒,并从地球上最随机的地方获得数据科学的证明。如果你问了正确的问题,到处都有答案。这是你将从书中学到的东西。

数据科学中必须知道的七种统计分布及其模拟

原文:https://towardsdatascience.com/seven-must-know-statistical-distributions-and-their-simulations-for-data-science-681c5ac41e32?source=collection_archive---------4-----------------------

[入门](http://Getting Started)

假设、关系、模拟等等

卢克·切瑟Unsplash 上拍摄的照片

统计分布是一个参数化的数学函数,它给出了随机变量不同结果的概率。根据它模拟的随机值,有离散分布和连续分布。本文将介绍七种最重要的统计分布,展示它们与 Numpy 库嵌入式函数或随机变量生成器的 Python 模拟,讨论不同分布之间的关系及其在数据科学中的应用。

不同的分布和模拟

1、伯努利分布

伯努利分布是一种离散分布。伯努利分布的假设包括:

1、只有两种结果;

2、只审一次。

伯努利分布描述了一个只包含两种结果的随机变量。举个例子,抛一次硬币,只能得到“头”或者“尾”。我们也可以通过将结果定义为“成功”和“失败”来概括它如果我假设当我掷骰子时,我只关心我是否得到 6,我可以将显示 6 的骰子的结果定义为“成功”,而将所有其他结果定义为“失败”尽管掷骰子有六种结果,但在我定义的这个实验中,只有两种结果,我可以用伯努利分布。

遵循伯努利分布的随机变量 x 的概率质量函数(PMF)为:

p 是这个随机变量 x 等于“成功”的概率,它是基于不同的场景定义的。有时我们有 p = 1-p,就像扔硬币一样。

从 PMF 中,我们可以根据 x 的数值计算出随机变量 x 的期望值和方差,如果“成功”时 x=1,“失败”时 x=0,则 E (x)和 Var (x)为:

通过定义一个随机变量来模拟伯努利试验是很简单的,这个随机变量只产生两个具有一定“成功”概率 p 的结果:

import numpy as np#success probability is the same as failure probability
np.random.choice([‘success’,’failure’], p=(0.5, 0.5))#probabilities are different
np.random.choice(['success','failure'], p=(0.9, 0.1))

2、二项分布

二项式分布也是离散分布,它将随机变量 x 描述为 n 次伯努利试验的成功次数。你可以把二项分布想象成 n 个相同的伯努利分布随机变量的结果分布。二项式分布的假设是:

1、每次试验只有两种结果(像扔硬币一样);

2、总共有 n 次相同的试验(抛同一个硬币 n 次);

3、每次审判都是独立于其他审判的(第一次审判得到“人头”不会影响第二次审判得到“人头”的机会);

4、p 和 1-p 对于所有试验都是相同的(在所有试验中得到“头”的机会是相同的);

分布中有两个参数,即成功概率 p 和试验次数 n。PMF 使用组合公式定义:

我们在 n 次试验中有 x 次成功的概率就像在顺序不重要的情况下从 n 次试验中选择 x。

将二项式分布视为 n 个相同的伯努利分布有助于理解其期望值和方差的计算:

如果你有兴趣得到上面这两个方程,可以看看可汗学院的这些精彩视频。

Python 的 Numpy 库内置了二项式分布函数。要模拟它,定义 n 和 p,并设置为模拟 1000 次:

n = 100
p = 0.5
size = 1000binomial = np.random.binomial(n,p,size)
plt.hist(binomial)

我们可以得到直方图:

二项式分布,平均值约为 n*p = 50

当设置 n 等于 1 时,我们可以模拟伯努利分布:

n = 1
p = 0.5
size = 10000bernoulli = np.random.binomial(n,p,size)
plt.hist(bernoulli)

伯努利试验

3、几何分布

几何分布是一种离散分布,它模拟在重复、独立的伯努利试验中首次成功之前的失败次数(x 次失败)。例如,随机变量可以是在你得到第一个“头”之前你会得到多少个“尾”它还可以模拟获得第一次成功的试验次数(x-1 次失败),比如你要折腾多少次才能得到第一个“头”这两个随机变量的唯一区别是失败的次数。几何分布假设与二项式分布相同,因为它们都来自一些相同的独立伯努利试验。

当随机变量 x 是第一次成功前的失败次数时,PMF 为:

期望值和方差为:

当随机变量 x 是获得第一次成功的试验次数时,PMF 是:

期望值和方差为:

我们需要使用几何级数来推导几何分布的期望值和方差。在可汗学院有一个很棒的教程可以解释细节。

为了模拟几何分布,我们可以使用伯努利试验,计算第一次成功之前的失败次数,然后绘制失败次数(非常感谢 Tiffany Sung 发现了这段代码中的错误):

geometric = []
failure = 0
n=0
p=0.5while n<10000:
    result = np.random.choice(['success','failure'],p=(p,1-p))
    if result == 'failure':
        failure+=1
    else:
        geometric.append(failure)
        failure = 0
        n+=1plt.hist(geometric)
plt.axvline(np.mean(geometric),color='red')

平均值在(1-p)/p 附近的几何分布

4、均匀分布

均匀分布模型是一个随机变量,其结果发生的可能性是相等的。结果可以是离散的,就像掷骰子得到的结果,也可以是连续的,就像等车的时间。因此,根据随机变量,均匀分布可以是离散的或连续的分布。这些假设是:

1,有 n 个结果(离散的),或结果的范围(连续的);

2,结果集或范围中的所有值出现的可能性相等。

离散均匀分布很简单,很容易计算期望值和方差。对于均匀分布在[a,b]的连续均匀分布,概率密度函数(PDF)为:

使用积分,期望值和方差为:

为了模拟均匀分布,我们可以使用 Numpy 的嵌入函数并指定分布的范围。基于[0,1]处的均匀分布,我们可以生成[a,b]处的均匀分布:

#generate a random variable follows U(0,1)
np.random.uniform(0,1,size=10000)#use U(0,1) to generate U(a,b)
def uniform(a,b):
    return a + (b-a) * np.random.uniform(0,1,size=10000)

在[2,3]处均匀分布

5、正态分布

正态(高斯)分布是最广泛使用的连续分布,因为它代表了大多数宇宙情况。由于中心极限理论,许多随机变量是正态分布的,或者在将它们拟合到统计模型之前假设它们是正态分布的。正态分布有一些独特的特征:

1,均值=众数=中位数=;

2,PDF 呈钟形,对称于 x =;

3,介于[ -σ,+σ]之间的值大约占数据的 68%,其中σ是标准差,并且:

图片由百科,此处=0

正态分布的 PDF 为:

当=0 且σ=1 时,我们有一个标准正态分布,其中 PDF 简化为:

期望值和方差嵌入在正态分布的 PDF 中。期望值是平均值,即,方差是标准差的平方,σ。

为了模拟正态分布,我们可以使用 Numpy 函数:

np.random.normal(mu, sigma, 1000)

或者我们也可以用中心极限理论来模拟正态分布:

def clm(N,n):
#generate a sample from any random population N
    lis = np.random.random(size=N)
    means = []#take a random sub sample with size n from N
    for i in range(n):
        lis_index = np.random.randint(0,N,n)
        means.append(lis[lis_index].mean())
        i+=1#plot means
    return plt.hist(means)clm(10000,1000)

CLM 正态分布

6、泊松分布

泊松分布是一种离散分布,它模拟在固定的时间或空间间隔内发生的多个事件的概率。泊松分布可用于表示一小时内到达商店的顾客数量,或公司一天接到的电话数量等。如果将事件发生的次数作为成功的次数来衡量,泊松分布与二项式分布密切相关。例如,当测量一个小时内有多少辆车经过一条特定的街道时,经过的车的数量是一个服从泊松分布的随机变量。要了解汽车通过事件,可以把一个小时分解成 60 分钟,看一分钟内会有多少辆车通过,然后概括成一个小时。在一分钟内,可能不止一辆车经过街道,因此它不是一个二元随机变量。然而,如果我们把一分钟分解成 60 秒,很可能在一秒钟内只有一辆车通过或没有车通过。我们可以继续分解一秒来做出更自信的主张。然后我们可以将汽车通过视为成功事件,没有汽车通过视为失败事件,并对 3600 次试验(一小时 3600 秒)中有多少次成功事件(有多少辆汽车通过)进行建模,这是一个成功概率为 p 的二项分布,试验次数等于 3600 次。

将泊松分布与二项分布联系起来,有助于我们理解泊松分布的假设和 PMF。假设泊松分布为:

1、任何成功的事件都不应该影响其他成功事件的结果(前一秒观察一辆车不影响下一秒观察另一辆车的机会);

2,成功的概率 p,在所有区间都是一样的(这个小时和其他小时观察汽车经过没有区别);

3、一个区间的成功概率 p 随着区间变小而趋于零(如果我们在讨论一毫秒内会有多少辆车通过,因为时间太短所以概率接近零);

泊松分布的 PMF 可以从二项分布的 PMF 中导出:

二项分布

我们知道 x 是 n 次伯努利试验的成功次数,E(x)=np。如果我们将λ =E(x) =np 定义为 n 次伯努利试验的平均成功次数,则成功概率 p 可由λ/n 来估算。当 n 趋于无穷大时,PMF 变为:

经过的一些计算,我们可以得到一个新的 PMF,也就是泊松分布的 PMF:

泊松分布给出了在一个时间间隔内观察到一定数量事件的概率,给出了该时间间隔内事件的平均数。服从泊松分布的随机变量的期望值和方差都是λ:

为了模拟泊松分布,我们可以使用 Numpy 函数:

lam = 1poi = np.random.poisson(lam=lam,size=1000)
plt.hist(poi)
plt.axvline(x=lam,c='red')

λ为 1 的泊松分布

7、指数分布

指数分布是一种与泊松分布密切相关的连续分布。它是泊松事件之间时间间隔的概率分布。如果一个公司一小时内接到的电话数服从泊松分布,那么电话之间的时间间隔服从指数分布。由于指数分布与泊松分布密切相关,其假设遵循泊松分布的假设。

我们可以通过首先推导其累积分布函数(CDF ),然后对 CDF 求导来推导指数分布的 PDF。我们使用这个技巧是因为我们可以用泊松分布得到 CDF。假设我们还在观察同一条街上有多少辆车经过,现在我们关心的是随机变量ω,它被定义为当我们看到一辆车经过时,至少需要ω分钟才能观察到另一辆车经过。我们从头说起——观察第一辆车需要多长时间?假设用ω分钟观察第一辆车用ω分钟,有零辆车通过。我们知道,一分钟内在街上通过的汽车数量遵循泊松分布:

每分钟汽车数量

在ω分钟内,街道上通过的汽车数量如下:

ω分钟内的汽车数量

我们在ω分钟内观察到零辆车的概率是:

从指数分布的角度来看,我们现在已经知道花至少ω分钟观察第一辆车的概率,那么花少于ω分钟的概率是:

这是随机变量ω的 CDF,对ω求导,我们得到 PDF:

如果我们知道在一分钟内,平均下来,我们很可能观察到三辆车(λ=3)经过街道,那么预计每 1/3 分钟,我们就会观察到一辆车经过。因此,指数分布的期望值和方差为:

为了模拟指数分布,我们可以使用 Numpy 随机函数:

lam = 2
exp = np.random.exponential(lam, 10000) 
plt.hist(exp)
plt.axvline(x=lam, c=’red’)

指数分布

或者我们可以用(0,1)的 CDF 和均匀分布来模拟它。以下等式显示了该过程:

遵循准则:

rate = 1/20
inverse_cdf=np.random.uniform(0,1,size=1000)interval = [-np.log(1-u)/rate for u in inverse_cdf]plt.hist(interval)

用 U(0,1)模拟指数分布

不同分布之间的关系

正如上面部分讨论的,这些分布以不同的方式彼此密切相关:

1、伯努利分布是二项分布在 n 等于 1 时的特例;

2,当 n 趋于无穷大,p 趋于零时,np = λ,一个有限数,二项分布逼近泊松分布;

3,当 n 趋于无穷大,p 不是无限小,λ也趋于无穷大时,二项分布接近正态分布;

4,如果长度为 t 的时间间隔内的事件总数服从参数为λ的泊松分布,则随机事件之间的时间服从速率为λ/t 的指数分布。

几何分布是唯一具有无记忆性的离散分布,指数分布是唯一具有无记忆性的连续分布。无记忆属性的数学定义是:

P( X > a + b | X> a ) = P ( X> b)

您可以在此阅读更多关于该房产的详细信息。你能想到的一个含义是,如果电池的寿命呈指数分布,那么一个用过的电池就和新的一样好,只要它没死。

数据科学中的统计分布

了解不同统计分布的假设和属性无疑有助于数据科学家的日常工作:

1,蒙特卡罗模拟从从均匀分布产生随机变量开始;

二项分布是任何二元分类模型的基础;

3,所有使用最小二乘成本函数的回归模型都假设残差遵循均值等于零的正态分布;

4、正态分布的变换分布,如学生 t 分布、标准正态分布是用于进行假设检验、计算 p 值和得到置信区间的分布;对数正态分布描述数据右偏时的所有数据样本;

5,泊松和指数分布更适合模拟具有固定时间速率(λ)的事件。例如,我们可以使用泊松分布来模拟一天中有多少客户会出现在商店中,并使用指数分布来模拟两个连续的客户进入商店所需的时间。

统计分布在日常生活中无处不在。了解统计分布对于数据科学家更透彻地了解数据、进行更好的数据分析、选择更合适的模型等有着非常重要的作用。这篇文章有帮助。感谢您的阅读。

这是我所有博客帖子的列表。如果你感兴趣的话,可以去看看!

[## 我的博客文章库

我快乐的地方

zzhu17.medium.com](https://zzhu17.medium.com/my-blog-posts-gallery-ac6e01fe5cc3) [## 阅读朱(以及媒体上成千上万的其他作家)的每一个故事

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

zzhu17.medium.com](https://zzhu17.medium.com/membership)

你可能正在制造 ML 技术债务的七个迹象

原文:https://towardsdatascience.com/seven-signs-you-might-be-creating-ml-technical-debt-1a96a840fd80?source=collection_archive---------49-----------------------

以及你能做些什么

[7]

在线机器学习 ML 社区同意萌芽的 ML 产品面临的大多数问题都是工程挑战[1][2]。领先的 ML 研究者和实践者似乎一次又一次地证实,快速迭代和添加优秀 ML 特性的能力才是最重要的。承诺是,通过将您的资源投入到持续的 ML 交付实践中,可以从优秀的特性和大量的迭代中获得显著的收益;而不是专注于最新的前沿 ML 算法、技术或框架。

在这篇文章中,我们将假设你已经确信,你的企业是时候建立一个机器学习驱动的产品了。你可能在没有任何机器学习的情况下推出了你的 ML 服务。您可能还关注于指标设计和收集。此外,你已经做出决定,你想使用 ML,而不是你试图取代的不可维护的启发式噩梦。

如果你已经在那里,请继续阅读——否则,请点击这里查看如何超越 ML 项目的第 0 阶段。

ML 技术债务的早期迹象

1.您不关心基础设施,而是专注于启动复杂的初始模型

[8]

在最初的发布阶段,很容易认为团队面临的大多数问题都与 ML 有关。基本上,如果你的团队正在讨论像这样的事情,“哦,太糟糕了,我们不能使用 GPT-3 文本嵌入,这将真正提高 初始 情感分析模型的性能。”。这可能是 ML tech 债务即将到来的迹象。

如果由于关注最新的模型性能,团队不清楚如何将样本带到模型的培训阶段,或者对好的和坏的业务结果看起来有些模糊,或者团队不知道模型是离线还是在线应用,那么团队的集体意识中应该有一个红色霓虹灯闪烁的尖锐警报。

此外,在第一个计划的发布中,如果团队不能解释特性是如何流向系统的,或者模型权重是不稳定的,或者服务管道有一种复杂的方式来访问推断所必需的特性,那么不要期望后续的发布会神奇地修复这些问题。

最后,如果对 v1 模型性能的期望是正向倾斜的,那么对性能的关注将使对基础设施的关注相形见绌,基础设施建立了一个更可持续的产品市场适应学习循环。

2.您将测试 ML 组件与测试基础设施混在了一起

[9]

测试对于 ML 从业者来说是一个巨大的眼中钉。通常,ML 团队报告说没有 ML 组件就不可能测试基础设施。如果 ML 模型与基础设施的其余部分是不可分的,那么您可能会有相当多的债务需要处理。

Next ML 团队有时是外部数据源的定制消费者。很容易理解,公司里没有人希望城市代码是一次性编码的。这使得无法将从特定于 ML 的转换中获得的统计数据与任何外部数据源进行比较。

最后,另一个迹象是,当选择候选模型时,在训练模型之后,没有对模型的输出进行验证,以判断未来服务时间分数的分布是否将匹配离线训练时间分数。

成长阶段的 ML 技术债务迹象

3。你期望你正在启动的模型将是唯一的、最后的、最好的一个

[10]

一旦 ML 团队完成了第一个端到端系统,“技术现金流问题”就会开始出现。ML 团队通常发现他们自己从初始阶段就开始关注累积的债务,在初始阶段,关注的焦点是将特性添加到模型中,通过偷工减料来收集度量,以及在各种支柱上支撑服务基础设施。

在 ML Eng 行业反复报道的一个误解是,团队推出的第一个模型将是唯一的、最后的、最好的模型。有些人甚至认为,总有一天模型会停止发布。这种一劳永逸的态度通常会在团队发现所有仍将包含在模型中的特性时得到迅速纠正。虽然每天用新数据重新训练无变化的 ML 管道正在成为标准,但至少,期望在 2 年内每月或每季度发布改进的模型管道应该是 ML 团队事实上的基线。

这个阶段对于 ML 团队来说是一个激动人心的时刻;他们开始关注用新功能改进模型,调整超参数,创建新的旧功能组合,甚至重新思考他们正在优化的代理业务指标。不幸的是,这是大多数技术债务产生的地方,因为项目已经运行了一段时间,所以为了按时发布新的改进,更多的可维护性方面的问题被忽略了。

ML 管道需要一些关心和关注的迹象是团队问自己:

  • 从现有模型中移除特征有多容易?
  • 添加新功能或将它们与现有功能相结合有多容易?
  • 拥有整个 ML 管道的副本需要什么?让黑暗启动的管道发布并比较它们与主线的性能会有多难?
  • 团队是否优先考虑将昂贵的特性包含到模型中,而不是频繁地发布增量版本,并从实时用户流量中了解什么可行,什么不可行?

如果一个 ML 团队发现自己因为之前的设计和架构决定而被锁定并且不能移动,那应该是系统中技术债务增长的警告信号。

4。您将未使用的特性留在管道中,直到它们不再被使用

[11]

最有效的提高性能的方法,伟大的特性,也可以是最阴险的技术债务创造者。如果你听到你的团队说我们应该在特性转换工作中保留一个未使用的特性“以防万一”,那么这可能是 ML 技术债务正在增长的一个信号。

这种迹象与添加一个新的令人鼓舞的特性不与代码角力就无法使用的情况密切相关,因为一个未使用的特性与新特性冲突。这个标志指向了管道设计的刚性,其中特征转换可能与模型训练/服务代码过度地交织在一起。

最后,有时即使有一种干净的方法来移除未使用的功能,也没有简单的方法来区分功能的有用性,因为没有适当的过程来根据例如功能的覆盖范围和与标注的相关性来对功能的效用进行排序。

5.您正在寻找将您的笔记本电脑安排为生产流水线的方法

[12]

Jupyter 笔记本是探索和原型制作 ML 管道的神奇工具。这个社区非常棒,将来可能会有基于笔记本电脑构建可靠软件的方法,但是专家们正在慢慢反对在生产中使用笔记本电脑。

随着笔记本电脑基础技术的发展,未来可能会安排笔记本电脑并在生产中使用它们。然而,截至 2020 年[5],指导方针是从笔记本电脑中提取智能,并使用标准的集成开发环境,促进更清洁的架构、模块化、自动化测试和标准软件实践。

目前,如果您正在尝试或计划将笔记本电脑作为生产设备,这可能会工作一段时间,但您的工作效率将会遇到阻碍,因为随着时间的推移,笔记本电脑中固有的问题和技术债务会越来越多。

培训服务 ML 债务陷阱

6.在训练和服务管道之间使用两个独立的实现

[13]

这种迹象很容易发现,也很难察觉。

容易发现的一点是决定在训练和服务/评分管道之间使用不同的编程语言或者甚至不同的 ML 代码实现。这可能是一个明确的信号,表明您正在放弃任何类型的迭代,并在第一次发布后重用。让一个伞兵工程班从头开始重新实现你的分类评分系统是一个灾难。从软件的角度来看,训练代码将极大地偏离评分代码,因为他们几乎相反的关注点。培训是面向后的,错误可能会触发内部电子邮件警报,而评分最有可能是面向客户的,这将在不恰当的时候点燃你松弛的渠道。

第二个迹象特别出现在评分是在线处理操作时。虽然团队可能在训练和模型选择阶段过度优化了批处理代码,但在线处理需要系统在每个请求到达预测服务时对其进行处理。如果你没有计划如何弥合在线和离线系统处理的数据处理性质的差异,那么这也可能是潜在增长的 ML 技术债务的一个迹象,这可能会在以后困扰你。

7 .。你不能 100%确定 CI/CD 代表什么

机器学习的 CD 连续交付和 CD4ML 连续交付。

[14]

这与第三点有关。计划迭代。

连续交付[3]是一种非常适用于 ML 工程世界的软件实践。有许多迹象表明,CD 实践将帮助您发展您的 ML 产品。如果你很少在产品中发布模型,并且在等待第四季度的发布系列时,多个“改进”不断堆积,那么对新的主要发布的影响的恐惧就会不断增长。一个变更在发布系列中停留的时间越长,它是否能在产品中工作的不确定性就越大。

需要 CD 的另一个迹象是当有一个昂贵的过程来发布模型到产品中。如果项目经理正在为一个变更窗口做预算,以允许数据管道中涉及的所有团队同步,那么这个可归因于发布过程的固定成本应该被视为一个信号。

缺乏可靠的部署管道可能会导致不必要的协调,但是会降低团队成员的幸福感。他们的模型改进未被使用,未被部署,可能会消除您的 ML 工程师和最终用户之间的重要反馈循环,而大部分责任感、持续学习和有用性都来自于此。类似地,如果没有办法组织代码和部署管道,以允许频繁的 A/B 测试,那么这可能是一个信号,表明 2/3 的功能没有被用户使用[3]。

8.额外收获:你意识到 ML Eng 很像软件 Eng,但是你从来没有找到一本好书来沟通这两个世界

机器学习(ML)管道毕竟是软件管道。

我有一个独特的机会来研究这个主题,作为一个隔离项目,以便提炼和组织我多年来在这本书里学到的东西:

清理机器学习代码。

我的书:清洁机器学习代码

这本书将帮助读者应用实用的软件工程原理来防止他们在机器学习软件工艺过程中的失败。

今天给自己买一本我最新的书吧!

谢谢你的支持。

伙计们,现在就这样。

我希望这篇文章对你有用。

感谢阅读。

在外面注意安全。

参考

[1]https://developers . Google . com/machine-learning/guides/rules-of-ml

https://research.google/pubs/pub43146/

https://continuousdelivery.com/

https://martinfowler.com/articles/cd4ml.html

[5]ThoughtworksTechnology Radar vol . 23 11/2020 先睹为快网络研讨会 2 — Zhamak Dehghani — 生产搁置的笔记本电脑:https://youtu.be/CUTSnAutoAM?t=2746

【6】转到 2019 年——整体结构分解模式——萨姆·纽曼https://youtu.be/9I9GdSQ1bbM?t=571

【7】Meme 模板在这里:https://img lip . com/Meme/257455447/Leonardo-Dicaprio-pointing-in-TV。迷因文本是自我创作的

[8] 模因模板在这里:https://imgflip.com/meme/155217391/Interstellar-7-years。迷因文本是自我创作的

[9] 模因模板在这里是 https://imgflip.com/i/3jqfd0

[10] Meme 模板在这里:https://img lip . com/Meme template/228603083/odd1 sout-vs-computer-chess。迷因文本是自我创作的

https://imgflip.com/memetemplate/Two-Buttons】【11】模因模板在此:模因文字为自己创作

[12]【https://imgflip.com/meme/Drake-Hotline-Bling】模因模板在这里:模因文字均为自己创作

[13]迷因模板在这里:https://imgflip.com/memetemplate/Disaster-Girl迷因文字为自己创作

[14]模因模板 https://imgflip.com/memegenerator/Afraid-To-Ask-Andy。迷因文本是自我创作的

免责声明:本文表达的观点是我个人的观点,不一定代表我现在或过去雇主的观点。

严重性分数推导

原文:https://towardsdatascience.com/severity-score-derivation-c5e63f9ae046?source=collection_archive---------44-----------------------

解释所涉及的步骤、思考过程以及新冠肺炎严重程度评分背后的研究,以便在州和县之间进行比较

美国严重性仪表板:Tableau Public 上的新冠肺炎登录页(2020 年 9 月 9 日)

当我为新冠肺炎制作美国严重性仪表板时,有几个人问我:

“您是如何为您的新冠肺炎仪表板计算出严重性分数的?”

我解释说,这是一个相当有趣的过程,有许多尝试。在与我在 LinkedIn 上的一个密友交谈后,我意识到我所经历的过程可能会成为一篇有趣的文章。因此,我们在这里。

解决问题有很多不同的方法;数学定律、推导出的数学方程式或有用的信息表示。例如,一个 FICO 信用评分是一个有用的和有意义的代表某人偿还贷款的能力。是法律吗?不,橄榄球联盟的四分卫得分也不是。我们作为指标所依赖的许多指数,如道琼斯指数,并不是经过验证的科学事实,而是以有意义的格式表示数据的一种简明方法。

钟系列的创造者埃里克·坦普尔·贝尔说:

“抽象性,有时被当作对数学的一种指责,是它的主要荣耀,也是它最可靠的实用头衔。它也是可能从数学中产生的美的源泉”

换句话说,有时候抽象思维可以导致实践。

收集的初始数据:

可用于构建严重性分数等式的构件

COVID 仪表盘在互联网上随处可见。一个共同点是,不清楚病毒在哪里受到最严重的打击。“严重性”与死亡或感染有关吗?假设像纽约市这样的城市里的人比该国农村地区的人与他人接触更多,那么人口是否应该在决定病毒的严重程度方面发挥作用?

然后我突然想到…

“如果我能想出一种方法来表示病毒在美国每个县的严重程度,这样人们就能很容易地说出哪里的病毒对健康影响最大,那会怎么样?”

我思考了这个想法,并决定研究一下流行病学家的结论。

这项研究

对于流感爆发,公共卫生官员通常使用疫情严重程度评估框架(PSAF) 来帮助确定疫情会有多“糟糕”。它使用两个因素;临床严重性和病毒传播性。文章提到,“PSAF 是疾病预防控制中心开发的两个评估工具之一,用于指导和协调参与疫情反应的联邦、州、地方和部落实体的行动”

文章随后提到了“评估流感流行和大流行的流行病学影响的新框架” (Reed et al. 2013)。新框架详细说明了根据数据可用性、可传递性和临床严重程度指标确定疫情严重程度的 4 个方法步骤。文章还提到,在历史上,病死率(CFR)一直被使用。

另一个众所周知的疾病统计是死亡率

通常代表每 1 千或 10 万人

CDC 网站上的另一个链接指向流感风险评估工具(IRAT) 。文章解释说,“IRAT 使用 10 项科学标准来衡量与每种情况相关的潜在疫情风险。这 10 项标准可以分为三大类:“病毒的特性”、“人群的属性”和“病毒的生态学&流行病学”。”(Reed 等人 2019)。

我的评估

  • 我知道临床严重程度指标在一段时间内不会出现,也不知道为了确定病毒如何在生物学上传播而进行的研究是否充分。
  • 病死率忽略了人口规模和密度,这在不同县之间进行比较时很重要。
  • 死亡率包括人口数量,但不包括感染。

似乎没有一个衡量标准可以概括这一切。现有的总体框架和评估工具似乎侧重于病毒如何传播的性质,而不一定是“每个地区有多严重”。

既然如此,我开始头脑风暴:

“我认为决定严重程度的因素是什么,我如何整合常见的流行病学计算来赋予这个等式一些合法性?

等式尝试 1:

我读过的文章中没有一篇提到增长率。感染和死亡的增长率不同。因此,我需要将它们作为单独的实体插入。这个思路让我创建了一个感染分数和一个死亡分数,其中:

我决定将死亡分数乘以 2,以说明感染人数将多于死亡人数的事实,并且我最初决定按照指数增长公式 y = ab^x 来模拟我的方程,其中 a 将是总指标, b 将是增长率,x 将被平方。除以人群进行归一化,第一个严重性评分诞生。

方程式:

严重性等式尝试 1

等式尝试 2:

坚持指数增长的概念,我添加了阳性检测百分比(PTP) 作为总感染增长率的系数,理由是一百万次检测中有 1000 次阳性结果的县应该比 1001 次检测中有 1000 次阳性结果的县不那么严重。

随着阳性检测百分比降低了总感染增长率的影响,我认为添加病死率作为总死亡增长率的降低系数将是包含在严重性分数中的适当指标。

方程式:

严重性等式尝试 2

辅助方程:

问题:这一轮方程式出现了两个主要问题,还有一个我还没有注意到的问题。

这两个问题是:

  1. 病死率 * 总死亡人数增长率是什么意思?
  2. 阳性检测百分比 * 总感染增长率是什么意思?

我没有注意到 CFR 和 PTP 都在< 1 and most of the growth rates are also < 1. Multiplying them together essentially added nothing to my score when deaths and infections could both be in the thousands.

收集反馈

抛开这些问题,我决定收集一些关于我正在做的事情的反馈。我收到的最常见的问题是

"为什么死亡总数要乘以 2?"以及“你为什么要平方增长率?”

我的教授 Vibhanshu Abhishek 告诉我,每个分数的权重不应该由我来决定,因为每个人对如何比较感染和死亡的严重程度都有自己的偏见。

在这种情况下,我决定添加两个可以由用户调整的系数,一个是死亡系数α,另一个是感染系数β,范围在 0 到 1 之间。此外,我在中加入了人口密度,理由是人口的增加应该会降低的严重程度(因为现在每个感染/死亡只占总数的一小部分),但是人口密度的增加应该会增加的严重程度,因为人们会更频繁地接触。为了实现这个行为,人口需要在分母上,而人口密度需要在分子上。为了便于阅读,可以表示如下。

方程式尝试 3:

结合这一反馈,这些方程得出:

方程式:

严重性等式尝试 3

问题:我后来才意识到分母的问题,但是

人口被取消,分母等于面积。

仪表板创建

带着一个充满了我最初没有意识到的疑问和问题的等式,我继续前进,创建了美国严重性仪表板的第一个迭代。

美国严重性仪表板:新冠肺炎登录页面—第一次迭代—(2020 年 4 月 12 日)

基于每个州和县的严重程度的国家整体视图。我对结果非常满意。我的教授告诉我,我可能应该对方程取一个对数,以便将严重性标准化,因为分布在当前状态下是高度偏斜的。

取我的严重性分数的对数,我意识到我在我的一个表示中违反了对数的第一定律。

对数第一定律指出:

log A+log B =log AB

这意味着:

log(感染分数)+ log(死亡分数)≠ log(感染分数+死亡分数)

这提出了一个新的问题,因为死亡分数感染分数不能相乘。如果它们相乘,0(无死亡)的死亡分数将导致 0 的严重性分数,即使该州或县有数百万感染。因此,我需要将感染分数加到死亡分数上。

在对正确的对数表示进行推导之后,我终于发现了我之前提到的问题,并决定重新构建整个方程。

方程式尝试 4:

几天的实验过去了,我试着把注意力集中在为什么我首先要创建严重性分数上。

“严重性分数的意义在于能够比较县或州之间的健康影响”

我重新构建了这个等式,以说明一旦增长率为 0,意味着没有新的感染,那么产生的严重性分数将基于该县或州已达到的感染和死亡总数。

什么改变了:

  • 修复了前面提到的所有问题
  • 我意识到我应该用实际感染或死亡人数乘以增长率
  • 我意识到阳性检测百分比使等式变得复杂,无法将其与增长率联系起来。
  • 我意识到病死率包含了感染和死亡。这意味着随着感染的增加,感染分数会增加,但是死亡分数会降低,因为 CFR < 1
  • 我意识到人口严重性有着压倒性的影响。我想让人群标准化严重性分数,但我不想让它成为线性效应。我决定平方根会对更大的人口产生更小的影响,而对数会有更陡的影响。

方程式:

严重性等式尝试 4

收集反馈(第二部分)

收集了几个人的意见后,我问了一个关于严重性等式的基本问题。

“当一个县或州不再有任何感染或死亡病例时,其严重性分数应该为零还是达到最高?”

我得到了响亮的答案

“当然,如果没有更多的感染或死亡,严重性分数应该为零,这时你会说没有严重性”

思考这个答案,我意识到这很有道理。在目前的状态下,这个等式永远不会等于零,因为总死亡数和总感染数永远不会等于零。这意味着需要做一点小小的调整。

方程式尝试 5:

我决定,如果我计算过去 7 天感染和死亡的周平均值,那么如果一个县或州停止出现新的感染或死亡,他们的严重程度得分将为零。我还必须改变增长率,使其基于过去 7 天的数据。

最终方程式:

严重性等式尝试 5

这种表现感觉就像我想在这个等式中达到的完美平衡。

  • 按人口标准化的感染和死亡的包容性方程。
  • 严重性的每周快照,如果没有进一步的感染或死亡,得分为 0。
  • 包含增长率以揭示趋势案例的方向性。
  • 一个用户可调整的参数,允许感染和死亡之间的重量感觉差异。

在启动严重性仪表板整整一个月后,我现在有了一个完整的等式和一个更新的仪表板来显示它。

媒体报道

两周后,我在 UCI 的学校写了一篇关于这个项目的文章。https://merage . UCI . edu/news/2020/05/Matthew-littman-msba-20-creates-新冠肺炎-dashboard.html

两个月后,《洛杉矶时报》刊登了这篇报道。

https://www . latimes . com/socal/daily-pilot/news/story/2020-07-15/UC-Irvine-graduate-is-the-architect-of-detailed-新冠肺炎-dashboard

美国严重性控制面板:新冠肺炎登录页面(2020 年 5 月 12 日)

成品是什么样子的?

经过几个月的添加工具提示、更新、新功能、用户体验和质量检查,目前形式的美国严重性仪表板:新冠肺炎如下图所示。点击链接查看,感谢阅读!

美国严重性仪表板:Tableau Public 上的新冠肺炎登录页(2020 年 9 月 9 日)

来源:

“流感风险评估工具(IRAT)。”2019.2019 年 10 月 10 日。https://www . CDC . gov/flu/疫情-资源/国家-战略/风险-评估. htm

里德、凯莉、马修·比格斯达夫、林恩·费内利、丽莎·m·库宁、丹尼斯·博韦、阿姆拉·乌兹卡宁、安德鲁·普卢默、乔·布雷西、斯蒂芬·c·里德和丹尼尔·b·杰尼根。“评估流感流行和大流行的流行病学影响的新框架——第 19 卷,第 1 期——2013 年 1 月——新发传染病杂志——CDC。”2020 年 9 月 9 日接入。https://doi.org/10.3201/Eid 1901.120124

性很重要,为什么我知道

原文:https://towardsdatascience.com/sex-matters-and-why-i-know-712578a6857d?source=collection_archive---------22-----------------------

使用 Captum,综合梯度和 PyTorch 闪电的神经网络的可解释性。看着黑盒!

看看黑匣子,由大卫·拉古萨拍摄。

介绍

神经网络已经席卷了全世界。每周都有关于 GPT-3 如何自动完成另一项语言任务的好消息。或者在当前的疫情中人工智能是如何帮助医生的。

但是越来越多的人对人工智能的转变越来越怀疑。它选择这种治疗方法是因为它是正确的治疗方法吗?还是因为它恰好是训练集中另一个 5.29 岁患者的最佳选择?

整个群体都在警告我们人工智能中糟糕设计的含义,我们应该更好地倾听。毕竟,种族和性别相关的特征已经以歧视的方式在最近的招聘流程算法中使用了!

作为一个人工智能社区,我们如何,

  1. 确保我们建立包容性的工具。
  2. 确保我们的模特做我们认为他们在做的事情。
  3. 向他人解释我们的模型在做什么。

1、2、3 的答案是明确的可解释性!它在深度学习领域掀起了一阵风暴。让我们今天了解一下它是什么,以及如何轻松地将其集成到我们的流程中。

我们将建立一个神经网络来预测泰坦尼克号乘客的生存机会。最后,了解我们做了什么,并使用 Captum 解释我们的模型。全部使用强大的闪电框架。

Gif 总结解释了我们神经网络的学习过程。作者图片

0.进口

我们将从导入依赖项开始。

# Our ML things
import pytorch_lightning as pl
import torch
from torch.utils.data import DataLoader, Dataset

from captum.attr import IntegratedGradients
from pytorch_lightning import seed_everything
from pytorch_lightning import Trainer# Visualization
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt# Utils
from enum import Enum
import pandas as pd
from sklearn.metrics import classification_report

1.资料组

为了制作这个最小的例子,我们将使用 Titanic 数据集(一个小文件)。可以在这里下载。下载完成后,将其放入一个新文件夹“data/train.csv ..”这个数据集可能是有史以来最受欢迎的 Kaggle 数据集,因此允许我们验证我们的结果。

它包含了泰坦尼克号的 890 名不同的乘客。对于每位乘客,我们将预测他们是否幸存!

为此,我们被赋予了几个特性。

PassengerId  **Survived**  Pclass  ...     Fare Cabin  Embarked
0              1         0     ...   7.2500   NaN         S

我们将只处理其中的一小部分,即:

**Survived**  Pclass     Sex   Age  SibSp     Fare
0           0       3    male  22.0      1   7.2500

现在我们有了一个概述,让我们定义数据集。数据集是 PyTorch 中的一个类。它需要定义 3 个私有函数,init()、len()、getitem()。

如果你对此不熟悉,可以在这里 ( 1)找到一个简单的解释 。数据集)。这里的目标是做一个最小的预处理,以便稍后展示我们的解释。

**# Simple enum that helps organizing
# Not really important**
class TrainType(Enum):
    train = 1
    test = 2**# Our Custom Dataset class** class RMSTitanic(Dataset):
    def __init__(self, type: TrainType):
        file = "data/train.csv"
 **# Preprocessing**
        df = pd.read_csv(file)
 **# Select relevant fields**
        df = df[['Survived', 'Pclass',
                 "Sex", "Age", "SibSp",
                 "Fare"]]
 **# Convert Sex -> 0/1**
        m = {'male': 1, 'female': 0}
        df['Sex'] = df['Sex'].str.lower().map(m)
 **# Fix the non available vals
        # Also normalize**
        df = df.fillna(df.median())
        df -= df.min()
        df /= df.max()
 **# The first 80% are Train**
        if type == TrainType.train:
            self.df = df.loc[:int(0.8 * len(df))]
        if type == TrainType.test:
            self.df = df.loc[int(0.8 * len(df)):]
 **# We will use this later for interpretation**
        self.base = torch.tensor(df[
                                     ['Pclass', "Sex",
                                      "Age", "SibSp",
                                      "Fare"]
                                 ].mean()).cuda().float()

    def __len__(self):
        return len(self.df)

    def __getitem__(self, item):
 **# This function return the i-th elem**        row = self.df.iloc[item]
        label = row['Survived']
        features = row[['Pclass', "Sex",
                        "Age", "SibSp",
                        "Fare"]]
 **# return the (label,features)**        return (
            torch.tensor(features).cuda().float(),
            torch.tensor(label).cuda().float()
        )

这已经是我们最小的数据集了。请记住,这只是一个小的助手类。它帮助 Pytorch Lightning 施展它的魔法,因此我们可以节省更多的代码。

简短解释

我们得到的特征和它们的解释是什么。

**Pclass**   "What class is person traveling in? First being best"
**Sex**      "Male or Female"
**Age**      "How old in years?"
**SibSp**    "How many Sibiling/Spouses are there onboard"
**Fare**     "Amount in money spend"

2.模型

我们现在将构建一个简短但强大的模型。它将依次调用下面的层。

 | Name      | Type     | 
  ------------------------
0 | input     | Linear   |   
1 | r1        | PReLU    |  
2 | l1        | Linear   |
3 | r2        | PReLU    |    
4 | out       | Linear   |   
5 | sigmoid   | Sigmoid  |

我们现在将定义一个名为 MyHeartWillGoOn 的 PytorchModel。基本上只有前进功能是至关重要的。

class MyHeartWillGoOn(pl.LightningModule):

    def __init__(self):
 **# Setting up our model**        super().__init__()
 **# way to fancy model**        self.lr = 0.01
        self.batch_size = 512
        l1 = 128

 **# We send our 5 features into first layer**        self.input = torch.nn.Linear(5, l1)
 **# PRELU is just a fancy activation function**        self.r1 = torch.nn.PReLU()
 **# More Layers**        self.l1 = torch.nn.Linear(l1, l1)
        self.r2 = torch.nn.PReLU()
        self.out = torch.nn.Linear(l1, 1)
 **# Befor the Output use a sigmoid**        self.sigmoid = torch.nn.Sigmoid()
 **# Define loss**        self.criterion = torch.nn.BCELoss()

    def forward(self, x):
 **# Heart of our model**        x = self.input(x)
        x = self.l1(x)
        x = self.r1(x)
        x = self.out(x)
        x = self.r2(x)
        x = self.sigmoid(x)

        return x

    def train_dataloader(self):
 **# Load our Dataset: TRAIN**        return DataLoader(
            RMSTitanic(type=TrainType.train),
            batch_size=self.batch_size,
            shuffle=True)

    def val_dataloader(self):
 **# Load our Dataset: TEST
        # Simplification: TEST=VAL**        return DataLoader(
            RMSTitanic(type=TrainType.test),
            batch_size=self.batch_size,
            shuffle=False)

    def configure_optimizers(self):
        return torch.optim.Adam(self.parameters(), lr=self.lr)

    def training_step(self, batch, batch_idx):
 **# Here we just log some basics
        # We can look at them later in tensorboard**        x, y = batch
        y_hat = self(x)
        y = torch.reshape(y, (y.size()[0], 1))
        loss = self.criterion(y_hat, y)
        tensorboard_logs = {'loss': loss}
        return {'loss': loss, 'log': tensorboard_logs}

3.火车

PyTorch Lightning 的训练是由一个不错的小训练师完成的。

if __name__ == '__main__':
 **# Seed so we can reproduce**    seed_everything(404)
 **# Load model to GPU**    device = torch.device("cuda")
    model = MyHeartWillGoOn().to(device)
 **# Make the Trainer do the work**    trainer = Trainer(max_epochs=20, min_epochs=1, auto_lr_find=True, progress_bar_refresh_rate=10)
    trainer.fit(model)
 **# Accuracy #ToBeMeasured**    ts = RMSTitanic(TrainType.test)
 **# Bit of Hacking**    x = torch.stack(
        [ts.__getitem__(i)[0] for i in range(ts.__len__())]
    )
    y = torch.stack(
        [ts.__getitem__(i)[1] for i in range(ts.__len__())]
    ).cpu().detach().numpy()
    y_hat = model.forward(x).cpu().detach().numpy()
    y_hat = (y_hat > 0.5)
 **# Accuracy and other metrics**    print("REPORT:\n",
          classification_report(y, y_hat))

在 GPU 上训练我们的模型 20 个历元将会得到以下结果。

**SURVIVED**   precision recall  f1-score   support**FALSE**      0.84      0.94      0.89       115
**TRUE**       0.86      0.67      0.75        64**accuracy**                               **0.84 **      179
macro avg          0.85      0.81      0.82       179
weighted avg       0.85      0.84      0.84       179

正如我们所看到的,我们得到了 84%的准确率,这对于这个任务来说是可以接受的。这次我们更感兴趣的是解读。如果你想知道如何在这项任务中获得满分,可以看看 Kaggle

4.解释

既然 Pytorch 闪电真的很新,而 Captum 更新;)我们在这方面相当领先。

我们需要解决一些尚未妥善解决的小问题。为了做到这一点,我们需要添加一个更小的包装函数,稍后呈现给 Captum。基本上,Captum 是一个有几种可用方法的库。这些方法预测输入特征对神经模型的重要性。他们以几种方式这样做。我们将使用可能是最流行的方法集成梯度。下面我就给出这种方法的一个直觉。

**# Let's start with the interpretation** STEP_AMOUNT = 50
SAMPLE_DIM = 5

**# Since Captum is not directly
# made for Lightning,
# we need this wrapper**
def modified_f(in_vec):
 **# Changes the shapes correctly
    # X:Shape([SAMPLE_DIM*STEP_AMOUNT]=250)**
    x = torch.reshape(in_vec,
        (int(in_vec.size()[0] / SAMPLE_DIM), SAMPLE_DIM)
    )
 **# RES:Shape([50,5])
    # Since we have 50ti Batches and 5 features**
    res = model.forward(x)
 **# Again reshape to correct dims**
    res = torch.reshape(res, (res.size()[0], 1))
    return res

ig = IntegratedGradients(modified_f)

现在我们可以开始学习我们的模型是如何思考的。赋予此对象 IntegratedGradients。我们可以使用它的 main 方法属性()!

attribute()是一个函数,它将一个张量作为输入,并返回给我们一个相同形状的张量

这意味着当我们告诉我们的模型,我们的案例研究对象:

**Pclass  Sex   Age  SibSp     Fare**
3       male  22.0      1       7.2500 (I am not normalized)

它将使用这 5 个特征进行预测。假设这个 22 岁的男子支付了 7.25 英镑的车费,那么这个数字就是 0.3%,也就是 0.3%的生存机会。预测后我们会发这个 30%存活率->0 %,意思是他死了。

现在积分梯度返回给我们一个张量,也有 5 个值。这些值中的每一个都会告诉我们各自的特性有多重要。这可能是 y. E .的差异

**Pclass  Sex   Age  SibSp     Fare**
0.1619, -0.1594,  0.0196, -0.0024,  0.0068

5.综合梯度

中间上了一堂理论课。集成梯度已经在中提出,用于深度网络的公理化属性综合梯度用于理解我们的神经网络是如何工作的。集成梯度是所谓的可解释性算法。

今天的人工智能社区中使用了几种可解释性算法,但 IG 是最早和最成熟的算法之一。科学界还没有明确决定哪种算法是最好的。随意测试一些其他的,比如 DeepLift

综合梯度—简而言之

这是一个简化的解释,更多细节请参考论文“深度网络的公理化归属

为了以神经网络的方式优化损失函数,我们建立梯度。为了了解每个输入要素对我们的损失函数的贡献大小,我们颠倒了这个过程(称为积分),因此我们对梯度进行积分。

现在,计算积分很难,答案也不清楚。这就是为什么我们必须近似它。我们用黎曼和来近似这个积分。

我们通过使用超参数 n_steps 和基线来近似该值。基线是我们与输入进行比较的对象(我们将在下面详细讨论)。n_steps 是我们反向传播以估计积分的次数。N_steps 基本上控制了我们对积分的估计有多精确。

6.资本基础

我们现在有三样东西:

  1. 受过训练的模特
  2. 测试设备
  3. 综合梯度

使用这些东西,我们将了解我们的模型

**# Test to understand the basics**
**# First get the 6th test example**
val = ts.__getitem__(6)[0]
print("IN X1:", val)
**# Predict the importance of the features
# for the male example**
imp_m = ig.attribute(inputs=val,
                     baselines=ts.base,
                     n_steps=STEP_AMOUNT)
print("IMPORTANCE X_m:", imp_m)
print("Probability SURVIVAl X_m:", modified_f(val))
**# Predict the importance of the features
# for the female example**
print("Let's Change the gender ->X2")
val_f = val
val_f[1] = 0
imp_f = ig.attribute(inputs=val_f,
                     baselines=ts.base,
                     n_steps=STEP_AMOUNT)
print("IMPORTANCE X_f:", imp_f)
print("Probability SURVIVAl X_f:", modified_f(val_f))

该代码将打印:

IN X1: [1.0000, 1.0000, 0.3466, 0.0000, 0.0303]
IMPORTANCE X_m:[-0.0593, -0.1121, -0.0010,  0.0019, -0.0040]
Probability SURVIVAl X_m:0.1265IMPORTANCE X_f:[-0.1178,  0.4049, -0.0020,  0.0037, -0.0080]
Probability SURVIVAl X_f:0.5817

如你所见,当我们给出 Captum,这两个相同的例子。除了性别。我们得到了截然不同的存活率。

**# MALE** Pclass  Sex   Age  SibSp     Fare
3       male  22.0      1       7.2500 (I am not normalized)
**# FEMALE** Pclass  Sex     Age  SibSp     Fare
3       female  22.0      1       7.2500 (I am not normalized)

男性的存活率是 12%,女性是 58%!我们得到的两个重要值是:

 Pclass  Sex         Age    SibSp     Fare  
IMPORTANCE X_m:[-0.0593, **-0.1121**, -0.0010,  0.0019, -0.0040]
IMPORTANCE X_f:[-0.1178,  **0.4049**, -0.0020,  0.0037, -0.0080]

正如我们在这两种情况下所看到的,在特征中重要性是最强的(就绝对而言)。这表明这是最重要的功能!

解读符号:我们可以把它看作是增加到预测(+)或从预测(-)中扣除的东西。即+使其更可能是(1)或更不可能是(1)。

我们可以看到,根据性别(男性\女性)的不同,产生的向量也大不相同。

7.基线的影响

基线是我们用来比较自己价值的东西。为了理解它的影响,我们将比较最明显的选择。在最初的论文中,使用了噪声和黑色图像(零)的概念。

我们将比较 4 个不同的基线。

对比:

1 .平均值!

2.噪声,与随机相比

3.全是 1

4.全是零

接下来,代码将产生期望的解释。

**# define a collection** to_be_df = []
**# Compare each element of the test set to out baselines
# we will than use this**
for i in range(0,
               1):  # ts.__len__()):
 **# load our test example**
    in_val = ts.__getitem__(i)[0]
 **# compare it to the 4 baselines**    att_b = ig.attribute(
        inputs=in_val,
        baselines=ts.base,
        n_steps=STEP_AMOUNT).detach().cpu().numpy()
    att_r = ig.attribute(
        inputs=in_val,
        baselines=torch.rand(
            5).cuda(),
        n_steps=STEP_AMOUNT).detach().cpu().numpy()
    att_z = ig.attribute(
        inputs=in_val,
        baselines=torch.zeros(
            5).cuda(),
        n_steps=STEP_AMOUNT).detach().cpu().numpy()
    att_1 = ig.attribute(
        inputs=in_val,
        baselines=torch.ones(
            5).cuda(),
        n_steps=STEP_AMOUNT).detach().cpu().numpy()
 **# save result, this will produce a df
    # you can skip the details**
    for base_type, vals in [
        ("mean-base", att_b),
        ("random-base", att_r),
        ("zero-base", att_z),
        ('one-base', att_1),
    ]:
        for i, name in enumerate(['Pclass',
                                  "Sex",
                                  "Age",
                                  "SibSp",
                                  "Fare"]):
            to_be_df.append({
                "base-type": base_type,
                "feature": name,
                "value": vals[i],
            })
**# Convert our data to a pandas** df = pd.DataFrame(to_be_df)
df.to_csv('data/interpretation_results.csv')
print("OUR INTERPRETATION:\n\n",
      df)

我们的结果看起来像这样。

 **base-type feature     value** 0     mean-base  Pclass  0.162004
1     mean-base     Sex -0.159421
2     mean-base     Age  0.019652
3     mean-base   SibSp -0.002433
4     mean-base    Fare  0.006821
5   random-base  Pclass  0.117517

现在我们找到了我们要找的东西!

8.形象化

一旦我们完成了工作,我们就可以坐下来享受它了!

**# Aggregate and Visualize
# Load Data**
df = pd.read_csv('data/interpretation_results.csv')
**# Defined the color map for our heatmap to be red to green**
cmap = sns.diverging_palette(h_neg=10, h_pos=130, s=99,
                             l=55, sep=3, as_cmap=True)
**# Aggregate the CSV by mean**
df = df.groupby(["base-type", 'feature', 'epoch'],
                as_index=False).mean()
df = df[df['epoch'] == max_epoch]
**# Make one plot per baseline to compare**
for b in ["mean-base",
          "random-base",
          "zero-base",
          'one-base']:
 **# Let's plot them isolated**
    tmp = df[df['base-type'] == b]
 **# Create a pivot frame**
    tmp = tmp.pivot(index='base-type', columns='feature',
                    values='value')
    print("We will plot:\n",tmp)

枢纽数据框基本上只是对相同的数据采用不同的视图。这里我们告诉它拥有索引(基本类型上的行)和“特性”上的列这看起来像这样。

**feature         Age      Fare    Pclass       Sex     SibSp**
**mean-base**  0.023202  0.004757  0.116368  0.225421  0.022177

现在剩下要做的就是用

**# Create a pivot frame**
 tmp = tmp.pivot(index='base-type', columns='feature',
                    values='value')
**# Some code to make a heatmap using seaborn** fig, ax = plt.subplots()
fig.set_size_inches(10, 2.5)

plt.title("Feature Importance ", fontsize=15)
sns.heatmap(tmp, ax=ax, cmap=cmap, annot=True)
plt.text(0, 0,
         'By Sandro Luck\nTwitter:@san_sluck',
         horizontalalignment='center',
         verticalalignment='bottom',
         fontsize=10)

plt.savefig(f'data/{b}.png')

Mean-基地

太好了,现在我希望最后一个怀疑者也相信性是伟大的!我们可以清楚地看到,特征性别的影响是显著的。当我们查看数据集时,我们可以注意到,作为一个男人,你的死亡几率会大大增加。毕竟,“妇女和儿童优先”是他们对待船只的方式。

一垒对零垒

一垒

零基数

这里我们看到基线之间有很大的差异。如果我们将这两个基线与平均基线进行比较,我们会注意到 SibSp 的重要性发生了巨大变化。这通常应该说明使用基线(如 1 和 0)是不可取的。这样做的原因是我们要计算预测在基线和值之间的变化量。

例如,对于图像,使用 0 基线可能是有意义的。原因是,在这种情况下,黑色方块代表没有信息。

随机基数

对我来说,这一天的惊喜来自于随机基线的成功。综合梯度的作者提到使用随机基线是明智的。但是我没有预料到它在这个例子中工作得如此之好。

显示训练时间重要性的 GIF

在某些平台上让人们关注你的数据时,gif 是至关重要的。尤其是在社交媒体上,动画可以决定点击和快速浏览的区别。

由于这篇文章已经相当长了,请参考我的文章《如何用 Python 和 Seaborn 从 Google Trends 数据制作 GIFS》以闪电般的速度学习制作上面的 GIF。

结论

我们已经了解了什么是可解释性,以及如何在 PyTorch 中使用它。我们已经看到在原型制作中使用它是多么容易,以及如何将其连接到 PyTorch Lightning。

我希望这种对可解释性世界的介绍是容易的,没有痛苦的。了解您正在构建什么可以帮助我们的客户和我们。这大大增加了他们对我们预测的信心。

如果你喜欢这篇文章,我会很高兴在 TwitterLinkedIn 上联系你。

一定要看看我的 YouTube 频道,我每周都会在那里发布新视频。

整个代码

最性感的工作,但是…

原文:https://towardsdatascience.com/sexiest-job-but-27b6e91ece8e?source=collection_archive---------3-----------------------

图片提供:Pixabay

作为人工智能、机器学习或数据科学从业者,在职业旅程中会有什么期待

《哈佛商业评论》的文章《数据科学家:21 世纪****最性感的工作》在整个行业掀起了涟漪。毕竟是天价工资的梦想工作部门,所有关于人工通用智能,认知机器学习等的炒作。流行媒体痴迷于所谓的人工智能强国的每一次突破。将人工智能、数据科学家或机器学习与一个人的职业联系在一起,不仅性感,而且极具魅力。

但是最性感的工作并不意味着什么都性感。数据科学的许多方面令人毛骨悚然,有时甚至令人恐惧。

在本文中,我将交替使用数据科学、机器学习和人工智能。

不要看外表,如果你是认真的,最好知道如果你开始机器学习或人工智能之旅,你将在余下的职业生涯中面临什么。

开始喜欢奇怪而复杂的数学符号

我每天都听到,“你们真幸运。只要用 fit/predict 写几行 python 代码,你的模型就好了”。我希望事情能这么简单。由于机器学习和人工智能在很大程度上依赖于数学,所以需要对数学的深刻理解(事实上,对于任何想在数据科学领域建立职业生涯的人来说,这是一种深度学习)。线性代数、统计学、微积分等。不仅对于博士来说,而且对于那些想要从事更高端(或者“性感”)的数据科学领域的人来说,具有高级应用水平是必要的。因此,如果你不喜欢复杂的方程或吓人的符号,最好从现在开始喜欢它。

每天“深度学习”

图片提供:Pixabay

数据科学是一个包含多个学科知识领域的领域。新的领域作为灵感或想法和应用的扩展被包括进来。随着政府、公司和研究人员的兴趣,这一领域近年来以非凡的进步蓬勃发展。正在进行的研究工作的数量令人难以置信。该地区进展非常快,跟上了变化;从业者需要不断更新他们的技能和知识。每天都有新的论文问世,其中一些论文在很大程度上改进了以前的最先进水平。因此,我们别无选择,只能了解新的变化,并在工作、研究或应用中采用它。你需要每天对这门学科进行真正的“深度学习”。

80%的数据科学工作非常无聊

图片提供:Pixabay

这一点我肯定是众所周知的,但我仍然想确保你没有任何误解。数据清理和数据预处理是数据科学中最讨厌但又无法逃避的部分。不要假设,如果你在一家世界知名的领先人工智能公司,你不会要求做这种肮脏的工作。只有前几%的人免于这种常规的折磨,如果你不在这前几%的人之列,那就下定决心,你必须执行这个肮脏的任务,清理污垢,刮去所有的短发或长发,从你在午休餐桌上听到的一些新来源获得更多的数据。这是非常重复的,就像处理丢失的数据,转换数据,合并数据,管理不同的管道,以一种你的模型理解的一致的格式,基本上是无聊工作的无限列表。但你必须这么做,无处可逃。习惯就好。

卡格尔是!=现实世界问题

图片提供:Pixabay

在 Kaggle 中,你可能是一个超级明星,在许多比赛中你都进入了前 5 名,但抱歉,你会发现现实生活中的项目比任何 Kaggle 比赛都难 10 到 30 倍。大多数情况下,你会纠结于如何收集数据,定义一个清晰的范围和衡量成功的方式。你可能不需要和 100 个其他人竞争,每次你提交时,你都知道你的立场,但在现实生活中,除了你的团队为一份公司预算或达到一个目标而竞争之外,没有其他竞争。如果你有一个正在生产中运行的模型,那么你是幸运的,因为你知道有一个基线,并且你正在努力改进。Kaggle 有助于你的基础和名声,但不要忘记现实世界的问题要困难得多,成功才是

哦,不,你可能要再次训练数据

图片提供:Pixabay

机器学习模型训练是需要时间的,很多时候是多次迭代。在这个深度学习的时代,有 100 多个隐藏层,数千个特征和数百万条记录,即使有数百个 GPU/TPU 单元,模型也需要很长时间来训练。因此,你必须学会如何度过这些反复,因为很多时候你必须重新开始。

arXiv.org 每天都有大量的新报纸

图片提供:谷歌照片

如果你梦想成为一名顶尖的数据科学家,你必须习惯阅读档案库中专家提交的最新研究论文。研究论文呈爆炸式增长,论文的大部分主张都无法复制,因为它们没有提供具体细节或代码来执行基于作者倡导的新算法的测试。尽管如此,特殊的新想法正在出现,而让自己保持更新或采用提议的架构的唯一来源是通过对论文的更深入理解。你必须养成一种习惯,并且找到一种只关注相关事物的方法。

哎呀,企业甚至不知道他们想要什么

图片提供:Pixabay

这可能并不奇怪,因为在许多其他部门中,企业也不知道他们需要或也想要什么。要求将会非常模糊,以至于连律师都很难解释这几行字(如果有的话)的意思。大多数组织的业务领导人不了解数据科学或人工智能的技术部分,但他们会假装什么都知道(就像许多患者认为他们比他们的医生知道得更多)。像我们希望通过这个人工智能项目彻底改变我们目前的业务方式,我们希望看到 30%的采用率增加等声明。就像你可能不得不处理的那样习惯它,这些非常高的期望,或者你可能不得不用你的业务部门仍然可能不理解的大量视觉解释和数据来解释模型的结果。如果你很幸运,并且在一家初创公司或技术领先的公司,那么你可能不会面临这种斗争,但总的来说,你会习惯这种情况,这在人工智能和人工智能采用刚刚开始的许多行业中非常常见。

它是关于一次杂耍多个球

图片提供:Pixabay

是的,数据科学家的角色要求很高,在许多组织中,你需要成为数据科学方面的万事通。你需要知道端到端的机器学习管道是如何工作的。如何规划培训和测试管道。你必须参与数据科学团队的工程方面,参与服务器/存储配置、容器管理、Kubernetes、Kubeflow、与 Django 一起构建前端 web 界面,可能必须扮演全栈开发人员的角色。你需要为你的模型产品化做一个清理工作。这就像同时戴着许多帽子,因此要习惯数据科学角色中这些具有挑战性的部分。

每隔几周,最先进的技术就会成为历史

图片提供:Pixabay

您可能在一个团队中工作,该团队正在使用最新的 NLP 架构进行一个任务关键型项目。尽管如此,由于超出任何人控制的多种原因,您的项目正在延期。经过三个月的努力,当你达到验收测试水平的时候,你已经意识到谷歌刚刚开源了一个新的艺术境界,而你的竞争对手已经开始着手这项工作了。欢迎来到数据科学领域的超音速变革。今天的新东西,很快就会过时。习惯这种新的职业生活方式。

R&D,是的,这就是数据科学的大部分内容

图片提供:Pixabay

你会看到,在许多项目或决策点中,你必须尝试多种方法才能有所突破。数据科学不仅仅是科学也是一种艺术形式,这些黑艺术很多更像是有或没有理论支撑的试错法。在迈出一小步之前,你必须做大量的 R&D,因为完成同样的任务有多种方法,但每种方法给出的结果都略有不同。适用于项目 X 的方法可能不适用于项目 y。如果您的损失函数或优化程序没有给出预期的结果或速度,则需要重新发明轮子。您可能需要用较小的数据集来尝试其中的几种,看看哪一种有效。你需要尝试一些策略,如果没有一个奏效,你可能需要完全改变行动方针。底线是数据科学是一个与 R&D 领域非常相似的领域,你需要习惯这种工作文化。

最后一个音符

很多事情让数据科学家的生活变得格外艰难,有时它感觉如何摆脱它。但是请记住,一旦你掌握了生存游戏,你就在做最性感的工作。许多人之所以成功,是因为他们接受了所有这些挑战,克服了所有这些缺点,从而变得成功。

我期待你的评论和分享,如果你有任何与这个行业的挑战相关的独特经验。感谢阅读。可以联系我@ LinkedIn

每月只需 5 美元,就可以无限制地获取最鼓舞人心的内容……点击下面的链接,成为一名媒体会员,支持我的写作。谢谢大家!

面部识别器—您的第四个 CNN

原文:https://towardsdatascience.com/shahrukh-khan-face-recognizer-your-4th-cnn-38668dae5afc?source=collection_archive---------47-----------------------

亚历山大·克里维茨基在 Unsplash 上拍摄的照片

第四 CNN?

这是我在自己动手 CNN 模型系列的第四篇文章。像往常一样,格式将保持不变。我将为您提供一个 Colab 文件(它工作得非常好),您必须在没有任何先决条件的情况下运行它,然后才能继续。原因是,一旦你自己运行它,你会变得更加重视这个问题,你会得到更深刻的见解。

你可以在这里查看我以前的文章:

在这篇文章中,我们将解决和理解 CNN 最重要的问题之一——人脸识别。即给定一个人的照片,找出其姓名。我们将拍摄宝莱坞最著名的演员沙鲁克·汗的照片,并确定他的身份。

来源

那么,事不宜迟,让我把 Colab 文件交给你🚀。这不是我的作品,而是从各地抄袭来的。我在这里做的唯一一件事是确保它在 Colab 设置中运行良好(令人惊讶的是,这很难做到)。但是,尽管如此,它现在工作得很好,唷!

请随意上传您的图像并检测它们!现在,这个文件看起来可能有点吓人,但实际上并不是这样。像往常一样,我们先从理论开始,稍后将讨论实现细节。此外,根据我以前的文章,我会尽量保持简短和甜蜜。

人脸检测 vs 验证 Vs 识别器

首先,我们所说的识别器实际上指的是什么?

  • 人脸检测——它完全类似于物体检测。检测图像中的所有人脸并找到它们的位置
  • 人脸验证——给出两张人脸,确定是否属于同一个人。
  • 人脸识别器——识别被检测人的姓名。

人脸检测

这与目标是专门检测面部(而不是任何随机对象)的对象检测完全一致。有几个著名的型号可供选择。我不会深入探讨这个问题,因为这超出了我的博客范围。

  • Dlib :作用于梯度方向直方图(HOG)和线性 SVM。不过,这只能检测正面人脸。 阅读更多
  • 哈尔级联: 是 CNN 上的一个优化技术。所有的内核并没有一起应用。相反,它们被分成多个更小的组。如果在第一组中没有检测到任何东西,它就不会继续前进。
  • MTCNN :其 CNN 有多个阶段。第一种状态检测边界框,在后面的阶段消除误报,并选择人脸的最终边界标志。

人脸识别器

现在,一旦检测到人脸,识别这个人的名字就完全是另外一个问题了。在继续之前,让我在这里介绍几个概念。

概念一:人脸嵌入

这正是在单词嵌入方面。唯一的区别是它代表欧几里得空间中的人脸。

  • 每张脸都被转换成一个矢量,这个矢量以某种方式代表了这张脸的所有特征。
  • 所有这些向量都被绘制成欧几里得空间上的点。
  • 点越近,脸越相似

概念 2:连体网络

你听说过连体双胞胎吗?这些是长得一模一样的连体双胞胎。我们的网络也是如此。

因此,连体网络是一种具有两个并行神经网络的架构,每个神经网络接受不同的输入。两个单独的输出然后被组合以提供两个图像的相似性的预测。

暹罗网络培训技术

基于我们拥有的大量训练数据,通过两种技术,暹罗网络可以用来预测人的名字。

技巧 1:一次性学习

什么时候用这个:当我们没有足够的学习数据的时候。

工作原理:

  • 训练数据: 100 个不同的人的 100 个不同的图像。
  • 场景: 检查一张图片是否符合以上 100 个人中的任何一个。
  • 解法: 计算出给定图片与上述所有 100 张图片的相似度得分。
  • 结果:100 分中图像相似度得分最高的一个(高于截止值),将被标记为匹配。

技巧 2:三重态丢失

什么时候用这个:当我们有足够的学习数据来很好地训练网络的时候。

它是如何工作的?

  • 训练数据: 1000 个不同的人的 1000 个不同的图像。
  • 训练步骤: 取一张锚点图像,用匹配图像和不匹配图像进行训练。并计算损失。这种损失叫做 三重损失
  • 场景: 检查一张图片是否符合以上 100 个人中的任何一个。
  • 解决方案: 就像其他 CNN 一样,把它作为输入发送给一个已经训练好的系统,得到相关的输出。

为了实现人脸检测和识别,以沙鲁克·汗为例。正如你所看到的,人脸检测和识别是如何工作的,并给出如此准确的结果。这里使用了基于 MTCNN 的人脸检测和基于三元组丢失的人脸识别器。

请随意上传你最喜欢的演员的照片,并与它一起玩。

莎士比亚遇上谷歌的亚麻

原文:https://towardsdatascience.com/shakespeare-meets-googles-flax-ecbd16f9d648?source=collection_archive---------34-----------------------

用 Flax 构建字符级语言模型

Unsplash 上由 Amariei Mihai 拍摄的照片

有些人生来伟大,有些人成就伟大,有些人是被强加伟大的。

威廉·莎士比亚,第十二夜,或者随便你

几个月前,谷歌研究人员介绍了机器学习领域的新星 Flax。从那以后发生了很多事情,预发布版也有了很大的改进。我自己用 CNN 在亚麻上做的实验开花结果,与 Tensorflow 相比,我仍然对其灵活性感到惊讶。今天我将向大家展示 RNNs 在 Flax 中的一个应用:字符级语言模型

在许多学习任务中,我们不必考虑对先前输入的时间依赖性。

但是如果我们没有独立的固定大小的输入和输出向量,我们能做什么呢?如果我们有向量序列呢?解决方案是递归神经网络。它们允许我们对如下所述的载体序列进行操作。

递归神经网络

灵感来自安德烈·卡帕西

在上图中,您可以看到不同类型的输入和输出架构:

  • 一对一是我们典型的 CNN 或多层感知器,一个输入向量映射到一个输出向量。
  • 一对多是一个很好的图像字幕 RNN 架构。输入是我们的图像,输出是描述我们图像的一系列单词。
  • 多对多:第一种架构利用输入序列输出序列进行机器翻译,例如德语到英语的翻译。第二种适用于帧级别的视频字幕。

RNNs 的主要优点是它们不仅依赖于当前的输入,而且依赖于先前的输入。

RNN 是具有内部隐藏状态的单元,根据隐藏的大小用零初始化。在每个时间步 t 中,我们将输入 x_t 插入我们的 RNN 单元,并更新隐藏状态。现在,在下一时间步 t+1 中,隐藏状态不再用零初始化,而是用先前的隐藏状态初始化。因此,RNNs 允许保存关于几个时间步长的信息并生成序列。

灵感来自安德烈·卡帕西

字符级语言模型

利用我们的新知识,我们现在要为我们的 RNN 构建第一个应用程序。字符级语言模型是许多任务的基础,例如图像字幕或文本生成。RNN 单元的输入是字符序列形式的大块文本。现在的训练任务是学习如何在给定一系列前一个字符的情况下预测下一个字符。所以我们在每个时间步长 t 生成一个字符,我们之前的字符是 x_t-1,x_t-2,…

作为一个例子,让我们把单词 FUZZY 作为我们的训练序列,现在词汇表是{'f ',' u ',' z ',' y'}。因为 RNN 只对向量起作用,所以我们把所有的字符都转换成所谓的一键向量。基于词汇表中的位置,一个 hot-vector 由 0 和 1 组成,对于“Z ”,转换的向量是[0,0,1,0]。在下图中,您可以看到给定输入“FUZZ”的示例,我们希望预测单词“UZZY”的结尾。我们神经元的隐藏大小是 4,我们希望输出层的绿色数字高,红色数字低。

灵感来自安德烈·卡帕西

如果你对 RNNs 背后的数学感兴趣,请点击链接

最后,我们正在编码

请注意,我在之前关于 CNN 的文章中解释了亚麻的一些基本概念。作为数据集,我们使用由如下对话组成的小莎士比亚:

爱德华:

即使如此;然而你仍然是沃里克。

格洛斯特:

来吧,沃里克,抓紧时间;跪下,跪下:不,什么时候?现在就打,否则铁就凉了。

我再次使用 Google Colab 进行培训,因此我们必须再次安装必要的 PIP 包:

您应该使用具有 GPU 支持的运行时,因为训练任务要求非常高。您可以使用以下命令测试 GPU 支持的存在:

现在,我们准备从头开始创建我们的 RNN:

在这样一个真实的训练环境中,我们不用普通的 RNN 细胞,而是用 LSTM 细胞。这些是进一步的发展,可以更好地处理消失梯度的问题。为了达到更高的精度,我使用了三个堆叠的 LSTM 池。非常重要的是,我们将第一个单元的输出传递给下一个单元,并且用自己的隐藏状态初始化每个 LSTM 单元。否则,我们会失去对时间依赖性的跟踪。

最后一个 LSTM 池的输出在我们的致密层中给出。致密层有我们的词汇量那么大。在我们之前的“模糊”例子中,神经元的数量是四个。如果“FUZZ”被设置为我们的 RNN 的输入,神经元最多应该产生类似于[1.7,0.1,-1.0,3.1]的输出,因为该输出指示“Y”是最可能的字符。

因为我们有两种不同的模式,所以针对不同的情况,我们将 RNN 封装在另一个模块中。

这些案例是:

  • 训练模式,我们想学习如何预测
  • 预测模式,我们实际上采样一些文本

在训练我们的模型之前,我们需要用以下函数创建它:

我们的每个序列都有 50 个字符的长度,我们有 65 个不同字符的词汇表。

作为我们 RNN 的优化器,我选择 Adam 优化器,其初始学习率为 0.002,权重衰减以避免过大的权重。

培训模式

在训练模式中,我们将一批 32 个序列输入我们的 RNN。每个序列都来自我们的数据集,包含两个子序列,一个包含从 0 到 49 的字符,另一个包含从 1 到 50 的字符。通过这个简单的拆分,我们的网络可以学习最有可能的下一个字符。在每一批中,我们初始化隐藏状态,并将序列提供给我们的 RNN。

在我们的训练方法中,我们有两个子功能。loss_fn 通过将被解释为向量的输出神经元与期望的独热向量进行比较来计算交叉熵损失。同样,在我们的“模糊”示例中,我们会有一个输出[1.7,0.1,-1.0,3.1]和一个热向量[0,0,0,1]。我们现在用这个公式计算损失:

其中 y 是我们的标签,y_hat 是逻辑的 softmax 输出。我不得不稍微改写一下 CNN 例子中的代码,因为我们现在处理的是序列而不是简单的类:

训练步骤中的另一种方法是指数衰减。我使用 Adam 优化器,初始学习率为 0.002。但是对于每五个时期,我想降低学习率以避免太强的振荡。在每五个时期之后,因子 0.97ˣ乘以我们的初始学习速率,x 是我们到达五个时期的频率。

你可以再一次看到 Flax 的力量,它是一种简单而灵活的方式,你可以在运行中集成你自己的学习率调度程序。

预测模式

现在我们想要评估我们学习的模型,因此我们从我们的词汇表中随机挑选一个字符作为入口点。像在训练中一样,我们初始化我们的隐藏状态,但这次只是在采样开始时。子功能推理现在接受一个字符作为输入。对于隐藏状态,我们在每个时间步长后输出它们,并在下一个时间步长将它们输入到我们的 RNN 中。因此,我们不会失去我们的时间依赖性。

这种方法被称为“贪婪采样”,因为我们总是在输出向量中选择概率最高的字符。还有更好的采样方法,比如波束搜索,我不在这里讨论。

训练和样本循环

至少我们可以在训练和样本循环中调用所有编写的函数。

每 10 个时期后,我们生成一个文本示例,在开始时,它看起来非常重复:

顶峰水手们所有的商人的意义的意义的意义的意义的意义的意义…

但是模型变得越来越好,经过 100 个时期的训练,输出看起来像莎士比亚还活着,正在写新的文本!

这是一个受尊敬的女人向国王的转变,向这个最危险的士兵和财富的转变。

安东尼奥:
如果她会在月亮的荣誉上出现,为什么,…

100 个周期后的训练准确率为 86.10%,我们的学习率衰减到 0.00112123。

结论

字符级语言模型在其基础上是完成文本的强大工具,并且可以用作自动完成。同样,给定文本的情感可以被学习来利用这个概念。但是如你所见,生成完整的新文本是一项非常困难的任务。我们的模型的输出句子看起来像莎士比亚的文本,但它缺乏意义。在下一篇文章中,我将使用这种模型,并根据有意义的输入创建更多有意义的句子。

尽管 Flax 拥有强大和众多的工具,但它仍处于早期开发阶段,但它们正在以自己的方式开发一个我喜欢的框架。真正巧妙的是,我只需要稍微修改一下我的“旧”CNN 代码,就可以在现有的基础上使用 RNN。

但是 Flax 仍然缺少自己的输入管道,因此我不得不用 Tensorflow 来写这个。您可以在 Github Repo 中找到数据集创建的代码和完整的 RNN。

如果你想自己试试我的代码,就看看我的 Github Repo

不然我可以推荐亚麻 Github Repo 和他们的文档

图片的灵感来自这个博客

浅层和深层拷贝——停止犯这些常见的切片错误

原文:https://towardsdatascience.com/shallow-deep-copies-stop-making-these-slicing-mistakes-12d02ffa2f7f?source=collection_archive---------29-----------------------

来源: Pixabay

正确管理你的记忆

当编写高效的代码和正确管理有限的内存时,浅副本和深副本是理解的基础。不知道浅副本和深副本上的操作也会导致切片和其他操作中的一些严重错误。幸运的是,它们是很容易理解的概念!

考虑一个 NumPy 数组。我可以选择两个路径,一个是浅拷贝(也称为视图,原因您很快就会看到)或深拷贝。

  • 浅层复制:x_view = x_list.view()
  • 深度复制:x_copy = x_list.copy()

这两个副本有什么不同?

浅层拷贝实际上并不拷贝每个元素的值。相反,它们引用x_list中每个值的存储位置。这意味着他们实际上是这样存储数据的:np.array([first element in x_list, second element in x_list, …])。因此,这些类型的拷贝依赖于原始阵列。因为浅拷贝本质上是与原始数据相同的数组,但是以不同的名称记录,所以它们可以被认为是原始数据的“视图”。

另一方面,深度副本复制每个值,并在内存中分配新的空间。不是存储值的存储位置,而是记录物理元素:np.array([1,2,3,4,5])。深层副本独立于原始数组,使用它们会占用更多的存储空间。

objx =存储在内存中的对象

把浅层复制想象成用两根吸管喝同一种饮料(数据)(访问机制),而深层复制则是点同一种饮料,并分别从那种饮料中喝。在浅层复制中,如果两个饮酒者中的一个把吸管吐到饮料中,另一个的饮料(和食欲)也会改变。然而,在深度复制中,一个饮酒者不愉快的习惯不会影响到另一个人的饮料,两个人都可以随意改变他们的饮料,而不会影响到另一个人。

列表也是如此。假设我做了一个改动:x_list[0] = 10,把x_list的第一个元素,也就是原来的数组,设置为等于 10。

  • x_view(浅抄):array([10, 2, 3, 4, 5])
  • x_copy(深度复制):array([1, 2, 3, 4, 5])

只有浅层副本受到影响,因为它是与原始(x_list)完全相同的数组,只是名称不同。

这就引出了一个问题:如果浅拷贝附加在原始列表上,为什么还会有人使用它呢?

答案在于许多人所说的复制列表的最有效的方法——使用x_list[:],它是一个“空片”,或者是一个没有边界的片,因此复制整个列表。所有切片,像x_list[1:4]和空切片,都是浅拷贝。这有道理;切片操作只是获取现有列表的一部分,因此创建深度副本和复制现有值是低效的。

切片只是一个关于如何显示原始列表中的数据的命令。如果我使用x_slice = x_list[1:4]并使用x_slice,程序简单地引用回x_list并从中提取值(即第一个到第三个索引)。浅层拷贝存在于复杂操作的每个方面,有助于提高内存存储的效率。

因为许多人没有意识到切片是一种浅拷贝操作,他们没有意识到像x_slice[0]=10这样的东西会把原来的切片列表变成array([ 1, 10, 3, 4, 5])。这是因为从第一个索引开始的切片的第 0 个索引是原始数组中的第一个索引。

对各种操作都要小心——理解它们是深层副本还是浅层副本,因为理解失败可能会导致您意外地更改原始列表中的值。除了切片,还有几个接口会让你认为是深层拷贝,但实际上是浅层拷贝。如果需要执行值变更,最好搜索文档,看看操作是使用浅层副本还是深层副本。

一般来说,浅拷贝的黄金法则是使它们不可改变。一旦你做了一个浅拷贝(或者一个变体,比如通过切片),不要改变原件或者拷贝,这样就不会出现意想不到的改变。如果您确实要编辑副本,请确保您完全了解它不仅会对原始数组产生影响,还会对由该原始数组制作的任何其他浅层副本产生影响。

许多 Python 对象,比如字典,都有默认的浅层复制函数,比如dict.copy()。但是,您也可以使用copy模块(import copy),调用copy.copy()进行浅层复制,调用copy.deepcopy进行深层复制。这些就像用于深层和浅层拷贝的 NumPy 命令一样。

[## 高级 NumPy 数组索引,变得简单

理解[::2,[0,3,4],…,2:5]是什么意思

towardsdatascience.com](/advanced-numpy-array-indexing-made-easy-fc49fdaef367)

除了由作者创建的标题之外的所有图像。

SHAP 价值观准确地解释了你希望别人如何向你解释

原文:https://towardsdatascience.com/shap-explained-the-way-i-wish-someone-explained-it-to-me-ab81cc69ef30?source=collection_archive---------0-----------------------

理解用于计算 SHAP 值的公式

去神秘化

SHapley 代表 SHapley Additive explaining——可能是机器学习可解释性的艺术状态。该算法由 Lundberg 和 Lee ( 此处是原文)于 2017 年首次发表,它是对任何预测算法的输出进行逆向工程的一种出色方式。

简而言之,每当您有一个复杂的模型(可能是梯度增强、神经网络或任何将一些要素作为输入并产生一些预测作为输出的东西)并且您想要了解模型正在做出什么决策时,就会使用 SHAP 值。

预测模型回答“多少”。SHAP 回答了“为什么”。

在之前的一篇文章中(黑盒模型实际上比逻辑回归更容易解释),我们用 SHAP 来理解为什么梯度推进模型表明泰坦尼克号乘客生还的可能性更大或更小。换句话说,我们用 SHAP 揭开了黑箱模型的神秘面纱。但是,到目前为止,我们开发了 Python 的 SHAP 库,而没有过多担心它是如何工作的。

具有讽刺意味的是,我们把 SHAP 本身当成了一个黑盒!

然而,理解 SHAP 值计算背后的思想对于理解其结果至关重要。这就是为什么,在这篇文章中,我们将通过 Slundberg 和 Lee 的文章中描述的 SHapley 加法解释的理论基础,并了解为什么 SHAP 值是以这种方式计算的。

博弈论和机器学习

SHAP 价值观是基于沙普利价值观,一个来自博弈论的概念。但是博弈论至少需要两样东西:一个游戏和一些玩家。这如何应用于机器学习的可解释性?假设我们有一个预测模型,那么:

  • “游戏”正在再现模型的结果,
  • “玩家”是模型中包含的特征。

沙普利做的是量化每个球员给游戏带来的贡献。SHAP 所做的是量化每个特征对模型所做预测的贡献。

重要的是要强调,我们所谓的“游戏”涉及到一个单一的观察。一局:一次观察。事实上,SHAP 是关于预测模型的局部可解释性。

强大的功能集

举例来说,我们将想象一个机器学习模型(假设是线性回归,但它可以是任何其他机器学习算法),该模型在知道一个人的年龄、性别和工作的情况下预测该人的收入。

Shapley 值基于这样一种想法,即应该考虑每个可能的玩家组合(或联盟)的结果,以确定单个玩家的重要性。在我们的例子中,这对应于 f 特征的每个可能组合(在我们的例子 3 中, f 从 0 到 FF 是所有可用特征的数量)。

在数学中,这被称为“幂集”,可以用树来表示。

强大的功能集

每个节点代表一个特性联盟。每条边代表包含一个先前联盟中不存在的特征

从数学上我们知道,幂集的基数是 2 ^ n ,其中 n 是原集合的元素个数。事实上,在我们的例子中,我们有 2 个^ f = 2 个^ 3 = 8 个可能的特征组合。

现在, SHAP 要求为权力集中的每个不同联盟训练一个不同的预测模型,这意味着 2 个^ F 模型。当然,这些模型在超参数和训练数据方面是完全等价的。唯一改变的是模型中包含的一组特性。

假设我们已经根据相同的训练数据训练了 8 个线性回归模型。然后我们可以进行一次新的观察(姑且称之为 x₀ ),看看 8 个不同的模型对相同的观察 x₀ 预测了什么。

不同模型对 x₀.的预测在每个节点中,第一行报告模型中包含的功能联盟,第二行报告该模型为 x₀ 预测的收入。

这里,每个节点代表一个型号。但是边代表什么呢?

建筑 SHAP 公式(1/2) —特征的边际贡献

如上所述,由边连接的两个结点仅在一个特征上有所不同,也就是说,底部结点具有与上部结点完全相同的特征,外加一个上部结点没有的附加特征。因此,两个连接节点的预测之间的差距可归因于该附加特征的影响。这被称为一个特性的“边际贡献”

因此,每条边代表一个特征给一个模型带来的边际贡献

假设我们在节点 1,这是一个没有特征的模型。该模型将简单地预测所有训练观察的平均收入(50k $)。如果我们转到节点 2,这是一个只有一个特征(年龄)的模型,对 x₀ 的预测现在是 4 万美元。这意味着知道了 x₀的年龄后,我们的预测降低了 1 万美元。

因此,年龄给只包含年龄作为特征的模型带来的边际贡献是-10k 美元。在公式中:

当然,为了获得年龄对最终模型的整体影响(即 x₀ 的年龄 SHAP 值),有必要考虑年龄在所有存在年龄的模型中的边际贡献。在我们的树表示中,这意味着考虑连接两个节点的所有边,使得:

  • 上面的不包含年龄,和
  • 最下面的一个包含年龄。

在下图中,这些边以红色突出显示。

年龄的边际贡献

所有这些边际贡献然后通过加权平均进行汇总。在公式中:

w₁+w₂+w₃+w₄=1。

构建 SHAP 公式(2/2)——权衡边际贡献

但是我们如何确定边的权重(即 4 个模型中年龄的边际贡献)?

这个想法是:

  • 对 1 特征模型的所有边际贡献的权重之和应该等于对 2 特征模型的所有边际贡献的权重之和,依此类推...换句话说,同一“行”上所有权重的总和应该等于任何其他“行”上所有权重的总和。在我们的例子中,这意味着: w₁ = w₂ + w₃ = w₄.
  • 对于每个 f ,所有对 f 特征模型的边际贡献权重应该彼此相等。换句话说,同一“行”上的所有边应该彼此相等。在我们的例子中,这意味着: w₂ = w₃.

因此,(记住它们的总和应该是 1)解决方案是:

  • w₁ = 1/3
  • w₂ = 1/6
  • w₃ = 1/6
  • w₄ = 1/3

看上面的图,你能猜出在一个通用框架中确定权重的模式吗?

剧透:一条边的权重是同一“行”中边总数的倒数。或者,等效地,对一个 f 特征模型的边际贡献的权重是对所有 f 特征模型的可能边际贡献的倒数。

这个有公式计算吗?事实上,这很简单。

每个 f 特征模型都有 f 边际贡献(每个特征一个),因此计算可能的 f 特征模型的数量并乘以 f 就足够了。因此,问题归结为计算可能的 f 特征模型的数量,给定 f 并且知道特征的总数是 F 。这就是二项式系数的简单定义。

综上所述,我们知道所有f-特征模型的所有边际贡献的数量——换句话说,每一“行”中的边的数量——是:

取这个的倒数就足够了,我们得到了对特征模型的边际贡献的权重。

下图举例说明了这一点:

如何从边的数量获得权重

现在,我们有了计算 x₀ 年龄的 SHAP 值所需的所有元素:

包装它

我们建立了一个计算三要素模型中年龄的 SHAP 值的公式。推广到任何特征和任何 F ,我们得到 Slundberg 和 Lee 在文章中报道的公式:

应用于我们的示例,该公式得出:

  • shap _ age(x₀)=-11.33 千美元
  • shap _ gender(x₀)=-2.33 千美元
  • SHAP_Job( x₀ ) = +46.66k 美元

将它们相加得到+33k $,这正好是完整模型的输出(83k $)和没有特征的虚拟模型的输出(50k $)之间的差。

这是 SHAP 值的一个基本特征:对给定观测值的每个特征的 SHAP 值求和产生了模型预测和零模型预测之间的差异(或其逻辑函数,如我们在这里看到的)。这实际上是他们的名字的原因:沙普利加法解释。

太好了!现在我可以自己计算 SHAP 值了

呃……不!

如上图所示,最初的 SHAP 公式需要训练 2 个^ F 模型。对于一个只有 50 个特征的模型,这意味着要训练 1e15 个模型!的确,随着 F 的增加,上面看到的公式很快就变得不适用了。

然而,像 Slundberg 写的这样的库使用了一些出色的近似和采样(我将在后续的文章中讨论这个话题)使得这项工作变得可行。

SHAP:如何用 Python 解释机器学习模型

原文:https://towardsdatascience.com/shap-how-to-interpret-machine-learning-models-with-python-2323f5af4be9?source=collection_archive---------8-----------------------

用一个函数调用就能解释的机器学习

没有人喜欢黑箱模型。有了复杂的算法和大量的数据准备,建立好的模型是很容易的,但是内部发生了什么?这就是可解释的 AI 和出现的地方。

Unsplashpaweczerwiński拍摄的照片

不想看书?看看我关于这个主题的视频:

今天你将学习如何向大众解释机器学习模型。我们将使用三个不同的图进行解释——一个用于单个预测,一个用于单个变量,一个用于整个数据集。

读完这篇文章后,你应该对解释机器学习模型的预测和每个预测器的重要性没有任何问题。

这篇文章的结构如下:

  • 什么是 SHAP?
  • 模特培训
  • 模型解释
  • 结论

什么是 SHAP?

我们来看看创作者的一份官方声明:

SHAP(SHapley Additive explaints)是一种解释任何机器学习模型输出的博弈论方法。它将最优信用分配与使用博弈论及其相关扩展的经典 Shapley 值的本地解释联系起来。(来源:https://github.com/slundberg/shap))

这是许多花哨的词汇,但这里有一件你应该知道的事情——SHAP 帮助我们用匀称的值来解释机器学习模型。

但是什么是匀称的价值观呢?简而言之,它们是每个预测器(特征)在机器学习模型中的贡献的度量。这肯定是网络上最不花哨的定义,但我认为它很容易理解。

让我们接下来开始训练我们的模型,以便我们可以尽快开始解释。

模特培训

为了解释机器学习模型,我们首先需要一个模型——所以让我们基于葡萄酒质量数据集创建一个模型。下面是将它加载到 Python 中的方法:

葡萄酒数据集标题(图片由作者提供)

没有必要清理数据—所有数据类型都是数字,并且没有丢失数据。训练/测试分割是下一步。列quality是目标变量,它可以是好的坏的。为了获得相同的分割,请将random_state的值设置为 42:

现在我们准备训练模型。XGBoost分类器会完成这项工作,所以确保首先安装它(pip install xgboost)。为了再现性,再次将random_state的值设置为 42:

开箱即用,我们有 80%的准确率(score)。现在我们有了开始解释这个模型所需要的一切。我们将在下一节中介绍这一点。

模型解释

为了通过 SHAP 解释这个模型,我们首先需要安装这个库。您可以通过从终端执行pip install shap来完成。然后我们可以导入它,基于 XGBoost 模型制作一个解释器,最后计算 SHAP 值:

我们准备好出发了!

解释单一预测

让我们从小而简单开始。有了 SHAP,我们可以对一个单一的预测做出解释。SHAP 图显示了有助于将输出从基础值(平均模型输出)推至实际预测值的特征。

红色表示将预测值推高的特征,蓝色表示相反的特征。

让我们来看看一款被归类为bad的葡萄酒的解读图:

对劣质葡萄酒的解读(图片由作者提供)

这是一个分类数据集,不用太担心f(x)值。只有residual sugar属性将这个实例推向了好的葡萄酒质量,但正如我们所看到的,这还不够。

接下来,我们来看看一款good葡萄酒的解读图:

一款优质葡萄酒的诠释(图片由作者提供)

这里完全是另一个故事。您现在知道了如何解释单个预测,所以让我们稍微增加一点趣味,看看如何解释单个特征对模型输出的影响。

解释单一特征

为了了解单个要素对模型输出的影响,我们可以绘制该要素的 SHAP 值与数据集中所有实例的要素值的关系图。

下图显示了随着alcohol值的变化,葡萄酒质量的变化。单一值的垂直离差显示了与其他特征的交互作用。SHAP 自动选择另一个特征来着色,以使这些交互更容易看到:

单个特征的解释(图片由作者提供)

现在,让我们检查整个数据集,以确定哪些要素对模型最重要,以及它们如何影响预测。

解释整个数据集

通过绘制摘要图表,我们可以直观地了解特性的重要性及其对预测的影响。下面的方法根据所有样本的 SHAP 量值总和对要素进行排序。它还使用 SHAP 值来显示每个要素的影响分布。

颜色代表特征值,红色表示高,蓝色表示低。接下来我们来看看剧情:

整个模型的解释(图片由作者提供)

解释为:

  • 高酒精值增加了预测的葡萄酒质量
  • 低挥发性酸度提高了预测的葡萄酒质量

您现在已经知道了足够开始解释您自己的模型。让我们在下一部分总结一下。

离别赠言

起初,解释机器学习模型似乎很复杂,但像 SHAP 这样的库让一切变得像函数调用一样简单。我们甚至不必担心数据可视化,因为有内置的函数可以实现这一点。

这篇文章应该为您提供更高级的解释可视化的基础,并为您的进一步学习提供足够的信息。

你对 SHAP 有什么看法?请在下面的评论区告诉我。

加入我的私人邮件列表,获取更多有用的见解。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

原载于 2020 年 11 月 9 日 https://betterdatascience.com

认识熊猫最难的功能,第三部分

原文:https://towardsdatascience.com/shape-tables-like-jelly-with-pandas-melt-and-pivot-f2e13e666d6?source=collection_archive---------9-----------------------

用熊猫重塑桌子

形状像果冻的桌子有熊猫旋转()和融化()

照片由 Anastase MaragosUnsplash 上拍摄

介绍

我并不羞于承认。melt()pivot()对我来说是pandas中最难学的。我花了 3-4 个多月才想明白。当我第一次看到它们时,我试了又试,但不明白它们是如何或何时被使用的。所以,我放弃了,继续前进,再次遇见他们。尝试过,失败过,继续前进,再相遇。重复了很多次。

令我感到困惑的是,在这个有数百万视频和博客教程的时代,我找不到一个简单的好的来源可以更好地解释这些功能。我最喜欢的pandas博客,实用商业 Python,它涵盖了pandas的许多硬功能,好心地把它们省略了😔😔。而且,他们的文档只有在你完全了解这些功能后才有意义,一些网站(如果你搜索这些功能,它们的排名总是很高)只是复制文档😶😶。

所以,就像我最近一直在写的pandas的硬功能一样(它们表现得真的很好),现在是melt()pivot()的时候了。我希望这篇文章对面临类似困难的人有用。

[## 通过我的推荐链接加入 Medium-BEXGBoost

获得独家访问我的所有⚡premium⚡内容和所有媒体没有限制。支持我的工作,给我买一个…

ibexorigin.medium.com](https://ibexorigin.medium.com/membership)

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

[## 阿尔法信号|机器学习的极品。艾总结的。

留在循环中,不用花无数时间浏览下一个突破;我们的算法识别…

alphasignal.ai](https://alphasignal.ai/?referrer=Bex)

可点击的目录(仅限网络)

简介
设置
熊猫融()
熊猫融()
熊猫枢()

你可以从这个 GitHub repo 下载笔记本和样本数据。在每个函数第一次出现时,我还用超链接链接了它们的文档。

设置

熊猫融化()

让我们从一个非常愚蠢的例子开始。我将创建一个 1x1 的数据帧,保存一个城市名称和一天的温度。然后,我会在它上面调用[melt()](https://pandas.pydata.org/docs/reference/api/pandas.melt.html),看看它有什么效果:

>>> df.melt()

因此,在没有任何参数的情况下,melt()获取一列,并将其转换为包含两个新列的行(不包括索引)。让我们再添加两个城市作为列:

如果你注意到,这种数据帧格式不容易使用,而且不干净。最理想的是将列转化为行,它们的温度值在右边:

df.melt()

让我们为城市添加更多的温度:

如果我们在这个版本的数据帧上调用melt(),你认为会发生什么?手表:

df_larger.melt()

正如预期的那样,它将每个列值转换成一行。例如,让我们以一个键值对为例。纽约的气温是[25,27,23,25,29]。这意味着有 5 个键值对,当我们使用melt()pandas获取每一个键值对,并将它们显示为一行两列。在pandasNew York完成之后,它移动到其他列。

melt()在两列中显示每个键-值对时,它为这两列提供默认名称variablevalue。可以将它们更改为更有意义的内容:

var_namevalue_name可用于改变熔化数据框的列的标签。

如果我们继续添加列,melt()将总是把每个值转换成一个包含两列的行,这两列包含前一列的名称和它的值。

现在,让我们严肃一点。假设我们有这个数据框架:

这一次,我们已经把城市列成了一列。但是,这种类型的表格格式仍然没有用。该数据集包含 5 个城市 5 天的温度信息。我们甚至不能对这种类型的数据进行简单的计算,比如平均。让我们尝试熔化数据帧:

>>> temperatures.melt()

这不是我们想要的,melt()把城市名也变成了行。理想的情况是,我们将城市保留为列,并将剩余的列追加为行。melt()有一个名为id_vars的参数可以做到这一点。

如果我们只想把一些列变成行,那么把要保留的列作为一个列表(即使是单个值)传递给id_varsid_vars代表身份变量。

temperatures.melt(id_vars=['city'])

使用id_vars后,city列作为列留了下来。但是它变长了。原因是每个城市都有 5 天的观测时间。当我们从列中获取这些观察值并将其显示为行时,pandas会自动添加新的行来适应新的值。

即使我们有了更好的表,列名也不是我们想要的。我们可以直接用melt()来做,而不是在融化表格后手动更改它们:

具有不同列标签的相同数据帧。

熊猫在真实世界的数据上融化()

现在,是时候我们在真实世界的数据集上工作来证明这一点了。我将加载纽约股票数据集,可以使用这个链接从 Kaggle 下载。它包含超过 501 家公司 2016 年的股票信息:

我将只对一个月进行子集划分,因为每天都有观察:

现在,为了向您展示如何在真实世界的数据上使用melt(),我将使用pivot()执行一个操作,我将在本文后面教您。

数据现在是这样的格式:

500 行,22 列

它为所有公司提供了 500 行,为 2 月份的 22 天提供了 22 列。每个单元格包含股票在某一天的收盘价。我为什么选择这种格式?因为现实世界的数据经常是这种形状。

例如,当记录这个数据集时,假设他们想为新的一天添加一个新值。有 500 家公司,如果您不将新的一天作为新列添加,您将不得不再次写出 500 家公司,向数据集中再添加 500 行。对于记录这些数据的人来说,添加新的观察值作为新的列非常方便。

因此,现在我们想使用melt()将这个stocks_small数据集转换回它的原始格式,以便更容易处理。如果您再次查看数据,我们希望将所有日期列转换成两列,其中包含(日期,收盘价)键-值对,保留symbol列。就像我们在前面的例子中所做的一样,如果我们将symbol传递给id_vars,它保持为一列,其他日期将变成行:

Number of rows in melted table: 10500

将其与原始数据进行比较:

简而言之,melt()采用宽数据帧,并使其变长变细。

熊猫枢轴()

[pivot()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.pivot.html)melt()完全相反。有时,您会希望将干净的长格式数据转换为宽格式数据。让我们看看我是如何将子集stocks转换成更宽的格式的。这里有数据提醒你:

stocks_small.head()

现在,我将旋转表格:

500 行,42 列

>>> pivoted.shape
(500, 42)

当您使用pivot()时,请记住以下几点:

  1. pandas将接受您为index参数传递的变量,并将其唯一值显示为索引。
  2. pandas将接受您为columns传递的变量,并将其唯一值显示为单独的列。

如果你注意到了,上面的数据帧不是我们在melt()中使用的那个。那是因为它还包含了不仅仅是收盘价的股票价格。在pivot()中,有一个名为values的参数,如果没有指定,它会告诉pandas将所有剩余的列包含到旋转数据帧中。这次我们只选择close价格:

500 行,21 列

>>> pivoted2.shape
(500, 21)

pivot()差不多就是这样。令人惊讶的是,它是pandas中最难的函数之一,然而它只有 3 个参数,甚至没有一个额外的参数来填充缺失的值。

对于pivot(),只需记住它接受两个分类变量,并将它们的唯一值显示为索引和列。这个结果表将是这两个变量的网格。如果没有指定values参数,所有剩余的列将作为单元格值给出,这将使表格更宽。

如果你喜欢这篇文章,请分享并留下反馈。作为一名作家,你的支持对我来说意味着一切!

阅读更多与主题相关的文章:

[## 认识熊猫最难的功能,第一部分

掌握 pivot_table()、stack()、unstack()的时机和方式

towardsdatascience.com](/meet-the-hardest-functions-of-pandas-part-i-7d1f74597e92) [## 认识熊猫最难的功能,第二部分

掌握交叉表的时间和方式()

towardsdatascience.com](/meet-the-hardest-functions-of-pandas-part-ii-f8029a2b0c9b) [## 想要 Jupyter 的进度条吗?

对你的长时间循环进行健全性检查(和一点视觉风格)

towardsdatascience.com](/ever-wanted-progress-bars-in-jupyter-bdb3988d9cfc) [## 来自 Kagglers:DS 和 ML 的最佳项目设置

来自顶级 Kagglers 的项目成功最佳实践的集合

towardsdatascience.com](/from-kagglers-best-project-setup-for-ds-and-ml-ffb253485f98) [## 我习惯如何将数据与熊猫绑定

您可能只使用了默认值

towardsdatascience.com](/how-i-customarily-bin-data-with-pandas-9303c9e4d946) [## 掌握连接:Pandas 合并、连接、追加方法

从半连接/反连接到验证数据合并

towardsdatascience.com](/masteriadsf-246b4c16daaf)

共享数据信息学:AWS Quicksight with Wordpress

原文:https://towardsdatascience.com/sharable-data-informatics-aws-quicksight-with-wordpress-4f5793469123?source=collection_archive---------24-----------------------

了解如何在 Wordpress 中使用 AWS Quicksight

为什么要使用带有 AWS Quicksight 的 Wordpress?

Wordpress 可以说是最简单、下载量最大的内容管理平台(CMS ),任何人都可以在几分钟内快速建立网站并展示内容。

那么亚马逊网络服务 (AWS) Quicksight 呢?简而言之,Quicksight 是一个完全托管的数据可视化解决方案。其竞争对手有 Tableau、Looker、Domo、qLik、SiSense、微软 Power BI 等等。您只需编写很少的代码,主要使用拖放式 GUI,并且不需要管理任何服务器、安全、备份等。

它提供了一个简单的用户仪表板,让您能够创建各种不同的可视化,动态编辑数据,从各种不同的来源(mySQL、postgres、csv/xls/)引入数据。json、presto、spark 等……)此外,您可以使用预建的第三方连接器 (Salesforce、github、Twitter、吉拉、雪花等),具有开箱即用的兼容性( HIPAA 和 HITRUST ),并且可以轻松(???)嵌入在其他应用程序中。

因为我在医疗保健行业工作,所以 AWS quicksight 是一个很容易尝试的工具,因为它符合 HIPAA & HITECH,并且具有很高的可扩展性。

你今天要学什么?

在接下来的文章中,我将详细介绍如何将 AWS Quicksight 仪表板连接到 Wordpress 实例中。

这会给你留下一个坚实的 MVP。您应该对 Wordpress (PHP、HTML)、AWS (IAM 策略)、SSH(终端导航)有所了解,才能按照步骤进行操作。

  • 第 1 部分:让服务器启动并运行
  • 第 2 部分:获取 AWS Quicksight 设置和发布带有虚拟数据的仪表板
  • 第 3 部分:在 AWS 中配置 IAM 凭证,这样我们就可以通过 Wordpress 服务器以编程方式访问 AWS Quicksight
  • 第 4 部分:和创建一些定制的 PHP 来检索动态生成的带有安全密钥的 URL,以便仪表板在 Wordpress 中显示

您将使用的工具包括

**## Tools/Themes Utilized for This MVP** - INSTALLED on the Wordpress Server:  
  - AWS CLI 2.0
  - JQ 
  - Wordpress **theme**: Divi (but you can choose whatever) 
  - Wordpress **host**: AWS lightsail + AWS Route 53 
  - Wordpress **plugins**:
    - ZYZ PhP Code 
- SERVERLESS AWS tools: 
  - AWS IAM  
  - AWS Quicksight

重要提示:要完全完成本教程,您需要启用企业版 Quicksight。 AWS 只允许在企业版中嵌入仪表盘。企业与一个创造者的成本将是每月 18.00 元美元。所以,如果你能在这个教程上挥霍一点,那就去做吧…否则我建议你还是跟着做,因为我希望 AWS Quicksight 会尽快发布这个功能到他们的标准计划中。

现在让我们开始吧!

第 1 部分:获取 Word Press 设置

为了让一个 Wordpress 实例快速运行起来没有太多麻烦,我推荐 AWS Lightsail (如果你已经在使用其他 AWS 服务的话)。这是非常简单的设置。例如,使用 Lightsail,您不需要像配置 EC2 实例那样配置端口(如:80 或 443 ),这样站点就可以被互联网上的外部查看者查看,并且它简化了域名管理和 VPCs/其他网络需求的流程。

出于我们的目的,带有 Wordpress 5 . 3 . 2–3 蓝图的 linux 平台将满足我们的需求。参考消息 AWS 提供的 Wordpress 风格是一个位图图像

如果你在这一步遇到困难,请点击此处观看视频说明

创建完映像后,您将希望通过 SSH 进入平台来安装一些工具。AWS 让这变得非常简单,只需点击“使用 SSH 连接”的大按钮

这将在您的 web 浏览器中打开一个终端,我们将使用它来安装一些程序:

工具 1: AWS CLI 2.0 :这是 AWS 提供给我们的命令行工具,我们可以通过终端使用它们的服务。您应该能够用两个命令来安装它:

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"unzip awscliv2.zip && sudo ./aws/install

您现在应该已经安装了 AWS CLI。您可以通过执行以下命令来确认它已成功安装

aws --version

工具 2:https://stedolan.github.io/jq/的 JQ 是一个命令行工具,它将帮助我们在终端中解析来自 AWS CLI 的 JSON 响应。相当酷!该程序的安装非常简单,只需执行:

sudo apt-get install jq

为了让这个练习更加真实,我建议你将一个域映射到你的新 Wordpress 实例。因此,你和潜在用户可以不去 37.125.157.64,而是去像ilikedatastuff.com、这样人类可读的地方,或者为你已经拥有的域名创建一个新的子域(wordpress.ilikedatastuff.com)。

此外,还要启用 SSL。如果你对 AWS Lightsail 上的 Bitnami Wordpress 站点的免费 SSL 感兴趣,请跟随这篇教程。

最后,你可能已经注意到在网站的右下角有一个烦人的Powered by Bitnami横幅。要将横幅 SSH 移回到运行 Wordpress 的服务器中,请执行以下命令:

sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1 sudo /opt/bitnami/ctlscript.sh restart apache

工具 3:插入 PHP 代码片段

现在,我们需要在 Wordpress 服务器上安装的最后一个工具在前端。用凭证登录你的 Wordpress 站点的管理门户(www.domainname.com/管理员):

用户名 : user

密码:password位于你的 Wordpress 服务器上一个名为bitnami_credentials的文件中。你可以通过 SSH 进入文件夹服务器,使用 nano 文本编辑工具做nano bitnami_credential来打开它。

如果您在这一步遇到困难,请在此处观看视频说明/

现在转到管理门户的插件部分,搜索插入 PHP 代码片段插件。通过安装这个插件,我们将能够编写一点点定制的 PHP 代码来自动查看 Wordpress 中的仪表板。

现在到 AWS Quicksight!

第 2 部分:获取 AWS Quicksight 设置

当你安装 AWS quicksight 时,你首先要做的是点击右上角的人物头像并导航到Manage Quicksight

步骤 1:管理 Quicksight

启用企业版后,您应该会看到如下所示的内容,版本为:Enterprise。

如果您没有看到上面显示的所有选项,这很可能意味着您没有启用企业版的 quicksight,并且在启用之前无法执行仪表板嵌入。

现在先导航到Domains and Embedding部分。

在这里,我们将把您的域名列入白名单,方法是输入您选择的带有www.DOMAINNAME.comDOMAINNAME.com但不带 www 的域名。

这将确保一旦我们将仪表板嵌入到我们的站点中,它们将有适当的安全权限来显示。如果我们不将域名放在这里,我们将会收到与不正确的查看权限相关的错误消息。如果您使用的是子域,请确保通过Include Sub-domains?问题点击/启用复选标记框。

步骤 2:发布虚拟数据

幸运的是,Quicksight 已经提供了一些虚拟数据。

当您在主屏幕上的 All Analyses 下时,您将看到四组虚拟数据(仪表板),其中包含各种不同的图表。

挑一个你想要的。为了发布,一旦您选择了仪表板(您想要使用的示例数据),请转到右上角,那里有一个标记为Share的按钮

为仪表板命名。在Advanced publish option下,您可以选择想要启用的选项。我选择了它们来全面测试所有功能。

接下来,您可以选择深入了解谁有权访问这组特定的数据。因为这是一个演示环境,并且很可能您没有任何其他用户——您可以保持选中Share with all users in this account。然后单击共享。

呜哇!一大步完成了。现在,在你浏览器的顶部有你的地址栏,现在我们需要复制部分的网址。例如,我的链接如下所示(为了安全起见,我稍微修改了数字):

https://us-east-1.quicksight.aws.amazon.com/sn/dashboards/69301f52-e492-44fd-69cf-dfd79e622dc6

与我们相关的部分是跟在…/sn/dashboards/{重要数字集} 后面的 URL 代码

对我来说,应该是:**92301f69-e492-44fd-69cf-dfd79e6ffdc6**这部分 URL 是静态的,将被 Wordpress 服务器上的 AWS CLI 工具使用。

现在,当一个外部应用程序(node.js、python、php)试图使用这个嵌入的 URL 时,它还需要将一个额外的安全密钥附加到这个静态 URL。这个安全密钥是通过对 AWS 的 API 请求生成的,大约每 10 分钟过期一次(?)来维护安全。我为什么要提这个?

因为拥有这个 URL 还不足以让仪表板嵌入工作。你不能只是将这个 URL 嵌入到 iFrame 中,然后期望它能工作——它不会工作,因为它缺少安全密钥。

因此,要做到这一点,我们必须创建几行自定义 PHP 代码,允许我们的 Wordpress 站点调用 AWS Quicksigh API,并向它提供一些用户详细信息,然后接收包含我们的安全密钥的响应,以显示 Quicksight 仪表板。如果这还没有意义,那也没关系。有一些关于 AWS 的文档详细介绍了这一点。

第 3 部分:IAM 凭证

登录 AWS 管理控制台,导航到 IAM,然后导航到策略。

我们希望创建一个新策略,并将其附加到我们现有的帐户(或另一个帐户)中,以授予 1)获取注册 Quicksight 用户和 2)嵌入仪表板 URL 的权限。对于那些跟随的人,这在 AWS 文档的第 2 部分中有描述。

当您阅读他们的文档时,您会看到类似这样的内容:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "quicksight:RegisterUser",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "quicksight:GetDashboardEmbedUrl",
            "Resource": "arn:aws:quicksight:us-west-2:11112222333:dashboard/22a7dcbd-7890-6956-9f87-ffd9876ab432",
            "Effect": "Allow"
        }
    ]
}

在很大程度上,我们可以将所有这些内容复制并粘贴到我们的新策略中,但有以下例外。我们想要更改的部分在下面以粗体显示:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "quicksight:RegisterUser",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "quicksight:GetDashboardEmbedUrl",
            "Resource": "arn:aws:quicksight:**us-west-2:11112222333**:dashboard/**22a7dcbd-7890-6956-9f87-ggd9876ab432**",
            "Effect": "Allow"
        }
    ]
}

第一部分是位置和帐户标识(us-west-2:1111222333),第二部分是我们想要共享的仪表板的静态 URL(69 a7 dcbd-7890–6956–9 f87-ffd 9876 ab 469)

例如,我的仪表板位于 us-east-1,我的帐号位于 AWS quicksight 的用户下。静态 URL 应该替换为您之前保存的自己的 URL。

一旦您修改了策略,请保存它。然后,您应该将此策略分配给已经创建的用户帐户,或者创建一个新用户,然后将此策略分配给他们。确保您拥有用户访问密钥 ID(一个类似于 AKIZX…leug1 的 20 个字符的密钥)以及一个类似于 XLUz…reqjnlag 3 fy…的 40 个字符的密钥。NdDsHF)。

现在到了最后一步!

第 4 部分:用 Quicksight 连接 Wordpress

以管理员身份登录你的 Wordpress 站点,并导航到我们在第 1 部分中安装的 PHP 插件。

您应该会看到类似如下的菜单:

正如你所看到的,我已经创建了 2 个包含一些 PHP 的短代码,分别命名为 dashboard1dashboard2

点击按钮Add New PHP Code Snippet并插入以下代码块。我用粗体显示了您将在自己的数据中插入的部分:

<?php
$region='**YOUR REGION**';
$key='**YOUR KEY ID**';
$secret= '**YOUR SECRET**';
putenv('AWS_DEFAULT_REGION=' . $region);
putenv('AWS_ACCESS_KEY_ID=' . $key);
putenv('AWS_SECRET_ACCESS_KEY=' . $secret);
$cmd2 = "aws quicksight get-dashboard-embed-url --aws-account-id **YOURACCOUNTID** --dashboard-id **YOURDASHBOARDURL** --identity-type IAM | jq -r '.EmbedUrl'";
$exec2 = shell_exec($cmd2);
settype($exec2, "string");
$regions= '"'.$exec2 .'"';
$regions = preg_replace('/\s+/', '', $regions);
echo $regions;
?>

上面这个东西是做什么的?

首先,它为我们的 AWS 帐户创建了三个变量,分别包含 region、key 和 secret(第 2–4 行)。然后,它利用putenv将这些存储为环境变量(第 5–7 行)。接下来,我们创建一个名为cmd2的变量,它将存储一个终端命令,该命令利用我们的AWS CLI工具请求生成一个新的安全密钥以及我们的嵌入式 url(第 8-10 行),并解析用jq返回的 JSON 响应,以提取我们的新嵌入式 URL 和安全密钥。然后,它使用*shell_exec* 运行终端命令,并将输出保存在一个名为 exec2 的变量中(第 11 行),使该变量成为一个字符串(第 12 行),向它添加双引号(第 13 行),最后删除任何空格(第 14 行)最后一行echo $regions打印出我们最终的、干净的 URL,带有现在可以被 iFrame 接收的安全代码。

现在来看粗体部分。让我们填入这些变量。下面是一些 假数据 的例子,包含 右结构和字符数 :

**YOUR REGION**: us-east-1
**YOUR KEY ID**: AKIAKF9MOV69S9LEVQG9
**YOUR SECRET**: EHavae9Lf4VNSA1I696w+EInQpAvQr2U5bTf5+Ju
**YOURACCOUNTID:** 351333326999 **YOURDASHBOARDURL**: 69401f25-e469-4a7f-92gm-dfd69e611dc6

所以最终版本应该是这样的:

<?php
$region='us-east-1';
$key='AKIAKF9MOV69S9LEVQG9';
$secret= 'EHavae9Lf4VNSA1I696w+EInQpAvQr2U5bTf5+Ju';
putenv('AWS_DEFAULT_REGION=' . $region);
putenv('AWS_ACCESS_KEY_ID=' . $key);
putenv('AWS_SECRET_ACCESS_KEY=' . $secret);
$cmd2 = "aws quicksight get-dashboard-embed-url --aws-account-id 351333326999 --dashboard-id 69401f25-e469-4a7f-92gm-dfd69e611dc6 --identity-type IAM | jq -r '.EmbedUrl'";
$exec2 = shell_exec($cmd2);
settype($exec2, "string");
$regions= '"'.$exec2 .'"';
$regions = preg_replace('/\s+/', '', $regions);
echo $regions;
?>

点击保存,给它起一个好记的名字,比如dashboard1。这将为您提供一个短代码,该代码可以插入到一个网页中,该网页为您提供带有安全代码的新嵌入 URL。

我的短码是[xyz-ips snippet="dashboard1']

最后一步:

现在是时候创建一个新的空白 Wordpress 页面了,我们将插入 HTML 代码和新的 PHP 短代码(输出新的嵌入式 URL +安全代码链接)以显示 iFrame。

第一步:新建一个空白页:

第二步:创建一个新的文本框。以 HTML 模式查看并插入以下代码,用您自己的 PHP 代码片段名替换粗体部分:

<!DOCTYPE html>
<html>
<head>
    <title>Basic Embed</title>
    <script type="text/javascript" src="[https://unpkg.com/amazon-quicksight-embedding-sdk@1.0.2/dist/quicksight-embedding-js-sdk.min.js](https://unpkg.com/amazon-quicksight-embedding-sdk@1.0.2/dist/quicksight-embedding-js-sdk.min.js)"></script>
    <script type="text/javascript">
        function embedDashboard() {
            var containerDiv = document.getElementById("dashboardContainer");
            var params = {
                url: [xyz-ips snippet="**dashboard1**"],
                container: containerDiv,
                height: "1100px",
                width: "1200px"
            };
            var dashboard = QuickSightEmbedding.embedDashboard(params);
            dashboard.on('error', function() {});
            dashboard.on('load', function() {});
            dashboard.setParameters({country: 'Canada'});
        }
    </script>
</head>
<body data-rsssl=1 data-rsssl=1 data-rsssl=1 data-rsssl=1 data-rsssl=1 onload="embedDashboard()">
    <div id="dashboardContainer"></div>
</body>
</html>

这里发生了什么事?我们利用了由官方 AWS 文档提供给我们的一些代码来通过 HTML 嵌入。你可以看到它调用了一个由 AWS 为 Quicksight 创建的 javascript helper 包(https://UNP kg . com/Amazon-quick sight-embedding-SDK @ 1 . 0 . 2/dist/quick sight-embedding-js-SDK . min . js),然后中途摄取了一个由我们的 PHP 插件小部件提供的变量 URL。

第三步:点击保存,退出预览模式。发布页面。

我在我的例子中使用了 DIVI Wordpress 主题来做一些样式设计,所以它看起来可能和你的不同。但是你现在应该看到的是嵌入在你自己的 Wordpress 页面上的 AWS quicksight 仪表盘。

感谢阅读!

如果你有问题,给我发消息,在 Linkedin 上关注我:https://www.linkedin.com/in/hantswilliams/

可共享的 Jupyter 笔记本!

原文:https://towardsdatascience.com/sharable-jupyter-notebooks-bf3ec9c2e0be?source=collection_archive---------46-----------------------

最后,团队可以快速、轻松地共享和测试代码

好的,它叫做,可以在 Google Drive 中找到。

什么牛逼?

  • 团队和协作者可共享的笔记本。
  • 体面的规格
  • 免费 GPU 访问
  • 预装的机器学习库,如 NumPy 或 Tensorflow
  • 导入现有笔记本

这是谷歌的描述:

装置

在你的 google drive 上,只需右击文件夹中的任意位置。

进入'更多** ' > ' 连接更多 app**

在 G Suite Marketplace 中,您可以搜索“ Colaboratory ”并安装它。

****搞定

使用合作实验室

打开它,你会看到一个和 Jupyter 笔记本非常相似的界面。

我不会进入编码部分,因为我假设你们都熟悉 Jupyter 笔记本,但让我们看看一些功能。

变暗模式

转到界面左上角的设置(齿轮图标)。在“网站”标签下的“主题”选择黑暗。

唷!现在我们可以开始了。

目录

在右侧,我们可以看到 3 个选项卡。

第一个让我们看到目录。在我正在玩的笔记本上,你可以看到我创建了一个名为' PDF 和 CDF 的部分和一个名为'卷积的部分。

分区是整理笔记本的好方法。

在 Colaboratory 中,可以通过以下方式创建它们:
—单击
目录选项卡
中的“
+部分”按钮,或者只需添加文本并将其格式化为标题(例如:' # Title1 ')。

代码片段

下一个选项卡是代码片段。合作实验室为你提供了一些非常有用的默认代码片段。有些很酷,比如相机抓拍。

您可以添加自己的代码片段。但据我所知,这有点复杂。我是这样做的。

  1. 创建一个新笔记本,随你怎么命名。我把我的笔记本叫做片段
  2. 为每个片段创建一个标题,并添加您的片段。例如,这里我有两个带有一些随机代码的片段。

3.然后只需复制你的片段笔记本的网址,打开设置(左上角的齿轮图标)。
在“
站点选项卡>下的“自定义片段笔记本网址”>粘贴您的片段网址并点击“保存”

4.搞定了。现在,您的代码片段可以根据其标题名称在代码片段部分进行搜索。例如,如果我在我的新笔记本中搜索 Imports

我可以访问我创建的代码片段!当代码不断被重用时,这是一个非常有用的特性。

文件管理器

这很好,因为它给你一个简单的方法来查看你所有的文件。我的原始笔记本似乎带有一些样本数据,我觉得很奇怪,但感谢谷歌。

如果你注意到皮卡丘的图像,我可以在网上抓拍一张照片,然后很容易地保存到我的文件管理器中(通过)!wget** )。酷的是,我们可以点击这些文件,并从合作实验室查看它们。**

您可以看到 CSV 文件和图像都是受支持和可查看的。这对于能够快速浏览文件而不必去我的本地文件目录或 GDrive 是很棒的。

共享

如果你曾经使用过谷歌文档,你可能已经知道如何分享文档。只需点击分享图标,将联系人添加到您的笔记本或发送链接给他们。

您还可以通过将鼠标悬停在某个单元格上并选择共享图标来链接到特定的单元格(当您的笔记本变得疯狂时)。

GPU 访问

最好的功能之一是提供的 GPU 访问。在工具栏上选择'运行时'** > ' 更改运行时类型',您可以在 GPUTPU 之间进行选择。**

这使得一些复杂的过程明显更快。Head 这里查看更多关于谷歌提供的规格的信息,因为它可能会随着时间的推移而改变。目前,你可以在启用 GPU 的情况下运行一台笔记本电脑12 个小时,考虑到其,这已经相当不错了。如果你想超越这一点,他们确实提供了付费层的选择。

合作实验室实际上是一个很老的东西,我只是不知道。我认为它是在 2017 年发布的,但我直到最近才听说它。但是不得不说功能超级酷,非常有用。有很多很棒的功能我没有介绍,所以如果我错过了什么很棒的功能,请在评论区随意评论,我相信它会帮助每个人,感谢阅读!

如果你喜欢这个故事,看看我的其他作品,

*** [## 数据可视化:动画条形图!

Excel 和 After Effects 中的数据可视化和动画

towardsdatascience.com](/data-visualization-animate-bar-graphs-df9ca03a09f2) [## 机器学习——处理缺失数据

开始使用数据前如何清理数据的指南。

towardsdatascience.com](/machine-learning-handling-missing-data-27b09ab146ba)***

借助这一新的 Streamlit 功能,您可以更轻松地共享您的项目

原文:https://towardsdatascience.com/share-your-projects-even-more-easily-with-this-new-streamlit-feature-a9be81a4ecfd?source=collection_archive---------24-----------------------

为数据科学家记录和分享:图片来自 Pixabay

为数据科学家记录和分享

如果我们没有一个好的方式来展示它,机器学习项目就永远不会真正完成。

在过去,一个制作精良的可视化工具或一个小 PPT 足以展示一个数据科学项目,随着 RShiny 和 Dash 等仪表板工具的出现,一名优秀的数据科学家需要具备相当多的 web 框架知识。

正如斯登冲锋枪·苏特拉在他的讽刺作品中所说,我非常喜欢:

秘诀:重要的不是你知道什么,而是你表现出什么。

这就是 StreamLit 的用武之地,它提供了一种只使用 Python 创建 web 应用程序的方法。在过去的几个月里,我一直在密切关注这个优秀的产品。在我的前几篇帖子中,我谈到了使用 Streamlit 以及如何使用 ec2 部署 Streamlit 应用。我也一直与 Streamlit 团队保持联系,他们一直致力于通过发布更多功能来改善用户体验。

那么,在向利益相关者/业务合作伙伴解释应用程序的工作方式时,您是否遇到过问题?不得不与不同国家的不同利益相关方进行多次通话,并一遍又一遍地解释整个过程?

或者你做过一个项目,想在社交媒体上分享?LinkedIn,Youtube 之类的?

在他们的新版本中,Streamlit 发布了一个名为“ 录制一个截屏视频 ”的新功能,将为您解决这个问题。

怎么会?请继续阅读。

安装

因此,为了检验这个新特性,它是 streamlit 版本0.55.0的一部分,我们需要首先安装或升级 Streamlit。使用以下命令完成此操作:

pip install --upgrade streamlit

我们还需要运行 Streamlit。这里我将使用演示应用程序。你也可以使用任何你自己的应用程序。

streamlit hello

您应该会看到类似下面的内容:

在你的浏览器中还会打开一个标签,你可以在那里尝试他们的演示。如果没有在浏览器中打开,您也可以手动转到本地 URL [http://localhost:8501/](http://localhost:8501/)

录制截屏

现在是时候录制我们的视频与世界分享了。您可以使用 Streamlit 右上角的菜单找到录制截屏的选项。

一旦你点击它,你会得到录音的选项,你可以选择名副其实的“开始录音”按钮开始录音。

然后,您可以选择想要共享的内容,是您的 streamlit 应用程序还是您的整个桌面。 如果用户需要在不同的程序之间切换,例如 Excel 表格、powerpoints 和 streamlit 应用程序,他们可以选择共享整个桌面。 在这里,我选择只显示“Streamlit”应用程序,然后点击“分享”。

您的截屏现在已经开始,您现在可以为您的股东录制解释会议。完成录制后,您可以再次单击右上角的菜单并选择停止录制。或者方便地按 escape 来结束记录会话。

你将能够预览并保存你录制为.webm文件的会议视频,你可以将它发送给你的股东,甚至在 LinkedIn/twitter/youtube 上分享你的个人项目。

仅此而已。这个过程非常简单,不需要我们安装任何额外的软件。

尾注

Streamlit 使创建应用程序的整个过程民主化了。

老实说,我喜欢 Streamlit 开发产品的方式,牢记用户的所有痛点。通过这次迭代,他们解决了另一个痛点,即用户难以在社交媒体网站上以有意义的方式展示自己的工作,或者向股东多次解释应用程序的工作原理。

最重要的是,Streamlit 是一款免费的开源软件,而不是开箱即用的专有网络应用。我不能推荐它。

此外,如果您想在评论区 请求 Streamlit 中的任何附加功能,请务必通知我。我会确保将其传达给 Streamlit 团队。

如果你想了解更多关于使用 Streamlit 创建和部署应用程序的信息,可以看看我的其他帖子:

[## 如何为数据科学家使用简单的 Python 编写 Web 应用?

无需了解任何 web 框架,即可轻松将您的数据科学项目转换为酷炫的应用程序

towardsdatascience.com](/how-to-write-web-apps-using-simple-python-for-data-scientists-a227a1a01582) [## 如何使用 Amazon Free ec2 实例部署 Streamlit 应用程序?

10 分钟内将数据应用程序上传到网上

towardsdatascience.com](/how-to-deploy-a-streamlit-app-using-an-amazon-free-ec2-instance-416a41f69dc3)

如果你想了解创建可视化的最佳策略,我想从密歇根大学调用一门关于 数据可视化和应用绘图 的优秀课程,它是一个非常好的 数据科学专业的一部分,本身带有 Python 。一定要去看看。

谢谢你的阅读。将来我也会写更多初学者友好的帖子。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。

此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

在 VirtualBox 中共享数据可视化,让 IT 部门满意

原文:https://towardsdatascience.com/sharing-data-visualisations-in-virtualbox-to-keep-it-departments-happy-f978854ea44d?source=collection_archive---------45-----------------------

当您的客户端无法使用容器或云时,如何将 Jupyter 演示作为独立的 VirtualBox 映像共享

在 Jupyter 或类似的原型环境中从事概念验证模型或演示的数据科学家需要找到一种方法,以便在项目完成时与客户分享。在他们的机器上复制成功运行它的环境并不容易。

Docker 提供了再现性的解决方案——环境和工作空间文件可以打包成一个图像。

然而,确保它能够在企业环境中轻松部署到客户端并不总是那么简单。他们的 IT 部门可能没有资源在云或内部服务器上临时托管应用程序;可能不允许在用户自己的计算机上安装 Docker Desktop。

一个路障,就像你的 IT 部门……(由杰米街Unsplash 上拍摄)

VirtualBox 是一个历史悠久的软件组件,被 IT 部门普遍接受,在大多数企业中只需很少的繁文缛节就可以安装。

本文描述了打包 Jupyter 笔记本环境的步骤,最初是作为 Docker 映像,但最终会作为独立文件发送给客户,可以直接导入到他们机器上的 VirtualBox 中。

这是一个我们可以在 ContainDS 为企业客户自动化的过程,但是下面描述的手动步骤将提供最重要的方面。

我们的 Jupyter Voila 演示样本

保存您的 Jupyter 体验

你的项目最重要的部分当然是首先构建可视化。我不会教你如何做到这一点…但就本文的目的而言,我们将假设它在一个本地 web 应用程序中,如 Jupyter notebook,或者如果你希望它对客户端更友好,Jupyter Voila 演示。

在这种情况下,有大量的指南来与 Docker 一起工作,以建立您的项目的图像,您可以与他人分享,或者如果您想完全不必了解 Docker,那么我们的桌面应用程序 ContainDS 将为您完成这一切,包括将您的基于 Jupyter 的环境转换为 Voila 演示。

对于这篇文章,我们将只使用一个简单的例子 Voila 演示,我已经将它打包成一个图像,并上传到 Docker Hub

我在 Mac 上运行这些步骤,但 Windows 非常相似。

使用 VirtualBox

我们有机会首先在自己的计算机上设置我们的 VirtualBox 虚拟机(VM ),加载 Docker 映像并设置一些其他配置。然后,我们将其导出为单个“OVA”文件,发送给客户端。

创建 VirtualBox 计算机的副本

我们将从 Docker 提供的 VirtualBox 映像开始,以便在 VM 中运行 Docker。这实际上是在 Docker Desktop 没有在 Mac 或 Windows 上本地运行的时候,但它在这里很有用。

从技术上讲,在这个虚拟机中直接与 Docker 交互是可能的——不需要在我们的计算机上本地安装任何 Docker 产品——但这需要更多的工作。有一个叫做 docker-machine 的产品,我们可以用它来初始化 VirtualBox 虚拟机,使其包含 docker 守护程序,并使我们能够从主机访问其 Docker 守护程序。如果我们的机器上有 docker 命令行工具,事情也会变得更简单。

因此,你应该安装 Docker 工具箱。安装程序包含 VirtualBox 以及 docker-machine 和 docker 命令。你可以从 GitHub 发布页面下载最新的 pkg 安装程序(Mac 版)或 exe(Windows 版)。

创建 VirtualBox 虚拟机

使用 docker-machine 在 VirtualBox 上创建一个包含 Docker boot2docker 映像的新虚拟机。我们将该虚拟机称为“dsdeploy”。在终端窗口中运行:

docker-machine create --driver virtualbox dsdeploy

然后配置我们的终端在 VM 中访问 Docker,而不是期望与在主机上本地运行的 Docker 守护进程一起工作。

docker-machine env dsdeploy

这将显示需要在计算机上设置的环境变量的详细信息。一旦设置好了(设置这些的命令应该通过你刚才运行的‘env’命令出现在你的屏幕上),docker命令现在将与 VM 中的 Docker 对话。

运行以下命令来获取我们项目的样本 Voila 演示 Docker 映像,并将其设置为作为新容器运行,所有这些都在我们的新 VM 中:

docker pull danlester/voila-sincos:de3b79a7docker run -p 8888:8888 danlester/voila-sincos:de3b79a7

这将从 Docker Hub 获取图像,然后启动一个新的容器,在端口 8888 上显示 Jupyter/Voila 服务器。

自动启动容器

我们可以现在就导出虚拟机,并与客户端共享。然而,我们忽略了一些能让我们的接收者更容易接受的东西。

当冷导入到他们自己的 VirtualBox 时,Docker 容器将仍然存在,但不会运行。他们必须获得一个进入虚拟机的终端,并让它再次运行。也很难知道他们在网络浏览器中访问 Voila 服务器需要什么 URL,所以我们会想办法通知他们。

在您的主机上创建一个名为docker_start_webapps的文本文件,包含以下内容:

echo -e "\n\n Starting all web apps..."docker start $(docker ps -a -q)echo -e "\n ******* \n\n Please visit this address in your web browser\n"ifconfig -a eth1 | grep 'inet addr' | awk -F '[: ]+' -v OFS='' '{print "http://",$4,":8888/"}'echo -e "\n ******* \n"

这个脚本将启动所有停止的容器,并输出访问 Voila 演示所需的 URL。它非常适合作为我们虚拟机引导过程结束时的启动脚本。

使用以下命令将文件复制到虚拟机:

docker-machine scp docker_start_webapps dsdeploy:/var/lib/boot2docker/docker_start_webapps

接下来,我们需要 ssh 到 VM 来完成引导过程,并确保我们的新脚本在启动时被调用。在您的终端上运行以下命令:

docker-machine ssh dsdeploy -t

现在,在虚拟机中新创建的 ssh 会话内运行以下命令:

sudo chmod a+x /var/lib/boot2docker/docker_start_webappssudo chmod o+w /var/lib/boot2docker/profilesudo ln -s /var/lib/boot2docker/docker_start_webapps /etc/profile.d/docker_start_webapps.shsudo chmod o-w /var/lib/boot2docker/profile

这里的要点是将我们的新启动脚本链接到/etc/profile.d 文件夹中,这样它将在启动时自动运行。

键入exit退出 ssh 会话。

每次重启时,虚拟机的很大一部分都会被擦除和重新初始化,因此我们需要一些变通方法来确保我们的启动脚本是永久的。

导出 VirtualBox 虚拟机

我们终于准备好将虚拟机导出为文件,与我们的客户端共享。

运行以下命令暂停虚拟机:

docker-machine stop dsdeploy

然后使用 VirtualBox 的 VBoxManage 命令将虚拟机导出为自包含文件:

VBoxManage export dsdeploy --iso -o voila_sincos_saved.ova

如果由于某种原因无法运行 VBoxManage 命令,可以使用 VirtualBox GUI 应用程序完成上述操作。(导出为 OCI 容器,确保包含 ISO 映像。)

与客户分享

OVA 文件 voila_sincos_saved.ova 可以使用大型安全文件的常用通道发送到您的客户端。请注意,它将超过 1 GB,所以电子邮件将不足够!

在他们的计算机上,他们应该像往常一样运行友好的 VirtualBox GUI 应用程序。在“文件”菜单中选择“导入设备…”

将 OVA 文件导入 VirtualBox

找到 OVA 文件,并使用默认设置导入它。

当虚拟机启动时,将会有一个有限的屏幕显示,但应该足以看到我们提供的最终说明:“请在您的网络浏览器中访问此地址”以及 Voila 演示文稿的 URL。

当我们的接收者导入时,虚拟机的基本显示

如果他们访问这个 URL,他们应该能够与我们的演示交互,就像我们创建它一样!

结论

找到一种在云中托管这个 Voila 应用程序的方法肯定会更好。但有时这是不可能的,例如,如果你没有权限在云中托管所有相关数据,或者如果你不能指望在预定观看演示的位置可靠地访问互联网。

另一种“更纯粹”的方法是以 Docker 图片的形式直接分享演示文稿。我们的包含桌面软件很容易实现这一点,正如最近的另一个教程中的所描述的,但是这依赖于 Docker 可以安装在源机器和目的机器上。

我希望这篇文章可以帮助你,如果你有这个非常具体的需要,以确保客户可以通过 VirtualBox 访问你的作品。

在您的本地机器上使用数据科学环境是我们 ContainDS 每天都在考虑的事情,我将非常高兴听到您如何应对这些挑战,或者您是否需要任何帮助。

如何与客户安全共享 Streamlit 应用

原文:https://towardsdatascience.com/sharing-streamlit-apps-securely-with-your-clients-a34bf0f9e00c?source=collection_archive---------13-----------------------

Streamlit 的框架允许轻松开发数据科学仪表板。以下是与他人共享您完成的应用程序的一些选项。

数据科学界已经热切地接受了 Streamlit 作为一个常见问题的解决方案。您可能在 Jupyter 笔记本或 Python 脚本中构建了您的模型,并向自己演示了当您更改一些输入时它是如何运行的。也许你可以把这个展示给一位数据科学同事,他正从你的肩膀上看着你的笔记本电脑。但是,对于不愿意阅读您的代码并通过笔记本进行 shift-enter 操作的客户或同事来说,您将如何让他们相信这一切呢?

Streamlit 使用纯 Python 脚本和自己的简单 API 来推断一个现代化的交互式 UI。你可以在他们的网站上找到更多信息,如果你还没有的话!

Streamlit.io 项目网站

托管选项

一旦你设计了你的样本应用程序,有几种在线托管的可能性。Streamlit 开发人员有一个测试版产品 Streamlit for Teams,它允许您“毫不费力地部署、管理和协作应用程序”。

论坛和常见问题也详细说明了如何在 Heroku、Azure 和 AWS 上进行托管。如果你经常使用这些云提供商,这是有用的,但没有自动认证层:除非你乐意向所有人开放应用程序,否则你需要更努力地考虑这个问题。

当然,所有的托管解决方案都可能有相关的成本,并且您的 IT 部门或信息官可能会限制在那里存储客户数据。

丹尼尔·帕斯科在 Unsplash 上的照片

本地复制

对于一个一次性的应用程序来说,为你的客户找到一种在他们自己的机器上运行脚本的方法是最有意义的。在企业环境中,期望您的客户端安装诸如 Python、conda 或 pip 之类的命令行工具通常是不合适的;即使你走这条路,平台和安装之间的细微差别也意味着你不能保证他们会看到和你一样的结果!

集装箱化是解决再现性问题的一个很好的方法。同样,您不希望留给您的客户端一个命令行指令列表。ContainDS 是一款用户友好的软件,通过图形用户界面运行可复制的环境。它可以主要在幕后使用 Docker 或 VirtualBox,但您和您的客户都不需要担心命令行细节。

本文的其余部分将带您完成与能够在自己的机器上安装 ContainDS 的客户端共享 Streamlit 示例应用程序所需的步骤。

ContainDS 桌面入门

首先,在你的 Mac 或 Windows 电脑上安装 ContainDS Desktop 及其底层需求 (Docker Desktop)。

一旦运行,ContainDS Desktop 将为您提供一系列推荐的起始“图像”,您可以在这些图像上构建您的应用程序。这个起点只是一个 Streamlit 环境(其中已经安装了 Streamlit ),我们还可以在其中安装我们可能需要的任何 pip/conda 包,并额外提供组成我们应用程序本身的 Python 脚本。

包含新容器屏幕

单击 streamlit-single 框旁边的“选择”(如果您想展示多个应用程序,请选择 streamlit-launchpad)。

一旦下载了底层 Docker 映像,ContainDS Desktop 会询问您最终的设置选项。这些只是一个容器名(您不需要更改它),以及硬盘上新的或现有工作区文件夹的路径。默认提供的应该是一个尚未创建的空文件夹,您将在其中放置 Python 文件和任何数据文件。如果您事先在硬盘上有这些文件,您可以选择一个已经存在的工作区位置。

对于本例,只需点击“创建”。

ContainDS Desktop 将创建新的容器——这是一个虚拟环境,运行一个独立的 Linux 系统,准备好托管您需要的包。在 ContainDS Desktop 中,该容器与工作区文件夹相结合,使您的完整应用程序能够运行。

由于我们还没有准备好 Python 脚本,新容器将运行,但会立即停止,并显示消息“没有。“py 脚本”。

创建 Python 文件之前的容器详细信息屏幕

将 Streamlit 的示例 intro.py 的内容复制到工作区文件夹中名为 intro.py 的文件中。您可以通过查看 ContainDS Desktop 中的“Streamlit Details”部分来提醒自己新工作区的完整路径。

一旦 intro.py 存在,返回到 ContainDS 桌面并点击顶部的大“开始”按钮。现在,日志部分应该会显示更多的进度,容器应该会保持运行状态(左侧列出容器的绿色图标):

显示应用程序的容器详细信息屏幕

单击“WEB”按钮或“在浏览器中启动 Streamlit”。这将在您的默认网络浏览器中启动应用程序。

运行 Streamlit 应用程序

与客户分享

您可以将此应用程序(容器本身加上工作区文件)作为一个单独的应用程序导出。包含直接与客户端共享的文件。

在 ContainDS 桌面中,单击共享选项卡。在导出子选项卡中,您的下载文件夹应被指定为保存该文件的默认位置。点击“导出”。

容器共享/导出屏幕

创建导出文件时,将显示一些进度信息。完成后,将显示输出文件名。

你可以分享一下。通过您常用的安全渠道(SharePoint、Dropbox 等)与您的客户端保存文件。它对于电子邮件来说太大了…

由您的客户端导入

一旦你的客户收到,假设他们已经安装了 ContainDS Desktop,他们可以启动 ContainDS Desktop (Docker 必须运行,除非你打算使用 VirtualBox)。在新建容器屏幕上,单击文件选项卡。

找到。包含您与他们共享的文件,然后单击“开始”。文件将被导入:

新容器屏幕的文件导入选项卡

一旦准备就绪,容器将完全像为您准备的那样运行:

运行容器详细信息屏幕

正如您所做的那样,单击“在浏览器中启动 Streamlit ”,他们将看到应用程序在他们的 web 浏览器中运行。因为 Docker 总是模拟底层的 Linux 系统,所以一切都保证完全按照预期运行!

结论

虽然有相当简单的解决方案来长期云托管完善的 web 应用程序,但 ContainDS Desktop 提供了一种非常简单的方式来共享您的工作,以便在本地运行,这对于“一次性”原型仪表板尤其有用,在这种情况下,在互联网上托管应用程序和数据可能不值得花费时间投资,至少要以合规的方式适当保护数据。

夏普比率、索提诺比率和卡尔马尔比率

原文:https://towardsdatascience.com/sharpe-ratio-sorino-ratio-and-calmar-ratio-252b0cddc328?source=collection_archive---------29-----------------------

在这篇短篇小说中,我们将探讨夏普比率的不足之处,以及我们如何用索蒂诺比率和卡尔马尔比率对其进行补充,以更清楚地了解投资组合的表现。

在投资组合业绩分析中,夏普比率通常是人们首先关注的数字。然而,它并没有告诉我们整个故事(没有什么能告诉我们……)。因此,让我们花些时间来看看更多一些有时非常有用的指标。

夏普比率再探

夏普比率是平均回报率除以年回报率的标准差的比率。我们在之前的故事中有过介绍。

让我们用一个测试价格时间序列再来看一下。

import pandas as pd
import numpy as np

from pandas.tseries.offsets import BDay

def daily_returns(prices):

    res = (prices/prices.shift(1) - 1.0)[1:]
    res.columns = ['return']

    return res

def sharpe(returns, risk_free=0):
    adj_returns = returns - risk_free
    return (np.nanmean(adj_returns) * np.sqrt(252)) \
        / np.nanstd(adj_returns, ddof=1)

def test_price1():

    start_date = pd.Timestamp(2020, 1, 1) + BDay()

    len = 100

    bdates = [start_date + BDay(i) for i in range(len)]
    price = [10.0 + i/10.0 for i in range(len)]

    return pd.DataFrame(data={'date': bdates,
                              'price1': price}).set_index('date')

def test_price2():

    start_date = pd.Timestamp(2020, 1, 1) + BDay()

    len = 100

    bdates = [start_date + BDay(i) for i in range(len)]
    price = [10.0 + i/10.0 for i in range(len)]

    price[40:60] = [price[40] for i in range(20)]

    return pd.DataFrame(data={'date': bdates,
                              'price2': price}).set_index('date')

def test_price3():

    start_date = pd.Timestamp(2020, 1, 1) + BDay()

    len = 100

    bdates = [start_date + BDay(i) for i in range(len)]
    price = [10.0 + i/10.0 for i in range(len)]

    price[40:60] = [price[40] - i/10.0 for i in range(20)]

    return pd.DataFrame(data={'date': bdates,
                              'price3': price}).set_index('date')

def test_price4():

    start_date = pd.Timestamp(2020, 1, 1) + BDay()

    len = 100

    bdates = [start_date + BDay(i) for i in range(len)]
    price = [10.0 + i/10.0 for i in range(len)]

    price[40:60] = [price[40] - i/8.0 for i in range(20)]

    return pd.DataFrame(data={'date': bdates,
                              'price4': price}).set_index('date')

price1 = test_price1()
return1 = daily_returns(price1)

price2 = test_price2()
return2 = daily_returns(price2)

price3 = test_price3()
return3 = daily_returns(price3)

price4 = test_price4()
return4 = daily_returns(price4)

print('price1')
print(f'sharpe: {sharpe(return1)}')

print('price2')
print(f'sharpe: {sharpe(return2)}')

print('price3')
print(f'sharpe: {sharpe(return3)}')

print('price4')
print(f'sharpe: {sharpe(return4)}')

正如你在这个例子中看到的,我有 4 个测试价格时间序列。第一个,price1,是一条简单的直线(不要介意曲线,这是由于周末被遗漏了)。第二个价格时间序列 price2 有一个平坦区域。第三个价格时间序列 price3 有一个向下倾斜的区域。最后一个时间序列 price4 的下降幅度稍大。

每种价格的夏普比率计算如下:

'''
price1
sharpe: 78.59900981328562
price2
sharpe: 7.9354707022912825
price3
sharpe: 3.61693599695678
price4
sharpe: 3.151996500460301'''

如你所见,由于几乎不存在波动性,price1 具有非常高的夏普比率。由于平坦区域的存在,Price2 的夏普比率几乎低 10 倍。由于向下倾斜,价格 3 和价格 4 比价格 2 低大约两倍,价格 4 的夏普比率略低于价格 3 的夏普比率。

看着这些数字,有一件事可能看起来有点奇怪,那就是夏普比率仅仅因为平坦区域的存在而降低了多少。毕竟总回报没变,根本不存在降额。对于投资者来说,价格 1 和价格 2 没有太大区别。

另一方面,价格 3 和价格 4 有相当大的下降,然而夏普比率下降了大约一半,而价格 1 和价格 2 之间下降了 10 倍。这似乎是夏普比率在告诉我们价格时间序列有多可取的能力上的一个缺陷。

排序比

为了解决夏普比率不能线性反映时间序列下行的问题,Sortino 比率有时是一个很好的指标。

排序比率=平均收益/下跌风险

其中下跌风险是时间序列内的平均负收益。

def downside_risk(returns, risk_free=0):
    adj_returns = returns - risk_free
    sqr_downside = np.square(np.clip(adj_returns, np.NINF, 0))
    return np.sqrt(np.nanmean(sqr_downside) * 252)

def sortino(returns, risk_free=0):
    adj_returns = returns - risk_free
    drisk = downside_risk(adj_returns)

    if drisk == 0:
        return np.nan

    return (np.nanmean(adj_returns) * np.sqrt(252)) \
        / drisk

将 sortino 比率应用于我们的测试价格:

'''
price1
sortino: nan
price2
sortino: nan
price3
sortino: 2.210224924119601
price4
sortino: 1.7688718895750382
'''

价格 price1 和 price2 根本没有负收益,所以对它们来说不存在排序比。对于价格 3,排序比是 2.2,而对于价格 4,排序比是 1.8,这是因为根据需要,向下的斜率更大。

让我们再看一个例子:

def test_price5():

    start_date = pd.Timestamp(2020, 1, 1) + BDay()

    len = 100

    bdates = [start_date + BDay(i) for i in range(len)]
    price = [10.0 + i/10.0 for i in range(len)]

    price[40:60] = [price[40] - i/10.1 for i in range(20)]

    price[80] = 15

    return pd.DataFrame(data={'date': bdates,
                              'price5': price}).set_index('date')

在这个新的价格时间序列 price5 中,我们在 price3 的基础上增加了一个下降,你会认为这个下降会降低 sortino 比率,对吗?让我们来看看:

'''
price3
sharpe: 3.61693599695678
sortino: 2.210224924119601
price4
sharpe: 3.151996500460301
sortino: 1.7688718895750382
price5
sharpe: 2.945329220777157
sortino: 0.4660330265232954
'''

是啊!Sortino 比率确实反映了下降。但是你不觉得变化有点太大了吗?由于价格下跌,索蒂诺比从 1.8 下降到 0.5,降幅超过 3 倍。

卡尔马尔比率

在努力控制异常值引起的失真时,就像我们之前展示的那样,另一个比率有助于检测它们。这是卡尔马尔比率。

卡尔马尔比率=回报的几何平均值/最大下降

我们已经在之前的故事中解释了最大压降。

回报的几何平均值是按时间周期长度缩放的累积回报。

def annual_returns(returns):

    num_years = len(returns) / 252

    cum_ret_final = (returns + 1).prod().squeeze()

    return cum_ret_final ** (1 / num_years) - 1

def calmar(returns):

    max_dd = max_drawdown(cumulative_returns(returns))
    if max_dd < 0:
        return annual_returns(returns) / abs(max_dd)

    return np.nan'''
price1
sharpe: 78.59900981328562
sortino: nan
calmar: nan
price2
sharpe: 7.9354707022912825
sortino: nan
calmar: nan
price3
sharpe: 3.61693599695678
sortino: 2.210224924119601
calmar: 35.10246841328119
price4
sharpe: 3.151996500460301
sortino: 1.7688718895750382
calmar: 28.081974730625276
price5
sharpe: 2.945329220777157
sortino: 0.4660330265232954
calmar: 29.404801742258666'''

正如您在结果中看到的,对于 price4 和 price5,calmar 比率分别为 28 和 29。它没有受到异常值的过多影响,还因为 price5 的向下斜率实际上比 price4 小一点点(注意 price5 定义中的 10.1!),它的 calmar 比居然增加了一点!

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

沙扎姆

原文:https://towardsdatascience.com/shazam-699a95d640f9?source=collection_archive---------20-----------------------

一个 web 应用程序,使用户能够在一个地方浏览顶级电影和热门电影的预告片

据估计,目前大约有 50 万部电影。这是任何人一辈子都看不完的。而且,不是所有人都会喜欢每一部曾经拍过的电影。大多数时候,人们倾向于看一些特定类型的电影。因此,对于任何给定的用户,大多数电影变得无关紧要。

每隔一段时间,我们都试图寻找新的东西来观看。许多人向朋友、家人和同事征求建议,然后看一部电影。但这并不总是可行的。有时,我们只想查看特定类型的顶级电影或我们周围的热门电影。就在那时,我和我的朋友尼克尔·纳尔苏拉吉·盖克瓦德想到开发“Shazam”并在 AWS 上托管它。

Shazam 让人们可以很容易地找到热门和顶级电影,以及它们的预告片。它还使用户能够对他们看过的电影之一进行评级,以帮助其他人做出决定。Shazam 是一个大规模分布式系统,提供热门电影和顶级电影,每天更新两次。这使得用户可以从世界各地获得最新最棒的电影预告片。

项目:

SShazam字面上翻译过来就是——“用来介绍一个非凡的行为、故事或转变。不要把这个和 Shazam——音乐识别应用混淆了。 Shazam 是一款网络应用,用户可以在一个地方浏览顶级电影和热门电影的预告片。

当任何人想看电影而不知道看什么时,他们会想查看他们周围的一些热门电影的预告片或有史以来收视率最高的电影。Shazam 是一个类似于网飞的门户网站,用户可以在这里观看各种电影的预告片。用户还可以对 youtube 预告片进行评级。用户可以选择通过不同类型的过滤器观看热门视频和高收视率的电影。Shazam 部署在 AWS 上,包含各种技术,如 EC2、DynamoDB、ElasticSearch、Lambdas、SQS、Python、Node.js、PySpark。

实施:

这个想法是在 SQS 开发主题,用于存储各种用户对预告片的看法和对预告片的评级。每当用户观看预告片时,相应的条目被推入队列。类似地,当用户对预告片评级时,相应的条目被推入队列。轮询队列的消费者将在 mongoDB 中存储这些视图(lambda 函数)和评级。这些条目然后在 Apache Spark 中进一步聚合,并存储在 mongoDB 中。这些新条目将用于显示高收视率和热门电影预告片。一个 lambda 函数将在一天内连续运行多次,这将在 Apache Spark 中执行聚合脚本。此外,ElasticSearch 将用于索引电影预告片,并将用于网站上的搜索机制。该网站是在 Node.js 中开发的后端和 HTML,CSS 和 Javascript 的 UI。

技术堆栈:

服务请求的 web 服务器用 Node.js 编写,用户界面用 HTML、CSS 和 Javascript 开发。为了处理多个并发请求,SQS 被用作消息队列。MongoDB 用于电影、收视率、浏览量、用户资料的数据存储。Apache Spark 用于聚合用户视图和评级,以提供高评级和热门电影。Docker 用于运行 Shazam 的所有组件,如 SQS、MongoDB、Node.js、Apache Spark 和 AWS 无服务器应用程序。

工艺流程:

通过 Shazam,用户将能够观看电影预告片。用户还可以选择观看热门电影和高收视率电影的预告片。每当电影预告片发布时,数百万用户同时开始观看预告片。为了处理这百万个并发请求,Apache Kafka 被用作消息队列。在这个模型中,所有观看电影预告片的用户都将充当发布者。一个消费者组中有多个消费者订阅主题,主题进一步处理请求并将用户评级和用户视图存储在 MongoDB 中。由于电影的用户浏览量和相应评级的总数将非常巨大,在 MongoDB 上执行聚合将需要大量时间。为了解决这个问题,Apache Spark 被用来执行聚合。cron 作业用于运行 Spark 作业,该作业将从 MongoDB 获取数据,执行聚合并将聚合的数据存储回 MongoDB。然后,汇总的数据在 Shazam 上显示给用户,作为热门和高评级电影。

AWS 服务:

  • 地对空导弹
  • API 网关
  • λ函数
  • 亚马逊 SQS
  • AWS EMR
  • AWS 弹性搜索
  • MongoDB
  • AWS 云观察
  • (美)工程科学学会(Society of Engineering Science)
  • S3

建筑:

Shazam 建筑

像阿帕奇 SQS,阿帕奇火花,弹性搜索等服务运行在引擎盖下。每当用户观看电影预告片时,( movie_id,user_id)的信息被发布到 movie_users_mapping 主题中。类似地,当用户对电影预告片进行评级时,( movie_id,user_id,rating)的信息被发布到 movie_ratings 主题中。一个消费者组中的多个消费者订阅两个主题,这两个主题获取存储在 SQS 中的信息,并将信息存储在 MongoDB 集合中。然后,Apache Spark 将聚合这些数据,并返回一个 JSON 数组,其中包含趋势主题的 schema (movie_id,views ),以及高评分电影的 schema(movie _ id,avg_rating)。这些数据存储在 MongoDB 的 trending_movies 和 top_rated_movies 集合中。Apache Sparks 使用 Mongo-Spark 连接器与 MongoDB 集成。Spark 中的数据聚合活动使用 CRON 作业在一天内执行两次。

数据存储模式:

MongoDB 模式

需要一个 NoSQL 数据库来方便获取和快速处理数据。Shazam 使用 MongoDB 作为 NoSQL 数据库来存储电影、用户评级、youtube 视频链接、电影海报和用户视图。图 2 显示了带有每个字段名的 MongoDB 的详细模式。从 Kafka 主题中读取数据的消费者会将用户视图存储在 movie_user_matchings 集合中,并将电影评级存储在 ratings 集合中。Apache Spark 然后将从 movie_user_matchings 集合中读取数据,以找到热门电影和评级集合,从而找到评级高的电影。

API 设计:

  1. 帖子/评级:存储用户给出的评级
  2. 帖子/视图:存储用户的视图
  3. GET /movies:根据过滤器返回电影列表
  4. 获取/搜索/电影:从
  5. 获取/登录:获取登录令牌
  6. POST /register:注册用户

数据集:

对于电影和评级,我们使用的数据集来自 grouplens.org '电影镜头 20M '数据集。对于 youtube 预告片,我们将使用 grouplens.org movie lens 2000 万 Youtube 预告片数据集。我们将使用来自 Kaggle 的单独数据集来获取电影海报。

数据集的链接如下所示:

[## MovieLens 20M 数据集

2000 万电影收视率。稳定的基准数据集。2000 万次评级和 465,000 个标签应用于…

grouplens.org](https://grouplens.org/datasets/movielens/20m) [## 电影镜头 20M YouTube 预告片数据集

GroupLens 感谢美国国家科学基金会在研究资助 IIS 05-34420 下的支持…

grouplens.org](https://grouplens.org/datasets/movielens/20m-youtube) [## 从海报看电影类型

通过分析电影海报预测电影类型

www.kaggle.com](https://www.kaggle.com/neha1703/movie-genre-from-its-poster)

部署说明:

打包和部署 SAM 模板的命令:

Sam package–template-file template . yml–S3-bucket shazam-Sam-templates–output-template-file output-template . yml Sam deploy–template-file output-template . yml–stack-name shazam–capabilities CAPABILITY _ IAM Sam delete-stack-stack-stack-name shazam

在 EMR 上运行 Spark 作业的命令:

spark-submit–master local[*]–conf " spark . MongoDB . input . uri = MongoDB+SRV://nikhil:nikhil @ shazamdb-ci1rz . MongoDB . net/"–conf " spark . MongoDB . output . uri = MongoDB+SRV://nikhil:nikhil @ shazamdb-ci1rz . MongoDB . net/"–packages org . MongoDB . spark:mongo-spark-connector _ 2.11:2 . 4 . 0 trending . py

应用:

Shazam 成功地提供了一个可扩展的、分布式的、自我更新的系统,为热门电影和顶级电影提供最新数据。在 SQS 的帮助下,用户积累的数据被存储到 mongoDB 上。然后,在运行 PySpark 和 SparkSQL 命令的 cronjob 的帮助下,每天聚合两次,并写回到 mongoDB 上。当用户刷新页面时,这提供了最新的趋势和最高评级的电影。

原型:

[## shazam-v2

由视觉带给你

chinmay609410.invisionapp.com](https://chinmay609410.invisionapp.com/prototype/ck3uz6xaa004g6g01yvn0wr2h/play)

应用演示:

代码:

整个应用程序的代码都保存在这个 github 存储库中:

[## NikhilNar/Shazam

当任何人想看电影而不知道看什么时,他们会想看一些电影的预告片…

github.com](https://github.com/NikhilNar/Shazam)

参考资料:

[1]https://grouplens.org/datasets/movielens/20m/

[2]https://grouplens.org/datasets/movielens/20m-youtube/

[3]https://www . ka ggle . com/neha 1703/movie-genre-from-its-poster/downloads/movie-genre-from-its-poster . zip/5

https://nodejs.org/en/docs/

https://docs.mongodb.com/

https://spark.apache.org/docs/latest/

https://docs.mongodb.com/spark-connector/master/python-api/

通过提及这些话题,在数据科学面试中大放异彩

原文:https://towardsdatascience.com/shine-in-data-science-interviews-by-mentioning-these-topics-622b1726386b?source=collection_archive---------41-----------------------

有时候,数据科学的成功不仅仅是创建最好的模型

上的拍摄的照片

如果你具备数据科学家的所有技能,你就有很大的机会在面试中胜出。但是如果你想得到额外的提升,你应该展示一些关于你自己的其他事情。其中一个就是我之前文章提到的:软技能。但是今天我想说点别的。

数据科学正在快速发展。新技术正在开发,新工具正在推出,新方法正在被发现。自然,公司倾向于雇佣那些愿意跟上的人。当然,你不需要知道人工智能或数据科学领域正在发生的每一件新事物来证明你感兴趣。有些进步对所有数据科学家来说都太具体了,以至于他们不知道。但有些话题关系到人工智能领域的每个人,从数据科学家到项目经理。大家都应该了解并有看法的话题。

数据科学中的两个这样的主题是可解释性和人工智能伦理。这些主题正在获得牵引力,成为人工智能中最重要的两个课外主题。展示你对这些主题的理解可以为你的潜在客户创造奇迹。即使这意味着只是表明你给了他们一些想法。

在这篇文章中,我将向你介绍可解释性和人工智能伦理,解释它们是什么,并分享一些常用的工具来将它们应用到日常项目中。读完这篇文章后,你应该能够在工作面试中轻松地讨论这些主题,并知道如何将它们应用到你的个人或专业项目中。

在我们进入细节之前,我想指出这两个主题是相关的。随着人工智能得到更广泛的应用,人们自然希望了解人工智能系统是如何做出决策的,以及它们是如何如此成功的。不仅仅是出于好奇,还因为人工智能开始在人们的生活中产生影响。今天,在许多其他事情中,人工智能算法被用来决定解雇谁或贷款给谁。

当然,我们对机器学习算法的理论以及它们在理论上如何工作有很好的了解。但是,对于这些算法中的许多算法,不可能看到特定案例的哪个属性导致算法以这种或那种方式做出决定。至少最近没有。因此,过去不可能,而且在一定程度上仍然不可能,来证明机器学习算法做出的决定是正确的。

有一些不公平申请的例子仅仅是因为缺乏对这个问题的认识。公司意识到他们的人工智能系统偏袒某个种族或歧视某个性别。这导致公众开始讨论监管人工智能技术和一般的人工智能伦理。让我们仔细看看这些主题。

可解释性

机器学习算法被许多教授它的人称为“黑盒”。这是一个相当准确的描述,因为我们真的不知道那里发生了什么。下图简单地展示了它的样子。你给了一些输入,一些事情发生了,你得到了一些输出。你可以改变黑盒中发生的一些参数,使输出更好,但你不知道为什么。

相信机器学习精灵会解决你的问题可能会令人欣慰,你可能会说,“嘿,如果它在工作,它就在工作。无需窥探模型内部。”让我们看看我能否用这个例子改变你的想法:
研究人员用狼和哈士奇的图片训练了一个模型。[1]该模型的目标是将某个图像分类为哈士奇或狼。这个模型做得很好,精确度很高。当研究人员查看发生了什么以及模型使用图片上的什么信息来决定照片是狼还是哈士奇时,他们看到了这个:

解释显示所有狼的照片都有雪作为背景。因此,该模型被优化为基于背景中是否有雪来分类。当给它一张背景是雪的哈士奇的照片时,它自然不能正确地分类,因为它一开始就捕捉到了错误的图案。这里只是一个免责声明,这个算法是用人工选择的数据训练的,专门用于研究模型解释。但是这些类型的不明显的、不期望的和难以检测的数据中的相关性,具有显著影响机器学习模型的潜力,如示例中所示。

除了可解释性有助于我们通过了解算法决策的基础来减少错误之外,理解成功的模型也有很大的好处。通过使机器学习算法基于其决策的模式可见,我们可以更好地理解手头的问题。

在研究一些可解释性工具之前,最好注意一些算法比其他算法更容易解释,即使没有可解释性工具。特性重要性图表是了解某个特性在整个决策过程中有多重要的好方法。基于树的算法是可能的,例如决策树、随机森林和梯度提升树。你必须记住,特性重要性图表上显示的重要性并不是相互独立的。并且不容易比较改变特征值的效果。最近开发的可解释性工具通过显示每个特征的重要性或权重,很好地解释了每个实例。

一些解释机器学习算法的工具有 SHAP、Lime(我目前使用的)、XGBoostExplainer(专门针对 xgboost)、Skater 和 ELI5。

下面是一些工具的解释。

SHAP 通过给每个特征分配一个叫做“沙普利值”的值来解释模型的决定。该值成为该特性的重要性。Shapley 值决定了如何在要素之间分配预测。对单个数据点的解释如下:

这个具体的用例是确定患者患心脏病的可能性。该行顶部标有“输出值”的值是该患者的预测值。1 表示存在心脏病,0 表示没有心脏病。蓝色和红色箭头显示了某个特征影响预测的方式。

看起来这位患者的性别和身高值更高,他们患心脏病的可能性更大,而其他特征,如胸痛类型或主要血管堵塞的数量,则表明患心脏病的风险较低。箭头的长度显示了某个特性相对于其他特性的重要性。所以对于这个例子,thal 的值更重要,因为与患者的性别相比,它更有可能导致心脏病。

Lime 像我们一样假设模型是一个黑盒,并查看模型的输入和输出之间的关系。为了理解模型如何做出决策,它调整输入以查看输出如何变化,并使用这种技术解释各个实例。使用 LIME 解释的来自相同模型的相同实例如下所示。

左边的图表显示了实际的预测,中间的图表显示了 Lime 如何解释每个特性对这个实例的总体结果的贡献。同样,条形的长度和顺序(从上到下)显示了特征在最终决策中的重要性/权重。

关于如何预测这个人有 50%的机会患心脏病,这两个解释者似乎有相似的想法。但情况并非总是如此。因为这些解释者试图使用不同的技术来解释模型预测,并且因为这些技术不能完全复制模型预测过程,而仅仅是估计它,所以他们往往有不一致的情况。在像这样的用例中,我们可以在一定程度上使用常识,如果解释者和/或模型有意义,这似乎很容易理解。但是当我们在一个我们不熟悉或者不擅长的领域工作时,决定使用什么样的解释就变得更加棘手了。这提醒我们要对这些解释持保留态度,不要根据它们做出夸大的声明。

人工智能伦理

这些年来,模型缺乏可解释性和一些不幸的人工智能应用引起了人工智能社区的关注。人们意识到人工智能系统开始反映现实生活中不理想的部分。这并不奇怪,因为机器学习算法是为了学习数据中的模式而创建的。如果你给它输入世界上所有 CEO 的数据,下一次你问它某个人成为 CEO 的可能性时,它自然会给出女性比男性更低的可能性。仅仅是因为它是数据中呈现的模式。

人工智能伦理只是努力确保人工智能系统是公平和可信的。我们不希望我们训练的人工智能系统有偏见或歧视任何群体。

人工智能伦理学有几个主要问题。让我们检查一下。

首先是偏见的问题。如果你用一个有偏见的数据集训练你的模型,自然你会得到一个歧视某些群体的有偏见的数据集。你会问现实生活中是什么样子?这里有一些例子。

这里有一个非常尴尬的例子,一个护照申请系统把一个亚洲血统的人误认为是一个闭着眼睛的人。[2]

一个来自亚马逊,那里的男性求职者比女性求职者更受青睐,原因很简单,在他们的培训数据中,以前被雇佣的人都是男性。这使得该模型认为男性更适合担任这一职位。[3]

谷歌的这个是我最喜欢的之一。只是一个免责声明,这是几年前的一个例子。谷歌现在有一个解决这个问题的方法,我马上会分享给大家。而是回到有偏差的系统;几年前,当你翻译“她是医生”这句话时。他是一名护士。”翻译成一种没有性别代词的语言,然后翻译回来,你会得到一个相当性别歧视的翻译,好像谷歌翻译没有给它一个机会,医生可能是一个女人。这一次又是由训练模型的有偏差的数据集引起的。

处理偏差的方式是:

  • 在模型训练中尽可能不包含个人信息。如果你正在开发一个贷款决策模型,你知道这个模型不知道这个人是男是女。
  • 如果您绝对需要包含个人信息,请确保您的数据集是平衡的,不会偏向或针对任何特定群体。有一些工具和指标可以用来计算偏倚的水平。一个示例工具是 IBM AI 公平 360 工具包。
  • 仅从数据集中排除个人信息可能还不够。您应该确保数据集中没有个人信息的隐藏代理。例如,您可能认为您没有在训练中包括种族信息,但是如果数据集来自一个高度隔离的城市,在那里来自同一种族的人往往居住在相同的街区,通过包括邮政编码信息,您将包括种族信息。
  • 始终,即使您没有个人信息,也要确保您的数据集公平地代表数据集中所有可能的群体。
  • 留意潜在的有偏差的应用,并调整您的系统。有许多棘手的案件。一定要采取创造性的措施。下面举个例子,Google translate 在发现这个问题后是如何适应的。[4]现在,当语言不明确时,他们会给你两种选择。

我已经向你展示了一些由有偏见的数据引起的问题的例子,但是偏见不是人工智能伦理的唯一问题。人工智能系统的滥用会导致严重的不道德行为。

这是一个学校老师的例子,她受到学生和家长的高度赞扬,却发现自己被解雇了。根据对学生成绩的统计评估,她被解雇了,这位老师对学校的整体数学成绩贡献不够。因此,由于现有的制度,她被解雇了,尽管她是一位受人爱戴的老师。[5]

另一个例子是大学做的一项关于辍学大学生的研究。根据过去几年的学生数据,训练了一个模型来评估某个学生几年后辍学的可能性。一所大学用这个模型来评估每一个申请的学生辍学的可能性,并剔除那些辍学可能性较高的学生。我相信你明白为什么这是不道德和不公平的。这让我想起了电影《少数派报告》,在那里他们根据先知的预见在犯罪之前逮捕人。

我们不应该因为这些例子而对人工智能系统的有用性失去希望。有办法将人工智能系统集成到决策过程中,并让它们支持决策,而不是推动决策。例如,回到辍学概率计算模型,另一所大学没有让它影响其招生,而是建立了一个平台,以支持辍学可能性较高的学生,确保他们留在学校。

毕竟,这些系统是我们制造的,我们也有责任道德地使用它们的成果,不让它们成为不公平的理由。

人工智能伦理学的另一个问题是人工智能的责任。人工智能的责任更多的是未来的问题。这是一个“如果一个人工智能系统伤害了人类,谁应该负责任”的问题当然,这个问题不是指机器人反叛,而是指自动驾驶汽车和自动智能系统。这个问题的一个很好的例子就是电车问题。

手推车问题是照片下面显示的伦理问题。如果一辆电车将要撞死 5 个人,而我们有足够的钱让它转向并只撞死一个人,我们会这么做吗?或者更确切地说,什么是道德的事情呢?除非我们决定转移手推车去救其他五个人,否则这一个人不会马上有危险。

人工智能责任中的这个问题是这样提出的:假设有一辆自动驾驶汽车,如果汽车直行,它会撞到墙上,车里的人会被撞死,但如果汽车突然转向,它会撞到其他人,他们也会被撞死。一个细节是过马路的人在闯红灯。我们应该教汽车做什么?如果过马路的人是老人呢?如果她们是孕妇呢?

这是一个很难回答的问题。但这是一个需要答案的问题。比方说,我们在汽车的设计过程中决定,它应该不惜一切代价保护车里的人。如果这种情况发生,过马路的人在事故中丧生,会怎么样?那是谁的错?

从我们还在琢磨的例子和问题可以看出,人工智能伦理学还有很长的路要走。不幸的是,获得符合伦理的人工智能并不像检查清单那么容易。这些年来,社区通过犯错误和意识到这些错误,已经发现了一些最佳实践,但是我们还没有一个可能出错的所有事情的详尽列表。我们能做的最好的事情就是留意可能的不道德的应用,并采取必要的预防措施来领先他们一步。

我希望这篇文章对你来说是一个好的起点。你现在应该能够描述可解释性在人工智能的上下文中意味着什么,以及人工智能伦理需要什么。我相信你的潜在雇主听到你不仅听说过这些术语,而且还做了足够多的阅读,给出了一些可能出错以及如何解决它们的例子,会留下深刻的印象。如果可以的话,你可以问问你的面试官他们在工作中是如何解决这些问题的,那就更好了。

除了在数据科学面试中成为一个很好的话题之外,一旦你开始工作,这些话题将成为你职业生活中的主要主题,这是有充分理由的。所以把它们记在心里,尽可能多的阅读。

👉对数据科学领域以及如何开始学习感到困惑? 免费参加数据科学入门迷你课程

如果你有兴趣了解更多,这里有一些我偶然看到的文章:

交代:

动手机器学习模型解读

人工智能伦理:

人工智能伦理的搭便车指南

参考文献:

  1. “我为什么要相信你?”:解释任何分类器的预测
  2. 新西兰护照机器人告诉亚裔申请人睁开眼睛
  3. 亚马逊废弃秘密人工智能招聘工具,该工具显示出对女性的偏见
  4. 减少谷歌翻译中的性别偏见
  5. “创造性…激励性”并被解雇

使用 PyCaret 将机器学习模型传送到数据—第二部分

原文:https://towardsdatascience.com/ship-ml-model-to-data-using-pycaret-part-ii-6a8b3f3d04d0?source=collection_archive---------42-----------------------

二元分类

约书亚·索蒂诺在 Unsplash 上拍摄的照片

我之前的帖子 使用 PyCaret 1.0 在 SQL 中进行机器学习提供了关于集成 PyCaretSQL Server 的细节。在本文中,我将提供如何使用py caret 2.0(py caret 是 Python 中的一个低代码 ML 库)在 SQL Server 中训练和部署监督机器学习分类模型的逐步细节。****

本文涉及的内容:

1.如何将数据加载到 SQL Server 表中

2.如何在 SQL Server 表中创建和保存模型

3.如何使用保存的模型进行模型预测并将结果存储在表中

一、导入/加载数据

现在,您必须使用 SQL Server Management Studio 将 CSV 文件导入数据库。

在数据库中创建一个表“癌症****

右击数据库,选择任务** - > 导入数据**

对于数据源,选择平面文件源。然后使用浏览按钮选择 CSV 文件。在点击下一个按钮之前,花一些时间配置数据导入。

对于目标,请选择正确的数据库提供程序(例如 SQL Server Native Client 11.0)。输入服务器名;勾选使用 SQL Server 认证,输入用户名密码数据库,然后点击下一步按钮。

在选择源表和视图窗口中,您可以在单击下一个按钮之前编辑映射。****

检查立即运行并点击下一个按钮

单击“完成”按钮运行包

二。创建 ML 模型&保存在数据库表

****分类是一种监督机器学习,用于预测离散无序的分类类别标签PyCaret 包中可用的模块可用于二进制多类问题。

在本例中,我们将使用'乳腺癌数据集'。在数据库表中创建和保存模型是一个多步骤的过程。让我们一步一步来:

I .创建存储过程以创建训练模型,在这种情况下是额外的树分类器算法。该过程将从上一步创建的癌症表中读取数据。

下面是用于创建该过程的代码:

*-- Stored procedure that generates a PyCaret model using the cancer data using Extra Trees Classifier Algorithm*DROP PROCEDURE IF EXISTS generate_cancer_pycaret_model;GoCREATE PROCEDURE generate_cancer_pycaret_model (@trained_model varbinary(max) OUTPUT) ASBEGINEXECUTE sp_execute_external_script@language = N'Python', @script = N'import pycaret.classification as cpimport pickletrail1 = cp.setup(data = cancer_data, target = "Class", silent = True, n_jobs=None)*# Create Model*
et = cp.create_model("et", verbose=False) *#To improve our model further, we can tune hyper-parameters using tune_model function.
#We can also optimize tuning based on an evaluation metric. As our choice of metric is F1-score, lets optimize our algorithm!*tuned_et = cp.tune_model(et, optimize = "F1", verbose=False) *#The finalize_model() function fits the model onto the complete dataset.
#The purpose of this function is to train the model on the complete dataset before it is deployed in production*final_model = cp.finalize_model(tuned_et)*# Before saving the model to the DB table, convert it to a binary object*trained_model = []
prep = cp.get_config("prep_pipe")
trained_model.append(prep)
trained_model.append(final_model)
trained_model = pickle.dumps(trained_model)', @input_data_1 = N'select "Class", "age", "menopause", "tumor_size", "inv_nodes", "node_caps", "deg_malig", "breast", "breast_quad", "irradiat" from dbo.cancer', @input_data_1_name = N'cancer_data', @params = N'@trained_model varbinary(max) OUTPUT', @trained_model = @trained_model OUTPUT;END;GO

二。创建存储定型模型对象所需的表

DROP TABLE IF EXISTS dbo.pycaret_models;GOCREATE TABLE dbo.pycaret_models (
model_id  INT NOT NULL PRIMARY KEY,
dataset_name VARCHAR(100) NOT NULL DEFAULT('default dataset'),
model_name  VARCHAR(100) NOT NULL DEFAULT('default model'),
model   VARBINARY(MAX) NOT NULL
);GO

三。调用存储过程创建模型对象并保存到数据库表中

DECLARE @model VARBINARY(MAX);
EXECUTE generate_cancer_pycaret_model @model OUTPUT;
INSERT INTO pycaret_models (model_id, dataset_name, model_name, model) VALUES(2, 'cancer', 'Extra Trees Classifier algorithm', @model);

该执行的输出是:

控制台输出

保存模型后的表格结果视图

SQL Server 表结果

三。运行预测

下一步是基于保存的模型运行测试数据集的预测。这也是一个多步骤的过程。让我们把所有的步骤再重复一遍。

I .创建一个存储过程,该存储过程将使用测试数据集来检测测试数据点的癌症

下面是创建数据库过程的代码:

DROP PROCEDURE IF EXISTS pycaret_predict_cancer;
GOCREATE PROCEDURE pycaret_predict_cancer (@id INT, @dataset varchar(100), @model varchar(100))
ASBEGINDECLARE @py_model varbinary(max) = (select modelfrom pycaret_modelswhere model_name = @modeland dataset_name = @datasetand model_id = @id);EXECUTE sp_execute_external_script@language = N'Python',@script = N'# Import the scikit-learn function to compute error.import pycaret.classification as cpimport picklecancer_model = pickle.loads(py_model)*# Generate the predictions for the test set.*predictions = cp.predict_model(cancer_model, data=cancer_score_data)OutputDataSet = predictionsprint(OutputDataSet)', @input_data_1 = N'select "Class", "age", "menopause", "tumor_size", "inv_nodes", "node_caps", "deg_malig", "breast", "breast_quad", "irradiat" from dbo.cancer', @input_data_1_name = N'cancer_score_data', @params = N'@py_model varbinary(max)', @py_model = @py_modelwith result sets (("Class" INT, "age" INT, "menopause" INT, "tumor_size" INT, "inv_nodes" INT,"node_caps" INT, "deg_malig" INT, "breast" INT, "breast_quad" INT,"irradiat" INT, "Class_Predict" INT, "Class_Score" float ));END;GO

二。创建一个表来保存预测和数据集

DROP TABLE IF EXISTS [dbo].[pycaret_cancer_predictions];GOCREATE TABLE [dbo].[pycaret_cancer_predictions]([Class_Actual] [nvarchar] (50) NULL,[age] [nvarchar] (50) NULL,[menopause] [nvarchar] (50) NULL,[tumor_size] [nvarchar] (50) NULL,[inv_nodes] [nvarchar] (50) NULL,[node_caps] [nvarchar] (50) NULL,[deg_malig] [nvarchar] (50) NULL,[breast] [nvarchar] (50) NULL,[breast_quad] [nvarchar] (50) NULL,[irradiat] [nvarchar] (50) NULL,[Class_Predicted] [nvarchar] (50) NULL,[Class_Score] [float] NULL) ON [PRIMARY]GO

三。调用 pycaret_predict_cancer 过程将预测结果保存到表中

*--Insert the results of the predictions for test set into a table*INSERT INTO [pycaret_cancer_predictions]EXEC pycaret_predict_cancer 2, 'cancer', 'Extra Trees Classifier algorithm';

四。执行下面的 SQL 来查看预测的结果

*-- Select contents of the table*SELECT * FROM [pycaret_cancer_predictions];

预测结果

四。结论

在这篇文章中,我们学习了如何在 SQL Server 中使用 PyCaret 构建分类模型。类似地,根据业务问题的需要,您可以构建和运行其他类型的监督和非监督 ML 模型。

托比亚斯·菲舍尔在 Unsplash 上拍摄的照片

您可以进一步查看 PyCaret 网站,了解可以在 SQL Server 中以类似方式实现的其他监督和非监督实验的文档。

我未来的帖子将会是在 QL 服务器中使用 Python 和 PyCaret 探索其他监督和非监督学习技术的教程。

动词 (verb 的缩写)重要链接

PyCaret

我的 LinkedIn 个人资料

Shopify 趋势产品 2020

原文:https://towardsdatascience.com/shopify-products-eda-8c14e3e544e8?source=collection_archive---------40-----------------------

数据科学

Shopgram.io [EDA 第二部分]

图片来自 Shopgram.io

机器学习正在变革许多行业,包括电子商务和在线购物,零售商可以通过时间序列预测管理供应链,并为他们的客户提供个性化和语义感知的搜索和推荐引擎。这些成就大多归功于需要大量训练数据的深度学习的进步。虽然有许多巨大的通用多媒体数据集,但大多数特定于电子商务的公共数据集并不令人惊讶。

shop gram . io是我们开始通过收集 Shopify 创建的在线商店数据来分析电子商务市场的地方,这些数据是全球电子商务市场的代表性样本。在 Shopify Stores EDA 中,我介绍了 Shopify 是最大的电子商务平台之一,具有许多数据科学潜力,并讨论了我们如何抓取超过 70 万家商店和 7000 万种产品以及商店 EDA 的信息。在这篇文档中,我的主要关注点是产品,在这里我首先解释产品数据结构,然后我谈论数据清洗,最后,我给出一些基本的 EDA,特别是关于 Shopify 商店中受欢迎的产品类型,以及它们的平均价格。

数据结构

假设我们有商店网址,找到产品信息并不是一件难事。其实 Shopify 提供了一个开放的 API,通过 URL{ shop-URL }/products . JSON 给出 JSON 格式的产品数据?limit=250 & page={i}。有了所有产品,我们可以构建一个大型多模态数据集(text & image ),并在以后将其用于数据挖掘目的。

Shopify 数据模型中的每个产品都有一个整数 id ,它在所有产品中是唯一的,标题,在产品 URL 中使用的句柄,提供者名称供应商,由商家确定的产品类型 product_type ,以及下面描述的标签、选项、变量、图像

图一。Shopify 产品的主要特点(图片由作者提供)。

标签是 Shopify 的内部概念,对客户不可见。它用于改善客户搜索体验,也用于执行批量操作,如构建自动收藏。产品也可以有零到三个选项。每个选项都有一个名称和值列表。例如,一件连帽衫可能有两个选项:尺码颜色,三个尺码值 (S,M,L) ,两个颜色值(黑色,白色)。这样,我们就有了 6 个变体。变体是通过组合选项构建的。每个变量都有一个标题,它是由反斜杠(例如 S / Black )、字符串形式的 skuprice (无货币)、 compare_at_priceoption1option2option3 (它们是期权的值)和分隔的选项值的串联由于一个产品可能有不同的变体,它也可能有不同的图像。每个图像都有一个 idsrc 即图像的 URL、宽度高度variant_ids

利用这些特性可以定义许多数据科学问题。我们将互相使用文本和图像数据,并建立一个多模态深度神经网络来对电子商务产品进行分类或比较类似的产品。但在下文中,我将解释我们如何利用 product_typeprice 功能来发现 Shopify 中最受欢迎的产品类型及其价格统计。

数据清理

产品类型是所有特征中最有趣的特征之一,因为它可以用来标记产品。然而,它很难使用,因为不同的商家可能会对一种特定的类型使用不同的名称:T 恤衫,T 恤衫,T 恤衫,t 恤,… 都是指的 t 恤

通过分析 6700 万种产品,我们发现了 160 万种独特的产品类型。使用引理化,我们可以将这个数字减少到 140 万,但仍然很大。但是好消息是,我们可以只保留 1128 种产品类型,仍然有 50%的产品(这个数字是 2515,没有术语化)。这些选定的产品类型仍然需要手动清洁(因为例如 t 恤t 恤仍然是不同的),在这样做之后,我们有 758 个干净的产品标签,并建立一个带标签的数据集。此外,为了构建分层产品类别,我们使用了易贝类别的前三个级别,并标记了我们的数据。

价格特色怎么样?如上所述,价格是变量数据的特征,其中缺少货币信息使其不能直接使用。事实上,我们已经从商店的主页上找到了商店货币,连接这些数据我们就可以得到价格和货币。将所有价格标准化为美元(使用 2020 年的货币比率)并去除异常值,可以得到干净的价格数据。现在,我们可以探索 Shopify 商店中受欢迎的产品类型,并对每个类别进行价格统计。

探索性数据分析

现在,我将展示经过清理的产品数据的基本统计数据,这些数据可能会让打算选择新产品的 Shopify 商家和想开展新业务的企业家感兴趣。让我们检查一下 Shopify 商店中受欢迎的产品类型。下图显示了 17 种最受欢迎的类型,占所有产品的 40%。这个数字分别为 60%和 80%的 58 和 170。

图二。覆盖所有产品 40%的前 17 种产品类型。(股份是有条件的,总股份可通过将这些数字乘以 0.4 得出)

同样考虑第一级易贝类别,所有产品的 75%来自以下四个类别:

图三。一级易贝类别。

对于需要比较和分析特定行业价格的商家来说,价格分析是另一个吸引人的信息。仅考虑覆盖 60%产品的前 58 种产品类型,并根据其价格中位数对其进行排序,这对于噪音更具鲁棒性,以下两个图分别显示了最昂贵和最实惠的流行产品类型。

图 4。最昂贵的流行产品类型。

图五。最实惠的流行产品类型。

涉及到时间作为另一个维度,我们可以通过时间来分析这些统计数据,显示了 2020 年 top 的受欢迎程度以及耳环项链的小幅下跌。这种趋势也可以在图 7 中的价格中观察到。

图六。不同时期流行产品类型的份额。

图 7。流行产品类型的价格中位数。

除了这些统计数据之外,还可以通过产品数据提取更多信息,尤其是使用自然语言处理方法从产品文本中提取信息,这将在 Shopgram.io 未来的帖子中进行更多调查。

购物商店

原文:https://towardsdatascience.com/shopify-stores-eda-d1f949604e1c?source=collection_archive---------31-----------------------

数据科学

shop gram . io【EDA 第一部分】

图片由 Sanaz Bidad 来自 Shopgram.io

hopify 是最大的在线商店电子商务平台之一,由于其统一的数据结构,对于数据科学社区来说具有许多潜力。在本文中,我首先介绍了 Shopify 及其数据模型。然后,我讨论了我们的数据收集挑战和方法,接着是一些基本的探索性数据分析(EDA)。最后,我简要地谈谈我们的主题建模和分类,这是我们下一篇文章的主题。

Shopgram.io 呈现我们分析的结果。它是 Shopify 商店的浏览器,根据不同的功能列出了 70 万家商店,包括类别、Alexa-排名、国家和产品数量。想要全面了解其他相关商店的 Shopify 商家可以轻松找到他们需要的数据,以获得见解。这对那些想看看是否有潜在机会创业的人来说也是有益的。

介绍

Shopify 是一个在线平台,在这里你可以轻松地建立自己的在线商店,无需任何特定的技术知识。订阅 Shopify 后,你有一个管理面板,你可以在那里设计你的商店和放置你的产品。根据 Shopgram 的报告,不同类别的顶级网站现在都在使用 Shopify,以获得其独特的好处。根据统计数据,如今,电子商务占据了全球零售市场 16%的份额,而 Shopify 作为电子商务领域最大的参与者之一,在使用电子商务技术的网站中占据了 20%的份额。

从数据角度来看,Shopify 为所有商店的数据提供了统一的数据结构,因为它们都是由 Shopify 创建的,尽管它们可能使用不同的主题和 ui。每个商店都有一个标题和描述,可以看作是一套产品。一个特定的产品有一个标题,可能有不同的图像,标题和价格不同的变体。另一个重要的概念是集合。每个商店可能有不同的系列,每个产品可能是许多系列的成员(见图 1)。因此,数据模型在所有商店中都是相同的,它为定义数据科学项目提供了巨大的潜力。

图一。有六种产品和五个系列的商店。

网上有一些关于 Shopify 应用和商店的统计报告(例如,见 IndieHackersas soft),但是,它们中的大多数提供一般信息,详细信息如 Storeleads 可在付费订阅后获得。

数据收集

找到所有商店是最具挑战性的任务之一。商店网址可通过许多数据提供商访问,如 SpyseNerdydataCartInsightPublicwwwWappalyzerbuilt within premium plan,但是,我们需要自己找到它们,因为其中一些不完整,其他的有限制使用条款。由于 Shopify 商店有一个独特的子域myshopify.com,如果我们找到这些子域,我们就有了完整的列表。此外,Shopify 服务器有几个为商店服务的 IP 地址。因此,我们可以通过找到指向这些 IP 地址的域来找到所有的商店。

仅仅通过处理 Shopify 商店的 HTML 主页就可以提取出很多有用的信息。我们可以找到标题、描述、收藏的名称、国家、主题和货币,并将它们用于第一版的 Shopgram.io ,以及它们的 Alexa-rank,可以通过 Alexa API 访问。我们也通过网址 {shop-url}/products.json 找到大部分店铺的商品,以后会用到。

探索性数据分析

在这一节中,我将展示一些基本的 EDA,它们可以帮助我们以后选择 ML 模型。呈现的统计数据来自我们可以通过数据收集机制获得的 70 万个商店数据,其中可能存在一些微小的偏差。

首先,我们来看看 Shopify 在不同国家的受欢迎程度。有趣的是,大多数商店(~88%)来自说英语的国家(见图 2)。图 3 中还显示了货币分布,大多数商店使用美元作为他们的货币。

图二。国家受欢迎程度直方图。

图 3。货币流行直方图。

另一个有吸引力的统计数据是 Alexa-rank 的分布(见图 4)。似乎虽然有许多 Shopify 商店,但只有 17%的商店 Alexa-rank 低于 1000 万,有足够的流量通过 Alexa 排名,只有 3.4%的商店 Alexa-rank 低于 1000 万。此外,在所有排名前 1000 万的互联网网站中,1.2%是 Shopify 商店。

图 4。Alexa-等级直方图。

商店收藏信息对我们也很重要,因为首先,它包含了关于商店类别的有用信息,因为我们在主题建模中使用了它;其次,它很容易从主页 HTML 中收集。如图 5 所示,收集的数量具有重尾分布,平均值为 13.2,中位数为 5。

图 5。集合数量直方图。

主题使用统计对于那些将要为他们的商店选择主题的人来说可能也是有趣的。首次亮相和布鲁克林是最受欢迎的主题,近三分之一的商店使用它们。主题分布如图 6 所示。

图 6。主题人气。

此外,产品的数量可以合理地衡量商店的规模,图 7 显示了它的分布。更多的信息可以从产品信息中提取,这将在未来的帖子中讨论。

图 7。产品数量直方图。

主题建模

现在,让我简单地谈谈我们的第一个 ML 项目,它是对商店进行分类并指定它们的类别,并将细节留给我们即将到来的帖子。这个项目的主要挑战是在监督任务中处理未标记的数据。第二个挑战是选择最终的类标签来将商店映射到它们。为了处理后者,首先,我们考虑利用亚马逊(Amazon)或 T2(Alibaba)的易趣(Ebay)层级作为类别标签,但后来我们决定为 Shopify 商店建立特定的标签,因为它与这两个平台的背景不同。因此,我们进行了主题建模,以便更深入地了解数据。我们将店铺名称、描述和收藏名称连接起来,并通过使用最先进的深度自然语言处理模型从中提取特征向量。然后,我们应用聚类方法,在所有商店中找到了近 800 个重要关键词。使用这些关键字,我们建立了一个带标签的数据集,训练了一个深度 NLP 模型,并将商店分类到不同的标签。完成这些任务的结果可以在 Shopgram.io 中找到。

用 Python 短期运行控制图(变量数据)

原文:https://towardsdatascience.com/short-runs-control-charts-variables-data-with-python-7feb220e6957?source=collection_archive---------41-----------------------

面向工业工程师的 Python

使用 Python 库创建质量控制图

图片由 Steven Lelham 拍摄,可在 Unsplash 获得

质量控制图

质量控制图是工程师监控一个过程是否在统计控制下的重要工具。它们有助于可视化变化,发现并纠正出现的问题,预测预期的结果范围,并分析特殊或常见原因导致的流程变化模式。质量控制图常用于精益六适马项目和 DMAIC 项目的控制阶段,被认为是过程改进的七个基本质量工具之一。

控制极限

在质量控制图中,控制极限是绘制在中心线(即平均值)上方和下方的线,其功能是作为识别信号(即超出控制极限的点)的阈值,并帮助确定过程是否处于统计控制之下。它们是由特定于每种类型控制图的公式定义的,这些公式包括常数,这些常数根据样本大小而变化。下表列出了这些常数:

控制极限常数

连续数据的短期控制图

小批量控制图(也称为偏离标称控制图)是一组用于高混合、小批量(即可定制产品)环境的质量控制图。短期控制图不是评估每个测量的变化,而是评估零件与其目标的变化。

对于以下示例,将使用 Python 从头开始构建连续数据的每种短期质量控制图。同样,将提供每个控制图的简要描述。让我们来看看 Python 代码。

目标九图和磁共振图

目标 IX 图(也称为个体 X 偏差图、差异图或名义图)和 MR 图用于监测和评估变量(测量)数据的一致性。目标 IX 图与常规 IX 图相似,但有一点不同:绘图点是单个数据点与其目标之间的

仅当不同目标的方差相同时,目标 IX 图和 MR 图才可以在同一个图上组合不同的运行。为了将目标 IX 图与 MR 图一起使用,样本大小 n 必须等于 1,并且每个样本应该有一个唯一的目标值。

在目标 IX 图上,y-轴显示与目标的偏差、目标值(即 0)、中心线和控制极限,而x-轴显示样本单位。在 MR 图上, y 轴显示移动范围、中心线和控制极限,而 x 轴显示样本单元。

z 条形图和 W 图

当不同目标运行之间的差异太大而无法使用目标 IX 图和 MR 图时,使用 Z 条形图和 W 图。Z 条形图和 W 图是 X 条形图和 R 图对分组数据的一种标准化。

如果所有部分的样本大小 n 相等,Z 条形图和 W 图可能在同一图表上组合不同的运行。目标 X bar2 和目标 R bar 可以从以前的控制图、历史数据、以前的经验或名义规范中获得。

在 Z 条形图上, y 轴显示相对于目标、中心线(即目标值= 0)和控制限值的标准化偏差,而 x 轴显示样本组。在 W 图上, y 轴显示标准化范围、中心线(即目标值= 1)和控制限,而 x 轴显示样本组。

z 图和 MW 图

当不同目标的运行之间的差异太大而不能使用目标 IX 图和 MR 图时,使用 Z 图和 W 图。Z 图和 W 图是个人 X 图和 MR 图的一种标准化。

如果所有零件的样本大小 n 相等,Z 图和 W 图可能在同一张图上组合不同的运行。

在 Z 轴图上, y 轴显示相对于目标、中心线(即目标值= 0)和控制限值的标准化偏差,而 x 轴显示样本单位。在 MW 图上, y 轴显示标准化的移动范围、中心线(即目标值= 1)和控制极限,而 x 轴显示样本单位。

总结想法

质量控制图是分析流程稳定性和获取重要统计信息的重要工具,可用于精益六适马和 DMAIC 项目的流程改进。质量和工业工程师必须能够准确地解释它们,以识别可能导致潜在不合格的不良趋势,从而采取预防措施而不是纠正措施,从而减少废料和浪费。

本指南涵盖了如何使用多个 Python 库从头开始构建短期质量控制图的分步教程。考虑到 Python 在专业人士和学者中的高受欢迎程度,Python 是一个很好的工具,能够为统计目的构建质量控制图表。虽然也有其他程序和软件可以构建它们(例如 Minitab、R、Microsoft Excel),但质量和工业工程师应根据他们的编码和分析技能决定使用哪一种,同时符合组织的目标和客户的规格。

如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。

——罗伯特

关于 Word2Vec、GloVe 和 Fasttext 的简短技术信息

原文:https://towardsdatascience.com/short-technical-information-about-word2vec-glove-and-fasttext-d38e4f529ca8?source=collection_archive---------19-----------------------

介绍

在深度学习的帮助下,自然语言处理(NLP)发展迅速。越来越多的公司愿意更快和大量地处理文本,这就是为什么 NLP 是人工智能研究中的动态领域之一。然而,这些研究主要致力于英语:到目前为止,大多数公司通过翻译处理法语,或者通过多语言算法将法语作为其他语言之一。这一点更加重要,因为深度学习可以导致更准确但更难解释的结果。

通过这篇文章,我试图给出三个最著名的嵌入之间的主要区别。

嵌入

单词嵌入使得单词可以被机器“理解”。它的主要目标是捕捉单词之间的一种关系。例如,这种关系可以是形态的、语义的、上下文的或句法的。将单词转换成向量的一种快速方法是将所有单词转换成整数,然后将这些整数作为它们的一键编码的索引。

让我们考虑三句话的一个热门编码:“狗和猫玩”、“狗吃肉”、“狗和猫吃肉”。在这里,我们可以给这些句子中出现的所有单词赋予整数,按照出现的顺序,一个热编码的长度就是单词集的长度。我们有 6 个唯一的字,独热编码的向量长度是 6。

狗(1,0,0,0,0,0),

和(0,1,0,0,0,0),

cat (0,0,1,0,0,0),

播放(0,0,0,1,0,0),

吃(0,0,0,0,1,0),

肉类(0,0,0,0,0,1)

这种类型的单词表示是有用的,但是效率不高,因为我们不使用单词相似度。对于阅读器来说,狗和猫是完全不同的,因为它们的向量是正交的。在这里是为了,什么是为了或者。然而,我们很容易发现"" dog "这个词与" cat "更相似,而不是与" and "或" eat "更相似。此外,独热编码导致维数为|V|的非常稀疏的向量,即词汇集的大小(|V | > 10^6)。与前面的例子一样,句子的表示如下:

“狗和猫的游戏”:(1,1,1,1,0,0)

“狗吃肉”:(1,0,0,0,1,1)

“狗和猫吃”:(1,1,1,0,1,0)

单词嵌入使得能够在低维向量中存储上下文信息。出现在相似上下文中的单词往往有相似的意思。维度降低(demb < 1000)。向量是由模型通过无监督学习来学习的,通常是在大量数据上,如维基百科、谷歌新闻或数字图书,甚至是普通爬行(网络上的大量文本样本)。相似性是可计算,两个公式是最常用的:余弦相似性和欧几里德距离。

余弦相似度的范围从 1(相反)到 1(共线且意义相同)。相似度高的两个向量通过一个模型容易导致相同的结果。借助 GloVe、FastText 和 Word2Vec 等算法,我们可以获得单词嵌入,帮助模型更好地理解我们的语言,并比使用一次性编码单词的模型给出更准确的结果。然而,这些模型有一个真正的瓶颈,因为它们只考虑了每个单词的一个意思。法语中的“piquer”有很多含义,但是对于这些模型只有一个向量。自 2018 年以来,新的模型已经出现,如著名的埃尔莫,伯特和 XLM。这些模型能够考虑单词的上下文来创建嵌入。不同上下文中的同一个单词不会有相同的相关向量。

单词嵌入的投影。在这里,巴黎之于法国,犹如柏林之于德国。这叫做“类比”。(【https://arxiv.org/abs/1310.4546】T2

作为这第一部分的结论,这里是带回家的:

对词汇表进行一次性编码可能有效,但会导致稀疏矩阵(昂贵的训练)和正交向量(所有单词都是等价的,没有语义捕获)

单词嵌入旨在捕捉低维向量上的语义和语法

单词之间的相似度通常通过余弦相似度来衡量

Word2Vec 之前

在 Word2Vec 之前,单词是通过统计进行编码的。SVD(奇异值分解)是对共生矩阵的降维。SVD 然后被用于处理 LSI(潜在语义索引)。LSI 允许术语间相似性、文档间相似性和术语间相似性。

但由于是基于矩阵分解,所以字典变化时矩阵的维数也变化,我们加一个词就要重新计算整个分解。它对词频不平衡也非常敏感,因此我们经常需要对文档进行预处理,以删除停用词并使所有其他词正常化(通过词条化或词干化)。

最后,它非常昂贵,不适合大型词典或语料库。即使它是 2013 年 NLP 的里程碑,Word2Vec 也不是第一个神经语言模型。其中一些自 2000 年就存在了,正如 Bengio 等人概述的那样。一开始,语言模型的目标是在给定一些前面的单词的情况下,预测“下一个”单词。

Bengio 等人[4]首先提出了遵循前馈架构的模型,Mikolov 等人[27]提出了递归神经网络模型来完成这项任务。前馈神经网络语言模型(NNLM)和递归神经网络语言模型(RNNLM)都具有过高的训练复杂度。实际上,Word2Vec 模型的简单性是主要的创新。

Word2Vec

Mikolov 等人[2] [3]在 2013 年带来了一个高效的单词嵌入实现的创新:Word2Vec。他们首先证明了更浅和更有效的模型 2 允许在更大量的数据上进行训练(速度提高了 1000!).这种效率是通过移除先前架构中存在的隐藏层来实现的。提出了 Word2Vec 的两个版本:连续词包(CBOW)和 SkipGram (SG)。第一种方法基于周围的单词窗口来预测中心单词,第二种方法正好相反:它基于中心单词来预测上下文。这些架构只包含一个隐藏层,这导致了更有效的训练。

Word2Vec 最著名的人物之一,Mikolov(https://arxiv.org/abs/1301.3781–2013)的 Skip-Gram 和 CBOW 模型架构

这是连续单词袋的目标函数:

这里,跳跃图的目标函数是:

随着这些体系结构的变化,一些技术被开发出来,如频繁词的二次抽样和负抽样,以减少模型中要改变的权重的数量。

论文展示了该模型在相似性任务方面的改进。他们还表明,他们获得了比以前发现的更好的结果,在类比任务上使用神经网络语言模型。许多论文讨论了这些模型如何捕捉线性关系[4] [7]。然而,根据经验,Word2Vec 的嵌入改进了 NLP 中的大多数任务,这足以开创一种新趋势。Mikolov 等人(2013)的 Word2Vec 论文被引用超过 28000 次,这表明了研究人员的浓厚兴趣。然而,Word2Vec 并不完美,期望和现实之间的差距相当大。

实际上,Word2Vec 是一个基于窗口的模型,因此它不能从整个文档中的信息中受益,也不能捕获子词信息,这可能是有趣的,因为从名词或动词派生的形容词拥有共同的信息。此外,Word2Vec 不能处理词汇表以外的单词(OOV),因为在训练期间没有看到的单词不能被矢量化。模型的输出是一个格式为“/”的文件。最后,Word2Vec 没有解决的另一个问题是解歧。一个词可以有多个意思,这取决于上下文。前三个问题由 GloVe 和 FastText 解决,而最后一个问题由 Elmo 解决。

处理子字信息的快速文本

快速文本(Bojanowski 等人[1])是由脸书开发的。它是一种学习单词表示的方法,依赖于 Word2Vec 的 skipgram 模型,并提高其效率和性能,如以下几点所述:

1.训练起来更快更简单。在相似性评估上,FastText 在较小的训练集上给出了比 Word2Vec 更好的结果。

2.它受益于子字信息。如果给出一个单词,比如“part out ”, fast text 会使用这个单词的所有 n 元语法来计算这个单词的分数。例如,对于单词“lapin ”,三个字母的单词是“”

3.由于 n 元语法,它可以从词汇表之外的单词中生成嵌入。OOV 单词向量可以用其 n 元文法的平均向量表示来构建。

实际上,使用 SkipGram,给出单词 t 的上下文的概率通过得分函数 s 由单词向量来参数化:

其中 u 和 v 分别取自输入和输出嵌入矩阵。使用 FastText,评分功能变为:

其中 G_wt 是单词 w_t 中 n 元语法的集合,z_g 是第 G 个 n 元语法的向量。v_wc 是上下文单词 wc 的向量。

词汇外单词中字符 n-grams 之间相似性的图解。(https://arxiv.org/abs/1607.04606

x 轴上的单词是 OOV。红色表示正余弦,蓝色表示负余弦。

即使自然语言处理的字符级特征已经是一个研究领域,这篇文章也是第一篇考虑这些特征来构建语言模型的文章。同样,该模型基于预测,而不是基于语料库的统计。此外,它不会根据上下文为每个单词生成多个向量。

处理语料库统计的手套

GloVe (Pennington 等人[5])由斯坦福开发,代表单词表示的全局向量。它的目的是调和单词预测模型和整个语料库的单词统计数据。它们提供了一种模型,该模型考虑了语料库的共现统计以及基于预测的方法的效率。

给定单词 i = ice 和 j = steam,我们想要研究与某个探测单词 k = solid 的共现概率的比率。我们可以预期单词 I 和单词 k (Pik)之间的共现在 Pjk 上更大。那里,比率 Pik Pjk 应该很大。

我们用下面的公式来描述这个比率:

如论文所示,可以简化为:

哪个决议与 LSA 和老方法密切相关。

冰和蒸汽在固体、气体、水和时尚中的共现概率和比率。由于冰与固体的关系比蒸汽更密切,所以同现率很高。考虑到探测字 steam,这是相反的。它们都同样与水(高度)和时尚(模糊)相关,所以共现率大约等于 1。(【https://www.aclweb.org/anthology/D14-1162/】T2

其目标是优化以下函数,这是一个最小二乘问题:

随着

其中 x 是共生矩阵,f 是加权函数,b 是偏差项,wi 是单词向量,w 是上下文向量。

即使 GloVe 在相似性和评估任务上显示出比 Word2Vec 更好的结果,但根据作者的经验,它还没有被证明,使用其中一个或另一个可以导致更好的结果:两者都值得尝试。

结论

最后,所有这些模型仍然有用,甚至是前者。只是看你的用途和需求。Word2Vec 在基本模型上仍然非常相关,可以通过取句子中单词向量的平均值(甚至通过它们的 tf-idf [6]分数加权)来用于嵌入句子或文档。找出答案的一个好方法是尝试所有方法,并保留模型在最终任务中获得最佳分数的方法。

文献学

[1] Piotr Bojanowski、Edouard Grave、Armand Joulin 和 Tomas Mikolov。用子词信息丰富词向量。计算语言学协会汇刊,5:135–146,2016。

[2]托马斯·米科洛夫、G.s .科拉多、程凯和杰弗里·迪恩。向量空间中单词表示的有效估计。第 1–12 页,2013 年 1 月。

[3]托马斯·米科洛夫、伊利亚·苏茨基弗、程凯、格雷戈·科拉多和杰弗里·迪安。词和短语的分布式表示及其组合性。更正,澳大利亚统计局/1310.4546,2013。

[4]大卫·明诺和劳雷·汤普森。负抽样跳跃图的奇异几何。《2017 年自然语言处理经验方法会议论文集》,2873-2878 页,丹麦哥本哈根,2017 年 9 月。计算语言学协会。

[5]杰弗里·潘宁顿、理查德·索切尔和克里斯托弗·曼宁。Glove:单词表示的全局向量。《自然语言处理中的经验方法》(EMNLP),第 1532–1543 页,2014 年。

[6]斯蒂芬·罗伯逊。理解逆文献频率:关于 idf 的理论争论。文献期刊,60:503–520,2004 年。

[7] Laura Wendlandt、Jonathan K. Kummerfeld 和 Rada Mihalcea。影响单词嵌入惊人不稳定性的因素。CoRR,abs/1804.09692,2018。

模拟的捷径:深度学习如何加速药物发现的虚拟筛选

原文:https://towardsdatascience.com/shortcuts-to-simulation-how-deep-learning-accelerates-virtual-screening-for-drug-discovery-f6d4d3bdb721?source=collection_archive---------62-----------------------

来源

药物研发的问题是

众所周知,开发药物是一个艰难的过程。开发一种新药并将其推向市场的成本在13 亿美元到近29 亿美元之间,这取决于你问谁。许多唾手可得的果实已经被摘下来了,而现代社会不断变化的健康状况加剧了这一挑战。我们的老龄化社会现在比我们的祖先更容易受到心脏病、痴呆症和癌症的影响。

抑制性配体 N3 与新冠肺炎冠状病毒蛋白酶 Mpro 的模拟对接。颜色为绿色的配体是实际结构(出自 2020) ),淡粉色的配体代表对接模拟(使用开源软件Smina*, 的一个叉自动对接 Vina )。体积卷积神经网络为生物分子的昂贵物理模拟提供了有效的替代方案, 深度学习 药物发现初创公司正在充分利用 CNN 架构。*

多亏了疫苗和抗生素,在过去的 100 年里,传染病导致的死亡率已经大幅下降。即便如此,正如新冠肺炎疫情提醒我们的那样,现代社会的连通性在新病原体传播的速度和普遍性方面产生了明显的挑战。药物研发者也有一个越来越强的安慰剂效应要处理;如果今天进入双盲临床试验,今天使用的许多抗抑郁药和止痛药可能达不到疗效阈值,甚至有创性心脏干预也可能被安慰剂效应混淆

深度学习基于动物中枢神经系统连通性的多层人工神经网络的使用,由于深度网络逼近和识别复杂模式的能力,已经取得了越来越大的成功。随着深度学习模型的不断改进,它们经常可以比人类更快地提供结果,并且具有更高(或至少相等)的准确性。因此,在决定如何将神经网络应用于给定问题时,有很多选择。

在药物发现中,用于显微镜的计算机视觉是深度学习可以用来为研究疾病的细胞模型创造巨大代表性空间的一个领域。但其他药物发现初创公司则更进一步,完全避开细胞,甚至跳过生化分析,专注于虚拟药物筛选。

生物化学尺度的物理学,即小分子与生物分子的相互作用,与我们日常经验的世界完全不同。热运动,静电排斥和吸引,是的,大量的量子效应都有助于一个违反直觉的环境,至少对习惯于宏观世界的人类来说是如此。

更不用说生物分子机械的复杂程度超过了人类最复杂的工程项目。仅仅是根据蛋白质的序列蓝图来预测蛋白质的折叠、静态结构,就对生物学来说是一个巨大的挑战(也被深度学习打乱),在我们宇宙的预计寿命内,很难用蛮力解决。

在他的讲座“用计算机模拟物理”中,费曼对模拟物理的计算需求的指数爆炸的解决方案之一是使用量子计算机。但是实际上,我们仍在等待量子优势,量子计算机可以证明计算非量子计算机不能计算的东西的极限。深度学习同样是一种具有自身组合爆炸的技术,我们已经看到深度神经网络被应用于近似经典物理问题,具有大规模加速和不同程度的成功。正如我们将在这篇文章中探索的,如果处理得当,深度学习是一个很好的选择,可以近似分子生物活动的指数级复杂物理学。

虚拟筛选词汇表

VS/LBVS/SBVS: 虚拟筛选/基于配体的虚拟筛选/基于结构的虚拟筛选:基于分子特征或结构的候选药物的计算筛选。

HTS: 高通量筛选:在细胞培养或生化分析中,使用自动化进行高度平行的实验室筛选实验。

生物分子:本帖中,生物分子是指生物大分子,包括脂类(脂肪)、蛋白质、碳水化合物、核酸聚合物等。对于我们的讨论,典型的生物分子药物靶标是蛋白质,它可以在细胞中充当酶、机械致动器和运输或信号分子。

小分子:与生物大分子不同,小分子是一种低分子量的有机化合物,如配体,由几十到几百个原子组成。这与单克隆抗体和融合蛋白等蛋白质药物不同,后者大得多,有数百个残基,每个残基由几十个原子组成。

配体:一种能与特定生物分子结合的小分子,有可能改变其活性或阻断其功能

QSAR: 定量构效关系:生物分子和小分子候选药物的结构与其活性之间的关系,例如小分子结合并阻断病毒蛋白酶正常活性的倾向。

在药物发现中使用深度学习的方法

药物发现通常是从大量化学库中筛选针对特定靶分子或表型的活性。现代方法与生物勘探中偶然发现药物的时代明显不同,在那个时代,改变世界的发现是保持一个有点凌乱的实验室的事情。

寻找有前途的候选药物的传统方法是通过高通量筛选(HTS),我们已经谈到自动化和深度学习数据科学如何被用来革新这种方法。为了进一步加快速度,甚至超过实验室实验自动化所能实现的速度,虚拟筛选(VS)提供了一种寻找候选药物的计算方法。

虚拟药物筛选的工作流程包括熟悉的培训、评估和部署步骤。过滤后的数据集被分割、训练、评估,并用于使用监督学习来训练模型。然后将训练好的模型部署为感兴趣的数据集上的屏幕,取代实验室中物理筛选化合物的艰苦过程。在筛查中发现的阳性结果将由实验室进行验证,如果成功,将进行临床试验。

在其他实际应用中,数据科学家和深度学习实践者将熟悉虚拟筛选工作流程,无处不在的“数据管理”或数据清洗步骤将被过滤小分子库所取代,以排除可能的假阳性和不切实际的候选药物(例如分子太大,无法实际放入生物分子靶标的结合口袋)。

过滤后,在部署到未知的虚拟小分子库之前,使用熟悉的训练、测试和验证分割来训练和评估模型。然后,在进入临床试验之前,可以通过化学、细胞和/或模型生物测定来验证在机器学习屏幕中发现的命中。用于虚拟筛选的数据集可以由对给定靶标具有已知活性的小分子的化学和分子性质的库组成,或者在更一般的情况下,由靶标和候选药物的结构信息组成。

虚拟筛选的两大策略

虚拟筛选的两种主要策略分别称为基于配体和基于结构,或 LBVS 和 SBVS。基于配体的 VS 将小分子的分子和化学性质作为输入,并基于与该靶标的已知活性化合物的相似性,预测该化合物是否对该靶标有活性。基于结构的虚拟筛选依赖于药物靶标和小分子的结构信息,将两者放在一起进行模拟,并预测它们是否会结合。

虽然虚拟筛选的两种方法都比实验室分析的高通量筛选少得多,但 LBVS 通常是一个更容易解决的问题,并且计算速度更快。另一方面,LBVS 需要包含已知活性化合物的训练数据集。这可能看起来违反直觉,因为这意味着对已经具有已知活性化合物的目标进行药物筛选,但这可能是可取的,例如,为了找到副作用减少的替代疗法。

基于结构的筛选更普遍,SBVS 通常是在位于蛋白质靶结合口袋中的小分子的物理模拟中完成的。拟合优度是根据原子之间的距离及其静电相互作用等特征来评估的。就深度学习实践者可能更熟悉的术语而言,LBVS 类似于对输入特征向量的训练,并基于虹膜数据集的花瓣宽度和长度提出了分类问题的放大版本。

SBVS 与原始像素作为输入的图像分类任务更密切相关,例如 MNIST 手写数字数据集。因此,SBVS 非常适合能够以端到端的方式学习显著特征的机器学习模型,毫不奇怪,深度人工神经网络非常适合这项任务。虽然深度学习模型可以用来拟合 LBVS 数据集,过度拟合是一个主要问题,而更浅层和更传统的机器学习技术,如支持向量机往往擅长 LBVS。

基于从原始像素到计算机视觉的类比,我们可以期望 SBVS 受益于卷积神经网络中共享权重的空间不变性和局部性特征。事实上,使用 3D 卷积核来匹配生物分子结构数据的维度,卷积神经网络,如来自 AtomwiseAtomNet 和来自 Benevolent AI 的deeply through可以通过评估小分子来筛选数百万至数十亿的潜在候选药物,因为它们适合蛋白质药物靶标的结合口袋。

与更常见的将输入数据乘以滑动方形窗口的 2D 卷积网络一样,3D 卷积网络通过将输入数据和隐藏层乘以滑动立方体窗口来构建隐藏的要素层。

监督学习是目前虚拟筛选药物发现的主要方法

用于结构数据的卷积,其中 2D 像素式卷积核由体素式 3D 核代替。

监督学习是工业 ML 中的主导方法,它是与虚拟筛选药物发现最相关的范式。在实践中,如果你没有足够大小和质量的数据集,开发一个出色的神经网络架构是不够的。为了克服过度拟合的重大障碍,即模型的拟合能力与训练数据集的规模和复杂性不匹配,VS 初创公司已经转向与老牌制药公司合作。像 ZINCPubchem 这样的公共数据集可以用于 VS,但制药公司往往有自己的大规模专有数据集,放大了传统制药公司和机器学习初创公司之间合作的价值主张。

例如,Atomwise 培养了众多的制药合作伙伴,包括查尔斯河实验室,礼来公司和拜耳。同样,两家合作伙伴包括 SK 生物制药公司和小野制药公司,而 Beneveolent AI 与诺华制药公司和阿斯利康公司有协议。学术合作也很重要,Atomwise 的学术合作伙伴包括斯坦福大学王新南教授实验室的一个头条项目,这一努力在 2019 年取得了重大进展,显示了领先的网络预测候选药物缓解了帕金森病的症状并改善了果蝇模型中的生物标志物。

人工智能/深度学习在药物发现中的未来是什么?

现代机器学习的灵活性,也就是深度学习,意味着有许多不同的领域可以应用深度 conv 网络。从应用于结构化数据的 3D 卷积网络,到在 LBVS 数据集上训练的多层感知器,甚至是利用生成对抗训练和强化学习的模型,基于机器学习的药物发现并不缺乏不同的方法。

对于大多数这些应用,深度神经网络采取了一种预测捷径,否则将需要昂贵的实验室分析或复杂的多线程物理模拟。在计算资源方面,神经网络不仅可以加快预测速度,还可以将计算要求转移到更依赖于神经网络原语已优化的高性能 GPU。

这种转变使药物发现和开发能够利用 PyTorch 和 Tensorflow 等基于张量的深度学习库的成熟发展。就像将分子装配在一起的指数级复杂问题一样,设计一个人工智能支持的工作流程需要从过多的选项中进行选择。

使用深度学习的最短路径距离近似:Node2Vec

原文:https://towardsdatascience.com/shortest-path-distance-with-deep-learning-311e19d97569?source=collection_archive---------20-----------------------

实施研究论文“使用深度学习技术的最短路径距离近似”

此处使用的图形数据集的子图

本文是一篇名为“使用深度学习技术的最短路径距离近似法”的研究论文的实现,作者在文中解释了一种新的方法来近似一个图的节点之间的最短路径距离。我将解释这篇论文和我的实现。你可以在我的 GitHub 账户这里找到这个项目。首先,我将概述本文中提出的方法,然后我们将讨论本文中用来解决问题的一些概念,最后是实现。

1.报纸上说什么了?

1.1 动机:当我们有传统的精确方法如 Dijkstra's 和 A算法时,为什么我们需要使用深度学习来近似节点间的*距离?这些传统算法的问题是,它们在非常大的图上运行缓慢,并且会消耗大量内存来存储预先计算的距离。因为对于大多数应用来说,实际距离的近似值已经足够好了,所以它鼓励人们探索各种方法来近似距离。还有,神经网络一旦训练完毕,推理时间(寻找节点距离)是常数( O(1) )。

1.2 算法:既然知道了'为什么',那就来看看'如何'。本文使用了另一篇优秀论文 node2vec:网络的可扩展特征学习中提出的思想。事实上,我要说的是,本文中使用的一些思想在 Node2Vec 论文中已经提出了(例如,在 Node2Vec 论文中提出了使用二元操作符来表示使用相应节点嵌入的边,在本文中扩展为表示路径。我们将在后面讨论嵌入)。本文更多的是 Node2Vec 的一个应用。Node2Vec 本身就是 Word2Vec 的扩展。Word2Vec 是一种用向量空间中的嵌入(数字向量)来表示单词的算法,使得语义相似的单词彼此更靠近。这本身就是一个迷人的话题。

以下是建议方法的总结:

  1. 收集您的图表数据。
  2. 使用 Node2Vec 算法为每个节点寻找节点嵌入。我们不需要从头开始写这个算法。作者提供了一个实现
  3. 使用图中一定数量的节点作为他们所谓的“地标”,并计算它们与所有其他节点的距离。现在你有了形式的样本((landmark_i,node_x),distance)。
  4. 对于上面找到的每个样本,获取界标和节点的相应节点嵌入,并且将它们与任何合适的二元运算符(平均、逐元素乘法等)组合。).所以现在你应该有形式的样本(嵌入,距离)。
  5. 现在你有了输入输出对,所以你做你最擅长的。找一个好的神经网络配置,训练出模型的地狱。但我们稍后会看到,就像一般的人工智能一样,这并不容易。

2.履行

该项目包含以下文件夹:

数据—包含程序使用的所有数据,包括下载的和处理的数据。

输出—保存所有输出,包括文本日志、tensorboard 日志、模型备份等。

src —源代码放在这里。

测试——任何相关的测试用例

注意:请注意,对于这个项目,我主要是在笔记本上工作,因为它涉及到许多探索和各种方法的实验。因此,工作并不完美,因为我还在探索更好的方法。我已经尽我所能解释了这些细胞。如果有不清楚的地方,请随时联系我。

2.1 数据

我在这里使用了的脸书数据集。下载的图形数据为“ mtx 格式。这只是共享矩阵数据的另一种格式。看起来是这样的:

%%MatrixMarket matrix coordinate pattern symmetric
6386 6386 217662
195 1
414 1
458 1
474 1
510 1
.
.
.

第一行称为“header”并定义了一些属性,这些属性用于决定如何解析文件以形成矩阵。它下面的线(大小线)定义了数据的大小。标题总是以“%%MatrixMarket”开头,其后的四个字段是对象、格式、字段和对称性。对象字段可以是“矩阵”或“向量”(在我们的例子中是矩阵),格式可以是“坐标”或“数组”。“坐标”格式在 mtx 文件中仅存储非零值,因此“大小线”保持矩阵中的行数、列数和非零条目数。如果格式为“数组”,则“尺寸线”的格式为[行数和列数]。下一部分是“数据行”,它保存实际的数据。如果格式是“坐标”,则有“非零条目数”数据行数,否则在“数组”的情况下,您应该期望{行数*列数}数据行数,其中每一行表示两个节点之间的一条边。对于加权图,数据线可以具有第三列“边权重”。其余的细节可以在上面的“mtx”链接中找到。我分享这些信息是为了让您对它有一点了解,这样如果您面临解析错误,您可以编写自己的实现。大多数时候我们可能不需要,因为 Scipy 支持读/写 mtx 格式。但是这里我们需要首先将 mtx 转换成 edgelist 格式,因为 Networkx (我用来处理图形数据的包)和 Node2Vec 脚本都使用这种格式。

Edgelist 只是去掉标题、注释和大小行后的数据行,就像这样:

2.2 构建节点嵌入

为了计算图中的节点嵌入,我们将使用 Node2Vec 作者提供的脚本。但是让我先简单介绍一下这个算法,因为它很有趣,也因为它是我们在这里所做的事情的一个重要部分。即使我们不必实现算法,也不应该阻止我们学习它。但是您可以选择跳到下一部分。

2.2.1 节点 2Vec

其思想是对图中每个节点的邻域进行采样,也称为“行走”(这是一种有趣的说法:收集附近的节点),将访问过的节点的列表转换为字符串(这样现在您就有了形式的样本([附近节点的列表,作为包含源节点的字符串])),然后将所有这样的列表传递给 Word2Vec 模型来训练和学习嵌入,就像我们对句子列表进行训练一样。但是 Node2Vec 最好的部分是它如何对邻居进行采样。作者认为,像 BFS 和 DFS 这样的经典方法位于光谱的两个相反的末端。BFS 倾向于对更靠近源节点的节点进行采样,这使得所学习的嵌入更好地捕捉节点的结构相似性(例如,节点是否在其邻域中充当中枢/中心)。但它只对图表的一小部分进行了采样。另一方面,DFS 倾向于对远离源的节点进行采样,因此从这种“行走”中学习会导致嵌入,这种嵌入更好地捕捉图形的宏观视图(连通性和“同质性”,如本文中所述),但不能捕捉更精细的细节,因为行走是有限长度的,并且它们有许多要覆盖的基础。

因此,他们提出了一种新的采样节点邻域的方法,称为“二阶随机游走”。为了更清楚,我们做这些只是为了以可控的方式对节点邻域进行采样,以便遍历包括 BFS 和 DFS 的质量。让我们考虑固定长度的步行'c ''l',并假设您已经从节点' u' 开始步行。假设您已经从节点 t 行进到 v 。他们使用以下概率分布,而不是随机或基于权重边缘选择下一个节点:

下一个节点的 PD,来自 node2vec 纸张

这意味着如果遍历中的前一个节点是 v ,那么下一个节点是 x 的概率由 pi_{vx}/z 给出(不能使用内联 latex,因为每次编辑内容时 Medium 都会搞砸它),如果节点 vx 通过边连接,则为 0。pi_{vx}是未规格化的转移概率, z 是规格化常数(可以是来自节点 v 的所有边的概率的总和)。他们将 pi_{vx}定义为:

非规格化概率修正:应该是 pi_{vx}

其中 w_{vx}是节点 vx 之间的边的权重,并且\(\alpha_{pq}(t,x)\)是:

阿尔法的定义

其中 d_{tx}是 tx 之间的最短路径距离。让我们来理解一下 pq 的作用,因为这是控制随机游走(BFS 或 DFS)性质的两个参数,因此有术语“二阶随机游走”。

如果我们稍微回顾一下,我们从节点 t 到达节点 v ,现在我们需要从 v 决定下一个要访问的节点。如果您将 p 设置为一个较低的值,那么行走会更喜欢重新访问先前的节点。你会问,怎么会?假设你已经从 t 到达 v ,现在你有以下选项——去 v 的其他邻居(x1,x2…xn)或者回到 t (别忘了‘t’也是邻居),在这种情况下 d_{tx}为零,因为这里的 x 是 t 本身(对应于上式中的第一个选项 1/p)。因此,如果 p 是一个非常低的值,那么 1/p 将会非常大,随机漫步将会返回到先前的节点,从而模拟 BFS 的行为。请参考下面的(丑陋的)图片来形象化这一点:

随机漫步:“v”处的下一个节点决策

这张纸有一个相似的图像,但没有距离值。类似地,如果我们为 q 选择一个较低的值,那么我们通过将较高的概率分配给定义α的等式中的第三个选项,鼓励算法冒险远离 t 。对遍历中的每个节点都进行这种决策。这样走了几次。

如果你理解了上面的解释,你就知道 node2vec 随机漫步是如何工作的了。你也可以在作者的 GitHub 库上查看它的实现(但是是 python 2 格式的)。在我的项目中,我也包含了作者的脚本,但是转换成了 Python3 格式。

2.2.2 运行 node2vec 脚本

运行脚本非常简单。您可以选择使用其参数的所有默认值运行,或者根据您的需要进行更改。我用默认值运行:

python node2vec/main3.py --input ../data/socfb-American75.edgelist --output ../data/emb/socfb-American75.emd

只需修改输入和输出路径。

2.3 构建数据集

在上一步中,我们有一个包含节点及其嵌入的文件,格式如下:

6386 128224 0.3206627 -0.0963422 -0.039677385 -0.03290484 0.4414181 ....4046 -0.036134206 -0.082308784 0.49080133 -0.36878866 0.13950641 ...
.
.
.

前两个数分别代表节点数和嵌入维数。我们的下一步是在图中选择一定数量的节点作为界标,并计算它们与所有其余节点的距离。这将给我们(界标数*(节点数-1))个样本。我们选择地标是因为寻找所有节点的距离需要更多的计算。

查找每个节点与所选标志点节点的距离

“distance_map”字典保存每个节点到给定地标的距离(作为关键字)。现在我们需要为每个节点/界标对获取相应的 node2vec 嵌入,并将它们组合起来形成一个单独的嵌入。

组合节点和标志嵌入

这里的 emd_map 是一个字典,它将每个节点作为键,并将它的嵌入作为值。

从嵌入距离字典形成数组

接下来,我们需要从嵌入距离字典中形成 numpy ndarrays,如上所示。请注意上面单元输出中的两件事—样本数不等于界标数*(节点数-1)。这是因为我忽略了具有 inf 距离的节点对,即没有路径连接它们。其次,训练数组的大小很大,大约为 927MB,因为它是“float64”类型的数组。为了节省空间,我把它们改成了 float32。

转换为 float32

如您所见,我们可以节省大约 50%的空间。如果您担心这种转换会导致精度损失,可以验证数据损失:

测量精度损失

这似乎无关紧要。接下来,让我们看看目标变量的分布。

距离值的分布

如您所见,距离值 2 和 3 实际上主导了数据。在图表上,6、7、8 看不到,但它们出现在数据中,只有距离为 8 的样本被我丢弃了。还要注意,在论文中,他们忽略了距离值为 1 的样本,但我已经将它们包括在训练中。

由于数据严重不平衡,我对培训/测试进行了分层:

…然后将其规范化:

我已经保存了分割数据,这样预处理就可以只进行一次。咻!!数据集的形成是这个项目的一大部分,最后我解释了主要步骤。我可能漏掉了一些,更多细节你可以查看项目库中的 data_prep.ipynb

2.4 训练神经网络

现在是激动人心的部分。训练的代码在 train.ipynb 文件中。你会注意到一些单元格看起来没有完成/自记。我特意留下这些,让感兴趣的读者从我失败的尝试和每次失败后采取的步骤中获得经验。我甚至已经将 tensorboard 日志(包括所做的更改、结果、注释等)上传到 GitHub repo 中,以便我和其他人以后可以使用所有的历史记录。如果您对日志不感兴趣,可以毫无问题地删除文件夹。

由于数据是倾斜的,我必须对少数目标值进行过采样(我在这里没有使用术语“类”,因为我已经训练了一个回归模型)。

我首先对多数值进行欠采样,然后对少数值进行过采样。直觉上是对少数距离值进行过采样,使其与多数值的样本数量相当,同时保持总体数据尽可能小。分数值“0.7”实际上不是从任何地方计算/得出的,只是通过查看每个距离值的频率看起来是合理的。是的……不要忘记在过采样/欠采样后重排数据。这似乎是一件微不足道的事情,你可以忽略,但事实证明,许多批次的距离值相同(如全是 1 或 2 等),这使得训练无法进行!

现在,让我们定义一个基线,一个简单的模型及其结果,我们可以与它进行比较,看看我们做得有多好:

使用线性回归设置基线

线性回归做得出奇的好!考虑到这种情况下的概率预测值约为 14% (1/7),50%是一个比较好的基线。

PyTroch 型号

对于我以前的所有项目,我都使用 Keras,但最近我改用 PyTorch,从那以后我就没有后悔过。我在做另一个项目,涉及到编写一个定制的损失函数,需要对模型中间层的输出和其他定制的东西进行一些计算。如果你曾经尝试过 Keras 的这些东西,你就会知道这并不简单。即使有急切的执行,我也不能让它工作。更糟糕的是,在一个晴朗的日子,Keras 开始抛出 CUDA 兼容性错误,无论我用所需的驱动程序构建了多少次新环境,它都不会消失。这是我的转折点。使用 PyTorch,您可能需要为训练循环编写一点额外的代码,但这是值得的。现在,我不是说这些问题不能通过更多的努力来解决,但是,在一个有 PyTorch 的世界里,为什么打破你的头呢?所以,我对我为什么转而使用 PyTorch 的咆哮到此结束。

但是对于不熟悉 PyTorch 的读者来说,不要灰心。几乎所有使用的组件都可以在 Keras 中获得(除了可能是循环 LR 调度器,但是有它的实现可以使用)。解释 PyTorch 超出了本文的范围。

给出最佳结果的模型具有以下配置(具有循环 LR 调度器、RMSProp 优化器和泊松损失):

**{'batch_size': 1000, 'input_size': 128, 'hidden_units_1': 200, 'hidden_units_2': 100, 'hidden_units_3': 50, 'do_1': 0.2, 'do_2': 0.1, 'do_3': 0.05, 'output_size': 1, 'lr': 0.001, 'min_lr': 1e-05, 'max_lr': 0.001, 'epochs': 500, 'lr_sched': 'clr', 'lr_sched_mode': 'triangular', 'gamma': 0.95}**

这是一个有辍学的 5 层(3 个隐藏层)模型,用循环学习率训练。

如果我在此之后尝试了其他配置,你可能在 GitHub 代码中找不到这个型号,因此参数可能会改变。但是你可以在 run47 文件夹 中找到相应的型号和参数。请注意,这种配置不同于他们在论文中提到的配置。正如我读过的几乎所有其他论文一样,他们跳过了神经网络的低级细节。

以下是如何为训练/验证/测试数据初始化数据加载器:

现在我们已经准备好训练模型了:

还只做过 Keras/Fastai 的人,不要害怕。训练 PyTorch 模型的代码并不总是这么大。我正在做很多其他的事情,比如提前停止,保存检查点等等。肯定比 Keras 复杂,但没什么一两天学不会的。但正如我之前提到的,所有这些组件都已经在 Keras 中存在(包括泊松损失),因此您可以轻松地在您选择的框架上进行尝试。

我训练了大约 110 个时期的模型。

结果如下:

泊松损失= -0.11
MAE 损失= 0.32
MSE 损失= 0.17
准确度= 76.40%
vs
基线:
MAE 损失= 0.59
MSE 损失= 0.56
准确度= 50.57%

虽然这是一个回归问题,但我仍然记录了准确性,因为我发现它更直观(它不是一个指标,只是我用来比较模型的东西)。这不是一个值得夸耀的结果,但也不坏。此外,我认为还有很大的改进余地,我将在后面提到这一点。

如果你想知道为什么路径距离越长准确性越差,作者也做了类似的观察。他们是这样说的:

观察到利用 node2vec 嵌入的较长路径导致的较大误差。一方面,在训练集中,我们没有足够的样本用于更长的距离。另一方面,node2vec 无法学习远处节点的结构特征。

论文的结果。请注意,路径距离越长,误差值越大。

注意:这个模型有一点让我很困扰。尽管使用 exp_range 作为 CLR 模式,学习率在整个训练中没有变化(至少按照图)。伽玛值为 0.95 时总是会发生这种情况。需要调查一下。或者你之前也面临过这种情况,有什么解决办法,欢迎在这里分享。

回想起来,以下是提高模型性能的一些因素:

  1. 泊松损失:我之前尝试过 MSE 和 MAE(论文中使用的),但是两者都不行。
  2. 批量正常化:批量正常化之前训练损失改善真的很慢。在 batch norm 之前,我在达到这些数字之前至少训练了 1000 个纪元。
  3. 欠采样/过采样
  4. 循环 LR 调度程序
  5. StandardScaler 代替 MinMaxScaler
  6. 将优化器从 SGD 更改为 RMSProp(本文中使用的是 SGD)

3。进一步改进

有很多事情可以探索,因此需要很大的耐心。以下是一个不完整的列表:

  1. 更好的超参数:尤其是学习率范围和不同的网络架构。
  2. 尝试对这些数据使用卷积神经网络。我很肯定这会改善结果。
  3. 不同的 node2vec 嵌入维度(我们用的是 128)。
  4. 您可能还记得,我们使用“平均”运算符来组合两个节点的嵌入。我们可以试试其他运营商。在论文中,作者观察到—

“二元运算符在不同的数据集和不同的维度大小上没有一致的行为。例如,在脸书图中,平均算子优于其他算子,而串联在 Youtube 数据集上效果更好”

5.特性选择:我们可以通过只选择重要的特性来减少特性的数量。(文中未使用)

6.更好的采样技术:如 KMeansSMOTE、SMOTE、聚类质心等。我试着使用这些技术,但是它们花了太长时间来完成。

7.训练损失和 val 损失差距较大,建议减少过拟合以获得更好的结果。也许可以试试小一点的模型,看看它是否有学习能力。

4。结论

嗯,这已经是一篇长文了,所以我就不啰嗦了。这是一个有趣的项目,有很多很酷的概念需要学习。我不能在这里容纳他们中的许多人,但我已经记录了并将记录更多关于这个问题的有趣事实,当我发现它们时,在项目的 fun.ipynb 文件中。谢谢你坚持到最后。编码快乐!

最短路径和 Dijkstra 算法

原文:https://towardsdatascience.com/shortest-paths-and-dijkstras-algorithm-68c9ec30eff0?source=collection_archive---------24-----------------------

地球上最经典的图形算法,解释。

这个问题的经典表述是:

如果给我一个节点图,每个节点都与其他几个节点相连,并且连接的距离不同,那么从图中的一个节点开始,到图中每个节点的最短路径是什么?

深度优先

为了实现 Dijkstra 算法,我们首先需要定义一个节点和一条边:

class Node:
    def __init__(self, value):

        self.value = value
        self.edges = set()

        self.distance = -1

    @staticmethod
    def add_edge(a, b, dist):
        a.edges.add((b, dist))
        b.edges.add((a, dist))

在本例中,我定义了一个节点,它包含一个值(基本上是一个 id),一个初始化为-1(无穷大)的距离。此外,该节点包含一个边列表,每个边都是该边连接到的目标节点(自自身)和到目标节点的距离的元组。

那么,我该如何填充从一个起始节点到图中每个节点的最短距离呢?

实际上很简单。在起始节点,我将其距离更新为 0,并且对于该节点具有的每条边,如果目标节点未被访问(距离= -1)或者目标节点的当前距离大于新距离,我递归地将目标节点的距离更新为当前节点的距离加上边距离:

def update_distance(self, dist):

    if self.distance < 0 or dist < self.distance:

        self.distance = dist
        for e in self.edges:
            e[0].update_distance(dist + e[1])

将所有这些与一个示例图放在一起:

节点= [1,2,3,4]
边= [(1,2,1),(1,3,10),(1,4,20),(2,3,30),(2,4,40),(3,4,50)]

class Node:
    def __init__(self, value):

        self.value = value
        self.edges = set()

        self.distance = -1

    @staticmethod
    def add_edge(a, b, dist):
        a.edges.add((b, dist))
        b.edges.add((a, dist))

    def update_distance(self, dist):

        if self.distance < 0 or dist < self.distance:

            self.distance = dist
            for e in self.edges:
                e[0].update_distance(dist + e[1])

def create_graph1():

    node1 = Node(1)
    node2 = Node(2)
    node3 = Node(3)
    node4 = Node(4)

    Node.add_edge(node1, node2, 1)
    Node.add_edge(node1, node3, 10)
    Node.add_edge(node1, node4, 20)
    Node.add_edge(node2, node3, 30)
    Node.add_edge(node2, node4, 40)
    Node.add_edge(node3, node4, 50)

    return [node1, node2, node3, node4]

def print_nodes(nodes):

    print('print nodes --')
    for node in nodes:
        print(f'value: {node.value}, distance: {node.distance}')

nodes = create_graph1()
nodes[0].update_distance(0) # set start node distance 0
print_nodes(nodes)'''
print nodes --
value: 1, distance: 0
value: 2, distance: 1
value: 3, distance: 10
value: 4, distance: 20
'''

现在,如果我将从节点 2 到节点 4 的距离更新为 1,那么节点 4 的最短距离应该是 2,因为现在我可以从节点 1 到 2,然后从 2 到 4,距离为 2。我们来看看是不是这样:

节点= [1,2,3,4]
边= [(1,2,1),(1,3,10),(1,4,20),(2,3,30),(2,4,1),(3,4,50)]

def create_graph2():

    node1 = Node(1)
    node2 = Node(2)
    node3 = Node(3)
    node4 = Node(4)

    Node.add_edge(node1, node2, 1)
    Node.add_edge(node1, node3, 10)
    Node.add_edge(node1, node4, 20)
    Node.add_edge(node2, node3, 30)
    Node.add_edge(node2, node4, 1)
    Node.add_edge(node3, node4, 50)

    return [node1, node2, node3, node4]nodes = create_graph2()
print_nodes(nodes)
nodes[0].update_distance(0)
print_nodes(nodes)'''
print nodes --
value: 1, distance: 0
value: 2, distance: 1
value: 3, distance: 10
value: 4, distance: 2
'''

看起来有用!

性能分析,深度优先

那还不算太糟,是吗?

但是让我们暂停一下,想想这个过程需要多长时间。

从起始节点开始,如果起始节点连接到所有其他节点,那么 update_distance 中的第一个循环是 O(n-1),其中 n 是图中的节点数。在 update_distance 内部,我们在连接的目标节点上递归调用 update_distance,在最坏的情况下,目标节点也可能连接到所有其他节点,并且只有一条边保证不会被遍历(与当前节点的边),因此第二次递归 update_distance 是 O(n-2)。

至此,不难认识到整体算法的复杂度为 O((n-1) * (n-2) * … * 2 * 1) = O(n!)在最坏的情况下。不太好。

最小堆

看起来我们有一些改进要做,这就是 Dijkstra 算法要做的。

从一个很巧妙的观察就能理解算法。在上面的图 2 中,节点 1 直接连接到节点 2、3、4。其中最小的距离是到节点 2 的距离,为 1。现在你知道到节点 2 的最短距离最多是 1,还能再短一点吗?答案是否定的,因为从节点 1 到节点 2 的任何间接路径都必须经过节点 3 或节点 4,这两个节点的距离都大于 1。

这是一个非常重要的见解,因为这意味着在处理完节点 2 之后,我不必再查看节点 2,因为知道到节点 2 的最短距离是 1。这避免了检查从节点 1 到节点 3 到节点 2 的距离的冗余,因为我们肯定知道该距离将大于节点 2 的现有距离。

为了实现这一点,我们采用了最小堆数据结构。它的实现可以有很大的不同,但是操作很简单,我可以把任何对象放到它上面,当我请求堆返回一个对象时,它总是返回带有最小关联键的对象。

以下是 Dijkstra 算法的最小堆实现:

import heapq as hq

class Node:
    def __init__(self, value):

        self.value = value
        self.edges = set()

        self.distance = -1
        self.visited = False

    @staticmethod
    def add_edge(a, b, dist):
        a.edges.add((b, dist))
        b.edges.add((a, dist))

def calc_distance(start):

    h = []

    start.distance = 0

    hq.heappush(h, (start.distance, start))

    while len(h) > 0:

        cur = hq.heappop(h)

        # check if the nodes has been updated
        if cur[0] != cur[1].distance:
            continue

        for e in cur[1].edges:
            new_distance = cur[1].distance + e[1]

            if e[0].distance < 0 or new_distance < e[0].distance:
                e[0].distance = new_distance
                hq.heappush(h, (new_distance, e[0]))

def create_graph1():

    node1 = Node(1)
    node2 = Node(2)
    node3 = Node(3)
    node4 = Node(4)

    Node.add_edge(node1, node2, 1)
    Node.add_edge(node1, node3, 10)
    Node.add_edge(node1, node4, 20)
    Node.add_edge(node2, node3, 30)
    Node.add_edge(node2, node4, 1)
    Node.add_edge(node3, node4, 50)

    return [node1, node2, node3, node4]

def print_nodes(nodes):

    print('print nodes --')
    for node in nodes:
        print(f'value: {node.value}, distance: {node.distance}')

nodes = create_graph1()
print_nodes(nodes)
calc_distance(nodes[0])
print_nodes(nodes)'''print nodes --
value: 1, distance: 0
value: 2, distance: 1
value: 3, distance: 10
value: 4, distance: 2
'''

有用!

性能分析,最小堆

让我们稍微讨论一下新算法的性能。

从第一个节点开始,我们将其距离设置为零,并将其添加到 min 堆中,将其当前距离作为排序关键字。然后,只要 min 堆不为空,就不断地弹出具有最小键的节点,循环遍历其所有连接的节点,并更新它们的最短距离,如果新距离更短,则将它们推送到 min 堆上。

需要注意的一件重要事情是循环中的以下几行:

# check if the nodes has been updated
if cur[0] != cur[1].distance:
    continue

这将检查堆上对象的键是否与节点的当前最短距离相同。考虑以下情况:

节点= [1,2,3,4]
边= [(1,2,1),(1,3,4),(2,4,10),(3,4,2)]

如果我有 4 个节点的图:1,2,3,4

节点 1 —节点 2,距离 1

节点 1 —节点 3,距离 4

节点 2 —节点 4,距离 10

节点 3 —节点 4,距离 2

Start:将开始节点推到堆上,距离为 0

[(0,node1_dist0)]

迭代 1:在第一次迭代中,最小堆包含键为 0 的 node1,然后弹出它,并将它的邻居添加到堆中。

[(1,节点 2_dist1),(4,节点 3_dist4)]

迭代 2:去掉 node2 并添加它的邻居。

[(4,节点 3 _ 分布 4),(11,节点 4 _ 分布 11)]

迭代 3:删除节点 3 并添加其邻居。

但是等等!节点 3 的邻居节点 4 已经在队列中,唯一的区别是它的最短距离现在更新为 6:

[(6,节点 4_dist6),(11,节点 4_dist6)]

您可以看到,堆中实际上有两个节点 4 的条目,一个具有键 6,一个具有键 11,只有一个条目的键等于当前节点 4 的距离值。

在下一次迭代中,具有键 6 的条目被弹出,因为它是最小的键,并且它的邻居被处理,但是因为它的邻居都已经具有最短的距离,所以它们不会进入队列。只剩下一个条目:

[(11,node4_dist6)]

在这种情况下,您显然想忽略它,因为 node4 已经被处理了,并且您可以知道的方式是键和 node4 的最短距离彼此不相等。

对于当前已知的最小堆实现,弹出函数是 O(log(n))运算。因为如果有边,你将把一个节点推到堆上,所以算法的复杂度是 O(e * log(n)),其中 e 是边的数量。

实际上,还有更多。你能拥有的最大边数是多少?如果每个节点都与其他节点相连,图中有 n 个节点,那么边的总数是 n * (n + 1) / 2。所以 e 实际上是 O(n**2)的量级,算法实际上是 O((n ** 2) * log(n))的量级

但是从上面的例子中可以看出,由于 node4 有两条边,所以它在堆中出现了两次,如果我们可以将现有的边 11 更新为 6,我们实际上就不必添加它两次。恰好有一种特殊类型的堆允许您这样做。它叫做 斐波那契堆 。在这种情况下,您可以将键从 11 个减少到 6 个,并且在堆中只让 node4 出现一次,不管有多少条边连接到它。

斐波那契堆中的 decrease 关键函数是 O(1),常数运算,所以你的整体复杂度归结为 O(n*log(n) + e)。你加 e 的原因是你必须减少 e 倍的 key。

最后,如果我们认为原始的最小堆算法具有运行时间为 O(log(n))(基本上是用键 11 弹出节点 4 条目所花费的时间)的减少键功能,那么原始算法的复杂度可以更精确地定义为 O((n + e) * log(n))。

数据科学家应该知道如何编码吗?

原文:https://towardsdatascience.com/should-a-data-scientist-know-how-to-code-b6fc8bd39094?source=collection_archive---------59-----------------------

深入了解不同类型的数据科学家

Joshua Sortino 在Unsplash【1】上拍摄的照片。

目录

1.介绍

2.商业数据科学

3.机器学习数据科学

4.摘要

5.参考

介绍

数据科学家可以是多种身份,而编码员可以是其中之一。在我从事数据科学的职业生涯中,我见过许多专业人员使用最少量的代码。但另一方面,我也见过有人写代码书来解释他们的模型。真的,归根结底是你想成为什么类型的数据科学家。在过去几年采访了无数家公司后,我了解到有特定的数据科学家角色。他们可以分为两大类:一类是使用建模来解释数据科学更侧重于业务的一面的人,另一类是执行高级 python 代码的人,这些代码不仅可以将模型投入生产,还可以找到一种方法来简化数据,从而实现整个流程的自动化。下面,我将详细阐述业务数据科学家和编码数据科学家的主要区别。

商业数据科学

有一些大型科技巨头会发布数据科学家的职位,但当你仔细看文本时,你会发现在第一种编程语言出现之前就有一句接一句的句子。

这个角色本质上是一个专注于统计的专家数据分析师。

这个职位的另一个重点是磨练你的可视化技能。也就是说,你必须是 Google Data Studio、Power BI 或最流行的 Tableau 等平台或工具的专家。不仅可视化数据很重要,获取数据也很重要。您将不得不练习强大的 SQL 技能来查询将构成您的模型数据集的数据库。一旦你开始建模,你需要知道的一些基本的东西是统计学——比如 A/B 测试。总而言之,这种类型的数据科学家的关键部分是:

可视化 — Tableau,向业务利益相关者展示您的关键指标和发现的最重要工具。

SQL —通过连接各种表、子查询和其他更复杂的获取数据的方式来查询数据库。

统计/洞察 —除了 A/B 测试之外,这部分角色还需要使用回归建模、方差分析(ANOVA)、SAS等工具。

机器学习数据科学

照片由法比安·格罗斯Unsplash【2】上拍摄。

与上面更以业务为中心的角色不同,这个角色旨在突出那些在以更面向对象的方式篡改机器学习模型时对软件工程有很大诀窍的人。

面向对象编程——你将不再只在你的 Jupyter 笔记本上工作,而是用它来编写干净的结构化的(很可能是 Python 代码)。使用类和函数的 py 文件。

【Docker/air flow/DAGs——这些工具有助于自动引入新数据、训练和评估。基于某些参数,您可以每小时、每天等运行您的模型,或者在有一定数量的新评估数据时运行。所有这些方法的另一个术语是机器学习管道。

摘要

尽管这两个角色重叠,甚至可能有两个独立的工作描述,有时在你的公司你会发现自己做其中一个。如果你幸运(或不幸运),你会有一个官方的机器学习工程师或软件工程师将你保存的模型投入生产,这样你就可以专注于模型本身,如超参数和无监督与监督学习。要成为最好的,你需要这两种角色。然而,请记住,一些公司会告诉你,你将成为一名数据科学家,而实际上你几乎将成为一名数据或商业智能分析师。

答案是肯定的,你需要知道如何编码才能成为一名数据科学家。

为了进一步了解数据科学家和数据分析师之间的区别,我写了一篇以前的文章,你可以在这里找到[3]。感谢您的阅读,我希望您觉得这篇文章有趣并且有用!

[## 数据科学与数据分析。区别就在这里。

数据科学家和数据分析师的主要区别和相同点是什么?阅读下面的概述…

towardsdatascience.com](/data-science-vs-data-analysis-heres-the-difference-4d3da0a90f4)

参考

[1]Joshua Sortino 在 Unsplash 上拍摄的照片,(2017)

[2]照片由 Fabian GrohsUnsplash 上拍摄,(2017)

[3] M.Przybyla,数据科学家 vs 数据分析师。差别在这里,(2020)

非洲国家应该寻求与散居者重新联系吗?想象加纳回归的一年

原文:https://towardsdatascience.com/should-african-countries-pursue-reconnection-with-the-diaspora-visualizing-the-year-of-return-b9f87abc3dc1?source=collection_archive---------29-----------------------

来源:美国有线电视新闻网

在 2019 年期间,加纳的“回归之年”活动在我的社交媒体时间轴上出现了无数次,最终在一个充满动作、星光熠熠、FOMO 鼓舞人心的 12 月达到高潮。当我得知这些努力使他们的经济增长了 19 亿美元(来源: Face 2 Face Africa )时,我感到一阵兴奋和鼓舞,同时也想知道这对其他非洲国家意味着什么,比如我的祖国尼日利亚。他们应该效仿吗?

我们今天的关键问题: 其他非洲国家是否应该效仿加纳的回归年策略?

来源:Face 2 面向非洲

答案显然是肯定的,对吧?和所有事情一样,这取决于…

首先,我们首先需要更好地了解它有多成功。19 亿美元是一个巨大的数字,但在上下文中它看起来像什么?如果我们将 19 亿美元与我银行账户的当前金额进行比较,这看起来是巨大的,而与微软、苹果或亚马逊的市值相比,可能就不那么大了。

这就是这篇博文的目的。此外,还有什么更好的机会来实践一些数据科学技能,并享受可视化的乐趣呢?

但是在我们试图回答这个问题之前,让我们后退一步,回到一个始于 400 年前的故事……(实际上要更久)

回归年份?

“2019 年加纳回归年”是一个重要的里程碑式的精神和生来权利之旅,邀请国内外的全球非洲家庭纪念第一批被奴役的非洲人抵达弗吉尼亚州詹姆斯敦 400 周年。被奴役的非洲人的到来标志着一个肮脏和悲伤的时期,我们的亲人被强行带离非洲,遭受多年的剥夺、羞辱和酷刑。虽然 2019 年 8 月是被奴役的非洲人抵达美国 400 周年,但“回归之年,加纳 2019”庆祝了分散在北美、南美、加勒比海、欧洲和亚洲世界各地的所有跨大西洋奴隶贸易受害者的累积复原力。

我们专注于确保我们的兄弟姐妹有一个安全、愉快和美好的回家之旅,这样他们就会想回来,参与进来,看到加纳存在的机会,让我们一起努力,并开始重建过去 400 年来被偷走和失去的东西。

听起来很神奇。怎么样了?

来源:美国有线电视新闻网

没那么快……

虽然你和我都想得到我承诺的性感图表,但在此之前,重要的是要进行一次诚实的对话,讨论这个分析是什么,不是什么,以及我们实际上可以从中得出什么结论。尤其是在这个假新闻和另类事实充斥的时代,信息可以在几秒钟内传遍世界,其他任何事情都是不负责任的。

19 亿美元的头条数字来自加纳旅游部长的一句话:

“根据旅游部长芭芭拉·奥腾-贾西的说法,通过与‘回归年’相关的活动,加纳的经济创造了总计 19 亿美元的收入。

她说:“大量的社区参与刺激了当地经济,包括酒店经营者、旅游经营和其他相关业务。””——面对 2 面对非洲

我能够追踪到的加纳旅游收入的数据来自世界银行,涵盖了 1995 年至 2017 年,但不是 2018 年或 2019 年。以下是他们对所提供数据的描述:

国际旅游收入是国际入境游客的支出,包括支付给国家航空公司的国际运输费用。这些收据包括在目的地国家收到的货物或服务的任何其他预付款。它们还可能包括当天游客的收据,除非这些收据非常重要,足以证明单独分类是正确的。对于一些国家,它们不包括客运项目的收据。数据以现值美元表示。

虽然世界银行提供了他们的数字是如何计算的,但我们 2019 年 19 亿美元的数字没有更多细节,这意味着我们很可能没有比较苹果,也不能做出任何权威声明。

这就是生活。这是真实的世界,我们并不总是能够获得我们想要的每一份数据。与其被吓到,不如让我们承认模型中的弱点,陈述我们的假设,并尽我们所能利用现有的数据。

这是一个起点。当我得到更完整的数据时,我们会深入调查,继续接近真相。加纳,尼日利亚,博茨瓦纳,向我叫喊。欢迎所有来者:)

这也是一个实践我们的数据探索和可视化技能的机会,并希望激励至少一位读者像我一样爱上数据科学。

有了基本规则,让我们玩得开心点…

活动成功

哇哦。这是一个很好的开始!

尽管我们继续承认 19 亿美元这一数字的严格性存在局限性,但在我们可以依赖这一数字的程度上,它代表着一个巨大的飞跃。

加纳的国际旅游收入在过去 25 年中快速稳定增长,2012 年达到 11.5 亿美元的峰值,2017 年降至 9.19 亿美元,这意味着 19 亿美元将是 2017 年收入的两倍以上。

如果不提高数据的精确度,我们就无法获得更高质量的答案,但我认为还有更大的娱乐空间。

【2018 年呢?处理缺失数据

嗯,这是尴尬的…由于数据收集的挑战,世界银行不提供实时或接近实时更新这个数据集。我们已经用部长的论断估计了 2019 年,但是 2018 年呢?我们什么都没有。

虽然没有 2018 年不会以某种方式影响我们分析的关键,但在我们的图表上显示一个值可能会很好,而且它给了我们另一个机会。

数据科学家每天都在处理缺失的数据。有时,解决方案是丢弃这部分数据,不再考虑它。其他时候,答案是插补,或根据我们从现有数据中得出的推论替换替代值(是的,我们正在编造……但以某种有意义的方式:)。根据具体情况,输入平均值、中值、零或单词“缺失”可能是有意义的。

在这种情况下,我测试了几种不同的可能性,包括平均值、中值和插值,最终确定了 2012 年至 2017 年的平均收入,因为当看这些数字时,这些年似乎是同一趋势的一部分。使用这一策略得出的估算值为 9.345 亿美元,这对于一个虚构的数字来说似乎相对合理。

另一个合理的选择是使用 2005 年至 2017 年的平均收入,这将为我们提供类似的 9.278 亿美元的结果。

83 亿美元之路

2012 年,加纳政府发布了一项 15 年国家旅游业发展计划,预计到 2027 年旅游业收入将超过每年 83 亿美元。

虽然我们没有人能肯定地说目标是否会实现,但我绝对知道想象会很有趣,所以让我们开始吧。

正如我在上面想象的那样,假设增长会以完美的直线方式发生是愚蠢的,但观察规模上的相对关系来了解我们正在谈论的增长类型仍然是有趣的。

入境人数的增长

根据“回归之年”秘书处 2019 年前九个月的数据,来自美利坚合众国、英国和其他主要目标国家的入境人数比上一年增加了 80,862 人。

数字显示,来自美利坚合众国和联合王国的机场入境旅客分别增加了 26%(17 455 人)和 24%(9 812 人)。一名官员指出,“与去年相比,机场总抵达人数增加了 45%(237,088 人)。”— 面对 2 面对非洲

虽然世界银行只报告了 2015 年的官方入境人数,但我们没有 2016-2019 年的数据,我们可以看到加纳的旅游政策一直处于正确的轨道上,入境人数呈稳步上升趋势。

然而,鉴于 2015 年入境人数为 897,000 人,比 2014 年增加了 72,000 人,单年增加 237,000 人绝对是一个惊人的飞跃。

另一方面,在过去几年中,每次抵达的收入没有显示出如此明显的趋势。我很想知道这一指标在回归之年的表现如何。

旅游业在加纳经济中的地位

虽然近年来旅游业持续增长,但加纳的总体出口增长更快,到 2017 年,旅游业收入仅占总出口的 4.5%(低于 2005 年 22%的高点)。加纳最大的出口商品是黄金、可可豆和木材产品,此外还有金枪鱼、铝、锰矿、钻石和园艺产品

我们很想知道这一比例是否受到回归年活动的影响,但无论如何,促进加纳的旅游业显然仍是一个重点。

总之

很明显,加纳的回归年是一次非常成功和有影响力的运动,其他国家应该明智地向它学习。

尽管如此,仍有许多问题有待探索,例如:

  • 与其他非洲国家相比,加纳的旅游收入及其增长如何?
  • 与同等规模的国家相比,加纳的旅游收入及其增长如何?
  • 回归年活动是否有任何意想不到的影响/后果?
  • 还有更多…

然而,鉴于这是一篇博客文章,而不是一本书,我将暂时在这里结束事情。

如果你想了解更多,请发表评论。

如果你有我正在寻找的数据,或者我可以帮助你探索的其他数据,请随时与我联系。

如果你对所使用的工具和技术有任何疑问,或者我做过的任何事情,请在评论中告诉我,我很乐意帮助你。

直到下一次!

来源:加纳周末

分析应向首席技术官、首席采购官或首席财务官报告

原文:https://towardsdatascience.com/should-analytics-report-to-cto-or-cpo-or-cfo-cddbdc39f962?source=collection_archive---------27-----------------------

苹果为何未能建立 Instagram 的答案给了我们一个线索

解释为什么苹果可以进入芯片制造领域,但不能在应用程序(照片共享、地图)上竞争的框架可以教给我们很多关于大中型公司数据团队的最佳组织结构。

组织结构至关重要,因为同样的人以不同的方式组织会产生“不同的”组织。在改变一个组织的两种方式之间,“改变谁在其中”和“改变互动拓扑”,第二种更便宜,破坏性更小。

首先,我们将讨论解释大公司为何无法占领新市场的堆栈谬误。当他们进入堆栈时,他们失败了,因为他们错误地认为构建上面的层是微不足道的,只是失败得很壮观。随后,我们将把这些概念应用于技术组织中的数据团队结构,在这些组织中,公司因为缺乏对堆栈谬误的理解而犯错误。产品向技术部门报告的错误很少发生,所以我们不会深究。

堆栈谬误和为什么大公司不断失败

堆栈谬误借鉴和建立在下面的漫画。

漫画致谢: XKCD

安舒·夏尔马认为,在商业战略的世界里,我们有一种幻觉,就像连环漫画中的数学家一样。这位数学家认为数学是一切的核心。他是自己领域的主人。因此,他是一切的主人。例如,数据库公司认为 SaaS 应用程序“只是一个数据库应用程序”,这给了他们可以轻松构建、竞争并获胜的错误信心。该框架解释了为什么 Salesforce 在 CRM SaaS 击败了 Oracle。

堆栈谬误是人性使然;我们过分看重我们所知道的。然而,成功的瓶颈往往不是对工具的了解,而是缺乏对客户需求的理解。令人惊讶的是,向下创新远比向上容易,因为我们是较低层的自然客户。越往上走,越容易忽视史蒂夫·乔布斯的建议——从客户需求开始,而不是从技术开始。

现在,让我们深入分析报告结构。

堆叠谬误与报告结构

组织通常有正确的报告结构;领导一群技术人员的商业人士。然而,对于“数据”团队来说,他们忘记了在堆栈谬误的环境中看到它,因此,犯了错误。对空间缺乏了解是因素之一。

概括地说,数据团队中有两个单元。第一个 pod 负责以可用的格式检测、收集、转换和呈现数据。第二个 pod 从数据中获得产品战略和执行的见解。第一个单元称为数据工程/技术,第二个单元称为分析和数据科学。在以下段落中,我们将把分析进一步分成三个部分,讨论它们在组织层级中的位置。

对于分析领导力和报告结构,您将在下面找到领导者犯下的错误列表,以及相应的见解和修复方法。

分析领导力

  1. 选择一位数据技术(DT)专家来领导一个分析团队是一个严重的错误。花费大量时间磨练核心技能和攀登职业阶梯的 DT 领导者在转变和管理高层角色方面表现不佳。他们挣扎是因为 a. DT 角色无助于加强用于分析的神经元 b .他们高估了自己核心技能的相关性 c .正式领导让他们看不到来自他们报告的反馈。
  2. 更明智的做法是,让精通数据的产品负责人或之前已经过渡到产品的分析负责人来领导团队。苹果成功制造芯片的方式是,产品人员可以在让分析成为洞察机器方面做得很好。
  3. 很少有 DT 人员在管理分析方面做得很好,但他们是例外,而不是常态。

报告结构

  1. 向技术部门提交分析报告会导致灾难。DT 应该向技术汇报,但分析必须更贴近业务。他们可以向产品部或首席运营官汇报——如果有的话。
  2. 数据科学可以是技术团队的一部分,但他们必须与业务(产品和分析)密切合作。数据科学有助于构建业务逻辑,它比构建经验更具迭代性。在这里,产品、分析和数据科学之间的紧密合作对于项目的成功至关重要。
  3. 分析有三个功能:a .为产品策略生成洞察 b .为优化执行和运营生成洞察 c .产品性能报告。理想情况下,第一批分析人员应该是产品团队的一部分。为了管理利益冲突,第二个和第三个分析单元可以是首席运营官或首席财务官的一部分。许多组织在这里犯了一个错误,因为他们认为这是一种“集中-分散”的权衡,而不是将分析区分为三个单元。
  4. 不常见,但是一些组织确实犯了向技术部门报告产品的错误,通常会导致混乱。尽管一个大的技术组织可能有一群技术产品经理,但是一个技术组织中的消费者产品经理是一个灾难的处方。

感谢, 瑞奇 Q 进行校对和编辑。

数据科学家该不该学数据讲故事?

原文:https://towardsdatascience.com/should-data-scientists-learn-data-storytelling-f0eadf118662?source=collection_archive---------48-----------------------

讲述故事如何让数据科学超越 KPI,走向真正的分析

图片由猴子商业图片提供

Jasmine Samuel 是纽约市的一名数据科学家。她几年前离开了学术界,进入了私营企业。在学术研究和商业咨询领域都工作过的她告诉我,学术界想要的和商业界想要的数据科学之间有很大的区别。

她告诉我,“许多组织只会使用非常基本的描述性统计数据来理解绩效。”

像这个成长中的行业中的许多年轻人才一样,她明白更好的预测模型可以为决策做些什么。

然而,唯一的问题是,向业务利益相关者明确这一点是一个挑战。

她说,“通常他们想要的衡量标准是‘A 组表现好了 60%或 20%’。“这就是他们要做的决定。”

虽然了解这类信息肯定很方便,但这意味着许多企业没有充分利用他们拥有的数据,更不用说数据科学家的高级技能了。

“描述性统计不是用来做决策的,”贾斯敏说。“他们没有推理能力。这是我希望更多人广泛理解的事情。”

这是新的数据科学专业正在经历的成长烦恼的一部分,因为它被从未使用过统计建模的企业所接受。

“我认为我们在数据领域有一个相当大的问题,”Jasmine 说。“每个组织都希望以数据为中心,但组织不一定知道如何做到这一点。从领导层的角度来看,他们不了解数据,也不知道如何利用这些数据。”

学术界、保险、金融和制药行业依赖统计建模的时间比大多数行业都要长。对于研究人员、精算师、经济学家和生物统计学家实际上为他们的组织做了什么,他们开发了一个共享的词汇和理解。

“这是学术界和研究的一件大事,”贾斯敏说。“你正在和具有相同心智模式和基本相同技能的人一起工作。我从来没有分解过一个模型,因为他们知道它是什么,它能做什么。”

其他企业还没有形成这种共识。

“当我运行任何类型的测试时,我都试图避开假设测试这几个词,”Jasmine 说。“因为我认为人们不理解这一点,否则它最终会变得有点过于学术化,不适合那种环境。”

虽然许多公司自豪地声称他们正在投资数据和预测分析,但许多公司仍然专注于 Jasmine 所称的“描述性统计”。

描述性统计通常在组织中显示为关键绩效指标 (KPI),这是大多数组织在想到数据时想到的。大多数 KPI 对于一个行业来说是独特的,但是它们通常包括简单的计算,如平均值、总数、中间值等。

KPI 对企业来说很重要。它们是团结团队支持共同业务战略的好方法,但有一点是,创建新的 KPI 会降低业务的回报率。

预测分析提供了更高的精确度和洞察力,一旦业务达到 KPI 报告的最高效率,就可以改善业务。

数据科学家知道这一点。但是像 Jasmine 一样,他们不得不调整他们的语言来帮助利益相关者看到这种价值。

“我认为,任何一个数据科学家或数据分析师都很难向利益相关者传达他们进行的任何测试,”Jasmine 说。“我认为最重要的事情是不仅能够解释发生了什么,而且能够解释没有发生什么。”

数据科学家如何学会更好地解释这些东西?

一个答案可能是更好的数据叙事。

数据故事能帮助利益相关者看到预测模型的价值吗?

如果你密切关注数据科学,你可能听说过术语数据故事。如今,用数据讲故事已经成为一个时髦词汇。但是像大多数流行词一样,在表面之下隐藏着价值。

我与 Brent Dykes 进行了交谈,他是《有效的数据叙事:如何用数据、叙述和视觉效果推动变革》一书的作者,他向我解释了为什么数据科学专业人士经常忽视这一技能。

“我认为数据人员对他们的信息是否有说服力有些犹豫,我认为这是一个错误,”布伦特说。“你不可能完全客观,尤其是如果我们希望人们对数据采取行动。我认为我们需要引导观众走上一条特定的道路,并以特定的方式解读信息。”

一些数据科学家可能不喜欢这个建议。这听起来像是操纵,这当然是一个合理的担忧。人们用某种方式篡改数据,向公众提供虚假信息的例子并不少见。

但根据布伦特的说法,善于讲故事并不意味着操纵观众。

“在德国,”他说。“有一群人对吃巧克力的好处做了一些研究。他们进行了一系列测试,看看巧克力如何影响食用巧克力的人的健康,然后将他们的发现发表在欧洲一家著名的健康科学杂志上。

他指的是一项关于巧克力如何帮助你减肥的故意伪造的研究。这项研究发表在一份受人尊敬的杂志上,并被全世界受人尊敬的新闻媒体分享。

“这项研究真的是糟糕的科学,”布伦特说。“[研究人员]想展示人们是如何抓住这些研究得出的事实和数据的。这是一个表面上看起来像数据故事的例子,但它实际上不是数据故事,因为它没有建立在坚实的数据基础上。”

换句话说,如果一开始就没有好的分析,好的数据故事永远不会好。一个使用好的方法论,而不是把数据故事作为一个好故事的捷径的数据科学家,一点也不善于操纵。布伦特认为,两者都是必需的。

“显然,我们手头有他们最感兴趣的东西,”布伦特说。“我们没有试图以任何方式欺骗或操纵(利益相关者)。我们只是试图向他们展示他们需要注意的见解,以及这些见解的后果。否则,我们在干什么?”

尽管利益相关者习惯于从 KPI 的角度思考问题,但他们可能会欣赏来自预测分析的见解。我们只需要学会如何推销这些好处。

这有助于解释数据科学家 Jasmine 之前强调的问题。大多数数据科学家理解预测分析,但利益相关者似乎只想要描述性统计。

为什么?利益相关者在描述性统计中找到一个故事要比在预测性分析中容易得多。

声称“A 组比 B 组做得好 60%”的分析师比专注于讲述他们如何减少模型中的误报的数据科学家更能讲述故事。

正如布伦特告诉我的那样,“[一个好的]数据故事讲述者了解观众,他们了解数据,并且他们能够使用叙事结构以有效的方式进行交流。”

如果你注意到了,Brent 不仅仅建议专注于一个好的叙事结构——你也必须考虑观众。

数据科学家可能会问自己,他们的受众是否真的需要预测分析?也许描述性统计能告诉我们这个行业需要的所有数据。

严酷的事实可能是,观众并不需要我们试图讲述的故事。

Brent Dykes 在他的书中提供了关于数据叙事的伟大建议,你可以在亚马逊 这里 找到。我也在我的文章中提供了一些关于呈现分析的技巧 这里

员工是否应该随意晋升?

原文:https://towardsdatascience.com/should-employees-be-promoted-at-random-data-says-idk-maybe-bb327b6bd96a?source=collection_archive---------31-----------------------

实践教程

数据说:“IDK,也许?”

对一个组织的非常概略的描述。(图片由作者提供)

“在一个层级结构中,每个员工都倾向于提升到他的无能水平”

—劳伦斯·J·彼得博士

上面有争议的引文来自一本半讽刺性的书,作者是彼得博士和雷蒙德·赫尔,该书自发布以来引发了不少关于这个话题的研究。其背后的想法是,由于晋升通常是根据某人在当前职位上的表现来分配的,人们在层级组织中的排名会上升,直到他们达到相对不胜任的职位,并且不再被考虑晋升。

当某个角色的表现不能很好地预测更高角色的表现时,这种逆向选择效应可以直观地预期:一个优秀的程序员不一定是一个好的经理。或者,正如普特定律所说:

技术由两类人主导,一类人了解他们不管理的东西,另一类人管理他们不了解的东西

—阿奇博尔德推杆

我最初遇到彼得原理是因为我是搞笑诺贝尔奖的超级粉丝,2010 年,三名意大利人 Pluchino、Rapisarda 和 Garofalo 因在管理科学领域的计算研究而获得搞笑诺贝尔奖。我总是发现他们的结果非常发人深省,因为我想尝试使用 Mesa 库进行基于代理的模拟,所以我想不出比这更好的论文来尝试复制了!😃

Pluchino-Rapisarda-Garofalo 模型

我们现在来回顾一下“彼得原理回顾:计算研究”中介绍的模型。让我们考虑一个层级组织,职位分布在一定数量的固定大小的层级上;每个职位可以是空缺的,也可以由员工占据,员工的特征是两个数字:他们的年龄和代表他们在当前职位上能力的分数。为了明确起见,我们假设分数是从 1 到 10 的实数。

一个分层公司的示意图,其中有空缺职位和各种能力的员工。(图片由作者提供)

公司的整体效率被定义为每个员工的能力得分之和,由一个依赖于级别的“责任因素”加权,该因素说明了这样一种观点,即与发生在较低级别的不称职或未履行的角色相比,发生在最高级别的不称职或未履行的角色对整个公司更有害。如果每个员工的能力得分都是 10 分,那么效率就可以用公司得到的分数来标准化。

员工只能晋升到其当前职位的上一级(前提是其中有空缺职位),并且只能从最底层进入公司。当员工被提升到一个更高的级别时,我们将如何表现他们的能力?该模型的作者提出了两种可能的机制:

  • 常识假设:当一名员工被提升时,他们在新职位上的能力与他们在之前职位上的能力大致相同,只有一些小的随机变化(比如说,在-1 和 1 之间均匀分布)。
  • 彼得假设:当一名员工被提升时,他们在新职位上的能力与他们在之前职位上的能力完全无关。并非完全不现实,如果我们想象有人从一个需要高度技术技能的角色转换到一个更具管理性的角色。

此外,人们可以想象出大量的策略,通过这些策略我们可以选择一个员工提升到下一个级别;在最初的模型中,作者研究了其中的三个:

  • 最佳策略:对于任何空缺的职位,从下一级提拔最有能力的员工。这是最常识性的策略,也是“理论上”人们在现实世界中使用的策略。
  • 最差的策略:不要从下面的级别中挑选最好的候选人,而是挑选最差的。直觉上… WTF?
  • 随机策略:每当有空缺职位时,写下所有可以升职的员工的名字来填补,放入一个鱼缸,随机抽取一个名字:那个家伙升职了!很想知道是否有人在现实世界中使用它。

最后,员工只有在达到退休年龄或能力得分低于某个阈值时才会离开公司。

记住这些规则,让我们实现一个基于代理的模拟,看看一个在开始时具有随机初始年龄和员工能力的公司如何随着时间的推移而演变。如果您对实现的细节不感兴趣,可以随意跳到原始结果部分的讨论。

用 Python 实现 PRG 模型

由于这是一个非常简单的基于代理的模拟,我认为其实现的自然选择是 Mesa 库,因为它允许我们不为我们的模拟编写大量样板代码,同时对于一些更复杂的库(例如 SimPy )来说更容易使用。这一部分的目标只是勾画出这样一个模拟的实现是什么样子的;要了解更多细节,请随意查看这篇文章的完整回购台面文档

我们可以从编写一个相当无趣的Employee类开始,如下所示:

Employee.step()方法描述了代理在模拟的每个时间步做什么;在这个模型中,很简单:他们只是变老,接近退休年龄。

描述公司动态的模型稍微复杂一些;在这里,我只报告对这个模型最重要的方法:

如您所见,我们上面描述的提升员工和重新计算能力的策略本质上是一行程序。

梅萨模型有一个非常有用的属性,data_collector,它可以在我们的模拟过程中跟踪我们想要的任何可观察的东西,并给我们一个方便的pandas.DataFrame。我们可以利用这一点,通过以下方式模拟公司的动态:

也就是说,我们只需要反复调用model.step()方法,所有剩下的工作或多或少都是自动完成的。对于运行批量模拟,也可以使用 Mesa 的 BatchRunner 类

事不宜迟,让我们看看我的 Pluchino-Rapisarda-Garofalo 模型实现的输出。

对原始结果的讨论

通过模拟一批公司在一段时间内的效率,在常识假设或彼得假设的假设下,并假设他们总是提拔最好的、最差的随机的员工,我们得到以下图表:

促销策略和能力转移机制不同组合的平均效率随时间的演变。再现原始论文图 2 所示的结果。(图片作者提供)

这里,每条线显示 50 次模拟运行的平均值。这些公司都是一样的:最初有 160 名员工,分布在 1、5、11、21、41 和 81 这 6 个级别。每个级别对公司绩效的权重分别为 1、0.9、0.8、0.6、0.4 和 0.2。每个员工的年龄从以 25 岁为中心的正态分布中随机初始化,标准偏差为 5 年,截断为 18 至 60 岁,而能力得分从以 7 岁为中心的正态分布中随机抽样,标准偏差为 2,截断为 1 至 10。退休年龄定为 65 岁。

可以想象,当常识假设成立时,即当员工在新职位上的能力与他们在旧职位上的能力非常相似时,在我们上面介绍的策略中,更好的策略是通过提升最好的员工来填补空缺,而总是提升平均最差的员工会导致效率下降,随机提升介于这两种策略之间。

根据彼得的假设,这些趋势完全相反:总是提升最优秀的员工会导致效率的下降。直观地说,我们可以这样解释这种现象:通过提升最优秀的员工来填补一个职位,我们正在摆脱一个级别中表现最好的员工;同时,由于新的能力得分完全是随机的,员工在新职位上的能力(将产生更大的影响)很可能会大大降低。我们正在处理一个教科书上的逆向选择案例!通过提升一个级别中表现最差的员工,我们都用另一个可能具有更高能力的员工来代替他们,并且我们也有机会在新的级别(也可能比以前更高)上为他们的技能重新掷骰子。

现在一个问题应该是很自然的:在一个真实的组织中,对于一个给定的晋升,哪种能力转移机制在起作用?在常识假设和彼得假设的可能性相等的情况下,Pluchino、Rapisarda 和 Garofalo 在他们的论文中表明,相对有效的策略是随机提拔空缺职位的最佳或最差候选人!

模型的扩展

我们的结果中另一个值得注意的奇怪现象是,这种动态与人们的预期大相径庭:在大约 25 年的时间里没有发生什么变化,然后在几十年的时间里,我们达到了平衡。这与这样一个事实有关,即职位最初是完全填满的,因为对于所选的年龄分布,99.85%的员工在模拟开始时不到 40 岁,所以我们需要等待几十年才能看到有人退休。

通过假设在开始时一些位置是空的,可以容易地修复这种假象;这可以通过强加最初在每个级别的代理数量不是由级别大小给出的,而是由二项式分布给出的(在我的实现中,参见这条线),使得总是有一个位置空缺的随机机会。我决定对每个等级使用相同的空缺概率,但是决定每个等级至少有一个人(见这里)。为了明确起见,我们取 0.2 作为每个位置最初空缺的概率。

另外,我引入了一些随机机会,人们在退休前的任何给定时间离开公司(也许他们从一家不提供晋升抽奖的公司得到了更好的提议:-P)。让我们给每个员工每个月分配 4%的机会离开公司,这样平均每个员工在离开他们的角色之前会呆两年左右。

由于我最感兴趣的企业类型是早期初创企业,我也决定考虑相对于原始论文来说层次较少、规模较小的公司。因此,让我们考虑一个公司,有一个首席执行官,一个仅在她下面的五个人的董事会,十个某种类型的“经理”,以及他们下面的三十个人。我非常随意地将每个级别的权重因子设置为 1.0、0.8、0.5 和 0.2。

最后,让我们使用一个月而不是一年的模拟步骤,并为 256 家公司的每一组促销策略和能力转移机制运行这个新的模拟。结果如下所示:

“扩展”模型中促销策略和能力转移机制的不同组合的平均效率随时间的演变。(图片由作者提供)

我们可以看到,现在的动态更加渐进,发生在更有意义的时间尺度上(几年而不是几十年/几个世纪)。除此之外,与最初的模型相比,似乎没有什么太大的变化;在这种情况下,战略之间的差距似乎较小,但我认为这是由于我使用的不同公司结构,而不是模型中的任何差异。主要观点仍然存在:与常识相反,根据彼得假说,提升最优秀的员工会导致效率下降。

留给读者作为练习的问题

我上面提出的对原始模型的修改只是一些小的修正,如果我们放松一些假设,看看结果会如何变化会很有趣。例如,我对前进道路的建议是:

  1. 员工只能进入层级的最底层;在模型中包括一个公司从公司外部雇佣有经验的人的可能性怎么样?
  2. 根据彼得假设,能力得分分布对所有级别都是一样的。根据级别来区分有意义吗?
  3. 员工在这个模型中是非常一维的(他们对公司的作用只用一个数字来表征)。我们能不能让它们不像真实的人类那样复杂,至少稍微有趣一点?
  4. 还有其他有趣的能力转移机制可以考虑吗?例如,一些新晋升的个人可能不如他们的同事有效,但他们可以由同一级别的(一些)人指导,所以我们至少有一些回归到平均水平。
  5. 在这里,我只研究了平均数量;发行版呢?与每个场景相关的风险是否具有可比性?
  6. 我们能否通过给每个代理人提供“性别”、“种族”或类似的属性来模拟歧视的影响?

结论

依我拙见,目前为止我们所看到的模型中有多少是真正模拟一个公司的,仍然是非常值得怀疑的。例如,一家公司在决定雇佣或提升某人时,能力是唯一(甚至是最重要的)考虑因素,这是极不可能的;通常证明这种决策合理的看似客观的指标通常只是偏见和歧视的一个表象。通常,度量越多,透明度越低。矛盾的是,我们能通过随机雇用和提升员工来改善工作场所的歧视问题吗?当然,我不是说这可能是最好的解决方案,但它会改善目前的现状吗?

我认为我们仍然很少了解什么是真正激励人们的,以及等级制度是如何运作的;尽管如此,基于代理的方法通常可以成为进一步研究的好灵感。此外,它们相对容易编码(特别是通过为它们使用一些专用库),因为人们只需要提供管理代理行为的简单规则。我可以全心全意地推荐 Mesa 入门教程,其中他们实现了另一个有趣的模型(玻尔兹曼财富模型),以获得更多关于这个主题的信息。

如果你做到了这一步,感谢你的阅读!

我应该参加数据科学训练营吗?

原文:https://towardsdatascience.com/should-i-attend-a-data-science-bootcamp-b96dd9310d21?source=collection_archive---------20-----------------------

格伦·卡斯滕斯-彼得斯在 Unsplash 上拍摄的照片

三个问题帮助你决定是否要迈出这一步

去训练营是一个重大的决定。较高质量的课程通常是全日制的,需要大量的资金投入(包括直接成本和放弃的工资)。

因此,在你采取行动之前,有三个问题你应该有明确的答案:

1.我有足够的资金储备和纪律来应对 7 个月的失业吗?

除了通常持续 3 个月的训练营之外,你还应该为之后 3 到 4 个月的求职做好计划。少数幸运者将在训练营结束时或之后立即找到工作。但他们是例外,而不是规律——更典型的是,你会在训练营结束后花至少几个月的时间寻找那份难以捉摸的工作。

在此期间,你将不再有训练营的日常结构和时间表。如果你不是一个积极主动的人(天生的乐观主义者),这段时间会因为不确定性和拒绝而极度疲惫。此外,如果你没有准备足够大的财务缓冲,那么在已经紧张的时候,这是第二层压力。

我不是说你不应该去。我非常享受作为 METIS 训练营的一员的经历,我喜欢在训练营之后得到的工作。但是转行可不是闹着玩的,你要做好努力工作和经历一些逆境的准备。

2.我有数据分析师的头衔可以吗?

让我先说一下数据分析师是伟大的。他们收入丰厚,从事有趣的工作,并为雇佣他们的企业贡献了很多价值。但是我从 Metis 训练营的其他参与者那里听到的一个共同的事情是,“我去数据科学训练营不是为了成为一名数据分析师。”

但事实是,很大一部分 bootcamp 毕业生成为了数据分析师。没有足够的数据科学家职位来满足不断增长的新数据毕业生的需求。最重要的是,一些公司意识到,雇佣 1.5 名(甚至 2 名)数据分析师可能比雇佣一名更昂贵的数据科学家更好。

数据科学家和分析师之间也有大量技能和职责重叠。A 公司称之为数据科学家,B 公司可能称之为数据(或产品)分析师。重叠之处在于您可能期望的东西,如对 SQL 的掌握、数据可视化技能、向非技术受众清楚地传达定量见解的能力,以及 Python(或 R)建模和统计的基础知识。角色可能有所不同的地方有:

  • 所需的 Python/R 知识的数量和深度。以及你花在编码上的时间和与利益相关者见面的时间。
  • 无论您是更多地致力于对数据进行切片以获得洞察力,还是试图对不确定的结果进行建模和预测。
  • 你的工作是更紧密地配合每周的业务需求,还是更专注于长期项目和研究。

我建议不要太在意标题。相反,如果公司和角色听起来很有趣,那就去做吧。当然,如果你执意将最先进的深度学习技术应用于宇宙的奥秘,那么你应该坚持担任数据科学家(或机器学习工程师)的角色。但是如果是这样的话,你可能会更适合去读研而不是去训练营。

3.你尊重模型建立的过程吗?

数据科学不像其他软件开发工作。你可以花很多时间整理数据集,清理数据集,建立模型,却发现它预测很差或者解释很少。

不能保证你花在建设上的时间会产生有价值的东西。当它不匹配时,将会有通过过度拟合或在测试集上训练模型(或两者)来欺骗系统的诱惑。作为一个有抱负的数据人,你需要能够抵制这些诱惑。

过度拟合可能会让你的模型在你的同行眼中看起来更好,但它也会严重阻碍你的模型在真实样本数据上表现良好的能力。这个问题不仅适用于是否去训练营,也适用于是否在数据科学时期从事职业生涯。

只有当你接受工作中不稳定和非线性的进展,并愿意对建模过程保持真实和诚实时,才这样做,这意味着尽可能诚实地对你的预测模型进行回溯测试,而不是使用你的测试数据做出建模决策,并报告你的结果,不管它们是否是世界上最好的。

更多数据科学相关帖子由我:

数据科学家是做什么的?

数据科学家挣多少钱?

拿到了数据科学的工作?

技能提升的更好方法

让数据科学面试变得更好

该不该买彩票?

原文:https://towardsdatascience.com/should-i-buy-a-lottery-ticket-6d3fece5a6bd?source=collection_archive---------23-----------------------

彩票分析

我分析了过去的彩票数据,利用统计学和概率来决定购买彩票。

迪伦·诺尔特在 Unsplash 上的照片

我经常发现自己在决定是否购买彩票,尤其是新年前夕的强力球抽奖。我在那些时刻感到犹豫的原因是我对所选数字的随机性缺乏信任。当你搜索彩票结果的操纵时,有许多资源解释这个系统是如何被欺骗和操纵的。你也可以遇到彩票前雇员如何操纵结果的过去事件。

看到关于过去彩票结果被操纵和造假的新闻,我对彩票结果的信任变得更加不适。有了数据科学的经验和背景,今年我决定用统计学来证明我和其他人一样有平等的机会赢得彩票。在这篇文章中,我将讲述我如何利用统计数据来分析彩票结果,并做出购买/不购买彩票的决定。

彩票机制

我要分析的彩票名为“Sayı sal Lotto”,是土耳其国家彩票的一种。游戏内部工作如下:从范围[1,49]中抽取 6 个数字,奖金按递减顺序分配给猜中 6,5,4,3 的人。在不涉及太多细节的情况下,让我们深入数学,从统计学的角度来分析这场比赛。

决定购买彩票

从这一节开始,我将解释我使用的方法并分享代码片段。然而,为了让你更好地理解所使用的方法,我将定义和使用一些术语,如随机变量和概率。各部分的概要如下:

  1. 什么是随机变量?在这里,我解释什么是随机变量和不同类型的随机变量使用。我还给出了统计学中事件的定义。
  2. 中乐透的概率。在这一步中,我计算了赢得乐透不同事件的各种概率。
  3. 概率的分布。随机变量相对于不同值变化的概率。我感兴趣的是找出在抽奖中答对一个特定数字的概率分布。
  4. 运行 chi2 拟合优度测试。该测试可用于比较理论分布与观察分布的吻合程度。我收集了彩票样本中每个号码的频率统计数据。我将使用 chi2 检验将每个数字的预期数字频率与这些统计数据进行比较。

第一步:什么是随机变量?

随机变量是其分布函数为实验的不同结果赋值的变量。随机变量通常用字母来表示。它们分为离散型和连续型,离散型具有有限或无限范围内的特定值,连续型可以取实数线上某个区间内的任何值。在抽奖的情况下,从 49 个数字中抽取一个数字只能是[1,49]范围内的整数。因此,我在彩票环境中处理一个离散的随机变量。

另一方面,一个事件是一个结果,它有一个概率值。我相信你可以在网上找到更正式的定义。但是为了我们的目的,让我们多谈谈数学。

第二步:中彩票的概率

一个事件的概率告诉你在所有可能的后果下,这个事件发生的可能性有多大。例如,“A 队有 1/3 的机会获胜”意味着考虑到所有可能的结果,A 队获胜的概率是 1 / 3 = 0.33 。如果事件的概率接近于 1,则很可能发生随机事件。

在彩票中,中奖概率等于中奖号码占所有可能彩票号码总数的分数。换句话说,你试图从一包 49 个数字中找出所有 6 个数字的组合。

为了找到中奖的概率,我需要算出所有可能的彩票结果。这是我使用密码的地方。我从一组 n 个物品中挑选 r 个物品,不管挑选的顺序如何,其中 r 是 6,n 是 49。那么彩票中奖的概率就变成了1/13983816。

你可能会说“好吧,那已经是不玩的理由了,因为赢的几率很低”。但是,请记住,我是在可能的操纵后得出的数字。所以我不打算谈论玩游戏是否理性。如果我要计算从 49 个数字中得到 2(不是任意 2 个随机数,而是实际的数字 2)的概率,那么我会将所有可能的 6 个位置中的 1 个位置设置为 2,并对其余的 5 个位置进行相同的计算,≊ 0.12

第三步:概率分布

我现在有可能得到一个数字(一个特定的数字,比如 2,3,30 等等。)中了彩票。概率的分布如下:

分析了最近的 1000 张彩票后,我得到了每张彩票的总号码频率,也就是说,我知道 2 在最近的 1000 张彩票中是否出现了 150 次。这是观察到的所画数字的数字频率分布。

为了找到特定号码在最近 1000 次彩票中出现频率的期望值(样本量=1000),我将范围 [0,1000] 中的每个 k 乘以在彩票中挑选该号码的相应概率(如果 k 为 100,则该特定号码在 1000 次彩票中出现 100 次)。公式是 E(x) = xP(x)。*

expectedValue = 0
for every k in [0,1000]:
  expectedValue+=k*P(k)where P(k)=(0.12**k)*(0.88**(i-k))*C(i,k)
C(i,k)=i choose k
i=1000

我最终得到了 122,作为一个样本为 1000 的特定数字的数字频率的期望值。

步骤 4:运行 chi2 拟合优度测试

卡方拟合优度检验用于确定样本数据分布是否与预期分布一致。我建立了卡方拟合优度检验的假设,随后计算了各自自由度的卡方统计量:

A.零假设:观察值和期望值之间没有显著差异。

B.替代假设:观察值与期望值之间存在显著差异。

运行上面的代码片段后,我得到了 35.596 的 chi2 统计值。检查了 chi2 表中的 p 值后,我得出结论,观察值和期望值之间没有显著差异。因此,我可以向自己保证,数据没有被操纵,可以购买彩票。

结束语

在这篇文章中,我分享了我是如何统计分析过去的彩票数据来决定购买彩票的。虽然我在统计上没有发现任何操纵行为,但我并不宣称这就是最终结论。您可以使用不同的方法分析相同的数据,并得出不同的结果。如果您也想尝试一下,非结构化代码(链接)可能会有所帮助。

如果你对帖子有任何疑问,或者对数据科学有任何疑问,你可以在Linkedin上找到我。

享受阅读,祝你新年快乐!

我应该去吃早午餐吗?一个交互式的新冠肺炎曲线展平工具

原文:https://towardsdatascience.com/should-i-go-to-brunch-an-interactive-tool-for-covid-19-curve-flattening-6ab6a914af0?source=collection_archive---------5-----------------------

一个帮助你了解你的行为如何影响冠状病毒在你的社区传播的工具

萨尔曼·默罕默德克劳德·雷奥帕特里克·斯蒂维斯

2010 年 3 月 19 日更新:感谢大量精彩的反馈,我们现在已经发布了该工具的 V2,它带来了贵国每天的历史病例数据,更好的图表,以及按年龄分列的预测死亡率!现在还在https://corona-calculator.herokuapp.com✌️

最近的发展说服了许多人,我们确实应该非常认真地对待冠状病毒。像这种的帖子强调了隔离作为一种控制冠状病毒传播的策略有多么重要。你可能见过受感染人数的可怕曲线:

来源

辅以“拉平曲线”的理念,以限制医疗保健系统的负荷:

来源

我能对这些曲线产生什么影响?

人们(包括我们)发现很难对疾病的可能发展进行推理,因为有许多不熟悉的概念(如指数增长)和潜在的重要变量(如人们多快得到诊断以及疾病在多长时间内保持传播)。

所有这些都让非专业人士很难思考他们应该如何改变自己的行为,以及这可能会给我们关心的事情带来什么样的影响:死亡、破坏。

因此,我们开发了一种工具来帮助我们了解这种疾病是如何根据感染者的社会接触次数而发展的。它被称为 Corona Calculator,旨在帮助你了解限制你的社交活动会如何影响冠状病毒的传播以及你所居住的医疗保健系统的负荷。

https://corona-calculator.herokuapp.com 找到它

https://github.com/archydeberker/corona-calculator为代码做贡献

在我们的公众观点页面阅读我们的方法和数据来源。

发现错误或想要请求功能?通过谷歌表格告诉我们。

为什么现在要建这个?

3 月 13 日星期五,我们的办公室关门了,我们开始远程工作。当时,加拿大有 24 名感染者,850 人正在接受调查。当我们开始讨论我们新的远程生活仪式和组织时,很明显不是每个人都对“隔离”有相同的理解。在咖啡店里重新组合成小团队可以吗?我们星期六还应该去参加那个聚会吗?我们的团体保龄球比赛怎么样?

我们开始查看这些数字,并计算出我们可以建造什么。已经有一些惊人的应用程序可以用来跟踪疾病的发展,从约翰霍普金大学到足够多的传播动力学背景让我们相当担心。与我们的家人和朋友讨论英国的“群体免疫”策略时强调,人们在考虑合理的公共卫生应对措施时,使用了非常不同的心理模型。

我们的专长是人工智能和创建使用直观的复杂系统。我们不是公共卫生专业人员,尽管我们中的一些人以前研究过传染病的数学模型。我们开始创造一种工具来帮助个人理解他们的选择可能产生的影响。

如何使用该工具

你所在的地区有多少病例?

从设置您的位置开始。我们每小时都会检查来自约翰·霍普金斯医院的数字,并使用这些数字为您提供贵国当前确诊病例的数量:

遏制冠状病毒的一个棘手问题是,我们知道我们并不真正知道任何时候有多少病例。我们使用日本论文中的数字来估计任何时候的真实病例数大约是确诊病例数的 10 倍。然而,这高度依赖于测试策略;在全球范围内,测试的普及程度存在巨大差异。

我的行为如何影响传播?

作为一个个体,你能控制的主要事情是你选择自我隔离的程度。这反映在应用程序中的感染者每天与之互动的人数。

这是一个非常重要的数字,因为它决定了疾病传播的速度:在流行病学中被称为基本繁殖率。记住,冠状病毒在几天内不会出现症状,所以很难知道你是否已经被感染。

用格雷汉姆·梅德利教授的话说,我们最好的选择是“想象你确实感染了病毒”..改变你的行为,这样你就不会传播了”。

TK:https://Twitter . com/BeardedGenius/status/1238475687830355970

你会发现,改变这一点会对感染人数和冠状病毒导致的死亡人数产生巨大影响:

我们所有的图表都是交互式的(谢谢, Plotly ),所以你可以放大来看发生了什么:

你可以在我们的概念页面中找到我们如何模拟疾病传播以及如何计算死亡率的细节。

为什么感染率很重要?

在感染冠状病毒后,有些人需要住院治疗,症状从呼吸窘迫到器官衰竭不等(我们根据本文计算约为 15%)。

这意味着很多人将需要医院护理,这将是一个问题。问题的严重程度取决于任何时候有多少人生病:

同样,你可以玩左边的滑块,放大来了解一个感染者与多少人互动是医疗系统负荷的一个关键决定因素。

对我们来说,这是冠状病毒疫情最可怕的部分:它将给我们的医疗保健系统带来潜在的巨大压力,可能导致死亡率相应增加——以及它给医疗保健专业人员带来的痛苦选择。

请注意,我们没有关于死亡率将如何随着医疗系统变得不堪重负而变化的良好数据,因此我们今天不能将其纳入我们的模型。似乎可以有把握地说,从(最终)得到良好控制的武汉疫情估算的死亡率,低估了处于崩溃边缘的医疗体系的死亡率。

你能确定这是对的吗?

不要!

我们可能会在几个方面出错:

  1. 我们使用的模型可能过于简单。

然而,它已经存在了很长一段时间,并得到了很好的尊重,所以我们认为这不太可能是一个大的误差源。

2.我们使用的数字可能不准确。

关于冠状病毒及其动态的关键数据,现在有很多不确定性。我们非常依赖来自约翰霍普金斯大学和迈达斯网络的数据,但是现在有很多我们不知道的,而且来自不同国家的数据可能完全不同!这可能是一个很大的误差来源。

3。我们可能把事情搞砸了

我们是技术专家,而不是流行病学家,我们匆忙地完成了这项工作(关于冠状病毒的一切都发生得很快……)。我们希望得到一些关于我们在周末编写的代码的反馈

如果你觉得这个有趣或有用,请让我们知道的概念或在评论中,并在你的网络中分享!

感谢Satsuko VanAntwerpStephanie Willis对本文的编辑

我应该在我的机器学习模型中包含截距吗?

原文:https://towardsdatascience.com/should-i-inlcude-the-intercept-in-my-machine-learning-model-2efa2a3eb58b?source=collection_archive---------12-----------------------

作者拍摄的图片

并简要介绍了数据科学中的回归建模

“回归建模和变量之间的线性关系”…这是我在数据科学和机器学习领域的第一堂课的名字。之前我们上过一些关于 GitHub 和 Python 的课程,但直到那天,班里的每个人都感觉到那种独特的大开眼界的感觉,终于理解了我们在大学时看到的一些概念的实际应用。在我的情况下,任何与数学和统计相关的东西都是我大约 10 年前最后一次访问的东西,所以我想可能是因为这个原因,我发现很难处理我们看到的一些东西。然而,在那次会议几个月后,在与我的一个妹妹交谈时,她完成了第一年的经济学课程,她惊讶地发现,她正在学习的所有抽象概念实际上都在现实生活中有实际应用。

我们在大学是如何被教导的,我们可能会失去更好地学习这些基本概念的机会,这在这个故事中简直太多了,但有一点是肯定的:没有接受理想的形式(或至少接受“旧学校”类型的形式,几乎没有概念的实际应用),加上在大学毕业多年后进入数据科学,这让我好几次甚至想不通最简单的概念,以理解一切。

如果你觉得与此相关,今天我们将深入研究一个非常基本但关键的概念,当我们开始使用 Sklearn 库时,时间有时会被误解或被遗忘,一切都很简单,只需写下 linreg.fit(X,y)。

顺便说一下,如果你真的想致力于整个机器学习和数据科学的东西,一个很好的建议是:刷新那些尘封的数学知识。这可能是你花时间思考未来的最佳方式。我知道,在数据科学的世界里有很多东西要学,但是你知道吗?技术和语言可能来来去去,但是这个领域的数学背景将会一直存在。我自己,我正在遵循一个为期一年的自我实现的道路。将来我可能会写一个或几个关于我学习经历的故事,所以请继续关注!

回归基础

从今天的主题开始,让我们暂时回到基础知识,重新审视机器学习中回归建模背后的概念。

在线性回归中,我们希望从预测变量 X 预测连续的结果变量 Y,并且我们假设这两个变量之间存在线性关系。通常,除了这种关系,我们假设还有一个额外的转变:

y = B0 + B1*x

这里,B1 的值给出了直线的斜率,增加的常数 B0 给出了称为截距的额外偏移。当 B0 等于零时,最后一个元素表示目标变量(也称为“因变量”、响应变量、结果变量以及许多其他名称)的值。

让我们来看一个实际的例子。假设做一道我的名菜,我花了整整 10 分钟把所有东西都放好,然后再花 5 分钟为每个用餐者切好食材,再加上 10 分钟在烤箱上烹饪这道菜。在这种情况下,斜率是 5,截距是 20 --从 10 分钟的固定设置和 10 分钟的烹饪中得出。

因此,我们的等式可以转化为:

  • Y = 5X + 20

因此,如果我今晚在家接待 4 个人吃饭,这就是我为所有客人和我做的名菜:

  • Y = 5*5 + 20 = 45 分钟

由于 B1 等于每位用餐者精细切菜的分钟数,我们的等式中可以有更多的项,例如,B2 可能是每位用餐者额外的购物分钟数,B3 可能是每位客人额外的烹饪分钟数,等等,以类似这样的形式结束:

Y = B1x + B2x + B3x + … + Bnx + B0

而 sklearn 是如何找到可能的最佳方程的呢?

嗯,都是优化/最小化问题。最小二乘法是回归分析中的一种标准方法,其目标是最小化每个方程结果的残差平方和。

其中:

  • 易才是真正的价值
  • yi 是预测值
  • N 是数据集/样本中的元素总数

为什么我们使用平方值而不仅仅是绝对值?只是为了增加对预测值和实际值之间较大差异的惩罚。

以我们之前的例子为例,暂时忘记我们知道初始方程的解,其中我们只有 B1,即每位用餐者精细切碎食材的分钟数。现在假设我们不知道 B1 的值,但我们知道为以下数量的客人烹饪整道菜需要多少钱:

游客数量= x = [1,3,5,10,15,20]

总分钟数= y = [25,35,45,70,95,120]

如果我们试图用等于 20 的截距和等于 3 的 B0 解这个方程,我们将得到烹饪分钟总数的下列值:[25,35,45,70,95,120]。继续上面的等式,我们将得到 506.67 的 MSE。同样,保持相同的截距,但 B0 等于 6,我们将得到[26,38,50,80,110,140]和 126.67 的 MSE。因此,对于我们的 B0 系数,6 比 3 更合适。如果我们继续尝试这些值,直到找到最准确的值,我们将会做一些与 Sklearn 实际做的非常相似的事情。只是 Sklearn 对此使用了一种叫做梯度下降的东西。如果你想了解更多这方面的内容,我向你推荐来自 Sagar Mainkar 的这个故事。

在我们进一步深入了解截距之前,值得一提的是,除了 MSE,我们还可以找到其他评估指标,如平均绝对误差或平均对数误差。前者对数据集中的所有值进行相同的惩罚,而后者对更高的值进行更大的惩罚。如果需要,我们甚至可以创建自己的误差函数,遵循类似的逻辑或者其他更适合我们业务模型的逻辑。

那拦截是怎么回事?

如前所述,截距是我们的目标变量的值,当我们所有的特征为零,我们的函数穿过 y 轴。在 Sklearn 中,我们可以通过使用任何线性模型的超参数,轻松地将截距包含或不包含在方程中。有时,当我们去掉截距时,我们的模型会变得更好,这几乎是奇迹。然而,记住这仅仅意味着我们强迫直线穿过原点。也就是说:当我们方程中的所有系数都等于零时,也就是说,我们所有的特征都等于零,那么我们的目标变量也将是零。这有意义吗?这取决于你的商业案例。

举以下例子:

  • 假设我们根据浴室、卧室的数量、房龄以及是否有游泳池、阳台、花园和暖气等其他功能来预测一所房子的房间数量。如果所有这些都等于零,意味着该物业是一个新的建筑,没有卧室,没有浴室,没有列出的其他功能,这是否意味着该物业根本没有房间?也许是的。
  • 然而,另一方面,如果我们使用与以前相同的特征来预测房价,会不会是房产价值等于零?可能不会。我们会发现 X 永远不会为零的情况,因此,截距没有特别的意义。当这种情况发生时,我们可以简单地放弃截距,因为它不会告诉我们任何关于 X 和 y 之间的关系。

当我们强制截距为零时,预测器的系数变得更强更大,这有时会被错误地解释为更重要。然而,在这种情况下,系数会变得更强,只是因为斜率会更陡,以便通过原点。不是因为我们有更强或更好的系数。也就是说,我们会人为地在我们的系数中强加那个重要性。

来源:pexels 的免费图片

这很棒,对吧?我们现在有一个非常简单直接的方法,来确定我们是否需要加权这个叫做截距的小东西,对吗?嗯,没那么快。有时候会有点棘手。当所有预测因子(B1,B2,B3 等。)是数字的和无中心的,它可以像前面提到的那样简单。由于截距是所有预测值都等于零时 Y 的值,因此只有当模型中的每个 X 实际上都有一些零值时,该值才有用。因此,如果我们只有一个特征,例如,某人的身高,我们不应该有任何接近于零的值,那么我们可以安全地放弃截距。然而,当我们拥有被虚拟化的分类变量或以均值为中心的特征时,会发生什么呢?

正如你可能知道的,当我们重新调整我们的预测变量时,我们把它们都集中在它们自己的平均值上。意味着所有的 X 都等于零。因此,在这种情况下放弃截距可能不是最明智的想法,因为它是所有预测变量的平均值 Y,因此有意义。

当我们有虚拟的分类特征时,截距的作用是一个完全不同的故事。虚拟变量将只取值 1 和 0,表示数据集的每个元素是否都观察到了这些特征。例如,如果我们的数据集中只有两个特征,第一个表明目标是不是狗,第二个告诉我们是不是猫,两个特征都等于零将告诉我们一些事情:Y 既不是猫也不是狗。您可以很容易地看到这个截距是如何变得有意义的。当我们处理已经集中的分类变量和数字特征的组合时,截距变得越来越重要,可能不应该被丢弃。

总而言之,更好的办法是对我们的商业案例现实一点,而不是仅仅因为我们得到了更大的系数或更好的 R2 就强迫截距为零。当这种情况发生时,通常我们会强迫我们的模型在方程中加入更多的变量,只是为了解释无法解释的原因,因此,可能会过度拟合我们的模型。

好了,今天就到这里。请继续关注未来的故事,了解处理分类特征的其他技术。同时,我邀请你看看我最近的两个故事:

此外,请随时访问我在 Medium 上的简介,查看我的其他故事:)回头见!感谢您的阅读!

来源:

作为数据科学家,我应该学习围棋吗?

原文:https://towardsdatascience.com/should-i-learn-go-as-a-data-scientist-8e5cdff1da28?source=collection_archive---------56-----------------------

乔恩·泰森号航天飞机上的照片

关于 Go 在数据科学领域表现如何的调查和自我解释

Python 是数据科学的强大工具。它可以涵盖从探索性数据科学到模型生产的一切。最重要的是,语法使它可以自我解释并且容易理解。

我已经使用 Python 年了,在我的数据科学之旅中,它是最常用的语言。然而,每个对 Python 有足够经验的人都知道,Python 以其速度而臭名昭著。

因此,我打算转向“去”。Go 以其并发性和可靠性而闻名。就速度而言,它无疑优于 Python。但当我打算将其用作数据科学项目的工具时,要问的核心问题是:

Go 是不是比 Python 更适合数据科学项目的工具?

为了回答这个问题,我决定做一些调查,并试图找到一些结论。

在网上搜索后,我发现了一些分为两个阶段的信息和观点:数据操作的编码经验社区资源。鉴于我希望在数据科学项目中使用 Go 代替 Python,数据操作的编码经验之间的比较是一个关键(因为我们知道 Python 确实提供了友好的代码阅读经验)。此外,Python 以其巨大的社区和资源支持而闻名。所以社区资源的规模很重要。

编码体验

我看了两篇展示编码风格的文章: 去找数据科学?达里奥·拉德契所著《从蟒蛇到蛇》桑吉·古普塔所作《 》,两部著作都是关于走向数据科学的。

他们都在文章中分享 Go 代码片段。Dario 演示了如何读取 CSV 文件创建数据帧使用 Go 过滤数据。Sanket 在解析 JSON 文件时演示了 Go 和 Python 之间的区别。此外,Sanket 指出了 Go 如何使静态类型的调试更容易,而 Python 有时会导致动态数据类型的痛苦错误。

对我来说,在读取 CSV 文件和处理数据帧时,这两种语言之间的差异并不大,尽管 Go 需要更多的步骤来执行过滤操作,而 Python 可以在一行中完成。然而,在处理 JSON 文件时,这种差异给我留下了惊人的印象。我就借用桑基的作品来展示一下。如果你对细节感兴趣,请到 Sanket 的帖子上阅读他的完整分析。

示例 JSON 内容

要解析的 Python 代码

转到要解析的代码

我的看法看了那些代码对比,Go 不是数据科学专用的语言。就代码易读性而言,Python 仍然比 Go 有优势。

社区资源

数据科学 101 的 Ryan Swanstrom 的《GoLang for Data Science》是一部讨论 Go 社区资源规模的好书。在文章中,Ryan 收集了关于 Go 社区的信息,从搜索 Go 的流行度数据科学的 Go 项目数量关于 Go 的数据科学书籍,到来自社区的想法

我发现参考社区的想法真的很有用。在 Ryan 的文章中,他收集了来自 RedditO'Reilly BlogStackoverflow、对数据科学的讨论。社区的普遍意见是,Go 并不专门针对数据科学,因此不会成为数据科学项目的首选。但是 Go 肯定对数据科学部署有帮助,鉴于 Go 比 Python 快得多。

结论

在我看来,Go 在某种程度上仍然是一个有用的工具。在进行数据科学项目时,如果您已经完成了数据探索和数据操作,并且您确定要使用什么作为最终模型,那么在使用 Go 训练模型和部署最终模型时,您将受益于 Go 的速度。但是,如果你还在学习数据科学,你可以把所有的精力放在 Python 上,专注于如何通过 Python 使用数据科学来提供真正的价值。毕竟用数据科学解决问题才是真正的价值,而不是你的过程有多快。

总的来说,我很喜欢迦的一句话,这句话很好地概括了 Python 和 Go 在数据科学项目中的性格:

Python 支持机器学习,基础设施支持

反正只是我看了那些资料后的看法。任何意见都非常欢迎。

该不该学朱莉娅?

原文:https://towardsdatascience.com/should-i-learn-julia-986696ca031d?source=collection_archive---------22-----------------------

意见

Python 和 MATLAB 的高性能 lovechild 到底好不好?

pixabay 上的 Free-photo 拍摄

朱莉娅是目前最新的“it”语言,所以我想我应该试一试。问题是,它值得加入数据科学家的武器库吗?

装置

关于 Julia,首先要知道的是它很容易下载和使用(无论如何,在 Mac 上,祝 Windows 用户好运)。安装内核让它在 Jupyter 笔记本上运行也是轻而易举的事情。

句法

Julia 不像 Python 那样是面向对象的语言,所以要写作,我们需要放弃一些(但不是全部)整洁的“Python 式”做事方式。

在 Julia 中没有类,所以我们必须像处理 MATLAB 一样处理结构。同样,像 MATLAB 一样,Julia 采用了语言中内置的优秀的线性代数语法。这取代了对像 NumPy 这样的模块的需要,有利于更直观的语法,如用于乘法、复共轭和逐点除法的A*xx'./

用户应该警惕的另一件事是用关键字end结束函数和循环,并且必须习惯使用 Julia。然而,你会很高兴地听到这样做的原因是因为 Julia 不是一种对空格敏感的语言,所以你再也不会看到“缩进中制表符和空格使用不一致”的错误了!

打字

从技术上讲,Julia 仍然是一种动态类型语言,这意味着你不需要告诉它哪个变量具有哪个类型——类似于 Python 的工作方式。

然而,与 Python 不同,Julia 支持将变量强制为特定类型的类型化。这非常方便,原因有二:

  1. 它允许 Julia 代码比完全动态的语言运行得更快,如果一个变量被键入,那么它不需要在执行计算之前检查它是什么类型。
  2. 在处理类型化变量时,调试更容易,因为在没有显式执行的情况下,变量不会被意外地赋给不同的类型。为了在 Python 中获得同样的效果,你必须花很多时间在每个函数输入上实现assert语句,即使这样,事情仍然可能出错!

Unicode 支持!

这是朱莉娅最有特色的地方之一…

在 MATLAB 或 Python 中实现数学表达式时,我们经常会遇到像x_hatsigma这样的变量。然而,在 Julia 中,我们可以使用 Unicode 字符作为变量,而不是给我们σ

“我怎么能记住σ的键盘组合呢?我不会每次想用的时候都去谷歌一下!”

这是一个合理的担忧,但不必担心,因为 Julia 的核心开发人员比我们领先一步。对于,只需写x\hat ⇥,对于σ,写\sigma ⇥,类似于你在 LaTex 中的做法。

虽然愤世嫉俗者可能认为这是一个噱头,但我认为它允许更多的可读代码,正如 Python 的所说,“可读性很重要”。

实际写作是什么感觉?

在我的上一篇文章中,我们从头实现了一个逻辑回归模型,但是在 Julia 中它看起来像什么呢?

function σ(x::Array{Float64,2})
    return 1.0 ./ (1.0 .+ exp.(-x))
endfunction fit(
        X::Array{Float64,2},
        y::Array{Float64,1},
        epochs::Int64=100,
        μ::Float64=0.0001
    )
    ε::Float64 = 0.00001
    loss = []

    X = vcat(X, ones(1,size(X)[end]))
    dims, n_data_points = size(X)

    w = randn(1,dims) for i in 1:epochs
        X̂ = w*X
        ŷ = σ(X̂) cost = -sum(y'.*log.(ŷ .+ ε) .+ (1 .- y').*log.(1 .- ŷ .+ ε))

        dc_dw = -sum((y' .- ŷ).*X,dims=2)'        
        w = w .- dc_dw * μ
        append!(loss,cost)
    end
    return w,loss
endfunction predict(X::Array{Float64,2},w::Array{Float64,1})
    X = vcat(X, ones(1,size(X)[end]))
    X̂ = w*X
    ŷ = σ(X̂)
    return ŷ
end

在这个实现中,我们可以看到 Julia 的 Unicode 字符如何使代码更具可读性的完美例子。本地线性代数支持进一步简化了代码,每次我们想要执行乘法或求和时,都删除了np.。我们还输入了函数输入,以确保输入的类型和维度都有效。

速度!

Julia 基于 C 的血统和类型使得它的速度比缓慢的 Python 有了很大的提高。这些都可以在不对代码效率进行任何重大改进的情况下完成。

让我们用这个简单的 Python 函数来计算前 10,000 个素数:

def n_primes(n:int)->list:
    primes = []
    i = 2
    while len(primes) < n:
        prime_bool = True
        for j in range(2,i//2+1):
            if i%j == 0:
                prime_bool = False
        if prime_bool == True:
              primes.append(i)
        i += 1
    return primes

耗时 2 分 42 秒。当我们使用打字时,让我们将它与 Julia 进行比较:

function n_primes(n::Int64)
    primes = Int64[]
    i::Int64 = 2
    while size(primes)[1] < n
        prime_bool::Bool = true
        for j = 2:i÷2
            if i%j == 0
                prime_bool = false
            end
        end
        if prime_bool == true
              append!(primes,i)
        end
        i += 1
    end
    return primes
end
>> @time n_primes(10000)

这只花了 7.55 秒!

Julia 编译成二进制…这很酷

对于那些想在野外部署代码的无畏者来说,编译成二进制文件是一个有用的工具。

Python 开发人员对定义依赖关系并与pip搏斗以确保所有包保持互操作性的问题并不陌生。Julia 对此的巧妙解决方案是编译成一个二进制文件。这不仅意味着部署可以像将二进制文件放入 Docker 容器并启动您的服务一样简单,而且还意味着这带来了与使用 Go 等语言相同的安全性改进。

但是我真的很喜欢 Python…

那么不要让 Julia 阻止你,有一个 Python 解释器直接内置在 Julia 中,所以使用 Python 就像使用 Pycall 一样简单。

using Pycall
packagename = pyimport(“packagename”)

真的就这么简单!Pycall 允许使用所有内置的 Python 名称空间函数和特性(甚至使用上下文管理器)。

这听起来很不错,有什么问题吗?

调试不像在 Python 中那么容易;这可能是因为我只是熟悉 Python 的回溯错误,或者 Python 只是用一种更具描述性的方式告诉你错误在哪里。

这里有一个简单的例子,可以尝试用 Python 来说明:

Python 将两个列表相乘

…在朱莉娅身上:

Julia 将两个数组相乘

我认为其中一个比另一个要清楚得多…

Julia 的另一个问题是缺乏对机器学习库的支持。这可能是其相对年轻的产物,但它仍然是一个令人沮丧的特征。Julia 有熊猫、TensorFlow 和 Sklearn 的包装器,但如果我们想获得预训练的 ResNet 50 或 Bert 模型,这并不能帮助我们,因为它们很可能是用 Python 编写的。

话虽如此,Julia 社区正在成长,更多的本地库几乎每天都在建立,像车床MLJ ,所以我们还有希望!

Julia 缺少基于类的对象,这也使得在 Python 之外使用这些库有些笨拙。例如熊猫的df.loc[] 变成了loc!(df, )

最后,Julia 的基础命名空间中有太多的函数。在某些方面,这是方便的,并允许类似 MATLAB 级别的可用性和编写代码的简易性。然而,这使得 Julia 代码的可读性更差,通常很难判断一个函数是默认存在的,还是用户自定义的,或者是从另一个模块导入的。

所以,该不该学朱莉娅?

我同意!这有什么坏处呢?鉴于缺乏可用的受支持库,在 Julia 中编写生产代码目前会很困难。但是,Julia 确实提供了易于学习的语法、极快的代码执行、内置的 Python 解释器以及对数据科学家工作流程的许多其他潜在改进。鉴于它越来越受欢迎,可能有理由在未来转换,或者,也许你的下一个项目有一些非常严格的性能约束?朱莉娅可能就是答案。

我应该重新分配吗?

原文:https://towardsdatascience.com/should-i-repartition-836f7842298c?source=collection_archive---------1-----------------------

关于 Spark SQL 中的数据分布。

在分布式环境中,拥有适当的数据分布成为提升性能的关键工具。在 Spark SQL 的 DataFrame API 中,有一个函数 repartition() 允许控制 Spark 集群上的数据分布。然而,该函数的有效使用并不简单,因为改变分布与集群节点上物理数据移动的成本有关(所谓的混洗)。

一般的经验法则是,使用重新分配的成本很高,因为它会导致洗牌。在本文中,我们将更进一步,了解在某些情况下,在正确的位置添加一次洗牌将会删除另外两次洗牌,从而提高整体执行效率。我们将首先介绍一些理论,以理解 Spark SQL 如何在内部利用关于数据分布的信息,然后我们将查看一些使用重新分区变得有用的实际例子。

本文中描述的理论基于 Spark 源代码,该版本是当前的 snapshot 3.1(编写于 2020 年 6 月),其中大部分内容在以前的版本 2.x 中也是有效的。此外,该理论和内部行为是与语言无关的,因此我们是将它与 Scala、Java 还是 Python API 一起使用并不重要。

查询规划

Spark SQL 中的 DataFrame API 允许用户编写高级转换。这些转换是懒惰的,这意味着它们不会被急切地执行,而是在幕后被转换成一个查询计划。当用户调用一个动作时,查询计划将被具体化,这个动作是一个我们要求一些输出的函数,例如当我们将转换的结果保存到某个存储系统时。查询计划本身有两种主要类型:逻辑计划和物理计划。并且查询计划处理的步骤可以相应地称为逻辑计划和物理计划。

逻辑计划

逻辑计划的阶段负责与逻辑计划相关的多个步骤,其中逻辑计划本身只是查询的抽象表示,它具有树的形式,其中树中的每个节点都是关系运算符。逻辑计划本身不包含任何有关执行或用于计算转换(如连接或聚合)的算法的特定信息。它只是以一种便于优化的方式表示来自查询的信息。

在逻辑规划期间,查询计划由 Spark 优化器进行优化,Spark 优化器应用一组转换计划的规则。这些规则大多基于启发式,例如,最好先过滤数据,然后再进行其他处理,等等。

物理计划

一旦逻辑规划得到优化,物理规划就开始了。这个阶段的目的是将逻辑计划转化为可以执行的物理计划。与非常抽象的逻辑计划不同,物理计划在关于执行的细节方面更加具体,因为它包含了在执行期间将使用的算法的具体选择。

物理规划也由两个步骤组成,因为物理规划有两个版本:星火计划执行计划。使用所谓的策略创建火花计划,其中逻辑计划中的每个节点被转换为火花计划中的一个或多个操作符。策略的一个例子是 JoinSelection ,其中 Spark 决定使用什么算法来连接数据。可以使用 Scala API 显示火花计划的字符串表示:

df.queryExecution.sparkPlan // in Scala

spark 计划生成后,有一组附加规则应用于该计划,以创建物理计划的最终版本,即执行计划。该执行计划将被执行,生成 RDD 代码。要查看这个执行的计划,我们可以简单地调用数据帧上的解释,因为它实际上是物理计划的最终版本。或者,我们可以到 Spark UI 查看它的图形表示。

确保要求(ER 规则)

这些用于将 spark 计划转换为执行计划的附加规则之一被称为确保需求(接下来我们将称之为 ER 规则),该规则将确保数据按照某些转换(例如连接和聚合)的要求正确分布。物理计划中的每个操作符都有两个重要的属性 outputPartitioningoutputOrdering (接下来我们将分别称它们为 oPoO ),它们携带有关数据分布的信息,即在给定时刻数据是如何被分区和排序的。除此之外,每个操作符还有另外两个属性required child distributionrequiredChildOrdering ,通过它们对其子节点的 oPoO 的值提出要求。有些运营商没有任何要求,但有些却有。让我们在一个简单的例子中看到这一点,这个例子使用了 SortMergeJoin ,这是一个对其子节点有很高要求的操作符,它要求数据必须按照连接键进行分区和排序,这样才能正确合并。让我们考虑这个简单的查询,其中我们连接了两个表(它们都基于一个文件数据源,比如 parquet):

# Using Python API:spark.table("tableA") \
.join(spark.table("tableB"), "id") \
.write
...

这个查询的 spark 计划将会是这样的(我还在那里添加了关于 oPoOSortMergeJoin 的需求的信息):

星火计划中我们可以看到 SortMergeJoin 的子节点(两个项目操作员)没有 oPoO (他们是 UnknownNone ),这是一种数据没有提前重新划分,表没有分桶的一般情况。当 ER 规则应用于计划时,它可以看到 SortMergeJoin 的要求不被满足,因此它会将交换排序操作符填充到计划中以满足要求。交换操作符将负责重新划分数据以满足要求的子分配要求,而排序将对数据进行排序以满足要求的子排序,因此最终的执行计划将如下所示(这也是您可以在 SQL 选项卡的 SparkUI 中找到的内容,您不会在那里找到 spark 计划【T6

桶装

如果两个表都由连接键存储,情况就不同了。分桶是一种以预混洗和可能的预排序状态存储数据的技术,其中关于分桶的信息存储在 metastore 中。在这种情况下, FileScan 操作符将根据来自 metastore 的信息设置 oP ,如果每个存储桶正好有一个文件,那么 oO 也将被设置,并且它将全部被传递到下游的项目。如果两个表都被连接键存储到相同数量的存储桶,那么将满足 oP 的要求,并且 ER 规则将不会向计划添加交换。这里,连接两端的分区数量相同是至关重要的,如果这些数量不同,交换仍然必须用于分区数量不同于spark . SQL . shuffle . partitions配置设置(默认值为 200)的每个分支。因此,有了正确的存储桶,连接可以是无洗牌的。

需要理解的重要一点是,Spark 需要知道要使用它的分布,所以即使你的数据已经用 bucketing 进行了预混洗,除非你将数据作为一个表来读取,以便从 metastore 中选择信息,否则 Spark 不会知道它,因此它不会在文件扫描上设置 oP

再分

如开头所述,有一个函数 repartition 可用于改变数据在火花簇上的分布。该函数将数据应该按其分布的列作为参数(可选地,第一个参数可以是应该创建的分区的数量)。幕后发生的事情是,它将一个RepartitionByExpression节点添加到逻辑计划中,然后使用一个策略将该逻辑计划转换为 spark 计划中的 Exchange ,并且它将 oP 设置为 HashPartitioning ,键是用作参数的列名。

repartition 函数的另一个用法是,调用它时只有一个参数,即应该创建的分区数量( repartition(n)) ),这将随机分配数据。然而,本文没有讨论这种随机分布的用例。

现在让我们来看一些实际的例子,在这些例子中,使用重新分配按特定字段调整分配会带来一些好处。

示例 1:单向无洗牌连接

让我们看看,如果上述连接中的一个表被分桶,而另一个没有,会发生什么情况。在这种情况下,要求不被满足,因为 oP 在两侧是不同的(一侧是由铲斗定义的,另一侧是未知的)。在这种情况下, ER 规则会将交换添加到 join 的两个分支,因此 join 的每一端都必须进行洗牌!Spark 将简单地忽略一方已经被预先洗牌,并将浪费这个避免洗牌的机会。这里我们可以简单地在 join 的另一侧使用重新分区来确保 oPER 规则检查它并添加交换之前被设置:

*# Using Python API:
# tableA is not bucketed 
# tableB is bucketed by *id* into 50 bucketsspark.table("tableA") \
**.repartition(50, "id") \**
.join(spark.table("tableB"), "id") \
.write \
...*

调用重新分配将向计划的左分支添加一个交换,但是右分支将保持自由洗牌,因为需求现在将被满足,并且 ER 规则将不再添加交换。所以在最终方案中,我们将只有一次洗牌,而不是两次。或者,我们可以改变混洗分区的数量,以匹配表 B* 中的桶的数量,在这种情况下,不需要重新分区(它不会带来额外的好处),因为 ER 规则将使右分支免于混洗,并且它将只调整左分支(以与重新分区相同的方式)😗

*# match number of buckets in the right branch of the join with the number of shuffle partitions:spark.conf.set("spark.sql.shuffle.partitions", 50)*

示例 II:聚合后连接

**重新分区变得有用的另一个例子与查询相关,其中我们通过两个键聚集一个表,然后通过这两个键中的一个连接另一个表(在这种情况下,这两个表都不存储)。让我们看一个基于此类事务数据的简单示例:

*{"id": 1, "user_id": 100, "price": 50, "date": "2020-06-01"}
{"id": 2, "user_id": 100, "price": 200, "date": "2020-06-02"}
{"id": 3, "user_id": 101, "price": 120, "date": "2020-06-01"}*

每个用户在数据集中可以有许多行,因为他/她可能进行了许多交易。这些交易存储在表 a 中。另一方面, tableB 将包含每个用户的信息(姓名、地址等等)。表 B* 没有重复,每条记录属于不同的用户。在我们的查询中,我们希望统计每个用户和日期的事务数量,然后加入用户信息:*

*# Using Python API:dfA = spark.table("tableA") # transactions (not bucketed)
dfB = spark.table("tableB") # user information (not bucketed)dfA \
.groupBy("user_id", "date") \
.agg(count("*")) \
.join(dfB, "user_id")*

该查询的 spark 计划如下所示

spark 计划中,你可以看到一对 HashAggregate 操作符,第一个(在顶部)负责部分聚合,第二个负责最终合并。 SortMergeJoin 的要求与之前相同。这个例子中有趣的部分是散列集合。第一个没有来自其子项的要求,但是,第二个要求 oP 是由 user_iddate 或这些列的任何子集构成的 HashPartitioning ,这是我们稍后将利用的。在一般情况下,不满足这些要求,因此 ER 规则将添加交换(以及排序)。这将导致执行以下计划:

正如你所看到的,我们最终得到了一个有三个交换操作符的计划,所以在执行过程中会发生三次洗牌。现在让我们看看如何使用重新分配来改变这种情况:

*dfA = spark.table("tableA").repartition("user_id")
dfB = spark.table("tableB")dfA \
.groupBy("user_id", "date") \
.agg(count("*")) \
.join(dfB, "user_id")*

**spark 计划现在看起来会有所不同,它将包含由从逻辑计划转换RepartitionByExpression节点的策略生成的交换。此交换将是第一个 HashAggregate 操作符的子操作,它将把 oP 设置为hash partitioning(user _ id),该操作将被传递到下游:

左分支中所有操作符的 oP 的要求现在都满足了,所以 ER 规则不会增加额外的交换(它仍然会增加 Sort 到来满足 oO )。本例中的基本概念是,我们按两列进行分组,并且 HashAggregate 运算符的要求更加灵活,因此,如果数据将按这两个字段中的任何一个进行分布,则要求将得到满足。最终执行的计划在左分支只有一个交换(右分支也有一个),因此使用重新分配,我们将洗牌次数减少了一次:

讨论

的确,使用重新分配,我们现在在左分支中只有一次洗牌,而不是两次,但是重要的是要明白这些洗牌不是同一种类的!在最初的计划中,两个交换都发生在负责部分聚合的哈希聚合之后,因此数据在洗牌之前被减少(在每个节点上本地聚合)。在新计划中,交换出现在散列之前,因此完整的数据将被打乱。

那么什么更好呢?一次全洗牌还是两次减洗牌?这最终取决于数据的属性。如果每个 user_iddate 只有几条记录,这意味着聚合不会减少太多数据,因此总洗牌将与减少的洗牌相当,并且只有一次洗牌会更好。另一方面,如果每个 user_iddate 有很多记录,那么聚合将使数据变得更小,因此采用原始计划可能更好,因为这两次小洗牌可能比一次大洗牌更快。这也可以用这两个字段 user_iddate 的所有不同组合的基数来表示。如果这个基数与总行数相当,这意味着 groupBy 转换不会减少太多数据。

示例三:两个聚合的联合

让我们再考虑一个例子,其中重新分区将优化我们的查询。该问题基于与前一个示例相同的数据。现在,在我们的查询中,我们希望对两个不同的聚合进行联合,在第一个中,我们将对每个用户的行数进行计数,在第二个中,我们将对 price 列进行求和:

*# Using Python API:countDF = df.groupBy("user_id") \
.agg(count("*").alias("metricValue")) \
.withColumn("metricName", lit("count"))sumDF = df.groupBy("user_id") \
.agg(sum("price").alias("metricValue")) \
.withColumn("metricName", lit("sum"))countDF.union(sumDF)*

以下是该查询的最终执行计划:

这是一个典型的类似 union 的查询计划,unionunion中的每个数据帧都有一个分支。我们可以看到有两次洗牌,一次用于一个聚合。除此之外,根据计划,数据集将被扫描两次。这里的再分配功能和一个小技巧可以帮助我们改变计划的形状

*df = spark.read.parquet(...)**.repartition("user_id")**countDF = df.groupBy("user_id") \
.agg(count("**price**").alias("metricValue")) \
.withColumn("metricName", lit("count"))sumDF = df.groupBy("user_id") \
.agg(sum("price").alias("metricValue")) \
.withColumn("metricName", lit("sum"))countDF.union(sumDF)*

**重新分区功能将在聚集之前移动交换操作符,并使交换子分支完全相同,因此它将被另一个名为 ReuseExchange 的规则重用。在 count 函数中,将星号更改为 price 列在这里变得很重要,因为这将确保投影在两个数据帧中是相同的(我们需要将 price 列也投影在左分支中,使其与第二个分支相同)。然而,只有在价格列中没有空值时,它才会产生与原始查询相同的结果。要理解这条规则背后的逻辑,请参见我的另一篇文章,在那里我用一个类似的例子更详细地解释了 ReuseExchange 规则。

与之前类似,我们在这里将洗牌的次数减少了一次,但是我们现在又有了一次总洗牌,而不是原始查询中减少的洗牌。这里的额外好处是,在优化之后,由于重用的计算,数据集将只被扫描一次。

分布信息损失

正如我们已经提到的,不仅以最佳方式分发数据很重要,而且让 Spark 知道这一点也很重要。关于 oP 的信息通过计划从一个节点传播到它的父节点,但是,即使实际分布没有改变,也有一些操作符会停止传播信息。其中一个操作符是BatchEvalPython——一个表示 Python API 中用户定义函数的操作符。因此,如果您对数据进行重新分区,然后调用 Python UDF,然后进行连接(或一些聚合),那么 ER 规则将添加一个新的交换,因为 BatchEvalPython 不会向下游传递 oP 信息。我们可以简单地说,在调用一个 Python UDF 后,Spark 会忘记数据是如何分布的。

控制生成文件的数量

让我简单介绍一下重新分区功能的另一个使用案例,该功能用于在将数据分区和/或存储到存储系统时控制生成文件的数量。如果您正在将数据分区到一个文件系统,如下所示:

*df \
.write \
.partitionBy(key) \
.save(path)*

如果数据在 Spark 作业的最后阶段随机分布,它会产生很多小文件。最后阶段的每个任务都可能包含所有键的值,因此它将在每个存储分区中创建一个文件,从而生成许多小文件。在写入之前调用自定义重新分区允许我们模拟文件系统所需的分配,从而控制生成的文件数量。在以后的文章中,我们将更详细地描述这是如何工作的,以及如何有效地用于存储。

结论

**重新分配功能允许我们改变数据在火花簇上的分布。这种分布变化会在底层诱发洗牌(物理数据移动),这是一种相当昂贵的操作。在本文中,我们已经看到了一些例子,在这些例子中,这种额外的混洗可以同时删除一些其他的混洗,从而使整体执行更加高效。我们还看到,区分两种混洗非常重要,即完全混洗(移动所有数据)和简化混洗(在部分聚合后移动数据)。有时,要决定什么最终更有效,需要理解实际数据的属性。

我应该留下还是离开

原文:https://towardsdatascience.com/should-i-stay-or-should-i-go-463c6a976db3?source=collection_archive---------37-----------------------

困境是一个强化学习代理,米克·琼斯,甚至蜘蛛侠的斗争。

图片由 DanaTentis 来自 Pixabay

我应该留下还是现在就走?
如果我走了,会有麻烦
,如果我留下,会有双倍的麻烦
,所以你必须让我知道
我应该留下还是离开?——冲突

我们不都有这种感觉吗?对目前的工作不满意,但新工作薪水更低。不确定是投资股市还是理财平台?甚至蜘蛛侠也不得不在拯救玛丽·简和拯救缆车上的人之间做出选择。

困境是一种发生在头脑中的斗争。它是关于必须在两个或更多的选择中做出选择,在这些选择中,结果都是有利的或不利的。做出正确的选择可能会带来积极的结果,而做出错误的决定会让你付出代价。

在强化学习中,机器学习代理也面临两难,在探索和利用之间选择。在培训过程中,代理必须:

  • 选择一些熟悉的东西,最大化获得奖励的机会
  • 选择一些新的可能(也可能不会)导致未来做出更好决定的东西

在探索和开发之间取得平衡

找到探索(未知领域)和利用(现有知识)之间的平衡是训练一个成功的强化学习代理的关键。未知需要被发现来扩展现有的知识。已知的需要被开发,以产生回报。

这意味着,有时你不得不故意决定不选择你认为对获取新信息最有益的行动。尽管有时这意味着在探索的过程中最终会做出一些糟糕的决定。但与此同时,你想通过利用你所知道的最有效的方法来最大化你的回报。

那么,我们如何在充分探索未知和利用最佳行动之间取得平衡呢?

  • 充分的初步探索,以便确定最佳方案
  • 利用最佳选择使总回报最大化
  • 继续留出一个小概率来试验次优和未开发的选项,以防它们在未来提供更好的回报
  • 如果这些实验选项表现良好,算法必须更新并开始选择这个选项

有时候探索会让我们付出代价。红迪网

ε贪婪

在强化学习中,我们可以决定一个智能体要花多少时间去探索。这是通过调整ε-greedy 参数来实现的,其范围从 0 到 1。

如果我们设置 0.1ε-greedy,该算法将在 10%的时间内探索,在 90%的时间内利用最佳选项。在大多数情况下,ε-贪婪参数值通常设置在 5%到 10%之间。

使用井字游戏代理评估不同的 greedy

我开发了一个井字游戏,代理可以通过互相对战来学习游戏。首先,让我向你介绍我们的代理人,他们是代理人 X 和代理人 o。代理人 X 总是先走,这意味着代理人 X 有优势。

你可以和我的井字游戏代理对战

实验一。为了找出这个游戏中每个代理最合适的ε贪婪值,我将测试不同的ε贪婪值。我会初始化代理 X 探索 1% (eps 0.01)的时间,双方代理对战 10000 场,我会记录代理 X 获胜的次数。然后我会增加到探索,重复测试,直到 X 特工 100%的时间探索(eps 1.0)。

代理 X 的结果(从 1%到 100%的探索)。vs 特工 O (eps 0.05)。蓝线代表代理 X 在不同探索率下赢得的游戏数。

代理 X 在不同的ε贪婪值上赢得的游戏数(10,000 个中的一个)

这说明探索率越高,X 特工胜率下降。当 X 特工探索 5%的时间时,它达到了赢得 9268 场比赛的顶峰。代理人 O 也开始赢得更多的游戏,因为代理人 X 探索超过 50%的时间。

5%的探索率是赢得大多数游戏的最佳选择

实验二。让我们看看如果我们用一个最优的 5%ε贪婪初始化代理 X,代理 O 会怎么样。蓝线代表 O 探员赢的游戏数。

代理 O 在不同ε-贪婪值下赢得的游戏数

好吧,特工 O 任何勘探率都没有胜算;它在学会游戏之前就已经输了大部分游戏。

实验三。让我们将代理 X 的 greedy 调整为 100%,这意味着代理 X 将一直玩随机动作。蓝线代表代理人 O 赢了随机代理人 x 的游戏次数。

代理 O 在不同ε-贪婪值上赢得的游戏数,其中代理 X 随机参与

代理人 O 在 30%勘探率后开始损失更多。

尝试演示

探索在线演示,在井字游戏中挑战我们的强化代理。您可以调整参数来训练不同的代理。

了解井字游戏代理如何学习:

[## 强化学习价值函数

代理使用价值函数学习井字游戏的强化学习算法——带网络演示

towardsdatascience.com](/reinforcement-learning-value-function-57b04e911152)

如果您喜欢在线演示,您可能也会喜欢这个:

[## 使用 TensorFlow.js 进行时间序列预测

从在线 API 中提取股票价格,并使用 RNN 和 LSTM 以及 TensorFlow.js 进行预测(包括演示和代码)

towardsdatascience.com](/time-series-forecasting-with-tensorflow-js-1efd48ff2201)

为什么顶尖计算机学院仍然是一项合理的投资

原文:https://towardsdatascience.com/should-i-still-go-to-a-top-cs-school-now-182b624a3c7f?source=collection_archive---------60-----------------------

意见

让我们来谈谈麻省理工学院、史坦福大学、柏克莱大学和 CMU 大学的教育巨擘能带给虚拟桌面的好处。

每个人都知道大学的价值主张在过去的几个月里急转直下,所以我在这里谈谈为什么你仍然应该考虑去。我不打算关注文凭主义或从高中毕业、进入好大学、找到好工作的一系列好处。我在这里讲的是这些大学如何在团队中制造网络和能够创造价值的人。

我第一次来到伯克利校园。

人才集中

多年来,最好的学生一直在最好的学校上学。这条管道仍将继续。那些不是一年级的学生已经开始享受这项福利,我认为他们应该坚持下去。培育网络。

聚合、网络和友情

对于决定间隔年或不上学的高中生,我会说要小心行事。我看过的在线课程给你提供了一个单一的教育途径。高等教育最有价值的部分是你遇到的人和团队合作的能力。我称之为 CS 网络效应— 没有一个位置的最佳路径是单独建造。

软件工程职位都是关于分享代码片段,共同构建,并从数字工作的边际规模中获利。单独教育不会教你必须调整你的编码风格,以适应更大的协作。

如果你有兴趣了解更多,这里有很多关于高等教育对社会资本的益处的文章。我在这里肯定有偏见,但是我的朋友们改变了我的生活。(来源 1234 )。

找工作

大公司从大学校招人。实习项目是未来员工的试用期。疯狂的支付率类似于未来服务的定金。在冠状病毒时代,这条管道仍在移动,并隐含着进入顶级 CS 学校的决定的一部分。

学位可以让你在招聘人员面前有所表现。多年来,脸书一半以上的新员工来自排名前十的学校(来源)。这是一个数据点,但它并不孤单。

随着劳动力变得遥远,教育变得分散,个人变得多样化,在你的应用程序中拥有一个稳定的价值可能是一个巨大的胜利。利用网上学习专业化,让自己变得有价值,让公司无法忽视。我认为会有很多人决定不完成学业并为此后悔。

财务稳定性和能力

捐赠是一个强有力的工具(也是永久关闭的安全网)。学校有办法容纳学生,并发展他们的课程。(捐赠基金的)投资将继续赚钱。没有柏克莱,麻省理工,史丹福,CMU 等等。面临着不存在的风险,他们将缓慢而谨慎地改善他们的教育系统。他们将继续努力向学生传递价值。我预计秋季将继续创新。这一部分主要是猜测,但虚拟教育在一段持续的时间内对大学是一个存在的威胁,这推动了变化。

例如,我看到加州大学伯克利分校人工智能导论的课程工作人员制作了一个带有随机化和多种反作弊措施的在线测试工具。这是在不到一周的时间里。变化的累积压力(最终)会带来好的东西。

大多数好处听起来像是来自社会惯性的剩余好处——也就是说,人们习惯于去这些学校,因此去这些学校有隐含的好处。这些机构将继续利用这些主题。在过去,高等教育也有过其他的中断。

虽然一所新学校现在很难运转起来,但我认为有必要记住是什么让这些大学走到今天,以及价值主张的哪些部分仍然存在。幸运的是,在这个时代,计算机科学学位仍然是一项有价值的投资。一些幸运的少数人已经退出了他们的项目,但是做出这样的决定是非常短视的,他们是成功的少数。

限制

我需要知道这些成本是如何融入这幅画面的。我已经付完学费了,所以我说起来很容易。

直接成本

官僚主义,成本,实践的惯性,成本,成本。在每学期支付 30k 美元后,去一所大的大学将会给你带来很多小的可交付成果,规划年数和完成各种学位要求,处理过时的做法,等等。我认为这些不必要的后勤负担将成为学校成败的压力点。在线教育可以顺畅很多。付费做物流好像落后了。

当一家技术公司可以即时提供个性化的教育内容时,为什么有人要每天花几个小时处理大学官僚主义?

人民。从大学团体学习环境到个人赛道的代价是巨大的隔离。你仍然可以获得技能,但是很难把它放在更大的范围内。看看这些来源中的一些 1234

间接成本

这些改变政策的间接成本是代表名额不足的成员将被更多的学校过滤掉。当学生回家时,他们并不都有机会进入学习空间,无论是身体上还是精神上。我希望看到学校带来他们的捐赠来帮助学生体验正常化。为远程学习学生支付部分房租。像科技公司给新员工一样,送他们一台笔记本电脑。学院为学生提供全面的远程医疗。

在加州大学伯克利分校,获得治疗师的等待时间是几周,他们的带宽只够学生一学期检查 4 次(我在试图通过大学获得帮助时了解到这一点)。对于竞争激烈的大学和不稳定的世界来说,这还不够。

蓬勃发展的学校将会采取激烈的行动来确保这种新的教育形式是公平的。我们这些有空间的人需要对这个话题发表意见。另一篇关于这个话题的文章,还有一些更多 来源:

[## 大学需要上网,但必须认识到学生之间的差异(观点)

对于许多未被充分代表的学生来说,在线学习是一条至关重要的途径,应该扩大。但是如果大学不明白如何…

www.insidehighered.com](https://www.insidehighered.com/digital-learning/views/2019/04/10/colleges-need-go-online-must-recognize-how-different-students-are)

这就是我家交学费的目的。这些朋友将改变世界。

我没有提到的主要缺点是成本。我没有一个好的方法来平衡我讨论的优势和明显的经济负担,但这正是个人的切入点。如果你负债累累,也许不值得。

[## 自动化大众化

一个关于机器人和人工智能的博客,让它们对每个人都有益,以及即将到来的自动化浪潮…

robotic.substack.com](https://robotic.substack.com/)

书评的顺序应该个性化吗?

原文:https://towardsdatascience.com/should-the-order-of-book-reviews-be-personalised-9d62ebf9ba33?source=collection_archive---------45-----------------------

照片由阿尔方斯·莫拉莱斯Unsplash 拍摄

我总是在购买一本书之前阅读书评,我经常发现自己不知道我应该给它们多少权重。就他们通常阅读的体裁以及他们如何评价这些体裁而言,评论者与我有多相似,因此他们的经历在多大程度上反映了我的经历?

注意:如果你只想看到推荐系统的结果,并想跳过过程的细节,请跳到最后的结果部分。所有的代码都在 GitHub 上。

项目目标

目前,评论是根据喜欢/有用投票的数量或评论者排名来排序的,在推荐系统的时代,观察个性化评论排序的效果也将是有趣的。

所以这个项目的目的是建立一个书评推荐系统— 这个系统不仅向用户推荐书籍,而且按照与该用户最相似的书评家的顺序对每个书籍推荐的现有书评进行重新排序

虽然这个项目将只考虑书籍,但这可以扩展到其他产品,尤其是体验比产品功能更重要的产品。

获取数据

我使用了 USCD 大学 Julian McAuley 和他的团队提供的亚马逊书评数据集,特别是 2014 年 5 核书评数据集和相应的图书元数据,包含 14 年的评论。我花了项目的大部分时间来研究存储、清理和重新设计数据集的方法,但我意识到我的数据清理困境的细节并不令人兴奋,所以我将在我的 GitHub 上为那些感兴趣的人保存细节。

在清理和压缩数据集之后,我有了大约 270,000 行评论,其中只包含那些写了至少 50 条评论的用户。每个审查都包含以下信息:

  • 审核人 ID
  • 阿辛(图书 ID)
  • 评级整数刻度,1 至 5
  • 复习总结——为了节省记忆把剩下的都落下了
  • 总投票数衡量点评的受欢迎程度,这决定了个性化应用前点评的顺序。这最初是作为有用投票与总投票的比率提供的,但是由于一些评论没有有用投票,并且有用投票和总投票的分布是相似的,所以我决定只使用总投票作为衡量标准。

书评数据集的快照

图书元数据数据集包含描述、类别等,不一致且混乱,因为并非所有的图书都有元数据信息,而对于有元数据信息的图书,由于它们最初在亚马逊上的列出方式,一些信息是模糊或不正确的。

例如,一些书只有“文学与小说”的标签,这是一个流行的分类标签,这使得很难区分书籍。这使得判断推荐系统的结果更加困难,我们将在后面看到。

前 15 类书籍

探索数据—随着时间的推移,人们变得越来越刻薄…

一般来说,人们似乎给书很好的评价,因为数据非常倾向于更高的评价(4 或 5 星)。一个不利之处是,这将使区分用户偏好和计算相关用户相似性变得更加困难。

负面评论似乎也获得了更多的关注,因为每个评级类别的平均总票数(喜欢)在 1 星和 2 星评论中最高。这可能会不公平地将负面评论推到首位。

从 2000 年到 2014 年,评论者对他们的评论变得更加苛刻,平均评分从大约 4.25 下降到大约 3.9。有趣的是,2007/2008 年的平均收视率大幅下降,这与金融危机相吻合…

推荐系统的类型

有 3 种主要类型的推荐系统:

  • 基于内容的方法:基于内容的方法使用关于用户或项目特征的信息来推荐项目,基于用户先前喜欢的类似项目或在类似用户中受欢迎的项目。
  • 协同过滤(使用显式或隐式数据的基于记忆和模型的方法):协同过滤方法使用先前的用户-项目交互,例如评级,来寻找相似的用户或项目(基于记忆)或预测未知的评级(基于模型)以生成推荐。
  • 混合模式:两种方法的混合

对于那些对不同类型的推荐系统有兴趣的人来说,这里有一篇很棒的文章。

这两种类型的主要区别在于它们处理的数据。在这种情况下,我们有过去的用户-项目交互、评级(显式数据)、vs 项目和用户特征(本质上是元数据),因此我们可以使用协作过滤方法——基于内存和模型的方法——使用惊喜库,它提供了一系列算法来构建推荐系统。

推荐系统的基础

为了更好地了解推荐系统是如何工作的,在使用来自 Surprise 的更高级的方法之前,我首先从头构建了一个基本的系统— 在另一篇文章中,我将一步一步地介绍用 Python 构建基本推荐系统的过程。

使用协同过滤(基于模型)的推荐系统背后的基本思想是使用所有已知的评级(用户已经评级的书籍)并通过计算信息来预测未知的评级(用户还没有评级的书籍),这些信息例如是他们过去如何对书籍进行评级、用户通常如何对该书进行评级以及根据算法使用来自相似用户或项目的评级。

一旦我们有了这些预测评分和完整的用户项目偏好矩阵,我们就可以对每个用户的预测评分列表进行排序,以获得评分最高的书籍,这将形成对该用户的推荐。

一个完整的用户项目矩阵,其中模型使用已知评级来计算未知评级

对于每一本书的推荐,我们可以通过计算评论者和用户之间的用户相似度来重新排序该书的现有评论。我们可以通过计算每个评论者和用户之间的余弦相似度来做到这一点。然后,我们可以根据最相似的评论者对评论进行重新排序,这样,出现在顶部的评论是由与用户最相似的评论者撰写的。

为了形象化余弦相似性是如何工作的,如果我们想象上表中的每个用户行是图书评级的向量,我们可以通过计算所有向量(用户行)之间的余弦距离(角度)来计算出哪些向量彼此“最接近”,如下图所示。余弦相似度就是 1-余弦距离。

余弦相似性如何指示用户相似性的可视化表示。书籍评级的向量越相似,角度就越小,因此用户被计算得越相似。

利用惊奇发现最佳模型

惊喜是一个简单易用的 Python scikit 用于推荐系统。在从零开始构建一个基本的推荐系统后,我测试了 Surprise 提供的所有更高级的算法,并根据 RMSE 评分选择了最好的 3 个模型,通过超参数调整进一步优化。

如下图所示,在彻底搜索前 3 个模型以找到最佳超参数后,BaselineOnly、SVD(由于拟合时间而选择 SVDpp)和 KNNBaseline,baseline only 模型以 0.85279 的 RMSE 分数名列第一,这里的 RMSE 分数告诉我们,平均而言,该模型的平均误差约为 0.85 个评级点。欲了解这些不同型号的更多信息,请查看惊喜文档

条形图显示每个算法的 RMSE,以及调整后前 3 名算法的最佳 RMSE

推荐前 10 本书并测量精度@k 和召回@k

在运行获胜的 BaselineOnly 模型并生成完整的用户项目矩阵后,我们可以为每个用户挑选该用户尚未阅读的前 10 本书(由无评级表示),方法是对预测评级列表进行排序,找到前 10 个评级。

为了防止推荐系统只推荐最受欢迎的书籍,我首先为每个用户挑选了排名前 15 位的书籍,从中我随机选择了 10 本书。这将覆盖率(所有用户推荐的前 10 本图书/图书总数)从 6%提高到了 10%。

除了 RMSE 评分之外,我们还可以通过测量每个用户的 Precision@k 和 Recall@k 来衡量我们的推荐系统有多好,其中 k 是您正在进行的推荐的数量(在我们的例子中是 10)。它们被定义为:

摘自惊喜文档

如果一个项目的真实评级大于给定的阈值,则该项目被认为是相关的,因此这只能通过已知评级来实现,因为我们不知道未知评级的真实评级是什么。

在这种情况下,我将相关性的阈值设置为 4 星,这使我的精确度为 0.9 @ 10,召回率为 0.3 @ 10。 0.9 Precision@10 是一个高分,表明推荐引擎通常推荐真实评分为 4 或更高的合适书籍,但这也可以很容易地用评分分布偏向 4 或 5 星的事实来解释。

然而,0.3 的回忆@k 分数表明只有大约三分之一的相关书籍(4 星或更高)被推荐。我们已经从排名前 15 的书中随机抽取了 10 本书来提高覆盖率——这也将提高 Recall @ k——但我们可以测试更复杂的方法来提高这些分数,并带来更多种类的推荐。

计算用户相似度并衡量影响

现在我们有了书籍推荐,对于每一个推荐,我们可以获取该书的现有评论,并计算这些评论者和推荐所针对的用户之间的余弦相似性。一旦我们有了余弦相似性,我们就可以根据最相似的评论者对评论重新排序,这样出现在顶部的评论是由与用户最相似的评论者撰写的。

因为通过一个例子更容易解释,所以让我们以用户 A3UDYY6L2NH3JS 为例,为了方便起见,简称为 Alex,并以他们推荐的书籍之一 asin: 0575081384 或以其他方式称为风的名称:王者杀手编年史为例。

如果 Alex 在 Amazon 上查找这本书,我们可以通过按总票数排序来估计当前的评论顺序,如下图所示-实际上,还会考虑书评人的排名。然后,我们可以计算所有审阅者与 Alex 之间的余弦相似性,并根据与 Alex 最相似的审阅者进行重新排序,以观察审阅顺序如何变化——结果显示在最后的结果部分。

现有的书评、风的名称以及它们出现的当前顺序

对于每个用户的每本书推荐,这是重复的。为了衡量推荐系统在推荐书籍方面的表现,我们使用了 RMSE 评分。然而,衡量基于用户相似性重新排序评论是否对用户个人有帮助要困难得多,因为我们需要用户告诉我们。因此,我决定为自己定义一些指标,尝试从数字上判断重新排序的影响:

  1. 评分差异:重新订购前后前 10 条评论总和的差异,因为大多数顾客从未阅读过前 10 条评论。计算所有图书推荐及其现有图书的这一指标表明,对评论进行重新排序将意味着前 10 篇评论平均增加 1.34 颗星,这可能对卖家有利。
  2. 等级差异:重新排序前后评分与评审等级乘积之和的差异。很难从这一指标中推断出太多东西(结果是 11.6),但事实证明,这在寻找书评在重新排序中变动最大的书籍时非常有用。
  3. 前后评论排名的皮尔逊相关性(本质上是前后评分的斯皮尔曼相关性)。0.48 的平均相关系数表明,重新排序将评论移动到足够低的相关性,这提出了一个问题,即最受欢迎的评论是否一定与每个人相关。

这些衡量标准并不完美,但帮助我评估了评审中是否有任何变动以及变动的程度。

可视化结果

虽然我们有很多方法可以使用 RMSE、覆盖率、Precision@k、Recall@k 和我上面定义的其他指标来从数字上衡量推荐系统的有效性,但我们也可以通过查看示例来感觉检查推荐引擎——总是更有趣!

我们还是坚持用户 A3UDYY6L2NH3JS,简称 Alex。下图左侧和右侧显示了 Alex 过去评价过的书籍,即推荐系统推荐的书籍。

Alex 过去评价过(因此读过)的书的子集与模型推荐的书的子集

通过翻看亚历克斯过去评价过的一些书,我们可以看出亚历克斯喜欢惊悚、科幻和历史文学。这一点在已推荐的书籍中也有所体现由于书籍元数据不完整,推荐中遗漏了部分书名信息。

从流派分类来看,没有明显的相似流派被推荐。这主要是由于图书元数据不完整和混乱,没有为每本书正确标记流派,一些书只有宽泛的标签,如“文学和小说”。

请注意,元数据不完整或不一致不会影响模型推荐书籍的能力,因为模型只需要过去的用户交互数据就可以工作,从中可以推断出要推荐的类似书籍。元数据不完整只会给可视化结果带来不便。但是不管怎样,通过分析书名,你可以看到这个模型推荐的书与 Alex 过去读过的书风格相似。

Alex 过去读过的书籍的流派分类与推荐系统推荐的书籍流派

现在,让我们从推荐列表中选择一本书,《风之名:弑君者编年史》( asin: 0575081384 ),并查看该书的现有评论以及如果 Alex 在亚马逊上查找该书,它们当前出现的顺序。

注意:此处仅显示前 10 条评论

看看前 10 名的评论(就投票而言),这似乎是一个大杂烩,可能会让亚历克斯对购买这本书持观望态度。但是如果我们现在重新排列评论,按照与 Alex 最相似的评论者的顺序,它显示了一个非常不同的故事…

注意:此处仅显示前 10 条评论

与 Alex 最相似的前 10 位评论家给这本书打了 4/5 星,而在重新排序之前,这本书的评论褒贬不一。如果亚历克斯先看到这些评论,他们可能会更有兴趣购买这本书。

查看评论者之前阅读的书籍类别,与 Alex 最相似的评论者在重新排序前阅读了更高比例的科幻和奇幻小说。但是考虑到不一致的元数据,很难从类型分类中得出更多的结论。

最后的想法

总而言之,这个项目是了解更多关于推荐系统的好方法。虽然我认为个性化评论的顺序很有趣,但我仍然认为这应该只是对评论排序计算的一部分,因为评论者的排名和喜欢/投票的数量对于保持出现在顶部的评论的质量也很重要。我的项目只是旨在观察增加个性化以增强用户体验的效果。

这个项目只是这种想法的第一步,我有几个想法想进一步完善这个模型:

  • 使用更广泛的书评和元数据数据集(如【GoodReads 数据集)和 AWS 来改进推荐引擎,并更准确地评估重新排序的影响
  • 使用本文中详述的评论文本上下文分析,以包括评论本身的细节,并可能改进评级预测
  • 定义更好的指标来衡量个性化评论的影响

感谢您的阅读,我一如既往地欢迎任何反馈/想法——请通过LinkedIn联系我!

是否应该抛弃云计算,拥抱边缘计算?

原文:https://towardsdatascience.com/should-we-abandon-cloud-computing-and-embrace-edge-computing-971228e3dae4?source=collection_archive---------50-----------------------

边缘计算正在呈指数增长,但它是什么,如何使用,在哪里使用,它会取代云吗?

赖特工作室拍摄于 Shutterstock

介绍

这篇文章有望向您介绍边缘计算。我们将把它与云计算进行比较,讨论它的主要优缺点和一些使用案例。顶端的樱桃:文章最后对边缘计算的预测,以及云计算是否会被边缘计算淘汰。

云计算现在已经深入我们的日常生活。不管你是否意识到,你现在可能正在使用它。从显而易见的在线云存储(想到 Dropbox 和 OneDrive)、通信服务(电子邮件&消息)、数字助理(Siri、Alexa、谷歌助手),到娱乐内容提供商(Spotify、网飞……)。

这些服务是集中的。无论您何时发送请求,它都会被发送到云提供商,经过处理后返回给您。简单地说:

作者创作—Raul Almu 在 Shutterstock 上创作的右侧图像

非物质化的程度在过去几十年中有所提高。这与以前使用物理存储的模式不同,想象一下访问 CD/DVD:

作者创作 PNG 创作的右侧图像(来源)

在这两个极端之间,现在出现了另一种范式:边缘计算。

什么是边缘计算?

边缘计算可以定义为“集中式云计算的本地分布式扩展”。

它在图中的什么位置?

要了解边缘计算的地位,我们先来对比一下云计算。

云计算是集中式的:

  • 所有者/管理者:大部分云计算由四家公司管理——亚马逊、微软、谷歌和 IBM,
  • 区域:数据存储在数据中心,
  • 数据处理:处理/计算在数据中心进行。

罗伯特·怀特在 Focus-works.com 拍摄的图片

边缘计算是分布式的:

  • 所有者:一家公司可以拥有一台边缘服务器,并将其安装在本地,
  • 区域:数据存储更靠近用户位置(在‘网络边缘’),在需要的地方,
  • 数据处理:大部分数据处理发生在分布式设备节点(IoT 设备——物联网),或者本地。数据中心因此变得可有可无。

此外,它还通过物联网设备与物理世界互动,例如传感器和摄像头(稍后将详细介绍)。

罗伯特·怀特在Focus-works.com拍摄的图片

云和边缘计算如何互动?

由 NoMore201 创建— CC BY-SA 4.0,在维基百科

  • 从底部的三分之一开始,我们看到物联网传感器交互并从物理世界收集数据。
  • 在中间,数据在本地边缘服务器上处理。这些数据可以在其他边缘服务器之间存储和交换。请注意,在某些情况下,数据的处理可能已经发生在物联网设备层面。
  • 云层在这里是可选的,它在任何繁重的处理过程中充当支持,或者用于存储历史数据。

现在,让我们回顾一些边缘计算的使用案例,以了解它在未来可能会颠覆哪些行业。

边缘计算的应用和使用案例

制造、零售和智能城市是边缘计算实施的三个主要潜在领域。

  • 制造:在整个生产周期中,放置在不同机器上的大量传感器用于测量速度、温度、化学品或溶液的浓度水平。传感器收集的数据可用于预测性维护、预测任何刹车以及进行库存管理。
  • 零售:库存跟踪&管理,优化库存、物流和跟踪。
  • 智慧城市:可以通过物联网摄像头分析行人流量,使用传感器管理停车场,使用物联网摄像头优化交通灯,以及联网车辆。

现在让我们来看看边缘计算的优势和劣势。

优势

  • 金融

照片由米歇尔·亨德森Unsplash 上拍摄

金钱几乎是一切事物的核心。对于边缘计算为什么会成为使用云计算的环境的有趣替代或补充,这并不令人惊讶。使用 edge 的一些好处可以减少:

  1. 云和存储成本
  2. 带宽使用

此外,通过在本地处理信息,可以提高反应速度和决策能力。根据一些估计,与云解决方案相比,成本可以降低三分之一。

  • 网络安全

丹·尼尔森在 Unsplash 上拍摄的照片

用户和组织越来越关注安全性和隐私。边缘计算在这个问题上也有自己的观点:

  1. 本地分析—分析现在在本地进行,即物联网设备(传感器/摄像机)和本地边缘服务器之间的数据流。
  2. 有限的传输——当使用常规云解决方案时,整个数据流必须加密并发送到数据中心,进行解密和处理,然后将结果返回给机器或用户。使用边缘计算,计算在本地发生,在物联网设备或边缘服务器的级别,唯一的传输将是返回的结果。
  • 主权 &合规

马库斯·斯皮斯克在 Unsplash 拍摄的照片

随着时间的推移,这两个因素变得越来越重要。在竞争激烈的世界中,数据是一项关键资产。领导者希望保留对这一关键组件的监管,同时遵守现有的法规。

  1. 对个人数据的主权可以通过边缘计算等本地解决方案来实现。尽管通过使用云解决方案,用户确实保留了其数据的所有权,但这可能会让领导者放心,因为他们的数据“触手可及”,而不是远在数据中心。
  2. 边缘计算还通过将数据存储和处理等事项保持在本地,使其更容易遵守数据法规(GDPR 和其他法规)。
  • 更快的部署

除了成本,解决方案的部署速度也是公司尽快获得收益的一个重要因素。

工业领域的部署预计只需 6 个月,而其他解决方案则需要 24 个月。更快的部署还意味着更低的成本和可以更快利用的新工具,以便做出更好、更快的决策。

  • 高反应性

使用边缘服务器进行本地数据处理意味着快速处理,远离对远程数据中心的依赖。有限的数据批次上的反应性差异可能不明显,但是在要传输的批次很大的情况下,本地边缘服务器会有所不同。

当涉及到关键决策的高反应性时,如自动驾驶汽车,边缘计算也将具有…优势。双关语。无人驾驶汽车正在从无数传感器收集数据,远程数据中心没有时间审查信息并返回警告以踩刹车。

  • 交通

杰克·吉文斯在 Unsplash 上的照片

想象一个由相互连接的监控摄像头组成的网络。他们不断地向数据中心传输信息,在数据中心对信息进行分析,看是否有入侵行为。如果每个摄像机都以 6 MB/s 的速率传输,这又会增加房屋带宽使用的负担,并会降低企业的正常运营速度。数据流到达数据中心进行处理,如果怀疑有入侵行为,就会向用户发回警报信息。

借助边缘计算,记录的分析将在配有机器视觉功能的单个物联网摄像机内进行。在任何可疑入侵的情况下,摄像机将简单地发送一个警报消息,这只是几个字节对 6 Mb/s 的流。

不足之处

这是一个很好的优势列表,但人们应该保持批判的头脑,不要把这些优势视为理所当然。对能源成本、安全性、部署速度的宣称可以经受考验,时间会证明它们是否站得住脚。人们应该提出以下几个问题:

  • 降低能源成本的说法是真的吗?他们能撑得住吗?

近年来,冷却数据中心的能效有了重大改善,例如“ ”谷歌刚刚将数据中心冷却的控制权交给了人工智能”。

  • 迁移到边缘计算会不会让组织变得更加脆弱?

随着物联网设备网络的实施,向边缘计算的转移意味着用于监控、修补和更新以防止网络攻击和降低风险的资产网络正在扩大。此外,物联网安全是物联网对象的已知风险和顾虑

我在这篇文章中讨论了这个问题:

[## 物联网时代的网络安全:保持安全的一些简单步骤

物联网正迅速进入我们生活的各个领域。你的新收音机,你的真空机器人,你的新…

medium.com](https://medium.com/@godfroidmaxime/cyber-security-in-the-time-of-iot-some-simple-steps-to-stay-safe-17a73b10bc0b)

  • 部署速度的说法会被验证吗?

人们应该记住,当前对快速部署的宣称是由提供商提出的。这被用作一个强有力的卖点。边缘计算领域尚未成熟,时间将提供支持或拒绝这些说法的证据。

预测和趋势

  • 今天,互联网和云计算主要由美国和中国公司主导。你可能已经猜到了哪些是美国公司。

Photo 黑客在 IphoneHacks.com拍摄的照片

从中国方面来看,精通技术的读者肯定也会认出这些巨头:

彼得·菲斯克在基因工程上拍摄的照片

他们已经成长为巨人,而欧洲正在落后,看不到主要冠军。

  • 明天,在汽车制造和其他制造领域、医疗保健和能源行业巨头的帮助下,欧洲可能会在边缘计算领域处于领先地位。这可能比我们想象的要快。

照片由 Christian LueUnsplash 上拍摄

Gartner⁵的一项研究估计:

大约 10%的企业生成数据是在传统的集中式数据中心或云之外(作者注,即通过 edge)创建和处理的。Gartner 预测,到 2025 年,这一数字将达到 75%。

云计算的终结?

考虑到上述数字,人们可能会想云计算是否会简单地消失,被边缘计算淘汰。

虽然边缘计算预计到 2025 年将处理 75%的企业生成数据这一事实是一个令人印象深刻的变化,但应该在整体背景下看待这一变化:

  • 每天产生的数据量是惊人的。在 year⁶.,它每年都在上升这意味着馅饼的大小在增加,尽管其预期的%份额相对下降,云计算将继续处理越来越多的数据。
  • 如前所述,云计算和边缘计算的使用是不同的,它们在一定程度上重叠,但也有其特殊性。

人们不会看到边缘取代云,而是会根据需要,两者都被采用:

“Edge 将需要与云中、企业数据中心或其他设备上的其他工作负载进行通信和交互。”

  • 云计算将进一步支持大数据应用,处理海量数据集,基于机器学习算法训练模型。本质上,大数据太大,无法在本地考虑,要以适当的规模运行,应该在云中运行。

总结或 TL;博士;医生

  • 边缘计算是集中式云计算的本地分布式扩展,
  • 边缘与本地环境相互作用。机器或联网车辆上的物联网摄像头或传感器是这个生态系统的一部分。它们在网络边缘本地捕获、处理和分析交互(因此称为“边缘计算”),而不是将数据发送到云以获得这些见解。
  • Edge 的应用有望颠覆制造业、零售业和智能城市领域,
  • 边缘计算的优势是财务、网络安全、高反应性、部署速度、主权和数据合规、带宽流量少。这些声称的优势能否经受住时间的考验还有待观察。
  • Edge 处理 10%的企业生成数据,预计到 2025 年将达到 75%。在制造业、健康和能源领域的领军企业的帮助下,欧洲有望成为边缘计算的领导者。
  • 随着边缘计算的兴起,云计算处理的数据份额预计将相形见绌。但是云不会消失,根据具体情况的需要,这两种模式有望并存。

感谢阅读!加入 Medium 完全访问我的所有故事。

参考

[1]保罗·米勒,什么是边缘计算? (2018)、https://www . the verge . com/circuit breaker/2018/5/7/17327584/edge-computing-cloud-Google-微软-苹果-亚马逊

[2][3]塞利娅·加西亚-蒙特罗, L'edge computing,un outil in contourable dans L ' industrie 4.0(2019)https://www . journal dunet . com/e business/internet-mobile/1420755-L-edge-computing-un-outil-in contourable-dans-L-industrie-4-0/

[4] EY,EY 网络安全与物联网(2015), EY 网络安全与物联网

[5] Rob van der Meulen,边缘计算对基础设施和运营领导者意味着什么* (2018),https://www . Gartner . com/smarterwithgartner/What-Edge-Computing-Means-for-infra structure-and-Operations-Leaders/*

[6]大卫。F. Carr,边缘计算与云计算:有什么区别?* (2020),https://enterprisers project . com/article/2020/4/edge-computing-vs-cloud-what-is-difference*

我们应该对民调和选举结果的差异感到惊讶吗?

原文:https://towardsdatascience.com/should-we-be-surprised-at-the-differences-between-polls-and-election-results-4cb457efb08e?source=collection_archive---------49-----------------------

剧透:没有

Unsplash 上的 Element5 数码拍摄

在 2020 年选举的投票预测和选举结果之间出现几次差异后,选举投票再次受到审查。首先,在密歇根州和威斯康星州等关键州的一些总统竞选结果比民调显示的还要激烈。第二,在佛罗里达州和北卡罗来纳州,根据选前民调,拜登原本预计会赢,但最终却输了。第三,特朗普在俄亥俄州和德克萨斯州等州拥有令人信服的选票份额优势,根据民调,这些州被认为是更接近的竞选(见 Silver,2020)。

Nate Silver 认为,尽管民意调查预测的总统选举结果与 2016 年和 2020 年选举的实际结果之间存在差异,但没有足够的证据表明民意调查的质量随着时间的推移明显恶化(Silver,2018 年,2020 年)。例如,2016 年州级总统民调的投票份额差距平均比实际结果低 5.2 个百分点。虽然平均 5.2 点的民调误差可能看起来很大,但这并不罕见,因为 1972 年至 2016 年间所有总统选举的平均州级民调误差为 4.8 点(Silver,2018)。因此,当我们看到 2020 年密歇根州、威斯康星州、佛罗里达州、北卡罗来纳州、俄亥俄州和德克萨斯州的选举结果时,我们应该感到惊讶吗?我个人不这么认为。事实上,我不认为我们应该期望民意调查能够始终如一地提供最终选举结果的精确近似值。请允许我详细说明。

调查更擅长描述而不是预测

一个设计良好的调查可以是一个很好的工具,用来描述一个群体的特征,这些特征可以通过回答者相对容易回答的问题来衡量。然而,根据对假设情景的反应来获得个人未来行为的可靠测量更具挑战性。通过询问受访者,如果选举在今天举行,他们会投谁的票,民意调查实际上是要求受访者在假设的情况下对他们的行为做出解释。使用候选人偏好问题来预测选举结果的问题是双重的。首先,不能保证被调查的个人也会投票。声誉良好的投票组织尽最大努力识别可能的投票者,但可能的投票者在实际投票之前仍然不是投票者(参见 Rosentiel,2012 年关于如何确定谁是可能的投票者的讨论)。第二,即使一个可能的选民真的会去投票,那个可能的选民也可能在投票日和选举日之间改变主意。

抽样误差

民意测验是在给定的时间范围内对样本进行的调查。因为样本只是总体中的一部分,所以样本值在多大程度上代表了更广泛总体中的潜在真实值,总是存在一定程度的不精确性。这种因测量样本而非总体而存在的不精确性被称为抽样误差。在民意测验中,抽样误差通常用误差幅度(MoE) 来表示,它反映了从民意测验中得出的兴趣估计值(例如,可能投票给某个候选人的选民的百分比)与相应人群中的真实值有多远。

例如,假设一项民意调查发现,53%的可能选民会投票给候选人 A,MoE 为+/- 4%。这意味着,如果选举在给定的投票日举行,我们估计可能投票的人口中有 53%会投票给候选人 A,但是我们也承认,打算投票给候选人 A 的人口的真实百分比可能与投票估计不同,因为投票没有测量整个人口。尽管如此,我们至少可以说,如果选举在投票日举行,我们有 95%的信心认为,投票给候选人 A 的估计百分比与投票给候选人 A 的实际百分比相差不超过 4 个百分点(见 Mercer,2016)。

如上例所示,所报告的 MoE 通常是指打算投票给某个候选人的参与者的百分比。然而,重要的是要注意,每个候选人的支持百分比之间的的 MoE 接近个人百分比 MoE 的 2 倍(Franklin,2007;美世,2016)。让我们再来看一次假设的民意调查,其中 53%的可能投票者表示他们将投票给候选人 A,假设只有两个候选人参加竞选,那么 47%的可能投票者表示他们将投票给候选人 B。候选人 A 领先候选人 B 6 个百分点,考虑到 MoE 为 4%,人们可能会得出这样的结论:候选人 A 的领先优势具有统计学意义,因为 6%超出了 4%的 MoE。然而,候选人之间的差异的 MoE 大约是单个候选人 MoE 的 2 倍,即 8%而不是 4%。虽然根据我们的民意调查,我们估计候选人 A 比候选人 B 有 6 个百分点的优势,但这是一个单一的估计,由于抽样误差,它具有不确定性。尽管如此,我们可以量化这种不确定性,并声明-2 到 14 个百分点的区间可能捕捉到感兴趣的人群差异。然而,由于该区间包含负值,这表明倾向于投票给候选人 B 的百分比较高,因此我们不能确信候选人 A 在本次民意调查中的领先不仅仅是由于抽样误差。那么,我们最好把这场比赛解释为一场胜负难料的比赛。这里的教训是,在选举中仅仅看候选人的投票份额是不够的。还需要考虑对 MoE 的正确解释,因为 MoE 提供了对投票估计的统计精度的感觉。

无反应

鉴于近年来许多调查中的历史低回复率,无回复是调查的一个问题(例如,Keeter 等人,2017 年;皮尤研究中心,2012 年;威廉姆斯&布里克,2018)。特别值得关注的是,无响应系统 可能会导致低估或高估,这种现象称为无响应偏差。然而,重要的是要认识到,高无应答率本身并不一定保证偏差,相反,当应答者与无应答者在具体措施上存在差异时,调查中的具体估计值会因无应答而产生偏差(Groves,2006;Groves & Peytcheva,2008)。

不幸的是,有理由怀疑特朗普的支持者可能在 2020 年不太可能对电话民调做出回应(Cohn,2020;法农,2020;另见 Gelman 等人,2016;莱维兹,2020;马修斯,2020;斯坦顿,2020)。如果特朗普的支持者相对于拜登的支持者更不愿意参与民意调查,这将高估拜登在民意调查中的支持,因为在这种情况下,不同的无回应将与候选人偏好相关联。

虽然目前需要对特朗普和拜登支持者在 2020 年的不回应模式进行更多研究,但我想在这里强调的要点是,每当阅读民意调查时,人们都应该意识到参与民意调查完全是自愿的。具有特定政治倾向的个人可能或多或少会对特定选举中的民意测验做出反应。当这种现象发生时,根据谁更可能是不响应者,投票的投票意向结果可能被低估或高估。虽然无回答偏差不是已知的,但我认为更保险的假设是,投票结果在某种程度上受到不同无回答的影响,特别是在竞争激烈的州的竞选中。

那么,现在怎么办?

应该以适度的怀疑态度对待基于民意调查的预测选举结果。意识到民意调查是受抽样误差和潜在无回答偏差影响的快照这一事实,选举日(或周或月)的实际结果可能远不如民意调查显示的投票份额优势那样具有决定性就不足为奇了。好吧,好吧,你可能会说,但是如果民调估计有这么多不确定性,那么民调还有用吗?

如果民意测验是根据他们在选举日预测获胜者的精确程度来评判的,那么不,许多民意测验并不是非常有用。如果投票被视为一种工具,有助于提供对候选人在特定时间点的总体表现的一些见解,那么投票可能会有更多的承诺。当多次民意调查一致显示某个候选人在该候选人的政党和观点历来表现良好的州大幅落后时,这可能对该候选人不是一个好兆头,可能是该候选人的竞选活动需要做出改变的证据。类似地,如果多项民调显示,在可能影响候选人前景的事件(比如某种丑闻)发生后,支持度发生了实质性变化,那么这也可以作为一个警告。当然,描述可能有用的投票情况的这两个场景假设可能投票的选民实际上可能投票,并且投票中的相关测量不会受到无响应偏差的不当影响。如果这些假设不满足,那么区分结果是数据的人工产物还是投票人群中实际倾向的代表就更具挑战性了。对我来说,判断民调的有用性最终与民调提供最终选举结果的准确预测的能力无关,而是与民调在选举前特定时间点提供代表性见解的程度有关。

参考

科恩,纽约州(2020 年 11 月 10 日)。民意测验出了什么问题?一些早期的理论。《纽约时报》。https://www . nytimes . com/2020/11/10/upshot/polls-what-go-wrong . html

Fannon,E. (2020 年 11 月 6 日)。为什么民调又错了。 WKOWhttps://wkow.com/2020/11/05/why-the-polls-were-wrong-again/(2007 年)。民意测验中差异的误差幅度。美国广播公司新闻。

格尔曼,a .,戈尔,s .,里弗斯,d .,&罗斯柴尔德,D. (2016)。神秘的摇摆选民。《政治学季刊》11 (1),第 103–130 页。

格罗夫斯,R. M. (2006)。家庭调查中的无回答率和无回答偏差。舆情季刊70 (5),646–675。

Groves,R. M .,& Peytcheva,E. (2008 年)无应答率对无应答偏倚的影响:一项荟萃分析。民意季刊72 (2),第 167–189 页。

Keeter,s .,Hatley,n .,Kennedy,c .,和 Lau,A. (2017 年 5 月 15 日)。低回复率对电话调查意味着什么。皮尤研究中心方法。https://www . pewresearch . org/methods/2017/05/15/what-low-response-rates-mean-for-telephone-surveys/

列维兹,E. (2020 年 7 月 17 日)。大卫·肖尔的美国政治统一理论。情报人员。https://nymag . com/intelligence r/2020/07/David-shor-cancel-culture-2020-election-theory-polls . html

马修斯博士(2020 年 11 月 10 日)。一位民意调查者解释了为什么民意调查出错。Vox。https://www . vox . com/policy-and-politics/2020/11/10/21551766/election-polls-results-error-David-shor

美世公司(2016 年)。了解选举民意调查的误差幅度。皮尤研究中心。https://www . pewresearch . org/fact-tank/2016/09/08/understanding-the-margin-of-error-margin-in-election-polls/

皮尤研究中心。(2012 年 5 月 15 日)。评估民意调查的代表性。皮尤研究中心——美国政治&政策https://www . pewresearch . org/politics/2012/05/15/assessing-the-representative-of-public-opinion-surveys/

t .罗森泰尔(2012 年 8 月 29 日)。确定谁是“可能的选民”。皮尤研究中心https://www . pewresearch . org/2012/08/29/ask-the-expert-determining-who ' s-a-possible-voter/

纽约州西尔弗市(2018 年 5 月 30 日)。民意调查没问题。五三八https://fivethirtyeight . com/features/the-polls-are-all-right/

纽约州西尔弗市(2020 年 11 月 11 日)。民意测验不太好。但这很正常。五十八https://fivethirtyeight . com/features/the-polls-not-great-but-that-pretty-normal/

斯坦顿,Z. (2020)。“人们将会感到震惊”:害羞的特朗普选民的回归?POLITICOhttps://www . POLITICO . com/news/magazine/2020/10/29/2020-民调-川普-拜登-预测-准确-2016-433619

威廉姆斯博士和布里克博士(2018 年)。美国面对面家庭调查的趋势:无回应和努力程度。调查统计与方法学杂志6 (2),186–211。

你应该买还是租下一辆车?端到端项目

原文:https://towardsdatascience.com/should-you-buy-or-lease-your-next-car-end-to-end-data-science-project-a26617f11fcb?source=collection_archive---------43-----------------------

探索这个项目,从收集数据到创建强回归的集合,再到回答你是否应该购买或租赁下一辆车

概观

在本帖中,我们将从头到尾浏览一个完整的数据科学项目,并给出问题的结论——你应该购买还是租赁下一辆车?

该项目将包括以下部分(请随意跳到您最感兴趣的部分):

  • 把问题框起来,看大局
  • 获取数据
  • 探索数据
  • 准备数据
  • 选择和训练模型
  • 微调系统
  • 分析最佳模型的误差
  • 结论

要在 Github 上查看该项目,请点击以下链接此处

把问题框起来,看大局

这个项目的目标是通过比较汽车租赁的总费用和汽车的折旧成本来确定汽车租赁是否划算。如果租赁费用更高,我们可以得出结论,购买新车并转卖会更符合 T2 的成本效益。然而,如果租赁比我们认为的便宜,你应该租赁而不是购买。

通过使用机器学习,我们预测汽车的价格,并使用它来计算折旧成本,并与租赁成本进行比较。

我们使用的指标是均方根误差(RMSE ),因为它给出了系统在预测中通常会产生多大误差的概念,误差越大,权重越高。

所以现在我们需要数据。我们没有收集数百辆不同汽车的数据,而是只收集了一辆最好的出租汽车——讴歌 TLX 的数据。这有助于我们简化问题,如果我们得出结论,你应该购买而不是租赁这辆车,我们可以得出同样的结论较低的汽车。

获取数据

在这个项目中,我们使用 BeautifulSoup 的图书馆收集数据。我们在网上搜索 Truecar.com 的讴歌 TLX 汽车列表。笔记本完整的代码用于网页抓取可以在这里找到。

该项目的其余部分的代码可以在这里查看。

让我们加载通过网络搜集收集的数据,并对其进行初步研究。

CARS_PATH = os.path.join(PROJECT_ROOT_DIR, "datasets")

**def** load_car_data(cars_path=CARS_PATH):
    csv_path = os.path.join(cars_path, "cars.csv")
    **return** pd.read_csv(csv_path)cars = load_car_data()

让我们看看我们的数据集有多完整。通过查看每一列的 null 值的百分比,我们可以很好地了解我们正在处理的缺失值的数量。

cars.isnull().sum() / len(cars)

每列的百分比 Null

我们看到在我们的 6 列中有缺失值。具体在我们的目标变量价格和属性驱动、发动机、内饰、外观颜色、内饰颜色。由于价格是我们的目标变量,我们将不得不放弃这些实例。由于 Drive、Engine 和 Trim 的缺失值百分比非常低,因此也可以删除与这些实例相关的实例。由于外部和内部颜色超过 10%为空,可能对价格没有太大的预测能力,我们将继续从数据集中删除这些列。

cars = cars.drop(columns=["Exterior_color", "Interior_color"])
cars = cars.dropna(axis=0)
cars.reset_index(inplace=**True**)

创建测试集

我们在这里使用分层分割来确保我们的测试集代表整个数据集中的各种比率。由于我们相信某些特征(如汽车年份)将是非常重要的价格预测因素,因此我们确保它们在训练集和测试集之间均匀分布。通过使用分层分割,我们避免了抽样偏差,即测试不能代表整个数据集。

下面的代码使用 pd.cut()函数创建一个包含 6 个类别的 year category 属性(标记为 0 到 5,对应于数据集中的每一年):

cars["Year_cat"] = pd.cut(cars["Year"],                            bins=[2014.5, 2015.5, 2016.5, 2017.5, 2018.5, 2019.5, 2020.5],                          labels=[0, 1, 2, 3, 4, 5]

现在我们准备根据 year 属性进行分层抽样。为此,我们可以使用 Scikit-Learn 的 StratifiedShuffleSplit()类:

**from** sklearn.model_selection **import** StratifiedShuffleSplit

split = StratifiedShuffleSplit(n_splits=1, test_size=0.2)
**for** train_index, test_index **in** split.split(cars, cars["Year_cat"]):
    train_set = cars.loc[train_index]
    test_set = cars.loc[test_index]

现在,我们删除 Year_cat 属性,使数据恢复到原始状态:

**for** set_ **in** (test_set, train_set):
    set_.drop("Year_cat", axis=1, inplace=**True**)

探索数据

现在,让我们发现并可视化这些数据,感受一下它的样子并获得一些见解。我们创建了一个训练集的副本,这样我们就可以在不破坏原始训练集的情况下使用它:

cars = train_set.copy()

下面是一个表,其中包含列、数据类型和详细描述它们包含哪些信息的简短描述。

我们将首先查看数字数据类型,并使用 corr()方法计算每对属性之间的标准相关系数:

corr_matrix = cars.corr()

现在让我们看看每个属性与价格的关联程度:

corr_matrix["Price"].sort_values(ascending=**False**)

检查属性之间相关性的另一种方法是使用 pandas scatter_matrix()函数,该函数将每个数值属性与其他数值属性相对照。

**from** pandas.plotting **import** scatter_matrix

attributes = ["Price", "Year", "Mileage", "Accidents"]
scatter_matrix(cars[attributes], figsize=(12,8))
save_fig("scatter_matrix_plot")

上图向我们展示了一些东西。事实上,年份和里程属性将是价格的强预测因素,并显示一些交互作用,我们可以通过创建一个新的功能,每年的里程来捕捉这些交互作用。此外,三起事故并不多见。将发生 2 次或 3 次事故的汽车归入一个 2 或更多的值可能是有益的。

要创建每年英里数属性,我们需要知道汽车的使用年限,而不是年份。我们通过从汽车年份中减去当前年份的绝对值来实现这一点。但是,我们无法将 2020 款讴歌 TLXs 除以 0,因此我们将 0 替换为 1(在这种情况下,属性 miles_per_year 将与 miles 相同)。

cars["Years_old"] = abs(cars["Year"] - 2020)
cars["Miles_per_year"] = cars["Mileage"] / 
                                     cars["Years_old"].replace(0, 1) 

现在让我们看看我们的目标价格与新属性的相关性:

corr_matrix = cars.corr()
corr_matrix["Price"].sort_values(ascending=**False**)

太好了!我们发现它也与价格密切相关!

我想看的最后一个有趣的专栏是 Trim。该列包含许多信息,包括汽车上的性能套件类型。提取包并把它作为一个属性使用可能是有益的。让我们观察不同的 trims 和中间价格之间的相关性。

cars[["Price","Trim"]].groupby("Trim").median()

现在让我们提取包,看看包之间是否有明显的相关性。

**def** extract_package(trims):

    packages = ["PMC Edition", "A-Spec", "Advance", "Technology"]

    pat = '|'.join(r"\b**{}**\b".format(x) **for** x **in** packages)
    packages = pd.Series(trims).str.extract("(" + pat + ")")
    packages.fillna("Standard", inplace=**True**)

    **return** packagescars["Package"] = extract_package(cars["Trim"].values)cars[["Price", "Package"]].groupby("Package").median()

解压软件包似乎没有太大的帮助。不同包装之间的相关性很弱,不符合我们预期的任何趋势。

摘要

现在我们对哪些特性是最有价值的有了一个很好的想法,并且探索了它们之间的关系。一些重要的发现是:

  • 创建新列miles_per_year增加了额外的预测能力。
  • 发生 2 起以上事故的汽车在我们的数据集中非常稀少,最好与发生 2 起事故的汽车归为一组。我们通过这种方式保持了更强的相关性。
  • 年份更适合用作序数特征。我们将减去该列的当前年份,以创建一个名为“years old”的列。
  • 从 trim 中提取性能包可能有用,也可能没用。与价格没有明显的相关性,因此我们可以在数据准备阶段将它作为一个选项添加进来。

准备数据

是时候为机器学习算法准备数据了。我们没有手动这样做,而是为此编写函数,这有几个原因:

  • 这将允许我们在任何数据集上重现这些转换(例如,下次您获得新的数据集时)。
  • 我们将逐步建立一个转换函数库,可以在未来的项目中重用。
  • 这将使我们能够轻松地尝试各种转换,并查看哪种转换组合效果最好。

我们需要一个数字属性和分类属性的准备管道。先说数值属性吧!

由于我们使用的是 Scikit-Learn,所以我们希望我们的转换器能够与 Scikit-Learn 功能(比如管道)无缝协作,但幸运的是,我们只需要创建一个类并实现三个方法:fit()(返回 self)、transform()和 fit_transform()。我们只需添加 TransformerMixin 作为基类,就可以免费获得最后一个。

我们还添加了 BaseEstimator 作为基类,为我们提供了两个额外的方法(get_params()和 set_params()),这对自动超参数调优很有用。

例如,这里有一个 transformer 类,它添加了前面讨论过的数字属性,并在我们将训练集传递给它时添加了它的输出。

**from** sklearn.base **import** BaseEstimator, TransformerMixin

**class** **NumericalAttributesAdder**(BaseEstimator, TransformerMixin):
    **def** __init__(self, add_miles_per_year = **True**):
        self.add_miles_per_year = add_miles_per_year
    **def** fit(self, X, y=**None**):
        **return** self
    **def** transform(self, X):
        years_old = abs(X["Year"] - 2020)
        accidents_adjusted = X["Accidents"].replace(3, 2)
        **if** self.add_miles_per_year:
            miles_per_year = X["Mileage"] / years_old.replace(0, 1)
            **return** pd.concat([X, years_old.rename("Years_old"),  
                         accidents_adjusted.rename("Accidents_adj"),                        
                         miles_per_year.rename("Miles_per_year")],   
                         axis=1) **else**:
            **return** pd.concat([X, years_old.rename("Years_old"),
                        accidents_adjusted.rename("Accidents_adj")],         
                        axis=1)

num_attr_adder = NumericalAttributesAdder(add_miles_per_year = **True**)
num_attr_adder.transform(X_train)

现在,在我们添加新的属性之后,我们想要选择在我们的机器学习算法中使用哪些属性。我们使用与上面相同的方法来创建一个选择属性的自定义转换器。

**class** **DataFrameSelector**(BaseEstimator, TransformerMixin):
    **def** __init__(self, attribute_indices):
        self.attribute_indices = attribute_indices
    **def** fit(self, X, y=**None**):
        **return** self
    **def** transform(self, X):
        **return** X[self.attribute_indices]

如您所见,有许多数据转换步骤需要按正确的顺序执行。幸运的是,Scikit-Learn 提供了 Pipeline 类来帮助处理转换序列。下面是数字属性的管道:

**from** sklearn.pipeline **import** Pipeline
**from** sklearn.preprocessing **import** StandardScalerattribs = ["Mileage", "Years_old", "Accidents_adj","Miles_per_year"]num_pipeline = Pipeline([
        ('num_attribs_adder', NumericalAttributesAdder()),
        ('select_numeric', DataFrameSelector(attribs)),
        ('std_scaler', StandardScaler())
    ])

我们使用上面的两个自定义转换器,然后使用 Scikit-Learn 的 StandardScaler()转换器来标准化所有数字属性。

现在下一步是为我们的分类属性创建一个管道。由于这些属性是字符串,我们需要使用 OneHotEncoder 将它们转换成数值。但是首先我们创建一个定制的转换器,它将从我们前面讨论的 Trim 属性中提取汽车的包。我们初始化 add_trim_features=True ,让我们选择是否添加新的包属性。

**class** **CategoricalAttributesAdder**(BaseEstimator, TransformerMixin):
    **def** __init__(self, add_trim_features = **True**):
        self.add_trim_features = add_trim_features  
    **def** fit(self, X, y=**None**):                          
        **return** self    
    **def** transform(self, X):        
        **if** self.add_trim_features:
            package = extract_package(X["Trim"]) 
            **return** pd.concat([X, package.rename("Package")], axis=1)                                
        **else**:            
            **return** X cat_attr_adder = CategoricalAttributesAdder(add_trim_features =**True**)cat_attr_adder.transform(X_train)

现在,我们分类属性的完整管道已经准备好了。我们使用 CategoricalAttributesAdder、DataFrameSelector 和 OneHotEncoder 将我们的分类属性完全转换为适合机器学习的格式。管道如下所示:

attribs = ["Drive", "Engine", "Trim"]cat_pipeline = Pipeline([
        ("cat_attribs_adder", CategoricalAttributesAdder()),
        ("select_categoric", DataFrameSelector(attribs)),
        ("one_hot", OneHotEncoder())
    ])

到目前为止,我们已经分别处理了分类列和数字列。如果有一个能够处理所有列的转换器,对每一列应用适当的转换,那将会更方便。幸运的是,Scikit-Learn 为此引入了 ColumnTransformer ,好消息是它对熊猫数据帧非常有效。让我们使用它将所有转换应用到训练集:

**from** sklearn.compose **import** ColumnTransformernum_attribs = ["Year", "Mileage", "Accidents"]
cat_attribs = ["Drive", "Engine", "Trim"]full_pipeline = ColumnTransformer([
        ("num", num_pipeline, num_attribs),
        ("cat", cat_pipeline, cat_attribs)
    ])

cars_prepared = full_pipeline.fit_transform(X_train)

在这个管道中,我们指定数字列应该使用我们之前定义的 num_pipeline 进行转换,而分类列应该使用我们之前定义的 cat_pipeline 进行转换。最后,我们将这个 ColumnTransformer 应用于训练集:它将每个转换器应用于适当的列,并沿着第二个轴连接输出(转换器必须返回相同数量的行)。

就是这样!我们有一个预处理管道,它接受完整的训练集,并对每一列应用适当的转换。

选择和训练模型

终于来了!我们构建了问题,获得了数据并对其进行了探索,对一个训练集和一个测试集进行了采样,我们编写了转换管道来自动清理和准备我们的数据以用于机器学习算法。我们现在准备选择和训练机器学习模型。

我们的第一个基本模型是一个线性回归,我们将尝试改进它。使用 Scikit-Learn 的 cross_val_score()允许我们将训练集随机分成 10 个不同的折叠,然后训练和评估我们的模型 10 次,每次选择不同的折叠进行评估,并在其他 9 个折叠上进行训练。结果是一个包含 10 个评估分数的数组:

**from** sklearn.linear_model **import** LinearRegression 
**from** sklearn.model_selection **import** cross_val_score lin_reg = LinearRegression()
lin_reg_scores = np.sqrt(-cross_val_score(lin_reg, cars_prepared,   
                  y_train, cv=10, scoring="neg_mean_squared_error"))

让我们来看看结果:

**def** display_scores(scores):
    print("Scores:", scores)    
    print("Mean:", scores.mean())
    print("Standard deviation:", scores.std()) display_scores(lin_reg_scores)

对我们的基本模型来说还不错!但是,我们不是像这样显示每个模型的分数,而是将每个模型的分数绘制在一个方框图中,显示平均值、四分位间距和最大/最小分数。请记住,我们的衡量标准是 RMSE,分数越低越好。以下是我们尝试的模型列表:

  • 线性回归
  • 多项式回归
  • 岭正则化多项式回归
  • 随机森林回归量
  • 支持向量机回归机
  • 梯度推进回归器

我们看到多项式回归比简单的线性回归稍好。此外,随机森林回归和梯度推进回归表现明显较好,而 SVM 回归表现明显较差。请记住,我们只是试图了解哪些机器学习算法执行得最好,因此所有这些算法都是用默认设置训练的。

微调你的系统

现在我们有了一份有前途的模特候选名单。我们现在需要对它们进行微调。由于我们使用默认超参数来训练我们的模型,我们将尝试看看哪个超参数最适合我们的最佳模型,随机森林回归器和梯度推进回归器。

我们没有手动这样做,而是让 Scikit-Learn 的 GridSearchCV 来搜索我们。我们需要做的只是告诉它我们希望它试验哪些超参数,试验哪些值,它将使用交叉验证来评估超参数值的所有可能组合。

随机森林回归量

**from** **sklearn.model_selection** **import** GridSearchCV

forest_param_grid = [{'bootstrap': [**True**],
     'max_depth': [12, 14, **None**],
     'max_features': ['auto', 'sqrt'],
     'min_samples_leaf': [1, 2],
     'min_samples_split': [ 2, 3],
     'n_estimators': [100, 200, 300, 400]}
    ]

forest_reg = RandomForestRegressor()

forest_grid_search = GridSearchCV(forest_reg, forest_param_grid, 
                                  cv=5,      
                                  scoring="neg_mean_squared_error",
                                  return_train_score=**True**,
                                  verbose=**True**,
                                  n_jobs=-1)

forest_grid_search.fit(cars_prepared, y_train)

我们可以直接得到最佳估计量:

forest_grid_search.best_estimator_

梯度推进回归器

gb_param_grid = [{'loss': ['ls'],
         'learning_rate': [0.05, 0.1, 0.15],
         'n_estimators': [200, 220, 240, 260],
         'subsample': [0.8, 0.9],
         'min_samples_split': [2, 3],
         'min_samples_leaf': [2, 3, 4],
         'max_depth': [4, 5, 6, 7],
         'max_features': ['sqrt'],
        }]

gb_reg = GradientBoostingRegressor()

gb_grid_search = GridSearchCV(gb_reg, gb_param_grid, cv=5,
                                  scoring="neg_mean_squared_error",
                                  return_train_score=**True**,
                                  verbose=**True**,
                                  n_jobs=-1)

gb_grid_search.fit(cars_prepared, y_train)

让我们看看最佳估计值:

gb_grid_search.best_estimator_

集合:随机森林回归和梯度推进回归

另一种微调系统的方法是尝试并组合性能最佳的模型。群体(或“整体”)通常会比最佳个体模型表现得更好。现在,我们已经调整了两个最佳模型的超参数,让我们尝试将它们结合起来,以进一步提高我们的最佳得分。

使用 Scikit-Learn 的 VotingRegressor()类可以相对容易地做到这一点,该类允许我们对随机森林回归变量和梯度推进回归变量进行平均预测。

**from** sklearn.ensemble **import** VotingRegressor

forest_reg =RandomForestRegressor(**forest_grid_search.best_params_)
gb_reg = GradientBoostingRegressor(**gb_grid_search.best_params_)

forest_gb_reg = VotingRegressor([("forest_reg", forest_reg), 
                                 ("gb_reg", gb_reg)])forest_gb_reg_scores = np.sqrt(-cross_val_score(forest_gb_reg, 
                               cars_prepared, y_train, cv=10,
                               scoring="neg_mean_squared_error"))display_scores(forest_gb_reg_scores)

看,成功了!我们的平均 RMSE 低于 1600!现在我们有了最好的模型,是时候分析它的错误了。但首先让我们做最后一个方框图,比较四个最好的模型。

让我们保存最好的模型,以便我们可以很容易地回到他们当中的任何一个!

**import** **joblib**

MODELS_PATH = os.path.join(PROJECT_ROOT_DIR, "models/")
os.makedirs(MODELS_PATH, exist_ok=**True**)models = [gb_grid_search.best_estimator_,
          forest_grid_search.best_estimator_,
          forest_gb_reg]
names = ["gradient_boosting_reg", "forest_reg","ensemble_(RF_&_GB)"]**for** model, name **in** zip(models, names):
    joblib.dump(model, MODELS_PATH + name)

分析最佳模型的误差

我们将使用 cross_val_predict 对我们的训练集中的每个实例进行干净的预测(“干净”意味着预测是由在训练期间从未看到数据的模型进行的)。

**from** sklearn.model_selection **import** cross_val_predict

preds = cross_val_predict(forest_gb_reg,cars_prepared,y_train,cv=10) 

让我们把我们的预测价格和实际价格对比一下。如果我们所有的点都在对角线上,这意味着我们的模型是完美的,误差为 0。

这看起来很好,我们的误差正态分布,而不是一个区域漏低,另一个区域漏高。剩下的工作就是对测试集进行评估,并得到最终的性能检查。谢天谢地,使用我们之前创建的管道,测试集很容易准备!

X_test = test_set.drop("Price", axis=1)
y_test = test_set["Price"].copy()
X_test = X_test[cols]
X_test_prepared = full_pipeline.fit_transform(X_test)**from** sklearn.metrics **import** mean_squared_error

final_predictions = forest_gb_reg.predict(X_test_prepared)
final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)
final_rmse

最终 RMSE: 2207.82

看起来我们的训练装备可能有点过量了。回过头来尝试在测试集上表现得更好可能很有诱惑力,但是这样我们就冒着过度适应测试集的风险。我们会让它保持原样,因为它仍然在我们在训练集中得到的分数范围内。

结论

现在回到最初的问题。你应该买还是租下一辆车?

现在,我们已经有了最终的模型和测试集的性能分数,我们可以用它来预测讴歌 TLXs 的价格,其功能对应于各种租赁。我们用来对比的租约来自讴歌的网站。让我们看看多个不同的租赁条款,看看我们会发现什么!

我们预测的汽车具有以下特征和租赁:

这里是三种不同调整的预计折旧成本和租赁比较。红线代表预计折旧成本,而蓝线代表租赁成本。阴影区域代表我们预测折旧的 95%置信区间。我们看到,在所有三种情况下,租赁都要贵得多。

如果你选择购买新车,你可以节省高达 10,000 美元。即使是最好的汽车之一,租赁也要贵得多。

未来的工作

项目结束后,我脑海中突然冒出了一些我认为会很有趣的想法:

  • 我们可以模拟不同的汽车,这些汽车也有很高的租赁费率,看看你能为一辆新车提供多少资金,让它仍然值得购买和转售。
  • 从交叉验证来看,集成似乎是有益的,但在测试集上的表现仍然很差。探索原因可能会很有趣。我想知道是否所有其他模型在测试集上表现更差,或者我们的最终模型实际上不是最佳选择,尽管在交叉验证的所有折叠中表现最好。
  • 进一步考虑这个问题,尝试建立多个汽车品牌和模型的模型,这些模型仍然可以准确预测汽车的价值。

一如既往地感谢你的阅读,我希望你喜欢它,并学到一些新的和有见地的东西!

[## 路金 2/汽车租赁

在这个项目中,我的目标是通过比较汽车的折旧成本来确定汽车租赁是否划算

github.com](https://github.com/lukenew2/car-leases)

应该读数据科学硕士吗?

原文:https://towardsdatascience.com/should-you-get-a-masters-degree-in-data-science-483d961ddc6b?source=collection_archive---------73-----------------------

剧透:答案不是是或不是

照片由好的免费照片Unsplash 上拍摄

我最近听说了贝特里奇的头条定律。它指出,如果一篇文章以一个问题作为标题,答案将永远是否定的。当然,这是一个幽默的法律,而不是实际的法律。尽管如此,我内心的反叛者不会错过与法律相抵触的机会。因此,这个标题的答案是一个闪亮的“视情况而定”。我肯定你没想到会这样。

是否应该获得硕士学位的问题是非常个人化的。这将取决于个人喜好、学习风格和职业目标。这就是为什么我认为试图在网上寻找答案是无效的。尽管这仍然是 Quora 上最常被问到的问题之一。

在本文中,我不会列出支持或反对获得数据科学硕士学位的理由。相反,我会给你一些建议,告诉你做这个决定时应该考虑什么。

请记住,我制定这些标准的前提是,你希望在获得这个学位后,在一家商业公司担任数据科学家。如果你想留在学术界,它可能不适合你。

以下是我认为你应该考虑的:

并非所有的学位都是平等的

数据科学是一个热门话题,每天都有几个数据科学学位冒出来。确保你所接受的教育有足够的质量。最终起作用的不是学位的名字。这是教育。检查教育质量的最好方法是检查教师和课程。尝试回答以下问题:

  • 导师是受人尊敬的学者吗?比如,他们对学术界有贡献吗?他们是活跃的研究人员吗?还是仍然停留在 10 年前的技术上?
  • 课程是否足够?当然,要回答这个问题,您需要对什么是数据科学以及所需的技能有一个大致的了解。我知道你可能愿意相信学校已经考虑过这个问题,并且创建了一个完整的、完美的课程,但是你还是应该检查一下。列出一张你绝对想学的技能的清单,并与学校提供的技能进行交叉核对。与其花两年时间学不到你想学的东西,不如谨慎一点。
  • 程度够动手吗?这是所有问题中最难回答的。判断该学位是否技术性太强,是否对实践技能不够重视的一个方法是询问以前或现在的学生。你可以在 LinkedIn 或者你的朋友网络中找到他们。

你学校的名字可能很重要

与前一点相关,如果有许多学校提供同名学位,考虑到两个候选人之间的其他一切都是一样的,学校的声誉可能会影响招聘决定。这并不是说千万不要考非名校的硕士。我的意思是,评价每一个学位都有它的价值。简而言之,如果你所在国家顶尖大学的数据科学学位在你未来雇主的眼中为你的个人资料增加了 10 分,那么一个不太受欢迎/知名学校的学位可能只会增加 5 分。确保当你计划你的道路时,考虑到这一点。

获得一份数据科学工作不仅仅是技术知识

公司寻找能够应对现实生活中的挑战并快速适应的有能力的人。如果这就是你想要的,那么拥有一个相关的学位可能不够有效。你申请的公司可能仍然会聘用没有学位但能更好地展示自己能力的人。相关的能力可以是人际交往技能、他们参与的项目、领域经验等。

每个公司都有不同的优先事项

如果你想申请一个特定的公司/行业,我会说在投资硕士学位之前,一定要了解他们的要求。也许他们可以只给你一些基本知识,并在途中教你。

你为什么要这么做?

一定要明白你为什么要考虑硕士学位。是因为你做了一些研究,你确信这将有利于你的职业生涯,还是因为你从互联网上的人那里听说,为了得到一份数据科学的工作,这是必须的?做对自己的事,而不是平常的事。仅仅因为不确定还能做什么而开始攻读数据科学学位可能会被证明是徒劳的。

毕竟,在一个官方学位上投入金钱和时间是一个重大的决定。对一些人来说,这将是一场伟大的比赛,而对一些人来说,这可能是不必要的分心。我想说的要点是:在简历中有一个相关的官方学位总是有利的,但你必须将这种好处与你的生活成本进行比较,然后决定是否值得。没有人能替你做这个决定。

我希望这有助于澄清你在做这个决定时应该记住的一些重要的事情。祝你好运!

👉对数据科学领域以及如何开始学习感到困惑? 免费参加数据科学入门迷你课程

该不该跳 Python 的船,搬去茱莉亚?

原文:https://towardsdatascience.com/should-you-jump-pythons-ship-and-move-to-julia-ccd32e7d25d9?source=collection_archive---------3-----------------------

意见

是应该为了朱丽亚的表现而抛弃 Python,还是朱丽亚的速度只是精心炒作?

(python 徽标由http://python.org/提供,julia 徽标由http://julialang.org提供,北海巨妖 src = http://cleanpng.com)

在过去的几年里,Python,一种用 C 语言编写的解释语言,越来越受欢迎。虽然 Python 肯定是一种有用的语言,从一开始就相当受欢迎,但这种受欢迎程度的飙升通常要归功于 Python 在机器学习和统计分析方面的出色能力。然而,随着时间的推移,新的语言应运而生,试图取代 Python,为机器学习创造普遍更快的体验。属于这一类的最有前途和最受欢迎的语言之一是 Julia。

Julia 是一种多范式、静态类型的通用语言,它是基于机器学习和统计学而构建的。大多数 Julia 用法背后的主要动机往往是 Julia 的速度,但我认为重要的是要记住仅速度一项就有多少变量。这甚至还没有触及到该语言的其他能力或缺陷。

Python 笔记本

朱丽亚笔记本

概述

虽然速度当然很重要,甚至在机器学习的环境中更重要,但我认为在讨论性能的同时讨论其他障碍和优势也很重要。在跳 Python 船之前应该问的一个大问题是

朱莉娅有什么问题?

如果权衡超过了表现这一单一的好处,那么学习一门新语言是没有意义的。Julia 确实有一些问题,对于某些开发人员来说,这些问题可能不一定使切换成为最佳选择。

Python 和 Julia 之间的转换中丢失的第一个,也是最大的一个东西是

包裹。

虽然 Julia 确实有一些很棒的包值得一试,也有一个很棒的包管理器来帮助它们,但是这些包的范围远不如 Python 成熟。许多 Julia 包严重缺乏文档,有依赖问题,或者错综复杂,分割得太多,以至于你必须添加 50 个包才能完成一件事。虽然这肯定是一个很大的缺点,但应该注意的是,Julia 没有 Python 所拥有的模块王朝,因为 Python 作为一种语言要成熟得多。随着时间的推移,这个问题几乎肯定会得到解决,随着伟大的开发人员致力于这种语言,再加上 Julia 周围的奇妙和快速发展的社区,这可能不会是一个很长时间的大问题。我理解为什么一些朱利安可能会指出“PyCall.jl”是一个潜在的解决方案,但我不同意这种立场,因为对所有东西都使用 PyCall 比对所有东西都使用 Python 要慢,所以为什么不在这一点上使用 Python 呢?

Julia 的另一个显著“缺点”是它的范式。虽然 Julia 确实是一种支持许多泛型的多范式编程语言,但 Julia 的语法本质上是静态的,这意味着在大多数情况下,Julia 代码将属于函数范式。虽然我敢肯定 Lisp、R 和 Haskell 的粉丝们会高兴得跳起来,但是看看最流行的编程语言列表,就会明白为什么转换到这种范式会令人难以置信地不舒服,即使对于有经验的程序员来说也是如此。因此,虽然这对我或其他人来说可能不是一个缺点,但肯定会让那些对这种语言没有太大兴趣的人望而却步。

很可能我们都熟悉 Python,所以我不打算花太多时间来解释为什么您可能想从 Python 切换到 Julia。然而,我认为 Python 有一些缺点,应该客观地提出来,以便确定潜在的转换编程语言的利弊。

首先,我确信我们都听说过,Python 是一种解释型语言。虽然肯定有解决方案来解决这个问题,使用各种工具来获得编译后的可执行文件,以及更快的速度,但这些都不是使软件包更快或分发软件的万无一失的方法。虽然我并不特别热衷于“Python == 'slow '”这一潮流,但不可否认 Python 的速度不够快。幸运的是,Python 通过 C 语言的解释确实把它放在了一个独特的位置,因为它可以用来从高级接口操纵和调用 C 代码。

虽然这对 Python 来说是一个很大的优势,但并不是所有的数据科学工作都是在已经用 C 编写的模块中完成的,有时 Python.h 头文件的附加层也会降低计算速度,破坏 C 的出色性能。

“由你决定”

虽然速度绝对重要,但我想重申,它绝对不是一切。同时使用 Python 和 Julia 有很多显著的优势,其中一些甚至是主观的。例如,我对 Python 中的缩进语法恨之入骨,所以在 Julia 中使用以分隔符结尾的函数是我主观的偏好。

def func:
    print("function body")
function func
println("I can put syntax here")
    println("Here")
        println("Or here, without any errors.")end

我想指出的另一件事是 Julia 的多态调度和 Python 的更简单的语法。所有这些都是为了说明,虽然性能很重要,但在选择使用哪种语言时,一种语言中的许多特性可能是更重要的因素。不仅如此,您还可以挑选在您当前的场景中使用哪种语言,因为自然有一些事情一种语言会比另一种语言更好。

另一个有趣的事情是,我以前在 Julia 中提到过,使用 Python 作为 Julia 的接口,而不是与 c 接口。这样做的好处是能够更快地编写快速代码,同时仍然保持类似的性能。幸运的是,我甚至创建了一个包来这样做,这样您就可以通过 PyPi 进行安装。

sudo pip3 install TopLoader

[## emmettgb/TopLoader

你好,装载愉快!您可以使用以下命令安装 TopLoader:sudo pip 3 立即从 TopLoader 安装 TopLoader 您可以…

github.com](https://github.com/emmettgb/TopLoader)

你选择的语言不一定是二进制的。Julia 的一个优点是,考虑到 Julia 的大数据能力和浮点精度,您可以保留对 Python 的使用,并像使用 Scala 一样使用 Julia。Julia 甚至有 BigInt 和 BigFloat 类型来处理比一般熊大的数字。

速度测试

(src =茱莉亚计算https://julialang.org/benchmarks/

实际速度方面,我已经把朱莉娅的基准放在上面了。正如我们从这个基本基准中看到的,Julia 倾向于徘徊在 Go 的性能附近,同时保持一点点的一致性。有趣的是,在极少数情况下,Julia 甚至可以超越 C 和 Rust。虽然这肯定是一个伟大的壮举,但这里的目标不是比较 Julia 和 C,而是比较 Julia 和 Python。

测试设置

为了保持两种比较之间的一致性,我将使用 Julia 的语法表达式来强制语言的类型更像 Python。如果你想进一步了解如何做到这一点,以及更熟悉 Julia 的调度,我有一篇我很自豪的文章,它会告诉你你需要知道的一切:

[## 用静态类型语言将 Julia 转换成 Python 和 Duck-Type

通过结合 Julia 富有表现力的语法和令人敬畏的调度,将 Julia 变成 Python。

towardsdatascience.com](/turn-julia-into-python-and-duck-type-in-a-statically-typed-language-119f708936ff)

对于我的迭代测试,我在 Julia 中创建了这个函数:

function LinearRegression(x,y)
    # a = ((∑y)(∑x^2)-(∑x)(∑xy)) / (n(∑x^2) - (∑x)^2)
    # b = (x(∑xy) - (∑x)(∑y)) / n(∑x^2) - (∑x)^2
    if length(x) != length(y)
        throw(ArgumentError("The array shape does not match!"))
    end
    # Get our Summations:
    Σx = sum(x)
    Σy = sum(y)
    # dot x and y
    xy = x .* y
    # ∑dot x and y
    Σxy = sum(xy)
    # dotsquare x
    x2 = x .^ 2
    # ∑ dotsquare x
    Σx2 = sum(x2)
    # n = sample size
    n = length(x)
    # Calculate a
    a = (((Σy) * (Σx2)) - ((Σx * (Σxy)))) / ((n * (Σx2))-(Σx^2))
    # Calculate b
    b = ((n*(Σxy)) - (Σx * Σy)) / ((n * (Σx2)) - (Σx ^ 2))
    # The part that is super struct:
    predict(xt) = (xt = [i = a + (b * i) for i in xt])
    (test)->(a;b;predict)
end

同样,我用 Python 创建了这个类来实现同样的目标:

class LinearRegression:
    def __init__(self,x,y):
        # a = ((∑y)(∑x^2)-(∑x)(∑xy)) / (n(∑x^2) - (∑x)^2)
        # b = (x(∑xy) - (∑x)(∑y)) / n(∑x^2) - (∑x)^2
        if len(x) != len(y):
            pass
        # Get our Summations:
        Σx = sum(x)
        Σy = sum(y)
        # dot x and y
        xy = dot(x,y)
        # ∑dot x and y
        Σxy = sum(xy)
        # dotsquare x
        x2 = sq(x)
        # ∑ dotsquare x
        Σx2 = sum(x2)
        # n = sample size
        n = len(x)
        # Calculate a
        self.a = (((Σy) * (Σx2)) - ((Σx * (Σxy)))) / ((n * (Σx2))-(Σx**2))
        # Calculate b
        self.b = ((n*(Σxy)) - (Σx * Σy)) / ((n * (Σx2)) - (Σx ** 2))
        # The part that is super struct:
    def predict(self,xt):
        xt = [self.a + (self.b * i) for i in xt]
        return(xt)

你可能会注意到我用 dot()和 sq()来代替。*对于逐元素乘法,和。元素式平方的^。这些功能如下:

def dot(x,y):
    lst = []
    for i,w in zip(x,y):
        lst.append(i * w)
    return(lst)
def sq(x):
    x = [c ** 2 for c in x]
    return(x)

数据

对于我的数据,我在 Julia 中生成了一个 500,000 的模糊数据帧,如下所示:

我还做了一个有 60 万个暗点的测试数据框架:

为了保持一致性,我保存了数据帧,并使用 Pandas 将它们读入 Python:

最终时机

当然,为了计时 Python 结果,我将使用 IPython %timeit magic 命令。至于 Julia 的结果,正如你所料,我将使用@time 宏。结果如下:

朱莉娅

计算机编程语言

虽然这是一个很好的比较,而且 Julia 在计算上确实节省了大约 30%的时间,但是我想

“向上反”

我们试试 10,000,000 个 dims。

朱莉娅

计算机编程语言

R.I.P. Python

结论

虽然 Python 能够如此出色地击败 Julia 令人印象深刻,但对于这个 Julia 胜过 Python 的真实机器学习示例,肯定有一些东西值得一提。我认为这也很好地说明了我之前所说的,Julia 在处理大数据方面非常有用。我想如果这个测试教会了我什么的话,那就是 Julia 在机器学习的世界里绝对有一席之地。即使 Julia 不能取代 Python,它也肯定能取代 Scala 和许多其他类似的语言。

尽管这种语言有其独特之处,并且在不断发展,但性能肯定是存在的。尽管现在可能还不是开始 Python 编程的时候

(尚未)

(我是开玩笑的),或者可能永远也不会为了机器学习而放弃 Python,同时我也找不到不学习 Julia 的好理由。幸运的是,如果您已经熟悉 Python,那么学习 Julia 应该相对简单,因为语法非常相似。谁知道呢——也许你也会在朱莉娅身上找到一些你喜欢的东西!总的来说,Julia 在机器学习领域的未来非常令人兴奋。我认为,任何希望拓宽自己视野的数据科学家都应该去看看,甚至为 Julia 语言这个日益壮大的庞然大物做出贡献。

你应该呆在家里过新冠肺炎吗?

原文:https://towardsdatascience.com/should-you-stay-at-home-for-the-covid-19-a281156c9597?source=collection_archive---------27-----------------------

用简单的理论模型分析限制措施的效果。

新冠肺炎疫情及其社会影响是目前推特上的热门话题。没有人没听说过这件事。在这种社会距离和限制的情况下,一些人只是想着自己,而忽视了政府的建议甚至限制。如果你正在读这篇文章,你可能不是这些人中的一员,但是,你应该警告那些你认识的符合前面描述的人吗?让我试着说服你。

SIR 模型

流行病学最简单和最著名的模型之一是 SIR (易感-感染-康复)模型,这是一组描述这三种状态在人群中演变的微分方程。

新冠肺炎代表(来源

(不要害怕下面的方程,它们只是为了介绍模型,你不需要深入理解这些方程就能理解整篇文章)

SIR 微分方程系统

在上面写的微分方程中, S 是易感人群的存量, I 是感染人群的存量, R 是康复人群的存量。显然,系统的动力学与易受感染的病原体被感染以及被感染的病原体被治愈的概率有关。因此,在微分方程中, β 代表感染率, γ 代表恢复率。最后, V 表示个体分布的体积。这是一个更技术性的细节,但很容易理解,这个体积越大,个体之间的接触就越少,因此发生的感染就越少,从而导致动力学更慢。

总而言之,这些是模型的参数

  • S: 易感人群存量
  • 一:感染人群存量
  • R: 恢复人口存量
  • β: 感染率(单位时间内个体被感染的概率)
  • γ: 恢复率(单位时间内个体恢复的概率)
  • V: 系统的体积(与两个个体接触的概率有关)

尽管该模型可以解析求解,但我们可以基于 Gillespie 算法使用数值方法求解。我们开始吧!

SIR 模型的结果

考虑分布在体积为 V=10β=0.5 / 100γ=10 / 100N=10⁵ 个体群体,我们得到以下结果:

用 Gillespie 算法实现 SIR 模型。

正如我们所看到的,考虑到这些参数,该疾病将会爆发,并且在大约 30 天内,感染高峰将达到近 50 %的人口。在这个模型中,我们没有考虑疾病的死亡率,但应该强调的是,卫生系统肯定会崩溃,因为我们连续几天看到如此大量的感染者。为了避免这种情况,那肯定会是灾难性的,政府采取措施来‘使曲线变平’,这是一个近来广为人知的概念。基本上,我们的目标是降低感染人数的峰值,这样卫生系统就不会崩溃。正如我们接下来将看到的,感染人数峰值的下降与疫情结束的延迟有关。出于这两个原因(降低峰值和延迟疫情结束),这被称为“平坦曲线”。

来源

用 SIR 模型模拟限制措施的效果

现在,我们可以将政府采取的限制措施建模为在某个时间点有效降低感染率β。考虑到在 t=25 时,即疫情达到上一次模拟得到的峰值前 5 天,采取限制性措施,有效降低一半感染率,得到以下结果, β'=β/2。

t=25 后感染率β'=β/2 变化的 SIR 模型

以这种方式模拟的限制措施的效果是明显的。通过将感染率降低到其原始值的一半,感染的峰值达到了人口的 25%,这也对应于在没有限制措施的情况下获得的值的一半。

快速应用这些措施有多重要?

为了解决这个问题,我们可以运行不同的模拟,并在不同的时间应用约束措施。例如,我已经考虑在 t=30、25、20 和 15 时应用这些措施,它们的效果与以前一样,将感染率降低到其原始值的一半。现在我们把重点放在受感染人群的进化上,所以没有必要画出易感人群和康复人群的比例。

分析应用措施的反应时间

从上图可以看出,实施禁闭措施的时间越长,效果越差。然而,尽管这些措施采取得相当晚(橙色线),但这些措施的效果是显著的,将峰值从近 50%降低到 35%左右。另一方面,如果及早采取措施,疫情的高峰期可以大大减少并及时转移。然而,也可以看到,这些措施除了降低感染高峰之外,还推迟了疫情的结束。这是一种不可避免的情况,但我们必须记住,我们的优先事项是使曲线变平,以免卫生系统饱和。然而,这种延迟似乎是因为恢复速度保持不变,但通过降低峰值和不使卫生系统饱和,我们可以希望这一速度增加(疾病治疗的新进展,卫生工作人员的更多经验等)。

作为一个更技术性的细节,可以观察到,如果在相当早的时候应用这些措施,这种流行病将发展成为一种新的流行病,具有新的感染率(紫线)。

实际遵守措施有多重要?

我们认为,通过应用这些隔离措施,流行病的有效感染率将下降到其原始值的一半,这可能或多或少是现实的。本文的目的不是提出一个现实的模型来预测模型的演变,而是说明限制措施的重要性。

在这个例子中,进一步考虑到,通过非常认真地采取措施,很少有人会走出家门,因此有效感染率将趋于零。因此,我们可以通过在将措施设置为 β'=0 后运行有效感染率的模拟来研究更认真地采取措施的影响。

当采取措施后传染率完全消失时流行病的演化

结果显示,采取措施后,感染人数迅速下降。如前所述,观察到越早采取措施,受感染人口的峰值就越小。而且我们可以看到疫情的结束是提前了而不是推迟了,之前的情况就是这样。然而,这种在应用这些措施后没有新感染的极端情况在现实生活中是不可能实现的,因为这需要对整个社会进行完全和完美的限制。

西班牙的现状

除了通过媒体和社交网络传播的信息,欧盟开放数据门户中也有可用的数据集。通过对这些数据进行适当的处理,可以估计每日新增病例和总病例的变化。在这里,我将展示西班牙的进展,西班牙是世界上感染病例总数第四多的国家。

新的感染从爆发演变而来。

正如我们所看到的,西班牙新发现的病例正以恒定的比率呈指数增长,具体为 0.35。事实上,对数标度帮助我们形象化这种趋势,因为它是一条直线。这种趋势正是我们想要避免的,因为如果这种情况持续几天,卫生系统就会崩溃。

我们还可以看看总病例的演变,它最终会像一条s 形曲线一样饱和。

总感染数从爆发开始演变。

很明显,我们已经远离了饱和点。在这种情况下,无法进行适当的指数拟合,因为在对数标度中可以清楚地看到,存在具有不同生长率的区域。这方面的好消息是,当前的增长率小于最初的增长率。

结论是什么?

首先,请记住,本文的目的不是提出一个新冠肺炎疫情的现实模型或预测其演变的工具。这篇文章的目的是展示一个研究流行病的最简单的模型,并用它来说明世界各地正在采取的隔离措施的重要性。

话虽如此,作为第一个结论,我们已经看到,考虑到适当的流行病(这意味着在给定的感染率和恢复率下,爆发存在),感染人口的比例呈指数增长。然后,如果不采取措施,这种指数增长将继续下去,直到大部分人口受到感染。在实际情况下,这将使卫生系统崩溃,导致高死亡率事件。

然后,我们将禁闭措施纳入模型,以研究其效果以及它们如何依赖于两个特征:实施措施的时间和措施的力度(可以理解为措施的限制性或接受措施的人数)。第一种情况的结果表明,对于早期应用的措施,获得的感染峰值显著降低,尽管流行病的结束被延迟。在第二种情况下,我们看到,更强有力的措施除了降低感染高峰之外,还促进了疫情的结束。

因此,最后的结论是,最好的选择是尽早采取最强有力的措施。

想想看

我想以一个想法结束我的发言:实施措施的时间关系到科学家和政治家的工作,但措施的力度部分取决于整个社会。也许限制措施采取得有点晚,但我们有能力使它们更有效。

你应该读机器学习硕士吗?

原文:https://towardsdatascience.com/should-you-take-a-masters-msc-in-machine-learning-c01336120466?source=collection_archive---------1-----------------------

包含来自理学硕士毕业生的想法和意见

安德烈·亨特在 Unsplash 上的照片

开始

答几周前,一个好奇的人在读了我的一篇文章后找到了我。联系我的主要原因是想了解我对一个硕士学位是否足以在人工智能行业建立职业生涯的看法,或者应该用一个博士学位来补充这个硕士学位。

简单的回答是没有。

一个机器学习的理学硕士学位使你具备足够的领域知识,在大多数实际环境中做出贡献。

但是——是的,有一个但是——你的职业发展水平可以由你拥有的学位类型来定义。

围绕机器学习有大量的炒作,大量的个人正涌向学术机构以获得 ML 内部的学位,包括我自己。

对于你想追求什么样的高级资格,做出正确决定的重要性怎么强调都不为过。

为了有助于更容易做出决定,并提供一些清晰度,我将提出攻读理学硕士的理由,并以我个人对这场辩论的看法作为结束。

我将利用三个标准作为指路明灯。

里士满·阿拉克的引导信标

对于那些对理科硕士毕业生的满意度感兴趣的人,只需向下滚动到“知识”部分。

介绍

机器学习硕士是建立理论和实践知识的最佳方法之一。最后,你会获得公认的高级学位。

只要你有数学、计算机科学、物理、机械或电子工程等学科的本科学习背景,获得机器学习硕士学位的道路会非常平坦。

英国的理学硕士通常需要一年的全日制学习,而非全日制的资格认证可能需要 2-4 年的时间。在美国,理学硕士的平均时间长度似乎约为 2 年。

我找到了一些很棒的资源,包括美国大学的链接和信息。 第一资源 是最近由Stacy Stanford在 2020 年写的,文章列出了 10 所大学,而 其他资源 ,由 写的

几个机器学习的理学硕士项目在该领域的教学中采取了一种一般化的方法。这意味着理学硕士学生将接触到各种主题,如机器人学、语言学、自然语言处理(NLP)、计算机视觉、编程、软件设计、信号处理、语音识别等。这种资格的普遍性在不断变化的行业中可能是有利的。

让我们使用我们的指导信标来进一步分析一个机器学习硕士的案例。

收入和职业潜力

理学硕士课程的通才性质使个人具备了许多雇主目前正在寻求的多面性。对 ML 领域有一个总的了解的好处是你不局限于广告中的入门级工作职位。

在完成我的理学硕士学位后,我能够申请一些职位,如数据科学家、计算机视觉工程师、机器学习工程师和 NLP 工程师。我需要大部分广告职位的原因是因为我的理学硕士课程足够详细地介绍了这些主题。

对于机器学习工程师的角色,我在 LinkedIn 上搜索的大约 30%的角色要求申请者拥有理学硕士学位。我使用 Paysa 来获得更多关于 ML 工程师工资的调查信息。根据对超过 300 毫升的 工程职位 的调查,17%的人拥有理学硕士学位,12%拥有理学学士学位,28%拥有博士学位。考个理学硕士肯定能打开更多的门。

分析超过 15,000 名数据科学家档案的调查我们可以观察到,近一半的档案拥有学士学位,14%拥有硕士学位。

有些人可能会认为,从统计数据来看,许多数据科学家角色只需要一个 BSc,这是真的。

与其他 ML 工程角色相比,数据科学对技术要求不高。尽管对 ML 从业者的需求可能会很高,但也有大量的毕业生希望获得入门职位。

关键是从人群中脱颖而出,一个理学硕士学位肯定会让你领先于拥有学士学位的同行。

现在谈谈收入潜力。

上面提到的对 ML Engineering profiles 和 Data Scientist profiles 的调查显示,这两个职位的平均工资分别为 94,510 美元和 99,558 美元。这两个职位的最高收入都超过了 12 万美元。

要成为一名高收入者,可以肯定地认为经验是一个决定性因素,另一个关键因素可能是申请人在机器学习方面的资格有多高级。

应该提到的是,这项调查的重点是主要位于美国的概况。

影响

受过良好教育的机器学习工程师或数据科学家在团队、企业或初创公司中蓬勃发展,会带来实质性的积极商业影响。

这种影响很可能决定一个组织的生存能力和成功。

理学硕士使个人具备在组织内创造和产生重要影响所需的技能。我所指的技能不是技术性的,而是软技能。

例如,理学硕士为你提供了一个机会,通过提交期末论文的过程来培养表达技能。

根据我的经验,我有三个不同的场合来展示我的论文。一个包括由教授和行业专家参加的展览,另一个涉及向机器学习教授和讲师进行最终演示。

[## 作为机器学习工程师你需要的 5 个软技能(以及为什么)

包括成为任何劳动力的有用组成部分的提示

towardsdatascience.com](/5-soft-skills-you-need-as-a-machine-learning-engineer-and-why-41ef6854cef6)

关于论文的主题,理学硕士给学生带来的另一个影响是通过项目将机器学习应用于特定行业或流程的独特机会。

在我攻读理学硕士期间,学生们与医院和诊断部门合作创建了计算机视觉系统,该系统加速了癌细胞和肿瘤的分类过程。

我承担了一个项目,涉及开发一个对四足动物(四条腿的动物)进行姿态估计的计算机视觉系统。该项目的进一步目标是开发一个系统,以帮助改善兽医步态分析程序。

知识

对于这一部分,我决定联系两个已经从机器学习和计算机视觉理学硕士学位毕业的人。我没有提供我对你从理学硕士那里获得的知识量的想法,而是把任务交给了他们。

下面是我们特邀嘉宾的背景简介。

  • kaushub Krishnamurthy 目前是澳大利亚悉尼的一名计算机视觉机器人工程师。
  • Ignacio Hernández Montilla 目前是西班牙马德里的一名计算机视觉研究工程师。

以下是伊格纳西奥的声明:

“硕士学位教你所有机器学习炒作背后的理论。目前有很多“机器学习工程师”和“数据科学家”,他们只上过一两门在线课程。

这些在线课程只是向你介绍机器学习有吸引力的部分。另一方面,硕士学位提供了 的机会,除了关键的数学思维 之外,还能教给你数据科学家或 ML 工程师需要的知识。”

以下是来自 Kausthub 的声明:

“为了能够做出明智的决策(为了研究或商业应用),我需要通过从头开始构建我的各种计算机视觉应用知识来进一步发展我的直觉。

是的——这意味着涉水深入数学,坦率地说,这不是我下班后轻松阅读的第一选择——参加一个硕士项目是激励我在计算机视觉的所有领域工作的一种方式,这将把我带到下一个水平

在理学硕士课程结束时,我发现自己喜欢数学的严谨性,能够恰当地理解和评估最新研究中做出的选择,这使我能够对我之前刚刚申请的应用程序做出明智的决定,因为这是教程告诉我要做的。”

不足之处

到目前为止,你可能已经了解了获得机器学习硕士学位的一些主要好处。为了公平竞争,我将提供一些我认为应该指出的缺点。

  • 学术资助始终是个人选择不继续深造的一个重要因素。一个 MSc 课程绝对是一个成本高昂的投资,比如我 2018-2019 年上的 MSc 机器学习课程价格是 10300。对于国际学生来说,这个数字超过了 2 万。
  • 调整期可能会更长一些。决定重返校园的人可能会发现很难适应需要长时间学习的学术生活方式。那些在重返校园前已经工作了几年的人肯定会发现这种变化是巨大的。下面是一篇文章,详细介绍了我在适应学术生活方式方面的个人经历。

[## 拿了一个机器学习的硕士学位,我(非常)没有准备

我从全职到人工智能硕士生过渡的探索。

towardsdatascience.com](/took-a-masters-in-machine-learning-and-i-was-very-unprepared-7aba95f044a8)

  • 参加全日制理学硕士课程会有一段时间没有收入,如果你参加的是业余项目,情况可能就不一样了。
  • 一种奇怪的被遗忘的感觉。对于那些年纪很大才获得理学硕士学位的人来说,在社交活动中,当你的朋友和同事抱怨工作生活和与学术无关的话题时,这可能会产生一种孤立感。

个人观点

如果你有时间和资金接受为期一年的挑战,以提高你的机器学习技能和知识,那么攻读机器学习相关主题的硕士学位可能是正确的决定。

理学硕士课程可以带来很多好处,尤其是在职业发展或变化方面。这需要做很多艰苦的工作,这是你必须准备好处理的事情。

至于那些可能无法全职参与任何学术项目的人,许多大学都提供非全日制的理学硕士课程,通常在两到五年内完成。对于资金有限的人来说,这种选择也是一种更便宜的选择。

最后,应该提到的是,理学硕士并不能完全保证职业发展。

对于那些没有机会考虑机构教育的人来说,Coursera 和 Udacity 等平台上发布了几个在线课程。

这些在线课程可能没有实际学位那么深入。尽管如此,它们确实为个人提供了机器学习方面的必要信息和实用知识。还有一个好处是,许多在线平台在完成课程后会提供认可的证书。以下是几个。

[## 深度学习专业化——deep Learning . ai

深度学习专业化是由人工智能的全球领导者和联合创始人吴恩达博士创建和教授的

www.deeplearning.ai](https://www.deeplearning.ai/deep-learning-specialization/) [## 机器学习|课程

机器学习是让计算机在没有明确编程的情况下行动的科学。在过去的十年里…

www.coursera.org](https://www.coursera.org/learn/machine-learning?utm_source=gg&utm_medium=sem&utm_content=07-StanfordML-ROW&campaignid=2070742271&adgroupid=80109820241&device=c&keyword=machine learning mooc&matchtype=b&network=g&devicemodel=&adpostion=&creativeid=369041663186&hide_mobile_promo&gclid=EAIaIQobChMI7Pnh_aDt6AIV2u3tCh1X2A9pEAAYASAAEgJen_D_BwE) [## Udacity |学习

“Nanodegree”是 Udacity 的注册商标。2011–2020 uda city,Inc .要兑现此优惠,请完成…

learning.udacity.com](https://learning.udacity.com/be-in-demand-ai/eu/?utm_source=gsem_generic&utm_medium=ads&utm_campaign=8778926767_c&utm_term=89916940033_UK&utm_keyword=%2Bmachine %2Blearning %2Bcourse_b&gclid=EAIaIQobChMI7Pnh_aDt6AIV2u3tCh1X2A9pEAAYAiAAEgK6uPD_BwE)

感谢您花时间阅读这篇文章,我希望它是有益的。

对于那些想看更多文章的人来说,下面是我写的一些你可能会感兴趣的文章。

[## 该不该考机器学习的博士?

探索攻读机器学习博士学位的好处

towardsdatascience.com](/should-you-take-a-phd-in-machine-learning-79530e1cb01c) [## 作为机器学习工程师你需要的 5 个软技能(以及为什么)

包括成为任何劳动力的有用组成部分的提示

towardsdatascience.com](/5-soft-skills-you-need-as-a-machine-learning-engineer-and-why-41ef6854cef6)

想要更多吗?

  1. 成为推荐媒介会员,支持我的写作
  2. 订阅 在我发表文章时得到通知
  3. 通过 LinkedIn 联系我
  4. 奥莱利 跟我学
posted @ 2024-10-16 09:01  绝不原创的飞龙  阅读(272)  评论(0)    收藏  举报