TowardsDataScience-博客中文翻译-2020-六十五-
TowardsDataScience 博客中文翻译 2020(六十五)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
如何不预测和防止客户流失
原文:https://towardsdatascience.com/how-to-not-predict-and-prevent-customer-churn-1097c0a1ef3b?source=collection_archive---------6-----------------------
学习生存分析技术,预测客户是否以及何时可能流失,以及预期的潜在损失

奥斯汀·凯梅尔在 Unsplash 上的照片
顾客是任何企业的面包和黄油。无论是 B2B 商业模式还是 B2C,每个公司都在努力争取一个流失最小的粘性客户群,以确保持续的、经常性的收入流。
但是,如何确定确保客户长寿的具体客户特征呢?如何识别“风险”客户,即那些可能流失的客户?给定客户流失的概率,我们什么时候能期待他流失?更重要的是,我们能在“风险”客户身上投资多少来留住他们?
如果一个企业对最大限度地减少客户流失感兴趣,这些都是理想情况下应该回答的问题。我会尽力帮你找到这些问题的答案。
分析非合同环境(如零售)中的客户流失是一项重要的工作,因为这里无法对流失进行单独定义。到目前为止已经购买了 X 次的顾客可以再次购买,也可以永远不再购买。已经提出了各种方法来解决这个问题,包括异常检测和寿命价值(LTV)分析。我曾在的另一篇文章中以非合同的形式报道过 LTV 分析。
然而,合同或基于订阅的模型更容易分析,因为在这些场景中,客户流失是在给定时间点的二元分类问题。如果一个客户不更新他的订阅,那么他毫无疑问已经发生了变化。对此不可能有两种选择:要么客户是活跃的,要么客户已经变得活跃。在本帖中,我们将介绍适用于订阅模式的客户流失分析。
传统的客户流失建模方法利用逻辑回归、随机森林或梯度下降推进来分析和预测客户流失。但是,我们将利用生存分析技术来获得与客户流失相关的更多信息。这将有助于我们回答本文开头提出的进一步的问题。
但是什么是生存分析呢?
生存分析是统计分析的一个分支,它解决诸如“特定事件发生前多久”的问题,即,它是一个“事件发生时间”模型(与事件发生的概率相比)。传统上,生存分析大量用于医学和生命科学领域,以确定个体或其他生物有机体的预期寿命。
生存分析适用于我们可以定义的情况:
- “诞生”事件:对我们来说,这将是客户与公司签订合同
- “死亡”事件:对我们来说,“死亡”发生在客户不再续订时
虽然逻辑回归和决策树适用于二元分类问题(客户是否会流失?),生存分析不止于此来回答客户什么时候会流失。如果我们不希望客户马上流失,这并不意味着他永远不会流失。如果不是现在,他以后很有可能会流失。在这种情况下,生存分析可以通过预测他们在未来不同时间点的生存(或流失)来揭示这些“被审查”的客户。
这种处理数据“审查”的能力使生存分析成为优于其他回归和基于树的模型的技术。
经过检查的数据
在传统意义上,审查是指在观察期内失去对个人的跟踪,或者在此期间没有观察到感兴趣的事件。这些数据被“审查”,因为每个人都会在未来某个时间点死亡或离开/取消订阅;我们只是错过了那个信息。仅仅因为我们没有观察到他们取消联系或订阅并不意味着他们永远不会。我们不能等到他们取消订阅才开始分析。这就是所谓的权利审查。
其他类型的审查包括左审查和间隔审查。前者是指我们不知道一个人何时成为我们的客户,因为他的“出生”事件发生在我们的观察时间段之前。相比之下,间隔-审查发生在数据以特定的时间间隔收集,不构成一个连续的观察期。因此,一些生命/死亡事件可能会在数据中被遗漏。
术语
- 事件时间:感兴趣的事件发生的时间——在我们的例子中是订购的流失或不续订
- 起始时间:客户开始服务/订阅的时间
- 事件发生时间:事件发生时间和起源时间之差
- 生存函数:这给出了我们感兴趣的事件在时间
t之前没有发生的概率。换句话说,它为我们提供了事件发生时间值大于t的人口比例 - 危险函数:这给出了我们感兴趣的事件在特定时间发生的概率。生存函数可以从风险函数中导出,反之亦然
- 风险比是我们感兴趣的事件在两个不同协变量组(如已婚或未婚)中发生的概率比。例如,风险比为 1.10 意味着协变量的存在会使风险事件的概率增加 10%
- 协变量是指生存分析中的预测因子、变量或特征
生存分析技术被设计成通过两个主要的数据点来识别生存函数:持续时间或事件发生的时间,以及一个二元标志,即对于每个观察,我们感兴趣的事件是否已经发生。生存分析并不真正关心事件发生的时间或起源的时间。相反,事件信息的时间是最重要的。
生存分析和信用风险分析
已经进行了几项研究来确定生存分析是否也可以预测客户违约的概率和预期时间。但是,相对于传统的逻辑回归方法,没有观察到显著的改善。此外,银行监管机构和巴塞尔协议要求一种易于理解和解释的信贷决策方法,这一事实使得逻辑回归在这些情况下成为更好的选择。
生存/风险函数估计
我们将涵盖两个最完善的,有文件证明的,实践中的模型,通过观察到的数据来估计生存和风险函数。
卡普兰-迈耶生存分析
虽然我们没有人口的真实生存曲线,但我们可以通过一种称为 Kaplan-Meier 估计量的强大的非参数方法,根据观察到的数据来估计人口的生存函数。KM 存活曲线在 x 轴上绘制时间,在 y 轴上绘制估计的存活概率。
KM 生存分析只需要两个输入来预测生存曲线:事件(搅动/非搅动)和事件发生时间。请注意,KM 没有使用其他特征或预测因子来评估生存函数。
考克斯比例风险(CPH)模型
在现实生活中,除了事件和持续时间数据,我们还有人口中个体的各种其他协变量(特征或预测因素)。很有可能这些额外的协变量也会影响我们感兴趣的事件在未来特定时间点不发生的概率(称为生存概率)。例如,在电信环境中,这些附加特征可以包括性别、年龄、家庭规模、月费等。CPH 模型既可以处理分类协变量,也可以处理连续协变量。
CPH 模型决定了协变量的单位变化对观测值生存概率的影响。CPH 是一个半参数模型,由两部分组成:
- 基线风险函数是模型的非参数部分。回想一下,危险函数显示了未来某一事件发生的风险或概率。基线风险函数在协变量的“基线”水平(通常是平均值)估计这种风险,通常类似于 KM 曲线
- 协变量与基线风险函数的关系,是模型的参数部分。这种关系表现为一个不随时间变化的因素(或系数),直接影响基线危害。
半参数模型的真正本质在于它允许我们拥有两个世界的最佳部分:一个可解释和可操作的模型(参数部分),同时仍然提供真实生活数据的公平表示,而不做任何与其函数形式相关的假设(非参数部分)。
然而,CPH 模型有一个很强的假设,叫做比例风险假设。这一假设表明,协变量的相关风险可能会随着时间的推移而变化,但风险比率会随着时间的推移保持不变。考虑一下二元协变量:已婚个体死亡的风险可能会随着时间而改变。但是下面两者的比率被假定为随时间保持不变:
- 已婚个体在时间
t死亡的风险 - 未婚个体死亡的风险
t
我们将在本帖后面的实际例子中详细讨论这一假设,以及在实际应用中是否可以容忍任何偏差。
生存分析案例研究——客户维系
理论讲够了,现在让我们转向一个实际的案例研究,我们将利用电信客户数据集上的生存分析技术来预测特定客户何时会流失,以及我们能够支付多少费用来留住他们。
所有相关的生存分析技术都包含在 Python 可用的lifelines包中。我们将使用电信客户的公开可用的数据集,除其他协变量外,该数据集还包含个人在公司的任期/持续时间信息,以及一个二进制标志,该标志表示在数据收集之日他是否有过不愉快经历:

我们最初的数据研究揭示了以下内容:
- 除了一个协变量之外,所有协变量都是
object数据类型,这意味着我们需要对它们进行一次性编码 TotalCharges属于object数据类型,而不是float64。原因似乎是一些用于特定观察的空白- 对于模型训练,唯一标识符(在本例中为
customerID)通常会被删除。然而,我们在这里的最终目标也是确定和规划客户层面的策略,以减少我们当前未流失客户的流失。因此,我们将把活跃的和被审查的个人的customerID&MonthlyCharges划分到一个单独的数据框架中,以便以后在设计客户层面的策略时使用 - 连续变量的 KDE 图描绘了偏态分布

然后,我们将执行以下特征工程步骤,为生存分析准备数据:
- 用
MonthlyCharges列的值替换TotalCharges中的空格,并将其转换为数值数据类型。 - 分别用 1 和 0 替换目标
Churn列的 Yes 和 No 值。 - 同样,对于其他特定功能,将“是”替换为 1,将“0”替换为其他值(例如,否,无互联网服务)。
- 创建剩余分类特征的虚拟变量。
注:对于每个虚拟变量,我们通常会删除其中一个编码特征,以消除多重共线性的风险。但是,我们将手动删除一个特定的虚拟变量,该变量通常代表我们的订户群体。当我们删除一个虚拟列时,该删除列的值会在基线危险函数中出现。手动控制应该删除哪个虚拟变量可以确保我们的基线风险函数代表典型的订户。其他一切都偏离了这个公认的基线,从而被业务直观地理解。因此,我们将去掉样本中出现频率最高的虚拟变量。
生命线中的 CPH 模型实施不适用于高度共线的协变量,因此让我们通过热点图来检查是否存在多重共线性:

由于上面的热图没有显示任何高的成对相关性,我们将继续我们的生存分析。
除了可视化和数据浏览之外,到目前为止执行的步骤的代码如下:
注意:我们很幸运,因为我们的数据已经有了一个持续时间或任期列。通常,您可能会遇到每个观察的开始和结束时间,而不是这些持续时间。lifelines有一个方便的实用函数,可以将开始和结束日期转换成一个表示持续时间的 NumPy 浮点数组和一个事件观察的布尔数组:[datetimes_to_durations](https://lifelines.readthedocs.io/en/latest/lifelines.utils.html#lifelines.utils.datetimes_to_durations)
KM 曲线
我们将通过首先绘制样本的 KM 曲线来开始我们的生存分析,该曲线向我们显示了在特定时间点平均客户的历史生存概率。请记住,协变量的存在对 KM 曲线没有影响,因为它只与持续时间和事件标志有关。通常,在实践中,在通过 CPH 模型进行更深入的分析之前,首先会查看 KM 曲线以了解我们的数据。
我们针对所有客户的第一条 KM 曲线,置信区间为 5%,如下所示:

以上应该让我们对客户有了一些基本的直觉。正如我们对电信业务的预期,客户流失率相对较低。即使过了 72 个月(我们数据中的最大期限),公司也能留住 60%或更多的客户。
图底部的行显示了一些要解释如下的附加信息:
- 有风险:观察到的期限超过该时间点的客户数量。例如,532 名客户的租期超过 70 个月
- 已审查:任期等于或小于该时间点且未被搅动的客户数量。例如,3,860 名客户的租期为 60 个月或更短,但他们当时并未流失
- 事件:任期等于或小于该时间点的客户数量,该时间点之前已经发生了变动。例如,1,681 名客户的租期为 50 个月或更短,到那时已经流失了
在这一点上,我们不知道我们的哪些协变量对我们客户的生存机会有实质性的影响(CPH 模型将在这方面帮助我们)。然而,凭直觉我们知道,更长的定期合同会影响客户的生存概率。为了检验这种潜在影响,我们将为合同列的每个唯一值绘制 KM 曲线:

我们这里有本质上不同的生存曲线,如预期的那样,月合同客户的生存概率随时间急剧下降。即使在三年后(准确地说是 40 个月):
- 2 年合同的客户几乎有 100%的生存概率
- 一年期合同的客户有超过 95%的生存概率
- 月合同的客户只有大约 45%的生存概率
CPH 模型
现在更有趣的事情来了,我们将分析数据中生存曲线和其他协变量之间的相互作用。拟合 CPH 模型就像 scikit-learn 中的任何其他 ML 模型一样。下面的模型摘要是通过模型的print_summary方法访问的:

上面的模型总结列出了 CPH 模型分析的所有一次性编码协变量。让我们看看这里提供的关键信息:
- 模型系数(
coef列)告诉我们每个协变量如何影响风险。协变量的正coef表明具有该特征的客户更有可能流失,反之亦然 exp(coef)是危害比,解释为变量每增加一个单位的危害风险的标度,1.00 为中性。例如,StreamingMovies的 1.332 风险比意味着订阅了流媒体电影服务的客户取消服务的可能性增加了 33.2%。从我们的角度来看,exp(coef)低于 1.0 是好的,这意味着客户在有协变量的情况下不太可能取消订单- 模型一致性 0.929 的解释类似于逻辑回归的 AUROC:
— 0.5 是随机预测的预期结果
—越接近 1.0 越好,1.0 显示出完美的预测一致性。
因此,我们的模型的 0.929 的一致性是一个非常好的一个!
但是什么是和谐指数呢?
0.929 的一致性基本上意味着我们的模型在未经审查的数据的 100 对中正确预测了 92.9 对。它基本上评估了模型的区分能力,即它在区分活着的和被搅动的受试者方面有多好。比较两种不同的模型是有用的。然而,concordance 并没有说我们的模型校准得有多好——这是我们稍后将评估的内容。
这里的一对指的是我们数据中所有可能的客户对。考虑一个例子,其中我们有五个未经审查的客户:A、B、C、D & E。从这五个客户中,我们可以有总共十个可能的对:(A、B)、(A、C)、(A、D)、(A、E)、(B、C)、(B、D)、(B、E)、(C、D)、(C、E)和(D、E)。如果 E 被删截,则一致性指数计算将排除与 E 相关的对,并将考虑分母中剩余的八对。
确认比例危险(PH)假设
回想一下上面解释的 CPH 模型的比例风险假设。PH 值假设可以使用基于缩放舍恩菲尔德残差的统计测试和图形诊断进行检查。该假设由残差和时间之间的非显著关系(例如,p > 0.05)支持,并由显著关系(例如,p < 0.05)反驳。
我不会深入许多技术细节,而是只关注实际应用。可以通过lifelines’check_assumptions方法在拟合的 CPH 模型上检查 PH 假设。执行此方法将返回不满足 PH 假设的协变量的名称、关于如何潜在地纠正 PH 违反的一些通用建议,以及对于违反 PH 假设的每个变量,缩放的舍恩菲尔德残差相对于时间变换的可视化图(一条扁平线确认 PH 假设)。更多详情请参考本。
在检查我们模型的 PH 假设时,我们发现 3 个协变量不符合它。然而,就项目的目的而言,我们将忽略这些警告,因为我们的最终目标是生存预测,而不是确定推断或相关性来理解协变量对生存持续时间和结果的影响。关于我们为什么可以安全地忽略这些偏差的更多细节,请参考和。
CPH 模型验证
lifelines library 有一个内置函数,可以对我们拟合的模型进行 k 重交叉验证。使用和谐指数作为评分参数运行它,结果在十个折叠中平均和谐指数为 0.928。
和谐指数没有说任何关于模型校准的事情,例如,预测的概率与实际的真实概率有多远?我们可以绘制一条校准曲线来检查我们的模型在任何给定时间正确预测概率的倾向。现在让我们使用sklearn的calibration_curve函数绘制 t = 12 时的校准曲线:

考虑到我们的数据在被搅动和未被搅动的客户之间的偏斜分布,我们将calibration_curve的strategy参数设置为‘quantile’。这将确保基于第 12 个月的预测流失概率,每个箱将具有相同数量的样本。这是可取的,否则,我们将有等宽的仓,这在搅动的/未搅动的客户之间不平衡的类别分布下是不具有代表性的。
上述校准图表明,对于绘制的前七个十分位数,我们的 CPH 模型低估了流失风险,而对于后两个十分位数,我们的模型高估了流失风险。
总的来说,校准曲线看起来不算太差。让我们通过计算 Brier 分数来确认一下,我们发现它是 0.17 (0 是一个理想的 Brier 分数),一点也不差!
我们还可以绘制每个月的 Brier 分数,如下所示:

我们可以看到,我们的模型在 5 到 20 个月之间进行了合理的校准,然后随着我们开始预测更远的时间而恶化。
CPH 模型可视化
现在让我们将 CPH 模型中分析的所有协变量的系数和风险比可视化:

通过该图,我们可以快速识别对预测客户流失至关重要的特定客户特征。
可能导致流失的协变量:
- 流媒体电视和电影订阅
- 多条电话线
- 设备保护订阅
- 独居的人
- 邮寄支票付款
可能有助于留住客户的协变量:
- 有 1 年或 2 年的合同期限(非常明显)
- 自动支付方式
- 没有网络和电话服务
- DSL 互联网服务
现在让我们绘制并想象在特定水平下改变生存曲线上的协变量以及基线生存曲线的效果:

很明显,总支出接近零的客户比总支出接近 3000 英镑或更多的客户更有风险(他们的生存曲线急剧下降)。此外,拥有长期合同提高了客户的生存概率。
与 CPH 建模、验证和可视化相关的所有代码如下:
流失预测和预防
因此,现在我们知道我们可以关注哪些协变量来降低现有右删失客户的流失风险,即那些尚未流失的客户。让我们首先绘制出Contract、PaymentMethod、InternetService和PhoneService的分类 KM 曲线:

见解:
- 鼓励客户通过银行转账或信用卡设置自动支付
- 与客户签订 1 年或 2 年的合同是非常明确的
- 关于互联网服务,首先,我们应该分析拥有 DSL 或光纤互联网订阅的客户流失率相对较高的根本原因,可能是服务质量差、价格高、客户服务不足等。我们还应该对互联网服务进行盈利能力分析。最佳行动方案将取决于这一分析
- 有或没有电话服务的客户的生存曲线似乎没有太大的统计差异
分析被审查的客户
现在,我们将把我们的重点放在审查和仍然活着的客户,以确定未来的一个月,他们可能会与我们一起做些什么来增加他们的保留机会。
在对所有客户的数据进行过滤后,我们将使用[predict_survival_function](https://lifelines.readthedocs.io/en/latest/fitters/regression/CoxPHFitter.html#lifelines.fitters.coxph_fitter.SemiParametricPHFitter.predict_survival_function)方法预测这些客户的未来生存曲线,给出他们各自的协变量。也就是说,估计我们客户的剩余寿命。
predict_survival_function的输出将是一个矩阵,包含每个剩余客户在特定未来时间点的生存概率,直到我们数据中的最大历史持续时间。因此,如果我们数据中的最大持续时间是 70 个月,predict_survival_function将预测从今天开始的未来 70 个月。该方法还允许我们通过times参数计算未来特定月份的生存概率(有助于回答我们希望在未来 3 个月和 6 个月结束时保留多少客户等问题)。
两个特定客户的predict_survival_function输出示例:

列 15 中的客户在从现在起的 73 个月后预期有 99.9%存活,而列 16 中的客户在仅 4 个月后预期有 74.4%存活的概率。
计算预期损失
我们可以使用这些生存概率来确定每个客户的生存可能性低于某个阈值的具体月份。根据用例,我们可以选择任何百分比,但是对于我们的项目,我们将通过median_survival_times方法使用中间值。qth_survival_times可用于任何其他百分位数。
median_survival_times方法的输出是代表未来一个月的单行,在该月中,每个被审查/存活客户的存活概率低于中值存活概率:

inf基本上意味着这个客户几乎肯定是活着的。
接下来,我们将执行以下操作:
- 将
median_survival_times的转置输出与 CustomerID 和相应的 MonthlyCharges 连接起来(我们在最开始时将其放在一边)。这将使我们能够将我们的预测与每个特定客户及其每月费用联系起来 - 计算每个客户的预期损失,如果他们今天流失,用他们每月的费用乘以他们预期流失的月份
- 对于预期流失月份为
inf的客户,将inf替换为启发式的,可能是 24,对应于 2 年的合同。这将使我们能够估计这些客户的相关预期损失,如果他们今天离开我们,假设他们将与我们在一起至少 24 个月
我们的数据,按照预期损失的降序排列,现在看起来像这样:

我们现在已经确定了如果客户今天离开我们,会给我们带来最高货币风险的客户。
计算预计收入提升
我们能做什么来留住他们?来自我们的 CPH 模型和相关的知识管理生存曲线的系数表明我们需要关注什么特征来留住我们当前的客户。但是,现在让我们尝试估计一下,如果我们能够说服客户注册这些防止客户流失的特定功能(如果他们还没有订阅这些功能的话),将会带来多大的经济效益。
因此,如果我们能让一个没有以下内容的客户订阅/注册这些功能,我们将估计以下功能的潜在收入提升。
- 一年的合同
- 两年的合同
- 数字式用户线路
- 通过银行转账自动支付
- 通过信用卡自动支付
我们现在将通过假设情景下的嵌套for循环计算上述每个协变量和每个客户的潜在提升。例如,如果他签订了一年的合同,而他没有签订一年的合同,我们可以计算修改后的预期流失月份。
我们最初的隆起分析得出如下结果:

现在,如果我们可以注册一个特定的功能,其他条件不变,我们就有了每个客户的预期流失月。例如,如果我们能让客户 7590-VHVEG 与我们签订一年的合同,在其他条件不变的情况下,我们可以期望他再与我们合作 11 个月。或者,如果他建立了自动支付系统,在其他条件不变的情况下,预计他会再呆 4 个月。
如前所述,我们有一些非常好的客户,他们的流失风险很低,表现为基准月份的inf值。我们暂时不需要把我们的营销努力集中在他们身上。所以我们将它们排除在进一步的分析之外。
让我们更进一步,看看每个潜在升级对客户的财务影响超过预期的修改寿命,而不仅仅是预期的额外月份。这是一个简单的计算方法,我们将每个协变量的基线和修订流失月之间的差异乘以每月费用。

现在我们知道了客户 7590-VHVEG 的以下信息:
- 如果他签订一年期合同,在其他条件不变的情况下,他的预期寿命将增加 328.35 美元的收入
- 如果他签订了 2 年的合同,在其他条件不变的情况下,他的预期寿命将增加 925.35 美元的额外收入
- 如果他转换为自动支付方式之一,在预期寿命增加的情况下,他将获得 119.4 美元的额外收入其他条件不变
与流失预测和预防分析相关的所有代码如下:
结论
现在,我们不仅对哪些客户面临流失风险有了一些可操作的见解,而且对客户流失的预期时间和通过引入客户特定策略可能带来的收入增长也有了一些可操作的见解。
完整的 Jupyter 笔记本可以在 GitHub 这里找到。
一如既往,如果您想讨论任何与数据分析、机器学习、金融和信贷风险分析相关的问题,请随时联系 me 。
下次见,继续!
如何不跑出跑道:种植种子的简单方法
原文:https://towardsdatascience.com/how-to-not-run-out-of-runway-the-simple-way-to-plan-your-seed-ef2f2c79548?source=collection_archive---------61-----------------------
到处都有很多创业建议。我给大家讲一个经常被忽略的非常实用的——如何规划自己的早期成长。种子期通常致力于寻找你的产品与市场的契合度,也就是说,你开始时没有或只有很少的产品,到最后应该会有一个明显的持续增长的用户群。我将告诉你如何规划这个成长阶段,一旦你这样做了,你就会有一个清晰的种子时间表:

经典种子期的三个步骤:寻找 PMF、早期成长和筹资。图片作者。
虽然存在差异,但当你有早期牵引力时,通过增长率和 ARR 或潜在货币化用户群进行评估,首轮融资被广泛筹集。
- 什么是好的用户群?一个可能或正在产生约 100 万美元收入的项目。
- 为什么是 100 万美元?因为你的 A 轮会在 1000 万美元估值附近,而 x10 一般是这个阶段使用的倍数。有许多变化,但很少数量级的变化。
- 什么是好的增长率?保罗·格拉厄姆说 5%-7% w/w 大卫萨克斯说每月 15%-20%(稍微慢一点)。你可以很容易地在 Twitter 和 VC 博客/播客上找到上述数字的 100 个其他基准——但除非你打算投资,否则花这么多时间是没有用的,只是用这些数字作为指南,然后尽你所能。
综合起来,所有这些数字意味着你的种子成长计划应该是这样的:你筹集了足够 X 个月的资金,比如 18 个月。就在这笔钱用完之前,你最好开始筹集 100 万美元左右的首轮资金。也许你想要一个 3 个月的缓冲期,以防万一你错过了你的成长目标。以 5% w/w 的增长率,需要多长时间才能制造出 100 万美元的 ARR?你应该在播种后的第 12 个月开始吗?还是第三个月?你还有多长时间到达 PMF?如果你错过了增长的起点几个月,你现在需要增长多快才能赶上?这意味着你每周需要带来多少用户?这个简单的互动模型将回答所有这些问题。(这个在 grid.is 上,让电子表格互动。我和他们没有关系,我只是喜欢这个工具)。

网格模型。是我们用来规划我们的成长。我们用 getradical.co 来谈论工作。图片作者。
要使用它,你填写你的目标结束日期(3 个月前你用完现金,所以你需要提高你的下一轮)。输入你将从第一次发布中获得的初始用户数量(可能是你的等待列表中的用户或主要的第一次推送——比如 100 个左右)。然后,设定你的目标用户数量,以及你预测的每周流失率。只有这样,才可以开始玩“场地开始”游戏。如果给自己 4 个月的成长时间会怎么样?这是一个现实的增长率吗?还是你需要达到罕见的 10%以上的 w/w 增长率?10 个月怎么样?你还有 10+3 个月的时间吗?或者你应该从今天就开始实现每周目标吗?
您可以找到一个表格,为您提供准确的每周增长目标,您可以打印出来并与您的团队分享。你可以填写你每周实际实现了多少,以及你是领先还是落后于目标。正如保罗·格拉厄姆所说,专注于这一点将会引导你走向成功,或者给你的创业带来更好的想法。
专注于达到一个增长率会把创业的繁杂问题简化成一个单一的问题。——p·格雷厄姆

底部的表格是你每周的目标。图片作者。
这是一个基本的模式,你可以去想象和添加更多的选项——按照有机和付费增长,按照渠道,或者增加不同的收入;你可以很容易地对一些低的和有上限的病毒率建模(例如,每个人可能以 15%的概率导致 3 个以上的人)。请随意联系我,让 Excel 来完成这些,我特别想知道这是否改变了你对种子期的计划。以上截图来自互动模式。
如何(不)赢得纸牌游戏比赛
原文:https://towardsdatascience.com/how-to-not-win-a-kaggle-competition-e83dcffab637?source=collection_archive---------13-----------------------

古伊列梅·斯特卡内拉在 Unsplash 上的照片
要是赢和输一样简单就好了
什么是卡格尔?
你有没有想过当一名医生会是什么样子?有机会探索这种可能性而不付诸实践?如果是这样,你并不孤单。然而,鉴于现代医学的复杂性以及所涉及的法律和责任的细微差别,成为一名医生有一个“试用期”是极不可能的,甚至是不可能的。对于数据科学来说,情况并非如此。
Kaggle 是一个平台,任何对数据分析和数据科学感兴趣的人都可以通过它来探索精选的数据集并解决非常具体的问题。如果您对开发模型来解决分类任务、回归任务和图像识别感兴趣,Kaggle 拥有数据集和支持小组,可以让任何人学习如何使用数据。如果您对数据可视化或探索性数据分析更感兴趣,也有专门用于这方面的数据集。Kaggle 还提供了许多其他任何人都会喜欢的功能。最感兴趣的一个特性是 Kaggle 竞赛。
由不同公司赞助的每场比赛都有一个数据集,其中有一组可用的变量和一个你想要预测的特定变量。通常有一个与竞争相关的指标,竞争的目标是优化该指标。竞赛的获胜者通常会获得奖品,通常包括奖金,但不排除与竞赛发起人合作的机会。
每个参与者部署一个策略,希望赢得比赛。但是,总有明确果断的输策略。
我们将讨论最常被用来赢(输)的常规策略,并讨论为什么这种策略从来不会产生胜利的结果。
典型的赢(输)策略

照片由JESHOOTS.COM在 Unsplash 上拍摄
参与者为赢得胜利而采取的典型策略包括两个基本概念:开发数据科学管道和尽可能实现最佳优化指标。这两个概念都是赢得 Kaggle 竞赛所必需的。然而,过度关注这两个概念通常是参与者失败的原因。
让我们首先检查实现最佳优化指标的可能性。随着 Kaggle 比赛的进行,开发了两个记分牌。这是每个人首先使用的初始记分牌,通常在比赛中会提供两个数据集。一个数据集用于培训您的数据科学管道,另一个数据集用于测试您的数据科学管道。您测试流程的数据集将提交给最初的委员会筛选,他们将测量您的预测或预测子集的准确性,并将其作为您在竞争中的初始得分。当比赛结束时,会显示第二个记分牌,并对来自测试数据集的全套预测进行评分,该分数是决定谁赢谁输的决定性分数。
不幸的是,大多数人专注于在第一轮获得高分,希望在最后一轮获得高分。这是大多数没有获胜的原因。数据科学中有一个概念叫做过拟合。过度拟合是指在数据集上训练并优化该数据集上的指标。即使您没有在将用于评分流程的数据集上训练您的数据科学流程,您仍然可以通过对预测执行最终调整来使您的数据科学流程过拟合,以便在第一个板上为您自己创造更好的分数。如果这是唯一要担心的板,那么也许该技术将是使用的技术。然而,鉴于第二板,情况并非如此。那些为第一轮做出的“优化的、高性能的”预测通常在最后一轮中表现不佳。这是大多数人犯的第一个错误。
大多数人犯的第二个错误是假设只有一种方法来创建一个高性能的数据科学管道,并且可能只需要一个参与者来创建这样一个管道。“条条大路通罗马”这句话在这里很适用。
从概念上讲,这两种策略都很重要,也很有必要。然而,仅仅关注这些,并不能让你前进并取得胜利。
制胜之道

照片由 NeONBRAND 在 Unsplash 上拍摄
制定成功战略的方法涉及制定失败战略的两个基本概念:开发数据科学管道和尽可能获得最高分。这两者的区别在于你如何对待这两个基本概念。
当试图获得尽可能好的分数时,你必须期望你的数据科学过程是高效的,并且能够很好地概括。为了确保泛化,必须将训练数据集分成两个不同的数据集。您必须有一个验证数据集,验证您的数据科学管道,并有一个初始培训数据集的子集来培训您的数据科学流程。这两者都是必需的。那么,目标不是在第一个记分牌上取得最好的成绩。记分牌更像是一个标尺,用来确定你的验证方案的有效性。您的目标应该是查看您的验证指标执行得如何,并确保与培训指标一起改进。
同样,在开发您的数据科学管道时,大多数人专注于独立完成,并且认为他们的方式是唯一的方式。事实并非如此!!
赢得 Kaggle 竞赛需要合作。
在 Kaggle 上,你可以创建小组,你可以与其他人合作,结合你的数据科学管道来取得胜利。大多数获胜者以团队形式联合在一起。协作和团队合作是取胜的必要因素。
总之,要强调几点,要赢得 kaggle 竞赛,您必须有一个适当的验证方案并进行协作。
如果这篇文章引起了你的共鸣,请到我的主页订阅我的时事通讯。
[## 主页
在这里,您将找到有关 Edward Turner 所做工作的信息,以及…
ed-特纳. github.io](https://ed-turner.github.io/)
如果你对我的更多文章感兴趣,请点击下面的链接
[## 埃德·特纳-中等
阅读艾德·特纳在媒体上的作品。作为佛罗里达州坦帕市的一名高级数据科学家,我热衷于…
medium.com](https://medium.com/@edward.turnerr)
如何获取和分析 Fitbit 睡眠评分
原文:https://towardsdatascience.com/how-to-obtain-and-analyse-fitbit-sleep-scores-a739d7c8df85?source=collection_archive---------7-----------------------

凯利·西克玛在 Unsplash 上的照片
准备用于机器学习模型的 Fitbit 睡眠数据并了解睡眠评分的工作原理
智能手表和其他可穿戴设备在过去几年里越来越受欢迎,并催生了“量化自我”的文化现象。Apple Watch 或 Fitbit 等设备让任何人都有可能轻松地自我跟踪,从而以某种方式量化他们的生活。流行的自我量化包括消耗的卡路里,白天走的步数或睡眠质量。
在本文中,我将使用使用 Fitbit 大约一年的真实生活数据,重点关注后者,即睡眠质量。Fitbit 为用户提供了一个睡眠评分,这应该是衡量睡眠质量的一个指标。我将使用 Python 训练和测试不同的机器学习模型,试图尽可能准确地预测 Fitbit 睡眠分数,同时解释不同的指标,如 REM 睡眠分钟数,如何影响分数。
这篇文章的结构如下:
- Fitbit 睡眠评分简介
- 从 Fitbit 获取睡眠数据
- 数据清理和准备
- 探索性数据分析
- 将数据分为训练集、验证集和测试集
- 扩展功能和定义性能指标
- 使用套索回归的特征选择
- 多元线性回归
- 随机森林回归量
- 极端梯度推进回归器
- 交叉验证
- 超参数调谐
- 最终模型评估
- 结论意见
因为涉及的内容很多,所以我把这篇文章分成三部分。第 1 部分包括第 1 点到第 4 点,重点是获取睡眠数据、预处理和可视化。第 2 部分涵盖了第 5 点至第 10 点,即基于第 1 部分的预处理数据实际构建机器学习模型。第 3 部分涵盖了剩下的部分,全部是关于改进第 2 部分的模型,以获得最准确的预测。
Fitbit 睡眠评分到底是多少?
Fitbit 睡眠评分最好通过一个例子来描述,所以这里有两个应用程序提供给用户的截图:


Fitbit 提供的睡眠统计数据
在 Fitbit 应用程序中,用户会得到一个睡眠分数,在这种情况下为 78 分,这是一个睡眠窗口中睡眠阶段的图形表示,这些睡眠阶段的具体细分为分钟和百分比,以及估计的氧气变化。
这本身似乎相当简单明了。Fitbit 只是有一些算法,他们插入相关的睡眠统计数据,如快速眼动睡眠的分钟数,并给出睡眠分数。
对于任何一个有 Fitbit 的人来说,如果他曾经试图理解他们睡眠分数的模式,很明显这远非一目了然。下面的截图会让你明白困惑是从哪里来的:


Fitbit 提供更多睡眠统计数据
将这些睡眠统计数据与最初的数据进行比较,我们可以得出以下结论:
- 睡眠时间比一小时长
- 快速眼动睡眠的时间几乎是一样的
- 深度睡眠的时间更长
基于这些观察,人们会认为第二次睡眠得分会比第一次高,但实际上是一样的。这是怎么回事?不同的统计数据在睡眠分数的计算中起什么作用?只看提供的睡眠统计数据,有可能自己预测睡眠分数吗?
本文回答了所有这些问题,并详细介绍了一个机器学习项目。我希望你喜欢它!
从 Fitbit 获取睡眠数据
Fitbit 允许用户通过他们的在线仪表盘导出 CSV 文件形式的睡眠数据。这个过程需要一些手工劳动,因为 Fitbit 一次最多只能导出 31 天的数据。几分钟后,我得到了所有的数据,并迅速将它们合并成一个 CSV 文件。
有一个问题。手动导出的 CSV 文件包括所有睡眠统计数据(睡眠分钟数、清醒分钟数、自由睡眠分钟数等)。)但不包括实际的睡眠分数。搞什么鬼?!
经过一番挖掘,我发现还有另一个名为“终身导出”的导出选项,它可以导出 Fitbit 从你开始佩戴他们的手表以来收集到的所有数据。在下载之前,你必须从 Fitbit 请求这个导出,一旦获得批准,你就可以下载一个包含各种不同文件的 zip 文件夹。该 zip 文件夹中包含一个 CSV 文件,其中包含额外的睡眠统计数据,包括睡眠评分。
我将包含睡眠统计数据的 csv 文件保存为 sleep_stats.csv,将包含睡眠分数的 CSV 文件保存为 sleep_score.csv。
数据清理和准备
本节解释了如何从 CSV 文件获取可用于机器学习模型的数据帧。在这个过程中,我遇到了一些将数据导入 Python 时可能出现的常见问题,我解释了如何处理这些问题,以便最终得到一个经过整齐预处理的数据集。
导入所有相关的库后(参见完整笔记本中的库),第一步是使用 pd.read_csv()函数将 CSV 文件中的睡眠数据导入 Python:
我只导入 sleep_score.csv 的前两列,因为它们包含日期和实际睡眠分数,所有其他相关数据都可以在 sleep_stats.csv 中找到。让我们来看看 sleep_stats_data 中的前五行:

这是第一个常见问题:由于 CSV 文件的结构方式,列名位于第一行。有一种方法可以解决这个问题:
使用。info()函数我们可以获得数据帧中数据的高级摘要,在我们的例子中,它看起来像这样:

这里,我们遇到了第二个常见问题:最后三列中有 NaN 值(缺失数据)。上面的信息摘要告诉我们有 322 个条目(行),但是最后三行的非空计数是 287,这表明了这一点。让我们使用下面的代码来看看包含缺失数据的行:

如果我们查看“入睡时间”或“开始和结束时间”一栏,就会清楚地看到这些行指的是 Fitbit 记录的午睡。小睡时间太短,Fitbit 无法可靠地测量重要的睡眠统计数据,因此我们将从数据集中删除所有这些行:
在上面的数据摘要中,我们还遇到了第三个常见问题,它与第一个问题相关:所有列的数据类型都是“object ”,但索引为 2 到 8 的列显然应该是数值型的,即数据类型要么是“int ”,要么是“float”。这些列的数据类型为“object”的原因很可能是因为列标题最初放在第一行,从而导致整个列被归类为“object”。让我们将这些列转换为数据类型“float”:
现在让我们看看前几行和 sleep_score_data 的摘要:


这个数据框架看起来好多了,列标题被自动识别,没有丢失值。
出于进一步分析的目的,我想将两个数据帧合并成一个,这意味着我想将它们合并。为了确保睡眠分数最终出现在对应睡眠统计数据的行中,我需要一个在两个数据帧中都相同的列,它将被用作合并的列。
在我们的例子中,两个数据帧都有一个带有某种时间戳的列。睡眠统计数据帧具有开始和结束时间,睡眠分数数据帧具有时间戳。因为睡眠分数总是在醒来后提供,所以睡眠统计数据帧中相关的日期是结束时间,我们可以去掉开始时间。但是还有一个问题:睡眠统计数据帧中结束时间的格式不同于睡眠分数数据帧中时间戳的格式。如果我们试图合并这些列上的数据帧,这些行将不会匹配。我的解决方案是在两个数据帧中创建一个只包含日期的“Date”列,合并这些列上的数据帧,删除多余的列,并在合并后删除一个包含缺失值的行。以下代码实现了这一点:
生成的组合数据帧如下所示:

合并和预处理的数据
我删除了所有与日期相关的列,因为这不是时间序列分析,我们不需要未来的日期。Fitbit 应用程序没有提供醒来的次数,因为我想只使用应用程序中提供的数据来预测睡眠分数,所以我也放弃了它。
有了经过组合和预处理的数据框架,我们可以继续进行一些探索性的数据分析。
探索性数据分析
在这一节中,我将使用可视化来提供对底层数据的更好理解。这些初步的见解将成为以后分析的基础。
首先让我们来看看睡眠分数的分布:

睡眠得分的分布向左倾斜,这是有道理的,因为由于多种原因,如熬夜或不得不早起,晚上睡不好比晚上睡得特别好更容易发生。此外,平均睡眠分数已经相对较高,为 82 分(满分为 100 分),因此不太可能(基本上不可能)出现许多远高于平均值的异常值。
让我们也来看看每个特征与睡眠分数的关系,以了解哪些特征可能是重要的,以及它们与睡眠分数的关系。我已经定义了一个函数,它将一个数据帧作为输入,该数据帧包含最后一列中的目标变量以及整个绘图中包含的列数。列的数量决定了每行有多少支线剧情。下面是函数:
使用 sleep_data 数据帧和 num_cols=3 作为输入来调用此函数会产生以下图形:

单独来看,睡眠分钟数和快速眼动睡眠分钟数似乎与睡眠得分有最强的正相关。一般来说,这是有道理的,因为当考虑睡眠质量和睡眠分数时,更多的睡眠时间应该是一件积极的事情。快速眼动睡眠时间延长也是如此。
为了完整地描述不同特征和睡眠评分之间的关系,我们来看看相关矩阵:

事实上,睡眠分数与快速眼动睡眠分钟数相关性最高,紧随其后的是睡眠分钟数。另一个需要注意的重要事情是,许多特性是高度相关的。这是有道理的,因为更多的睡眠时间应该导致更多的时间花在睡眠的各个阶段,并且这些特征将会一起移动。虽然这可能是此处包含的要素的性质不可避免的副产品,但它可能会导致多重共线性问题。稍后将详细介绍。
第二部分基于预处理数据和探索性数据分析的见解,建立了两个不同的预测睡眠分数的机器学习模型。第 2 部分可以在这里找到:
[## 使用机器学习来预测 Fitbit 睡眠分数
随机森林、极端梯度推进以及它们在预测 Fitbit 睡眠分数时的表现
medium.com](https://medium.com/@bennerjonas10/using-machine-learning-to-predict-fitbit-sleep-scores-496a7d9ec48)
如何用 Python 函数获得你最喜欢的球员的 NBA 统计数据
原文:https://towardsdatascience.com/how-to-obtain-nba-statistics-for-your-favorite-players-with-a-python-function-8947516af286?source=collection_archive---------18-----------------------
直接从命令行查询 70 年的 NBA 统计数据

TJ·德拉戈塔在 Unsplash 上的照片
介绍
本文将向您展示部署 Python 函数来模拟一项任务的方法之一,这项任务就像搜索您喜爱的篮球运动员在给定 NBA 赛季的统计数据一样简单。
作为一个 NBA 篮球迷,我经常在网上查找某个特定球员的表现,并想知道我是否可以尝试使用 Python 复制这个过程,简单地从笔记本电脑的命令行启动搜索并获得结果,而不需要实际打开浏览器并上网。
让 Python 为您进行 web 搜索对于许多不同类型的应用程序来说是非常强大的,我希望这个简单的例子能够让它变得有用,并启发您将这些概念应用到自己的个人项目中。
步骤 1:确定你的统计网站
在篮球分析社区的例子中,BasketballReference.com是一座数据的金矿,因为它拥有对许多篮球分析项目有用的各种相关游戏内统计数据。我将使用这个网站来收集相关数据。
特别是对于 NBA 的统计数据,该网站有一个“每场比赛”部分,人们可以在这里获得任何相关类别的每场比赛表现统计数据,包括参加任何给定赛季的大约 500 名 NBA 球员。
我们的目标是编译和执行一个 Python 程序,它可以返回任何球员在任何给定赛季的每场比赛的完整统计数据。该网站从 20 世纪 50 年代开始记录每场比赛的统计数据,所以给你大约 70(!)年的数据,你可以搜索。
第二步:编写 Python 函数
现在让我们来看一下实现这一点所需的函数代码,并一步一步地分解它。
- 导入相关的包:作为第一步,您需要导入相关的 Python 包并定义指向在线数据源的 url 变量。您还应该导入熊猫包(" import pandas as pd "),因为您稍后会需要它。
import requests
from bs4 import BeautifulSoup
import pandas as pd
2。定义功能并获取用户输入
你用 def 关键字定义函数,给它一个有代表性的名字,比如get _ NBA _ stats;该函数不接受任何参数,而是让用户通过两个输入命令来定义它们,其中程序提示输入年份和球员姓名,以返回每场比赛的统计数据。
def get_NBA_stats():year=input("Which NBA season are you interested in?: ")
player=input("For which player do you want to get stats?: ")
3。抓取并保存数据
然后,您需要用 request.get 方法获取相关的 url 内容。请注意年变量是如何用于将搜索指向年季统计数据所在的网页的。然后,您可以用提取它的文本。text 方法,最后把它解析成一个 Beatiful Soup 对象。
url = '[https://www.basketball-reference.com/leagues/NBA_{}_per_game.html'.format(year)](https://www.basketball-reference.com/leagues/NBA_{}_per_game.html'.format(year))
r = requests.get(url)
r_html = r.text
soup = BeautifulSoup(r_html,'html.parser')
为了在 BasketballReference 网页的 HTML 中定位包含球员数据集的表格,您可以检查页面的代码(这可以通过在 Google Chrome 上单击 Ctrl + Shift + I 来完成),并看到您感兴趣的表格元素有一个与 full_table 相等的类,您可以使用该类通过 soup.find_all 命令将表格内容存储到 table 变量中。
然后,您可以使用 soup.find 来定位页面中的元素,其中类等于 table_head ,因为该类存储我们的玩家数据集的列名。您可以将它们保存在一个名为 head,的变量中,然后该变量用于提取和清理最终数据集的相关列名,例如每个球员的姓名、每场比赛的得分、每场比赛的篮板数等..如下图所示。
table=soup.find_all(class_="full_table")
""" Extracting List of column names"""
head=soup.find(class_="thead")
column_names_raw=[head.text for item in head][0]
column_names_polished=column_names_raw.replace("\n",",").split(",")[2:-1]print(column_names_polished)['Player',
'Pos',
'Age',
'Tm',
'G',
'GS',
'MP',
'FG',
'FGA',
'FG%',
'3P',
'3PA',
'3P%',
'2P',
'2PA',
'2P%',
'eFG%',
'FT',
'FTA',
'FT%',
'ORB',
'DRB',
'TRB',
'AST',
'STL',
'BLK',
'TOV',
'PF',
'PTS']
然后,您可以遍历整个表元素,对于每一行数据(与单个玩家相关并由 td HTML 标签标识),您可以提取所有玩家的统计数据,并将它们存储到一个名为 players 的列表中。一旦完成,你所要做的就是将所有玩家的信息存储到一个熊猫数据框中,该数据框采用先前定义的列名,你可以将玩家的全名设置为索引。
注意:获得一个给定赛季的球员的完整名单对于完成手头的特定任务来说不是必要的,我只是展示如何这样做,因为通常最好的做法是存储所有潜在有用的数据(例如,如果以后你想将单个球员的表现与其同行进行比较,拥有 NBA 球员的完整样本将是有益的)。
"""Extracting full list of player_data"""
players=[]
for i in range(len(table)):
player_=[]
for td in table[i].find_all("td"):
player_.append(td.text)
players.append(player_)df=pd.DataFrame(players, columns=column_names_polished).set_index("Player")#cleaning the player's name from occasional special characters
df.index=df.index.str.replace('*', '')

NBA 2019-2020 赛季球员场均数据
4。通过返回您请求的玩家统计数据来关闭该功能
然后你可以通过显示我们请求的玩家的全部统计数据来结束这个函数,玩家的名字是你在函数体开始时指定的,并将其打印到屏幕上。
print(df.loc[player])if __name__ == "__main__":
get_NBA_stats()
步骤 3:从命令行启动并执行函数
您的功能现在已经设置好了!你现在所要做的就是保存 python 文件(我把我的文件命名为 NBA_per_game.py )并在任何你想要的时候执行这个文件,对于任何你想要的球员和年份组合,直接从你的 PC 命令行执行。
请记住将文件保存在一个可以从命令行轻松访问的目录中,以便在心跳中启动程序。
我把我的保存在我的桌面上,这样就很容易访问,然后在下面的视频中记录了几个执行过程。
从命令行调用这个函数来获得迈克尔·乔丹(1998 年)和比尔·拉塞尔(60 年代的统计数据!)
后续步骤
您的功能已正式设置好,并可立即运行。如果你发现自己在一遍又一遍地搜索这类信息,这是一个非常好的解决方案,它显示了网络抓取对于加速甚至是最简单的任务是多么有帮助。
我是网络抓取软件包的忠实粉丝,也曾将它们用于其他目的,例如使用 API s 提取金融股票数据
希望下次你想浏览一些 NBA 的统计数据时,你会发现这很有用(也许在准备你的梦幻篮球阵容时!).
访问我的免费数据科学资源清单 这里
[## 通过我的推荐链接加入 Medium-Edoardo Romani
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
edo-romani1.medium.com](https://edo-romani1.medium.com/membership)
如何开源你的第一个 Python 包
原文:https://towardsdatascience.com/how-to-open-source-your-first-python-package-e717444e1da0?source=collection_archive---------16-----------------------
Python 打包的初学者友好分步指南

开源软件的世界很棒!照片由克拉克·蒂布斯在 Unsplash 上拍摄
为什么是 Python 包?
Python 是一种直观的通用语言,具有易于理解的语法。它使得原型开发、web 开发、数据科学等等比其他任何编程语言都要简单得多。这要归功于它庞大的支持性社区和众多的软件库。
你有没有发现自己在不同的项目中多次编写相同的代码行?或者,您可能已经编写了一些有用的库,希望其他人也能使用?或者,你只是对 Python 打包或者对 Python 社区有贡献感兴趣?
在本文中,我们将创建一个小的包,然后将其上传到 Python 包索引(PyPi) ,这样任何人都可以使用pip install下载并使用您的代码作为软件库。
当我用 Python 构建我的第一个包时,我发现这个过程有些乏味。这促使我写了这篇文章,这篇文章将带你了解如何构建一个 Python 包的基础知识,并与世界其他地方分享。
要求
如果你有一个 GitHub 帐户并且安装了 Python,你可以跳到项目概述。
Git 储存库
要成为开源社区的一员,您必须在版本控制托管服务上公开托管一个项目。最常见的选择是使用 Git 存储库主机,它保存项目的虚拟存储。它允许您协调程序员之间的工作,并保存您的代码版本,您可以在需要时访问这些版本。使用最多的托管服务是 GitHub 。如果您还没有帐户,第一步是在这里创建一个权限。
计算机编程语言
我们将使用 Python 3。Python 3.5 的任何版本都可以用于该项目。如果你没有 Python,可以从 python.org 的下载页面下载。我将在 Windows 上使用 Python 3.7,但这个项目使用什么版本或操作系统并不重要。如果你是 Python 的新手,我可以建议你做一些教程的练习。
集成驱动电子设备
集成开发环境(IDE)是一个源代码编辑器,为您提供调试和自动化工具。只要你喜欢,用什么代码编辑器或者 IDE 都没关系。我将亲自使用一个叫做 Visual Studio Code 的轻便而强大的代码编辑器。

准备深潜!由 Max Duzij 在 Unsplash 上拍摄的照片
项目概述
现在让我们构建一个简单的处理质数的包。如果您已经有了一些代码想要使用,在将您的代码组织成与项目相似之后,可以随意跳过这一部分。
你要做的第一件事是为你的库取一个合适的名字。因为我们的图书馆处理质数,所以我选了primelib。
下面是项目结构的样子。你可以和我一起创建文件,或者直接下载 GitHub 上的整个库。
primelib/
primelib/
__init__.py
prime_numbers.py
tests/
test_prime.py
.gitignore
LICENSE
README.md
setup.py
这可能看起来像很多文件,但不要担心,我们将一个接一个地制作和解释它们。
逐步构建项目
启动并克隆 GitHub 存储库
首先要做的是在 GitHub 中启动一个存储库。登录 GitHub,点击绿色的“新建”按钮。您应该会看到一个标题为“创建新存储库”的页面。选择自述文件 Python 时,请填写下面的空白处。gitignore 文件和 MIT 许可证。当你准备好了,点击创建库。

一旦在 GitHub 上创建了存储库,就必须在本地计算机上克隆它。为此,你应该在你的机器上安装 Git 和终端。在 Windows 中,我推荐使用新的 Windows 终端,尽管你肯定可以使用命令提示符。打开一个终端,通过运行git --version确保 git 安装正确。然后使用cd将你的项目存储到你想存储的地方。终于可以跑git clone https://github.com/YOUR-USERNAME/primelib.git了。点击绿色的“代码”按钮时提供链接。
现在,您应该已经将项目复制到您的计算机上了。在您喜欢的代码编辑器中随意打开primelib文件夹。您应该具有以下结构。
*.gitignore
LICENSE
README.md*
- 的。gitignore file 使您能够在跟踪和上传代码到存储库时忽略一些文件。
- 许可证文件只是一个包含项目许可证的. txt 文件。您可以在这里找到您的需求,尽管 MIT 许可证对于几个项目来说是一个很好的默认选择。
- README.md 文件是一个包含项目描述的 Markdown 格式文件。您可以为您的库将提供的模块和函数编写文档。

我们都爱 Python。克里斯·里德在 Unsplash 拍摄的照片
Python 代码
在primelib/文件夹中,你现在可以添加一个名为primelib的新文件夹,它将包含你所有的代码。在这个新文件夹中,创建两个名为prime_numbers.py和__init__.py的 Python 文件(带有两个前导下划线和两个尾随下划线)。
*primelib/
__init__.py
prime_numbers.py
.gitignore
LICENSE
README.md*
让我们从包含我们将使用的 Python 代码的prime_numbers.py开始。您可以将这段代码复制并粘贴到您的prime_numbers.py文件中。
Python 代码包含两个函数:
_divides是私有函数,因此以前导下划线开头。它被下一个函数is_prime使用,当且仅当div除以n时返回True。is_prime检查一个数n是否有一个不同于 1 和它自身的除数,如果有,它返回True。
__init__.py文件是将 primelib 转换成一个包所必需的。它将是您的 Python 解释器在运行import primelib或from primelib import ...时执行的文件。要使用命令primelib.is_prime(n)从库中直接访问函数is_prime,必须在__init__.py文件中写入以下内容:
试验
好了,现在是时候创建一些测试来确保我们的函数按预期工作了。现在,您可以在项目目录中创建一个tests文件夹,并在其中添加一个test_prime.py文件。
*primelib/
__init__.py
prime_numbers.py
tests/
test_prime.py
.gitignore
LICENSE
README.md*
您可以简单地复制以下测试。
然后就可以用 Python 标准库的一部分 Pytest 库了,所以 Python 自带的,不用安装。Pytest 会自动检查你在任何test_*.py文件中的断言语句。在您的终端中,您可以运行以下命令。
*python -m pytest*
现在您应该看到您的两个测试成功通过了。这意味着您已经准备好构建包并与社区共享您的库。

是时候建造你的图书馆了。照片由马特·阿特兹在 Unsplash 上拍摄
建造图书馆
我们将使用三个库setuptools、wheel和twine。确保它们在您的环境中可用。
*pip install --upgrade setuptools wheel twine*
构建包需要最后一个文件。您必须在目录的根目录下添加一个setup.py文件。这告诉setuptools如何实际构建这个包。让我们添加最后一个文件来获得最终的树结构。
*primelib/
primelib/
__init__.py
prime_numbers.py
tests/
test_prime.py
.gitignore
LICENSE
README.md
setup.py*
这里是setup.py文件。您可以复制并粘贴它,同时用您的名字替换您的-USERNAME 以使库名唯一。
三个强制参数是名称、版本和包。您现在可以用下面的代码构建这个库。
*python setup.py sdist bdist_wheel*
这将在dist/目录中生成分发档案。现在你可以在你的本地环境中安装这个库,执行python setup.py install。可以尝试在 Python shell 中导入primelib。
*python
>>> import primelib
>>> primelib.is_prime(13)
True*
上传到 PyPi
现在您有了一个工作库,您可以将它上传到 Python 包索引(PyPi)上,以便与 Python 社区共享。出于本教程的目的,我们将使用 TestPyPi ,它的工作方式与 PyPi 完全一样,但它是为测试包而设计的,以便尽可能保持真实服务器的干净。
首先你必须在 TestPypi 上注册一个账户并验证你的电子邮件。最后,您可以使用下面的代码将您的包作为归档文件上传。
*python -m twine upload **--**repository**-**url https:**//**test**.**pypi**.**org**/**legacy**/** dist**/****
就这么定了!您的包现在可供社区使用。如果它被上传到 PyPi 上,你可以直接用pip install primelib安装包,但是因为它现在在 TestPyPi 上,你可以用下面的代码安装包:
*pip install **--**index**-**url https:**//**test**.**pypi**.**org**/**simple**/** primelib-YOUR-USERNAME*
如果你遇到任何关于打包的问题,请参考 Python 打包教程。
您的库现在可以在 Python 环境中使用了。我强烈推荐使用virtualenv来管理不同的环境。
结论
恭喜你。你已经学会了如何创建一个 Python 包来包装你的一些代码,然后如何与社区共享你的库,这样任何人都可以使用你的作品。
我希望您现在已经准备好为 Python 社区做出贡献,并与世界其他地方分享您的伟大代码!
如果你有兴趣继续深入,我推荐这些重要但更高级的主题:
- 使用虚拟环境
- 使用持续集成工具( Travis CI )
- 版本管理工具( SemVer )
- 自动测试氮氧化物(氮氧化物)
- 自动化 HTML 文档( Sphinx )
如何最佳地操作人工智能是一个视角问题
原文:https://towardsdatascience.com/how-to-operate-an-ai-optimally-is-a-matter-of-perspective-d1d1d28f74ec?source=collection_archive---------53-----------------------

不是每个问题都可以用数学和算法来回答。当谈到人工智能的可操作性时,视角很重要,每个利益相关者衡量成功的方式都不同。接下来,是时候让领导层站出来,做出高层决策了。(来源:Shutterstock)
当你将人工智能引入企业时,数学是简单的部分。它很简单,因为它可以用普遍接受的标准客观地判定。但是许多重要的决定不属于这一类。当要做出这样的决定时,争论就开始了:十几个利益相关者带来了尽可能多的意见,每个都有合理的论据支持。为了防止不必要的混乱,现在是领导必须站出来的时候了,这些问题迟早会不可避免地成为高层决策。
一个人工智能项目要取得成功,数学、经济学、战略和心理学都必须考虑在内。为了说明这是如何实现的,在本帖中,我们将看看机器学习在德国汽车保险领域的应用。
想象一个被训练来验证汽车保险索赔的机器学习系统。汽车保险的运作方式因国家而异。在德国,索赔通常附有认证专家的损坏评估,或维修店的报价或发票。基于这些文件,机器学习系统将索赔分为两类:要么它建议直接支付,要么如果发票似乎部分或完全不合理,技术上不正确,或在任何其他方面有问题,它会将案件发送给人类主题专家进行进一步调查。
正如安盛和 Controlexpert 在一份联合声明中对德国汽车保险业务的重量级人物报告的那样,完全合法的索赔比例约为 40% [1]。因此,一个能够让人类专家专注于剩余 60%的相关案例的人工智能,有望节省大量时间和金钱。为了充分实现这一优势,必须对系统进行配置,以最好地满足用户的需求。
这就是问题的开始。对用户来说什么是最好的?
人们可能会想,在高度数学化和定量化的机器学习世界中,肯定有这种单一的神奇度量可以用来找到最佳配置。没有。
但在我们看到为什么之前,让我们先从简单的开始,看看能客观地说什么。
如何量化分类器性能
当然,有种客观的方法来评估机器学习模型的性能。事实上,像我们的声明分类器这样的系统是一个特别简单的情况,即所谓的二元分类器。二进制,因为它回答非此即彼的问题,有两种可能的结果:是或否,零或一,砰-上或砰-下。或者,在我们的具体场景中:保险索赔看起来可疑吗?
使用历史案例数据训练分类器。为了评估它在新的、未知的情况下的性能,你拿出一部分所述数据,并且不使用它进行训练。相反,一旦模型被定型,您就可以用它来测试模型。从模型的角度来看,这些数据是未知的,就像全新的数据一样,但是你,测试者,知道每个样本在过去是如何被人类专家决定的,所以你知道它应该如何被分类。
有了这些知识,您可以将分类器的测试集结果分成四类。
1.如果分类器建议对该索赔进行进一步调查,并且根据记录,该索赔确实令人反感,那么您就有了一个真阳性(TP) 。
2。如果分类器建议直接支付索赔,并且根据记录该索赔是罚款的,则您有一个真负数(TN) 。
3。如果分类器建议调查,但记录显示索赔是罚款,那么这是一个假阳性(FP) 。
4。如果分类器建议直接支付,但记录显示索赔是不良的,那么这是一个假阴性(FN) 。
这四类中的数字通常以二乘二矩阵的形式表示,即所谓的 混淆矩阵 :

虽然混淆矩阵由 TP、FP、FN、TN 四个数字组成,但实际上只有两个数字是独立的。这是因为数据本身,或者更具体地说是测试集,有一定数量的 P 个实际上为正的样本和一定数量的 N 个实际上为负的样本。所以,不管分类器工作的有多好,最后我们总会有 TP + FN = P 和 TN + FP = N,两个含有四个未知数的方程留给我们两个自由度。参数化这些自由度的一种常见方式(但不是唯一的方式)是通过真阳性率(TPR) 和假阳性率(FPR) 。
数学上,它们被定义为

从这些定义出发,你可以很容易地用很少的代数说服自己,TPR 和 FPR 足以确定所有四个 TP、FP、FN 和 TN,注意


然而,在现实中,一个案件很难 100%清楚。相反,决策是在或多或少的自信下做出的,这取决于证据——但也取决于个体决策者的个人倾向(理解为:偏见)。
想象一下,我们的分类任务将不得不由人类专家而不是人工智能来完成。此外,假设有两个求职者。一方面,有极端怀疑的主题专家。对她来说,任何要求都是无可置疑的。尽管案件细节,她只是标记每一个索赔进行进一步调查。有趣的是,甚至不需要考虑一秒钟的证据,她就可以肯定一定比例的案例是正确的:她正确地建议对每一个不合理的主张进行调查。然而,与此同时,她错误地推荐每一个正确的主张进行更仔细的检查。
第二个候选人与她完全相反。他对索赔者的信任是无限的。因此,他建议每一项索赔都进行直接赔付。这位专家也有一些成功可以展示,因为他正确地对待每一个合理的主张——但错误地对待每一个不合理的主张。
在这些虚构人物所代表的两个极端立场之间,人们可以想象出一系列或多或少严格的决策者。为了表示这个光谱,我们可以引入一个“严格参数”p,更正式的名称是鉴别阈值,其值可以在 0%和 100%之间选择。如果给定案例数据,索赔有 70%的可能性是可疑的,那么如果 p < 70%,则严格程度为 p 的专家将建议进一步调查,如果 p > =70%,则直接赔付。
这正是我们的分类器在内部工作的方式。它计算一个概率,并根据一个配置参数 p(鉴别阈值)将其转换成一个二进制判决。

图一。蓝色曲线代表的分类器优于绿色曲线代表的分类器。(来源:作者)
因此,TPR 和 FPR 以及混淆矩阵中的所有四个数字都依赖于阈值。TPR 和 FPR 如何随着阈值的变化而变化可以通过查看 ROC 曲线来理解。通过将 0%和 100%之间的所有 p 值的点(FPR(p),TPR(p))标绘到 FPR-TPR 坐标系中,可以获得该曲线。
ROC 曲线可用于比较两个分类器。一般来说,对于每个 FPR,如果一个分类器的 TPR 大于另一个分类器,那么这个分类器就比另一个好。在 ROC 图中,上级分类器的 ROC 曲线处处都在另一个分类器的 ROC 曲线上方(见图 1)。

图二。两个(或多个)模型可以组合成一条 ROC 曲线,对应于它们各自的 ROC 曲线的凸包。(来源:作者)
所以你可以系统地比较各种模型,直到找到 ROC 曲线最好的那个。结果可能是,最佳曲线不是来自单个分类器,而是来自两个或几个不同分类器的组合。重要的是,最后你总会有一条单一的最佳 ROC 曲线。(在分类器组合的情况下,该曲线是每个单独分类器的 ROC 曲线的上凸包[3],见图 2。)
此时,我们仍处于一个简单的世界。您可以客观地选择 ROC 曲线击败竞争对手的模型,并且您确定您将最佳球员带到了赛场。
不幸的是,选择了最佳分类器之后,您还远远没有完成。你还是要选择曲线上最好的点。那么问题是:哪个阈值最适合用户?
最佳精确度
(在本文的剩余部分,我们将展示一个训练好的二元分类模型的 ROC 曲线和其他特征。该模型仅被理解为一个示例——它是而不是在实际保险数据上训练的,而是在“成人”数据集上训练的[4]。)
乍一看,寻找最佳阈值似乎是一项微不足道的任务。追求最大的准确性,即尽可能多的预测是正确的。每一个其他的选择都会导致更多的错误。当然,我们希望避免这种情况,对吗?
准确性正式定义为所有预测中正确预测的比率,即


图三。在我们的例子中,可能的最佳精度是 85%。(来源:作者)
当我们计算本例中 ROC 曲线上每个点的 ACC 时,我们发现最大准确度为 85%(见图 3 和图 4)。那是我们能做的最好的吗?
有可能是这样,但只是在一种特殊的情况下,也就是说,当两种错误,假阳性和假阴性,从用户的商业角度来看是同样痛苦的。然而,在大多数情况下,这两种错误有着明显不同的影响,正如我们将看到的,我们的汽车保险索赔例子也不例外。

图 4。沿着我们示例的 ROC 曲线的准确性、成本和完全混淆矩阵。CST 已被重新调整以增强可视化,因此最大可能成本为 1。(来源:作者)
成本最优
错误决策造成的损失并不总是容易量化。权衡假阳性和假阴性是一个经典的难题:判一个无辜的人入狱(假阳性)比让一个杀人犯逍遥法外(假阴性)更糟糕吗?差多少?
幸运的是,在商业世界里,事情并没有那么戏剧化,只要付出一些努力,错误决策造成的损失就可以用金钱来量化。这让我们想到了成本估算。为了给假阳性和假阴性这两种可能的错误定价,我们必须检查在每种错误的情况下到底发生了什么。
在假阳性的情况下,完全正确的账单被不必要地发送给专家,然后专家花费一些宝贵的时间试图在没有错误的地方找到错误。为了简化计算,我们假设这个过程花费他 12 分钟,他的劳动总成本是每小时 100 €。那么,每个假阳性浪费 20 €。
在假阴性的情况下,支付带有不合理项目的发票。这意味着,保险公司不必要地损失了所述项目的相应货币价值。不合理索赔的平均值可以从历史案例数据中计算出来,这些数据已经过人类主题专家的检查和纠正。让我们假设,每箱是 100 €。
当然,这是成本估算的一种过于简化的表示,但它足以理解这一思想:最终,您将获得每种错误类型的明确的货币价值。在我们的例子中,它看起来像这样:

或者,换句话说,根据 TPR 和 FPR:

由于 FP 和 FN(或者等效地,TPR 和 FPR)取决于我们的阈值参数 p 的值,我们可以将成本绘制为 p 的函数,即 CST(p)。在同一张图中标出成本和精确度是有启发性的。为此,我们显示成本不是绝对值,而是最大可能成本的百分比(见图 5)。

图 5。准确度和成本相对于辨别阈值作图。作为参考,完整的混淆矩阵显示在右下角。(来源:作者)
具有最佳成本的操作点也可以从 ROC 曲线几何地确定。从上述将 CST 与 TPR 和 FPR 联系起来的等式中,我们注意到


图六。我们示例中的 ROC 曲线(蓝色)有几条等性能线(黄色),每条线对应一个固定成本。从左上到右下,成本垂直于等性能线增加。(来源:作者)
这意味着等价点排列在具有 0.2⋅(N/P).斜率的直线上这些线被称为等性能线【3】。成本随着错误率的增加而增加,也就是在 ROC 图右下角的方向。因此,在 ROC 曲线与最高等性能线相切的地方,成本最低(见图 6)。

图 7。精度最优和成本最优之间的成本差异会导致大量浪费。(来源:作者)
我们发现,在 76%的准确率水平下,最优成本为 29%。相比之下,最大准确率 85%水平的成本是 40%。因此,准确率提高 9 个百分点,每个案例的成本就会增加 11 个百分点(见图 7)。以高得多的最佳精度有效地操作系统会毁掉您客户的钱!
准确性(以及 F1 或 Matthews 相关系数等替代分数)本身没有价值。只有在与实际成本相联系时,基于彻底的成本估算,这些指标才有意义。
战略决策
既然已经找到了对应于最优成本的阈值,您是否应该相应地配置 AI?这取决于这样的配置如何适应用户更广泛的策略。例如,考虑经营保险业务的两家公司的不同观点。
第一家公司是传统的保险公司。他们从人工智能中获得的潜在好处是提高了索赔验证流程的成本效益。第二家公司是一家服务公司,向保险公司提供主题专业知识。
许多德国保险公司已将其各种损害类型的专业知识外包给专业公司,如 CarExpert、ControlExpert、Dekra、Eucon 和其他公司[5],并向他们支付费用以确定不合理的索赔。乍一看,专业公司似乎也可以简单地应用人工智能来最大化成本效率。然而,他们受到一个额外的约束:他们的客户不关心专家提供者端的不必要的工作(由误报导致),但他们非常关心由于未被发现的不合理索赔(由误报导致)而造成的金钱损失。根据上面定义的指标,保险公司根据 TPR 来衡量提供商的服务质量,除了非常高的价值之外,不愿意接受任何东西。正如我们在上面看到的,最优成本的 TPR 大约是 90%。从保险公司的角度来看,这个值是不可接受的,因为它意味着 10%的不合理索赔没有被注意到。
因此,供应商必须在成本效率和提供足够高的 TPR 之间取得平衡,而不是简单地以最佳成本运营。这给他们留下了两个基本选择。他们可以优先考虑降低运营成本,同时降低服务价格,以在 TPR 较低的情况下保持市场吸引力。或者,他们可以故意将产品质量置于价格之上,例如,以维持高质量服务的声誉,并以长期客户满意度为目标。如果他们选择后者,机器学习解决方案必须在非常高的 TPR 下运行(见图 8)。通过这种方式,提供商可以从适度的自动化率中获益,同时保持非常低的错误率,接近人类水平的性能。

图 8。优先考虑 TPR 减少了假阴性,但同时也损失了金钱和准确性。(来源:作者)
不利的一面是,与以最佳成本运行相比,以高 TPR 运行会导致每箱成本增加和准确度降低。实际上,所有这种准确性损失都可以归因于误报,遵循的逻辑是,只要找到大多数不合理的主张,人类专家做更多的工作是可以接受的。
不可能从数学上证明哪个选择是正确的。如何在市场中定位自己是一个超越任何公式的决定。困难不止于此。需要考虑的其他因素还有很多,例如公司战略、合规和监管问题、政治和道德考量等等。所有这些点的共同点是它们很难量化——如果有的话。单靠数学无法解决这些困难,在这种复杂的情况下,需要强大而聪明的领导才能找到正确的方法。这是经验丰富的高管(以及他们身边的顾问)能够大放异彩的时刻。
结论
现实并不像 Kaggle 竞赛那样清晰,人工智能在现实世界应用中的表现也不能简单地自动评分。这个问题在战略和人的层面上的成功是无法用公式计算的。从这个意义上说,AI 与商业运营的任何其他重大变革没有什么不同。在现实世界中实施人工智能是一个涉及众多利益相关者的过程,他们根据非常不同的指标评估解决方案的成败,这些指标通常无法用数学方法形式化。例如,由不满意的员工或客户造成的间接成本可能会延迟数月或数年才显现出来,从而使相关风险难以量化。由于这些原因,技术性能指标通常在变更管理过程中扮演重要但最终是次要的角色。
参考
[1] 团队力量,C€-简介 2019 ,第 21 页,2020 年 5 月 30 日检索
[2] T. Fawcett,ROC 分析介绍 (2006),模式识别字母, 27 ,861–874 页
[3] F. Provost 和 T. Fawcett,不精确环境的稳健分类 (2001),机器学习, 42 ,第 203–231 页(也可在 arχiv 上找到)
[4] 成人数据集 (1996),通过 Dua,d .和 Graff,C. (2019), UCI 机器学习知识库提供
[5]k . Braun worth,Wertorientiertes prozess management von Dienstleistungsprozessen(2009 年),博士论文,第二节。B1–8
原载于 2020 年 6 月 6 日https://consilica . de。
在 5 分钟内编排 Jupyter 笔记本
原文:https://towardsdatascience.com/how-to-orcestrate-jupyter-notebooks-752aa8081208?source=collection_archive---------31-----------------------
用 Bayesnote 替代笔记本用户的气流
Jupyter notebook 是数据科学家中最受欢迎的交互式开发环境。虽然有一次性任务,例如 Jupyter 笔记本电脑就足够了的数据探索,但许多数据科学家很难维护他们长期运行的数据管道,以刷新报告、仪表板和机器学习模型。他们的解决方案非常有限:
- 克朗。这是最古老和最常用的解决方案。数据科学家在服务器上设置 cron 时间表,以触发笔记本电脑按照固定的时间表运行,例如每天早上 5 点。Cron 不足以完成这样的任务。
然而,随着数据团队开始编写更多的 cron 作业,不断增长的数量和复杂性变得难以管理。特别是,管理作业之间的依赖关系非常困难。其次,故障处理和警报必须由作业来管理,因此作业或随叫随到的工程师必须处理重试和上游故障,这很麻烦。最后,对于回顾团队来说,必须手动筛选日志来检查某一天的工作执行情况,这是一个时间陷阱。由于这些挑战,数据编排解决方案应运而生。(由阿斯塔西亚·迈尔斯
2.气流 ,及其竞争对手(路易吉 和 达格斯特 )。这种解决方案解决了 cron、处理故障以及用户定义的任务的依赖性等问题。下面的代码是一个 bash 任务,打印 Airflow 官方教程提供的数据。
t1 = BashOperator(
task_id='print_date',
bash_command='date',
dag=dag,
)
Airflow 及其竞争对手的目标用户主要是数据工程师或 ETL 工程师,他们可能习惯也可能不习惯对实际执行的代码进行强制抽象(例如“print_date”)。一方面,这种抽象对于实现 Airflow 及其竞争对手的设计目标,减少维护数据管道的成本和麻烦是必不可少的。另一方面,这种抽象或“外部代码”本身会引发新的问题:数据科学家需要付出学习成本,他们不得不在调试中的精确问题上花费更多时间。
- Argo 和其他基于 Kubernetes 的解决方案。Argo 及其竞争对手在 Kubernetes 上编排 Docker 容器,而不是编排通常是 python 函数的气流任务。它们解决了维护数据管道和环境的问题,而不用担心从本地开发环境转移到生产环境时会丢失一些系统级的依赖。然而,即使有像 AWS 这样的云平台的帮助,运营 Kubernetes 集群也是昂贵且耗时的。对于大多数公司来说,雇佣一个有经验的 Kubernetes 工程师是不可行的。有针对 docker 的学习曲线:如何启动/停止 docker 容器,将 shells 附加到正在运行的容器,重置 root 密码,构建、推送和维护 docker 映像。

照片由蒂姆·阿特伯里在 Unsplash 拍摄
工作流编排考虑的基本设计考虑是由这样的系统解决的问题必须比产生的问题大得多。否则,它只会帮助数据科学家简单地将他们修复 cron 问题的时间转移到修复工作流编排系统的问题上。
为了实现这个目标,这种系统必须做出比上述当前解决方案弱得多的假设。这就是我们开发 Bayesnote 的原因。我们做一个最弱的假设:即使数据团队仅由一名数据科学家组成,他们也可以在 5 分钟内开始在不同的集群上编排笔记本电脑。那儿有
- 没有学习曲线。不需要学习抽象概念,也不需要 docker/Kubernetes 知识。
- 无运营成本。没有额外的数据库安装,没有端口打开。它可以毫无困难地将自己安装到集群中。

Bayesnote
主持人:
- 添加要用来运行笔记本的主机。确保 Jupyter 笔记本已经安装。

2.一键打开远程笔记本,浏览器会在随机端口打开 Jupyter 笔记本。

3.写你的代码。print("Hello bayesnote")
流程:
- 创建一个新流程。在
next中添加 depdency。

2.启动 a 流程。

3.点击显示查看笔记本。浏览器将打开一个新的选项卡来显示输出笔记本。

就是这样。

输出笔记本
我全职从事这个项目。让我知道你的想法。欢迎提问、评论、功能请求和拉动请求。
该项目正在快速增加新功能:https://github.com/Bayesnote/Bayesnote
如何组织机器学习团队取得成功
原文:https://towardsdatascience.com/how-to-organise-your-machine-learning-teams-for-success-199f544afd20?source=collection_archive---------21-----------------------
优步、Linkedin 和 AirBnb 探索将机器学习融入组织的三种组织形式

职能团队组织、中央团队组织还是混合团队组织?图片由作者提供。
优步、LinkedIn 和 Airbnb 都是大规模机器学习的成功故事,不是因为它们产生了很酷的研究或有很多人才,而是因为它们实际上成功地将数据转化为金钱和很多钱。
这三家公司都花了数年时间探索组织机器学习工作的不同方式。
我想分享我从他们的努力中获得的关键见解,这样你就不必花费数年来探索不同的模式。
组织机器学习工作的三种方式
组织机器学习工作的方式实际上只有三种,这三种方式各有优缺点,要么让你的机器学习工程师失业,要么让他们成为你最有价值的资产。
因此,让我们来看看三种不同的方式:功能上的 —在一个大型机器学习或数据科学或分析功能中,分散的 —在一个产品/工程团队中,或者两者的混合形式。
功能上有组织的机器学习工作可能涉及一个拥有十几名数据科学家的分析部门,或者几个生产 API 的机器学习团队。分散化机器学习工作可能会将机器学习工程师直接整合到产品工程团队中,也可能会将一个机器学习团队与其产品团队一起置于一个单一的产品经理之下。
公司通常从集中的、功能性的方法开始,并且经常失败。有些人设法过渡到分散或混合模式,有些人干脆停止亏损,少数幸运儿坚持下去。
所以让我们从一个工作功能模型的例子开始吧!
AirBnB &优步的功能数据科学团队
尽管许多公司都放弃了功能性的中央模型,但优步公司在多年的机器学习后仍然采用了这种模型。所以我发现看一看它们非常有用。
优步有一大批机器学习工程师、数据科学家等。艾尔。他们在只有机器学习工程师和数据科学家的大型团队环境中,从功能上组织它们的一部分。如果产品工程团队需要他们不能做的事情,这需要机器学习/数据科学专业知识,产品工程团队可以与专家机器学习者和数据科学家合作一段固定的时间,例如三个月。

两个功能组织单元(工程和机器学习)之间的协作,例如基于项目的协作。图片由作者提供。
这个模型有一堆关键优势,首先,它最大限度地减少了公司中数据科学/机器学习功能的空闲时间。这反过来意味着公司可以非常早地启动这样的功能。例如,Airbnb 聘请了一名数据科学家作为其第八名工程师,并在此后相当长的一段时间内使用中央模型来分配工作。
第二,它最大化了跨职能部门的知识共享,从而允许开发知识深度、设定标准、创建共享技术堆栈。所有这些都使评估功能需求的时间最小化。
因此,选择采用这种组织形式的公司旨在通过采用共享的技术堆栈、定期研讨会和跨职能部门的大量知识共享工具来释放这些优势,并由一个中央产品经理跨职能部门分配工作量。他们在与工程团队的合作上有明确的界限,比如“3 个月的项目”,如果合理的话,他们会移交代码、所有权和专业知识,以免产生耦合。
LinkedIn 的去中心化方法
LinkedIn 公司也是从一个中心模式开始的,这是一个我称之为“数据科学家”的职能团队,目的是通过为其他团队开发酷的东西来“创造伟大的东西”。
但他们很快意识到这在 LinkedIn 不起作用。引用前 Linkedin 的 DJ Patil 的话:“那些家伙(数据科学家)提出伟大的想法,展示数字,然后被告知这不在[产品团队]的路线图上……
他们会设计一个“推荐引擎”的原型,展示大量的数据,但无法让一个工程团队合作并为其构建一个前端。解决办法?他们转向了一个分散的模式,一个全栈团队。他们把他们变成了一个完整的产品团队,然后创建了 PYMK,他查看了我的个人资料、技能和职业探索。该团队包括设计、网络、产品营销、工程,PYMK 功能成为 Linkedin 团队有史以来最成功的产品之一,将 LinkedIn 的北极星指标提升了 50%。
“矛盾的是,建立一个数据团队的结果是,你会看到公司的各个部门都在生产数据产品。当公司看到数据可以创造什么,当它看到数据的力量,你会看到数据产品无处不在。这就是你知道自己何时赢了的方法。”()

强大的全栈去中心化团队,将机器学习工程师整合到需要他们的团队中。图片由作者提供。
Spotify 从一开始就采用了这种模式,将机器学习工程师整合到产品团队中。在 Spotify Weekly 工作的机器学习工程师坐在同样的单位里,也创建了前端,使他们在这个产品上完全授权。
这种模式的第一个优势是产品所有权的集中。这导致了快速的循环时间。将一个新的机器学习想法投入生产所花的时间与添加一个新的下拉选项所花的时间一样长。无需整合不同团队的路线图。这当然释放了机器学习的真正潜力,因为它真的是唯一允许实验的东西,而这在协作环境中几乎是不可能的。
有没有尝试过说服另一个团队构建一个前端特性,这样你就可以运行一个“实验”,并有可能再次杀死前端特性?
第二个优势是产品知识的集中。机器学习者和前端开发人员参与所有的团队活动,并获得他们需要的所有知识,以高速交付正确的东西。
优步的混合模型及其研究
优步虽然是一个工作职能部门的好例子,但实际上是一个混合模型。但优步认识到,团队中的机器学习工程师、从事项目工作的专家机器学习工程师和数据科学家,以及旨在提供公司相关研究的研究团队之间需要明确的区分。
混合模型的优势从单个模型的优势中显而易见。它具有所有的优势,但在组织和沟通方面增加了很多开销。因此,它最适合工程方面的大型功能或异构需求。

混合全栈团队、项目专家协作和研究团队的混合模型。图片由作者提供。
如果一家公司有 1-2 个产品团队有很多机器学习需求,20 个其他团队有一些需求,那么混合模式可能是有意义的。
致力于混合模式的公司试图通过开发通用的机器学习框架来减轻可能的弱点,比如优步与 Ludwig 一起开发的框架。像 Spotify 一样聚合技术,将所有机器学习的努力集中在 TFX 和 Kubeflow 管道上。
不要利用弱点
人工智能、机器学习、数据科学都是热门的新趋势,但最终唯一重要的是将这些新东西转化为商业价值。
Airbnb 是深度数据驱动的,并且总是试图最大化他们数据的商业价值。Airbnb 也认识到了职能数据科学组织的弱点。他们意识到,一个核心职能部门既缺乏产品专业知识,也缺乏产品工程团队的工程技能。因此,他们为他们的数据科学家创造了一种教育形式,使他们能够培养这两种技能。
为你的公司选择错误的模式,你的努力将浪费金钱,并最终关闭努力。选择正确的模型,释放模型的优势,而不是迎合它的弱点,你将能够将机器学习和数据科学深入整合到公司中,远远超出分析功能。
进一步阅读
在写这篇文章时,我参考了上述公司提供的一堆不同的文章和文件。我会试着把它们都列在这里,这样你就可以深入了解这些公司的个人经历。
- Airbnbs 计划教授数据科学家工程技能。
- 一篇深入优步机器学习结构的中等帖子。
- 一篇文章解释了 Airbnbs 从中央车型到混合动力车型的旅程。
- 2011 年,DJ Patil,建立数据科学团队,讲述了他在 Linkedin 的经历以及更多内容,解释了 Linkedin 的历程以及更多内容。
对如何建立伟大的数据公司、伟大的数据密集型产品、成为伟大的数据团队感兴趣,还是对如何利用开源构建伟大的东西感兴趣?然后考虑加入我的 免费简讯《三个数据点周四》 。它已经成为数据初创企业、风投和数据领导者值得信赖的资源。
如何组织机器学习项目
原文:https://towardsdatascience.com/how-to-organize-machine-learning-projects-babd04f7a679?source=collection_archive---------29-----------------------
Python,Git,Anaconda,Code,没有 Jupyter 笔记本

图片作者。子图片都是由作者或允许(见个人链接后)。
这篇文章描述了组织机器学习项目的最佳实践,我在攻读机器学习博士学位期间发现这些实践非常有效。
Python
Python 是一种很棒的机器学习语言。Python 包含了一系列对 ML 非常有用的库:
- numpy : n 维数组和数值计算。对数据处理有用。
- 熊猫:数据分析库。pandas 数据帧本质上是用描述性字符串作为行和列标签的 numpy 数组。它们可以被排序、过滤、分组、连接等。对数据处理有用。
- PyTorch :构建神经网络。包括许多预训练的模型和干净的计算机视觉数据集。PyTorch 是我最喜欢的神经网络库,因为它鼓励使用面向对象的编程(模型是一个类,数据集是一个类,等等。),用 PyTorch 写代码很快,PyTorch 默认支持急切执行,所以可以和 Python 调试器一起使用。
- tensor flow:py torch 的替代品,在业界更受欢迎。几年前,我使用 TensorFlow,但在改用 PyTorch 后,我再也没有回头。我发现 PyTorch 更适合做研究。如果你想使用 TensorFlow,并且你想要一个更高级别的接口,你可以使用 Keras 。
- 这是一个很好的库,用于回归、支持向量机、k 近邻、随机森林、计算接收器工作特性下的面积、计算混淆矩阵等。
- matplotlib 和 seaborn :制作可爱的可视化效果!我将在后面的章节中介绍这些库。
Git
Git 版本控制对于保持机器学习项目的有序非常有用。
Git 是一个工具,可以用来跟踪您对代码所做的所有更改。Git“存储库”是包含代码文件的目录。Git 使用节省空间的技术,因此它不会存储代码的多个副本,而是存储旧文件和新文件之间的相对变化。Git 有助于保持您的代码文件目录整洁有序,因为只有最新版本“明显”存在(尽管您可以随时轻松访问任何版本的代码)。您可以选择何时标记已经发生的更改,使用“提交”将特定的代码更改与您提供的书面描述捆绑在一起。Git 存储库也使得代码共享和协作变得容易。总的来说,与在“myscript_v1.py”、“dataprocessing_v56.py”、“utils_73.py”等下保存一百万个不同版本的代码相比,Git 是保留旧代码功能的更好的解决方案。
Git 版本控制可以通过 GitHub、GitLab 和 Bitbucket 获得。我最常使用 GitHub。一旦你设置好 GitHub 并习惯了使用它,建立一个新的资源库大约需要 2 分钟。

Octocat,允许在博客帖子中使用 GitHub 徽标和用法
以下是在您的机器上安装 GitHub 的步骤:
- 安装 Git:【https://git-scm.com/downloads】T2
- 制作 GitHub 账号【www.github.com
- 通过 SSH 密钥将您的 GitHub 帐户与您的机器连接起来。这一步使您能够将代码从您的机器推送到 GitHub 的云存储中。参见生成新的 SSH 密钥,向您的 GitHub 帐户添加新的 SSH 密钥
- 在 GitHub 上创建一个新的资源库,方法是在您的个人资料的“资源库”部分点击绿色的“新建”按钮。
- 使您的计算机能够推送至该存储库(请注意,在您创建存储库之后,GitHub 会立即为您提供这些说明以及存储库的正确 URL 以下命令只是一个示例):
echo "# pytorch-computer-vision" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M master
git remote add origin https://github.com/rachellea/pytorch-computer-vision.git
git push -u origin master
假设您现在已经更改了 myeditedscript.py .中的一些代码,以“提交”到存储库(即记录该更改):
git add myeditedscript.py
git commit -m 'added super useful functionality'
git push origin master
蟒蛇
Anaconda 是一个包管理器。它允许创建不同的计算环境,这些计算环境可能包含不同的 Python 版本和/或不同的包和/或不同的包版本。当您处理多个具有冲突依赖关系的项目时,Anaconda 尤其有用。
Anaconda 很容易使用。步骤:
首先,安装 Anaconda:https://docs.anaconda.com/anaconda/install/
接下来,创造一个环境。我发现以项目命名环境很有用。例如,如果项目是关于胸部 x 光分类使用神经网络,环境可以被称为 chestxraynn:
conda create --name chestxraynn python=3.5
请注意,您不希望在环境名称两边加上引号,否则引号字符本身将成为环境名称的一部分。此外,您可以选择任何想要的 Python 版本。它不一定是 Python 3.5。
一旦创建了环境,就该激活环境了。“激活”仅仅意味着你将被“放入环境中”,这样你就可以使用安装在环境中的所有软件。
要在 Windows 上激活环境,请运行以下命令:
activate chestxraynn
在 Linux 或 macOS 上,
source activate chestxraynn
您可以使用“conda install”命令在环境内部安装软件包。
例如,安装 matplotlib 的 conda 命令是:
conda install -c conda-forge matplotlib
你可以谷歌“conda install packagename”来找到告诉你运行什么 conda 命令来安装该软件包的页面。从技术上讲,在 conda 环境中,你也可以使用 pip 安装包,但是这会导致问题,所以如果可能的话应该避免。
Anaconda 将负责确保环境中所有内容的版本都是兼容的。更多命令见 Conda 备忘单。
也可以从别人放在一起的文件中创建一个 conda 环境。在 GitHub 库https://github.com/rachellea/pytorch-computer-vision中,有一个名为 tutorial_environment.yml 的文件,这个文件指定了运行教程代码所需的依赖关系。要基于该文件创建 conda 环境,您只需在 Anaconda 提示符下运行以下命令:
conda env create -f tutorial_environment.yml
组织你的代码:类和函数
代码组织非常重要。在过去的不同时期,我遇到过研究代码被数千行代码塞进一个模块,没有文档,重复的代码块到处复制粘贴,一些代码块没有解释就被注释掉,还有奇怪的变量名。代码不会运行,即使运行了,也可能是不正确的。
我也遇到了许多优秀的代码——例如,我在 PyTorch 实现中看到的所有代码都是有组织的,并且有良好的文档记录。
从长远来看,如果你为自己的项目编写高质量的代码,将会节省你很多时间。高质量代码的一个方面是它在模块中的组织。
建议:
- 使用面向对象的编程。我强烈推荐 PyTorch 作为机器学习框架,因为它有助于在任何事情上使用面向对象编程。模型就是一个类。数据集是一个类。等等。
- 使用函数。如果你写的东西不能很好地作为一个类,那么就把代码组织成函数。功能是可重用的。全局命名空间中的代码块是不可重用的。

有组织代码的示意图。图片作者。
组织你的代码:目录
使用多个模块来组织代码,并将这些模块组织到目录中。
我喜欢的一个简单的示例组织展示在我为这篇文章和其他相关文章整理的 GitHub 库中:【https://github.com/rachellea/pytorch-computer-vision
整体组织如下:
- 一个用于训练/评估/测试循环的模块(src/run_experiment.py)
- 一个用于计算绩效指标的模块(src/evaluate.py)
- 一个(或多个)数据处理模块:(load_dataset/custom_pascal.py 和 load_dataset/custom_tiny.py)
- 模型的一个(或多个)模块:models/custom_models_base.py
以下是存储库的整体组织结构:

组织py torch-计算机视觉。图片作者。
请注意,虽然这个存储库中存储了一个数据集(这些 png 位于“train”、“val”和“test”目录中),但一般来说,将数据集放入存储库并不是一个好主意。这个存储库中有一个数据集的唯一原因是因为它是一个很小的假数据集,是为了举例而创建的。除非您的数据非常小,否则不应该放在存储库中。
导入
请注意,您需要一个名为 init 的空文件。py,以便模块可以从这些目录中导入文件。
下面是如何让一个名为 awesomecode.py 的模块导入一个名为 helpercode.py 的模块,这是基于它们相对于彼此所处的目录:

作者图片
文档
写很多文档是有好处的。评论一切。用 docstrings 记录所有的函数、方法和类。有时候,在编写函数之前对它进行文档化是很有帮助的。如果文档有时比代码长也没关系。“过于清晰”总比不够清晰好。

作者图片
上图是一个简单的函数 rand_rotate(),它随机旋转一个代表 CT 体积的 3D numpy 数组。可以通过指定

作者图片
上图显示了我的数据处理教程 代码中的一些文档。
文档将确保当你回顾旧代码时,你能很快记住它做了什么。当你看到一些看起来很奇怪的东西并本能地改变它时,文档将防止你意外地破坏你自己的代码——如果它旁边有一个注释解释为什么奇怪的东西是必要的,你就不去管它。文档也能让其他人使用你的代码。
命名变量
总是使用描述性的变量名。“volumetric_attn_gr_truth”是比“truth”更好的变量名(什么 truth?),而且比“gt”或“g”好得多。如果你的变量有很长的名字也没关系。他们不应该有单字母的名字。
即使你正在对行和列进行迭代,也要使用“row”和“col”作为你的变量名,而不是“I”和“j”。我曾经花了一整天的时间寻找一个非常奇怪的 bug,结果发现它是由于错误地迭代了一个 2D 数组引起的,因为我在数百行代码中的一行代码中调换了“I”和“j”。那是我最后一次使用单字母变量名。
单元测试
很多人声称他们没有时间为他们的代码编写测试,因为“这只是为了研究。”我认为测试研究代码甚至更重要,因为研究的全部意义在于你不知道什么是“正确的答案”——如果你不知道你的代码产生的答案是否正确,你怎么知道你是否得到了正确的答案?
每次我花一天时间为我的代码编写单元测试时,我都会发现错误——有些很小,有些更严重。如果你写单元测试,你将捕捉你代码中的错误。如果你为别人的代码编写单元测试,你也会在他们的代码中发现错误。
除了促进代码的正确性,单元测试还有助于执行良好的代码组织,通过阻止你编写一次做太多事情的“神函数”。God 函数通常是测试的噩梦,应该被分解成更小、更易管理的函数。
至少,对代码中最关键的部分进行单元测试是个好主意,比如复杂的数据处理或者模型中奇怪的张量重排。确保你的代码是正确的从来都不是浪费时间。
你可以在这里看到一个非常简单的单元测试的例子。这些单元测试包括出于演示目的对一些内置 PyTorch 函数的测试。
用可视化检查代码
特别是在计算机视觉中,使用可视化来执行健全性检查是非常有用的。
matplotlib 非常适合查看图像、分割图、带边框的图像等。以下是通过将 matplotlib 的 imshow()函数应用于输入图像而生成的可视化示例:

matplotlib imshow 生成的示例图像,来自图像演示。Matplotlib 使用一个 BSD 许可证,这是一个许可的自由软件许可证。
seaborn 专为统计数据可视化而设计。它非常适合制作热图和制作复杂的性能指标可视化。以下是一些在 seaborn 中用大约一行代码就可以绘制出的图形示例:

分别由seaborn group violin plots、seaborn group box plots和 seaborn heatmap 制作的示例图像。seaborn 使用一个 BSD 许可证,这是一个许可的自由软件许可证。
matplotlib 和 seaborn 都可以用于创建可视化效果,即时显示输入数据是否合理,基础事实是否合理,数据处理是否没有意外出错,模型的输出是否有意义,等等。
演示 0:单元测试和可视化
在教程存储库中,Demo-0-Unit-Tests-and-visualization . py将运行 src/unit_tests.py 中的单元测试,然后将运行 PASCAL VOC 2012 数据集图像和分段基础事实的可视化。
为了运行演示的可视化部分,将 Demo-0-Unit-Tests-and-visualization . py 中的路径更改为您的计算机上的路径,您可以在该路径中存储 PASCAL VOC 2012 数据集,并取消注释路径下的行以下载数据集。一旦数据集被下载,您就可以运行可视化。进行可视化的代码在load _ dataset/custom _ Pascal . py中。此刻,在演示文件中,images_to_visualize 的总数被设置为 3;如果您想要可视化更多的图像,您可以进一步增加该数字,例如增加到 100。
这是可视化效果的样子:

图片作者。原帕斯卡 VOC 2012 年飞机验证集图像。

图片作者。PASCAL VOC 2012 验证集已重新采样为 320 x 320 像素的飞机图像。图像重采样使用 torch . nn . functional . interpolate(mode = ' bicubic '),而分割基本事实重采样使用 PIL 调整大小(重采样=PIL。Image.NEAREST)即最近邻重采样。
从这些图像中,我们可以推断出一些有用的东西:
- 输入图像和地面实况分割之间的映射是正确的。
- 用于定义逐像素分割基础事实的整数和标签描述字符串之间的映射是正确的。例如,1 正确映射到“飞机”
- 重采样步骤不会“破坏”输入图像或分割基础事实,也不会导致它们严重错位。
终端中的可视化
如果您处于“非交互式环境”(即没有图形用户界面的终端),那么您需要关闭交互式绘图并保存您的图形,以便您可以在其他地方打开它们:
import seaborn
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
plt.ioff() #seaborn figure:
heatmap = seaborn.heatmap(some_dataframe, cmap = 'Blues', square=True, center=0)
heatmap.get_figure().savefig('Descriptive_Figure_Name.png',bbox_inches='tight')
plt.close() #matplotlib figure:
plt.imshow(chest_x_ray,cmap='gray')
plt.savefig('Other_Descriptive_Figure_Name.png')
plt.close()
Python 调试器
Python 调试器是一个非常有用的工具,因为它允许你在程序崩溃的地方检查状态中的一切,并在程序崩溃的地方运行代码片段,这样你就可以尝试可能的解决方案。使用 Python 调试器比使用 print 语句进行调试要高效得多,它将为您节省大量时间。Python 调试器也可以与 PyTorch 一起使用;您可以检查张量、梯度、测井数据帧等。
要使用 Python 调试器在终端中交互式运行脚本,请使用以下命令:
python -m pdb myscript.py
您将看到一个(Pdb)提示符出现。键入“c”继续。(这只是一个单独的小写字母 c,表示继续)。
要退出 Python 调试器,请使用‘q’(这是一个单独的小写字母 q,表示退出)。您可能需要使用 q 两次才能完全退出。
如果你想在程序的某个特定点停止,那么你可以在相关模块中导入 pdb,然后在你想停止的特定点放置“pdb . set _ trace()”。或者,如果你不想麻烦导入 pdb,你可以只在你想停止的地方写“assert False ”,这将保证程序在你想它死的地方死亡(尽管这不是使用 Python 调试器的正式方式)。
不要用 Jupyter 笔记本
鉴于前面的所有章节,我现在必须推荐永远不要使用 jupyter 笔记本进行机器学习项目,或者实际上进行任何需要花费你几天以上时间的编码项目。
为什么?
- 笔记本鼓励你在全局名称空间中保存所有的东西,这产生了一个巨大的模块,它做所有的事情,没有函数,没有类,也没有任何结构。
- 笔记本使得重用你的代码更加困难。功能可重复使用;“单元格 5、10 和 13 中的代码”不可重复使用。
- 笔记本使单元测试变得困难。函数和方法可以进行单元测试。“单元格 5、10 和 13 中的代码”不能进行单元测试。
- 你的代码越有组织(比如,越细分成类和函数),笔记本的交互性就越差——而交互性是人们喜欢笔记本的主要原因。笔记本吸引人的交互性本质上与高度结构化、组织良好的代码相反。
- 笔记本很难正确使用 Git 版本控制。笔记本只是大量的 JSON 文件,所以正确地合并它们或者用它们做拉请求基本上是不可能的。
- 笔记本使与其他人合作变得困难。您必须“轮流”在笔记本上工作(而不是像“常规代码”那样从同一个回购中推/拉)。
- 笔记本有一个非线性的工作流程,这与可复制的研究完全相反。你不必“以特定的顺序运行单元格”来复制别人的工作。
笔记本有什么用?一些可能可接受的用例是初始数据可视化、家庭作业、“演示风格”软件和交互式演示。(然而,我认为所有这些都可以不使用 jupyter 笔记本来完成。)
我不是现存的唯一一个认为机器学习项目最好避免使用 jupyter 笔记本的人。如需进一步阅读/参考,请参见 Daoud Clarke 的为什么我不用 Jupyter 笔记本,你也不应该用;【jupyter 笔记本烂的 5 个理由亚历山大穆勒著;克里斯蒂娜·杨的《T4》和《笔记本反模式》。
目标
两个有用的目标是:
- 编写正确易懂的代码。如果你的代码是正确的,你的模型更有可能产生好的结果,你的研究结论将是正确的,并且你将创造一些实际有用的东西。
- 确保任何人都可以通过在终端中运行一个命令(例如“python main.py”)来复制您所做的一切,例如您的模型、结果、图形。这将有助于他人建立在你的工作之上,也将有助于“未来的你”建立在你自己的工作之上。
总结
- Python 是一种优秀的机器学习语言
- Git 版本控制有助于跟踪不同版本的代码。它可以通过 GitHub 获得。
- Anaconda 是一个包管理器,可以创建不同的环境,其中可能包含不同的 Python 版本和/或包。当处理多个具有冲突依赖关系的项目时,这很有用。
- 将代码组织成模块中的类和函数。在 Git 存储库中以分层目录结构组织模块。
- 用注释和文档字符串记录您的代码
- 使用描述性的变量名。不要使用单字母的变量名。
- 编写单元测试,尤其是对于数据处理和模型中最复杂或最关键的部分。
- 使用 matplotlib 和 seaborn 可视化工具可视化您的数据集、模型输出和模型性能
- 使用 Python 调试器进行快速、高效的调试
- 不要将 jupyter 笔记本用于机器学习项目
机器学习快乐!

维基百科的微笑猫,知识共享许可
原载于 2020 年 9 月 22 日【http://glassboxmedicine.com】。
如何用 Github 组织你的数据科学文章
原文:https://towardsdatascience.com/how-to-organize-your-data-science-articles-with-github-b5b9427dad37?source=collection_archive---------20-----------------------
被新信息淹没?现在,您可以轻松地跟踪文章并为其创建自定义注释

从下一个网页中检索
动机
在数据科学领域,每天都有大量的论文和文章发表。许多像 Medium 这样的网站都有一个高效的推荐系统,可以很好地推荐那些我们无法抗拒点击的文章。一篇接一篇的文章似乎都很有用。所以我们继续阅读,要么关闭标签,要么保存文章以备将来参考。既然我们每天都会碰到很多文章,那我们一定是被新的信息所告知,对吗?不完全如此。
质量比数量更重要。一个本垒打比两个双打好得多。—史蒂夫·乔布斯
我们吸收新知识的最好方式是使用它。无论我们读了多少技术文章,如果我们不应用新知识,我们将几乎什么都不会保留。我们现在可能会记住一些东西,但一周后就会忘记。但是仔细想想。在快节奏、超负荷的社会,我们阅读一篇文章的常用策略是什么?

我的文章堆在我的 Instapaper 文件夹里
当我们阅读一篇有用的文章时,我们通常不会马上尝试代码、探索工具和深入概念,而是保存它。要么是因为我们正在使用手机阅读文章,要么是因为我们想在需要时试用代码和工具。当我们回顾我们保存的大量文章时,我们会不知所措,并发现浏览这些文章以找到一篇对我们当前项目有用的文章非常耗时。那么什么是解决方案呢?
现有工具的问题
有很多工具可以让我们保存你的文章,并对它们进行分类。但是使用这些工具保存文章有几个缺点:
- 我们只是保存这些文章,因为它们很有趣,但不太确定如何以及何时应用它们
- 我们需要重读某一特定类别中的文章,以找到包含我们要寻找的信息的文章,而这些信息可能是一些很小的东西,比如代码片段
- 如果我们对文章有一些问题或意见,我们要么回到文章的网站,要么在网上发布问题,这很费时间,等等
好消息是,我们不需要花太多时间来组织你的文章!有了 Github,并在平台的使用上稍加改动,我们可以高效地组织文章。
欢迎来到 Github 及其问题选项卡
Github 是一个轻量级平台,它将开发者聚集在一起,发现、共享代码并构建更好的软件。Github 有一个 Issues 选项卡,允许用户请求关于现有代码的问题。我们将把这个选项卡用于另一个目的:组织和总结我们的文章。大概是这样的:

探索这个仓库这里。这就是为什么您应该开始使用和贡献这个库的原因:
- 整理你的文章,以便很容易找到你的文章以备将来参考
- 不看整篇文章,快速复习文章重点
- 总结的艺术将帮助你更好地保留和理解信息
- 通过看别人喜欢的文章来节省阅读低质量文章的时间
- 对问题评论区的文章提问或发表意见
我是 Github 的新手。我还能用吗?
是的,当然!这个存储库的构建使得任何人都可以轻松开始。每当您找到一篇想要保存的有趣文章时,请单击左上角“代码”旁边的“问题”按钮,然后单击右上角的“新问题”。

将显示一个模板。你需要做的就是填写模板。想象一下,就像你的笔记本一样,你想快速保存一篇文章的基本信息,这样你就可以很容易地在将来快速保留这些信息,或者让其他人看到并知道这篇文章的内容。

模板
以下是该模板中各部分的简要描述:
- TL;博士——论文的简短摘要。
- 文章链接。
- 作者
- 关键要点——文章中你觉得有用的部分。
- 有用的代码片段——您希望保存以备后用的有用代码
- 有用的工具 —你想尝试或整合到你的工作流程中的有用工具
- 评论/问题 —您对文章的想法或问题。
- 图像(可选)—为您提供文章内容的直观描述
这是点击“提交新问题”后模板的外观

Github 链接
请随意跳过任何与您正在寻找的内容无关的部分。记住,把这个当成自己的文件夹。把你认为对自己回顾会有用的东西写下来就行了!如果一篇文章有很多条信息,有些你已经知道了,懒得写在模板里。写下你想写的任何东西。写点东西总比一路放弃好。
最后但同样重要的是,使用标签相应地标记文章的类别。

您也可以使用评论部分作为讨论、评论、提问或对文章给出反馈的地方。

结论
花在组织上的每一分钟,都是一小时的收获。—本杰明·富兰克林
在这个信息超载的社会,我们不需要成为那些被新信息淹没而一路放弃的人。我们只需要改变我们的方法,这样我们就可以更有效地做我们经常做的事情。开始使用这个存储库来组织和保留更多信息。我希望通过这个平台,我们可以一起建立一个社区,在那里每个人都渴望学习和分享有用的知识。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上和我联系。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
[## 如何用 Ngrok 用 3 行代码分享你的 Jupyter 笔记本
想象一下,让你的朋友在远程机器上使用你的本地 Jupyter 笔记本
towardsdatascience.com](/how-to-share-your-jupyter-notebook-in-3-lines-of-code-with-ngrok-bfe1495a9c0c) [## 如何使用 HyperDash 远程监控和记录您的机器学习实验
培训需要很长时间才能完成,但你需要去洗手间休息一下…
towardsdatascience.com](/how-to-monitor-and-log-your-machine-learning-experiment-remotely-with-hyperdash-aa7106b15509) [## 当生活不给你喘息的机会,如何学习数据科学
我努力为数据科学贡献时间。但是发现新的策略使我能够提高我的学习速度和…
towardsdatascience.com](/how-to-learn-data-science-when-life-does-not-give-you-a-break-a26a6ea328fd) [## 使用 Python 最大化您的生产力
你创建了一个待办事项清单来提高效率,但最终却把时间浪费在了不重要的任务上。如果你能创造…
towardsdatascience.com](/maximize-your-productivity-with-python-6110004b45f7)
如何克服编码障碍
原文:https://towardsdatascience.com/how-to-overcome-coders-block-51ece9dafe00?source=collection_archive---------8-----------------------
当你害怕你的游戏机时

游戏机可能会令人生畏。Patrick Amoy 在 Unsplash 上拍摄的照片
H 你有没有觉得自己完全被堵住了?你曾经盯着你的空白屏幕几个小时,不能记下任何东西吗?欢迎加入俱乐部。
当我走进房间时,你正在滔滔不绝地谈论你的计算机科学作业。你的桌子上堆满了脚本和条款清单。你的电脑屏幕是一个黑色的大空间,除了左上角闪烁的白色指针。整个房间似乎都在尖叫着说出你的绝望。
“一切都好吗,”
不——我计算机科学课的作业快把我逼疯了。明天就要交了,而我连一行代码都没写!
“你现在已经做了多长时间了,”
“三个小时,”
好了,该休息了。“你想喝杯茶吗?”

编码很难。一杯热饮料会有帮助。 Goran Ivos 在 Unsplash 上拍摄的照片
是的,但是——”
之后你就可以回去完成你的任务了。
你跟着我下楼,我打开水壶。一旦我们的茶倒了,我们回到你的房间。
只是——我什么也不懂。我坐在那里,想了又想,就是做不到。
有什么问题?“你知道你应该做什么吗,”
原则上,是的。但是我不知道如何告诉电脑它应该做什么。“我该怎么开始呢,”
你害怕游戏机。
呃。“是的,我想是的,”
这就像作家的块。有时当你写作时,你会在一张白纸前坐几个小时,一个字也记不住。在某些时候,你会害怕那张纸,因为你已经看了很久了。
同样的情况也发生在编码器的区块。你盯着你的控制台,什么也做不了,直到控制台吓到你。
是的,听起来很熟悉。
一段复杂的代码由许多简单的子程序组成
让我们一步一步来。我们将从编写一个 Hello-World 程序开始。
“但这很简单,我们五周前就这么做了,”
这正是我们再次这么做的原因。很简单,所以你不会被屏蔽。
好吧,等等……
你打开一个新的文本文件。
在打印 Hello-World-message 之前,我必须包含一些包吗?
你当然知道。“Hello-World-message 是什么样的对象?”
一根绳子?啊,等等!我需要包含字符串包…好的,知道了。
好了,现在输入信息并执行。

从简单的事情开始。你总是可以呆会儿……安妮·斯普拉特在 Unsplash 上拍摄的照片
“耶,它起作用了!”
太好了!在你的作业中,你还必须在屏幕上打印一些东西。“先写那部分怎么样,”
好吧,但那更复杂,”
我们将一步一步地做它。你需要打印什么?
一些变量的值。但我还没算过。“那我怎么能把它们打印出来呢,”
你现在可以放入虚拟值。请务必留下评论来标记这些假人。通过这种方式,我们会记得以后用实际价值来替换它们。
好吧,等等……我想我已经做到了。
让我们检查一下!请执行程序。
哎呀,输出没有我们预期的那样。让我们来解决这些问题吧。
“但我看不出代码中有任何错误!”
“你在那里打了一个小错字……”
该死的。好了,现在它正常工作了。
厉害!“现在我们还需要做什么,”
计算变量的值。
“好吧,就这么办!”
半小时后,程序启动并运行。
永远不要忘记进行测试和调试
哇,谢谢你!你救了我的命。
嗯,基本上是你自己写的代码。我只是给了你一些指导。顺便说一下,你可以删除 Hello-World 程序。
哦,当然,我忘了那部分。但是说真的——我在那里坐了几个小时。然后你进来,几分钟就解决了。“你是个天才,”
好吧,花几个小时解决一个问题通常不是办法。
当我开始写代码的时候,我经常太害羞而不敢向别人寻求帮助,因为我觉得这样会显得很愚蠢。所以我会在屏幕前坐几个小时,无法解决问题,越来越焦虑。
当我最终去寻求帮助时,问题通常是一个小小的打字错误或另一个小错误。
“这就教会了你遇到困难时要寻求帮助,”

是的,你应该经常寻求帮助。不要等几个小时才问。设法在合理的时间内解决这个问题。如果这段时间过去了,却没有取得很大进展,那就去问。
就我而言,我已经解决了问题,但我无法告诉电脑该怎么做。
既然如此,那就做点傻事吧。没有什么是完全没有意义的,而是非常简单的——比如 Hello-World 程序。你知道如何让计算机做事情。但是某种程度的复杂性在开始时可能会令人生畏。
您可以使用这个简单的代码来构建您的程序。“从最简单的部分开始,然后再进行最难的部分,”
[## 在编码器的块上
编码很难。有时候感觉你一点进步都没有。尼尔·科斯拉有一些振奋人心的话给那些与编码障碍作斗争的人。
medium.com](https://medium.com/@nealkhosla/on-coders-block-72125ff9f50f)
所以下次我不知道如何开始的时候,我会做一些真正简单的事情——即使它看起来与手头的任务无关。然后先做我任务中最简单的部分。
没错。如果你在写代码之前已经思考这个问题几个小时了,休息一下吧!喝杯茶或咖啡,或者散散步。毕竟,在经历了数小时的编码阻塞后,你不太可能会有所收获。
天哪,我想我需要把这些都贴在海报上。“非常感谢!”
不客气!如果你下一个任务有问题,请告诉我。
如何无痛分析你的时间序列
原文:https://towardsdatascience.com/how-to-painlessly-analyze-your-time-series-f52dab7ea80d?source=collection_archive---------14-----------------------
MPA 简介:矩阵概要 API

图片来源: Needpix
我们被时间序列数据包围着。从财务到物联网再到营销,许多组织都产生了数千个这样的指标,并挖掘它们来揭示业务关键型洞察力。一个站点可靠性工程师可能会监控来自服务器群的成千上万的时间序列流,以期检测异常事件并防止灾难性故障。或者,实体零售商可能关心识别顾客客流量的模式,并利用它们来指导库存决策。
识别异常事件(或“不一致”)和重复模式(“主题”)是两个基本的时间序列任务。但是如何开始呢?对于这两个问题,有几十种方法,每一种都有独特的优点和缺点。
此外,众所周知,时间序列数据很难分析,数据科学社区的爆炸式增长导致了对更多“黑盒”自动化解决方案的需求,这些解决方案可以由具有广泛技术背景的开发人员利用。

如何在单一图片中分析你的时间序列(图片来源:Matrix Profile Foundation)
我们在矩阵档案基金会相信有一个简单的答案。虽然没有免费的午餐,但 Matrix Profile(加州大学河滨分校基奥研究小组开发的一套数据结构&相关算法)是一个强大的工具,可以帮助解决异常检测和模体发现的双重问题。Matrix Profile 是健壮的、可扩展的,并且在很大程度上是无参数的:我们已经看到它适用于广泛的指标,包括网站用户数据、订单量和其他业务关键型应用程序。
正如我们将在下面详细介绍的那样,Matrix Profile Foundation 已经在三种最常见的数据科学语言(Python、R 和 Golang)中实现了 Matrix Profile,作为一种易于使用的 API,适用于时间序列新手和专家。
那么什么是矩阵轮廓呢?
Matrix Profile 的基本原理很简单:如果我将数据的一部分沿着时间序列的其余部分滑动,它在每个新位置的重叠程度如何?更具体地说,我们可以评估一个子序列和相同长度的每个可能的时间序列片段之间的欧几里德距离,建立所谓的片段的“距离轮廓”
如果子序列在数据中重复自身,将至少有一个完全匹配,并且最小欧几里德距离将为零(或者在存在噪声的情况下接近零)。相反,如果子序列是高度独特的(假设它包含一个重要的离群值),匹配将很差,所有重叠分数将很高。注意,数据的类型是不相关的:我们只关注一般的模式守恒。
然后我们在时间序列上滑动每一个可能的片段,建立一个距离轮廓的集合。通过对所有距离剖面的每个时间步长取最小值,我们可以构建最终的矩阵剖面。请注意,矩阵轮廓值范围的两端都是有用的。高值表示不寻常的模式或异常事件;相比之下,低值突出了可重复的主题,并为您感兴趣的时间序列提供了有价值的见解。

图片来源:矩阵简介基金会
对于那些感兴趣的人来说,我们的联合创始人之一的这篇文章提供了一个关于 Matrix 简介的更深入的讨论。
尽管 Matrix Profile 可以改变时间序列分析的游戏规则,但利用它来产生洞察力是一个多步骤的计算过程,其中每一步都需要一定程度的领域经验。然而,我们认为,数据科学中最强有力的突破发生在复杂系统变得可访问的时候。当谈到 Matrix Profile 时,可访问性有三个方面:“开箱即用”的工作实现,对核心概念的温和介绍,这自然会导致更深入的探索,以及多语言可访问性。
今天,我们很自豪地推出 Matrix Profile API (MPA),这是一个用 R、Python 和 Golang 编写的通用代码库,实现了所有这三个目标。
MPA:工作原理
使用矩阵配置文件包括三个步骤。
首先,你计算矩阵轮廓本身。然而,这并不是结束:您需要通过利用您已经创建的矩阵档案来发现一些东西。你想找到重复的模式吗?或者发现异常事件?最后,将你的发现可视化是至关重要的,因为时间序列分析极大地受益于某种程度的可视化检查。
通常,你需要通读几页文档(学术的和技术的)来弄清楚如何执行这三个步骤。如果您是一名事先了解矩阵概况的专家,这可能不是一个挑战,但我们已经看到许多用户只是想通过突破方法来分析他们的数据,以达到一个基本的起点。代码可以简单地利用一些合理的默认值来产生一个合理的输出吗?
为了与这种自然的计算流程并行,MPA 由三个核心组件组成:
1.计算(计算矩阵轮廓)
2。发现(评估 MP 的主题、不一致等)
3.可视化(通过基本情节显示结果)
这三个功能被打包成一个叫做分析的高级功能。这是一个用户友好的界面,使对 Matrix Profile 的内部工作一无所知的人能够快速利用它来获取自己的数据。随着用户对 MPA 的体验和直觉越来越多,他们可以很容易地深入到三个核心组件中的任何一个,以获得更多的功能。
MPA:一个玩具例子
作为一个例子,我们将使用 MPA 的 Python 风格来分析如下所示的合成时间序列:

图片来源:矩阵简介基金会
目测表明,既有模式,也有不一致。然而,一个直接的问题是你选择的子序列长度将会改变你的基序的数量和位置!指数 0-500 之间是否只有两个正弦图案,还是每个周期都是该图案的一个实例?让我们看看 MPA 如何应对这一挑战:

图片来源:矩阵简介基金会
因为我们没有指定任何关于我们的子序列长度的信息,所以“分析”从利用一种称为泛矩阵谱(或 PMP)的强大计算开始,以产生帮助我们评估不同子序列长度的见解。我们将在后面的帖子中讨论 PMP 的细节(或者你可以阅读相关的论文),但简单地说,它是对所有可能的子序列长度的全局计算浓缩成一个单一的视觉摘要。X 轴是矩阵轮廓的索引,Y 轴是相应的子序列长度。阴影越暗,该点的欧几里德距离越低。我们可以使用三角形的“峰”来寻找在合成时间序列中视觉呈现的 6 个“大”主题。
PMP 很好,但是我们承诺了一种简单的方式来理解你的时间序列。为了促进这一点,“分析”将结合 PMP 与引擎盖下的算法,从所有可能的窗口大小中选择合理的主题和不一致。由“分析”创建的附加图形显示了前三个基序和前三个 discords,以及相应的窗口大小和在矩阵轮廓中的位置(以及,通过扩展,您的时间序列)。

图片来源:矩阵简介基金会

图片来源:矩阵简介基金会

图片来源:矩阵简介基金会

图片来源:矩阵简介基金会

图片来源:矩阵简介基金会
毫不奇怪,这是来自默认设置的大量信息。我们的目标是这个核心函数调用可以作为您未来许多分析的起点。例如,PMP 表明在我们的时间序列中有一个长度约为 175 的保守基序。尝试对该子序列长度调用“analyze ”,看看会发生什么!
收尾
我们希望 MPA 能够让你更无痛的分析你的时间序列!欲了解更多信息,请访问我们的网站、 GitHub repos ,或在 Twitter 上关注我们。如果你觉得代码有用,请在我们的 GitHub repos 上打星号!MPF 还开设了一个 Discord 频道,您可以通过该频道与 Matrix 档案的其他用户交流并提出问题。快乐的时间系列狩猎!
致谢
感谢 Tyler Marrs、Frankie Cancino、Francisco Bischoff、Austin Ouyang 和杰克·格林审阅本文并协助其创作。最重要的是,感谢埃蒙·基奥、阿卜杜拉·穆恩和他们众多的研究生,感谢他们创建了 Matrix 档案并继续推动其发展。
补充
1.矩阵概况研究论文可在埃蒙·基奥的 UCR 网页上找到:
https://www.cs.ucr.edu/~eamonn/MatrixProfile.html
2.矩阵轮廓算法的 Python 实现可在此处找到:
https://github.com/matrix-profile-foundation/matrixprofile
3.矩阵分析算法其余实现可在此处找到:
https://github.com/matrix-profile-foundation/tsmp
4.矩阵轮廓算法的 Golang 实现可在此处找到:
https://github . com/matrix-profile-foundation/go-matrix profile
如何用 Python 熊猫解析 JSON 数据?
原文:https://towardsdatascience.com/how-to-parse-json-data-with-python-pandas-f84fbd0b1025?source=collection_archive---------0-----------------------
使用 Pandas 读取 JSON 数据并将其规范化为平面表的一行程序。

来源:作者图片
如果您正在从事与数据相关的工作,无论是数据工程、数据分析,甚至是数据科学,您肯定会遇到 JSONs。
JSON (JavaScript Object Notation)是在 web 上交换数据最常用的数据格式之一。像 MongoDB 这样基于 NoSQL 的数据库以这种格式存储数据。尽管这种格式很适合存储数据,但需要将其转换成表格形式以便进一步分析。
在这个故事中,我们将看到解析 JSON 数据并将其转换成表格形式是多么容易。您可以从下面提到的 GitHub 资源库下载示例数据。此外,请查看笔记本,了解有关所用数据和 API 的更多详细信息。
[## ankitgoel 1602/数据科学
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/ankitgoel1602/data-science/tree/master/json-data)
数据细节
我将使用我在处理机器学习聚类问题时生成的数据。不必担心这些数据没有意义,因为它们仅用于演示目的。我将使用两种不同的 JSON
- 没有嵌套列表/字典的简单 JSON。
这已经是扁平化的 JSON,只需要最少的处理。
Sample Record:
{
"Scaler": "Standard",
"family_min_samples_percentage": 5,
"original_number_of_clusters": 4,
"eps_value": 0.1,
"min_samples": 5,
"number_of_clusters": 9,
"number_of_noise_samples": 72,
"adjusted_rand_index": 0.001,
"adjusted_mutual_info_score": 0.009,
"homogeneity_score": 0.330,
"completeness_score": 0.999,
"v_measure_score": 0.497,
"fowlkes_mallows_score": 0.0282,
"silhouette_coefficient": 0.653,
"calinski_harabasz_score": 10.81,
"davies_bouldin_score": 1.70
}
2.带有嵌套列表/字典的 JSON。
这可能看起来有点复杂,一般来说,需要你写一个扁平化的脚本。稍后,我们将看到如何用一行代码将它转换成 DataFrame。
Sample Record:
{
'Scaler': 'Standard',
'family_min_samples_percentage': 5,
'original_number_of_clusters': 4,
'Results':
[
{
'eps_value': 0.1,
'min_samples': 5,
'number_of_clusters': 9,
'number_of_noise_samples': 72,
'scores':
{
'adjusted_rand_index': 0.001,
'adjusted_mutual_info_score': 0.009,
'homogeneity_score': 0.331,
'completeness_score': 0.999,
'v_measure_score': 0.497,
'fowlkes_mallows_score': 0.028,
'silhouette_coefficient': 0.653,
'calinski_harabasz_score': 10.81,
'davies_bouldin_score': 1.70
}
},
{
'eps_value': 0.1,
'min_samples': 10,
'number_of_clusters': 6,
'number_of_noise_samples': 89,
'scores':
{
'adjusted_rand_index': 0.001,
'adjusted_mutual_info_score': 0.008,
'homogeneity_score': 0.294,
'completeness_score': 0.999,
'v_measure_score': 0.455,
'fowlkes_mallows_score': 0.026,
'silhouette_coefficient': 0.561,
'calinski_harabasz_score': 12.528,
'davies_bouldin_score': 1.760
}
}
]
}
熊猫阅读 _json()
Pandas 的这个 API 有助于读取 JSON 数据,对于已经扁平化的数据非常有用,就像我们在示例 1 中看到的那样。你可以从这里下载 JSON。
# Reading JSON
pd.read_json('level_1.json')
只是看了 JSON 就把它转换成了下面的平面表。

作者使用 read_json()展平数据
当 JSON 数据是半结构化的,即包含嵌套的列表或字典时,就像我们在示例 2 中看到的那样,这样做效果不好。
# Example 2 JSON
pd.read_json('multiple_levels.json')
在阅读了这个 JSON 之后,我们可以在下面看到我们的嵌套列表被放在一个单独的列“Results”中。在下一节中,我们将了解如何扁平化这些数据。

来源:作者图片
熊猫 json_normalize()
这个 API 主要用于将半结构化的 JSON 数据转换成平面表或数据帧。你可以从这里下载 JSON 的例子。
# load data using Python JSON module
with open('multiple_levels.json','r') as f:
data = json.loads(f.read())# Normalizing data
multiple_level_data = pd.json_normalize(data, record_path =['Results'], meta =['original_number_of_clusters','Scaler','family_min_samples_percentage'], meta_prefix='config_params_', record_prefix='dbscan_')# Saving to CSV format
multiple_level_data.to_csv('multiplelevel_normalized_data.csv', index=False)

作者使用 json_normalize()平面化数据
现在,让我们来理解我在这里使用的将 JSON 转换成平面表的一个神奇的代码行。这个 API 提供了不同的参数,你可以在这里阅读更多关于它们的信息。这里我们使用了-
- 记录路径
- 记录前缀
- 自指的
- 元前缀
让我们一个一个地看一遍。
**记录 _ 路径 **
这是我们想要展平的嵌套数组或列表的路径。在我们的例子中,“结果”有多个包含算法超参数和度量分数的嵌套字典。
记录 _ 前缀
默认情况下,json_normalize 会根据父数据为嵌套字典添加一个前缀(字符串),就像我们的示例中 davies_bouldin_score 转换为 scores.davies_bouldin_score 一样。对于嵌套列表,我们可以使用 record_prefix 添加到扁平数据中。在我们的示例中,“结果”列表中的每个值都与 DBSCAN 算法相关,因此我们可以追加相同的值(dbscan_)。这将把 scores.davies_bouldin_score 转换为 db scan _ scores . Davies _ boul din _ score。
元
该参数有助于将每个记录的元数据添加到结果表中。此处,元数据将位于记录路径之外,即 Scaler、original_number_of_clusters 或 family_min_samples_percentage。
元 _ 前缀
与 record_prefix 类似,meta_prefix 会将字符串附加到定义为“meta”一部分的元数据中。在我们的例子中,所有的元数据都与 ML 问题的配置参数相关,因此我们在每个元数据后面附加了‘config _ params _’。
我希望这篇文章能在您下次处理 JSON 数据时有所帮助。我过去常常编写 python 脚本来扁平化数据,或者使用各种包来解决问题,而现在只需要 10 秒钟。如果你对数据科学感兴趣,或者想了解一些很酷的 python 库,那么看看我的另一个博客- 今天就开始你的数据科学之旅。
注意安全!!!继续学习!!!
如何通过 Azure 数据科学家助理测试
原文:https://towardsdatascience.com/how-to-pass-the-azure-data-scientist-associate-test-ad794794c646?source=collection_archive---------15-----------------------
我花了 50 个小时来学习,我做到了
本文涵盖了最新的考试大纲。我在 2020 年 6 月 13 日参加了考试
在本指南中,我将解释 Azure Data Scientist Associate 的理念、考试内容、准备工作以及课程结束后带走的一些钥匙。

我的图像
为了拿到证书,我花了大约 50 个小时从几乎零知识开始学习 Azure。关于我的背景,我作为一名数据科学家工作了 2 年,现在我是一名全职数据工程师,有 3 年多的经验。我在这两方面都很熟悉,从为大规模数据建立基础设施,到为生产构建和部署实时模型。我认为这是帮助我通过考试的优势之一。
微软 Azure DP-100 考试是什么?
在讨论细节之前,我想回顾一下微软 Azure DP-100。“在 Azure 上设计和实施数据科学解决方案”(或 DP-100) 是获得 Azure 数据科学家助理资格的考试。本课程以微软为基础,测试你在数据科学和机器学习方面的知识,在 Azure 上实现和运行机器学习工作负载。考试中测试了 4 项技能
- 设置 Azure 机器学习工作场所(30–35%)。
- 运行实验和训练模型(25–30%)。
- 优化和管理模型(20–25%)。
- 部署和消费模型(20–25%)。
更多细节,考试 55 题(其中 10 题无法复习)。这些问题分为 5 种不同的类型
- 多项选择单项答案
- 多重选择多重答案
- 按正确的顺序排列
- 基于情景的问题
- 通过填写空白处来完成代码
哦,我差点忘了说,考试需要 180 分钟,可以在家参加。
我该如何准备?

照片由里沙布·阿加瓦尔在的上拍摄
我所有的学习资源都是微软免费提供的。当我第一次注册免费账户时,微软给了我 30 天 200 美元的信用额度。那足够为考试练习了,实际上我花了大约 50 美元。
由于对 Azure 知之甚少,我决定跟随微软在 github 上提供的 DP-100 实验室(https://GitHub . com/Microsoft learning/DP 100/tree/master/labdocs)。我花了大约 20 个小时完成实验室。该实验室分为 10 个模块,但我可以说它涵盖了两个主要工具
- Azure Machine Learning Designer,这是一个拖放工具,可以用来构建、测试和部署预测分析解决方案。
- 使用Azure Machine Learning SDKfor Python 来构建、运行和部署带有 Azure Machine Learning services 的机器学习工作流。您可以使用 SDK 在任何 Python 环境中与服务进行交互。
在进行实验时,您需要注意理解每一行代码。有很多【填码】题,所以你要记住。考试的时候我很纠结,因为大部分答案都有些雷同。
其余时间,我通过阅读和跟随官方文档(https://docs . Microsoft . com/en-us/Azure/Machine-Learning/overview-what-is-Azure-ml)来尝试了解 Azure 机器学习工作室。我只是在查找代码中的一个 bug 时找到了文档。幸运的是,它确实对我的考试有帮助,大多数问题都来自文档。文件涵盖了工作室的各个方面,不包括实验室。例如,使用 PyTorch 或时间序列预测进行模型训练,甚至是数据存储的用户权限。
总的来说,更新的考试很短,主要涵盖了 Azure Machine Learning Studio。根据我的记忆,大约有 3-5 个问题需要数据科学知识,如调整参数或选择正确的参数。虽然,这是数据科学的基础知识。
这就是我为准备考试所做的。我并不是说我的方法是正确的,但是如果你没有找到任何材料或者其他方法不起作用,请随意使用我的方法。
考完试带走钥匙
在我看来,Azure 数据科学家助理对于那些拥有数据科学知识或者至少训练过几个预测分析模型的人来说是有用的。
通过研究,我们了解了训练模型、构建实验管道以及将模型高效部署到生产中的整个过程。在我看来,这不仅对 Azure 平台有好处,而且有助于你了解真实世界的流程,即使是在其他平台上。
我希望这个指南对那些即将参加考试的人有所帮助,并有望成为他们的信心助推器
祝你好运!
如何通过脸书数据科学面试
原文:https://towardsdatascience.com/how-to-pass-the-facebook-data-science-interview-3f2615c17012?source=collection_archive---------5-----------------------

赢得面试的 4 个技巧
本周早些时候,我完成了作为脸书数据科学家的第一年绩效总结周期(PSC)。我们利用 PSCs 来收集关于我们的影响力、技能和发展领域的反馈,我再次发现,最重要的技能与面试过程中测试的技能相同——正如您可能希望的那样!
这些技巧也不是脸书面试所独有的。我所有的数据科学面试都集中在同一套简短的技能上,以评估我推动影响的能力。
因此,我认为与其他正在寻找数据科学工作的人分享这些技能会很有用。
当然,我不能分享我在脸书面试时收到的确切问题,反正它们现在已经改变了。但是技巧本身并不保密,短短一年肯定也没变。
所以没有特别的顺序,他们在这里。
1.流畅的 SQL
如果你一直在工作中编写 SQL,你会发现基础知识涵盖了你在实践中要处理的 90%的问题。
最重要的概念是各种类型的JOIN语句是如何工作的。例如,您肯定需要理解这样一个事实,即INNER JOIN将删除没有出现在两个表中的记录,而LEFT JOIN将保留出现在左表中的所有记录。
中情局分析师吉姆·哈尔珀特解释 SQL 连接
您还需要习惯使用WHERE子句过滤数据,使用sum之类的函数使用GROUP BY子句聚合数据。
因此,这实际上是实现 90%的方法所需要的全部:主 SQL 连接、过滤器和聚集。
但是剩下的 10%让我在面试中更容易通过 SQL 测试。
SQL 基础知识将帮助您完成 90%的工作,但最后 10%是您需要通过的
这 10%包括理解较少使用的技术,比如像这样的子查询。
在我的 SQL 编码测试中,我使用了几个更“高级”的概念,包括窗口函数、命名子查询、self JOIN和 join 的ON子句中的条件。
使用更高级的 SQL 特性可能会使您更容易解决 SQL 问题。
2.概率论
我从未经历过评估我的直觉概率的面试,但我的现场展示了一个相当深入的案例研究。
幸运的是,我没有被要求写下任何公式,因为大学毕业后我已经把它们都忘了。
但我确实需要对我所学的关键概念有很强的理解:像中心极限定理、事件的独立性,以及选择合理的概率空间来建模问题的能力。
练习解释概率的关键概念,比如中心极限定理,不要使用任何技术词汇
我还被要求评估概率模型的输出,并根据这些输出提供业务建议。
数据科学家 Pam Halpert 评估了她同事的机器学习模型
最终,我能够给出一个明智的建议,因为我对这些概念建立了一种实用的直觉,即使我不记得量化模型拟合度的确切公式。
你不用任何技术词汇解释技术概念的能力是通过面试技术部分的关键技能。
3.沟通
在我看来,沟通技能比 SQL 或概率论等技术技能更重要。

用幻灯片演示死亡
就像技术技能一样,沟通不是你在使用手机屏幕前一周就能提升的。
但是你可以在面试前做一些简单的事情,这些事情将会对获得工作机会产生巨大的影响。
- 练习讲述你的“故事”:你工作经历背后的历史,你申请这家公司的原因,以及你最引以为豪的项目。每个面试官都会要求你讲述你的故事来介绍你自己,所以有一个清晰易懂的故事会给你留下深刻的第一印象。
- 写下你从沟通中学到的经验:对我来说,那就是讨论一种叫做“直接沟通”的表达方式,这是我在当时的工作中学到的。它只是意味着“从结论开始”,并且它通常比以您的方法或模型参数开始更有效。
- 了解你在沟通中看重什么:你最认同哪种风格?你认为什么最有效?有个例子可以说说。对我来说,这是有逻辑的组织和术语自由。
对一般的面试问题有一个排练好的答案会对你的面试结果产生最大的影响。
4.分析判断
大多数公司向数据科学家候选人提出的标准面试问题之一是:“你将如何衡量 X ”?
脸书以间接的方式问了这个问题,但回答这个问题仍然需要同样的两个技巧:
- 能够解释你如何权衡不同方法之间的权衡。所有的决策都有权衡,选择一个度量标准也不例外。在选择 KPI 或成功指标时,明确列出权衡,同时用可靠的判断进行权衡尤为关键。
- 理解测量对业务的价值,而不仅仅是它可能有多“准确”。有些模型相当不准确,但非常有价值(例如,预测用户是否会关注他们新闻订阅中的帖子)。了解您的工作如何影响业务是您分析判断的最重要部分。
想想你将如何评估你的商业模型的价值,而不仅仅是它与数据的吻合程度
正是由于这四项技能,我才得以在一年多前获得了脸书的工作机会。它们当然不容易开发:我在各种分析工作中工作了近四年,才提高到让我得到这份工作的水平。
但我不认为发展这些技能需要我有任何特殊的天赋或才华。我确信任何花时间提高这四项技能的人都能在数据科学领域找到工作。
感谢阅读!如果您觉得这很有帮助,我写的是关于数据科学和 Medium 编程的文章,所以请关注我,获取更多类似本文的文章。
[## 如何在科技初创公司找到一份数据科学的工作
帮助你获得更多面试机会的三步系统
towardsdatascience.com](/how-find-a-job-at-a-tech-start-up-bde5ae7f1b9c)
如何通过 Tableau 桌面专家认证考试
原文:https://towardsdatascience.com/how-to-pass-the-tableau-desktop-specialist-certification-exam-bccb85b8e000?source=collection_archive---------5-----------------------
我的成功秘诀和诀窍

照片由 Pexels 的 Lukas 拍摄
注:更新以反映截至 2021 年的新版考试。
我最近以 97%的成绩通过了 Tableau 桌面专家认证考试。不,我不是超级用户——我只在工作中使用 Tableau 几个月来创建一些仪表板。所以如果我能做到,你也能!这是我准备和参加考试的经验,我希望它也能帮助你成功。
什么是 Tableau 桌面专家认证?
Tableau 桌面专家认证测试基础产品知识。这是 Tableau 提供的最简单的认证级别,没有有效期,不像更高级的认证只有两三年的有效期。
考试时长 60 分钟,有 45 道选择题(40 道有分数,5 道无分数)。你需要在 1000 分中获得 750 分以上才能通过,所有的问题都是基于知识的(以前有使用 Tableau 的动手问题,但那些已经被删除了)。它是受监督的,不能访问互联网或 Tableau 应用程序。
考试通常花费 100 美元。一旦付费,以后最多可以安排 6 个月。我建议你提前安排考试,因为考试时间很快就会满。如果需要,您可以在考试前 24 小时免费重新安排考试时间。忠诚者考试服务(LES)管理考试,所以你需要创建一个 LES 帐户来注册。
建议的培训是 Tableau 的 Desktop I: Fundamentals 课程,该课程可通过其电子学习平台获得(下面将详细介绍)。也建议有 3 个月以上的产品经验,尽管在我看来,只要你对考试准备指南中的所有主题感到满意,你就可以参加。
你为什么要获得认证?
无论您是业务分析师、数据分析师、求职者还是学生,获得认证都是展示您精通 Tableau(一种广泛用于数据可视化和商业智能的工具)的绝佳方式。
更重要的是,为这个考试而学习让你对 Tableau 有一个全面的了解。我可以自信地说,准备这次考试加强了我的 Tableau 知识,使我现在能够更轻松地创建 vizzes。
我是怎么备考的?
1.备考指南(免费)
这份官方文件包括考试信息、测试技能和一些样题。我把测得的技能作为我需要学习的所有课题的清单。
2. Tableau 电子教学(120 美元/年)
Tableau 电子学习有自定进度的学习模块,每个主题都有一个演示和互动活动。这是我用来学习的主要资源。然而,我发现建议的桌面 I:基础课程涵盖了考试准备指南上列出的大部分但不是全部技能。以下技能实际上在桌面 II:中级课程中——数据连接(添加连接、混合或联合)、创建集合、添加上下文过滤器、使用 bin 和直方图以及添加参数。因此,我也参加了中级课程来完善我的理解——尽管如果你愿意,你可以只参加相关的模块。我建议您在观看演示时做笔记,捕捉重要的概念,例如离散字段和连续字段之间的区别。我还发现重做练习对复习很有帮助。
电子学习费用为 10 美元/用户/月,按年计费。您还需要个人或专业 Tableau 桌面许可证来访问。twbx 活动文件。如果你是一名在职的专业人士,询问你的雇主是否能支付你的培训、平台和认证费用是值得的。如果你是学生,那么你很幸运——你可以用一个有效的大学电子邮件获得一年的免费使用 Tableau 电子学习和桌面的机会。
3.LearningTableau.com 小测验(免费)
Lukas Halim 的这个网站提供免费的实践测验。我做了所有三个专家测验和一个挑战的认证助理测验(如果您不能完成所有 CA 测验,请不要担心,因为它们是下一级认证的内容)。还有 Tableau 专家实践考试,象征性收费。
您可能会发现有用的其他资源
- Tableau 的培训视频 (免费)——Tableau 提供大量培训视频,每个主题都有练习和解决方案练习册。除了 Tableau 准备和发布到 Tableau 服务器/ Tableau Online 之外,Creator 部分下的大多数主题都与本次考试相关。这里有一点需要注意的是,内容相当深入,而且没有描述技能水平,所以你可以跳过考试准备指南中没有提到的更复杂的主题(例如,立方体分析、空间文件)。
- Udemy 上的 Tableau 课程(20-200 美元):Udemy 上有大量由独立讲师教授的 Tableau 课程,这可能是 Tableau 电子教学的一种更便宜的替代方式。我没有上过这些课程,但许多课程都有很好的评价和认证成功案例。****
如何在考试当天取得成功?
考试前
- 查看考试设置文档以确保您的计算机、网络、网络摄像头和麦克风(仅限计算机麦克风,不允许使用耳机)以及物理环境配置正确
- 独自呆在一个安静、光线充足的房间里,没有任何笔记、书写材料和手机
- 准备好政府颁发的带照片的身份证
- 确保关闭所有应用程序,并断开所有 VPN 连接
- 确保您只使用一个电脑屏幕(没有外部或双显示器)
- 隐藏计算机上的任务栏,因为它可能会覆盖虚拟环境中的任务栏,而您将需要它来访问应用程序
开始考试
- 登录您的 LES 帐户,点击“参加考试”按钮
- 您将首先通过 Zoom 连接到您的监考人,在那里您将被要求进行屏幕共享并共享您的视频。监考人将与您一起检查所有设置,要求您打开任务管理器以确保您没有运行其他应用程序,并要求您出示您的政府 ID 并提供您房间的 360 度视图。这可能需要 15-30 分钟,不计入 60 分钟的考试时间。一旦您通过所有检查,他们将启动虚拟桌面。
- 一旦您正式开始考试,计时器将增加 5 分钟,以便您阅读说明并熟悉考试功能(例如,如何标记问题,计时器在哪里)。你可以快速浏览这个,直接进入第一个问题。
考试提示
- 连接到监考老师后,将视频面板最小化以进行缩放,这样就不会分散您的注意力或覆盖屏幕的任何部分。
- 有些问题允许您勾选多个框,因此请确保您的答案涵盖了所有解决方案。
- 如果时间允许,仔细检查你的工作。我在大约 45 分钟内完成了我的考试,并用剩下的 15 分钟检查了一遍。
我的考试经历和结果
总的来说,我觉得考试非常简单。一旦您提交了您的考试,您将立即收到您的结果。您的认证和详细分数也将发送到您的电子邮件中。
我最大的建议是彻底熟悉考试准备指南中的所有主题,因为这是一个多项选择考试,无法访问 Tableau 平台、互联网或任何其他外部应用程序。知道如何在心中达到某种类型的视觉化的步骤是及时完成考试的关键。这不仅有助于你通过考试,还能让你更高效、更有效地使用 Tableau,从而在工作中获得回报。
我希望这篇文章对你有所帮助,祝你考试和 Tableau 之旅好运!
如何窥视黑盒模型内部——理解部分依赖图
原文:https://towardsdatascience.com/how-to-peek-inside-a-black-box-model-understand-partial-dependence-plots-17d1b673aafc?source=collection_archive---------34-----------------------
使用部分相关图揭示目标特性对黑盒模型的影响。

作者拍摄的照片
在这篇文章中,我们将学习一个工具来揭示黑盒模型的工作机制。但是在我们开始之前,让我们谈点别的。
浣熊是一种非常有趣的动物,喜欢在进食前清洗食物,如下图所示:

让我们洗一些棉花糖(GIF 来自 Giphy
这种行为在我们看来可能是正常的,因为卫生问题。但是这对可爱的小浣熊有关系吗?
事实并非如此。为了解开这个神秘的行为,研究人员研究了浣熊的神经纤维和大脑皮层,最终得出了一个可能的解释。浣熊的前爪上有非常敏感的神经群。通过弄湿它们的爪子,它们能够获得更多关于将要吃什么的感官信息。
黑箱模型
现在,让我们回到我们的主题。什么是黑盒模型。在计算机科学中,黑盒模型是一个系统,可以根据其输入和输出来查看,而无需了解其内部工作原理。

我们的小科学故事中的浣熊是一个黑箱模型,输入包括食物和水,输出是它们良好的进食习惯。仅从我们的观察来看,我们无法理解他们为什么那样做。因此,我们的好奇心可能会驱使我们进一步探索。除了情感上的自我实现,揭开黑匣子确实有实用价值。
例如,在像航空航天这样的任务关键型行业中,即使黑盒模型可以为我们提供更高的准确性,采用这种解决方案也是值得怀疑的,因为我们不了解它是如何工作的以及会受到什么影响。因此,如果我们能有一些工具来揭示这个神秘的工厂就更好了。其中一个有用的工具叫做部分依赖图(PDP)。

GIF 来自 Giphy
并行分布处理
部分相关图(PDP)显示了模型预测如何部分依赖于感兴趣的输入变量值。
通俗地说,就是剧情。从该图中,它将帮助我们了解一个或两个输入特征如何影响模型预测结果。
你可能会问为什么有一两个特征?因为我们生活在一个三维世界中。我们很难想象更高的维度。
原则上,我们将检查给定训练模型的特征集对预测结果的边际效应。下面的公式明确说明了我们将如何实现这一目标:

左手边的功能 f 称为部分功能。在右侧,它将对感兴趣的特征 Xs 保持不变,并对数据集中其他特征 Xc 的所有其他组合进行平均预测。
例如,给定以下数据集:

虚拟房屋特征表(图片由作者提供)
如果我们要检查街道值的边际效应,我们将在日期集中取唯一的街道值 A、B 和 C,并分别替换每个样本的街道值。然后,我们可以使用新生成的数据样本来计算模型的平均预测值:

替换每个样本的街道值(图片由作者提供)
获取每个街道价值的平均预测价格后,我们将能够绘制一个街道价值与平均预测价格的关系图:

街道虚拟 PDP(图片由作者提供)
从该图中,我们知道该模型通常预测街道 A 上的房屋价值较高,而街道 B 上的房屋价值较低。
实施
在理解了 PDP 的整体概念之后,我们将通过一个真实的例子来更深入地探讨这个问题。
以下是 2017 年世界幸福得分的数据集快照。

来自数据集的样本(图片由作者提供)

特写(图片由作者提供)
据此,我建立了一个简单的关于快乐的回归模型。选择 7 个特征对进行评分。模型训练过程的细节可以在下面的笔记本中找到。
2017 年幸福值 XGBoost 回归模型
由于我们使用的是 XGBoost,这是一种集成方法,会产生一个黑盒模型,因此我们可以使用 PDP 来探索和了解每个功能在这个复杂的工厂中是如何发挥作用的。代码可以在下面的笔记本中找到:
为了更好地说明,我使用 Plotly 重新创建了这个图表。代码可以在这里找到供你参考。

带有 Plotly 的 PDP(图片由作者提供)
在分析 PDP 之前,我们需要考虑三个预防措施。
第一个是特征关联。通过使用 PDP,我们假设了目标特性和其余特性之间的独立性。如果存在相关性,替换目标特征值可能会导致其不具有任何实用价值的情况。例如,健康。预期寿命与经济高度相关。GDP.per.Captita ,通过改变经济的数值。健康。预期寿命应该相应地改变。然而,当我们检查这两个值的部分相关性时,我们通过修正另一个值来创建在现实生活中不太可能存在的数据点。因此,重要的是要记住这样一个假设,即目标特性应该独立于其他特性。
第二个是数据分配。您可能会注意到,在 x 轴上,我显示了来自样本数据集的目标特征值的分布。由于我们是从这些值计算部分相关性,不考虑数据分布的分析可能是危险的。在无数据区,我们可能高估了目标特征的影响。

反乌托邦的分布。x 轴上的残差可以帮助识别无数据区域(图片由作者提供)
第三个,还有一个诡雷我们需要关心,隐藏的异质效果。由于部分相关性是一个平均估计值,因此得到的值可能无法代表给定目标特征的实际边际效应。例如,如下所示:

作者图片
一半的分数高于平均水平,一半低于平均水平。然而,由此产生的部分依赖性却讲述了另一个故事。为了解决这个问题,我们可以使用其他工具,如个人条件期望(ICE)图来提供模型的粗略视图。
考虑到这些,我们可以从模型中提取一些有用的信息。一般来说,家庭,自由和反面乌托邦。残差对从模型中得出的幸福分数有正面影响。尽管经济不景气。人均 GDP 和健康。预期寿命也可能有潜在的积极影响,它们高度相关,在进一步的研究之前,我们不能相信这一点。
总结
总之,PDP 是一种模型不可知的方法,有助于理解目标特性如何影响任何派生的模型。它直观且易于实施,但确实有一些限制:
- 一个图(线图或热图图)中只能检查一到两个要素。
- 目标特征应该独立于其他特征。
- 在分析影响时,需要考虑数据分布。
- 情节中可能隐藏着不同的影响,并可能导致错误的结论。
希望这篇帖子有所帮助,帮助你打开神秘世界的大门。敬请期待,再见~
GIF 来自 Giphy
如何高效地对 Twitter 中的流行语进行网络分析?
原文:https://towardsdatascience.com/how-to-perform-a-network-analysis-for-buzzwords-in-twitter-efficiently-ebf8e139037d?source=collection_archive---------45-----------------------
数据收集、预处理、分析、可视化和交互的一站式解决方案。

作者截图
需求
Twitter 拥有大量活跃的用户,并一直以数据可访问性著称。利用 twitter 上的数据分析热点趋势已经是一种成熟的方法。

作者截图来自谷歌学术
但是,以前,如果我们要进行这种分析,我们需要完成以下步骤:
- 数据收集;
- 一系列数据预处理;
- 关键词提取;
- 网络绘图;
对于那些有足够编码技能的人来说,这似乎不是一个很大的挑战。然而,对于编程背景差的社会科学家来说,这可能是一个难以逾越的障碍。
幸运的是,一种新工具将有助于克服这一障碍。
下面的介绍将解释这个新工具如何高效地一站式完成上述一系列操作。
让我们开始吧。
演示
首先,请访问这个链接。

作者截图来自 InfraNodus 主页
正如你在这里看到的,这个工具叫做“InfraNodus”注册后,你可以进入几种不同的功能。

作者截图自 InfraNodus
现在让我们点击按钮“Twitter 情绪分析”,它在上图中被圈起来。

作者截图来自 InfraNodus
这里会提示您输入一个查询词。比如你对 Luckin coffee 最近的丑闻感兴趣,可以输入“Luckin”。
单击“go ”,请注意加载可能需要几秒钟时间。

作者截图来自 InfraNodus
然后绘图完成并呈现。

作者截图来自 InfraNodus
在这个图中,每个节点代表一个关键词,两个节点之间的线表示这两个词出现在同一个 tweet 中。
由于过滤机制,图中没有显示每个单词。
正如我们所看到的,不同的颜色代表不同的主题,这些主题在右边的对话框中被分类。
例如,第一个类是黄色的集群,包含关键字“咖啡”、“股票”和“贷款”。
这个剧情的一大亮点就是动态性。
假设您对关键词“欺诈”感兴趣,请点击它。

作者截图自 InfraNodus
你会注意到“欺诈”会自动出现在右上角的搜索框中,这意味着你刚刚执行了一次相关性过滤。
现在,您可以看到一些与“欺诈”高度相关的关键词
事实上,“首席运营官”和“调查”显然是高度相关的。
现在点击上面图左上角标有红色的按钮。

作者截图来自 InfraNodus
而所有包含“调查”的推文都在这里。
你可以继续潜心分析,比如继续查看关于调查的推文。

作者截图来自 InfraNodus
只要点击它,

作者截图自 InfraNodus
现在原始推文中只剩下一条相关推文。这样,当你试图理解热点问题时,你可以轻松地瞄准特定的单词来找出主题及其关联。
点击上面带红圈的部分,可以很容易地将 InfraNodus 分析结果导出为 png 格式,或者 gexf 格式。Png 文件可以直接显示,而对于 gexf 格式,我们可以在 Gephi 中得到进一步的分析和高质量的绘图。
到目前为止,InfraNodus 帮助我们做了很多工作。正如我们在开头提到的,有四个基本过程。
- 数据收集;
- 一系列数据预处理;
- 关键词提取;
- 网络绘图;
我们完成了第一、三、四项。此外,还增加了动态交互。
但是,数据预处理怎么样呢?
放轻松,别担心。
我们点击了下图中红色标记的按钮,以了解我们可以在设置中做些什么。

作者截图来自 InfraNodus
请向下滚动。

作者截图来自 InfraNodus
在这里你可以预处理文本。比如什么程度的距离算是“同现词”特别是下面有停用词设置。您可以过滤掉不想在结果中出现的单词。
所以,我说它是一站式的分析工具,是不是有点夸张?
延长
我们在本教程中只尝试了 Twitter 分析功能。

作者截图自 InfraNodus
其他部分呢?在我应用到不同领域之后,也是行得通的,无论是新闻,谷歌搜索词汇,甚至是维基百科分析。
当我们有更多的时间时,我们可以进一步解释。
发布说明
InfraNodus 在 Github 上为公众提供了一个免费开源版本。这里是链接。

作者截图来自 InfraNodus 的 Github 页面
然而,这个免费版本必须在本地计算机上构建和运行。需要特殊的编码技能。
如果你想立即使用它,你可以付费订阅。目前的订阅费是每月 9 欧元。

作者截图来自 InfraNodus
我们之前提到过,这个软件主要是赋能社科研究者,所以订阅的方式相对更实用。
摘要
最后,如果你想对社交媒体 Twitter 上的特定话题进行词汇共现分析,InfraNodus 可以帮助你一站式完成,为你的研究赋能。
思考问题:
Twitter 的分析仅限于关键词共现吗?能不能分析一下作者,hashtag,甚至几个不同元素的综合评论?
欢迎大家自行尝试,然后将结果反馈给社区。让我们互相学习。
相关博客
如果你对这篇博客文章感兴趣,你可能也想看看下面几篇:
- 如何用 Google Colab 练习 Python?
- 如何用 Python 和递归神经网络预测严重堵车?
- 如何用不到十行代码用 BERT 做文本二进制分类?
承认
我要感谢我以前的本科生 Shelly Yin 帮我把中文原版翻译成英文。
以下是她的信息:
- NYU 数据科学校友
- 天津师范大学管理信息系统校友
如何手动执行一个样本 t 检验,并在一个均值上进行 R:检验
原文:https://towardsdatascience.com/how-to-perform-a-one-sample-t-test-by-hand-and-in-r-test-on-one-mean-70f867c4aa1?source=collection_archive---------18-----------------------
一个样本 t 检验用于确定测量变量的平均值是否不同于规定值。

照片由 Helloquence
介绍
答在写了一篇关于学生对两个样本(独立和配对样本)进行 t 检验的文章后,我认为是时候详细解释如何手工和以 r
单样本 t 检验是推断统计学的重要组成部分(可能是学生学习的第一个统计检验之一)。提醒一下,与描述性统计不同,推断统计是统计学的一个分支,旨在根据一个或两个总体的子集(或两个)得出关于该总体的结论(称为样本)。换句话说,我们首先从总体中随机收集一组观察值,然后计算一些测量值,以便将通过样本发现的信息推广到总体。
在这种情况下,单样本 t 检验用于确定测量变量的平均值是否不同于指定值(例如信念或理论预期)。它的工作原理如下:如果样本的均值与指定值(零假设下的值)相差太远,则认为总体的均值与期望的不同。相反,如果样本的均值接近规定值,我们就不能拒绝总体均值等于期望值的假设。
像学生对两个样本的 t 检验和 ANOVA (对 3 个或 3 个以上样本)一样,单样本 t 检验也有不同的版本。幸运的是,这个测试只有两个不同的版本(学生对两个样本的 t 检验有 5 个版本!).一个样本 t 检验的两个版本的区别在于,当总体的方差(不是样本的方差!)是已知的,当总体的方差未知时使用另一个版本。
在本文中,我将首先一步一步地详细说明如何手工执行单样本 t-test 的两个版本。为了说明和方便起见,将对一小组观察值进行分析。然后,我将展示如何用完全相同的数据在 R 中执行这个测试,以便验证手工发现的结果。还将介绍假设检验背后的推理、p 值和结果的解释以及该检验的假设。
请注意,本文的目的是展示如何手动和在 R 中计算单样本 t 检验,因此我们避免测试假设,并假设所有假设都满足本练习。为了完整起见,我们仍然提到假设以及如何测试它们。感兴趣的读者可以看看文章的结尾,了解更多关于这些假设的信息。
无效假设和替代假设
在开始手动计算单样本 t 检验之前,让我们回顾一下该检验的无效假设和替代假设:
- H0: μ=μ0
- H1:μ≦μ0
其中μ是总体平均值,μ0 是总体平均值的已知值或假设值。
这是在一般情况下,我们只想确定总体平均值与假设值相比是否不同(就因变量而言)。在这个意义上,我们没有关于总体均值大于或小于假设值的先验信念。这种类型的测试被称为双边或双边测试。
如果我们对总体均值大于或小于假设值有一些先验信念,单样本 t 检验也允许检验以下假设:
- H0: μ=μ0
- H1: μ>μ0
或者
- H0: μ=μ0
- H1: μ
In the first case, we want to test if the population mean is significantly larger than the hypothesized value, while in the latter case, we want to test if the population mean is significantly smaller than the hypothesized value. This type of test is referred as a 单边或单边测试。
假设检验
在统计学中,许多统计检验是以假设检验的形式进行的。假设检验用于根据手头的数据(即样本)确定某个信念是否为真(似是而非)。大多数假设检验可以归结为以下 4 个步骤: 1
- 陈述无效假设和替代假设。
- 计算测试统计量,表示为 t-stat。计算检验统计量的公式在不同版本的单样本 t 检验中有所不同,但它们具有相同的结构。请参见下面的场景 1 和场景 2,了解不同的公式。
- 给定测试的理论统计分布、分布参数和显著性水平α,找出临界值。对于一个样本 t-检验的两个版本,它要么是正态分布,要么是学生的 t 分布( t 表示学生分布, z 表示正态分布)。
- 通过比较 t-stat(在步骤 2 中找到)得出结论。)与临界值(在步骤中找到。3).如果 t-stat 位于拒绝区域(由临界值和测试方向决定),我们拒绝零假设,否则我们不拒绝零假设。这两个选项(拒绝或不拒绝零假设)是仅有的两个可能的解决方案,我们从不“接受”一个假设。总是根据最初的问题来解释决定也是一个好的做法。
一个样本 t 检验的两个版本
一个样本的 t 检验有两个版本,取决于总体的方差(不是样本的方差!)已知或未知。这个标准相当简单,我们要么知道总体的方差,要么不知道。无法计算总体的方差,因为如果您可以计算总体的方差,这意味着您拥有整个总体的数据,那么就没有必要再进行假设检验了…
所以总体的方差要么在语句中给出(在那种情况下使用它们),要么没有关于方差的信息,在那种情况下,假设方差是未知的。实际上,总体的方差大部分时间是未知的。然而,在假设检验的 4 个步骤之后的下一节中,我们仍然说明了如何手工和在 R 中进行这两个版本的检验。
如何手工计算单样本 t 检验?
请注意,这些数据是人为的,并不代表任何真实的变量。此外,提醒可能满足也可能不满足假设。本文的重点是详细说明如何手工和在 R 中计算不同版本的测试,所以所有的假设都被假定为满足。此外,假设所有测试的显著性水平α=5%。
如果你对手工应用这些测试感兴趣,而不需要自己做计算,这里有一个闪亮的应用程序可以帮你做。你只需要输入数据,并通过侧边栏菜单选择合适的测试版本。还有一个图形表示,帮助您可视化测试统计和拒绝区域。希望你会觉得有用!
场景 1:总体方差已知
对于第一个场景,假设下面的数据。此外,假设总体方差等于 1,并且我们想要测试总体均值是否不同于 0。

所以我们有:
- 5 次观察:n=5
- 样本的平均值:0.56
- 总体方差:1
- μ0=0
按照假设检验的 4 个步骤,我们有:
- H0:μ=0,H1:μ≠0。(≠因为要检验总体均值是否不同于 0,所以在检验中不强加方向。)
- 测试统计:

- 临界值:z(α/2)= z(0.025)= 1.96(如果你很难找到临界值,请参见如何阅读统计表的指南)
- 结论:因此,拒绝区域从∞到-1.96 和从 1.96 到+∞。检验统计量在拒绝区域之外,所以我们不拒绝零假设 H0。就最初的问题而言:在 5%的显著性水平上,我们不排斥总体均值等于 0 的假设,或者数据中没有足够的证据可以得出总体均值不同于 0 的结论。
情景 2:总体的方差未知
对于第二种情况,假设下面的数据。此外,假设总体中的方差是未知的,并且我们想要测试总体均值是否大于 5。

所以我们有:
- 5 次观察:n=5
- 样本的平均值:6.8
- 样本的标准偏差:s=0.825
- μ0=5
按照假设检验的 4 个步骤,我们有:
- H0:μ=5,H1:μ>5。(>因为我们要检验总体均值是否大于 5。)
- 测试统计:

- 临界值:t(α,n1)= t(0.05,4)=2.132(如果您很难找到临界值,请参见关于如何阅读统计表的指南
- 结论:拒绝区域因此从 2.132 到+∞。检验统计量位于拒绝区域内,因此我们拒绝零假设 H0。就最初的问题而言:在 5%的显著性水平上,我们得出总体均值大于 5 的结论。
这就总结了如何手工执行一个样本 t-检验的两个版本。在接下来的小节中,我们将详细介绍如何在 r 中执行完全相同的测试。
临界值的不同基础分布
您可能已经注意到,根据总体方差是已知还是未知,用于查找临界值的基本概率分布是不同的。
方差已知时(情景 1)的底层概率分布是正态分布,方差未知时(情景 2)的概率分布是学生的 t 分布。这种差异的部分原因是,当总体的方差未知时,数据中存在更多的“不确定性”,因此我们需要使用学生的 t 分布,而不是正态分布。
注意,当样本量较大时(通常是当 n > 30 时),学生的 t 分布趋于正态分布。方差已知时使用正态分布,方差未知时使用学生 t 分布,这也适用于两个样本的 t 检验。
如何计算 R 中的单样本 t 检验?
在 R 中进行 t-tests 之前,一个好的实践是借助于箱线图(或者密度图,或者最终两者)来可视化数据。箱线图给出了关于样本位置的第一个指示,并且因此给出了关于零假设是否可能被拒绝的第一个指示。然而,即使箱线图或密度图能很好地显示样本的分布,只有可靠的统计测试才能证实我们的第一印象。
在数据可视化之后,我们在 R 中复制手工发现的结果。我们将看到,对于具有已知总体方差的 t-test 版本,R 中没有内置的默认函数(至少就我所知,如果我错了,请不要犹豫让我知道)。在这种情况下,编写一个函数来手动复制结果。
请注意,我们对两个场景使用了相同的数据、相同的假设和相同的问题,以便于比较手工测试和 r。
场景 1:总体方差已知
对于第一个场景,假设下面的数据。此外,假设总体方差等于 1,并且我们想要测试总体均值是否不同于 0。
dat1 <- data.frame(
value = c(0.9, -0.8, 1.3, -0.3, 1.7)
)dat1## value
## 1 0.9
## 2 -0.8
## 3 1.3
## 4 -0.3
## 5 1.7library(ggplot2)ggplot(dat1) +
aes(y = value) +
geom_boxplot() +
theme_minimal()

注意,如果你想用包 [{ggplot2}](https://www.statsandr.com/blog/graphics-in-r-with-ggplot2/)画一个方框图而不自己写代码,你可以使用[{esquisse}](https://www.statsandr.com/blog/rstudio-addins-or-how-to-make-your-coding-life-easier/#esquisse) RStudio addin 。如果你喜欢默认图形,使用boxplot()功能:
boxplot(dat1$value)

箱线图表明样本的分布并不远离 0(假设值),因此我们倾向于认为我们将无法拒绝总体均值等于 0 的零假设。然而,只有正式的统计测试才能证实这一观点。
由于 R 中没有使用已知总体方差来执行 t 检验的函数,因此这里有一个函数,其参数接受样本(x)、总体方差(V)、零假设下的均值(m0,默认为0)、显著性水平(alpha,默认为0.05)和备选项(alternative、"two.sided"(默认)、"less"或"greater"):
t.test2 <- function(x, V, m0 = 0, alpha = 0.05, alternative = "two.sided") {
M <- mean(x)
n <- length(x)
sigma <- sqrt(V)
S <- sqrt(V / n)
statistic <- (M - m0) / S
p <- if (alternative == "two.sided") {
2 * pnorm(abs(statistic), lower.tail = FALSE)
} else if (alternative == "less") {
pnorm(statistic, lower.tail = TRUE)
} else {
pnorm(statistic, lower.tail = FALSE)
}
LCL <- (M - S * qnorm(1 - alpha / 2))
UCL <- (M + S * qnorm(1 - alpha / 2))
value <- list(mean = M, m0 = m0, sigma = sigma, statistic = statistic, p.value = p, LCL = LCL, UCL = UCL, alternative = alternative)
# print(sprintf("P-value = %g",p))
# print(sprintf("Lower %.2f%% Confidence Limit = %g",
# alpha, LCL))
# print(sprintf("Upper %.2f%% Confidence Limit = %g",
# alpha, UCL))
return(value)
}test <- t.test2(dat1$value,
V = 1
)
test## $mean
## [1] 0.56
##
## $m0
## [1] 0
##
## $sigma
## [1] 1
##
## $statistic
## [1] 1.252198
##
## $p.value
## [1] 0.2104977
##
## $LCL
## [1] -0.3165225
##
## $UCL
## [1] 1.436523
##
## $alternative
## [1] "two.sided"
上面的输出概括了执行测试所需的所有信息:测试统计量、 p 值、使用的备选项、样本均值、假设值和总体方差(将 R 中找到的这些结果与手工找到的结果进行比较)。
可以照常提取 p 值:
test$p.value## [1] 0.2104977
p-值为 0.21,因此在 5%的显著性水平上,我们不拒绝零假设。数据中没有足够的证据来否定总体均值等于 0 的假设。这个结果证实了我们手工发现的东西。
如果你对p-价值的概念不熟悉,我邀请你阅读我关于p-价值和显著性水平α 的笔记。
总结一下那篇文章中所说的关于p-值和显著性水平α:
- 如果 p 值小于预定的显著性水平α(通常为 5%),那么如果 p 值<为 0.05,我们拒绝零假设
- 如果 p 值大于或等于预定的显著性水平α(通常为 5%),那么如果 p 值≥ 0.05,我们不拒绝零假设
这毫无例外地适用于所有的统计测试。当然,无效假设和替代假设会随着测试的不同而变化。
情景 2:总体的方差未知
对于第二种情况,假设下面的数据。此外,假设总体中的方差是未知的,并且我们想要测试总体均值是否大于 5。
dat2 <- data.frame(
value = c(7.9, 5.8, 6.3, 7.3, 6.7)
)dat2## value
## 1 7.9
## 2 5.8
## 3 6.3
## 4 7.3
## 5 6.7ggplot(dat2) +
aes(y = value) +
geom_boxplot() +
theme_minimal()

与前面的场景不同,这个盒子与假设值 5 相差甚远。从这个箱线图中,我们可以预期该检验会拒绝总体均值等于 5 的零假设。尽管如此,只有正式的统计测试才能证实这一预期。
R 里面有一个函数,简单来说就是t.test()函数。这个版本的测试实际上是一个样本的“标准”t 检验。请注意,在我们的例子中,替代假设是 H1:μ > 5,因此我们需要将参数mu = 5和alternative = "greater"添加到函数中,因为默认参数是mu = 0和双边测试:
test <- t.test(dat2$value,
mu = 5,
alternative = "greater"
)test##
## One Sample t-test
##
## data: dat2$value
## t = 4.8809, df = 4, p-value = 0.004078
## alternative hypothesis: true mean is greater than 5
## 95 percent confidence interval:
## 6.013814 Inf
## sample estimates:
## mean of x
## 6.8
上面的输出概括了执行测试所需的所有信息:测试的名称、测试统计、自由度、 p 值、使用的替代值、假设值和样本均值(将 R 中的结果与手工得到的结果进行比较)。
可以照常提取p-值:
test$p.value## [1] 0.004077555
p 值为 0.004,因此在 5%的显著性水平上,我们拒绝零假设。
与第一种情况不同,这种情况下的 p 值低于 5%,因此我们拒绝零假设。在 5%的显著性水平上,我们可以得出总体均值显著大于 5 的结论。这个结果证实了我们手工发现的东西。
置信区间
注意,置信区间可以用$conf.int提取:
test$conf.int## [1] 6.013814 Inf
## attr(,"conf.level")
## [1] 0.95
可以看到总体均值的 95%置信区间为[6.01;∞],意味着在显著性水平α=5%时,只要假设值μ0 低于 6.01,我们就拒绝零假设,否则不能拒绝零假设。
假设
对于许多统计测试,为了能够解释结果,需要满足一些假设。当一个或几个假设不满足时,尽管技术上可以进行这些测试,但解释结果是不正确的。以下是单样本 t 检验的假设以及如何检验它们:
- 从总人口中有代表性的和随机选择的部分收集的数据应该是相互独立的。
- 因变量(即测量变量)必须是连续的。
- 正态性:在小样本情况下(通常为 n < 30), observations should follow a 正态分布 )。正态性假设可以通过直方图和 QQ 图进行直观测试,和/或通过夏皮罗-维尔克或科尔莫戈罗夫-斯米尔诺夫测试等正态性测试进行正式测试(参见更多关于正态性假设以及如何测试的信息这里)。可以对观察值应用一些变换,例如取对数、平方根或 Box-Cox 变换,以变换数据,使其更好地符合正态分布。对于大样本量(n ≥ 30),不需要数据的正态性(这是一个常见的误解!).根据中心极限定理,即使数据不是正态分布,大样本的样本均值通常也是正态分布的近似值。
感谢阅读。我希望这篇文章能帮助你理解不同版本的样本 t-test 是如何工作的,以及如何在 r 中手动执行它们。如果你感兴趣,这里有一个闪亮的应用程序可以轻松地手动执行这些测试(你只需要输入你的数据,并通过侧边栏菜单选择合适的测试版本)。此外,如果你想知道如何计算学生的 t 检验,请阅读这篇文章,但这次是针对两个样本——为了比较两个相依或独立的组——或者如果你想使用方差分析比较 3 个或更多组,请阅读这篇文章。
和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。
相关文章:
- 每个数据科学家都应该知道的概率中的 9 个概念和公式
- 学生的 R 和手工 t 检验:如何在不同场景下比较两组
- R 中的相关图:如何突出显示数据集中最相关的变量
- R markdown 入门
- 聚类分析完全指南:k-means 和手动和 in R 系统聚类
- 这至少是关于参数假设检验的情况。参数测试意味着它是基于理论统计分布,这取决于一些定义的参数。在单样本 t-检验的情况下,它是基于具有单个参数的学生 t 分布、自由度(df = n1,其中 n 是样本大小)或正态分布。 ↩
原载于 2020 年 3 月 9 日【https://statsandr.com】。
如何使用 CRISP-DM 方法进行数据分析?
原文:https://towardsdatascience.com/how-to-perform-data-analysis-using-the-crisp-dm-approach-201708f220b2?source=collection_archive---------12-----------------------
CRISP-DM 代表数据挖掘的跨行业标准流程。

费尔南多·巴切斯基在 Unsplash 上拍摄的照片
首先让我们把这个想法搞清楚,如果你上过一些数据科学领域的在线课程,读过一些相关的书籍,会编码,或者对如何探索/分析数据集有足够的了解,那么你就是一名数据科学家,我会把你称为数据科学家。所以当我提到数据科学家时,你知道我说的是你,而不是两年后的你。
介绍
对于数据科学家来说,以一种非常随意的方式花费大部分时间探索和清理数据是非常常见的,并且不遵循一个明确的指导方针,尽管投入时间让您的代码保持在干燥(不要重复)指导方针中是有帮助的,并且遵循一个过程以保持头脑中的大图,这就是 CRISP-DM 出现的地方。
CRISP-DM 流程可以使您的项目简化、易于理解,并为部署做好准备。

为了让 CRISP-DM 流程更容易理解,我使用了对 StackOverflow 开发者调查 2017 数据集进行的数据分析的见解。
CRISP-DM 阶段:

CRISP-DM 的阶段
CRISP-DM 阶段非常灵活,并不一定要按照所示的顺序进行。例如,在对数据建模后,您对数据的理解可能会发生变化。任何新的业务理解都可以改进您准备数据的方式,因此您可能需要采用各种策略来处理丢失的数据或您之前面临的任何其他数据问题。
这些阶段是不言自明的,但是我想在 StackOverflow 分析中展示它们的价值。
商业理解
一般来说,作为业务问题解决的一部分,我们需要一些问题的结果。我将从 StackOverflow 开发者调查 2017 数据集中回答以下 3 个问题,以更好地解释这一流程。
- 其他开发者是如何建议进入这个领域的(从事什么教育)?
- 个人的哪些因素对工资有影响?
- 帮助个人进入开发人员角色的训练营情况如何?
这些问题向数据科学家提出了一个问题陈述,他们需要利用数据来提出见解,以便业务用户可以做出决策。
数据理解
这个舞台对我的挑战最大。对我来说,正确的选择是对整个数据集进行一次整体检查,并为我勾勒出一条路径,以最大限度地发挥数据的潜力来解决公布的问题。
您可以选择这样做,或者从几个基本步骤开始学习数据:
- 数据量有多大?有多少行和多少列?
- 有多少数据丢失了?
- 有多少列包含文本、数值或分类值?(用数值以外的值转换数据需要更多时间。)
- 如果所有列包含不相关的信息,可以删除哪些列?
….以及更多类似的问题。

测量数据:数据视图

调查数据:缺失数据统计- 53 列缺失超过 50%的数据
准备数据
数据科学家一般花 80%的时间准备数据。我已经执行了以下步骤来做数据准备。
- 输入缺失值
- 数据争论
- 数据转换
我可以做更多的事情来转换数据,但是我们必须从某个地方开始,然后我们总是可以迭代。尽量遵循干的原则。
模型数据
最后,我们使用像 scikit-learn 这样的机器学习库来训练一个模型,以选择一个合适的算法,并建立一个可以使用验证集进行预测的模型,在您期望的精度内。
一旦我们达到可接受预测精度,我们就可以最终确定部署的模型。目前,我没有在这个数据集中使用预测分析进行演示。
结果
沟通是数据科学家角色中非常重要的一部分。此时,您通常会使用一些可视化或统计数据来分享您的分析结果。有时,您可能会根据结果更改建模算法或数据准备技术。让我们跳到我在 StackOverflow 开发者调查 2017 上做的 EDA 的结果。
其他开发者是如何建议打入该领域的(追求什么教育)?

调查结果
近 30%的开发人员推荐参加在线课程是成为开发人员的一种方式,只有 12.7%的开发人员认为训练营是进入 IT 领域的一种方式。
个人的哪些因素对工资有贡献?

工薪阶层的建议
已经就业的开发人员中,21%推荐参加在线课程是成为开发人员的最佳解决方案,只有 7.6%的开发人员考虑进入 IT 领域。
帮助个人进入开发人员角色的训练营是什么样的?

训练营经验持有者的就业状况
一般来说,我们认为训练营是为那些失业者和寻找开发者工作的人准备的。这些统计数据显示,46%的 Bootcamp 毕业生已经被开发人员聘用。36.5%的人在毕业后的 3 个月内找到了开发人员的工作。
部署
部署可以通过将您的方法投入生产或使用您的结果说服公司内的其他人根据结果采取行动来实现。
一旦你到了这个阶段,你可能会认为“我的工作已经完成了,我现在需要做的就是将这段代码投入生产,然后用“结束它。虽然,它不是那么直截了当,但也不是那么复杂。
如果您已经为自己进行了分析,那么您的工作确实已经完成,但是如果您是一名为公司/团队工作的数据科学家,您需要遵循更多的步骤来将代码部署到生产中。例如以下步骤:
- 将您的代码转换成可执行文件。py 脚本。朱庇特笔记本只是用于分析目的。只需逐行复制您的代码,并将其粘贴到一个文本文件中,然后用扩展名保存。py”。
- 例如,从代码中删除静态变量;准确性阈值、输入文件名、文件目录或路径,在运行时将这些值作为参数发送。保持你的参数列表在一个可管理的范围内。
- 简单地按照 PEP 8 风格指南在 python 脚本中添加注释形式的指令。这有助于其他开发人员理解您的代码,并在必要时做出更改。
- 您可以选择为您的函数创建单独的 python 脚本,然后将这些脚本作为库导入,就像我们导入 pandas、NumPy 等一样。
一旦您的代码准备好部署,请始终检查目标 python 环境是否安装了您的数据科学库。如果没有,您需要创建一个虚拟环境,并在部署代码之前安装所有必需的库。
如果你想让你的代码按计划运行,那么你可能需要一个像 Autosys,Cron 或者基于 Windows 的调度器这样的调度器。
结论
在本文中,我们研究了 CRISP-DM 如何在进行数据分析或训练机器学习模型时帮助维护更大的画面。来自stack overflow 2017 年开发者调查支持的见解,了解 CRISP-DM 流程的理念。
本文是 Udacity 数据科学家纳米学位项目的一部分。要了解更多关于这个分析的信息,请点击这里的链接。
这是我第一篇关于媒介的文章,希望你喜欢。感谢阅读。
如何对回归问题进行特征选择
原文:https://towardsdatascience.com/how-to-perform-feature-selection-for-regression-problems-c928e527bbfa?source=collection_archive---------8-----------------------
在本文中,我将解释什么是特征选择,以及在用 Python 训练回归模型之前如何进行特征选择。

1.介绍
什么是特征选择?
特征选择是从输入 变量中选择与目标变量(我们希望预测的)最相关的子集(所有可用变量中的一部分)的过程。
目标变量这里的是指我们希望预测的变量。
对于本文,我们将假设我们只有数字输入变量和回归预测建模的数字目标。假设,我们可以很容易地估计每个输入变量和目标变量之间的关系。这种关系可以通过计算诸如相关值的度量来建立。
如果你想在交互式路线图和活跃的学习社区的支持下自学数据科学,看看这个资源:https://aigents.co/learn
2.主要的数值特征选择方法
可用于数字输入数据和数字目标变量的两种最著名的特征选择技术如下:
- 相关性(皮尔森、斯皮尔曼)
- 互信息(MI,归一化 MI)
相关性是衡量两个变量如何一起变化的指标。最广泛使用的相关性度量是皮尔逊相关性,它假设每个变量为高斯分布,并检测数值变量之间的线性关系。
这分两步完成:
- 计算每个回归变量与目标之间的相关性,即((X[:,i] — mean(X[:,I)))(y—mean _ y))/(STD(X[:,I)) STD(y))。
- 它被转换成一个 F 值,然后被转换成一个 p 值。
互信息源于信息论领域。其思想是应用信息增益(通常在决策树的构造中使用)来执行特征选择。在给定一个变量的已知值的情况下,计算两个变量和测量之间的互信息,作为一个变量的不确定性的减少。
3.数据集
我们将使用波斯顿 房屋 - 价格 数据集。该数据集包含由美国人口普查局收集的有关马萨诸塞州波士顿地区住房的信息。数据集由以下变量组成:
- CRIM——城镇人均犯罪率
- ZN——面积超过 25,000 平方英尺的住宅用地比例
- 印度河——每个城镇非零售商业用地的比例。
- CHAS——查尔斯河虚拟变量(1 如果区域边界为河流;否则为 0)
- NOX——氮氧化物浓度(百万分之一)
- RM——每个住宅的平均房间数
- 年龄——1940 年之前建造的业主自用单元的比例
- 到五个波士顿就业中心的 DIS 加权距离
- RAD——放射状公路可达性指数
- 税收—每 10,000 美元的全价值财产税税率
- pt ratio——按城镇分列的学生-教师比率
- B — 1000(Bk — 0.63),其中 Bk 是按城镇划分的黑人比例
- LSTAT —人口中地位较低的百分比
- MEDV——以千美元为单位的自有住房的中值
4.Python 代码和工作示例
让我们加载数据集并将其分为训练集(70%)和测试集(30%)。
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_regression
import matplotlib.pyplot as plt
from sklearn.feature_selection import mutual_info_regression# load the data
X, y = load_boston(return_X_y=True)# split into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=0)
我们将使用众所周知的 scikit-learn 机器库。
情况 1:使用相关性度量的特征选择
对于相关性统计,我们将使用 f_regression()函数。该功能可用于特征选择策略,如通过选择最佳类别选择前 k 个最相关的特征(最大值)。
# feature selection
f_selector = SelectKBest(score_func=f_regression, k='all')# learn relationship from training data
f_selector.fit(X_train, y_train)# transform train input data
X_train_fs = f_selector.transform(X_train)# transform test input data
X_test_fs = f_selector.transform(X_test)# Plot the scores for the features
plt.bar([i for i in range(len(f_selector.scores_))], f_selector.scores_)plt.xlabel("feature index")
plt.ylabel("F-value (transformed from the correlation values)")
plt.show()
提醒:对于关联统计情况:
- 计算每个回归变量与目标之间的相关性,即((X[:,i] — mean(X[:,I))(y—mean _ y))/(STD(X[:,I)) STD(y))。
- 它被转换成一个 F 分数,然后被转换成一个 p 值。

特征重要性图
上图显示,特性 6 和 13 比其他特性更重要。y 轴表示根据相关值估计的 F 值。
情况 2:使用互信息度量的特征选择
scikit-learn 机器学习库通过 mutual_info_regression()函数为带有数字输入和输出变量的特征选择提供了互信息的实现。
# feature selection
f_selector = SelectKBest(score_func=mutual_info_regression, k='all')# learn relationship from training data
f_selector.fit(X_train, y_train)# transform train input data
X_train_fs = f_selector.transform(X_train)# transform test input data
X_test_fs = f_selector.transform(X_test)# Plot the scores for the features
plt.bar([i for i in range(len(f_selector.scores_))], f_selector.scores_)plt.xlabel("feature index")
plt.ylabel("Estimated MI value")
plt.show()

特征重要性图
y 轴表示每个特征和目标变量之间的估计互信息。与相关性特征选择方法相比,我们可以清楚地看到更多的特征被评分为相关。这可能是因为数据集中可能存在统计噪声。
5.结论
在这篇文章中,我提供了两种方法来执行特性选择。特征选择是选择与目标变量最相关的输入变量子集(所有可用变量中的一部分)的程序。目标变量这里的是指我们希望预测的变量。
使用相关性度量或者相互 信息度量,我们可以很容易地估计每个输入变量和目标变量之间的关系。
相关性 vs 互 信息:与相关性特征选择方法相比,我们可以清楚地看到更多的特征被评分为相关。这可能是因为数据集中可能存在统计噪声。
您可能还喜欢:
[## LSTM 时间序列预测:使用 LSTM 模型预测股票价格
在这篇文章中,我将向你展示如何使用预测 LSTM 模型来预测股票价格
towardsdatascience.com](/lstm-time-series-forecasting-predicting-stock-prices-using-an-lstm-model-6223e9644a2f) [## 时间序列预测:使用 ARIMA 模型预测股票价格
在这篇文章中,我将向你展示如何使用预测 ARIMA 模型来预测特斯拉的股票价格
towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-an-arima-model-2e3b3080bd70)
敬请关注并支持这一努力
如果你喜欢这篇文章,并且觉得它有用,那么关注我就可以看到我所有的新帖子。
有问题吗?把它们作为评论贴出来,我会尽快回复。
最新帖子
[## 最佳免费数据科学资源:免费书籍和在线课程
最有用的免费书籍和在线课程,适合想了解更多数据科学知识的人。
medium.com](https://medium.com/@seralouk/the-best-free-data-science-resources-free-books-online-courses-9c4a2df194e5) [## 用新冠肺炎假设的例子解释 ROC 曲线:二分类和多分类…
在这篇文章中,我清楚地解释了什么是 ROC 曲线以及如何阅读它。我用一个新冠肺炎的例子来说明我的观点,我…
towardsdatascience.com](/roc-curve-explained-using-a-covid-19-hypothetical-example-binary-multi-class-classification-bab188ea869c) [## 支持向量机(SVM)解释清楚:分类问题的 python 教程…
在这篇文章中,我解释了支持向量机的核心,为什么以及如何使用它们。此外,我还展示了如何绘制支持…
towardsdatascience.com](/support-vector-machines-svm-clearly-explained-a-python-tutorial-for-classification-problems-29c539f3ad8) [## PCA 清楚地解释了——如何、何时、为什么使用它以及特性的重要性:Python 指南
在这篇文章中,我解释了什么是 PCA,何时以及为什么使用它,以及如何使用 scikit-learn 在 Python 中实现它。还有…
towardsdatascience.com](/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e) [## 关于 Python 中的最小-最大规范化,您需要知道的一切
在这篇文章中,我将解释什么是最小-最大缩放,什么时候使用它,以及如何使用 scikit 在 Python 中实现它
towardsdatascience.com](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79) [## Scikit-Learn 的标准定标器如何工作
在这篇文章中,我将解释为什么以及如何使用 scikit-learn 应用标准化
towardsdatascience.com](/how-and-why-to-standardize-your-data-996926c2c832)
和我联系
- LinkedIn:【https://www.linkedin.com/in/serafeim-loukas/
- https://www.researchgate.net/profile/Serafeim_Loukas研究之门:
- https://people.epfl.ch/serafeim.loukasEPFL简介:
- 堆栈 溢出:https://stackoverflow.com/users/5025009/seralouk
如何满怀信心地执行线性回归
原文:https://towardsdatascience.com/how-to-perform-linear-regression-with-confidence-5ed8fc0bb9fe?source=collection_archive---------11-----------------------
它的工作原理和失败之处

由 Unsplash 上 Greg Rakozy 拍摄的照片
线性回归可能是建模关系最广泛使用的方法之一。它的主要吸引力在于它很容易向非技术读者解释,并且假设关系是线性的。
在这篇文章中,我们将解释线性回归的理论和假设,并实现产生类似于scipy . stats . Lin regression结果的代码。
代码用 Python 3.x 编写,整个工作流程可以在这里找到:https://github . com/NadimKawwa/Statistics/blob/master/linear _ regression . ipynb
假设
以下是关于预测变量、响应变量以及它们之间关系的假设:
- 弱外生性:我们假设预测变量是无误差的,例如没有现场测量误差。
- 线性:响应变量的平均值是参数和预测变量的线性组合。
- 同方差:响应变量的不同值在其误差中具有相同的方差(方差齐性)。
- 误差的独立性:响应变量的误差彼此不相关。
- 缺乏完美的多重共线性:对于最小二乘估计方法,设计矩阵 X 必须具有满秩,否则可能意味着一个预测变量被给出两次。
最小二乘法
理论
在实践中,有许多问题,其中一组配对数据给出回归是线性的指示,其中我们不知道所考虑的随机变量的联合分布。
最小二乘法的法是一种近似线性关系的曲线拟合方法。
请看下表,该表显示了随机抽取的 10 名学生的考试成绩和学习时间:

在下图中,我们展示了学习时间与考试分数的分散情况:

我们得到的印象是,直线提供了相当好的拟合,因此估计的回归线给出如下:

假设我们拟合了一条任意的线,这条线很好地估计了线性关系。我们如何确定拟合优度?设ei表示一个点到估计回归线的垂直偏差。因此,我们希望最小化关于 α 和 β 的量 q:

我们不详细讨论 q 相对于α和β的部分微分,而是直接跳到解,并引入以下符号来简化未来的计算:

给定样本数据(xi,易),最小二乘系数α和β为:

履行
在下面的代码中,我们实现了这个简单的线性回归。我们首先定义一个助手函数 getPairStats 来计算 Sxx、Syy 和 Sxy:
实施线性回归现在变得简单明了:
为了更深入地了解我们正在做的事情,请考虑下面的图表,其中显示了拟合直线和垂直偏差的结果。

假设检验
理论
在正态回归分析中,假设对于每个固定的 Xi,相应的随机变量 Yi 的条件密度是正态密度:

这样,α、β和σ对于每个 I 都是相同的。给定配对数据的随机样本,正态回归分析涉及σ和回归系数α和β的估计,以及关于这些参数的假设检验。
σ的最大似然估计由下式给出:

更多的时候,我们感兴趣的是测试斜率β。我们注意到β hat 具有正态分布,在正态回归分析的假设下,具有(N2)自由度的 t 分布的随机变量的值计算如下:

为了建立参数β的(1-α)置信区间:

履行
现在让我们测试以下关于学习时间与分数的假设:
- H0: β=3
- H1: β>3
- 设置显著性水平α=0.01
下面的函数基于上一节中的配对回归函数,如果我们没有拒绝 H0,则返回 False,否则返回 True。
参考相同的数据,我们可以为β构建 95%的置信区间:
在截距保持不变的情况下,我们的回归看起来如何?下面的图提供了一个可视化。

正态相关分析
理论
样本相关系数表示为 r,衡量两组数据 X 和 y 之间的线性关系强度。当 r=0 时,随机变量不相关。该系数计算如下:

使用辅助函数 getPairStats,计算 r 非常简单:
陷阱
线性回归的局限性在假设中是显而易见的。此外,我们必须记住,相关性并不意味着必然的因果关系。
Anscombe 的四重奏是 11 个数据点(x,y ),它们被设计成具有几乎相同的均值、标准差和相关性。结果是相同的回归线,证明了在绘制图形之前绘制数据的必要性以及异常值的影响。

安斯康贝的四重奏
另一个考虑因素是季节性,特别是对于时间序列图。对所有时间跨度使用一个斜率系数可能没有意义。
多元线性回归
理论
在实际应用中,我们将面临许多使用多个变量来逼近目标结果的情况。在这一节中,我们将简单的线性回归推广到多元线性模型。
我们可以使用矩阵符号来求解多元线性回归。设 X 是一个由给定值组成的(n,k+1)矩阵,第一列附加了常数项。y 是由 y 的观察值组成的(n,1)矩阵,即列向量。B 是由回归系数的最小二乘估计组成的(k+1,1)矩阵。
在矩阵格式中,X、Y 和 B 写为:

多元回归系数的最小二乘估计由下式给出:

履行
考虑使用卧室数量和浴室数量来预测房屋价格的尝试:

为了节省以后的计算时间,我们定义了一个辅助函数 calculate (X.T X)-。在下一节中,这个术语将被证明是重要的:
上面的等式在下面的紧凑函数中解释:
多重假设检验
对于多个系数,需要针对无效假设测试每个系数。在上面的例子中,系数 B1=15,314 意味着每间卧室在要价上增加了大约 15,000 美元。
具有(n-k-1)个自由度测试统计量由下式给出:

使得 c_ii 是矩阵(X.T X)的第 I 行和第 I 列;

履行
假设我们希望测试以下假设:
- H0: B1=9500
- H1: B1>9500
- 设置显著性水平α=0.05
在函数中实现它:
我们得出的结论是,平均每间卧室会给房子的要价增加 9500 美元以上。
结论
线性回归是近似关系的有用工具,广泛应用于所有科学领域。它的简单和易于解释使它成为向技术观众和外行人传达结果的首选。
当然还有更多回归方法,如 KNN 回归和随机森林回归。
参考
约翰·e·弗罗因德,数理统计及其应用,第 8 版
[## 简单线性回归
在统计学中,简单线性回归是只有一个解释变量的线性回归模型。那就是,它…
en.wikipedia.org](https://en.wikipedia.org/wiki/Simple_linear_regression) [## 线性回归
在统计学中,线性回归是一种建模标量响应(或变量)之间关系的线性方法
en.wikipedia.org](https://en.wikipedia.org/wiki/Linear_regression)
如何在 Python 中执行金融投资组合的场景分析
原文:https://towardsdatascience.com/how-to-perform-scenario-analysis-of-a-financial-portfolio-in-python-c2a68f05dd1f?source=collection_archive---------11-----------------------
蒙特卡罗模拟在金融投资组合情景分析中的应用

由马库斯·斯皮斯克在 Unsplash 上拍摄的照片
金融投资者知道没有人能预测未来,但他们也知道他们必须至少对未来的可能性有一个概念。这就是为什么情景分析是投资者工具箱中非常强大的工具。
情况分析
情景分析是一门学科,它试图给出与一种现象相关的未来可能发生的情景的概率观点。
在上一篇文章中,我已经向您展示了如何使用遗传算法在 R 中执行投资组合优化。虽然投资组合优化是一门科学,但情景分析几乎就像一门艺术。它通常从一些假设开始,然后使用蒙特卡罗技术模拟许多未来情景。模拟场景的数量越多,精确度越高。最后,对所有仿真结果进行了分析。例如,金融投资组合的典型情景分析可以与风险相关(例如,我们的投资组合在 30 天内损失 3%的概率是多少)。
在本文中,我将向您展示如何将情景分析应用于金融投资组合。对于这个例子,我们将使用 2010 年 1 月 1 日至 2019 年 1 2 月 31 日的每日历史数据,模拟由微软(50%)、苹果(20%)和谷歌(30%)股票组成的投资组合。我们将以比过去更悲观的方式修正他们的平均回报率,并计算我们投资组合的累积预期回报率、置信区间和预期夏普比率。
一切都将在 Python 中完成。你可以在这里获得 GitHub 上的完整笔记本:https://GitHub . com/gianlucamalato/machine learning/blob/master/Portfolio _ scenario _ analysis . ipynb
数据收集
首先,我们需要安装yfinance库。它允许我们直接从笔记本上下载股票价格。
!pip install yfinance
然后我们可以导入一些有用的库:
import yfinance
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
对于每只股票,我们要计算从第 t 天到第 t+1 天的收盘价 P 的日收益,定义为

幸运的是,Python 系列提供了有用的 pct_change 方法,为我们计算这个公式。
让我们来定义投资组合的组成和用每只股票的日收益填充熊猫数据框的循环。
portfolio_composition = [('MSFT',0.5),('AAPL',0.2),('GOOG',0.3)]
returns = pd.DataFrame({})for t in portfolio_composition:
name = t[0]
ticker = yfinance.Ticker(name)
data = ticker.history(interval="1d",
start="2010-01-01",end="2019-12-31")
data['return_%s' % (name)] = data['Close'].pct_change(1) returns = returns.join(data[['return_%s' % (name)]],
how="outer").dropna()
returns数据帧如下所示:

现在我们准备模拟我们的数据。
单一股票的蒙特卡罗模拟
如果我们想在未来模拟 m 天,我们只需要:
- 以一只股票的原始收益时间序列为例
- 选择替换的 m 值,随机均匀取值
就是这样。它与 bootstrap 非常相似,bootstrap 是一种重采样技术。这种方法假设未来收益是对过去收益的随机重采样。这是一个很强的近似值,但它可以是一个很好的起点。
这种模拟可以通过下面函数中的一行代码轻松完成:
def simulate_returns(historical_returns,forecast_days):
return historical_returns.sample(n = forecast_days,
replace = True).reset_index(drop = True)
如果我们尝试模拟 1000 天,我们会得到:
simulate_returns(returns['return_AAPL'],1000)

现在让我们为模拟投资组合创建必要的函数。
投资组合的蒙特卡罗模拟
投资组合是收益和权重的组合。给定第 i- 只股票的收益 R ᵢ,给定投资组合中每只股票的权重 w ᵢ(所有权重总和必须为 1),投资组合收益 R 可以表示为:

这是股票收益的加权和。
这是从我们之前创建的returns数据帧开始执行所有计算的函数:
def simulate_portfolio(historical_returns,
composition,
forecast_days):
result = 0
for t in composition:
name,weight = t[0],t[1]
s = simulate_returns(historical_returns['return_%s' % (name)],
forecast_days)
result = result + s * weight
return(result)
让我们看看如果我们模拟 10 天的投资组合会发生什么:
simulate_portfolio(returns,portfolio_composition,10)

对于投资组合模拟来说,这可能已经足够了,但是我们还需要更多,那就是假设分析。
假设分析
如果我们像之前那样进行投资组合模拟,我们只是说未来收益是过去收益的随机样本。我们已经知道这并不完全正确。此外,也许我们正在进行情景分析,因为我们想知道如果某些条件将会发生什么。比如,如果每只股票的日均收益低于其历史价值,会发生什么?
历史平均回报率为:

让我们试着模拟一下,如果 MSFT 的平均回报率下降-0.0001,AAPL 下降-0.001,谷歌下降-0.0005,会发生什么。我们必须从每只股票中减去这些数量,然后用修改后的新数据模拟未来的投资组合。
我们将把这些修正直接添加到portfolio_composition列表中(它们是每个元组的第三个组件):
portfolio_composition = [
('MSFT', 0.5,-0.0001),
('AAPL', 0.2,-0.001),
('GOOG', 0.3,-0.0005)
]
然后我们可以重新定义所有先前定义的函数。
这是模拟修改股票的功能:
def simulate_modified_returns(
historical_returns,
forecast_days,
correct_mean_by): h = historical_returns.copy() new_series = h + correct_mean_by return new_series.sample(n=forecast_days,
replace = True).reset_index(drop=True)
这是模拟修改后的投资组合的函数:
def simulate_modified_portfolio(
historical_returns,
composition,
forecast_days):
result = 0
for t in composition:
name,weight,correction = t[0],t[1],t[2]
s = simulate_modified_returns(
historical_returns['return_%s' % (name)],
forecast_days,correction
)
result = result + s * weight
return(result)
最后,我们可以定义一个多次执行投资组合模拟的函数,生成许多可能的场景:
def simulation(
historical_returns,
composition,
forecast_days,
n_iterations):
simulated_portfolios = None for i in range(n_iterations):
sim = simulate_modified_portfolio(
historical_returns,
composition,
forecast_days
) sim_port = pd.DataFrame({'returns_%d' % (i) : sim}) if simulated_portfolios is None:
simulated_portfolios = sim_port
else:
simulated_portfolios = simulated_portfolios.join(sim_port)
return simulated_portfolios
现在我们准备开始我们的模拟和分析结果。
模拟和结果
让我们模拟未来 20 天,计算 200 个不同场景的统计数据。
forecast_days = 20
n_iterations = 200
我们现在可以运行模拟:
simulated_portfolios = simulation(returns,
portfolio_composition,forecast_days,n_iterations)
如果迭代次数很多,此功能可能需要几秒钟甚至几分钟。
这是结果:

每一列是一个模拟投资组合的场景,每一行是未来的一天。
以投资组合的每日收益为例,我们可以用复利公式计算出 N 天后的收益:

由于回报是非常小的数字,我们可以将该表达式近似为:

即 N 天后的收益是 N 天的收益之和。
我们现在可以从这个数据集计算一些可观测量。
未来回报的置信区间
情景分析可以用作风险管理工具。为此,我们可能要计算未来累积回报的第 5 个和第 95 个百分位数。前者告诉你,我们的投资组合有 5%的机会跑输这个价值,后者告诉你,你的投资组合有 5%的机会跑赢这个价值。我们还想了解投资组合的平均表现。
下面是计算这三条曲线的代码。
percentile_5th = simulated_portfolios.cumsum().apply(lambda x : np.percentile(x,5),axis=1)percentile_95th = simulated_portfolios.cumsum().apply(lambda x : np.percentile(x,95),axis=1)average_port = simulated_portfolios.cumsum().apply(lambda x : np.mean(x),axis=1)
情节是这样的。

波段是百分位数,实线是平均投资组合。如你所见,20 天后,我们的投资组合有 5%的可能性会损失 5.3%(低波段),有 5%的可能性我们的投资组合回报会高于 8.3%(高波段)。平均而言,我们预计我们的投资组合有 1%的回报率(实线)。
达到目标回报的概率
我们可以进行的另一种分析是,作为未来一天的函数,我们的投资组合跑赢目标回报的概率。
由于概率是一个可观测的值,我们也想计算它的标准误差。
如果我们有一个样本概率 p (即肯定事件的数量除以场景的数量 N ),其标准误差的估计值为:

我们可以使用每天计算的这个值,在图表中显示误差线。
假设我们有一个 2%的目标。达到这一目标的概率计算如下:
target_return = 0.02target_prob_port = simulated_portfolios.cumsum().apply(
lambda x : np.mean(x > target_return)
,axis=1)
误差线的大小用标准误差公式计算:
err_bars = np.sqrt(
target_prob_port * (1-target_prob_port) / n_iterations
)
最后,我们可以绘制结果:

正如你所看到的,超额完成我们的目标回报的可能性随着时间的推移而增加(这显然是正确的,因为我们的投资组合有正的平均回报)。20 天后,我们的投资组合将以 38.0 +/- 3.4%的概率跑赢 2%的目标。
夏普比率的期望值和直方图
最后,我们可以计算一些与夏普比率相关的统计量。这是一个非常受欢迎的投资组合绩效指标,对于本例,我们可以计算投资组合的夏普比率回报率 R 如下:

其中 E(x) 是期望值, Var(x) 是方差。
我们的 200 个投资组合场景中的每一个都有自己的夏普比率,所以我们可以计算出每一个的夏普比率。然后我们可以绘制直方图并计算平均值。
sharpe_indices = simulated_portfolios.apply(
lambda x : np.mean(x)/np.std(x)
)
直方图为:

平均值为:

结论
在本文中,我向您展示了如何用 Python 对金融投资组合进行简单的场景分析。这种方法可以适用于许多问题和情景(例如,波动性增加、黑天鹅、某些行业的危机),以评估投资组合未来可能的风险及其成长能力。
这个工具可以很容易地与投资组合优化混合,以评估金融资产配置的完整分析。
参考
[1]吉安卢卡·马拉托。利用遗传算法进行 R 中的投资组合优化。交易科学家。https://medium . com/the-trading-scientist/portfolio-optimization-in-r-using-a-genetic-algorithm-8726 EC 985 b 6 f
[2]吉安卢卡·马拉托。自举。任何数据科学家的瑞士军刀。数据科学记者。https://medium . com/data-science-reporter/the-bootstrap-the-Swiss-army-knife-of-any-data-scientist-acd6e 592 be 13
[3] 二项分布页。维基百科。https://en.wikipedia.org/wiki/Binomial_distribution
[4] 夏普比率页。维基百科。https://en.wikipedia.org/wiki/Sharpe_ratio
如何利用 MAFFT 对 2019-nCoV 执行序列对齐
原文:https://towardsdatascience.com/how-to-perform-sequence-alignment-on-2019-ncov-with-mafft-96c1944da8c6?source=collection_archive---------20-----------------------
截至 2020 年 1 月 26 日,2019-nCoV 已经在中国武汉造成 76 人死亡。作为一种针对人类呼吸系统的冠状病毒,2019-nCoV 具有很高的传染性,尤其是在潮湿和寒冷的季节。

DNA,图片来自 Pixabay
呼吸系统相关的病原体可以随着体液从喷嚏中高速射出。它们可以通过多种方式感染人类,最常见的是通过接触嘴、鼻子和眼睛。为避免感染,建议避免户外活动,尤其是在人群密集的地方。经常消毒双手,不要用手揉眼睛也很重要。
人们开玩笑说,他们现在只要躺在家里的沙发上就可以为社会做贡献。我在农历新年期间的所有会议计划现在都取消了。所以我决定分享一个教程,如何获取 2019-nCoV 的基因序列数据,并用 MAFFT 对其进行序列比对。我希望这篇文章提高了人们对生物信息学研究的兴趣,并有助于我们对抗下一场流行病。
什么是序列比对和 MAFFT?
序列比对是一种排列 DNA、RNA 或蛋白质以识别相似区域的方法,这可能揭示序列之间的功能、结构或进化关系。最近的一份出版物提出,借助于 MAFFT 的序列比对,蛇可以跨物种传播给人类。
MAFFT(MmultipleAalignment usingFastFourierTtransform)是 2002 年发表的一个多序列比对程序。它可用于 RNA 序列的序列比对。冠状病毒是例如具有单链 RNA 的病毒,该单链 RNA 被包裹在来源于宿主细胞膜的外壳中。关于 MAFFT 算法的细节可以在找到。
从哪里获取 RNA 序列数据?
2019-nCoV 的最新更新可以在 NGDC (中国国家基因组数据中心)上找到。在本教程中,我们将分析在 NCBI(国家生物技术信息中心)数据库内发现的 2019-nCoV 病毒和 SARS-CoV 病毒。SARS-CoV,众所周知的 SARS(严重急性呼吸综合征),在 2020 年左右在 17 个报告的国家中导致 774 人死亡。

我有一份拷贝,并将数据粘贴到一个以病毒名称命名的文件中。它们应该类似于上面的内容,一个索引号后跟一批 10 个代码,每行 60 个代码,用空格分隔。我已经上传了这个分析的相关文件,并在本文末尾附上了链接。
如何用 MAFFT 对 2019-nCoV 进行序列比对?
首先,我们需要安装 MAFFT。我们可以用下面的命令通过 Anaconda 安装它。不同操作系统的手动安装可以在maftt 官网找到。
conda install mafft
MAFFT 非常容易使用,但是它以一种特殊的格式处理数据。我们将需要对我们获得的数据进行预处理,以便它可以通过 MAFFT 进行校准。下面是执行此操作的 Python 脚本:
import sys
import re
output = ""
for filename in sys.argv[1:]:
infile = open(filename)
data = infile.read()
data = " ".join(re.split("[^atcg\n]", data))
data = data.replace(" ", "")
output = output + ">" + filename + "\n" + data + "\n"
print(output)
outfile = open('SEQUENCES.txt', 'w+')
outfile.write(output)
我们可以将上面的 Python 代码保存到一个名为“preprocess.py”的文件中,与我的病毒 RNA 数据放在同一个文件夹中。然后我们可以在文件夹中运行下面的 bash 命令来预处理数据。
python3 preprocess.py 2019-nCoV_HKU-SZ-002a_2020 icSARS-C7-MA
名为“SEQUENCES.txt”的输出文件现在应该如下所示。由于病毒名称附加在文件的前面,空格和索引号也被去掉。

现在,我们可以通过以下步骤在我们的终端下使用 MAFFT 执行序列比对:
- 定位到工作文件夹。
- 在终端内呼叫“mafft”。
- 对于输入文件,输入“SEQUENCES.txt”。
- 对于输出文件,输入“output.txt”。
- 为“Clustal 格式”选择“1”作为输出格式。
- 选择“1”作为“自动”策略。
- 为附加参数保留空白。

在我们按下回车键后,我们只需要等待 MAFFT 来排列我们的 RNA 代码。成品应该看起来像下面的东西。“-”用于移动代码,下面的“*”表示类似的顺序。

恭喜你,你已经学会了如何使用 MAFFT 进行序列比对!现在你可以玩基因代码,并利用你喜欢的排列信息!
附录(相关文件的链接)
[## 黄慎/shenhuang.github.io
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/shenhuang/shenhuang.github.io/tree/master/2019-nCoV)
作为开发人员、数据科学家等,帮助武汉抗击致命疾病:
https://github.com/wuhan2020/wuhan2020
如何通过 5 个步骤执行威胁建模和安全分析
原文:https://towardsdatascience.com/how-to-perform-threat-modeling-security-analysis-in-5-steps-c42639efc952?source=collection_archive---------22-----------------------

彼得·拉格森在 Unsplash 上的照片
想学习如何执行威胁建模吗?
那么,你来对地方了。
但在此之前,让我们快速讨论一下执行威胁建模和安全分析的重要性。
如今,几乎所有的软件系统都面临着各种各样的威胁,随着技术的成熟,网络攻击的数量也在不断上升。根据的一份报告,2018 年第二季度,利用软件漏洞的恶意软件增长了 151%。
安全漏洞可能是由内部或外部实体造成的,它们可能会带来灾难性的后果。这些攻击可能会泄漏您组织的敏感数据或完全禁用您的系统,甚至可能导致数据完全丢失。
您如何保护您的数据不被窃取或防止恶意攻击您的设备?
一种开始的方法是执行威胁建模,这是一个帮助您分析您的环境、识别潜在的漏洞和威胁,并创建适当的安全需求来应对这些威胁的过程。
对于您的设备,什么是合适的安全级别?威胁建模如何帮助您实现这一级别?
为了设计安全性,建议开发人员和制造商分析操作环境,以确定每台设备可能受到的攻击,然后记录下来。
理解和记录安全需求的过程被称为威胁建模和安全分析(TMSA)。
但是,执行威胁建模和安全分析如何帮助您保护您的设备免受网络安全攻击呢?
它可以帮助您分析您的设备并了解:
- 您的安全性需要有多强?
- 您应该采取哪些预防措施来避免安全问题?
- 哪些潜在威胁会影响您的设备?
威胁建模和安全分析(TMSA)强调了在实施安全措施来保护您的产品或设备时应该考虑的关键问题和挑战。
它会提示您考虑一些关键问题,例如:
- 您的设备面临哪些潜在威胁?
- 这些威胁有多严重?
- 您的设备符合安全标准吗?
- 有哪些潜在的漏洞会使您的设备面临安全漏洞的风险?
- 您可以实施什么对策来保护您的设备?
执行威胁建模的步骤
下面是一个分步过程,它将帮助您了解如何执行威胁建模和安全分析来确定您的安全需求。
步骤 1:确定用例、要保护的资产和外部实体
执行威胁建模的第一步是确定一个用例,即作为您的安全评估主题的系统或设备。通过这样做,你将会知道什么设备或系统需要进一步分析。
由于攻击者可能会以您的设备为目标来窃取重要数据或恶意操作,因此您需要识别包含敏感信息或最有可能受到攻击的资产。
例如,如果您有一个智能扬声器,那么您可能希望保护以下资产:
- 登录凭证
- 网络通信
- 固件
- 事件日志
- 证书和唯一密钥
- 系统配置(保护您的 IP 地址)
- 设备资源(如扬声器、麦克风阵列、电池、存储、调试接口、网络带宽和计算能力)
您的设备中可能有许多不同的资产,但重要的是,您要专注于保护保存有价值数据且对您的组织和客户至关重要的资产。
此外,为了识别和了解可能影响您设备的潜在威胁,您需要确定与设备交互的外部实体和用户。
这可能包括合法用户,如虚拟系统管理员或设备所有者。但是它还应该扩展到识别试图访问设备的潜在对手或攻击者。
一旦确定了这些,就该进入执行威胁建模的下一步了。
步骤 2:确定信任区域、潜在对手和威胁
在执行威胁建模的这一步中,您必须确定信任区域和相应的入口-出口点。通过使用这些信息,您可以开发带有权限边界的数据流图,这将帮助您定义输入数据验证、用户身份验证和错误处理的方法。
此外,您需要创建一个基于对手的威胁模型,以帮助您识别可能试图利用或攻击您设备的潜在对手和攻击者。
通常,基于对手的威胁模型有四类攻击者:
- 网络攻击者:这种类型的攻击者可能会进行中间人攻击等网络攻击,攻击者拦截双方的通信。
- 恶意内部攻击者:这些攻击者可能是您的员工、第三方供应商或任何能够访问您的设备或网络的个人。
- 远程软件攻击者:大多数攻击者都属于这一类,他们试图通过引入恶意脚本/代码或病毒来破坏安全软件,从而窃取数据或控制设备/网络。
- 高级硬件攻击者:这些攻击者通常拥有高级资源,需要物理接触设备。他们经常在专业设备的帮助下部署复杂的攻击,如显微镜探测或离子束光刻。
至此,您应该已经确定了需要保护的内容,以及哪些潜在的对手可能会导致安全漏洞。
接下来,您应该识别潜在的漏洞,包括软件、物理设备、开发生命周期和通信,它们可能作为进入您设备的入口点,并允许攻击者进入您的系统。
这些漏洞包括哪些?
这些漏洞可能包括过多的用户访问权限、薄弱的密码策略、缺乏 Web 应用程序防火墙(WAF)、不可靠的身份验证、不安全的加密存储、缺乏安全指南或安全错误配置。
一旦确定了潜在的漏洞,就可以针对每个入口点实现一个威胁模型来确定安全威胁。
但是,如何设计合适的安全级别来保护您的设备免受这些威胁呢?
在识别潜在的安全威胁后,您需要考虑评估每个威胁或攻击的严重性,并适当地分配您的资源。
您可以使用通用漏洞评分系统(CVSS)来评估威胁的影响。它使用 0 到 10 之间的分数来帮助您了解攻击会如何影响您的设备。
例如,如果威胁的 CVSS 分数是 9,那么您应该将您的资源和注意力集中在它上面,因为它的影响将是严重的。
通过这样做,您将能够在您的设备中建立适当的安全级别。
步骤 3:确定应对潜在威胁的高级安全目标
在如何执行威胁建模的这一步中,您必须建立安全目标,重点维护以下安全元素:
- 机密
- 有效性
- 完整
- 安全开发生命周期
- 真实性
- 不可否认性
攻击的类型决定了这些安全元素的风险。
例如,您可以确定篡改攻击可能会影响设备的完整性,而欺骗攻击可能会影响设备的真实性。
一旦您评估了潜在威胁及其严重性,您将能够确定需要采用什么对策来应对这些威胁,以及如何适当地应对它们。
步骤 4:明确定义每个安全目标的安全需求
由于每个威胁对高级安全目标构成不同的风险,您需要分析并创建具体的、可操作的安全需求,以直接应对这些威胁。
例如,为了保护身份,您应该:
- 维护角色、可信的通信渠道和授权
- 实现最低特权用户访问
- 设置故障阈值限制
- 安全远程管理
步骤 5:创建一个文档来存储所有相关信息
一旦收集了为系统设置安全要求所需的所有必要信息,就可以创建一个威胁建模文档来准确存储这些信息。
你应该在这份文件中包括什么?
该文档应包括单独的表格,列出您需要保护的资产、潜在的对手和威胁、您需要采取的对策以及安全要求。
它应该是结构良好的,并且具有清晰简明的信息,以帮助您了解攻击的潜在严重性以及如何应对每种威胁。
维护良好的文档可以帮助您高效地执行威胁建模和安全分析(TMSA)。
本指南中关于如何执行威胁建模的关键要点
既然您对威胁建模以及如何执行威胁建模有了更多的了解,那么就从 TMSA 文档开始吧。请记住,您需要根据安全需求识别潜在的漏洞,这将有助于保护您的系统免受攻击者和威胁。
关于如何执行威胁建模,您还有其他问题吗?请联系我们的安全专家。
关于作者:
Steve Kosten 是 Cypress Data Defense 的首席安全顾问,也是“Java/JEE 中的 SANS DEV541 安全编码:开发可防御应用程序”课程的讲师。
在预算有限的情况下,如何为深度学习 PC 挑选零件?
原文:https://towardsdatascience.com/how-to-pick-parts-for-a-deep-learning-pc-when-on-a-budget-d50457f9fd37?source=collection_archive---------19-----------------------

照片由 Tistio 在 Unsplash 上拍摄
介绍
我想我不需要提及这样一个事实,即像大多数人一样,我们研究人员,或者更准确地说,博士生在考虑计算机设备时是有预算的。我不能代表其他国家,但在克罗地亚,作为一名助教,你可以期待一台像样的中档笔记本电脑。对于大多数人来说,这很好,因为我认识的大多数博士生都在实验室工作或进行实地实验,对他们来说,一台能够运行 excel、R 和/或 Python 的基本统计脚本、一些 GIS 软件或 AutoCAD 的像样的笔记本电脑就足够了。
在相当长的一段时间里,我认为一台像样的笔记本电脑将非常适合我的水文学和水文模型相关的研究。这真的很棒,一切都运行得又快又好(多亏了固态硬盘和 16g 内存)。随着我开始处理大量数据,尤其是格式不太好的数据(在我的另一篇文章中找到如何解决这个问题)。在我的导师和一位也在类似职位工作的朋友的建议下,我越来越开始认为我需要学习编程,以缩短与数据格式化、复制等相关的无聊任务。我决定给 Python 一个机会。
瞬间,我兴奋地发现这是一门多么棒的编程语言,它让我可以轻松完成一些任务,而我通常会在 excel 中浪费 3-4 个小时来完成这些任务。不要误会我的意思,这不是对 excel 的指责,无论如何它对一些快速可视化,数据管理或作为一个简单的数据库来说都是很棒的。但是越来越多的时候,我的任务中,一个写得好、想得好的 Python 脚本只是赢得了游戏,让生活变得更容易。
让我们回到这个故事的主题。当你在网上消费 Python 和 Data Sconce 相关的内容时,你迟早会偶然发现“机器学习”这个术语,因为 Python 在这类任务中很受欢迎。这正是发生在我身上的事情。很快我就迷上了,并开始对这个话题进行更多的研究。
很快,我发现自己注册了 Udacity 课程“用 Python Nanodegree 进行人工智能编程”,在封锁期间,我可以免费使用 Udacity 的某些课程 30 天。课程的最终目标是建立一个花的图像分类器。简而言之,您得到了一个输入图像,代码将它分类到一个定义的标签中。我花了大约一个半月的时间通过了这门课程。
当你开始机器学习任务,特别是深度学习时,你经常会发现一些“绿色果汁”(NVIDIA GPU😉)可以让你的中端笔记本电脑或个人电脑运行得更快。为什么会这样呢?答案是,CUDA 核心。为什么它们如此重要,在此阅读 伟大文章 !因此,在预算有限的情况下,我开始在电脑爱好者论坛和网站上查找二手硬件的二手零件。
我不会提供任何测试结果,这更多的是一个建议类型的文章,从我的角度和多年的经验购买二手零件的论坛和不同的网站。我将试着解释哪些零件可以买二手货,以节省一些现金,或用同样的钱获得更好的性能,而不冒不必要的风险。
中央处理器

栾卓卡在 Unsplash 上拍照
许多人认为“中央处理器”或简称 CPU 是计算机的心脏。当你一起搜索术语“CPU”和“深度学习”时,最常见的问题是“CPU 对深度学习重要吗?”。这是一个棘手的问题,我找到的最好的答案可能是科林·卡萨迪在 Quora 上的回答,“这和游戏一样重要”。由于 CPU 为 GPU 做数据准备的工作,它必须足够快,以避免所选 GPU 出现瓶颈。CPU 可以被认为是一辆快车,它可以非常快地从主存中获取数据,但它的带宽很低,因此它不能一次处理大量数据。
我发现必须考虑的事情有:a) 内核数量(和时钟速度)和 b) 价格(当你预算紧张时很重要)。
自 2017 年锐龙问世以来,许多人认为它比英特尔更有价值。或许这是真的。尤其是在工作负载方面,锐龙远远超过英特尔。英特尔唯一能大放异彩的是游戏。
我试图找到二手零件之间的最佳交易。我不是在寻找英特尔或 AMD,只是最好的性价比。我发现一款英特尔 i5 8400 非常划算,这是一款 6 核 6 线程 CPU,基础时钟为 2.8 GHz,提升为 4.0 GHz。当然,i7 或锐龙肯定会更好,但当时没有好的交易。
我强烈建议你去当地的二手电脑网站看看,比如易趣或者亚马逊,因为 CPU 很少会坏。就物理损坏而言,英特尔可能更难损坏,因为触针在主板上,而 AMD 的触针在 CPU 上。
一如既往,购买二手设备时,最好的选择是亲自移交,以避免欺诈或物理损坏的零件。
主板或 MBO
当你决定哪种 CPU 最适合你的需求时,是时候为它选择合适的 MBO 了。由于我不需要支持多 GPU 或许多硬盘驱动器,一个更基本的板将做这项工作。自从我去了英特尔,他们提供了几种不同的芯片组 H、B、Q 和 Z 。h 和 B 芯片组是基本的,而 Z 提供更多的升级选项和功能,是为发烧友,超频和游戏玩家。我在我的城市附近找不到一个好的二手交易,所以我去当地商店买了一个来自 Asrock board 的 H310M 板。我个人避免购买二手主板,因为如果不小心处理,很容易损坏英特尔主板上的针脚。此外,对二手汽车的节省也不是很大。
GPU

照片由 Christian Wiediger 在 Unsplash 上拍摄
我再次做了功课,并开始在网上搜索关于深度学习的 GPU 的最佳“性价比”。有几十个来源,有些在媒体上也很棒。实际上,他们中的许多人都有一年左右的历史,并表示迄今为止最赚钱的 GPU 是 RTX 2070 或 2060 超级。我需要提到的是,在我构建 PC 的时候,RTX30XX 系列还没有推出,我链接的文章已经更新了 RTX30XX 系列的结果。
我在商店里找不到一个好的 RTX 2070 交易,也不是二手的,所以从一个论坛上选择了一个全新的技嘉 RTX 2060 超级游戏。卖家通过旧故障卡的 RMA 流程获得了该卡。GPU 的可以买二手,但要注意保修。此外,用于加密挖掘的 GPU 不是最佳选择。
有很多关于如何为深度学习选择合适的 GPU 的主题和文章,所以我强烈建议查看一下。在培养基上也有一些好的。
程序存储单元(Program Storage Unit)
PSU 有三种类型。非模块化、半模块化和全模块化。如果你不喜欢太多的电缆,你当然可以选择模块化的。我喜欢半模块化 PSU,因为它们通常有硬连线的 24 针 MBO、8 针 CPU 和一根用于 GPU 的 6 针 PCI-EX 电缆。所有这些都是需要的,所以这样的单位是完全适合我的。我看不出有必要为一个完全模块化的单元支付额外的费用,因为我肯定不会拆下一根 24 针的电缆。
RTX 2060 Super 在满负荷时需要大约 180W,加上系统中的 CPU 和所有“小”用户,我们在满负荷时大约需要 250-275 W。我是一个有点沉默的怪胎,所以一个能持续几年的高于平均水平的 PSU 是必须的。Seasonic 可能是世界上最受欢迎的 PSU 制造商,也有很好的声誉。他们的 PSU 我从来没有问题。谢天谢地,我在当地的一家商店买到了一辆保修 7 年的 Seasonic 核心 GM-650 。
PSU 是一个可以买到二手的部分,如果你确定它不是用于电力加密采矿机。此外,如果是二手的,确保它至少有 4-5 年的保修期,因为 PSU 不是经常更换的部件。
固态硬盘(或硬盘)
由于我们生活在 2020 年,系统中的一个 SSD 对我来说是必不可少的,至少是 250 GB 的操作系统。在硬盘上装有操作系统的 PC 或笔记本电脑上工作是非常痛苦的,Windows 加载时间大约为 1 分钟,或者浏览器需要 20 秒才能打开。在亚马逊上,250 GB 的固态硬盘从 30 美元起,到目前为止,这是配置你的电脑时最划算的 30 美元。没有任何其他部件能比固态硬盘提供更大的性能提升,只需 30 美元。
现代 SSD 支持两种标准,SATA 和 m.2。我不会深入研究它们之间的差异,因为这超出了本文的范围。点击这里了解更多信息。
就我而言,我在二手市场上找到了很多东西,我买了一台英特尔 660p 的 m.2 设备,还找到了一台 Kingston A400 sata 设备,两者的大小都是 500GB。英特尔 one 作为系统驱动器,因为它的读/写速度更快。在购买之前,请检查机器学习模型的空间要求以及您计划用机器做的任何其他工作。对我来说,有 1 TB 的可用空间就足够了。

SSD 在几个月的日常使用后的统计数据(图片由作者提供)
固态硬盘可以购买二手,但一定要检查写入的数据量,因为固态硬盘的缺点是“有限”的生命周期。正如在我的例子中看到的,我在使用水文模型时对它进行了一些磨损,这些模型往往会对驱动器进行大量的写入。
情况
在这里,我寻找一个体面的情况下,不会打破银行。对我来说,外表排在第二位,建筑质量和空气流通排在第一位。遗憾的是,二手箱子的市场并不大。通常情况下,情况并不乐观。此外,由于一个好的情况下可以找到像 70 美元,我去了当地的 PC 零件经销商,并得到了一个安泰克 P6 m-atx 的情况下,折扣为 39 美元。该案件有体面的气流结合高于平均水平的外观(至少在我看来)和足够的空间固态硬盘。我喜欢整洁的外观,因此在管理线缆时格外小心。
其他部分
我们忘记了什么?如上所述,通过机箱的气流是很重要的,因此请确保您的机箱预装了风扇,或者在售后加装了风扇。我选择了北极 P14 风扇,因为他们的性价比很高。此外,售后 CPU 冷却器是一个好主意,如果你喜欢安静。这里,使用了北极冷冻机 34。这是一个 20 美元的 CPU 冷却器,非常适合中高端 CPU(如果不是超频的话)。水冷也是一个选择,如果你想要一个更狂热的建筑。对于中档建筑,像这样的,空气冷却就足够了。
结论和最终想法

最终建成(图片由作者提供)
在这里,我提出了我对在考虑预算的情况下构建深度学习机器这一主题的想法。我想给我的意见,哪些部分和为什么可以买到二手。最后的结果可以在这里看到。我设法用不到 1000 美元的预算建造了一台像样的深度学习 PC,仅在 CPU 和 GPU 上我就节省了近 300 美元。总共大约 400 美元。这是一个很好的节省,它使我的构建延迟了 3-4 周,并花费了我一些努力去寻找好的交易。
但是,我再次建议,你只去二手的某些组件,只有当你可以确定这个特定的部分没有损坏,并有适当的保证。应避免使用无保修的零件。
如果你喜欢我的文章,欢迎在媒体或 LinkedIn 上关注我。干杯!
如何为数据科学选择合适的笔记本电脑
原文:https://towardsdatascience.com/how-to-pick-the-right-notebook-for-data-science-7dc418c4da57?source=collection_archive---------13-----------------------
数据工程 101
流行的开源笔记本框架的深入比较。

照片由思想目录在 Unsplash 上拍摄
如果你是一个大数据爱好者,你可能使用过(或者至少听说过) Jupyter Notebook ,这是数据科学社区中事实上的开源笔记本框架。但是,您知道其他可能更适合您的数据科学项目的笔记本工具吗?
在这篇博文中,我将比较一系列开源笔记本,包括 Jupyter、Zeppelin、Spark Notebook 和 Polynote,以帮助您选择最适合您的分析用例的笔记本。
在我们开始之前…
以下是我们将对每个笔记本选项进行评估的主要功能列表:
- 内核:我可以使用哪些编程语言?我可以在同一个笔记本中用多种语言编写代码吗?
- 版本控制:笔记本和 Git 集成的怎么样?
- 数据可视化:绘图的灵活性如何?
- 社区:虽然社区大小不是产品的特性,但是一个大的用户社区意味着更好的文档,更成熟的插件,以及当你需要帮助时更容易排除故障。
Jupyter 笔记本

来源: Jupyter 笔记本
截至今天,Jupyter 无疑是最受欢迎的笔记本框架。它支持超过 40 种编程语言,包括 Python、R、Julia 和 Scala。虽然基本的 IPython 内核不允许在单元之间切换语言,但是你可以安装一个第三方工具,比如 BeakerX 和 SoS 来实现这个特性。
自从朱庇特笔记本(。ipynb)本质上是 JSON 文件,用户可以使用 Git 轻松地控制笔记本的版本,Github 可以在浏览器上非常好地显示笔记本。如果您更喜欢使用Jupyter Lab(Jupyter 的一个扩展的类似 IDE 的用户界面),您可以添加一个 Github 扩展来使您的 Git 工作流更加容易。像 matplotlib 和 plotly 这样的流行绘图库与 Jupyter Notebook 很好地集成在一起。
在所有可用的开源笔记本框架中,Jupyter 拥有最大的用户群体。截至 2018 年 9 月,GitHub 托管了超过250 万台公共 Jupyter 笔记本。超过 15,000 个与 Jupyter 相关的问题在 Stackoverflow 上得到回答。JupyterCon 是一个致力于 Jupyter 社区的系列会议,每年由 Project Jupyter 和 O'Reilly Media 主办。
阿帕奇齐柏林飞艇

来源:阿帕奇·泽普林
Apache Zeppelin 可能是分析社区中第二受欢迎的笔记本电脑。Zeppelin 支持三种编程语言:Python、R 和 SQL。它与 Apache Spark 有着惊人的内置集成,允许用户使用 JDBC 无缝查询许多数据库系统。Zeppelin 还支持同一笔记本中的多种解释器/语言。
齐柏林笔记本(。json)可以由 Git 进行版本控制,但不幸的是,Github 目前只将它们显示为纯文本文件,这使得没有本地或托管实例的笔记本很难共享。然而, ZEPL 可用于在浏览器中重新呈现公共笔记本。
Zeppelin 的一个独一无二的特性是,它让用户可以像 BI 仪表板一样调整和排列笔记本单元格,而在其他笔记本框架中,用户根本不允许移动单元格。
火花笔记本

来源:星火笔记本
Spark Notebook 构建在用于内存数据处理的顶级分析引擎 Apache Spark 之上。Scala 是 Apache Spark 唯一支持的编程语言。SparkContext 是现成的,它为每个 Spark 会话生成单独的 JVM,以避免潜在的冲突。
目前 Github 无法显示 Spark 笔记本(。snb)而且目前还没有共享 live 笔记本的托管服务。数据可视化选项似乎也很有限。
截至目前,Spark Notebook 的用户群体相对较小,因为很难在网上找到示例和指南。
波利诺特

来源:开源的 Polynote:一个 IDE 启发的多语言笔记本
Polynote 是网飞在 2019 年末开源的一款全新笔记本工具。用户可以用 Scala(有一流的支持)、Python 和 Polynote 中的 SQL 编写代码,并且可以在单元格之间切换语言和共享变量(又名 polyglot )。
Polynote 共享相同的文件扩展名(。ipynb ),这样它们也可以被版本控制并显示在 Github 上。
Polynote 已经内置了与 matplotlib 和 Vega 的集成。此外,它有一个自动完成的编辑器来提高您的工作效率,还有一个额外的内核状态面板来让您更清楚地了解正在运行的作业。
Polynote 仍处于早期阶段,但许多数据科学爱好者已经在尝试它了。就我个人而言,我非常期待看到它变得更加稳定,增加更多的功能。
想了解更多关于数据工程的知识?查看我的 数据工程 101 专栏关于走向数据科学:
[## 数据工程 101 -走向数据科学
阅读《走向数据科学》中关于数据工程 101 的文章。分享概念、想法和…
towardsdatascience.com](https://towardsdatascience.com/tagged/data-engineering-101)
如何在 Python 中为投资组合挑选不相关的股票
原文:https://towardsdatascience.com/how-to-pick-uncorrelated-stocks-for-an-investment-portfolio-in-python-d75867d1c11e?source=collection_archive---------27-----------------------
一个简单的 Python 代码,用来挑选标准普尔 500 相关性最低的股票

马库斯·温克勒在 Unsplash 上的照片
有价证券投资是一种迷人的投资,有可能带来令人满意的回报。根据现代投资组合理论,选择相关性低的股票或 ETF 总是一个好主意。
让我们看看为什么以及如何在 Python 中测量股票相关性来选择股票。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
什么是线性相关?
股票之间的相关性是衡量一只股票的回报如何影响另一只股票的回报。如果两只股票高度相关,它们可能会同向波动(即,如果一只股票价格上涨,另一只股票价格也会上涨)或反向波动。
从数学上讲,两只股票之间的线性相关指数,比如说 a 和 b ,定义为:

其中分子是股票之间的协方差,分母是标准差的乘积。
这个数字的范围是从-1 到 1。如果它是-1,股票向相反的方向移动(即,如果一只股票上涨,另一只股票下跌),如果它等于 1,股票完全向同一方向移动。如果它等于 0,股票是不相关的,它们的运动是相互独立的。我们必须寻找这些不相关的股票。
为什么要选择不相关的股票?
如果我们建立一个由一些股票组成的投资组合,它们的权重是 x ,投资组合的方差是:

因此,只要股票之间的相关性为正,我们投资组合的方差相对于方差之和就会增加,其风险也会增加。有些人可能会说,我们会喜欢负相关的股票,但在这种情况下,不会有任何回报,因为如果一只股票上涨,另一只股票下跌,净回报为 0。
所以,我们的想法是保持我们的股票不相关,以消除第二项,避免更高的方差。这是现代投资组合理论的一个分支的目的,有数学工具允许我们根据权重 x 优化方差。在这篇文章中,我们将重点选择那些线性相关性的绝对值几乎等于 0 的股票。
代码
在文章的这一部分,我们将研究标准普尔 500 股票,我们将找出相互关联度较低的几只股票。一切都可以在我的 GitHub 资源库中找到:https://GitHub . com/gianlucamalato/machine learning/blob/master/Stocks _ correlation . ipynb
我们将使用 pandas 库来执行所有的计算,而 S & P 成分的列表将从这个 GitHub 存储库下载:https://GitHub . com/datasets/S-and-P-500-companies/tree/master/data
首先,让我们导入一些有用的库:
然后,我们希望获得历史时间范围内的所有标准普尔 500 股票,例如从 2018 年到 2019 年。让我们先下载标准普尔 500 的历史数据,以获得这一时期的有效交易日。
现在,我们可以滚动 tickers 数据框并下载每个符号的历史数据。由于我们列表中的一些股票可能已经被摘牌,或者可能太新,我们检查每只股票是否在标准普尔 500 的交易日进行过交易。如果没有,我们丢弃库存。如果股票不再是标准普尔 500 的一部分,或者根据我们的历史时间范围,它太新,就会发生这种情况。因为我们想有一个均匀的时间间隔,我们丢弃这样的股票。
然后,对于每只股票,我们计算每日百分比回报。
这是总数据帧。每一列都是股票的每日收益,股票的名称就是列的名称。索引是日期。

我们现在可以使用 Pandas 的“corr”方法计算每只股票之间的线性相关性,然后我们可以使用“melt”方法将列转置为行来规范化该表。

如你所见,我们有每只股票与自身的相关性(显然是 1),我们得到股票 A 与股票 B 的相关性,以及股票 B 与股票 A 的相关性,这是相同的,因为相关性是对称的。我们可以去掉这些无用的记录,计算相关指数的绝对值。
然后,我们可以按绝对值升序对表进行排序,这样我们在第一条记录中就有了相关性较低的股票对。
最后,这是 2018-2019 年期间标准普尔 500 相关性较低的股票对的表格。

结论
计算股票之间的相关性是有用的,每个投资组合投资者都必须这样做。然而,相关性可能会随着时间的推移而变化,因此定期计算它可能会有助于调整投资组合,使其不会遭受可能会增加整体风险的突然相关性。
如何规划和组织数据科学/分析项目?
原文:https://towardsdatascience.com/how-to-plan-and-organize-a-data-science-analytics-project-a9418c12c808?source=collection_archive---------5-----------------------
开展数据科学/分析项目总是需要时间,而且从来都不容易。一个成功而全面的分析项目远远不止编码。相反,它涉及复杂的计划和大量的沟通。

照片由屋大维丹在 Unsplash
分析项目的生命周期是怎样的?
要完成一个数据科学/分析项目,您可能需要经历五个主要阶段,从了解问题和设计项目开始,到收集数据、运行分析、展示结果、做文档和自我反思。

由作者创建
我有一种强烈的感觉,运行一个分析项目非常类似于建造一座房子。首先,架构师会见他/她的客户,了解他们的需求,并提出一个可行的蓝图(理解和计划)。
然后需要收集建筑材料,如水泥、钢材、砖块等。你必须了解建筑材料的特性,选择合适的建筑材料。否则,你最终可能会拥有一个很容易倒塌的房子。这就像一个数据收集过程,你必须做一些 EDA 或功能工程来理解数据,并找到正确的数据来解决你的分析问题,否则你可能无法从你的分析中获得可靠或具体的结果!
有了建筑材料和蓝图,你就可以开始建房子了(运行分析)。施工完成后,需要进行房屋检查和质量检查,以确保安全。同样,我们需要记录我们关于方法、结论和限制的分析项目。
了解&计划
如果问我整个周期最关键的阶段,我会毫不犹豫地说理解和规划,因为数据科学和分析的主要目的不是用花哨的技术创建项目,而是解决实际问题。因此,分析项目的成功在很大程度上取决于您对情况的了解程度、对问题的定义以及将业务问题转化为分析问题的能力。从这个角度来看,花时间思考您的分析项目的更广泛的背景总是值得的。
- 提问
通常情况下,一个分析项目始于一个与业务合作伙伴会面的启动会议。他们会提供一些背景信息,并简单谈谈他们在寻找什么。问聪明的问题总是会让你更好地理解业务涉众的痛点和需求。这里有一些你可以问的问题。

由作者创建
- 分析计划
在开始分析之前,让我们制定一个分析计划,并召开另一次跟进会议来回顾问题并强化预期。
它将提供该计划的高层次概述,给出接下来步骤的清晰画面,并从业务方面绘制技术行动和更大画面之间的联系。以下是我的分析计划中的一些关键要素:

由作者创建
不要让数据科技成为一个谜。尝试用通俗易懂的语言对方法进行简要描述,概述用例及场景,并总结优点和局限性。避免复杂的公式或函数,而是专注于该方法如何帮助解决问题。
完成一个分析项目可能需要几周时间,有时甚至更长。一个项目持续的时间越长,一些变量在工作中捣乱的可能性就越大。因此,在你的项目开始之前,第一件事是解开你完成项目必须做的所有步骤。然后估计完成这些任务所需的时间框架,并标记一些里程碑。

由作者创建
建议你不要只做一个最终演示,而是在项目中间设立一些检查点,与你的利益相关者接触并获得他们的反馈,这样你就可以及时进行调整。

由作者创建
如何组织项目并跟踪进度
- 利用项目管理工具
当你在处理一个复杂的分析项目,并且需要与多个团队合作时,比如工程、产品和业务等,简单的待办事项列表或基于 excel 的跟踪工具是不够的。

Jo Szczepanska 在 Unsplash 上拍摄的照片
但是,您可以利用专用的项目管理工具和软件。如果你去谷歌简单地搜索项目管理工具,许多工具会抓住你的注意力,如 Asana,Trello,Monday.com JIRA 等。我打赌你会根据你的团队规模和你喜欢的工作方式找到合适的工具。但是,idea 赢得了我的心,因为它是一个一体化的工作空间,将几个工作应用程序融为一体。我真的很讨厌有多种工具用于不同的目的,所以你可以想象,“多合一”是最有效的营销信息来转换我。
对我来说,在一个地方做计划、跟踪、知识分享和写博客是一个很棒的选择。信不信由你,它还提供模板,以方便旅行计划,并协助您跟踪工作申请的进展。
- 冲刺规划
你有一个强大的工具。就像你的私人助理。如何保证协作,让轮子运转起来?先说冲刺规划。
对于那些不熟悉 sprint 概念的人来说,sprint 是一个短暂的、有时间限制的时期,团队在这个时期努力完成一定数量的工作。
sprint 让项目更容易管理,让团队更快更频繁地交付高质量的工作,并给他们更多的灵活性来适应变化。
进行冲刺规划的首要任务是决定冲刺的长度。尽管没有硬性规定每个 sprint 应该持续多长时间,但它必须足够长以确保任务可以完成,同时它也应该足够短以使需求和目标保持不变。
在 sprint 规划会议上,整个团队将调整即将到来的 sprint 的目标,并计划有助于实现该目标的工作。这些任务将被逐项列出,按优先顺序排列,分配给团队成员,并记录到即将到来的 sprint 的板上。
- 每日一站
Sprint 规划是为了定义要实现的目标和要交付的任务,以推动项目的进展,而 5 到 10 分钟的每日例会将有助于规划与执行相一致。更具体地说,就是让团队达成共识,明确优先级,避免一些常见的障碍。

由作者创建
长话短说,这里有三个大家都会回答的基本问题:
- 你昨天做了什么?
- 你今天要做什么?
- 什么阻碍了你的发展?

由作者创建
不要忽视文档和反思的重要性
我在数据分析/数据科学领域已经工作了六年多。我希望在我开始职业生涯时就知道的一件事是,文档和反思与分析本身同等重要。由于你所做的所有分析项目都有可能作为一个闪亮的项目进入你的简历,然后它们将成为面试的谈话点,一旦完成,总结和框定你的分析工作对你刷新记忆、巩固所有材料和构建故事非常有益。
- 记录并框定你的分析
你可以遵循这个框架,包括情况、问题、解决方案和后续步骤(SPSN)。

由作者创建
首先,描述当前的状态和痛点,然后描述问题并大声说出该项目的业务影响。
最关键的部分是解决方案,在这里您概括了高层次的方法,并逐步提供关于数据和分析的细节。然后记录从您的分析中得出的结果、见解和可行的建议。
请注意,没有完美的数据科学项目。开诚布公地谈论你的项目的注意事项和局限性。大声说出你的分析可以解决的问题是很好的,同时了解什么样的问题不能回答也是很有价值的。
最后一部分是下一步。潜在的下一步将是测试新的方法以提高准确性,包括新的数据源,或者自动化整个过程以使结果每天都显示出来等。
同时,不要忘记通过创建一个故事网格来进行自我反思,并将你在每个分析项目中遇到的一些例子和情况映射到以下五个类别中。

由作者创建
希望它有助于促进您的分析/数据科学项目的整个过程!
如何利用强化学习玩井字游戏
原文:https://towardsdatascience.com/how-to-play-tic-tac-toe-using-reinforcement-learning-9604130e56f6?source=collection_archive---------23-----------------------
关于 Q-learning 的简单教程
Q-learning 是一种出色而基本的强化学习方法,由于深度学习革命,它最近取得了很多成功。虽然本教程不会解释什么是深度 Q 学习,但我们将通过原始的 Q 学习算法来教一个代理如何玩一个井字游戏。尽管它很简单,但我们会看到它能给出极好的结果。
首先,我们将通过一些必要的背景知识来快速了解强化学习,然后我们将介绍 Q-learning 算法,最后是如何实现它来教代理玩井字游戏。
为了理解本教程,不需要有任何关于强化学习的知识,但它将有助于对微积分和线性代数有一个基本的了解。最后,我分享了我自己的 Github 知识库,里面有我解释的东西,你可以免费查看,如果你感兴趣,点击这里。
强化学习概述
强化学习的目标是当智能体在不同状态的环境中运行时,根据某种奖励函数优化智能体的行为。对于本教程,环境是井字游戏,它有明确定义的动作,代理必须决定选择什么动作来赢得游戏。此外,代理人将因赢得游戏而获得奖励,这鼓励它在游戏中学习好的策略。
强化学习的一个常见框架是(有限)马尔可夫决策过程 (MDP)。它帮助我们定义一组动作和状态,代理的决策是基于这些动作和状态的。
一个 MDP 包括
- 一组有限的动作(在游戏板上放置标记的位置)
- 状态的有限集合(游戏板的给定配置)**
- 一个奖励函数 R(s,a) ,该函数基于在状态 s 中执行动作 a 来返回值。
- 一个转移函数 T(s,a,s’)
当执行动作时,转换函数给出从状态 s 移动到s’的概率。当我们处在一个不确定某项行动是否总能产生预期结果的环境中时,这是必要的。然而,在井字游戏中,我们确切地知道每个动作会做什么,所以我们不会使用这个。**

状态空间由所有可能的游戏配置组成。在每个状态下,我们可以执行一组可用的操作。在这个例子中,当前玩家有六个可能的动作要执行。(图由作者提供)
MDP 框架帮助我们形式化了这个问题,根据当前的状态,确定哪些行为将使代理人在游戏中的总报酬最大化。奖励函数 R(s,a) 会非常简单:
- 如果代理人从执行一个赢得游戏的动作—,那么 R(s,β)= 1。
- 否则,如果代理犯了一个错误,选择了错误的动作从而输掉了游戏,那么 R(s,γ)=-1。
- 否则,当上述情况都没有发生时,奖励简单来说就是 R(s,a) = 0。
在强化学习中,我们找到了一个最优策略,代理使用它来决定采取哪些行动。由于我们使用 Q-learning,我们将简单地把我们的策略表示为当代理处于状态 s 时最大化函数【s,a】的动作。这是 Q-learning 的核心,所以让我们来看看如何计算这个函数。**

对于游戏中的每个状态,每个动作都与一个 Q 值相关联。最佳策略是选择价值最高的行动。在这个具有状态 s 的例子中,下一轮属于玩家 X,并且很明显哪个动作具有最高的预期奖励,因为 X 即将获胜。
用贝尔曼方程更新
Q(s,a) 的解释是:如果代理人在状态 s 中拾取动作 a 则 Q 是游戏结束时给出的期望奖励。由于代理人想使其报酬最大化,它想选择使 Q 最大化的行动。

在游戏的这种状态下,我们显示当前玩家 X 的 Q 值的场景示例。通过将下一个标记放置在最大值所在的位置,玩家将赢得游戏并获得奖励。(图由作者提供)
为了计算 Q(s,a) ,代理必须探索所有可能的状态和动作对,同时从奖励函数【R(s,a)** 获得反馈。在井字游戏的情况下,我们通过让代理与对手玩许多游戏来迭代更新 Q(s,a) 。利用 Q 学习算法,用于更新 Q 的等式如下:**

- 我们执行一个动作 一个 当前状态 s.
- 最后一项展望未来并返回可用的最大 Q 值,【ŝ】是执行动作后的新状态。然后,动作—是下一个状态 ŝ 的最佳动作。**
- 学习率 α 决定我们在多大程度上覆盖旧值,我们将使用 α = 0.1 。
- 折扣因子 γ 决定了与当前时间步长 t 的奖励相比,未来奖励的权重。我们将使用 γ = 0.9 。
这个等式基于强化学习中众所周知的等式,称为贝尔曼等式。让我们看看如何使用这个等式来教导我们的代理。
Q 学习算法的实现
要得到一个训练有素的代理,我们需要学习 Q(s,a) 的值。这将通过让两个代理相互竞争来实现。我们将引入一个概率 ε 每个智能体挑选一个随机动作,否则它将根据 Q(s,a) 挑选最佳动作。用这种方式,我们确保到平衡学习,使得代理有时探索新的动作,而其他时候利用代理已经学习的信息。
这个训练阶段可以用 Q 学习算法的下列伪代码来描述:
**Initialise: Q(s,a) = 0, starting state s,
starting player P, iterations Nfor t = 0 : N With probability **ε** :P picks random action a
Else, pick action a that maximise Q(s,a) Observe new state ŝ and reward R(s,a) If current player is our agent,
update Q(s,a) = (1-α)Q(s,a) + α[R(s,a) + γ**max(*Q(ŝ,â)*)*] s = ŝ
Switch turn, P = the other player**
注意迭代次数 N 一定比较大,我一直用 50 万左右。另外, Q(s,a) 可以实现为 Python 字典,或者如果我们将 (s,a) 表示为整数,则可以实现为二维数组。最后,可以随时间改变概率 ε ,以强调早期迭代中的更多随机探索,这可能会加快学习。
在你用算法训练了你的代理之后,你可以保存【Q(s,a)】的值,当你想和代理对战的时候加载它。然后,代理人只需通过选择最大化【s,a】的行动来遵循最优策略。虽然代理并没有因为井字游戏的简单而变得非常聪明,但是如果你想学习如何实现 Q-learning 并看到它的工作,尝试一下仍然很有趣。
摘要
总之,本教程首先解释了马尔可夫决策过程(MDP)框架,以及它是如何用于强化学习的。我们用状态、动作和奖励函数模拟了井字游戏。在此基础上,我们定义了函数 Q(s,a) ,该函数通过在状态【s中选择动作来量化期望的奖励,并通过反复玩游戏展示了计算【Q(s,a)* 的公式。***
我希望你喜欢这个教程,如果你有任何问题,欢迎在这里或通过 Twitter 联系我。最后,如果你想看看这在实践中是如何工作的,那就在下面链接的我的 Github 资源库中查看我的实现。
https://github.com/RickardKarl/bill-the-bot
如何以友好的方式用加权调查绘制李克特量表
原文:https://towardsdatascience.com/how-to-plot-likert-scales-with-a-weighted-survey-in-a-dplyr-friendly-way-68df600881a?source=collection_archive---------28-----------------------
如果你在 R 中使用过 Likert scale 可视化,你可能知道 Jason Bryer 的 Likert 包。尽管这是一个很棒的包,但它在处理加权调查时的能力是有限的。在寻找解决方法时,我发现了这个的好帖子,它解释了这个过程,但是使用了很多我不太熟悉的 base R 函数。最后,我设法以一种适合我的工作流程的 dplyr 友好的方式复制了这个过程,并认为它可能对面临同样问题的其他 R 用户有用。在这里我会指导你整个过程。
数据
为了使这成为一个非常普遍的情况,让我们生成一些您可以在加权调查中找到的随机数据。我们的数据框将包含每个回答者的 id、他们对 5 个不同问题的 Likert 量表的回答、一个表示他们所代表的群体的字母,以及分配给每个回答者的权重。
library(tidyverse)n_sample <- 100sample_data <- tibble(
id = seq(1, n_sample, 1),
q1 = sample.int(5, n_sample, replace = TRUE),
q2 = sample.int(5, n_sample, replace = TRUE),
q3 = sample.int(5, n_sample, replace = TRUE),
q4 = sample.int(5, n_sample, replace = TRUE),
q5 = sample.int(5, n_sample, replace = TRUE),
group = sample(c("A","B"), n_sample, replace = TRUE),
weight = runif(n_sample, 1, 3)
)
获得加权结果
我们这里的主要目标是对我们的结果进行加权(否则我们会直接使用 Likert 包)。为此,您可以使用超级有用的调查包,它为您提供了许多处理调查数据的工具。这个包与我通常使用的 tidyverse 工具不太兼容,但幸运的是,我们可以使用 srvyr 包,它允许我们使用 dplyr 语法处理调查包函数。
首先,我们将把数据转换成一个调查对象。然后,我们将定义一个函数来提取单个问题的加权结果,最后,我们将应用这个函数来获得每个问题的结果。
library(srvyr)# Tranform sample data into survey data
survey_data <- sample_data %>%
as_survey_design(id = 1,
weights = weight)# Function that gets the weighted frequency of answers for a single question
get_weighted_results <- function(q, survey_data){
survey_data %>%
group_by(group) %>%
summarize(a = survey_total(get(q) == 1),
b = survey_total(get(q) == 2),
c = survey_total(get(q) == 3),
d = survey_total(get(q) == 4),
e = survey_total(get(q) == 5)) %>%
pivot_longer(-group,
names_to = "ans",
values_to = "freq") %>%
filter(!str_detect(ans, "se"))
}# Apply function to each question and calculate proportion
likert_results <- tibble(q = c("q1", "q2", "q3", "q4", "q5")) %>%
mutate(results = map(q, get_weighted_results, survey_data)) %>%
unnest(results) %>%
group_by(q, group) %>%
mutate(prop = freq / sum(freq)) %>%
ungroup()
让我们花点时间来研究一下我们的新函数有什么作用:
- 获取您的调查数据并按预定义的变量对其进行分组。这里我假设你有一个分组变量:如果没有,就忽略这一步。
- 汇总得到每个可能答案在李克特量表上的加权频率。请注意,我将每个答案保存在不同的信中。稍后我们将把这些信件翻译成文本。
- 将我们的数据框转换为整齐的格式。当我们开始用 ggplot2 绘图时,这将很有帮助。
- 过滤包含“se”的行。默认情况下,survey_total 函数也将返回总数的标准误差。我们不会在这里使用它,但是如果需要的话,你可以把它留下。
然后,我们从头开始创建一个新的数据框,其中有一列包含我们的 Likert 问题的变量名。我们将函数应用于该列,对结果进行去嵌套,并计算我们将要绘制的比例。您应该会得到如下所示的数据框:

我们将要绘制的整洁的数据框应该如下所示
制作我们的绘图功能
在我的例子中,我有许多李克特量表问题要在不同的分组中显示,所以我认为最方便的解决方案是创建一个函数来绘制我需要的任何问题。这个函数很长,但是不要害怕,我会一步一步地指导你。让我们来看看吧。
plot_weighted_likert <- function(x, my_labels, likert_results) {
# Filter data for questions needed
likert_results2 <- likert_results %>%
filter(q %in% x)
# Create data frame with labels
prop_labels <- likert_results2 %>%
mutate(
position = case_when(
ans == "a" | ans == "b" ~ "left",
ans == "c" ~ "center",
ans == "d" | ans == "e" ~ "right"
)
) %>%
group_by(q, group, position) %>%
summarize(label = sum(prop * 100)) %>%
pivot_wider(names_from = position,
values_from = label)
# Data frame with right side values
high_columns <- likert_results2 %>%
filter(ans == "c" | ans == "d" | ans == "e") %>%
mutate(prop = case_when(ans == "c" ~ prop / 2 * 100,
ans == "d" ~ prop * 100,
ans == "e" ~ prop * 100,)) %>%
arrange(ans)
# Data frame with left side values
low_columns <- likert_results2 %>%
filter(ans == "a" | ans == "b" | ans == "c") %>%
mutate(prop = case_when(ans == "a" ~ prop * 100,
ans == "b" ~ prop * 100,
ans == "c" ~ prop / 2 * 100)) %>%
arrange(ans)
# Define empty ggplot object
p <- ggplot() +
# Add central black line
geom_hline(yintercept = 0) +
# Add right side columns
geom_bar(
data = high_columns,
mapping = aes(x = group,
y = prop,
fill = ans),
position = position_stack(reverse = TRUE),
stat = "identity"
) +
# Add left side columns
geom_bar(
data = low_columns,
mapping = aes(x = group,
y = -prop,
fill = ans),
position = "stack",
stat = "identity"
) +
# Left side labels
geom_text(
data = prop_labels,
mapping = aes(
x = group,
y = -100,
label = paste(round(left) , "%", sep = "")),
hjust = 1,
color = "black",
size = 3
) +
# Central labels
geom_text(
data = prop_labels,
mapping = aes(
x = group,
y = 0,
label = paste(round(center) , "%", sep = "")),
hjust = 0.5,
color = "black",
size = 3
) +
# Right side labels
geom_text(
data = prop_labels,
mapping = aes(
x = group,
y = 100,
label = paste(round(right) , "%", sep = "")),
hjust = -0.2,
color = "black",
size = 3
) +
# Scale formatting
scale_y_continuous(
breaks = seq(-100, 100, 50),
limits = c(-105, 105),
labels = abs
) +
# More formatting
theme(legend.title = element_blank(),
legend.position = "bottom",
axis.ticks = element_blank(),
strip.background = element_rect(fill = "#F0F0F0",
color = "#F0F0F0"),
panel.background = element_blank(),
panel.border = element_rect(
colour = "#F0F0F0",
fill = NA,
size = 1.5)
) +
facet_wrap(~ q, ncol = 1) +
coord_flip() +
ylab("Proportion") +
xlab("") +
# Change Likert labels
scale_fill_discrete(labels = my_labels)
# Print the plot
p
}
好吧,那么,我们在这里做什么?
- 我们的函数将采用一个包含我们要绘制的问题名称的字符向量,另一个包含我们的 Likert 量表标签的字符向量,以及我们创建的数据框。
- 第一步是过滤数据框,因为我们只对给定的一组问题感兴趣。
- 然后,我们计算将出现在绘图左侧、中间和右侧的标签。和最初的 Likert 包一样,在每一边,我们都要显示极端答案的百分比。为此,我们创建一个名为 position(左、右或中心)的新列,计算每个位置的比例总和,最后将数据框转换为更宽的格式,以便于使用。
- 现在,我们将准备绘制两个新的数据框,分别包含较低和较高的值。中心值将除以 2,每一半将放入其中一个数据框中。我们必须按“ans”列排列每个数据框,以便在我们的绘图中正确堆叠值。
- 我们准备好开始策划了。首先,我们创建一个空的 ggplot 对象并添加我们的中心线。
- 然后我们添加两个
geom_bar,用于我们的左列和右列。这里要注意两点:对于左侧的值,我们将-value绘制为我们的 y 美学,并且我们在右侧的条中指定了position_stack(reverse = TRUE),因此它们按照我们想要的顺序堆叠。 - 然后我们添加三个
geom_text来绘制百分比标签。由于我们的标签目前是十进制数字,我们将它们四舍五入,并粘贴一个百分号。对于hjust参数,我只是使用了最初的 Likert 包中的默认值。 - 接下来,我们对 y 轴进行格式化。这里我在
labels参数中传递了abs函数,所以我们的标签从 100 到 0 再到 100。 - 然后我用
theme做一些格式化。在这种情况下,我选择了一个与原来略有不同的面板边框,因为我更喜欢它。之后,我加上刻面,翻转天平,加上标签, - 最后,我添加了一个
scale_fill_discrete来将我的“a,b,c,d,e”标签更改为所需的标签。
结果
让我们看一些由此产生的李克特曲线图的例子。(不要忘记定义一个 labels 对象,因为函数中没有默认的对象)。
my_labels <- c("Very\nunsatisfied",
"Unsatisfied",
"Neutral",
"Satisfied",
"Very\nsatistifed")plot_weighted_likert(c("q1"), my_labels, likert_results)
plot_weighted_likert(c("q2", "q3", "q4"), my_labels, likert_results)
plot_weighted_likert(c("q1", "q2", "q3", "q4", "q5"), my_labels, likert_results)

只有一个问题的情节

三个问题的情节

五个问题的情节
就是这样!我希望这有所帮助,如果您有任何疑问,请告诉我。
一些改进
你可能需要对你的情节做一些我在这里没有提到的改进。我将简要阐述这些问题:
- 个性化的颜色。为此,将
scale_fill_discrete替换为scale_fill_manual,保留 labels 参数,并将一个 5 色矢量添加到values参数中。 - 分组顺序。在结果图中,我们将 B 组绘制在 a 组之上。要定义绘制组的顺序,您可以使用
factor函数并指定组的顺序来改变group列。 - 问题标签。这里最简单的方法是让您的
q列包含问题文本。通过这种方式,该功能将继续按预期工作。您还可以添加一个新的包含问题文本的text列。如果你这样做,你将不得不修改函数,以便它在需要时使用text而不是q作为变量。 - 问题顺序。绘制问题文本时,您的问题可能会以不同于预期的顺序显示。为了解决这个问题,您可以创建一个
text_order向量,它按照您希望问题显示的顺序包含问题,并使用factor函数改变likert_results2数据框中的text列(在函数内部,在您过滤它之后),并传递这个向量。
如何用 Logzero 练习 Python 中的日志记录
原文:https://towardsdatascience.com/how-to-practice-logging-in-python-with-logzero-82e4f9842a5c?source=collection_archive---------40-----------------------
为您的 Python 项目提供强大而有效的日志记录。

儿子阮金的照片
Logzero 是由 Chris Hager 创建的 Python 包,它简化了 Python 2 和 3 的日志记录。Logzero 作为打印语句更容易显示信息和调试细节。
如果你想知道什么是日志记录,我推荐你阅读我之前写的关于“如何用 Python 日志记录模块运行机器学习实验”的文章,尤其是前 3 节。
在那篇文章中,您将了解到:
- 什么是日志记录?
- 为什么日志记录很重要。
- 测井在不同技术行业中的应用。
Logzero 具有不同的特性,使得它更易于在 Python 项目中使用。这些功能包括:
- 轻松记录到控制台和/或文件。
- 提供完全配置的标准 Python logger 对象。
- 漂亮的格式,包括控制台中特定级别的颜色。
- 适用于各种字符编码和特殊字符。
- 兼容 Python 2 和 3。
- 不再依赖 Python。
安装。
使用 pip 运行安装 logzero。
pip install -U logzero
你也可以从公共 Github repo 安装 logzero:
git clone https://github.com/metachris/logzero.git
cd logzero
python setup.py install
基本例子。
我们将从一个基本的例子开始。在 python 文件中,我们将从 logzero 导入日志记录器,并尝试 4 种不同的日志记录级别示例。
#import logger from logzero
from logzero import loggerlogger.debug(“hello”)
logger.info(“info”)
logger.warning(“warning”)
logger.error(“error”)
输出是彩色的,易于阅读。

对数零输出
如你所见,每一关都有自己的颜色。这意味着您可以通过检查颜色轻松识别级别。
将日志写入文件
大多数时候 Python 用户倾向于在文件中写日志。系统运行时,您可以将日志保存在文件中,并查看它们以进行错误检查和维护。您还可以设置一个文件来保存 legzero 中的所有日志条目。
我们将从 logezero 导入日志记录器和日志文件。logfile 方法将帮助我们配置日志文件来保存我们的日志条目。
现在,您的日志条目将被记录到名为 my_logfile.log 的文件中。
#import logger and logfile
from logzero import logger, logfile
#set logfile path
logfile('my_logfile.log')
# Log messages
logger.info("This log message saved in the log file")
my_logfile.log 中的输出包含日志级别标签(对于标记为“I”的信息级别)、日期、时间、python 文件名、行号和消息本身。
[I 200409 23:49:59 demo:8] This log message saved in the log file
旋转日志文件。
您不需要一个单独的日志文件来保存所有的日志条目。这导致系统打开和关闭大量日志文件。
您可以使用 maxBytes 和 backupCount 参数来允许文件以预定的大小翻转。当大小即将超出时,文件将被关闭,并自动打开一个新文件进行输出。每当当前日志文件的长度接近 maxBytes 时,就会发生翻转。如果 maxBytes 或 backupCount 为零,则永远不会发生翻转。
在下面的例子中,我们将 maxBytes 设置为 1000000 字节(1 MB)。这意味着当文件大小超过 1MB 时,文件将被关闭,并打开一个新文件来保存日志条目。要保留的备份数量设置为 3。
# Set a rotating logfile
logzero.logfile("my_logfile.log", maxBytes=1000000, backupCount=3)
设置最低日志记录级别。
日志级别是指设置给定日志消息的重要性级别。您还可以通过使用 logfile 方法中的 log level 参数为文件处理程序设置不同的日志级别。
在下面的例子中,我们将 loglevel 设置为warning。这意味着低于警告级别的所有日志条目将不会保存到日志文件中。
#import logzero package
from logzero import logger, logfile
import logging
# You can also set a different loglevel for the file handler
logfile("my_logfile.log", loglevel=logging.WARNING)
# Log messages
logger.info("This log message saved in the log file")
logger.warning("This log message saved in the log file")
设置自定义格式化程序。
如何格式化日志记录由您决定。有不同的方法可以格式化你的日志记录。您可以在格式中包含日期、时间和日志记录级别,这样您就可以知道日志是何时发送的以及在什么级别发送的。
以下示例显示了如何配置日志记录的格式。
#import logzero package
import logzero
from logzero import logger, logfile
import logging
#set file path
logfile("my_logfile.log")
# Set a custom formatter
my_formatter = logging.Formatter('%(filename)s - %(asctime)s - %(levelname)s: %(message)s');
logzero.formatter(my_formatter)
# Log messages
logger.info("This log message saved in the log file")
logger.warning("This log message saved in the log file")
在上面的例子中,我们配置了日志格式,包括文件名、日期、时间、日志级别名称、和消息。
这是 my_logfile.log 中的输出:
demo.py — 2020–04–10 00:51:44,706 — INFO: This log message saved in the log file
demo.py — 2020–04–10 00:51:44,707 — WARNING: This log message saved in the log file
自定义记录器实例
除了使用默认的记录器,您还可以使用 logzero.setup_logger(..)。您可以使用不同的参数配置并返回一个完全配置的 logger 实例,如名称、日志文件名称、格式化程序、最大字节数、备份计数、和日志记录级别。
这是一个如何使用自定义记录器实例设置日志记录的工作示例:
import logzero package
from logzero import logger, logfile, setup_logger
import logging
# Set a custom formatter
my_formatter = logging.Formatter('%(filename)s - %(asctime)s - %(levelname)s: %(message)s');
#create custom logger instance
custom_logger = setup_logger(
name="My Custom Logger",
logfile="my_logfile.log",
formatter=my_formatter,
maxBytes=1000000,
backupCount=3,level=logging.INFO)
# Log messages
custom_logger.info("This log message saved in the log file")
custom_logger.warning("This log message saved in the log file")
在上面的例子中,我们已经用不同的配置参数值设置了一个名为 custom_logger 的自定义记录器实例。
包裹
在本文中,您已经学习了如何使用 Logezero Python 包的基础知识和一些示例。您可以在文档中了解更多可用功能。现在您可以开始在下一个 python 项目中实现 logzero 包了。
如果你学到了新的东西或者喜欢阅读这篇文章,请分享给其他人看。在那之前,下期帖子再见!也可以通过 Twitter @Davis_McDavid 找到我
你可以阅读 freecodecamp 的原文。
最后一件事: 在以下链接中阅读更多类似这样的文章。
[## 为什么您需要探索您的数据以及如何开始
探索性数据分析逐步指南。
medium.com](https://medium.com/analytics-vidhya/why-you-need-to-explore-your-data-how-you-can-start-13de6f29c8c1) [## 使用投票方法的特征选择
如何应用多种技术来选择 Xverse 包的特性?
medium.com](https://medium.com/analytics-vidhya/feature-selection-by-using-voting-approach-e0d1c7182a21) [## 如何用 Python 日志模块运行机器学习实验
有时候“打印”并不是一个好主意
medium.com](https://medium.com/analytics-vidhya/how-to-run-machine-learning-experiments-with-python-logging-module-9030fbee120e)
如何在 AWS 上免费练习 SQL
原文:https://towardsdatascience.com/how-to-practice-sql-on-aws-for-free-dde1bc461e10?source=collection_archive---------12-----------------------
通过在真实数据库上练习来提高您的 SQL 技能

弗洛里安·克拉姆在 Unsplash 上拍摄的照片
数据科学家的必备技能之一是使用 SQL 处理数据库。你可能会说这是数据工程师的工作,但数据科学家的角色更倾向于全栈。此外,作为一名数据科学家,你不会希望依赖数据工程师从数据库中检索数据。
有很多教程解释 SQL 语法来完成某些操作。您甚至可以在示例数据库上练习和测试您的查询。然而,这并不是一种非常有效的学习方法。
在你自己的数据库上工作,用 RDBMS(例如 MySQL)运行 SQL 查询,在提高你的技能方面要有效得多。在本文中,我们将在 AWS 上创建一个 MySQL 数据库,并使用 MySQL Workbench 连接到它。
大纲如下:
- 使用 Amazon RDS 创建一个 MySQL 数据库
- 使用 MySQL Workbench 连接到数据库
- 实践部分
你首先需要在 AWS 上创建一个自由层账户。这是非常简单的创建,你不会被收取一毛钱,如果你留在免费层的限制。免费层的范围对于学习来说已经足够了。
如果您已经有一个 AWS 帐户或刚刚创建了一个免费的一级帐户,我们准备开始下面的部分。
1。使用亚马逊 RDS 创建一个 MySQL 数据库
我们将使用 Amazon RDS(关系数据库服务),可以通过在控制台上键入 RDS 来访问它。

(图片由作者提供)
向下滚动一点,点击“创建数据库”框。

(图片由作者提供)
您需要选择标准选项和 MySQL 作为引擎选项。

(图片由作者提供)
你不需要改变版本。确保选择模板下的“自由层”。

(图片由作者提供)
在模板下的 settings 部分中,键入数据库实例的名称、主用户的登录 ID,并创建密码。

(图片由作者提供)
对于数据库实例大小,空闲层只有一个选项,即 db.t2.micro。
对于存储,只需选择通用和默认的 20 GB。确保取消选中“启用存储自动缩放”选项。

(图片由作者提供)
多 AZ 部署不适用于自由层,因此我们将跳过它。
下一部分是“连接性”。选择默认的 VPC。确保为公共访问选择“是”,并创建一个新的 VPC 组。

(图片由作者提供)
创建新的 VPC 组非常重要,因为这将创建一个安全组,允许从您当前使用的设备的 IP 地址连接到所创建的数据库。
对于数据库端口,保留默认值 3306。
在 additional configuration 部分,键入一个初始数据库名称,并将其他两个选项保留为默认设置。

(图片由作者提供)
对于其余的配置部分,默认选择就可以了。确保未选择“监控”选项。

(图片由作者提供)
现在,您可以向下滚动到页面的末尾,并单击“创建数据库”框。

(图片由作者提供)
点击“创建数据库”后,您将被定向到 Amazon RDS 仪表板中的数据库。状态将被视为“正在创建”一段时间,然后变为“可用”。

(图片由作者提供)
2。使用 MySQL Workbench 连接到数据库
下一步是下载同样免费的 MySQL 工作台。

(图片由作者提供)
为您的计算机选择合适的版本,下载,然后安装。
在 MySQL Workbench 控制台上,单击顶部“数据库”部分下的“连接到数据库”。

(图片由作者提供)
将弹出以下屏幕。

(图片由作者提供)
- 主机名:数据库的端点。当您单击数据库实例时,可以看到端点。

(图片由作者提供)
- 端口:3306
- 用户名:创建数据库时输入的用户名(我输入的是 MasterUser1)
- 密码:点击“存储在保险库中”并输入您创建的密码
然后,点击“确定”。
恭喜你!现在,您已经连接到 AWS 上的数据库。MySQL Workbench 将打开一个 SQL 编辑器,这样您就可以开始练习和运行查询了。
在运行查询之前,还有最后一件事要做。单击“schemas ”,然后双击要使用的数据库。现在只有一个。

(图片由作者提供)
3。练习部分
我们现在准备走了。让我们运行几个简单的 SQL 查询。
创建表格
在编辑器中键入以下 SQL 代码,然后单击 run。

(图片由作者提供)
现在,您的数据库中有了一个表。该表的名称是“sample ”,它有 4 列。
要获得该表的概述,在编辑器中键入“DESC 示例”,并运行它。

(图片由作者提供)
插入一行
“样本”表现在是空的。我们可以使用 insert 函数添加条目。

(图片由作者提供)
我已经使用上面的插入查询添加了两个条目。
从表中选择
我们现在可以看到表中的条目。下面的 select 查询将查询表中的所有行。

(图片由作者提供)
结论
我们使用 Amazon RDS 服务在 AWS 上创建了一个 MySQL 数据库,并使用 MySQL Workbench 连接到它。
我们现在可以通过在真实数据库上练习来提高我们的 SQL 技能。它模拟了现实生活中的工作场景,我认为这会激励你,让你更容易学习 SQL。
感谢您的阅读。如果您有任何反馈,请告诉我。
如何在 Python 中预测可变正弦曲线
原文:https://towardsdatascience.com/how-to-predict-a-variable-sinusoid-in-python-4a21404dc061?source=collection_archive---------19-----------------------
数据分析
基于数学的预测 Python 中可变正弦曲线的方法。

本教程描述了如何用 Python 预测一个可变正弦曲线。首先,从 CSV 文件加载一些正弦数据。然后,通过正弦曲线对数据进行整形。之后,使用线性回归对最小和最大峰值进行建模。最后,建模的线用于计算下一个峰值。
完整的代码可以从我的 Github 库下载。
分析的数据:旅游住宿机构的到达人数摘自https://ec.europa.eu/eurostat/web/tourism/data/database
数据导入和清理
从 CSV 加载数据并清除它们
首先,我们读取 CSV 文件,我们只选择与意大利(df[df['geo'] == 'IT'])相关的数据,以数字(df[df['unit'] == 'NR'])的形式,并参考所有可用数据的总和(内部和外部到达)(df[df['c_resid'] == 'TOTAL'])。
然后我们通过函数drop()删除无用的列。注意,我们通过参数inplace=True将效果存储在原始变量df中。
import pandas as pd
df = pd.read_csv(‘data/eurostat.csv’)
df = df[df[‘geo’] == ‘IT’]
df = df[df[‘unit’] == ‘NR’]
df = df[df[‘c_resid’] == ‘TOTAL’]
df.drop([‘c_resid’, ‘unit’, ‘nace_r2’, ‘2019M11’, ‘geo’],axis=1, inplace=True)
df = df.reset_index()
df.drop([‘index’],axis=1, inplace=True)
现在我们可以纠正数据中的一些错误:一些行包含字符:,这意味着没有可用的数据。其他行包含字母b。我们改变了0中的:,并删除了字母b。
columns = df.columns[::-1]
for column in columns:
for row in range(1, len(df[column])):
if “b” in df[column][row]:
df[column] = df[column][row][:-2]
if “:” in df[column][row]:
df[column][row] = “0”
现在我们计算各列的总和,以获得每个月的总到达人数。我们将结果存储在变量y中。
y = []
for column in columns:
df[column] = df[column].astype(str).astype(int)
y.append(df[column].sum())
初步分析
绘制数据以了解数据趋势
我们绘制y来理解趋势线。我们构建辅助向量X,它包含所有的月份。0 月指的是 1990 年 1 月。为了每 5 年在图中显示 x 标签,我们构建了两个辅助变量,x_ticks和x_labels。
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
X = np.arange(0, len(columns))step = 5
x_ticks = np.arange(0, len(columns)+step, step=12*step)
x_labels = []
x_labels.append(1990)
for i in range(1, len(x_tick)+1):
x_labels.append(x_labels[i-1]+step)
plt.xticks(x_ticks, x_labels)
plt.plot(X, y, color=”red”, linewidth=1)plt.grid()
plt.xlabel(‘Months’)
plt.ylabel(‘Number of arrivals’)plt.show()

我们注意到,与前几年相比,在过去的 8 年中,最大峰值有所增加。因此,我们限制了过去 8 年的分析。这意味着我们应该跳过最初的 22 年。我们将X和y重置为仅适用于最近几年。
skip = 22*12
X = X[skip:]
y = y[skip:]
数据近似值
用正弦曲线逼近数据
现在我们可以用正弦曲线来近似数据。正弦曲线的方程式为A*np.sin(omega*x+phase) + offset,其中:
- |
A|表示振幅,即函数最大值和最小值之间距离的一半 omega是 0 到 2pi 之间的循环数。周期 T 是 2pi/ωphase是水平移动offset是垂直位移,即最小峰值和振幅之和。下面是一些关于偏移的细节:https://www . ck12 . org/book/CK-12-precalculus-concepts/section/5.4/
关于正弦曲线的更多细节,可以给看看:https://mathbitsnotebook . com/代数 2/trig graphs/TG sinusoid . html。
def sinusoid(x,A,offset,omega,phase):
return A*np.sin(omega*x+phase) + offset
我们还定义了正弦曲线的初始值。我们设置周期T = 12,即一年中的月数。如果不知道周期,我们应该计算它。我们可以使用快速傅立叶变换。在这些链接中,你可以找到更多关于这方面的细节:https://stack overflow . com/questions/16716302/how-do-I-fit-a-sine-curve-to-my-data-with-pylab-and-numpy、https://www . oreilly . com/library/view/elegant-scipy/9781491922927/ch04 . html
T = 12
def get_p0(x, y):
A0 = (max(y[0:T]) — min(y[0:T]))/2
offset0 = y[0]
phase0 = 0
omega0 = 2.*np.pi/T
return [A0, offset0,omega0, phase0]
现在我们准备用正弦曲线来近似我们的数据。我们使用scipy提供的curve_fit()函数。我们绘制结果。关于curve_fit()功能的更多细节,请看https://docs . scipy . org/doc/scipy/reference/generated/scipy . optimize . curve _ fit . html。
from scipy.optimize import curve_fit
import math
param, covariance = curve_fit(sinusoid, X, y, p0=get_p0(X,y))step = 1
x_ticks = np.arange(skip, skip+len(X)+step+12, step=12*step)
x_labels = []
x_labels.append(2012)
for i in range(1, len(x_tick)+13):
x_labels.append(x_labels[i-1]+step)
plt.xticks(x_ticks, x_labels)
plt.ylabel(‘Number of arrivals’)
plt.plot(X, y, color=”red”, linewidth=1,linestyle=’dashed’)
plt.plot(X, sinusoid(X, *param), color=”blue”, linewidth=1)
plt.show()

我们用恒定值为A的正弦曲线来近似我们的数据。在我们的例子中,振幅A和offset都是可变的。这个想法是计算我们数据中所有的最大峰值和最小峰值。然后我们可以使用它们的差来计算振幅的向量,并将它们传递给sinusoid()函数。
我们定义了函数get_peaks(),它计算一个数组的峰值。我们每隔T个元素对数组进行采样,并计算每个T内的峰值。
def get_peaks(y, metrics):
n = int(math.ceil(len(y)/T))
step = 0
x_peaks = []
y_peaks = []
for i in range(0,n):
peak_index = y.index(metrics(y[step:step+T]))
x_peaks.append(peak_index + skip)
y_peaks.append(y[peak_index])
step = step+T
return [x_peaks,y_peaks]
我们计算最大和最小峰值。
min_peaks = get_peaks(y,min)
max_peaks = get_peaks(y,max)
现在我们可以计算振幅和偏移的数组。
A = []
offset = []
for i in range(0, len(min_peaks[1])):
c_a = (max_peaks[1][i] — min_peaks[1][i])/2
c_offset = min_peaks[1][i] + c_a
for j in range(0,T):
A.append(c_a)
offset.append(c_offset)
# last two months of 2019 are not available
A = A[:-2]
offset = offset[:-2]
由于A和offset是新特性,我们应该把它们作为变量添加进去。因此,我们定义了一个新变量features,它定义了我们模型的新输入特性。然后我们定义函数variable_sinusoid(),它将特性作为输入。
我们的模型返回的唯一参数是omega和phase,因此我们也用初始值omega和phase修改函数get_p0()。新功能称为variable_get_p0()。
features = [X, A, offset]
def variable_sinusoid(features,omega,phase):
x = features[0]
A = features[1]
offset = features[2]
return A*np.sin(omega*x+phase) + offsetdef variable_get_p0(x, y):
phase0 = 0
omega0 = 2.*np.pi/T
return [omega0, phase0]
我们拟合模型并绘制结果。
param, covariance = curve_fit(variable_sinusoid, features, y, p0=variable_get_p0(X,y))
plt.xticks(x_ticks, x_labels)
plt.ylabel(‘Number of arrivals’)
plt.plot(X, y, color=”red”, linewidth=1,linestyle=’dashed’)
plt.plot(X, variable_sinusoid(features, *param), color=”blue”, linewidth=1)
plt.show()

预测未来趋势线
预测可变正弦曲线的未来值
下一步包括预测下一个正弦曲线,即 2020 年的正弦曲线。为此,我们需要计算下一个最大和最小峰值。我们可以通过用两个线性回归分别逼近最大和最小峰值的向量来做到这一点。然后,我们可以计算出瞬时 2020 年 8 月)的最大峰值,作为瞬时(i-1) + pi (i-1 代表 2019 年 8 月)给出的最大线性回归的 y 值。同样,我们可以计算出 2020 年的最小峰值。
首先,我们对要传递给线性模型的峰值进行整形。然后,我们使用sklearn类LinearRegression()建立两个线性模型,每条预测线一个。之后,我们使用fit()函数拟合每个模型。
from sklearn import linear_model
# reshape x_peaks
x_min_peaks = list(map(lambda el:[el], min_peaks[0]))
x_max_peaks = list(map(lambda el:[el], max_peaks[0]))# min model
model_min = linear_model.LinearRegression()
model_min.fit(x_min_peaks,min_peaks[1])
# max model
model_max = linear_model.LinearRegression()
model_max.fit(x_max_peaks,max_peaks[1])
我们将下一个峰值添加到x_max_peaks和x_min_peaks,然后通过predict()函数预测最大和最小峰值。
x_min_peaks.append([x_min_peaks[len(x_min_peaks) -1][0] + T])
x_max_peaks.append([x_max_peaks[len(x_max_peaks) -1][0] + T])
y_pred_min = model_min.predict(x_min_peaks)
y_pred_max = model_max.predict(x_max_peaks)
我们绘制了两条预测线。
plt.xticks(x_ticks, x_labels)
plt.plot(X, y, color=”red”, linewidth=1,linestyle=’dashed’)
plt.scatter(x_min_peaks, y_pred_min, color=”green”, linewidth=1,linestyle=’dashed’)
plt.scatter(x_max_peaks, y_pred_max, color=”green”, linewidth=1,linestyle=’dashed’)
plt.ylabel(‘Number of arrivals’)
plt.grid()
plt.show()

我们计算所有周期的正弦曲线,包括 2020 年。我们构建一个变量X_pred,它包含X和 2020 年的 12 个月。
X_pred = np.array(X)
month = X_pred[len(X_pred)-1]
for i in range(0,T):
X_pred = np.append(X_pred,month)
month = month + 1
现在,我们可以更新要传递给variable_sinusoid()函数的变量features_pred。首先,我们用新值更新振幅A和offset,然后我们更新features_pred变量。
index = len(max_peaks[0])-1
c_a = (max_peaks[1][index] — min_peaks[1][index])/2
c_offset = min_peaks[1][index] + c_a
for j in range(0,T):
A.append(c_a)
offset.append(c_offset)
features_pred = [X_pred,A,offset]
最后,我们绘制图表。
plt.xticks(x_ticks, x_labels)
plt.plot(X, y, color=”red”, linewidth=1,linestyle=’dashed’)
plt.plot(X_pred, variable_sinusoid(features_pred, *param), color=”blue”, linewidth=1)
plt.grid()
plt.ylabel(‘Number of arrivals’)
plt.savefig(“data/sinusoid.png”)
plt.show()

吸取的教训
在本教程中,我介绍了一种通过可变正弦曲线来逼近正弦趋势数据的方法。然后我描述了预测下一个数据值的机制。
所描述的方法可以推广到所有类型的曲线:
- 加载和清理数据
- 绘制数据以了解趋势线
- 通过
curve_fit()功能用曲线逼近趋势线 - 绘制近似结果,并与原始数据趋势线进行比较
- 如果需要,改进近似趋势线
- 重复前两步,直到你得到一个好的近似值
- 计算(线性、多项式、…)回归以预测未来值
- 使用预测值更新近似趋势线。
如果你读到这里,对我来说,今天已经很多了。谢谢!你可以在这个链接阅读我的趋势文章。
相关文章
[## Python PyCaret 中的完整数据分析工作流
这是一个现成的教程,利用了我用过的最好的机器学习库。
towardsdatascience.com](/a-complete-data-analysis-workflow-in-python-pycaret-9a13c0fa51d4) [## Python 和 scikit 中的完整数据分析工作流程-学习
towardsdatascience.com](/a-complete-data-analysis-workflow-in-python-and-scikit-learn-9a77f7c283d3) [## Python 中探索性数据分析的可视化技术概述
关于如何在 seaborn 和 matplotlib 中为 Visual EDA 绘制最常见图形的教程
towardsdatascience.com](/an-overview-of-visual-techniques-for-exploratory-data-analysis-in-python-d35703d43faf)
在等待机器学习算法的输出时,你在做什么?
数据科学家的工作非常具有挑战性:你的知识必须涵盖从数据挖掘到数据分析,直到数据可视化。你从不停止。
然而,当你启动一个繁重的计算时,比如一个大数据集上的机器学习算法,会发生什么呢?你停下来等待结果。你可能会盯着屏幕看几个小时,希望你的剧本能完成。
不管怎么说,这不是消磨时间的最佳方式。你应该做些别的事情。你不能坐下来等待结果。
在这里继续阅读。
保持联系!
- 在媒体上跟随我
- 注册我的简讯
- 在 LinkedIn 上连接
- 在推特上关注我
- 跟着我上脸书
- 在 Github 上关注我
如何用带有 Keras 的 CNN 预测一个图像?
原文:https://towardsdatascience.com/how-to-predict-an-image-with-keras-ca97d9cd4817?source=collection_archive---------0-----------------------
图片里有什么?

由卡斯滕·怀恩格特在 Unsplash 上拍摄的照片
如何预测图像的类型?
确定图像包含什么对象有以下六个步骤?
- 加载图像。
- 将其调整为预定义的大小,如 224 x 224 像素。
- 将像素值缩放到范围[0,255]。
- 选择预先训练的模型。
- 运行预先训练的模型。
- 显示结果。

如何预测图像的类型
使用 Keras 实施解决方案
要求
安装 TensorFlow 和 Keras。
pip install tensorflow
设置您的环境
首先,我们设置环境。
# TensorFlow and tf.kerasimport tensorflow as tf
from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image# Helper libraries
import numpy as np
import matplotlib.pyplot as plprint(tf.__version__)
加载图像
然后,我们加载并尝试显示我们想要预测的图像。
img_path = "./samples/dog_1100x628.jpg"plt.imshow(img)
plt.show()
它展示了一只维兹拉狗,那么我们的模型如何预测这个图像呢?

调整图像大小
请记住,在将任何图像输入 Keras 之前,我们需要将其转换为标准格式,因为预先训练的模型希望输入具有特定的大小。在这种情况下,我们需要将图像的大小调整为 224 x 224 像素。
img = image.load_img(img_path, target_size=(224, 224))
第二是大多数深度学习模型期望一批图像作为输入。在这种情况下,我们创建一批一个图像。
img_array = image.img_to_array(img)
img_batch = np.expand_dims(img_array, axis=0)
将像素值缩放到一致的范围
第三,当数据在一个一致的范围内时,模型表现良好。在这种情况下,图像像素值的范围是从 0 到 255。因此,如果我们在输入图像上运行 Keras 的preprocess_input()函数,就会将每个像素标准化到一个标准范围。
img_preprocessed = preprocess_input(img_batch)
选择预先训练的模型
这里,我们将使用一个名为 ResNet-50 的 CNN 网络。
model = tf.keras.applications.resnet50.ResNet50()
运行预先训练的模型
prediction = model.predict(img_preprocessed)
显示结果
Keras 还提供了decode_predictions函数,它告诉我们图像中包含的每一类对象的概率。
print(decode_predictions(prediction, top=3)[0])
下面是运行这个程序时的输出。
[(‘n02099601’, ‘golden_retriever’, 0.75317645),
(‘n02100583’, ‘vizsla’, 0.061531797),
(‘n02099267’, ‘flat-coated_retriever’, 0.04048888)]
该图像的预测类别是各种类型的狗。

三种狗
完整的源代码完成。
很简单,对吧?
参考
https://github . com/house cricket/how _ to _ predict _ an _ image _ with _ keras
如何预测 Sparkify 中的搅拌
原文:https://towardsdatascience.com/how-to-predict-churns-in-sparkify-ab9a5c3f218d?source=collection_archive---------63-----------------------
使用 Spark 预测哪些用户有可能因取消服务而流失

由马尔特·温根在 Unsplash 上拍摄的照片
简介
parkify 是一种流行的数字音乐服务,类似于由 Udacity 创建的 Spotify 或 Pandora。该项目的目标是预测哪些用户有被取消服务的风险。如果我们能在这些用户离开之前识别出他们,我们就能为他们提供折扣或激励。
用户可以做的不同页面动作是,例如,播放一首歌、喜欢一首歌、不喜欢一首歌、登录、注销、添加朋友或者在最坏的情况下取消服务。我们所知道的关于用户的信息是 id、名字和姓氏、性别、他们是否登录、他们是否是付费用户、他们的位置、他们注册的时间戳以及用户使用的浏览器。我们对他们正在听的歌曲的了解是艺术家的名字和歌曲的长度。

作者在 Sparkify data 上的图片
第一部分:用户故事示例
让我们以单个用户为例来更好地理解用户可以做的交互。让我们研究一下来自北卡罗来纳州罗利的用户 id 2 Natalee Charles 的三个操作。
Row(artist=None, auth='Logged In', firstName='Natalee', gender='F', **itemInSession=1**, lastName='Charles', length=None, level='paid', location='Raleigh, NC', method='GET', **page='Home'**, sessionId=1928, song=None, status=200, userAgent='"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"', userId='2', timestamp='2018-11-21 18:04:37', registration_timestamp='2018-09-13 02:49:30'),Row(**artist='Octopus Project'**, auth='Logged In', firstName='Natalee', gender='F', **itemInSession=2**, lastName='Charles', **length=184.42404**, level='paid', location='Raleigh, NC', method='PUT', **page='NextSong'**, sessionId=1928, **song='What They Found'**, status=200, userAgent='"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"', userId='2', timestamp='2018-11-21 18:04:45', registration_timestamp='2018-09-13 02:49:30'),Row(**artist='Carla Bruni'**, auth='Logged In', firstName='Natalee', gender='F', **itemInSession=3**, lastName='Charles', length=123.48036, level='paid', location='Raleigh, NC', method='PUT', page='NextSong', sessionId=1928, song="l'antilope", status=200, userAgent='"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"', userId='2', timestamp='2018-11-21 18:07:49', registration_timestamp='2018-09-13 02:49:30'),...Row(artist=None, auth='Logged In', firstName='Natalee', gender='F', itemInSession=106, lastName='Charles', length=None, level='paid', location='Raleigh, NC', method='PUT', **page='Add Friend'**, sessionId=1928, song=None, status=307, userAgent='"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"', userId='2', timestamp='2018-11-21 23:30:04', registration_timestamp='2018-09-13 02:49:30')
第一个动作是会话中的第一个动作:访问主页。第二个动作是听一首歌,这允许我们收集关于歌曲本身的信息:艺术家、歌曲和长度。第三个动作是听一首不同的歌(卡拉·布鲁尼:l'antilope)。整个会话的最后一个操作是添加一个朋友。
第二部分:识别特征
用于搅动的用户的定义是提交取消确认的用户。我们需要找到代表两种用户类型之间巨大差异的特征:一个用户频繁使用,一个用户不频繁使用。困难在于,数据中包含的搅动数(233290)比非搅动数(44864)多得多,这意味着,尽管数据不平衡,我们也必须找到具有可比性的特征。

作者图片
第一个想法是按会话比较项目,因为会话的持续时间不受用户数量的影响,只受会话中项目数量的影响。音乐服务平台最重要的项目是歌曲的播放。这导致决定比较两种用户类型之间的下一首歌曲的数量。恶心的人最多听 708 首歌,而不恶心的人最多听 992 首。流失用户平均听了 70 首歌,非流失用户平均听了 105 首。这是一个很好的特性,因为我们已经看到了这两种用户类型的很多差异。

作者图片
第二个想法是检查两种用户类型之间的比例差异。数据中已经有用户类型定义,级别(免费/付费用户)。我们想研究搅动和非搅动的比例分布是否不同。我们可以看到,非用户的付费用户比例高于用户,而用户的免费用户比例也高于用户。这也是一个很棒的特性,因为在这种情况下,免费用户比付费用户更容易流失。
第三部分:建模
我们使用逻辑回归来寻找预测搅拌的最佳模型。因为我们有一个二元决策,所以我们使用 BinaryClassificationEvaluator 来评估结果。由于被搅动的用户是一个相当小的子集,我们使用 f1 分数(结合准确度)作为优化的指标。我们使用三种不同的输入类型来测试,例如,在训练之前对数据进行加权是否会提高 f1 分数。另一个测试是删除重复项。

基于三种不同输入数据类型的作者图像
在第一轮中,通过所有数据和加权数据获得最佳精度和 f 值。他们都取得了同样的结果。但是唯一的数据集实现了标签 1 的最佳 f 值。
**All data**
Accuracy: 0.9023548583351629
F-measure: 0.8560382799176114
F-measure by label:
label 0: 0.9486714367527147
label 1: 0.0**Weighted data**
Accuracy: 0.9023548583351629
F-measure: 0.8560382799176114
F-measure by label:
label 0: 0.9486714367527147
label 1: 0.0**Unique data**
Accuracy: 0.6666666666666666
F-measure: 0.5859374999999999
F-measure by label:
label 0: 0.7906666666666665
label 1: 0.18229166666666666
在第二轮中,我们使用基于阈值的 f 得分的最大值的最佳阈值。总准确度和 f 值下降,但标签 1 的 f 值上升。最好的 f 1 测量(标签 1)是由唯一的数据集实现的,而最好的总精度和 f 测量是由另外两个数据集实现的。
**All data**
Accuracy: 0.7611244603498374
F-measure: 0.7955698747928712
F-measure by label:
label 0: 0.8594335689341074
label 1: 0.20539494445808643**Weighted data**
Accuracy: 0.7611244603498374
F-measure: 0.7955698747928712
F-measure by label:
label 0: 0.8594335689341074
label 1: 0.20539494445808643**Unique data** Accuracy: 0.5859872611464968
F-measure: 0.5914187270302529
label 0: 0.6044624746450304
label 1: 0.5657015590200445
最后一轮(参数调整)使用不同的参数来优化平均指标。在参数调整后,独特数据集预测 317 个预期标签 1 值中的 597 个,在测试数据上的准确度为 0.5754,而所有数据集预测 73990 个预期标签 1 值中的 134437 个,在测试数据上的准确度为 0.7786。
**All data** Average Metric Max: 0.5703188574707733
Average Metric Min: 0.5
Accuracy on test data: 0.7786
Total count of Label 1 prediction: 134437
Total count of Label 1 expectations: 73990**Unique data** Average Metric Max: 0.6750815894510674
Average Metric Min: 0.5
Accuracy on test data: 0.5754
Total count of Label 1 prediction: 597
Total count of Label 1 expectations: 317
结论

作者根据 1.0 =搅动的最佳预测制作的图片
最好的模型是使用我们选择的特征的所有数据的模型。总精度和 f 值低于其他测试模型,但它提供了标签 1 值的最佳预测,这是该模型的主要用例。
通过使用其他算法,例如随机森林分类器或梯度增强树分类器,可以进行进一步的改进。另一个改进的来源可能是更多的特征,这些特征改进了最终模型的预测。
要了解这个项目的更多信息,请点击这里查看我的 Github 的链接。
如何在 Spark 上使用机器学习模型预测客户流失?
原文:https://towardsdatascience.com/how-to-predict-customer-churn-using-machine-learning-model-on-spark-99f5277993b7?source=collection_archive---------34-----------------------
使用 Spark 探索您的大数据,这是一种初学者方法。

Oleg Gratilo 在 Unsplash 上拍摄的照片
如果你以前处理过机器学习模型,你就会知道处理庞大数据集时的感受。在某些时候,我们都意识到了这一障碍,并选择使用较小部分的数据,从数据分析和训练模型开始。
介绍
大数据非常模糊,但我们都同意,每当我们感觉到笔记本电脑或机器的计算能力受到限制时,由于数据集的巨大规模,我们会将其视为大数据问题。而且,让我们面对现实吧,像 pandas 这样的 python 数据分析库,由于其本地内存限制和性能问题,在处理大型数据集时有其自身的局限性。
商业理解
Sparkify 是一个虚构的音乐流媒体服务,就像 Spotify 或 Pandora 一样,我将使用 Sparkify 流失预测作为问题陈述来详细解释这篇文章。我将在这个项目中使用 PySpark。
注 : Sparkify 数据集由 Udacity 数据科学家纳米学位项目提供,本文是我的顶点项目的一部分。
数据理解
我在本地机器上用 Udacity 提供的小型 Sparkify 数据集开始进行探索性数据分析。
*# loading dataset*
df = spark.read.json("mini_sparkify_event_data.json")*# columns in dataset*
df.printSchema()root
|-- artist: string (nullable = true)
|-- auth: string (nullable = true)
|-- firstName: string (nullable = true)
|-- gender: string (nullable = true)
|-- itemInSession: long (nullable = true)
|-- lastName: string (nullable = true)
|-- length: double (nullable = true)
|-- level: string (nullable = true)
|-- location: string (nullable = true)
|-- method: string (nullable = true)
|-- page: string (nullable = true)
|-- registration: long (nullable = true)
|-- sessionId: long (nullable = true)
|-- song: string (nullable = true)
|-- status: long (nullable = true)
|-- ts: long (nullable = true)
|-- userAgent: string (nullable = true)
|-- userId: string (nullable = true)*# Number of Rows*
df.count()286500# *showing types of events in dataset or pages a user might visit while using the Sparkify app.*df.select("page").dropDuplicates().show()+--------------------+
| page|
+--------------------+
| Cancel|
| Submit Downgrade|
| Thumbs Down|
| Home|
| Downgrade|
| Roll Advert|
| Logout|
| Save Settings|
|Cancellation Conf...|
| About|
| Settings|
| Add to Playlist|
| Add Friend|
| NextSong|
| Thumbs Up|
| Help|
| Upgrade|
| Error|
| Submit Upgrade|
+--------------------+
数据准备
在数据准备期间,我处理了一些数据挑战,比如缺失值、数据清理、输入分类变量以及确定一个目标变量来预测流失的客户。
为了准确预测流失的客户,我们需要他们的 userId 信息,因此通过删除 userId 为 null 或空的所有行来清理数据。
添加一个目标变量为。如果用户访问了“ 取消确认 ”页面,则列的值为 1,否则为 0。**
数据可视化
让我们通过可视化方式更深入地了解 Sparkify 客户。
****
按流失类型划分的总客户分布

基于服务水平的总客户分布
Sparkify 有两种服务,一种是免费的广告服务,另一种是付费服务。我们的目标是在付费客户停止使用该应用程序之前识别他们。
下面的事件代表了一组非常重要的特征来预测被搅动的顾客。

总事件分布
特征工程
是时候选择重要的特征来训练我们的机器学习模型了。
****['gender', 'level', 'page', 'userId', 'Churn']****
页面的 列将进一步划分为它的事件。
**df.groupBy(["userId", "Churn", "gender", "level"]).count().show()+------+-----+------+-----+-----+
|userId|Churn|gender|level|count|
+------+-----+------+-----+-----+
|200008| 0| 1| 1| 1988|
| 93| 0| 0| 0| 566|
|100013| 1| 1| 0| 303|
| 91| 0| 0| 1| 2862|
| 4| 0| 0| 0| 141|
|300021| 0| 1| 1| 4650|
|100019| 1| 0| 0| 89|
|100021| 1| 0| 0| 319|
| 140| 0| 1| 1| 5662|
| 73| 1| 1| 0| 16|
| 59| 0| 0| 1| 693|
|200025| 0| 0| 0| 597|
| 41| 0| 1| 1| 2220|
| 37| 0| 0| 0| 79|
| 54| 1| 1| 1| 2859|
| 69| 0| 1| 0| 39|
|200024| 1| 0| 0| 342|
|300005| 0| 1| 0| 64|
| 27| 0| 0| 0| 291|
| 101| 1| 0| 0| 76|
+------+-----+------+-----+-----+
only showing top 20 rowsEvent_list = [(row['page']) for row in df.select('page').dropDuplicates().collect()]
for event in Event_list:
df_temp = df.filter(df.page==event).groupBy(df.userId).count()
df_temp = df_temp.withColumnRenamed('count', event)
df_sparkify = df_sparkify.join(df_temp, 'userId', how='left')**
将 页面 事件分发到自己的类别中作为一列后,dataframe 看起来是这样的。
**df_sparkify.printSchema()root
|-- userId: integer (nullable = true)
|-- Churn: integer (nullable = true)
|-- gender: integer (nullable = true)
|-- level: integer (nullable = true)
|-- count: long (nullable = false)
|-- Cancel: long (nullable = true)
|-- Submit Downgrade: long (nullable = true)
|-- Thumbs Down: long (nullable = true)
|-- Home: long (nullable = true)
|-- Downgrade: long (nullable = true)
|-- Roll Advert: long (nullable = true)
|-- Logout: long (nullable = true)
|-- Save Settings: long (nullable = true)
|-- Cancellation Confirmation: long (nullable = true)
|-- About: long (nullable = true)
|-- Settings: long (nullable = true)
|-- Add to Playlist: long (nullable = true)
|-- Add Friend: long (nullable = true)
|-- NextSong: long (nullable = true)
|-- Thumbs Up: long (nullable = true)
|-- Help: long (nullable = true)
|-- Upgrade: long (nullable = true)
|-- Error: long (nullable = true)
|-- Submit Upgrade: long (nullable = true)**

相关性—热图
注意 : Dataframe 可能看起来与全数据集不同,在 AWS Spark 上运行。
将所有列字符串值更改为数字形式后,dataframe 就可以进行建模了。
注:为了防止 数据在建模过程中泄露 ,删除了“取消”和“取消确认”栏。
建模
AWS Spark MLlib 库支持很多有监督和无监督的机器学习算法。我使用了决策树分类器、随机森林分类器和梯度推进分类器来训练三个模型,并在选择获胜模型之前比较结果。
列车测试分割
**# spliting in 70% training and 30% testing settrain_data,test_data = final_data.randomSplit([0.7,0.3])**
分类器
**# Using three classifiers before finalizing best performerdtc=DecisionTreeClassifier(labelCol='Churn',featuresCol='features')
rfc=RandomForestClassifier(labelCol='Churn',featuresCol='features', numTrees=300)
gbt=GBTClassifier(labelCol='Churn',featuresCol='features')# fit the models
dtc_model = dtc.fit(train_data)
rfc_model = rfc.fit(train_data)
gbt_model = gbt.fit(train_data)# transform the models
dtc_predictions = dtc_model.transform(test_data)
rfc_predictions = rfc_model.transform(test_data)
gbt_predictions = gbt_model.transform(test_data)**
评估指标
在 pySpark 中,我们可以不打印混淆矩阵,而是要用multiclassacrificationevaluator来评估 准确度 和 f1_score 。我们也可以使用 BinaryClassificationEvaluator 来计算ROC 曲线下的面积和 Precision-Recall 下的面积。
**# calculating accuracy
acc_evaluator = MulticlassClassificationEvaluator(labelCol="Churn",predictionCol="prediction",metricName="accuracy")# calculating f1 score
f1_evaluator = MulticlassClassificationEvaluator(labelCol="Churn",predictionCol="prediction", metricName="f1")areaUnderROC = BinaryClassificationEvaluator(labelCol='Churn',metricName='areaUnderROC')areaUnderPR = BinaryClassificationEvaluator(labelCol='Churn',metricName='areaUnderPR')dtc_acc = acc_evaluator.evaluate(dtc_predictions)
rfc_acc = acc_evaluator.evaluate(rfc_predictions)
gbt_acc = acc_evaluator.evaluate(gbt_predictions)dtc_f1 = f1_evaluator.evaluate(dtc_predictions)
rfc_f1 = f1_evaluator.evaluate(rfc_predictions)
gbt_f1 = f1_evaluator.evaluate(gbt_predictions)dtc_auc = areaUnderROC.evaluate(dtc_predictions)
rfc_auc = areaUnderROC.evaluate(rfc_predictions)
gbt_auc = areaUnderROC.evaluate(gbt_predictions)dtc_aupr = areaUnderPR.evaluate(dtc_predictions)
rfc_aupr = areaUnderPR.evaluate(rfc_predictions)
gbt_aupr = areaUnderPR.evaluate(gbt_predictions)**

比较所有模型的评估
结果
预测和防止客户流失对每个公司来说都意味着巨大的额外潜在利益来源。我们的目标从一开始就是识别那些 Sparkify 客户。
在不同评价指标上比较所有模型后,梯度提升表现优于其他两个。您可以看到梯度增强算法的 f1 值为 0.90,而随机森林的 f1 值为 0.79。
我相信一个模型有更高的回忆分数用于积极的客户流失分类。用 Lehman 的话来说,选择一个能够预测较少假阴性(类别为 1 但预测为 0 的情况)而不是假阳性(类别为 0 但预测为 1 的情况)的模型,以成功识别流失客户。****
我将选择梯度推进分类器作为我现在的最终模型。
部署
作为我未来的工作,我将在 AWS Spark Cluster 上运行这段代码。但是,我现在不会在任何地方部署这个模型。
未来作品
- 在未来,我可以尝试将整个数据集分离成每月或每周的数据,并预测下个月或下个星期的客户。
- 我可以通过结合两种或更多种算法来使用更先进的机器学习技术,以提高整体预测率。
- 我可以在 AWS 集群上运行这个来查看模型性能,并使用交叉验证来获得更好的 f1 分数。
附注:在我的数据科学项目中,我总是试图遵循 CRISP-DM 方法。
本文是 Udacity 数据科学家纳米学位项目的一部分。要查看更多关于此分析的内容,请在此处 查看我的 Github 可用链接 。
用随机森林模型估计国际足联球员的价值
原文:https://towardsdatascience.com/how-to-predict-fifa-players-value-with-random-forest-model-8869daa4263c?source=collection_archive---------56-----------------------

米奇·罗森在 Unsplash 上的照片
背景:
每年,EA Sports 都会根据每位国际足联球员目前的状态发布其评级。为了确保数据库中的每个球员都得到适当的评级,EA Sports 会在在线赛季的实时数据库中更新整个赛季的球员评级。
对于数据科学家和足球迷(恰好是我自己)来说,这是一个很好的数据资源。每个国际足联的球员都被赋予了一个分数,包括运球、速度、加速度等等。更重要的是,它为每个球员提供了市场价值和工资。因此,我有兴趣看看我是否可以应用机器学习技术来发现模式,识别和排列特征的重要性,并预测未来新玩家的价值。
虽然球员的价值和工资可能是真实的,但每个属性的评级都是主观的,来自 EA Sports,该公司推广自己的视频游戏 FIFA 2020。尽管有这样的免责声明,但这仍然是一个值得探索的有趣实践。完整的代码可以在这里找到。
数据收集:
所有数据来自 fifaindex.com。使用 BeautifulSoup,我通过迭代获得每个玩家的 ID,然后循环进入每个玩家的页面,收集这些属性的评级。数据被用作下一步的输出。
数据探索:
与任何数据科学项目一样,我必须清理数据,例如删除“”并将字符串转换为数值。由于大多数属性是针对场上球员的,所以我缩小了范围,排除了那些守门员。同时,我创建了几个我认为更相关的新的派生属性。例如,身体质量指数可能是一个比体重或身高更好的指标。
在所有数据清理之后,数据集中有 17,286 名球员。每个玩家都有自己的价值和 39 个属性。目标是创建一个模型来预测基于这些属性的价值。
接下来,我探索了球员的价值与一些属性如速度、敏捷等之间的关系。他们中的许多人都表现出了很强的人际关系。我还检查了那些分类特征,比如“首选位置”,看看它是否对价值有影响(确实有)。
plt.bar(df['Acceleration '], df['Value '])
plt.show()

加速度与数值
plt.bar(df['Preferred Positions '], df['Value '])
plt.show()

位置与价值
对于这些属性,直方图是检查数据是否遵循正态分布的好方法。还检查了相关性。通过颜色编码,可以非常直观地显示哪些属性是正相关/负相关的。
df['Dribbling '].plot(kind='hist', bins=20)
plt.show()

运球直方图
corr = df.corr(method ='pearson')
corr.style.background_gradient(cmap='coolwarm').set_properties(**{'font-size': '0pt'})

特征相关性(仅部分显示)
建立模型:
为了便于说明,我删除了“工资”和“交易”,它们可以用于单独的练习。作为例行工作的一部分,数据被分成训练和测试两部分。
X, y = df.drop(['Value ','Wage ','Deal'], axis=1), df['Value ']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
因为我们的属性包括数值和分类数据,所以引入了两种类型的数据转换(MinMaxScaler 和 OneHotEncoder)。MinMaxScaler 本质上是将不同尺度的数值数据转换成从 0 到 1 的特征范围。OneHotEncoder 用于将分类数据转换为虚拟变量数组。使用 ColumnTransformer,我在一个步骤中转换了所有输入数据,以便进行后续的模型构建。
numerical_ix = X_train.select_dtypes(include=['int64', 'float64']).columns
categorical_ix = X_train.select_dtypes(include=['object', 'bool']).columns
t = [('cat', ce.OneHotEncoder(use_cat_names=True), categorical_ix), ('num', MinMaxScaler(), numerical_ix)]
col_transform = ColumnTransformer(transformers=t)
为了得到更准确的模型,我应用 KFold 作为交叉估值,将训练数据随机拆分 X 次,分别运行。
cv = KFold(n_splits=5, shuffle=True, random_state=0)
我使用了 RandomForestRegressor 来开发模型。给定几十个参数组合,我为迭代创建 grid_param,然后引入 GridSearchCV 来运行整个过程。这种迭代将使用一系列不同的参数进行模型拟合,在 5 重交叉验证的基础上,自动找到最佳值。
grid_param = {
"m__n_estimators" : [100, 300, 500],
"m__max_features" : ["auto", "sqrt", "log2"],
"m__min_samples_split" : [2,4,8],
"m__bootstrap": [True, False],
}gd_sr = GridSearchCV(pipeline,
param_grid=grid_param,
scoring='r2',
cv=cv,
n_jobs=3)
一旦最佳模型符合数据,我就将它应用于测试数据。通过比较预测值和真实测试值,我能够得到准确性分数。结果相当令人满意,相关系数为 0.91。
y_pred = gd_sr.predict(X_test)
from sklearn.metrics import r2_score
test_score = r2_score(y_test, y_pred)
print(test_score)
然后,我进一步检查了特征的重要性,令人惊讶的是,最重要的特征是“反应”,它的价值远远高于任何其他特征,如“冲刺速度”和“击球力量”,我之前怀疑这些特征的重要性很高。另一个最重要的特征是“年龄”,这与国际足联球员的价值呈负相关。这是理所当然但可悲的事实😊。
feature_importance = gd_sr.best_estimator_.named_steps['m'].feature_importances_
output = pd.DataFrame(list(zip(feature_name,feature_importance)))
output.columns = ['feature_name','feature_importance']
output.sort_values(by='feature_importance', ascending=False)

顶级功能
我尝试了第二个模型梯度推进回归树,另一个健壮的回归模型。同样的交叉估价程序也已实施。结果甚至更好,r 接近 0.94。与随机森林相似,最重要的特征也是“反应”,其他顶级特征也相似。
结论:
就像典型的数据科学项目一样,我经历了数据收集、可视化探索、特征转换、交叉估值、参数搜索、模型拟合和测试的过程。最后,我认为参数合适的梯度推进模型是预测国际足联球员价值的最佳模型。
目前,这种模式是所有人的混合体。同时,为不同位置的球员探索和开发不同的模式是值得的。对进攻球员来说,诸如“滑铲”等属性的评分并不像防守球员那样重要。按位置划分球员将有助于建立一个更加精确的模型。
房产经纪如何预测美国家庭收入?
原文:https://towardsdatascience.com/how-to-predict-us-household-income-for-real-estate-brokerage-ac86ff581b4e?source=collection_archive---------82-----------------------
一个 ML 框架,以潜在买家为目标,并在新冠肺炎驱动的住房危机中促进低成本住房选择

蒂埃拉·马洛卡在 Unsplash 上拍摄的照片
一个 框架 利用数据解决现实世界的商业问题…
思维能力
哈佛大学住房研究联合中心最近的一份报告谈到了美国高成本租金的强劲增长是如何与低成本住房的急剧下降同时发生的。它还谈到了住房不稳定性的增加,其中,2018 年,收入在 3 万美元至 44,999 美元之间的租房者每月剩余 2,010 美元用于非住房支出——比 2001 年每月减少近 9%,或一年内总共减少 2,300 美元。
在新冠肺炎·疫情之后,根据布鲁金斯学会的数据,形势已经恶化,
甚至在新冠肺炎疫情之前,数百万美国人就缺乏稳定、负担得起的住房。现在,这场危机凸显了安全网中这一关键缺口的社会和经济成本。居住在质量差、拥挤或不稳定的住房中的人——或者根本没有家的人——无法按照公共卫生指令安全地“就地避难”因此,他们感染这种病毒以及其他慢性疾病的风险要大得多。
因此,考虑到人们不像以前那样有强大的购买力,利用新时代的数据分析不仅可以帮助普通美国人,还可以帮助房地产经纪公司应对未售出房屋的令人难以置信的挑战,这变得非常重要。
测量和实验——一个 ML 框架
收入是最重要的变量,有助于决定他或她能买得起哪种房地产。这种买方水平的信息可以很容易地从 UCI 的人口普查收入数据集中得到。这个数据可以很容易地替换为经纪公司可能获得的最新收入数据。ML 框架将在 Google Colab 上实现,包括以下要点:
- 业务简介:房地产经纪公司
- 问题类型:未售出房产
- 工作单位:住房单位
- 价值指标:房屋销售收入
- 目标:锁定潜在买家
- 数据来源: UCI 人口普查数据(存储在 AWS S3 )
- 唯一标识符:公民个人
- 客观问题:预测收入是否 50K 美元
- 信号:收入,年龄,职业,国籍,工作级别,婚姻状况,教育,种族,性别
使用的算法:
由于我们需要预测收入是> 50K 还是≤50K,这是一个二元分类问题。因此,我们将使用以下机器学习算法:
- 逻辑回归
- SVM
- 决策图表
- 随机森林
在此之后,我们需要按照网格搜索微调超参数,以便模型理解这种关系,并能够预测此人的收入是否超过 5 万美元。收到的高 AUC 分数证实所选模型工作正常。

图一。分析中使用的 ML 算法的训练分数
为什么选择谷歌合作实验室?
Colaboratory,简称“Colab ”,允许您在浏览器中编写和执行 Python,使用
- 不需要配置
- 免费访问 GPU
- 轻松分享
在我们的业务用例中,它将允许经纪公司充分利用流行的 Python 库来分析和可视化数据。
为什么选择亚马逊 S3?
亚马逊简单存储服务(亚马逊 S3)是一种对象存储服务,提供行业领先的可扩展性、数据可用性、安全性和性能。这意味着各种规模和行业的客户都可以使用它来存储和保护各种使用情形下的任意数量的数据,例如网站、移动应用程序、备份和恢复、归档、企业应用程序、物联网设备和大数据分析。
在我们的业务用例中,亚马逊 S3 将为房地产公司提供易于使用的管理功能,以组织数据和配置微调的访问控制,从而满足特定的业务、组织和法规遵从性需求。
沟通
从分析中可以得出以下关键业务见解:
- 大多数人收入不到 50K
- 受过高等教育的人收入超过 5 万
- 男性的收入比女性高
- 更多的已婚人士收入超过 5 万英镑
- 目标人群收入低于 5 万英镑,可选择低价住房
未来范围
诸如信用历史、储蓄或流动债务等其他参数也可以包括在内,以更全面地了解个人的购买力和负债。
结论
本文的目的是提供一个框架,从构思- >测量- >实验- >沟通,说明如何使用数据科学工具和机器学习来解决现实世界的业务问题,尤其是在一个受到疫情打击的世界正在应对各种挑战的时候,其中之一是美国的住房危机,以及为面临高失业风险的人提供负担得起的住房选项的需要。
注 : 这篇文章的代码文件可以在这里找到,以供参考。
如何准备用于字符识别和分割的自定义数据集?
原文:https://towardsdatascience.com/how-to-prepare-a-custom-dataset-for-character-recognition-and-segmentation-c39f6bf3690?source=collection_archive---------30-----------------------
详细说明

照片由德鲁·比默在 Unsplash 上拍摄
本文是对泰卢固文字识别研究的一部分。它的重点是为字符识别创建一个自定义数据集,不用担心,你可以用它来为“对象识别”和“分割”任务创建你自己的数据集。
我们开始吧,
目录
- 简介
- 所需工具
- 创建数据集
介绍
字符识别用于识别来自不同来源的字符,如阅读邮政地址、银行支票、表格、招牌等。它广泛应用于银行、教育、国防、信息技术等领域,不胜枚举。
我们将开发一个包含泰卢固语的前 6 个元音的数据集。这是一张泰卢固语元音的图片,带有发音和辅助符号。“创建数据集的过程与此类似,因此您可以使用它来创建自己的数据集”。
泰卢固语是印度第四大通用语言,有 8110 万人使用。它由 60 个符号组成,16 个元音,3 个元音修饰语,41 个辅音。这项研究将继续开发泰卢固语的 OCR 系统。
所需工具
我们将使用 python 编程语言来创建用于字符识别和分割的数据集。使用的工具/包是:
- 标签 4.2.10
- 数字版本 1.17.2
- 枕头 5.3.0
- OpenCV 4.0.0.21
创建数据集
开源平台上有很多数据集可用,比如 Kaggle 、 Google Datasets 。你可以使用 Adrian Rosebrock 的这些信息丰富的博客来自动收集图像。
[## 如何(快速)建立深度学习图像数据集——PyImageSearch
我小时候是个超级口袋妖怪迷。我收集了交易卡,玩了游戏机,看了…
www.pyimagesearch.com](https://www.pyimagesearch.com/2018/04/09/how-to-quickly-build-a-deep-learning-image-dataset/) [## 如何使用 Google Images 创建深度学习数据集- PyImageSearch
PyImageSearch 读者 José提问:嗨,Adrian,感谢你将计算机视觉的深度学习与 Python 结合在一起…
www.pyimagesearch.com](https://www.pyimagesearch.com/2017/12/04/how-to-create-a-deep-learning-dataset-using-google-images/)
1。收集数据

桑德拉·格鲁内瓦尔德在 Unsplash 上的照片
收集数据以创建定制数据集成为一项劳动密集型任务,直到数据/图像不可用,因为泰卢固语字符图像不广泛可用,所以我手动收集图像。将采集到的图像预处理成 400×400 的形状。
您可以使用下面的代码来实现这个目的,它采用两个参数 path 到要处理的图像的文件夹,并采用一个空的文件夹名来存储预处理后的图像。
我已经收集了将近 200 张图片,其中每张图片至少有泰卢固语前 6 个元音中的一个。以下是收集的几个数据示例。

收集数据中的少量图片—作者提供的图片
2.标签数据
因为我们正在创建用于字符识别和分割的数据集,所以我们需要标记已经收集的每个图像中的数据。为了完成这项任务,我们将使用 LabelMe ,这是一个应用程序来标记图像。您可以通过在命令提示符下键入 labelme 来启动应用程序。

LabelMe 应用程序界面—作者图片
以下是标记图像的步骤:
- ‘打开目录’—打开包含预处理图像的目录。
- 在左窗格中选择“创建多边形”,在图像中的角色周围画一个边界框,并分别标记它们,最后保存。
- 选择“下一张图像”并继续步骤 2,直到所有图像都被标记。
- 为每个图像创建一个 Javascript 对象符号(JSON)文件,该文件包含图像的信息,例如文件名、边界框坐标、图像的高度和宽度以及每个边界框的标签等
完成上述步骤后,下面显示了一个样本图片。

标签后的样本图像—作者提供的图像
如上图所示标记图像后创建的 JSON 文件如下所示:
要使用任何识别和分割算法,如掩蔽递归神经网络(MaskRNN),您只需查看一次(YOLO)。需要上下文中的公共对象(COCO)格式的 JSON 文件来训练所提到的算法。
因为我们有单独的 JSON 文件 w.r.t 图像,所以我们需要组合并制作一个 COCO 格式的注释 JSON 文件。下面的代码可以满足这个目的,因为它只需要两个参数,即图像和 JSON 文件的目录路径和保存结果 JSON 文件的输出路径。
下图显示了标记数据后的几幅样本图像。

作者图片
最终想法和未来范围
- 本文有助于为识别和分段任务创建自定义数据集。
- 此外,我们可以使用这种类型的数据集为泰卢固语字符开发字符识别和分割系统。
参考
[## 拉贝梅
使用 Python Labelme 的图像多边形注释是一个图形图像注释工具,灵感来自于…
pypi.org](https://pypi.org/project/labelme/) [## COCO -上下文中的常见对象
编辑描述
cocodataset.org](http://cocodataset.org/#home)
你应该如何准备数据科学面试?
原文:https://towardsdatascience.com/how-to-prepare-for-a-data-science-interview-d0d9fa650a20?source=collection_archive---------48-----------------------
应对数据科学面试所需的技能

资料来源:eurada via 启动倡议
数据科学是 21 世纪要求最高、报酬最高的技术之一,也需要大量的技能,需要大量的努力和规划。
在本文中,我们将讨论在数据科学面试中表现出色的人应该注重哪些技能。
常见的数据科学问题
对你做过的“数据科学”项目的完整描述
通过解释你参与过的一个项目开始你与面试官的对话,你可以从一个小故事开始,讲述你是如何考虑参与这个项目的,你关注的问题,数据的来源,你在数据集中使用的参数,解释在参与这个项目时出现的一些异常结果,你使用的机器学习模型以及使数据分析变得容易的统计技巧。
现在准备好你应该为面试准备的其他技能。
基于概率的情景问题
概率是每个数据科学项目背后的主要关键之一,所有面试官都希望了解候选人处理概率问题的能力以及他们遵循的基本方法。面试官可能试图检查候选人是否有能力为一个特定的问题考虑所有的情况。
结构化查询语言(SQL)
面试官可能会给你一些数据集字段及其数据类型,并给你一个 SQL 查询来从中提取一些特定的元素。面试官可能试图检查候选人是否有能力为一个特定的问题考虑所有的情况。
编程知识
编程知识对于数据科学面试是非常必要的,因为它证明了你编写代码解决问题的能力。主要来说,数据科学问题是使用 Python 或 R 来解决的,所以选择任何一种你觉得舒服的语言(Python/R ),并尝试以非常简化的方式处理给定的问题。
机器学习的应用和解释
在准备数据科学家职位时,一个人应该对所有机器学习模型有深刻的理解,并学会如何用手工制作的图表解释模型,模型的目的,以及它对特定活动或任务的优势和劣势。一些主要的机器学习算法是线性回归、逻辑回归、随机森林、朴素贝叶斯、决策树、支持向量机等。
统计术语的含义
概率和统计在从数据集中提取重要信息以及深入了解统计术语(如标准差、假设的 p 值、相关性、协方差等)方面发挥着重要作用。,也是使用它们时的条件。
设计问题
数据科学是一个广阔的领域,在我们周围有很多应用,所以如果面试官想测试你的知识而不是技术技能,他/她可能会为你提供任何周围问题的示例,并要求你使用你的数据科学技能设计一个解决方案。例如,一个今天下雨的场景,它背后的主要特征是什么,一个可以用来预测某一天是否下雨的机器学习模型。
行为问题
问行为问题是为了检查你如何处理现实生活中的问题,这可以作为一个机会,用一些独特的答案给面试官留下深刻印象,并使他/她与其他受访者相比对你没有什么偏见。
下面是一些行为问题的例子:
工作中的动力是什么?
你认为这一领域最紧迫的问题是什么?
你最大的优点/缺点是什么?为什么你认为你会喜欢这个领域?
描述一次你和一个性格与你截然不同的人一起工作的经历。告诉我你承受巨大压力的一次经历。当时是什么情况,你是怎么熬过来的?
告诉我一个你管理的长期项目。你是如何保持组织有序并确保一切按计划进行的?
希望这篇文章能帮助你准备数据科学面试,获得你梦想中的工作。 万事如意!
如何准备 AI
原文:https://towardsdatascience.com/how-to-prepare-for-ai-4dbf87cbc2e1?source=collection_archive---------52-----------------------
当人工超级智能迫使我们失去平衡时,永生的生存指南。

人工智能的出现
人工智能还没有到来,它已经来了。已经有文章和书籍将人工智能拟人化,列出其失败模式,并证明人类将努力应对与新范式相关的错综复杂的道德和伦理问题。有些因揭示了人类尚未面对的社会问题而受到称赞;其他人则因未经请求和未经支持的散布恐惧而受到批评。
这些参考文献在很大程度上涵盖了人工通用智能(AGI)领域,指的是一种能够在各种环境下执行高阶心理功能的机器,如人类。关于我们什么时候能在社会上看到 AGI,专家们有不同的观点——但是有一个普遍的共识,那就是这不是一个是否的问题,而是什么时候的问题。
与此同时,人工狭义智能(ANI)——指的是机器或算法可以完成的专门任务——就在这里,而且非常好。它可以像人类一样完成一些任务(比如区分小狗和松饼)和一些比人类更好的任务(比如下棋)。
为什么这很重要?
- 认知含义:每个人都需要花费数年时间来发展理解松饼概念所必需的知觉、感觉和认知技能,从多个角度观看松饼时感知松饼,并在看到松饼时检索相关单词“muffin”。然而,一旦建立了图像分类器,该算法可以通过一次软件更新立即在数千台机器上实施——人类需要几年才能获得的东西,机器可以在几分钟内完成。
- 经济影响:失业被认为是一系列行业中 ANI 的重要影响,包括娱乐和新闻媒体、战争、法律、体育、交通和金融市场。近年来,人工智能研究人员、企业家和政策制定者提出了多种解决方案来对抗与人工智能发展相关的外部性,从普遍基本收入到全州监管。
AGI 是最聪明的人工智能吗?
否——引入超级智能。
雷·库兹韦尔提出了智能爆炸的概念——人工智能变得足够聪明以改善自己。一个基于软件的 AGI 将进入一个自我改进循环的递归回路,导致一个甚至超过人类智能的智能爆炸——超级智能(ASI)

像素通过像素 (CC0)
如何准备 AI
这篇文章旨在提供一个指南,告诉你可以部署哪些策略来为 AI 时代做好准备。
理解与人工狭义智能、人工广义智能和人工超智能相关的风险。这包括:
- 理解当前机器学习算法的范围,以及它们如何改变经济和扰乱行业。
- 辨别由无监督学习算法产生的人类无法理解的相关性
3.理解算法偏差是如何发生的:
- 不具代表性的训练数据可能会产生算法偏差
例如,从训练数据集中没有足够多的深色皮肤的人的训练数据集中,导致面部识别系统不能识别少数民族

- 算法偏差可能由有偏差的训练数据引起
例如,通过使用书写数据的语料库来改进算法——在一项研究中,句子“男人对于医生来说,就像女人对于……”由预测性 NLP 算法用“护士”来完成。
围绕新技术发布后的伦理和道德含义展开对话
个人、企业家、公司和政策制定者都有责任围绕新技术范式展开富有成效的、批判性的辩论。这将导致公众意识到当前技术的范围,防止类似真相的案例发生——一个假设人类灭绝的思想实验,由最初被编程为书写机器的东西引发。
在公司拥有的 ani 层面,个人可以通过了解他们的数据如何被收集(例如:当你访问网站时的 cookies)、使用(例如:定向广告)、存储(例如:Snapchat 在其服务器上存储数据),以及在各个层面有偏见的(例如:有偏见的训练数据,导致服务无法在边缘情况下工作)来最好地准备自己。)
在 ASI 的层次上,人类可以被解释为生命平衡木上的另一个物种,它的绊网正在接近;ASI 的出现可能将我们推向灭绝或永生。广受赞誉的人工智能研究员尼克·博斯特罗姆提出了一个平衡木模型的概念。所有物种突然出现,在平衡木上摇摇晃晃,然后陷入灭绝——博斯特罗姆称灭绝为吸引状态。
除了灭绝,还有另一个吸引子——状态——永生。因此,吸引子状态由物种灭绝和物种永生组成。到目前为止,所有的物种最终都灭绝了——但是有可能一个物种会掉到平衡木的另一边,变成永生
绊网是指一个物种存在的阈值。对于一个物种来说,撞上绊网是一个巨大的变革性事件,就像一个世界性的疫情或小行星。或者人工超级智能。
哲学家认为 ASI 可能是人类的绊网,让我们要么走向灭绝,要么走向永生。因此,在更大的范围内,人工智能是否会对人类产生积极影响,这是一个与我们的生存问题密不可分的问题。

在这段不确定时期,个人最大的财富是知识。这包括理解人工智能的各种理论,意识到与人工智能发展相关的挑战和风险,以及合理化结合人工智能、生物技术和纳米技术等各种快速发展领域的创新可能带来的潜在结果。
作为创新者,我们应该意识到资本主义的激励结构,这种结构以牺牲人性为代价,促进创新,奖励对快速发展技术的投资。对于 ASI 这样的高影响力技术,我们应该专注于稳定的开发,在每个阶段测试功能,以避免智能爆炸,而不是快速移动的破坏。
作为个人和人类,我们有权游说为追求 AGI 的公司和研究机构设立“检查站”级别的政策——对创新、研究和开发实践透明的公司有潜在的财政利益——从而激励人工智能技术的规范发展,并在全球范围内校准进展水平。
作为分析师,如何赢得案例研究面试
原文:https://towardsdatascience.com/how-to-prepare-for-business-case-interview-as-an-analyst-6e9d68ce2fd8?source=collection_archive---------2-----------------------
咨询案例研究 101
案例研究面试准备终极指南

Clem Onojeghuo 在 Unsplash 拍摄的照片
作为数据分析师或数据科学家,我们不仅需要知道概率和统计、机器学习算法、编码,最重要的是,我们需要知道如何使用这些技术来解决任何业务问题。大多数情况下,你将有 30-45 分钟的时间与一位数据科学家或招聘经理面谈,在面谈中,你将回答一个可能与组织日常工作相关的多方面业务问题。
当我第一次开始准备案例研究面试时,我不知道有不同类型的案例研究。成为案例研究专家的最快方法是了解解决不同类型案例研究的所有框架。案例研究面试可以帮助面试官评估候选人是否适合这个职位。有时,他们甚至会问你一个他们实际遇到的问题。了解面试官在寻找什么可以帮助你更好地准备你的回答。
他们在面试中寻找什么?
📌逻辑和可操作的思维过程
▶️:面试官关心你的思维过程,以及你如何得到解决方案。如果你能够在没有任何框架的情况下得到答案,面试官可能会认为这只是你的幸运日,下次你就不能解决问题了。
📌适应性
▶️:有时候,如果你走错了方向,面试官可能会问你一些问题来帮助你回到正轨。如果这发生在你的面试中,你很可能错过了他们认为重要的东西。
📌信心
▶️:求职面试时紧张是正常的。但是,作为一个分析师,你自己都不相信自己,别人怎么会相信你呢?
📌清晰通信
▶️:作为一名分析师,分析数据和解释结果的能力非常重要。根据您的公司,一些分析师确实需要向利益相关者展示他们的分析。
如何总能得到他们想要的答案
📣结构
他们想知道你是否能采取系统的方法来解决问题,并且你能清楚地描述它。例如,他们可能会问你:“这个月活跃用户账户增加了 xx%,你能告诉我们是怎么回事吗?”
要回答这类问题,你不必马上准备好答案。最重要的是你的思维过程。不要马上告诉他们你的任何猜测或假设。用一个框架来回答。向他们提问,表明你了解这个行业。
📣综合性
他们想知道你的回答是否涵盖了问题的所有方面。例如,他们可能会给你一个情况,并问你一些问题,如“看起来怎么样”、“当前的问题是什么”、“我们如何改进”等。
有许多方法可以回答这类问题。得到完美答案的关键是要简洁,并在最后提供一个推荐。假设营销副总裁问你“看起来怎么样?”在 2 分钟内,您可以通过陈述当前的目标是什么、我们目前所处的位置、我们距离公司的目标有多远、我们下一步计划做什么来达到目标(建议)以及我们需要多长时间才能达到目标来回答这个问题。
📣可行性
他们想看看你的回答是否实用,是否能切实可行。要更精准;尽可能使用数字。
我注意到很多分析师经常忘记用数字来支持他们的观点。如果你想让经理知道根据你的计算不可能达到特定的目标,你应该用你的分析数据来证明为什么会这样。使用数字可以帮助你的建议更有说服力和可靠性。
📣观众
有时,他们可能会要求你对不同的人(你的经理、CEO 等)回答一个模糊的问题,比如“看起来怎么样”。).这类似于当招聘人员问,“告诉我关于你自己的情况”,你不想认真对待你所做项目的本质,因为你的招聘人员可能会失去兴趣。另一方面,招聘经理可能希望你多谈谈你过去的项目。
这也适用于案例研究面试。知道谁是你的观众是非常重要的。如果你和销售副总裁交谈,他或她可能更关心顾客的数量。相反,如果你与营销副总裁交谈,他或她可能不像销售副总裁那样关心潜在客户的数量,相反,他们可能关心如何提高回复率和转化率。
什么是完美的框架
- 澄清问题
- 分解问题
- 解决每一块
- 将它们整合到最终结果中
这给了你一个如何得到完美解决方案的总体思路。然而,对于每种类型的案例研究问题,我们可以有一个不同的框架。
案例研究类型
案例研究有几种类型。以下是案例研究面试问题的主要类型:
- 损益
- 进入新市场
- 增长和销售增长
- 市场规模估计
损益
面试官喜欢问案例研究问题的原因之一是,咨询师经常需要帮助客户解决一个模糊的问题,而不知道从哪里开始。客户陈述了他们面临的盈利/亏损问题,他们希望你能帮助他们找出发生这种情况的原因。一个典型的情况是,一家公司在过去几年中相对盈利,但最近利润突然下降。他们应该怎么做?
你可以把这个问题分成两部分——收入和成本。我们知道利润等于收入减去成本。如果利润下降而成本保持不变,那么收入就是问题。我们需要考虑如何增加收入。如果是反过来,那么我们就需要想出一个降低成本的方案,比如削减产量和劳动力成本。
进入新市场
向新市场扩张是发展业务的有效途径。因此,一些客户可能会问顾问,进入一个新市场是否是个好主意。
在回答是或否之前,你应该问一些澄清性的问题,以更多地了解客户的公司。
以下是一些你可以问的澄清性问题:
- 公司的目标是什么?它符合我们的整体战略吗?
- 我们需要增加投资吗?(分销渠道、生产、新员工..)
- 现在和未来的市场是什么样的?(新兴?成熟?下降)
- 客户群会与现有的不同吗?
- 竞争对手是谁?他们的市场份额有多大?
- 他们的产品和我们的有什么不同?
- 有进入/退出的障碍吗?
增长和销售增长
我希望有一种终极方法来增加所有公司的销售额。不幸的是,根据行业和市场规模的不同,发展公司和增加销售的方式会有所不同。
这里有一些公司可以尝试发展业务的方法:
⛳️调查公司和行业:我们需要知道行业是否在增长。如果有,公司可以投入多少资金来扩大公司规模?相对于行业/竞争对手,公司的发展如何?我们的价格与竞争对手一致吗?谁是我们的目标市场?
⛳️选择最合适的增长战略:一旦我们对公司及其行业有了更多的了解,我们就可以相应地推荐最合适的增长战略。例如,如果客户想收购一家完全不同行业的公司,这可能不值得,因为目标受众完全不同。
市场规模估计
作为一名分析师,做出合理估计的能力至关重要。你的面试官可能会问这样的问题:在美国每个月要吃掉多少平方英尺的比萨饼?
这是一个经典的猜测问题。回答这类问题的诀窍是将问题分成不同的部分,为了便于计算,将任何数字向上或向下取整,并解释你为什么要估计你正在估计的东西。我决定把问题分成 4 部分。
- 美国有多少人吃披萨?
让我们假设大约 2/3 的美国人都吃披萨。美国大约有 3.2 亿人口。然而,我们可以用 300 来简化计算,而不是用 2/3 乘以 320。现在我们知道美国有 2 亿人吃披萨。
2.普通美国人一个月吃多少比萨饼?
我们可以估计,平均来说,一个美国人每月吃一次披萨。假设人们通常每餐吃 3-4 片比萨饼,我们可以估计每人平均消费 4 片比萨饼。现在我们需要把比萨饼切片转换成平方英尺。
3.比萨饼切成平方英尺
如果一片比萨饼底长 4 英寸,长 5 英寸,那么面积就是 10 平方英寸(1/2 底高=45/2)。因为平均来说,一个人每月吃 4 片比萨饼,所以一个吃比萨饼的人每月的比萨饼面积是 40 平方英寸。乘以 2 亿人(美国吃比萨饼的人口),现在我们得到 80 亿(2 亿 40)平方英寸。最后,在将平方英寸转换成平方英尺(除以 144 →四舍五入到 100)后,现在我们每月可以得到大约 8000 万平方英尺的比萨饼。
方便的信息
事先了解一些方便的信息可以帮助我们更好地估计市场规模。以下是《破解 PM 面试一书中列举的一些随手可得的信息:

来自破解 PM 采访本的截图
最终提示
- 确保你理解了被问到的问题;如果你需要澄清问题,不要害怕提问。但是要记住!注意,试着总结面试官告诉你的话。
- 花时间思考问题,建立一个框架。例如,你可以谈论问题陈述,比如组织面临的问题是什么;然后你可以总结你提出的所有建议,并解释每一条建议。
- 陈述你的假设,但不要做出愚蠢的假设,比如某人表现得不够好。
- 熟能生巧!多读一些案例研究的例子,从中学习。
资源
以下是我用来准备案例研究面试的资源清单。
书
📚破解 PM 面试:如何获得技术领域的产品经理职位
📚第 10 点案例:完成案例面试准备
📚面试数学:超过 60 个问题和定量案例面试问题的解决方案
网站
[## 我的咨询教练
我认为能够提出一个好的框架是成功进行案例面试的最重要的因素…
www.myconsultingcoach.com](https://www.myconsultingcoach.com/) [## 星状细胞
“StellarPeers 是一个由伟大的人组成的网络,我很高兴成为这个团体的一员。我真的很喜欢模拟面试…
stellarpeers.com](https://stellarpeers.com/)
播客
[## 案例面试准备和管理咨询|战略|对苹果的批判性思考…
咨询公司在麦肯锡、波士顿咨询集团和贝恩公司内部为客户提供服务的成功率保持在 80%。这是最高的…
podcasts.apple.com](https://podcasts.apple.com/us/podcast/case-interview-preparation-management-consulting-strategy/id904509526)
油管(国外视频网站)
[## 案例访谈
欣赏您喜爱的视频和音乐,上传原创内容,并在上与朋友、家人和全世界分享这些内容…
www.youtube.com](https://www.youtube.com/channel/UC-YKX7L2GNNA-IHrhMpwzWA)
如何为机器学习准备数据
原文:https://towardsdatascience.com/how-to-prepare-your-data-for-machine-learning-307cc556af48?source=collection_archive---------31-----------------------
预测泰坦尼克号上的幸存者
TL;博士 :这篇文章涵盖了泰坦尼克号沉船数据集的完整准备。
本帖是本书的一部分: 用 Python 动手做量子机器学习

作者弗兰克·齐克特的图片
泰坦尼克号的沉没是历史上最臭名昭著的海难之一。
1912 年 4 月 15 日,泰坦尼克号与冰山相撞后沉没。被认为是不沉的,没有足够的救生艇给船上的每个人。当晚 2224 名乘客和机组人员中有 1502 人死亡。
当然,722 名幸存者一定有一些运气。但是似乎某些人群比其他人群有更好的生存机会。
因此,泰坦尼克号的沉没也成为任何对机器学习感兴趣的人的著名起点。
如果你有一些机器学习的经验,你可能会知道 Kaggle 提供的传说中的泰坦尼克号 ML 比赛。
如果你还不知道 Kaggle,Kaggle 是世界上最大的数据科学社区之一。它提供了许多有趣的数据集,因此,它是一个开始的好地方。
要解决的问题很简单。使用机器学习创建一个模型,根据乘客数据,预测哪些乘客在泰坦尼克号沉船中幸存。
获取数据集
为了获得数据集,你需要创建一个 Kaggle 帐户(它是免费的)并加入竞争。即使 Kaggle 完全是关于竞争的,你也不需要通过上传你的解决方案来积极参与其中。
当你参加比赛时,你需要接受并遵守规则,这些规则规定了你每天可以提交多少份作品,最大团队规模,以及其他比赛的具体细节。
您可以在竞赛页面顶部的数据选项卡中找到竞赛数据。然后,向下滚动以找到文件列表。
数据中有三个文件:
train.csvtest.csvgender_submission.csv
文件train.csv包含泰坦尼克号乘客子集的数据。这个文件应该作为你的算法的基础,以了解一名乘客是否幸存。
文件test.csv包含另一个乘客子集的数据。它决定了你的算法执行的有多好。
gender_submission.csv文件是一个例子,它展示了如果您打算将预测提交给 Kaggle,您应该如何构建预测。因为我们在这里开始学习,还没有准备好竞争,我们将跳过这个文件。
下载文件train.csv和test.csv。
看数据
我们需要做的第一件事是加载数据。我们用熊猫来表示。它在机器学习社区中以数据处理而闻名。它提供了各种有用的功能,比如加载.csv-文件的功能:read_csv。
从 csv 文件加载数据
我们将数据加载到train和test中。这些是熊猫。
A DataFrame将数据保存在带有标签的二维结构中。例如数据库表或电子表格。它提供了许多现成的有用属性和功能。
例如,DataFrame的属性shape提供了一个由两个整数组成的元组,表示行数和列数。
让我们来看看:
泰坦尼克号数据集的形状
train has 891 rows and 12 columns
test has 418 rows and 11 columns
我们可以看到我们有 891 个培训和 418 个测试条目。更有趣的是,train数据集比test数据集多一列。
DataFrame的info()方法显示了一些更详细的信息。看一下train数据集。
train.info()

训练数据集的结构
info方法返回列的列表:它们的索引、名称、有多少条目有实际值(不是null)以及值的类型。
让我们也来看看test数据集。
test.info()

测试数据集的结构
当比较这两个信息时,我们可以看到test数据集遗漏了列Survived,该列指示一名乘客是幸存还是死亡。
正如 Kaggle 指出的,他们使用test数据集来评估提交的内容。如果他们提供了正确的答案,那就不再是什么竞赛了,不是吗?我们的任务是预测正确的标签。
由于我们不打算将我们的预测提交给 Kaggle,以获得对我们算法执行情况的评估,test数据集对我们来说毫无用处。
因此,我们专注于train数据集。
info输出非常抽象。能看到一些实际数据不是很好吗?没问题。这就是head方法的用途。
head方法显示列标题和前五行。有了这个印象,我们再来过列。你也可以在 Kaggle 页面上看到解释。
train.head()

每一列代表我们数据的一个特征。PassengerId是识别每一行的连续数字。Survived是乘客是否幸存的指示器(0 =否,1 =是)。Pclass是票类(1 = 1 号,2 = 2 号,3 = 3 号)。然后我们有不言自明的Name、Sex和Age。
表示该乘客在泰坦尼克号上的兄弟姐妹或配偶的数量。Parch表示泰坦尼克号上该乘客父母或子女的编号。
然后就是乘客付费的Fare,号码Cabin和登船港口(embarked ) (C =瑟堡,Q =皇后镇,S =南安普顿)。
数据准备和清理
我们的数据有不同的类型。有数字数据,如Age、SibSp、Parch、Fare。有分类数据。一些类别由数字表示(Survived、Pclass)。有些用文字表示(Sex、Embarked)。还有文字资料(Name、Ticket、Cabin)。
这真是一团糟。为了一台电脑。此外,当再次查看train.info()的结果时,您可以看到不同列的计数有所不同。虽然大多数列有 891 个值,但只有 714 个用于Age,204 个用于Cabin,889 个用于Embarked。
在我们可以将数据输入任何机器学习算法之前,我们需要清理。
缺少值
大多数机器学习算法在缺失值的情况下效果不佳。有三种方法可以解决这个问题:
- 去掉相应的行(不考虑乘客)
- 去除整个列(去除所有乘客的整个特征)
- 填充缺失的值(例如,用零、平均值或中值)
应对缺失值

我们可以使用DataFrame的dropna()、drop()和fillna()方法轻松完成这些事情。一般来说,没有一个最佳选择。但是你要仔细考虑具体的语境。
只有两个乘客的出发港口我们不知道。这些占我们数据不到 1%。如果我们完全忽略这两个乘客,我们不会看到完全不同的结果。因此,我们用dropna方法删除这些行(第 3 行)。
dropna-方法将列("Embarked")作为命名参数subset。此参数指定确定是否删除行(乘客)的列。如果这些列中至少有一个值缺失,该行将被删除。
关于Cabin,情况有所不同。我们只有 991 名乘客中 204 人的信息。这是否足以从中得到任何信息是值得怀疑的。我们不知道为什么这些值会丢失。即使我们发现Cabin与乘客的生存高度相关,我们也不知道这种相关性是否可以推广到所有乘客,或者是否存在选择偏差,这意味着我们知道Cabin的事实取决于一些其他方面。
我们用方法drop删除整个列。我们提供想要移除的列(Cabin)作为定位参数。我们作为命名参数axis提供的值1指定我们想要移除整个列。
接下来我们知道 714 乘客的Age。将我们不认识的所有乘客排除在考虑范围之外似乎不是一个选项,因为他们占了我们数据的大约 22%,相当重要的一部分。移除整个列似乎也不是一个好的选择。首先,我们知道大多数乘客的Age,直觉表明Age可能对某人的生存机会很重要。
我们用fillna方法填充缺失的值(第 13 行)。因为我们只想填充Age列中缺失的值,所以我们在该列上调用这个函数,而不是整个DataFrame。我们提供想要设置的值作为参数。这是我们之前计算的所有乘客的平均年龄(第 12 行)。
太好了。我们现在有 889 行,10 列,不再有丢失的数据。
标识符
机器学习的目标是创建一个能够预测数据的算法。或者,就像我们之前说的:给一个东西贴上标签。虽然我们在构建算法时使用了已经标记的数据,但我们的目标是预测我们还不知道的标签。
我们没有告诉我们的算法它如何决定选择哪个标签。而是我们告诉算法,“这是数据,你自己算出来”。也就是说,一个精明的算法可能能够记住你提供给它的所有数据。这被称为过度拟合。结果是算法在已知数据上表现良好,但在未知数据上表现不佳。
如果我们的目标是只预测我们已经知道的标签,我们能做的最好的事情就是记住所有的乘客以及他们是否幸存。但是,如果我们想要创建一个即使在未知数据上也能表现良好的算法,我们需要防止记忆。
我们甚至还没有开始构建我们的算法。然而,我们为算法提供的基本功能会影响算法是否能够记忆数据。因为我们的数据中有潜在的标识符。
当查看数据集的前五个条目时,有三列看起来可疑:第PassengerId、Name和Ticket。
PassengerId是一个后续数字。数字有多大和有没有乘客生还应该没有联系。
乘客的名字或车票上的号码也不应该成为生存的决定性因素。相反,这些是识别单个乘客的数据。让我们验证这个假设。
让我们看看这些列中有多少唯一值。
列中的唯一值
There are 889 different (unique) PassengerIds in the data
There are 889 different (unique) names in the data
There are 680 different (unique) ticket numbers in the data
Name和PassengerId是完美的标识符。在我们的数据集中,889 行中的每一行都有一个唯一的值。
并且有 680 个不同的Ticket号。Ticket不是完美标识符的一个可能解释是家庭票。然而,基于这一数据的预测似乎支持记忆,而不是学习可转移的洞察力。
我们移除这些柱子。
删除识别数据

处理文本和分类属性
正如我们将在本书中看到的,所有的算法,包括经典算法和量子算法,都与数字有关。除了数字什么都没有。如果我们想使用文本数据,我们需要把它转换成数字。
Scikit-Learn 为此任务提供了一个名为LabelEncoder的转换器。
将文本数据转换为数字

首先,我们导入LabelEncoder(第 1 行)并初始化一个实例(第 2 行)。我们用文本数据(Sex和Embarked)遍历列(第 4 行)。对于每一列,我们需要fit将列中的数据(第 5 行)编码,然后才能转换值(第 6 行)。
最后,让我们再看看我们的DataFrame。可以看到,Sex和Embarked现在都是数字(int64)。在我们的例子中,0表示男性,1表示女性乘客。但是当您再次运行转换时,您可能会产生不同的赋值。
特征缩放
机器学习算法只对数字起作用。此外,他们通常使用相同比例的数字。如果数字具有不同的标度,算法可能会认为标度越高的数字越重要。
尽管我们所有的数据都是数字,但还没有统一的比例。大多数列的值在0和3之间。但是Age和Fare的规模要大得多。
max方法返回一列中的最大值。我们可以看到,年龄最大的乘客 80 岁,最高票价约 512。
最大值
The maximum age is 80.0
The maximum fare is 512.3292
处理不同比例数据的一种常用方法是最小-最大比例(也称为归一化)。这个过程会移动和重新调整值,使它们最终的范围从0到1。它从每个值中减去最小值,然后除以最大值减去最小值。
Scikit-Learn为我们提供了MinMaxScaler转换器来完成这项工作。
数据的标准化
The minimum value is 0.0 and the maximum value is 1.0
同样,我们首先导入转换器(第 1 行)并初始化它(第 3 行)。然后,我们fit转换我们的数据(第 4 行)并转换它(第 5 行)。
因此,我们数据集中的所有数据都在0.0和1.0之间。
scaler 返回一个 Numpy 数组,而不是 Pandas 数据帧
培训和测试
我们已经提到了构建一个算法的目标,该算法不仅对已知数据表现良好,而且还能预测未知数据的标签。
这就是为什么将数据分为训练集和测试集非常重要。我们使用训练集来构建我们的算法。我们使用测试集来验证它的性能。
尽管 Kaggle 提供了一个测试集,但我们跳过了它,因为它没有包含Survived列。每次我们想验证它的时候,我们都需要问 Kaggle。为了保持简单,并且能够自己进行验证,我们宁愿从 Kaggle 训练集中抽出一些行来进行测试。
分离一个test集合相当简单。Scikit-learn 也为此提供了一个有用的方法。这是train_test_split。
此外,我们需要将输入数据与我们想要预测的结果标签分离开来。
将输入从标签中分离出来,将训练从测试集中分离出来
We have 711 training and 178 testing rows There are 7 input columns
我们用 Python 数组索引将输入列与标签分开(第 3–4 行)。第一列(位置0)包含我们想要预测的Survived标志。其他列包含我们用作输入的数据。
train_test_split将训练与测试数据集分开。参数test_size = 0.2 (= 20%)指定了我们希望测试集拥有的部分。
我们可以看到我们的训练数据集包含 711 个条目。因此,我们的测试集由 178 个条目组成。我们有 7 列输入和一列输出。
让我们保存我们准备好的数据,这样我们就可以在将来使用它,而不需要重复所有这些步骤。
将数据保存到文件系统
本帖是本书的一部分: 用 Python 动手做量子机器学习。

在这里免费获得前三章。
如何为机器学习模型准备数据
原文:https://towardsdatascience.com/how-to-prepare-your-data-for-your-machine-learning-model-b4c9fd4e7ea?source=collection_archive---------18-----------------------
数据准备分步指南

由故事创建的数据向量—www.freepik.com
目录
- 介绍
- 什么是数据准备
- 探索性数据分析
- 数据预处理
- 数据分割
介绍
在我们进入这个话题之前,我想澄清一点,数据准备没有严格的流程。准备一组数据的方式很可能与准备另一组数据的方式不同。因此,本指南旨在提供一个总体指南,供您在准备任何特定数据集时参考。
在我们进入指南之前,我应该先回顾一下什么是数据准备…
什么是数据准备?
数据准备是机器学习生命周期中数据收集之后的步骤,它是清理和转换您收集的原始数据的过程。通过这样做,在对数据进行分析和建模时,您会轻松得多。
我将在本文中介绍数据准备的三个主要部分:
- 探索性数据分析
- 数据预处理
- 数据分割
1.探索性数据分析
探索性数据分析,简称 EDA,听起来就是探索你的数据。在这一步中,您只是简单地了解您正在处理的数据。在现实世界中,数据集不像 Kaggle 数据集那样干净或直观。
您对正在处理的数据探索和理解得越多,数据预处理就越容易。
以下是您在此步骤中应该考虑的事项列表:
特征和目标变量
确定什么是特征(输入)变量,什么是目标变量。不要担心确定什么是最终输入变量,但要确保你能识别这两种类型的变量。
数据类型
弄清楚你在处理什么类型的数据。它们是绝对的,数字的,还是都不是?这对于目标变量尤其重要,因为数据类型将缩小您可能想要使用的机器学习模型的范围。像 df.describe() 和 df.dtypes 这样的熊猫函数在这里很有用。
检查异常值
一个异常值是一个明显不同于其他观察值的数据点。在这一步中,您需要识别异常值,并尝试理解它们出现在数据中的原因。根据它们出现在数据中的原因,您可以决定将其从数据集中移除或保留。有几种方法可以识别异常值:
- Z 值/标准偏差:如果我们知道一个数据集中 99.7%的数据位于三个标准偏差之内,那么我们可以计算一个标准偏差的大小,乘以 3,并确定超出该范围的数据点。同样,我们可以计算给定点的 z 分数,如果它等于+/- 3,那么它就是异常值。注意:使用这种方法时需要考虑一些意外情况;数据必须是正态分布的,这不适用于小数据集,并且太多异常值的存在会影响 z 值。
- 四分位距(IQR) : IQR,用于构建箱线图的概念,也可用于识别异常值。IQR 等于第三个四分位数和第一个四分位数之差。然后,如果一个点小于 Q1-1.5 * IRQ 或大于 Q3 + 1.5*IQR,则可以确定该点是否为异常值。这达到大约 2.698 个标准偏差。
提问
毫无疑问,你很可能会对你正在处理的数据有疑问,尤其是对于你领域知识之外的数据集。例如,Kaggle 有一个关于 NFL 分析和伤病的比赛,我必须做一些研究,了解不同的位置是什么,以及他们的功能对团队有什么作用。
2.数据预处理
一旦您理解了您的数据,作为一名数据科学家,您的大部分时间都花在这一步上,即数据预处理。这是你花时间操纵数据,以便它可以被正确建模的时候。就像我之前说的,没有通用的方法来解决这个问题。然而,有一些重要的事情你应该考虑,我们将在下面讨论。
特征插补
特征插补是填补缺失值的过程。这很重要,因为当数据集中有缺失数据时,大多数机器学习模型都不起作用。
我想写这个指南的主要原因之一就是为了这个步骤。许多文章说你应该默认用平均值填充缺失值或者简单地删除行,而这不一定是真的。
理想情况下,您希望选择最有意义的方法—例如,如果您正在对人们的年龄和收入进行建模,那么一个 14 岁的孩子获得全国平均工资就没有意义。
总的来说,有几种方法可以处理缺失值:
- 单值插补:用列的平均值、中值或众数替换缺失值
- 多值插补:对有缺失数据的要素进行建模,并用模型发现的内容输入缺失数据。
- K-最近邻:用另一个相似样本的值填充数据
- 删除该行:这不是一种插补技术,但当样本量非常大时,如果你能负担得起,这种方法也是可行的。
- 其他包括:随机插补、移动窗口、最频繁等…
特征编码
特征编码是将值(即字符串)转化为数字的过程。这是因为机器学习模型要求所有值都是数字。
有几种方法可以解决这个问题:
- 标签编码:标签编码只是将一个特征的非数值转换成数值,不管这个特征是不是序数。例如,如果名为 car_colour 的要素具有红色、绿色和蓝色的不同值,那么标注编码会将这些值分别转换为 1、2 和 3。使用这种方法时要小心,因为虽然有些 ML 模型能够理解编码,但有些却不能。
- 一热编码(又名。get_dummies): 一种热编码的工作原理是为给定特征的每个非数值创建一个二进制特征(1,0)。再次使用上面的例子,如果我们有一个名为 car_colour 的特征,那么一个热编码将创建三个名为 car_colour_red、car_colour_green、car_colour_blue 的特征,并且将有一个 1 或 0 来指示它是否存在。
特征标准化
当数值处于不同的尺度时,例如,以厘米为单位的身高和以磅为单位的体重,大多数机器学习算法都表现不佳。k-最近邻算法是不同比例的要素不能很好工作的主要例子。因此,规范化或标准化数据有助于解决这个问题。
- 特征标准化重新调整数值,使其在[0,1]/的范围内
- 特征标准化重新调整数据,使平均值为 0,标准差为 1。
特征工程
特征工程是将原始数据转化为更好地代表人们试图解决的潜在问题的特征的过程。这一步没有具体的方法,但你可以考虑以下几点:
- 转换日期时间变量以仅提取星期几、月份等…
- 为变量创建容器或桶。(例如,对于高度变量,可以有 100-149 厘米、150-199 厘米、200-249 厘米等。)
- 组合多个要素和/或值以创建一个新要素和/或值。例如,泰坦尼克号挑战最准确的模型之一设计了一个新的变量,称为“是女人还是孩子”,如果这个人是女人或孩子,这个变量为真,否则为假。
特征选择
接下来是要素选择,即选择数据集最相关/最有价值的要素。我喜欢使用一些方法来帮助您选择功能:
- 特性重要性:像 random forests 或 XGBoost 这样的算法允许您确定哪些特性在预测目标变量的值时是最“重要”的。通过快速创建其中一个模型并进行特征重要性分析,您将了解哪些变量比其他变量更有用。
- 降维:最常见的降维技术之一,主成分分析(PCA)取大量特征,利用线性代数将其降维为较少的特征。
处理数据失衡
你要考虑的另一件事是数据不平衡。例如,如果一个类别有 5,000 个示例(例如,非欺诈性的),但另一个类别只有 50 个示例(例如,欺诈性的),那么您需要考虑以下几件事情之一:
- 收集更多的数据——这总是对你有利的,但是通常是不可能的或者太贵了。
- 您可以使用 scikit-learn-contrib Python 包对数据进行过采样或欠采样。
3.数据分割
最后是分割你的数据。我将给出一个非常通用的框架,你可以在这里使用,这是普遍同意的。
通常,您会希望将数据分成三组:
- 训练集(70–80%):这是模型学习的内容
- 验证集(10–15%):模型的超参数在这个集上进行调整
- 测试集(10–15%):最后,在此基础上评估模型的最终性能。如果你已经准备好了正确的数据,测试集的结果应该给出一个模型在真实世界中表现的很好的指示。
感谢阅读!
我希望你已经从中学到了一些东西。通过阅读本文,您现在应该对数据准备有了一个大致的了解。需要考虑的事情很多,但是有这样的资源提醒你总是有帮助的。
如果您遵循这些步骤并牢记这些事情,您一定会更好地准备您的数据,并且您最终能够开发一个更准确的模型!
特伦斯·申
- 查看 我的免费数据科学资源 每周都有新资料!
- 如果你喜欢这个, 跟我上媒 了解更多
- 我们连线上LinkedIn
如何预处理社交媒体数据和短信
原文:https://towardsdatascience.com/how-to-preprocess-social-media-data-and-text-messages-b011efacf74?source=collection_archive---------26-----------------------
因为我觉得很多人只是这样写🤦🏻♂️ (╯ □ )╯︵ ┻━┻

约纳斯·勒普在 Unsplash 上拍摄的照片
在社交媒体数据和文本消息上执行 NLP 任务的最大挑战之一是网络英语与标准英语有很大不同。在 Reddit 帖子、tweets、WhatsApp 消息等中,有俚语、首字母缩写词、缩写词、首字母缩写词、表情符号、标签、URL 以及其他一些不以标准英语出现的拼写错误。在深度学习的乌托邦中,我们将收集尽可能多的数据,并从头开始训练我们的模型和标记器,以弄清楚这些俚语和首字母缩写词等的含义。然而,在现实生活中,我们可能希望利用现有的预训练模型(及其相关的标记器),如 BERT。由于这些模型和它们的标记器通常是在英语维基百科和图书语料库数据上预先训练的,我们将需要首先预处理我们的互联网英语数据。另一方面,如果我们决定使用非深度学习方法,那么数据预处理就更加重要,因为它对特征工程有着巨大的影响。在本文中,我们将介绍一些专门针对互联网英语数据的数据预处理步骤,或者需要特别注意的步骤。
常见的 NLP 数据预处理步骤
在本节中,我们将讨论一些最常见的 NLP 数据预处理步骤。它们是如此普遍,以至于我们可能会认为这是理所当然的,并且不假思索地执行这些步骤。对于互联网英语数据,我们很可能仍然需要这些数据预处理步骤,但是需要进行适当的修改。
将文本转换为小写
对于情感分析这样的任务,字母大小写有时是一个有用的特性。下列句子
- “我已经通过了驾驶考试”
- “我已经通过了驾驶考试”
- “我已经通过了驾驶考试”
表现出作者不同程度的兴奋。然而,一旦我们将文本转换成小写,它们将变得无法区分。
建议:在我们将文本转换成小写字母之前,设计一些关于字母大小写的特性。
删除标点符号
标点符号和字母大小写一样,对于情感分析非常有用。一个简单的例子是使用连续的感叹号:
- “我已经通过了驾驶考试”
- “我已经通过了驾驶考试!!!!!!!!"
而且,在网络俚语中使用货币符号来表示贪婪和腐败也是相当常见的,比如“ micro$oft ”。
标点符号还能够通过表情符号传达不同的感情,例如:-)和(> _
建议:对不同标点符号的外观进行特征工程,尤其是连续的外观。对于表情符号,我们可以设计新的功能,或者通过使用字典用英语单词替换它们。比如我们可以把:-)换成“笑脸”。最后,互联网俚语将在下面的章节中讨论。
请注意,在对标签、URL 等进行预处理之后,也需要删除标点符号。
删除号码
数字在 NLP 中有一个非常有趣的作用。对于像回答问题这样的任务,数字是绝对重要的。对于命名实体识别,数字并不重要,除非它们是实体名称的一部分(例如 NBA 的76 人,电子竞技的 C9 和 G2 )。对于情感分析,数字通常是无关紧要的。
说了这么多,总有例外需要我们注意。 1984 出现在 politics subreddit 中的不仅仅是一个数字,1–7”传达了巴西球迷的负面情绪。
到目前为止,我们讨论的内容适用于网络英语和标准英语,但网络英语在俚语中的数字用法上有一个额外的复杂性,如“10q”和“2mr”。
建议:数字的用法多种多样,如何预处理没有固定的规则。预处理步骤将在很大程度上取决于数据集的性质和探索性数据分析的结果。俚语将在下一节讨论。
扩展缩写、首字母缩写、首字母缩写和俚语
扩展很容易,因为它只需要查字典。困难的部分是关于维护这本词典。对于网络俚语,我们可以通过像城市词典这样的网站或者仅仅是谷歌来获得它们的意思。然而,许多网络俚语是含有脏话和身体部位的夸张短语的首字母缩写。我们可能想在资料片中缓和一下。比如“lmfao”简单扩展为“笑”。
建议:探索性数据分析时,收集所有非标准英语单词的高频术语。为扩展这些术语创建一个字典,如果需要的话,淡化扩展短语的夸张和/或攻击性。
网络英语的数据预处理步骤
在这一节中,我们将介绍专为网络英语定制的新的数据预处理步骤。他们中的大多数人也为其他语言的网络版本工作。
URL、用户提及和标签
对于大多数任务,URL 是不相关的,可以简单地删除。然而,对于主题模型和主题分类,理解 URL 是关于什么的是至关重要的。合并这些信息的一个简单方法是用标题替换 URL。这可以通过首先执行 HTTP GET,然后解析 HTML 响应来完成。
同样的想法也适用于用户提及和标签。尽管如此,决定我们应该用什么文本来替换要困难得多,而且这个过程将需要大量的人工检查。以 Twitter 中的“@ManCity”为例。它的用户名是“Manchester City ”,但是为了更好地说明这个用户名称的性质,我们可能希望使用“Manchester City Football Club”。
表情符号
表情符号的预处理步骤与表情符号基本相同。例如,我们可以替换😀用“狞笑脸”。不同表情符号的含义可以在表情百科中找到
请注意,有时表情符号被用来代替英文字符。在这种情况下,表情符号的含义可以添加到句子的末尾。作为一个例子,“g⚽al”被转换为“目标足球”。
拼写错误
有不同类型的拼写错误,每一种都需要不同的预处理方法。
- 错别字:这是最简单的一个,因为我们只需要通过拼写检查库运行我们的文本。话虽如此,请记住,没有一个拼写检查库是完美的,我们应该随时准备添加额外的逻辑。
- 重复字符:像“goaaallllllllll”这样的重复字符对于情感分析很有用,值得进行一些特征工程。对于拼写纠正部分,请注意大多数拼写检查库利用了 Levenshtein 距离。因此,重复字符会影响拼写校正的性能。为了解决这个问题,我们可以首先使用正则表达式将重复字符的数量减少到 2(因为标准英语单词最多包含双字符)。然后我们可以应用我们的拼写检查库。
- 其他:用户有无数种方法可以用拼写错误写出有意义的消息,从“哈哈哈哈哈哈哈哈哈”到“G O A L”。一个切实可行的办法是通过探索性的数据分析,找出数据集中最常见的模式,只关注它们。
进一步阅读
- [1]采用深度学习方法处理互联网俚语。它在城市词典的内容上训练了一组单词嵌入,初步的评估结果看起来很有希望。
- tokenizer [2]上的 HuggingFace transformers 文档很好地介绍了这个主题。特别是,它为不同类型的标记器提供了许多示例和参考。如果我们想使用像 BERT 这样的预训练模型,我们必须了解如何预处理我们的数据,以便它能很好地与 BERT 记号化器一起工作。
参考
- 南 Wilson,W. Magdy,B. McGillivray,K. Garimella 和 G. Tyson。俚语自然语言处理应用的城市词典嵌入 (2020 年),LREC 2020 年
- 分词器摘要
如何展示:面向有抱负的分析师
原文:https://towardsdatascience.com/how-to-present-for-aspiring-analysts-c0c0b15555c5?source=collection_archive---------50-----------------------
数据科学/数据分析/教育
思考你在学校里没有学到的关于演讲的知识

来源
在学习市场分析之前,作为一名市场营销专业的学生,演示占据了我所参与的课程的很大一部分。营销战略概述、推销和案例介绍都是我市场营销研究的重要部分。演讲是一项非常重要的技能,就我个人而言,在观众面前演讲从来没有问题。作为一名音乐家,我也在很多观众面前表演过。你会认为关于分析或建模的演示也是一样的,对吗?不幸的是,在专业领域并非如此。
今年夏天,我有机会做了两次关于分析主题的报告,一次是在我的部门面前,另一次是在管理团队面前。现在,虽然我还不是一个全职的专业分析师(希望很快!),这两个演示完全改变了我对分析演示的看法,以及如何接近它们。我想分享我对此的想法,并希望有助于提升你的演示!在这个故事中,我们将分三个阶段进行演示:研究、准备和演示。让我们开始吧!
免责声明:我不是全职的数据专家,我只是简单地转述我在暑期实习和个人实践中的经验。这并不是要告诉你你到底需要知道什么,而是从我的经历中给你一些实用的建议。高级技术信息请查看 走向数据科学 。如果你对一些帮助你演讲的建议感兴趣,请继续阅读!
第一阶段:研究
如果你正在展示某样东西,很有可能你已经得到了一个需要解决的商业问题。这可能是拉动销售数据、分析业绩,甚至是创建机器学习模型之类的事情。无论你遇到什么样的业务问题,在这个阶段,你都应该记住以下几点:
记录您的流程
根据你的听众是谁,你可能会被问到你是如何得出你的数字和结论的。如果你被问到这样的问题,保留一个“数字线索”,这样你就可以展示你的工作,这会给人一种专业和可信的感觉。能够以简洁的方式解释你是如何得到这些数字的,比结结巴巴地解释你是如何得到这些数字要走得更远。这一切都从记录您的流程开始!
创建项目计划
这更多的是一个工作流程/项目管理的话题,但是当涉及到演示的时候也是非常重要的。演示通常是项目的最后阶段之一,因此使用良好的项目管理实践将有助于您按时完成任务。创建一个项目计划,列出资源、工具和带有时间线的里程碑。根据我的经验,数据专业人员喜欢使用 CRISP-DM 和敏捷方法,但是,许多数据专业人员也根据自己的经验创建自己的工作流。无论你使用什么,确保你使用它,这样你就不会让时间从你的展示日溜走。
有应急计划
有些时候,你会对你的演讲有一个完整的计划。你知道你需要分析什么数据,从哪里得到你的数据,你的受众是谁。有时事情的发生会打乱你的计划。当我在做一个演示的时候,我计划在我工作的公司里调查一个人群。就在我准备寄出调查问卷之前,人力资源部门告诉我,这违反了数据保护政策,我不能寄出。我有一个应急计划来调查不同的人群,并能够得到批准,并继续按计划进行。如果我没有制定一个应急计划,我将会有一段更加困难的时间来组织我的演讲。
第二阶段:准备
在我的演示过程中,研究就是将数据转化为信息。在准备阶段,信息被搅拌成见解。理想情况下,你在研究阶段已经完成了你的探索性数据分析和数据清洗,现在你正在建模并得出结论。当您将信息转化为见解时,请记住以下一些想法:
了解你的受众
在准备和演示分析演示文稿时,了解您的受众是需要牢记的最重要的变量之一。商业智能总监理解你展示的信息和见解的方式与营销副总裁不同。永远要事先了解你的听众,因为听众应该是你演讲的核心。如果你还没有读过我之前的一个故事, 数据可视化受众和场景 ,一定要去看看,因为了解你的受众是那个故事的一个突出主题。
保持你的幻灯片简单
今年夏天,我学到的一个重要知识就是如何准备幻灯片。在许多大学,演示软件被认为是艺术。你的幻灯片应该有 50 张幻灯片,每张幻灯片上有两个段落,每张幻灯片上有 6 个可视化效果,对吗?大多数公司都没有。长度取决于你要展示的内容,但目标应该是尽可能使用最少的幻灯片和文字。应该使用可视化效果,但是它们应该占据单个幻灯片的大部分。我们都有过这样的经历,在演示中,我们看到了第一张包含大量内容的幻灯片,然后就一片空白。信息过载会让观众害怕,所以不要试图把它塞进一张幻灯片,而是用幻灯片作为支撑,而不仅仅是整个演示。因此,如果我在谈论销售业绩和提高下一季度销售额的方法,我可能会在一张幻灯片上展示数字,在下一张幻灯片上展示图表,在第三张幻灯片上展示见解。观众不只是想要一个演示,他们想要一个旅程。
“观众不仅仅想要一场演示,他们还想要一段旅程。”
练习真的有帮助
去年夏天,作为实习的一部分,我必须向高管团队和高级副总裁做一次演示。我和另外两个实习生在一个团队。作为一个团队,我们至少练习了 7 到 10 次演示。我将在另一个方面深入探讨这个问题,但是分析性的演示与销售或营销演示是完全不同的。你不能事后批评自己或推销你的数据。如果数字是正确的,那么你应该知道他们是正确的!当你站在一群人面前时,你的信誉和信心会受到威胁,因此,许多人(包括我自己)会自动说“可能”或“应该”。应该不惜一切代价避免这些,实践有助于这一点。有时间的话,练习你的演讲至少五到十次,这样你会对它有信心。如果你感到自信,你的观众也会如此。我们的工作是让我们的受众对我们的数据和见解充满信心,这样他们就能对自己可能直接影响公司的决策充满信心。
第三阶段:演示
现在你已经完成了你的研究并准备好了你的演示文稿,是时候实际演示了。虽然演示可能会令人望而生畏,但这里有一些提示在演示分析性主题时对我有所帮助:
避免填充词
避免使用“喜欢”、“嗯”、“我认为”、“我假设”等词语和短语。现在这是一件很难实施的事情,但是它会提升你的演讲。当你在演讲中紧张地说,“我认为明年的销售额会增加”,这会让你的听众质疑你的可信度。最有可能的是,根据你的数据,你会知道销售会增加还是减少,所以不要说,“我假设明年的销售会增加”,而是说“我预计明年的销售会增加”。这增加了一点自信,让你的观众对你的可信度有信心。
与屏幕互动
演示是一个旅程。如果你想让你的观众注意,你需要引导他们通过你的幻灯片。假设您有一个图表,显示了下一年的营销参与预测。与其坐在那里谈论这些预测,我建议你站起来,走到屏幕附近,在解释你的发现时,指着不同的数据点。这将有助于你的观众理解他们所看到的。如果你记得参观一所你自己一无所知的大学,那可能不是那么愉快。然而,如果你参观一所你一无所知的大学,并有一名导游帮助你,那可能是一次更愉快的经历。在新冠肺炎·疫情期间,这也适用。在 Zoom 或 Skype 会议中,您可以使用鼠标光标模拟亲自指向屏幕。
保持你的解释的相关性
演示时,领域知识和部门知识很重要。如果您正在向其他分析师和数据科学家演示,详细介绍您的回归模型或平均误差可能是可以接受的。如果你要向销售主管做演示,这可能不是正确的方向。例如,我在今年夏天的高管团队演示中使用线性回归作为工具,然后详细讨论了我如何设置回归或者我在 Python 中分配了什么变量,我讨论了变量之间的关系是多么重要。这又回到了了解你的听众,这是你可以在你的演讲中融入的最强有力的概念。
结论
我希望这些建议对你的演讲有所帮助!作为数据专业的学生和专业人士,我们的工作是充当我们世界的导游。与企业的其他部门相比,我们的工作非常独特和不同,但是我们的信息对企业的成功极其重要。把你对数据的热情带到你的演讲中,你的听众会注意到的!保重,注意安全!
看看我的其他一些故事吧!
数据可视化受众和场景
三大技术栈
成功实习的 10 个小技巧
我作为营销分析实习生学到的东西
营销分析实习生的一天
联系我或接收更多内容,在 Twitter 上关注我@BMNAnalytics!
如何在 Python 中呈现多个变量之间的关系
原文:https://towardsdatascience.com/how-to-present-the-relationships-amongst-multiple-variables-in-python-70f1b5693f5?source=collection_archive---------16-----------------------

Jonah Pettrich 在 Unsplash 上的照片
了解如何使用 Python 中的多元图表和绘图来呈现要素之间的关系
处理大型数据集时,了解要素之间的关系非常重要。这是数据分析的一大部分。这些关系可以是两个变量之间的关系,也可以是几个变量之间的关系。在本文中,我将讨论如何用一些简单的技巧来呈现多个变量之间的关系。我将使用 Python 的 Numpy、Pandas、Matplotlib 和 Seaborn 库。
首先,导入必要的包和数据集。
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.read_csv("nhanes_2015_2016.csv")
这个数据集非常大。至少大到不能在这里截图。以下是该数据集中的列。
df.columns
#Output:
Index(['SEQN', 'ALQ101', 'ALQ110', 'ALQ130', 'SMQ020', 'RIAGENDR', 'RIDAGEYR', 'RIDRETH1', 'DMDCITZN', 'DMDEDUC2', 'DMDMARTL', 'DMDHHSIZ', 'WTINT2YR', 'SDMVPSU', 'SDMVSTRA', 'INDFMPIR', 'BPXSY1', 'BPXDI1', 'BPXSY2', 'BPXDI2', 'BMXWT', 'BMXHT', 'BMXBMI', 'BMXLEG', 'BMXARML', 'BMXARMC', 'BMXWAIST', 'HIQ210'], dtype='object')
现在,让我们用几列来缩小数据集。所以,在本文中更容易处理和展示。
df = df[['SMQ020', 'RIAGENDR', 'RIDAGEYR','DMDCITZN',
'DMDEDUC2', 'DMDMARTL', 'DMDHHSIZ','SDMVPSU',
'BPXSY1', 'BPXDI1', 'BPXSY2', 'BPXDI2', 'RIDRETH1']]
df.head()

您可能会觉得列名很奇怪。当我们继续使用它们时,我会继续解释。
- 在这个数据集中,我们有两个收缩压数据(' BPXSY1 ',' BPXSY2 ')和两个舒张压数据(' BPXDI1 ',' BPXDI2 ')。这两者之间是否有关系值得研究。观察第一次和第二次收缩压之间的关系。
为了找出两个变量之间的关系,散点图已经被使用了很长时间。这是看待两个变量之间关系的最流行、最基本、最容易理解的方式。
sns.regplot(x = "BPXSY1", y="BPXSY2", data=df, fit_reg = False, scatter_kws={"alpha": 0.2})

两个收缩压之间的关系是正线性的。在图中观察到许多重叠。
2.为了更好地了解收缩压和舒张压数据及其关系,可以制作一个联合图。Jointplot 同时显示数据的密度和两个变量的分布。
sns.jointplot(x = "BPXSY1", y="BPXSY2", data=df, kind = 'kde')

在该图中,它非常清楚地显示了最密集的区域是从 115 到 135。第一和第二收缩压分布都是右偏的。还有,他们两个都有一些离群值。
3.找出男性和女性人群中第一次和第二次收缩压之间的相关性是否不同。
df["RIAGENDRx"] = df.RIAGENDR.replace({1: "Male", 2: "Female"})
sns.FacetGrid(df, col = "RIAGENDRx").map(plt.scatter, "BPXSY1", "BPXSY2", alpha =0.6).add_legend()

这张图显示,两者的相关性都是正线性的。让我们更清楚地找出相关性。
print(df.loc[df.RIAGENDRx=="Female",["BPXSY1", "BPXSY2"]].dropna().corr())
print(df.loc[df.RIAGENDRx=="Male",["BPXSY1", "BPXSY2"]].dropna().corr())

从上面的两个相关图来看,女性人群中两个收缩压之间的相关性比男性高 1%。如果这些东西对你来说是新的,我鼓励你尝试理解两个舒张压或收缩压和舒张压之间的相关性。
4.人类的行为会随着许多不同的因素而改变,如性别、教育水平、种族、经济状况等等。在这个数据集中,我们还有种族(“RIDRETH1”)信息。检查种族和性别对收缩压之间关系的影响。
sns.FacetGrid(df, col="RIDRETH1", row="RIAGENDRx").map(plt.scatter, "BPXSY1", "BPXSY2", alpha = 0.5).add_legend()

随着种族和性别的不同,相关性似乎会有一点点变化,但通常会像以前一样保持正线性。
5.现在,关注数据集中的其他一些变量。找出教育和婚姻状况之间的关系。
“教育程度”列(“DM deduct 2”)和“婚姻状况”列都是分类的。首先,用有意义的字符串值替换数值。我们还需要去掉那些不会给图表增加有用信息的值。例如,教育栏有一些值“不知道”,婚姻状况栏有一些值“拒绝”。
df["DMDEDUC2x"] = df.DMDEDUC2.replace({1: "<9", 2: "9-11", 3: "HS/GED", 4: "Some college/AA", 5: "College", 7: "Refused", 9: "Don't know"})
df["DMDMARTLx"] = df.DMDMARTL.replace({1: "Married", 2: "Widowed", 3: "Divorced", 4: "Separated", 5: "Never married", 6: "Living w/partner", 77: "Refused"})
db = df.loc[(df.DMDEDUC2x != "Don't know") & (df.DMDMARTLx != "Refused"), :]
最后,我们得到了这个干净的数据框架,可以用于图表了。
x = pd.crosstab(db.DMDEDUC2x, db.DMDMARTLx)
x

这是结果。这些数字看起来很容易理解。但是一张人口比例的图表会是一个更合适的表述。我得到了基于婚姻状况的人口比例。
x.apply(lambda z: z/z.sum(), axis=1)

6.找出按种族(' RIDRETH1 ')和教育水平划分的婚姻状况的人口比例。
首先,将“种族”列中的数值替换为有意义的字符串。我是从疾控中心网站找到这些字符串值的。
db.groupby(["RIDRETH1x", "DMDEDUC2x", "DMDMARTLx"]).size().unstack().fillna(0).apply(lambda x: x/x.sum(), axis=1)

7.观察受教育程度随年龄的差异。
在这里,教育水平是一个分类变量,年龄是一个连续变量。观察教育水平随年龄变化的一个好方法是做一个箱线图。
plt.figure(figsize=(12, 4))
a = sns.boxplot(db.DMDEDUC2x, db.RIDAGEYR)

该图显示,年轻人接受大学教育的比率较高。小提琴情节可能会提供一个更好的画面。
plt.figure(figsize=(12, 4))
a = sns.violinplot(db.DMDEDUC2x, db.RIDAGEYR)

所以,小提琴图显示了一个分布。受过大学教育最多的人在 30 岁左右。与此同时,大多数不到 9 年级的人,大约是 68 到 88 岁。
8.显示按性别分布和隔离的婚姻状况。
fig, ax = plt.subplots(figsize = (12,4))
ax = sns.violinplot(x= "DMDMARTLx", y="RIDAGEYR", hue="RIAGENDRx", data= db, scale="count", split=True, ax=ax)

这里,蓝色表示男性人口分布,橙色表示女性人口分布。只有“从未结过婚”和“与伴侣同居”这两个类别在男性和女性人口中的分布相似。其他类别在男性和女性人口中有显著差异。
我希望它有帮助。请随时在推特上关注我,并喜欢我的脸书页面。
以下是我在本文中使用的数据集:
[## rashida 048/数据集
在 GitHub 上创建一个帐户,为 rashida048/Datasets 开发做出贡献。
github.com](https://github.com/rashida048/Datasets/blob/master/nhanes_2015_2016.csv)
更多阅读:
[## 学习机器学习和深度学习的优质免费课程
顶级大学高质量免费课程的链接
towardsdatascience.com](/great-quality-free-courses-to-learn-machine-learning-and-deep-learning-1029048fd0fc) [## 数据宁滨与熊猫削减或 Qcut 方法
当你在寻找一个范围而不是一个确切的数值,一个等级而不是一个分数
towardsdatascience.com](/sort-and-segment-your-data-into-bins-to-get-sorted-ranges-pandas-cut-and-qcut-7785931bbfde) [## 学习使用 Python 的 Scikit_learn 库通过项目开发 KNN 分类器
适合机器学习新手
towardsdatascience.com](/clear-understanding-of-a-knn-classifier-with-a-project-for-the-beginners-865f56aaf58f) [## Numpy 完全指南
日常工作中需要的所有数字方法
towardsdatascience.com](/a-complete-guide-to-numpy-fb9235fb3e9d) [## Python 中从头开始的多项式回归
学习用一些简单的 python 代码从头开始实现多项式回归
towardsdatascience.com](/polynomial-regression-from-scratch-in-python-1f34a3a5f373) [## Python Matplotlib 的日常备忘单
完整的可视化课程
towardsdatascience.com](/your-everyday-cheatsheet-for-pythons-matplotlib-c03345ca390d) [## 练习数据科学技能和制作优秀投资组合所需的所有数据集
一些有趣的数据集提升你的技能和投资组合
towardsdatascience.com](/all-the-datasets-you-need-to-practice-data-science-skills-and-make-a-great-portfolio-857a348883b5)
如何在您的企业中防止数据篡改
原文:https://towardsdatascience.com/how-to-prevent-data-tampering-in-your-business-7493066ca899?source=collection_archive---------30-----------------------
数据防篡改越来越受到全球安全领导者和企业的关注。

在 Unsplash 上由 Balázs Kétyi 拍摄的照片
谁喜欢别人乱动自己的东西?我们从小就知道,我们的就是我们的,我们不希望别人乱动我们的东西。我们组织的数据也是如此。不要让攻击者破坏它!
组织最重要的资产之一就是这些数据,防止数据被篡改是企业的首要任务之一。
网络攻击每年都在大幅增加。
虽然组织正在解决这些安全问题,但数据真实性仍然是网络安全方面最关键的因素之一。因此,公司现在正在寻找方法来防止数据篡改,并在其组织中实施更好的安全性。
在我们深入研究防止数据篡改的最佳方法之前,让我们来看看它如何影响您的组织,以及为什么您应该关注它。
数据篡改有什么风险?
据英国国家医疗服务系统(NHS)称,他们在 WannaCry 勒索软件攻击中损失了1 亿美元。更令人不安的是,勒索软件等网络攻击往往涉及某种数据篡改。
攻击者插入恶意文件,这些文件会改变网络或系统的配置,修改用户凭据以获得对敏感数据的访问权限,或者篡改日志文件。
想象一下,如果攻击者渗透到您公司的网络中,修改您客户的数据,然后篡改日志文件来掩盖他们的踪迹。
过多久你才会意识到自己已经成为数据篡改的受害者?
您是否能够追踪到攻击者或保护您客户的数据?
攻击者越来越多地使用勒索软件,这是一种恶意软件攻击,黑客在攻击过程中加密组织的数据或系统,并要求赎金来释放解密密钥。
据 Coveware 报道,2019 年最后一个季度,赎金要求的平均金额增至 84116 美元。
虽然建议公司不要向攻击者支付赎金,但此类攻击通常会利用公司的敏感数据,并可能一下子威胁到他们的整个业务。数据篡改会给组织带来深远而严重的后果。
遏制数据篡改造成的损害的两个最重要的步骤是快速检测到您的数据已被修改或篡改,并维护与核心数据分开的数据的良好备份(这样它们就不会被篡改)。显然,企业必须保持警惕,以保护他们的数据免受篡改攻击。
让我们来看看您可以为防止数据篡改做些什么。
如何防止数据篡改?
随着企业定期处理大量数据,防止数据篡改变得十分必要。
以下是防止数据篡改的 5 种有效方法:
1.对静态数据和传输中的数据实施加密
未受保护的数据,无论是静态的还是传输中的,都会使组织容易受到数据篡改和其他网络攻击。保护静态数据和传输中数据的最有效方法之一是加密。
简而言之,数据加密是将数据从一种形式转换为另一种形式的过程,未经授权的用户无法解密。
数据加密如何防止数据篡改攻击?
例如,您将客户的信用卡详细信息存储在数据库中,因此通过加密静态数据,您实际上是将客户的敏感数据转换为加密格式,没有解密密钥就无法解码或读取。
虽然攻击者可能能够篡改加密数据,但他们无法以有意义的方式篡改数据。例如,他们不能改变从史蒂夫->乔到史蒂夫->攻击者的转移。
为了保护静态数据,您可以在存储敏感数据之前对其进行加密,或者对存储驱动器本身进行加密。对于传输中的加密数据,您可以使用加密连接,如 SSL、TLS、HTTPS、FTPS 等。
要进一步加强您的数据加密,请分配基于角色的控制,以确保只有授权用户才能访问加密数据。此外,您还可以实施多因素身份认证来提高安全性。
2.写入时复制文件系统
写时复制,通常被称为 COW,是一个用于在数据库服务器上维护即时快照的概念。它还有助于防止数据篡改。
每次修改数据库时,都会拍摄增量快照。安全团队可以通过监控快照和检查意外的文件系统快照来检测数据篡改。
许多数据库应用程序和操作系统(如 Linux、Unix)都有内置的快照功能。这使得企业很容易集成 COW 或任何其他类似的技术,并随时更新数据库修改。
COW 还有助于保护数据免受潜在的网络攻击,如基于勒索软件的加密攻击。因此,将文件系统恢复到攻击前的状态(数据处于原始状态)、恢复丢失的数据以及消除任何停机变得更加容易。
3.使用 HMACs 的数据完整性
基于哈希的消息认证码(HMAC)是一种消息认证码(MAC ),由加密哈希函数和加密密钥组成。
基本上,HMAC 是一种对消息/文件进行签名的方式,因此如果数据被篡改,很容易检测到,然后您就知道不要相信被篡改的数据。
HMAC 是如何防止数据篡改的?
当两方或多方通过安全文件传输协议交换数据时,数据会附带 HMACs,而不仅仅是普通的哈希。这项技术由共享密钥和散列函数组成。
对消息进行哈希处理,然后用共享密钥对其进行签名。共享密钥有助于交换方确保数据的真实性。因此,提供了一种方法来验证他们接收的数据和 HMAC 是否真的来自授权的、预期的发送者,并且消息没有被改变。
4.文件完整性监控(FIM)
文件完整性监控是一种强大的安全技术,可以保护业务数据和 IT 基础设施免受已知和未知威胁的侵害。FIM 是监控文件以检查是否有任何更改的过程。
这项技术如何帮助防止数据篡改?
它评估系统文件并生成一个加密校验和作为基线。然后,FIM 反复重新计算相同资源的校验和,将其与基线进行比较,如果检测到更改,它将生成安全警报。
FIM 系统通常会监控用户凭据、权限、身份、操作系统、配置文件、应用程序文件和加密密钥存储。
FIM 系统是资源密集型的,尤其是在处理大量数据和频繁变化的数据时。也就是说,监控更容易受到网络攻击的文件或机密文件至关重要,这样才能有效地投入资源。
5.WORM 系统(一次写入多次读取)
一写多读(WORM)系统指的是一种存储技术,其中数据一旦写入就不能被覆盖或修改。这项技术长期以来一直用于大型企业和政府机构的存档目的。
WORM 系统提供长期存储策略,确保用户不会意外或故意擦除或修改数据。这项技术提供了虚拟保护,防止数据被擦除。
即使在最好的情况下,破坏 WORM 系统上的数据也是很困难的,但是如果一个具有高度技术知识的专家可以不受限制地访问操作系统的最深层,并获得访问 WORM 驱动器的权限,那么破坏数据还是有可能的。
为了确保您的 WORM 系统得到很好的保护,请实施用户访问控制,例如最低权限模型,该模型只允许用户访问他们执行工作所需的内容。
外卖食品
数据篡改是一个新出现的网络安全问题,对一个组织来说可能是毁灭性的。
虽然数据篡改的影响因受损数据的业务价值而异,但它更有可能给企业带来严重损害。
防止数据篡改可以包括简单的安全措施,如数据加密,也可以包括一些措施,如使用文件完整性监控(FIM)系统来提高安全性。
最终,哪种解决方案最适合您来保护您的数据免受潜在威胁,这取决于您的组织需求。
我们可以帮助您运行安全审计,以确保您的组织免受数据篡改攻击,并帮助您实施一个可靠、强大的安全模型。
关于作者:
Steve Kosten 是 Cypress Data Defense 的首席安全顾问,也是“Java/JEE 中的 SANS DEV541 安全编码:开发可防御应用程序”课程的讲师。
如何使用 Big Query & Data Studio 在 Google Cloud 上处理和可视化财务数据
原文:https://towardsdatascience.com/how-to-process-and-visualize-financial-data-on-google-cloud-with-big-query-data-studio-f37c2417d4ef?source=collection_archive---------35-----------------------
GCP 从业者从金融数据开始的教程

卢卡斯·布拉塞克在 Unsplash 上的照片
介绍
本文将向您展示使用 Google 云平台的 BigQuery 处理股票价格数据的一种方法,并使用 Google Data Studio 在处理后的数据上构建一个简单的仪表板。
学习这样做对于任何希望自动从股票价格洞察中发现结果,并且正在寻找一种高效快速的方法将整个过程存储在云平台上的人来说都是非常有用的。
这篇文章是上一篇文章的延续,或者说是“第二部分”,在上一篇文章中,我展示了如何使用 API 和 Google Cloud用 Python 自动收集金融数据。 如果您对这个工作流的上游数据导入和脚本自动化方面感兴趣,请随意阅读。如果没有,就跳过并继续阅读。
步骤 1:识别 BigQuery 的数据源
Google big query是 GoogleCloud 的数据仓库解决方案(众多解决方案中的一个),非常适合处理本教程中的关系数据。
在第 1 部分中,我展示了如何使用云函数将数据自动送入 BigQuery。在下一步中,您将使用相同的数据源(来自 S & P500 公司的每日股票价格数据,以及相关的映射表,这将允许我们使用一些分类变量来丰富数据)来构建简单的& neat 处理和数据可视化管道。
注意:下面的截图将取自我自己的 GCP 控制台(我已经将意大利语设置为默认语言)。我已经记录了每个带有解释的截图,这样每个人都可以用英语理解。
首先,一旦登录到 BigQuery 的编辑器,并且假设您已经设置了数据集,您可以通过简单地点击编辑器页面左侧的“Resources”选项卡来识别上传的数据源。

作者截图
这允许您立即获得数据集列表以及每个数据集中包含的表。
对于这个练习,我的数据仓库结构如下(我将忽略上面截图中报告的 USA_SectorViews 表):
数据集:CSM
表格:
- sp components:标识标准普尔 500 成员公司完整列表的表格(来源:标准普尔 500 公司列表)
该表中的大多数列与上面的源链接中报告的完全相同,因此您可以直接使用该网页作为参考。

SPComponents 表中的快照
②。历史 : 包含从 2000 年到 2020 年 6 月所有标准普尔 500 指数成员公司每日股票价格信息的表格。

SPhistorical 表的快照,包含所有列出的列
步骤 2:计算股票指标,并在保存的 SQL 查询中合并分类变量
使用上面的两个表,让我们使用 BigQuery 的 SQL 编辑器处理数据,以导出一个包含股票价格指标和分类变量的综合表。
出于本示例的目的,最终输出表将以下列为特征:
时间戳 :每行和每只股票的日期键
符号 :每个 S & P500 公司的股票标识符
【GICS】_ Sector:列表示各公司所属的行业(医疗保健、消费等..)
总部:各事务所总部所在地
百分比 _ 每日 _ 回报: 每只股票的每日回报(基于收盘价)
MA_5_days: 股票前 5 天的移动平均线,期间的参照是当前行的日期。基于接近的价格。
MA_10_days: 股票前 10 天的移动平均线,其中期间的参照是当前行的日期。基于接近的价格。
MA_15_days: 股票前 15 天的移动平均线,期间参照为当前行的日期。基于接近的价格。
计算移动平均线的周期选择没有内在原因,只是为了走查而计算的。你绝对可以在网上了解更多关于均线的知识,因为有很多 有价值的教程 。
使用我们的两个表,您可以看到您有大多数列 (时间戳,【GICS】_ 扇区,总部)* 已经准备就绪。*
使用 历史 表中的收盘价格列,您可以计算剩余的列(Percentage_Daily_Returns 和股票在 5–10–15 天期间的移动平均值)。
首先,让我们计算一下每只股票的日收益率。股票回报的计算方法是任意两天的收盘价之差,用前一天收盘价的百分比表示。
*ROUND(((CAST(Close AS float64)-CAST(LAG(Close,1) OVER(PARTITION BY p.Symbol ORDER BY Timestamp) AS float64))/CAST(Close AS float64))*100,2) AS Percentage_Daily_Return*
您可以使用 LAG 函数来识别前一天的收盘(仅针对每个股票代码,因为您不想根据不同的股票价格计算收益;因此使用OVER(PARTITION BY Symbol)),取其与当天的收盘之差,除以当天的收盘价格来计算收益。
这是计算的本质。然后,您可以使用 CAST 函数将文本数据类型转换为浮点数,以便能够对数字进行加法和除法运算,而 ROUND 函数将返回两位小数。
如果你的数据类型已经是正确的,你可以避免使用 CAST 函数..)
股票在 5 天内的移动平均线计算如下:
*AVG(CAST(Close AS float64)) OVER (PARTITION BY p.Symbol ORDER BY Timestamp ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) AS MA_5day*
您可以使用 AVG 函数来计算每个不同符号的收盘价格的平均值,考虑由当天收盘和组成 5 天时间段的前 4 天组成的行窗口。
同样的逻辑在 10 天和 15 天内重复。
*AVG(CAST(Close AS float64)) OVER (PARTITION BY p.Symbol ORDER BY Timestamp ROWS BETWEEN 9 PRECEDING AND CURRENT ROW) AS MA_10daysAVG(CAST(Close AS float64)) OVER (PARTITION BY p.Symbol ORDER BY Timestamp ROWS BETWEEN 14 PRECEDING AND CURRENT ROW) AS MA_15days*
将所有内容放在一起,您将获得以下 SQL 查询:

作者截图
总之,该查询从 SPhistorical (别名为" p ")和 SPcomponent s 表(别名为" c ")中提取。使用相互的符号列作为键来连接这两个表。
我使用 SPhistorical 表作为两者之间的主要参考表。因此我定义了一个左连接,通过它我从 SPcomponents 带来我感兴趣的分类变量( GICS_Sector &总部)。
**时间戳、符号、每日收盘均从 p 拉取。分类变量GICS _ 部门和总部从 c 中提取。在每日收盘时,将进行上述计算。
然后,该表按相关变量分组,并按符号和时间戳排序。您启动查询,等待 BigQuery 进行计算和执行,并在不久后获得结果。

作者截图
然后,您可以优化您的查询,计算新的指标,并尽可能多次地重新运行,以获得您想要的输出。另外,不要忘记通过点击“执行”按钮旁边的“保存查询”按钮,将您的查询保存为“已保存查询”。点击查看更多信息。
完成后,您就可以将查询结果用作 Data Studio 仪表板的数据源层了。
步骤 3:从 Data Studio 中,连接到保存的查询并将数据拖到仪表板上
选项 1:
你现在可以跳到你的数据工作室账户上,点击加号开始一个新的报告。

作者截图
在这里,您可以选择各种数据连接器:

作者截图
选择 BigQuery 后,您只需点击导入个性化查询并粘贴到我们在第 3 步构建的已保存查询中。完成后,点击添加。

作者截图
假设您已连接,数据将被提取,然后您将看到一个空白的报告视图,您可以从该视图开始构建您的仪表板。注意如何选择 BigQuery 作为我的数据源。

作者截图
选项 2:
在 BigQuery 内,你可以点击“探索数据”>“用 Data Studio 探索”。

作者截图
单击此处,将弹出一个 Data Studio 数据探索窗格,您将能够开始绘制和可视化数据。这对于进行快速分析和获得查询结果的直观感觉特别有用。

作者截图
第 4 步:使用 Google Data Studio 探索数据
在这一步,如果您的最终目标是构建一个完整的仪表板或可视化报告,您可能更喜欢选择选项 1。
我还会选择这个选项,以便在探索数据时获得更多的灵活性( space exploration 功能在撰写本文时仍处于测试版本)。
为了更深入地了解数据并概述 Data Studio 的功能,我将回答以下问题:
1)2020 年标准普尔 500 指数由哪些主要行业组成?
2)这些公司在地理上是如何分布的(就总部基地而言)?
*3)历史上 间谍 表现如何?
对于间谍来说,移动平均线的最新趋势如何?
*跟踪整个 S&P500 的指数基金。在第 1 部分中,除了每个 S & P500 个体成员之外,我还包括了间谍,我将在这里使用它
总的来说,Data Studio 相当简单地充当了一个直观的拖放界面,用户可以在不同的图表类型中进行选择,并根据自己处理的数据对它们进行样式/格式设置。
在 这个 链接,你还可以参考一个很棒的指南,它非常详细地说明了它们的整个界面。
现在让我们看看不同的图表类型如何帮助回答上述问题。
1)2020 年构成 S & P500 的主要行业板块有哪些?
为了解决第一个问题,饼图似乎是一个不错的选择。有关在 Data Studio 上向空白报告添加图表的详细信息,请参考本快速指南 e。

作者截图
S&P500 在各产业部门之间很平衡。按流行程度排列的前三名是工业、信息技术和金融,约占总数的 13-14%。
这些公司在地理上是如何分布的(就总部而言)?

作者截图
就总部所在地而言,正如所料,我们可以看到美国公司占主导地位,也有一些欧洲公司。使用地图时,您可以充分利用工具栏进行放大和缩小,进入全屏模式,以及整体调整地图视图。
*间谍 历史表现如何?

接下来,我用折线图绘制了这些年来的每日收盘图,以了解其趋势。
从长远来看,间谍的价值从 150 到 300+左右,稳定增长。
对于间谍来说,移动平均线的最新趋势如何?
然后我画出最近 5/10/15 日的移动平均线,看它们如何相互叠加。在为这三个指标选择了相似的时间尺度后,您可以看到,总体而言,它们倾向于非常紧密地相互跟踪,15 天周期的平均值显示了围绕总体趋势线的更多可变性。

计算移动平均线的周期选择没有内在原因,只是为了绘制而进行计算。你肯定可以在网上了解更多关于均线的知识,因为有很多 有价值的教程 。
将所有内容放在一起,您可以为您的报告添加标题,并获得类似于以下内容的内容:

作者截图
这允许您获得您感兴趣的数据和指标的完整快照。
正如您所看到的,Data Studio 使用起来非常简单,并且提供了很好的数据连接器和交互性。
后续步骤
您的工作流程正式建立。您可以保存所有的 BigQuery SQL 查询和 Data Studio 报告,并在新数据到来时刷新/扩展资源。
我希望给你看了一些有用的东西。你可以使用 GCP 的免费账户开始用你自己的数据构建你的谷歌云解决方案。
非常感谢您的阅读!
访问我的免费数据科学资源清单 这里
* [## 通过我的推荐链接加入 Medium-Edoardo Romani
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
edo-romani1.medium.com](https://edo-romani1.medium.com/membership)*
如何在 5 分钟内制作一个 DeepFake 视频
原文:https://towardsdatascience.com/how-to-produce-a-deepfake-video-in-5-minutes-513984fd24b6?source=collection_archive---------1-----------------------
每个人都可以不用写一行代码就能制作 DeepFakes。

克里斯蒂安·格滕巴赫在 Unsplash 上拍摄的照片
你跳舞吗?你有没有最喜欢的舞者或表演者,你希望看到自己模仿他们的动作?现在你可以了!
想象一下你有一张全身照。只是一个静止的图像。然后你所需要的就是你最喜欢的舞者表演一些动作的独舞视频。现在没那么难了,因为抖音正在接管世界…
图像动画使用视频序列来驱动图片中对象的运动。在这个故事中,我们看到图像动画技术现在是多么的简单易用,以及你是如何制作出你能想到的任何东西。为此,我将相关出版物的源代码转换成一个简单的脚本,创建了一个任何人都可以用来生成 DeepFakes 的瘦包装器。有了源图像和正确的驾驶视频,一切皆有可能。
学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!
它是如何工作的
在这篇文章中,我们谈论一个新的出版物(2019),部分神经信息处理系统进展 32 (NIPS 2019) ,称为“图像动画的一阶运动模型”【1】。在这篇论文中,作者 Aliaksandr Siarohin、Stéphane Lathuilière、Sergey Tulyakov、Elisa Ricci 和 Nicu Sebe 提出了一种在给定驾驶视频的情况下对源图像进行动画制作的新方法,而无需关于要动画制作的对象的任何附加信息或注释。
在引擎盖下,他们使用一个经过训练的神经网络来重建视频,给定一个源帧(静止图像)和视频中运动的潜在表示,这是在训练过程中学习的。在测试时,该模型将一幅新的源图像和一段驾驶视频(例如一系列帧)作为输入,并根据这些帧中描述的运动预测源图像中的对象如何移动。
该模型追踪动画中所有有趣的东西:头部运动、说话、眼球追踪甚至身体动作。例如,让我们看看下面的 GIF:特朗普总统驾驶《权力的游戏》的演员像他一样说话和移动。

方法和途径
在创建我们自己的序列之前,让我们进一步探索这种方法。首先,训练数据集是大量视频的集合。在训练期间,作者从同一视频中提取帧对,并将它们馈送给模型。该模型试图通过某种方式学习这些对中的关键点以及如何表示它们之间的运动来重建视频。

图 1 —框架架构(A. Siarohin 等人,NeurIPS 2019)
为此,该框架包括两个模型:运动估计器和视频生成器。最初,运动估计器试图学习视频中运动的潜在表示。这被编码为特定于运动的关键点位移(其中关键点可以是眼睛或嘴的位置)和局部仿射变换。这种组合可以模拟更大的变换族,而不是仅使用关键点位移。模型的输出是双重的:一个密集的运动场和一个遮挡掩模。该遮罩定义了驾驶视频的哪些部分可以通过扭曲源图像来重建,以及哪些部分应该由上下文来推断,因为它们不存在于源图像中(例如,头部的后面)。例如,看看下面的时尚 GIF。每个模型的背面在源图片中不存在,因此,应该由模型来推断。

接下来,视频生成器将运动检测器的输出和源图像作为输入,并根据驱动视频将其动画化;它以类似于驾驶视频的方式扭曲源图像,并保留被遮挡的部分。图 1 描述了框架架构。
代码示例
本文的源代码在 GitHub 上。我所做的是创建一个简单的外壳脚本,一个薄的包装器,它利用源代码,每个人都可以很容易地使用它进行快速实验。
要使用它,首先,您需要安装模块。运行pip install deep-animator在您的环境中安装库。那么,我们需要四样东西:
- 模型权重;当然,我们不希望从零开始训练模型。因此,我们需要权重来加载预训练的模型。
- 我们模型的 YAML 配置文件。
- 源图像;例如,这可以是一幅肖像。
- 一段驾驶视频;最好先下载一个面部清晰可见的视频。
为了快速获得一些结果并测试算法的性能,您可以使用这个源图像和这个驾驶视频。型号重量可在这里找到。下面给出了一个简单的 YAML 配置文件。打开一个文本编辑器,复制并粘贴以下行,并将其保存为conf.yml。
model_params:
common_params:
num_kp: 10
num_channels: 3
estimate_jacobian: True
kp_detector_params:
temperature: 0.1
block_expansion: 32
max_features: 1024
scale_factor: 0.25
num_blocks: 5
generator_params:
block_expansion: 64
max_features: 512
num_down_blocks: 2
num_bottleneck_blocks: 6
estimate_occlusion_map: True
dense_motion_params:
block_expansion: 64
max_features: 1024
num_blocks: 5
scale_factor: 0.25
discriminator_params:
scales: [1]
block_expansion: 32
max_features: 512
num_blocks: 4
现在,我们已经准备好做一个模仿莱昂纳多·迪卡普里奥的雕像了!要获得结果,只需运行以下命令。
deep_animate <path_to_the_source_image> <path_to_the_driving_video> <path_to_yaml_conf> <path_to_model_weights>
例如,如果您已经将所有东西都下载到了同一个文件夹中,cd到那个文件夹并运行:
deep_animate 00.png 00.mp4 conf.yml deep_animator_model.pth.tar
在我的 CPU 上,大约需要五分钟才能得到生成的视频。除非--dest选项另有规定,否则该文件将保存在同一文件夹中。此外,您可以通过--device cuda选项使用 GPU 加速。终于,我们准备好看到结果了。相当牛逼!

结论
在这个故事中,我们介绍了 A. Siarohin 等人所做的工作,以及如何使用它来不费吹灰之力获得巨大的成果。最后,我们用一个薄薄的包装纸deep-animator制作了一个雕像。
虽然对这种技术有一些担忧,但它可以有各种各样的应用,也显示了如今制作假新闻是多么容易,提高了人们对它的认识。
学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!
关于作者
我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。
如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请关注我的 Medium 、 LinkedIn 或 Twitter 上的 @james2pl 。
所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。此外,请访问我的网站上的资源页面,这里有很多好书和顶级课程,开始构建您自己的数据科学课程吧!
参考
[1] A. Siarohin,S. Lathuilière,S. Tulyakov,E. Ricci 和 N. Sebe,“图像动画的一阶运动模型”,神经信息处理系统会议(NeurIPS),2019 年 12 月。
如何在 Jupyter 环境下生成交互式 Matplotlib 图
原文:https://towardsdatascience.com/how-to-produce-interactive-matplotlib-plots-in-jupyter-environment-1e4329d71651?source=collection_archive---------0-----------------------
使用所有使用 Matplotlib 的 Python 库创建交互式绘图/地图

用 Canva 创建的图像
Matplotlib 是非常强大的可视化库,是许多其他 python 库的默认后端,包括 Pandas、Geopandas 和 Seaborn 等等。
今天,有不同的选项来启用 Matplotlib 绘图的交互性。然而,新的本地 Matplotlib/Jupyter 交互小部件为所有使用 Matplotlib 的第三方包提供了更广泛的用途和好处。
这项技术建立在 Matplotlib 和 Widgets 之上,允许您在没有第三方库的情况下进行交互式绘图。唯一的要求是安装 Ipympl,所有的交互性扩展都可以在您的 Jupiter 笔记本环境中获得。
在本教程中,我将介绍一些使用 ipympl 的 Matplotlib 交互式数据可视化的用例及示例。我们将首先介绍 ipympl 的基础知识,它的画布和一些例子。
利用 Jupyter interactive widgets 框架, IPYMPL 在 Jupyter 笔记本和 JupyterLab 中启用 matplotlib 的交互特性。
Jupyter 实验室的 IPYMPL
要启用交互式可视化后端,您只需使用 Jupyter magic 命令:
%matplotlib widget
现在,让我们设想一个 matplotlib 图。我们首先用 Pandas 读取数据,并用 Matplotlib 创建散点图。
url =df = pd.read_csv(
“[https://raw.githubusercontent.com/plotly/datasets/master/tips.csv](https://raw.githubusercontent.com/plotly/datasets/master/tips.csv)”
)# Matplotlib Scatter Plot
plt.scatter(‘total_bill’, ‘tip’,data=df)
plt.xlabel(‘Total Bill’)
plt.ylabel(‘Tip’)
plt.show()
没有额外的代码,只使用简单的 matplotlib 代码,输出是一个交互式的绘图,您可以放大/缩小,平移并重置为原始视图。下面的 GIF 图像显示了 ipympl 可能的交互性。

使用 Ipympl 的 Maptlotlib 交互式绘图
此外,您还可以定制用户界面的可见性、画布页脚和画布大小。
fig.canvas.toolbar_visible = **False**
fig.canvas.header_visible = **False** fig.canvas.resizable = **True**
这些命令改变 Ipympl 和 Matplotlib 图的用户界面。按钮将从用户界面上消失,但您仍然可以使用这些功能。要恢复到通常的 matplotlib 图,可以内联调用 matplotlib:
%matplotlib inline
让我们转向与熊猫互动的情节。
互动熊猫情节
熊猫图建立在 Matplotlib 之上;因此,我们也可以使用 Ipympl 创建交互式熊猫情节。让我们用熊猫做一个简单的线图。
df.plot(kind=”line”)
瞧,我们有一个与熊猫互动的情节。这个线图很密集,有了这个交互功能,我们可以放大到特定的地方,与图进行交互。见下图 GIF。

互动熊猫情节与 Ipympl
请注意,熊猫已经有一些交互式后端选项,包括 Plotly 和 Bokeh。然而,这并没有扩展到构建在 Pandas 之上的其他库。Geopandas 就是这样一个库,多亏了 Ipympl,它获得了第一批交互式地图。
带有 Geopandas 的交互式地图
如果您在 Pandas 中使用过地理空间数据,那么您应该已经知道 Geopandas,它在地理空间数据科学领域得到了广泛的应用。带有 Geopandas 的交互式地图改变了游戏规则。虽然 pandas 有其他后端选项来使其情节互动,但这在 Geopandas 上是不可能的。
由于 Geopandas 也构建在 Maptlotlib 之上,因此 Ipympl 的交互式后端也扩展到了它。我们现在可以在 Geopandas 中拥有交互式地图,而无需使用任何其他第三方地理可视化库。
让我们看一个由 Ipympl 支持的 Geopandas 交互式地图的例子。我将首先使用 Pandas 读取数据,因为我们使用 CSV 文件并将其转换为 Geopandas 地理数据框架。
carshare = “[https://raw.githubusercontent.com/plotly/datasets/master/carshare.csv](https://raw.githubusercontent.com/plotly/datasets/master/carshare.csv)"
df_carshare = pd.read_csv(carshare)gdf = gpd.GeoDataFrame(df_carshare, geometry=gpd.points_from_xy(df_carshare.centroid_lon, df_carshare.centroid_lat), crs=”EPSG:4326")
我们现在可以使用 Geopandas 绘制任何地理空间数据。我们可以直接打电话。plot()以可视化地图。然而,在这个例子中,我还添加了一个用于上下文目的的底图。
import contextily as ctx
fig, ax = plt.subplots()
gdf.to_crs(epsg=3857).plot(ax=ax, color=”red”, edgecolor=”white”)
ctx.add_basemap(ax, url=ctx.providers.CartoDB.Positron)
plt.title(“Car Share”, fontsize=30, fontname=”Palatino Linotype”, color=”grey”)
ax.axis(“off”)
plt.show()
我们有一个互动地图,上面有 Geopandas。我们可以放大缩小和平移地图。太棒了。

使用 Ipympl 的交互式 Geopandas 地图
我每天都使用 Geoapndas,所以这是一个没有太多障碍的巨大补充。您仍然可以使用 Geopandas 并拥有交互式地图,而无需使用其他第三方包。
结论
在本教程中,我们介绍了一种使用 Ipympl 通过 Maptlotlib 启用交互式绘图的简单方便的方法。我们已经看到了如何使用 Matplotlib、Pandas 和 Geopandas 创建交互式绘图。
要使用 Ipympl 的交互功能,您可以使用 Conda/ pip 安装它:
conda install -c conda-forge ipympl
pip install ipympl
如果使用的是 jupyterLab,还需要安装 node js 和 Jupyter Lab 扩展管理器。
conda install -c conda-forge nodejsjupyter labextension install @jupyter-widgets/jupyterlab-manager
jupyter lab build
如何利用 MLOps 自动化更快地将 ML 产品化
原文:https://towardsdatascience.com/how-to-productize-ml-faster-with-mlops-automation-d3f25caf38c4?source=collection_archive---------25-----------------------

来源 shutterstock
在我们最近在两周一次的 MLOps Live 网络研讨会系列中进行的一项调查中,数百名与会者证实了数据科学团队正在努力应对的头号挑战——将机器学习引入生产。这一点得到了 Gartner research 的证实,该公司一直认为将人工智能产品化是当今人工智能实践中最大的挑战之一。许多人工智能项目,根据研究超过 80% ,陷入实验室,产生部分成功,或者消耗远多于最初计划的资源和时间。找到更快、更简单的方法将机器学习项目产品化是必不可少的,这样它们才能对业务产生影响。
抛开政治和组织方面的挑战不谈,主要障碍是数据科学团队通常在孤岛中工作,与工程和 DevOps 团队分离,并使用手动开发流程(也称为“jumbo”Jupyterplaygrounds),然后需要手动转换为生产就绪的 ML 管道。这需要 ML 工程师、数据工程师、DevOps 和开发人员的独立团队投入额外的时间和资源,通常远远超过最初的预期。每当数据准备或模型训练逻辑发生变化时,整个循环都会重复。
人工智能服务和应用开始成为任何业务的重要组成部分。伴随着这种趋势而来的是责任,这进一步增加了复杂性。需要添加数据、代码和实验跟踪,监控模型以检测概念漂移,通过使用 AutoML 技术和集成提高模型准确性,等等。
目前占主导地位的以研究为导向的数据科学方法在这种环境下不再流行。数据科学必须采用具有微服务、持续集成 (CI)、持续部署 (CD)、代码版本化(Git)和配置/元数据版本化(GitOps)的敏捷软件开发实践。
当我与数据科学团队领导交谈时,他们都同意这种方法,但在实施方面存在困难。毕竟,数据科学家不是软件开发人员或 ML 工程师,反之亦然,这是有原因的。我们需要自动化流程的方法,并弥合软件和数据科学实践之间的差距。这就是一些新的开源工具可以派上用场的地方,我将演示这一点。
在这篇文章中,我将建议并展示如何加速 ML 的可操作性并减少摩擦。
各个击破
你有没有尝试过将数据科学笔记本或一个 Kaggle 项目转化为可以在生产中运行的东西?祝你好运。典型的项目包括 XXL 笔记本,从数据收集、数据准备、特征分析、制图、培训、验证等开始。
您通常会发现相同的模板和助手函数在多个笔记本中重复,代码没有在函数中组织,异常很少被处理,等等。如果您尝试对笔记本进行版本控制,很难发现版本之间的差异,更不用说尝试查看和评论拉取请求了。
我们需要采取的第一步是将我们的项目分解成功能(例如数据探索、培训等。)和定义良好并记录在案的 API。如果这些函数是共享的,我们应该把它们放在一个单独的 Python 或 notebook 文件中。当我们定义 API 时,调试、跟踪和理解代码变得更加容易,我们可以测试单个的功能,或者将它们作为更大流程的一部分。将单个功能或步骤重构为微服务要比重构整个项目笔记本简单得多。稍后我将展示如何实现自动化。
从实验到生产,没有任何麻烦
既然我们已经将数据科学代码和工作流分解为一组独立的功能,我们需要找到一种方法来运行这些功能,同时考虑生产或规模,并满足以下要求:
- 使其可部署(用所需的包、Kubernetes 运行时规范等构建 docker 映像。)
- 增加健壮性和故障处理
- 使用参数、结果、数据和元数据跟踪执行情况
- 针对性能进行优化,支持针对要求苛刻的工作负载或更大的数据集进行扩展
- 实施:支持日志记录、监控、强化安全等。
这通常是开发人员、数据和 ML 工程师团队重构代码并为生产做好准备的地方,这意味着添加更多的资源并显著延迟该过程。在团队各自为政的组织中,这是极其困难的,并且会导致许多数据科学计划中途被放弃。
另一种方法是跨团队协作,通过自动化从代码到产品的迁移以及我们跟踪执行和数据的方式,最大限度地减少人工工作。
我们希望利用我们的数据科学功能,自动构建和部署它们,根据实际使用情况扩展它们,并以最少的工作量监控它们的所有输入和输出。这在今天已经用“无服务器”技术实现了,我们只需要让它适应独特的数据科学问题和开发实践。
一个名为 MLRun (由我的公司 Iguazio 发起)的新开源框架与其他工具结合使用,如 Nuclio (无服务器引擎)和 Kubeflow pipelines (管道编排),以自动化 MLOps 流程,并将 CI/CD + Git 实践引入数据科学。这项技术的早期采用者报告说,他们将整体交付时间从几个月缩短到几周,显著减少了计算资源和劳动力,现在他们终于可以完全了解所有的实验和数据。
MLRun 提供 SDK 和 Kubernetes 服务。SDK 可以在任何地方使用(在你的代码 IDE、Jupyter 笔记本、像 Google Colab 或 AWS Sagemaker 这样的托管笔记本服务、生产容器等等。).它可以自动跟踪你所有的功能活动,输入和输出。它处理各种函数之间的参数和数据传递,它可以使用一个命令将您的本地代码转换为分布式函数或完整的 ML 管道。(详见 mlrun 文档)
MLRun 服务记录来自所有客户端的跟踪信息,基于所提供的代码+元数据自动提供“无服务器”功能,通过编排 Kubeflow 管道端到端管理工作流,并提供基于 web 的 UI,用于端到端管理正在运行的作业/实验、功能和工件。

从代码到可重用微服务(图片由作者提供)
您可以查看这个笔记本来了解一个函数是如何在 Jupyter 中编写和记录的,以及如何通过一个命令将它转换成一个无服务器的函数(微服务)对象,该对象可以发布到 Git 或在可重用函数市场中编目。

功能代码(图片由作者提供)
该笔记本还演示了如何从存储库/市场加载功能,并使用以下三种方式之一来执行任务:1 .作为本地可执行文件,2。作为一个自动扩展的容器化微服务,3。作为内存模块。执行及其元数据、输入和输出被自动跟踪。

MLRun 实验跟踪(图片由作者提供)
在其他示例中,您可以看到如何使用受支持的分布式运行时引擎之一(Nuclio、Dask、Spark、Horovod over MPI)横向扩展计算、管理模型、管理完整的项目以及提供按需资源或 GPU 分配(在我的 GPU 即服务博客中有详细介绍)。
这些功能是原子的(代码+所有的运行时定义),版本化的,文档化的,这使得它们高度可重用。开发人员可以对功能进行扩展/增强,或者直接使用它们。这可以大大加快开发时间,并且您可以查看和重用一系列适用于不同数据科学阶段和算法的有用的预烤函数。
查看我的视频,它展示了我们如何自动将笔记本代码转换为可扩展的、自动跟踪的微服务:
自动化 ML 管道
我们的数据科学管道需要的不仅仅是一个功能。我们需要接收和准备数据,选择主要特性,训练我们的模型,验证它,部署它,等等。我们需要组装一个管道(工作流)——我们为此使用 Kubeflow 管道——并让 MLRun 组合、执行和跟踪我们的管道。

从 ML 函数构建自动化工作流(图片由作者提供)
你可以看到这个例子,它展示了一个由笔记本和市场功能组成的完整的 ML 管道。管道接收数据,通过 AutoML、验证、模型部署和生产测试运行功能分析培训。可以通过命令行或 SDK 手动触发管道,也可以通过 Git 事件(如 pull 请求注释)触发管道。基于 Git 的 MLOps 自动化将在我的下一篇博客文章中详细讨论。
如果我们想要跟踪我们的管道结果,我们可以使用 MLRun UI,或者简单地将结果摘要作为注释推送到我们的 slack 通道或 Git pull 请求中。

获取时差通知(作者图片)
摘要
通过采用敏捷、CI/CD 和无服务器实践,数据科学和 MLOps 任务可以以节省大量时间和资源的方式实现自动化。MLRun 项目是一个新项目,但它是第一个旨在加快生产率和生产时间的整体 MLOps 自动化解决方案。MLRun 开发团队欢迎想要试用它的新用户和新贡献者,如果您不喜欢安装和开发,您可以通过 Iguazio 将其作为管理服务使用。
如果您想讨论这个博客或其他与 MLOps 相关的挑战和最佳实践,我邀请您到加入 MLOps Live Slack 社区,与我和其他 MLOps 粉丝/专家聊天。
如何在 Python 中分析您的代码
原文:https://towardsdatascience.com/how-to-profile-your-code-in-python-e70c834fad89?source=collection_archive---------2-----------------------
使用 cProfile 查找瓶颈并优化性能

来自 Pexels 的 Anthony Maggio 摄影
如果你曾经写过一行代码(或者甚至几万行),你一定想知道“为什么我的代码需要这么长时间才能运行?”回答这个问题并不总是简单的,但如果你以正确的方式寻找答案,它会变得更容易。
也许你相信你手头问题的知识,利用你的专业知识先检查某些片段。也许你对几个不同的模块/类/函数计时,看看大部分执行时间花在哪里。更好的是,您可以分析您的代码,以获得更多关于不同函数和子函数所花费的相对时间的信息。不管你的过程是什么,这个博客可能会教你一些更快找到答案的方法。
在这篇文章中,我将首先向您展示一个基本的分析方法。我将为它添加越来越多的特性和味道,以一个好的、可靠的剖析装饰器结束。对于那些赶时间的人(或者想回头参考这些资料的人),可以去这个 GitHub 仓库,在那里你可以找到概要文件装饰器和一个例子。
计时!
要分析你的代码,你需要知道如何计时。为此,您可以使用如下简单的方法:
**from** time **import** timestart = time()
*# your script here* end = time()
print(**f'It took {**end - start**} seconds!'**)
为了方便地为几个函数/代码片段计时(或者如果您只是喜欢使用更简洁、更 pythonic 化的方法),您可以将上面的内容转换成一个计时器装饰器(这里用示例讨论)。
在任何函数上使用定时器都可以单独显示该部分的运行时间。为了使这种方法有助于找到瓶颈,我们需要更多的信息。为了有效地分析代码,下列两个条件中至少有一个应该为真:
- 我们应该知道程序的总运行时间,以便更好地了解我们期望的功能/部分的相对运行时间。例如,如果一段代码需要 5 分钟来执行,那是总运行时间的 10%、40%还是 90%?
- 我们应该对手头的问题或程序其他部分的运行时间有足够的了解,从而有把握地将一段给定的代码标记为瓶颈。即使一个功能需要 10 分钟才能运行(假设 10 分钟相对来说很长),如果我们确信没有其他部分需要更长的时间,我们就应该担心它的低效率。正如唐纳德·克努特的名言:
过早优化是万恶之源。
像[cProfile](https://docs.python.org/3.8/library/profile.html)这样的分析器包通过满足这两个条件来帮助我们找到代码中的瓶颈。
如何使用 cProfile
基本用法
用cProfile进行概要分析的最基本方式是使用run()函数。您需要做的就是将您想要分析的内容作为字符串语句传递给run()。这是报告的一个示例(为简洁起见,进行了删节):
>>> **import** cProfile
>>> **import** pandas **as** pd>>> cProfile.run(**"pd.Series(list('ABCDEFG'))"**)258 function calls (256 primitive calls) in 0.001 secondsOrdered by: standard namencalls tottime percall cumtime percall filename:lineno(function)
4 0.000 0.000 0.000 0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
1 0.000 0.000 0.000 0.000 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 _dtype.py:319(_name_get)
....
11/9 0.000 0.000 0.000 0.000 {built-in method builtins.len}
1 0.000 0.000 0.000 0.000 {built-in method numpy.array}
1 0.000 0.000 0.000 0.000 {built-in method numpy.empty}
....
第一行表示监控了 258 个调用,其中 256 个是原始调用(原始调用不是通过递归引起的)。下一行Ordered by: standard name表示报告是基于标准名称排序的,标准名称是filename:lineno(function)列中的文本。其后的一行是列标题:
ncalls:呼叫次数。当有两个数字时(如上面的 11/9),该函数循环出现。第一个值是调用的总数,第二个值是原始或非递归调用的数量。
tottime:给定函数花费的总时间(不包括调用子函数的时间)。
percall:是tottime除以ncalls的商。
cumtime:该功能及所有子功能的累计时间。这个数字对于递归函数来说是精确的甚至。
percall:是cumtime的商除以原语调用。
filename:lineno(function):提供各功能各自的数据。
run()函数可以再接受两个参数:一个filename将结果写入文件而不是 stdout,另一个sort参数指定输出应该如何排序。您可以查看文档以了解更多关于有效排序值的信息。常见的有'cumulative'(累计时间)'time'(总时间)'calls'(通话次数)。
如果您传递一个文件名并保存结果,您可能会注意到输出不是人类可读的。在这种情况下,您需要使用pstats.Stats类来格式化结果,我们将在接下来讨论。
使用Profile和pstats.Stats进行更多控制
虽然在大多数情况下使用cProfile.run()就足够了,但是如果您需要对分析进行更多的控制,您应该使用cProfile的Profile类。下面的片段摘自Profile级文档。
**import** cProfile, pstats, io
**from** pstats **import** SortKey
pr = cProfile.Profile()
pr.enable()
*# ... do something ...* pr.disable()
s = io.StringIO()
sortby = SortKey.CUMULATIVE
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print(s.getvalue())
让我们一行一行地过一遍:
首先,我们创建一个Profile类(pr)的实例,并通过调用enable收集概要分析数据。当我们想要停止收集分析数据时,我们调用disable。接下来是对收集的统计数据进行格式化。然后,我们可以使用[pstats.Stats](https://docs.python.org/3.8/library/profile.html#pstats.Stats)类构造函数来创建 statistics 对象的实例(ps)。
Stats类可以从 profile 对象(pr)创建一个 statistics 对象,并将输出打印到传递给它的流中。Stats类还有一个sort_stats方法,根据提供的标准对结果进行排序。在这种情况下,标准是SortKey.CUMULATIVE,它代表在一个函数中花费的累计时间。如[sort_stats](https://docs.python.org/3.8/library/profile.html#pstats.Stats.sort_stats)文档所述,排序标准可以是SortKey枚举(在 Python 3.7 中添加)或字符串的形式(即使用'cumulative'代替SortKey.CUMULATIVE也是有效的)。最后,创建结果并打印到标准输出。
这是构建装饰器的好样板(要了解更多关于装饰器的知识,我推荐这本伟大而全面的初级读本):
**import** cProfile
**import** io
**import** pstats**def** profile(func):
**def** wrapper(*args, **kwargs):
pr = cProfile.Profile()
pr.enable()
retval = func(*args, **kwargs)
pr.disable()
s = io.StringIO()
sortby = SortKey.CUMULATIVE # **'cumulative'** ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print(s.getvalue())
**return** retval
**return** wrapper*# Profile foo* @profile
**def** foo():
print(**'Profile me!'**)
虽然这是一个好的开始,但是上面的装饰器中还有几个部分可以做得更好。特别是,更全面的职能可以:
- 允许用户指定排序键(单个键或一组排序键)
- 仅显示最大时间消费者,而不是所有线路
- 通过删除文件名中的所有前导路径信息来整理报告,减小打印输出的大小并使报告更易于阅读
- 将输出保存到文件,而不是打印到标准输出
以上所有情况都可以使用pstats.Stats中的方法进行处理。让我们按顺序复习一下:
- 将所需的排序键传递给
sort_stats()方法(尽管我们仍然需要检查它是单个值还是一个元组) - 将最大所需打印行数传递给
print_stats() - 使用
strip_dirs() - 默认情况下,输出被打印到
[sys.stdout](https://docs.python.org/3/library/sys.html#sys.stdout),因为pstats.Stats()使用它作为默认的流参数,但是要将结果写入文件,我们可以将文件作为流传递
将上述更改应用到profile装饰器将产生以下函数(在 docstring 中提供了参数的更多解释):
总结示例
为了了解profile装饰器如何帮助我们检测瓶颈,让我们创建一个具有多个函数的例子。假设您有一份过去一年销售的产品列表,并且您想通过计算售出的数量来了解每种产品的受欢迎程度。(我们想要的可以通过使用[collections.Counter](https://docs.python.org/3/library/collections.html#collections.Counter)很容易地完成,或者如果你是一个pandas用户,通过[pandas.Series.value_counts](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.value_counts.html),但是为了这个练习,让我们忘记那些。)
**import** random
random.seed(20)**def** create_products(num):
*"""Create a list of random products with 3-letter alphanumeric name."""* **return** [**''**.join(random.choices(**'ABCDEFG123'**, k=3)) **for** _ **in** range(num)]
*# version1* @profile(sort_by=**'cumulative'**, lines_to_print=10, strip_dirs=**True**)
**def** product_counter_v1(products):
*"""Get count of products in descending order."""* counter_dict = create_counter(products)
sorted_p = sort_counter(counter_dict)
**return** sorted_p
**def** create_counter(products):
counter_dict = {}
**for** p **in** products:
**if** p **not in** counter_dict:
counter_dict[p] = 0
counter_dict[p] += 1
**return** counter_dict
**def** sort_counter(counter_dict):
**return** {k: v **for** k, v **in** sorted(counter_dict.items(),
key=**lambda** x: x[1],
reverse=**True**)}
*# ===========
# Analysis starts here
# ===========* num = 1_000_000 *# assume we have sold 1,000,000 products* products = create_products(num)
*# Let's add profile decorator to product_counter_v1 function* counter_dict = product_counter_v1(products)
结果将保存在您当前目录下的product_counter_v1.prof中,它应该是这样的:
1007 function calls in 0.228 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.228 0.228 scratch_6.py:69(product_counter_v1)
1 0.215 0.215 0.215 0.215 scratch_6.py:86(create_counter)
1 0.000 0.000 0.013 0.013 scratch_6.py:105(sort_counter)
1 0.013 0.013 0.013 0.013 {built-in method builtins.sorted}
1 0.000 0.000 0.000 0.000 scratch_6.py:106(<dictcomp>)
1000 0.000 0.000 0.000 0.000 scratch_6.py:107(<lambda>)
1 0.000 0.000 0.000 0.000 {method 'items' of 'dict' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
检查这个文件,我们可以看到绝大部分的执行时间(0.228 秒中的 0.215 秒)都花在了create_counter函数上。所以,让我们制作一个新的create_counter函数,并检查它的效果。
*# version2* @profile(sort_by=**'cumulative'**, lines_to_print=10, strip_dirs=**True**)
**def** product_counter_v2(products):
*"""Get count of products in descending order."""* counter_dict = create_counter_v2(products)
sorted_p = sort_counter(counter_dict)
**return** sorted_p
**def** create_counter_v2(products):
counter_dict = {}
**for** p **in** products:
**try**:
counter_dict[p] += 1
**except** KeyError:
counter_dict[p] = 1
**return** counter_dict
剖析结果product_counter_v2如下所示:
1007 function calls in 0.169 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.169 0.169 scratch_6.py:78(product_counter_v2)
1 0.158 0.158 0.158 0.158 scratch_6.py:95(create_counter_v2)
1 0.000 0.000 0.010 0.010 scratch_6.py:105(sort_counter)
1 0.010 0.010 0.010 0.010 {built-in method builtins.sorted}
1 0.000 0.000 0.000 0.000 scratch_6.py:106(<dictcomp>)
1000 0.000 0.000 0.000 0.000 scratch_6.py:107(<lambda>)
1 0.000 0.000 0.000 0.000 {method 'items' of 'dict' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
运行时间从 0.228 秒减少到 0.169 秒,减少了约 26%。如果这仍然不令人满意,您可以尝试使用[collections.defaultdict](https://docs.python.org/3/library/collections.html#collections.defaultdict)来创建counter_dict。对于最后一个实现,我们将使用collections.Counter:
**import** collections
*# version3* @profile(sort_by=**'cumulative'**, lines_to_print=10, strip_dirs=**True**)
**def** product_counter_v3(products):
*"""Get count of products in descending order."""* **return** collections.Counter(products)
性能分析product_counter_v3显示它比product_counter_v1提高了 62%。
11 function calls in 0.086 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.086 0.086 scratch_6.py:118(product_counter_v3)
1 0.000 0.000 0.086 0.086 __init__.py:517(__init__)
1 0.000 0.000 0.086 0.086 __init__.py:586(update)
1 0.086 0.086 0.086 0.086 {built-in method _collections._count_elements}
1 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance}
1 0.000 0.000 0.000 0.000 abc.py:180(__instancecheck__)
2 0.000 0.000 0.000 0.000 _weakrefset.py:70(__contains__)
2 0.000 0.000 0.000 0.000 {built-in method builtins.len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
试验一下profile装饰器的不同参数,看看输出会如何变化。你可以在这个 GitHub 库中找到完整的例子。
快乐剖析!
我希望这篇博客对你有用。我可以在Twitter和LinkedIn上联系,我欢迎任何反馈。
作为数据科学家,如何更有效地编程和调试
原文:https://towardsdatascience.com/how-to-program-and-debug-more-effectively-as-a-data-scientist-92e753144d54?source=collection_archive---------41-----------------------
我的第一个数据科学软件项目的经验教训

奥斯卡·伊尔迪兹在 Unsplash 上拍摄的照片
最近,我交付了我的第一个软件包,旨在自动化一些对我的团队的数据工作流至关重要的时间密集型计算。这个过程包括了比我愿意承认的更多的调试周期,部分是因为代码复杂性的增加和需求的发展,部分是因为我可以更有效地计划和执行。
经过一番思考,这里有一些从那次经历中得到的重要教训,可以帮助你作为一名数据科学家更有效地编写软件。
1。规划你的软件设计
当我开始我的项目时,我在有限的前期规划下投入到编码中,认为我的软件设计的确切细节会随着我的编码变得更加清晰。
随着我的代码变得越来越复杂,我开始忘记所有的函数是如何组合在一起的。当需求发生变化时,我不得不重新投入时间去理解我的代码,以做出想要的修改。
相对来说,避免这一陷阱并不费力。对你的软件在高层次上做了什么有一个简单而清晰的描述,不管你是画一个图表还是对你的软件的设计和功能做笔记。用纸笔、盒子和箭头画一张草图就足够了。我亲自在一个工作文档上写下了我可以不断修改的项目符号。
保留设计图有几个好处。首先,记录你的软件设计会给你一个更清晰的想法,你的所有代码是如何组合在一起的。用语言表达数据操作的逻辑可以帮助你检查你的逻辑是否会给你想要的结果。当然,当您需要对代码设计进行更大的更改时,有一个清晰的参考会变得非常方便。
2。投资文件组织
在多个脚本和 Excel 文件之间,我严重低估了我将在整个项目中导航的文件的数量。当我的专用文件命名系统最终失败时,我发现自己重新编写了几个函数,因为我找不到我编写它们的原始文件。
投资于你的组织必然会减轻压力,提高长期效率。在开始一个项目之前,投入一些前期工作来定义一个清晰的、可维护的文件组织和命名系统是有帮助的。
一些基本准则是:
- 您正在处理的每个项目都有一个单独的文件夹
- 每个文件类别(即脚本、数据、输出、QA 等)对应一个文件夹。)
- 代码的一致命名约定
- 数据文件的一致命名约定
除此之外,我发现在代码和数据文件(v2-file-2020-08-03)上使用版本标签和日期标签很有帮助,可以更容易地按时间顺序导航。
3。验证每个代码单元
到目前为止,调试是我的编程项目中最痛苦的部分。这种痛苦通常源于缩小 bug 的位置。我学到的一个教训是在每个转换步骤定期进行验证,以确保任何数据处理结果都具有我期望的值和维度。
这使我能够在早期捕捉到意外的行为,并让我对每一步的数据充满信心。
我经常使用的几个基本检查:
- 检查连接两个数据框前后的行数
- 检查处理前后变量的和是否匹配
- 检查缺少的值
为了提高效率和重复击键,我会考虑自动验证的方法,要么通过创建简单的验证函数,要么通过 Excel 模板。对我来说,在自动化验证上投入的时间很容易获得十倍的回报。
4。有条不紊地调试
当出现错误时,根据直觉进行调试有时会有回报。但是如果没有一个计划,这种方法可能是武断和令人沮丧的。从长远来看,遵循有条不紊的调试过程是更有效的策略。
建立一个系统来缩小错误的来源并记录尝试的解决方案,可以帮助你更有效地找到解决方案。此外,这可以缓解压力,让你以一种有条理和冷静的心态专注于调试。
在高层次上,我认为一个系统应该包括理解错误信息,围绕 bug 开发上下文,以及以一种有组织的方式测试和记录解决方案。在这个系统中,您可以更好地控制您的调试过程,为未来的调试周期提供参考文档,并以少量额外的时间和精力投入来换取压力的显著降低。我一直使用的程序是:
1.如果有错误信息,仔细阅读,查找;如果不是,请以书面形式描述意外行为
2.通过插入手动测试来缩小违规代码的位置
3.一旦您确定了错误发生的位置,检查进入违规代码的数据的结构、格式和值——通常这将导致一个解决方案
4.修复、重新运行、评估、记录
5.如果错误仍然存在,请进一步研究错误并再次测试
6.如果错误仍然存在,请寻求调试帮助
虽然您的系统可能不同,但我认为核心原则是相同的:理解您的错误,定位错误,调查明显的错误来源,并测试和记录。
5。记录错误和解决方案
在我的项目过程中,我发现自己多次调试同一个问题,这是对时间的低效利用。
为了避免两次解决同一个问题,我开始维护一个文档,记录我遇到的错误以及它们的解决方案。这个参考还有一个预防性的好处,允许我跟踪常见的错误,避免一开始就犯那些错误。
我建议保持你的解决方案文档简单;你可以在电子表格中记录你遇到的每一个错误——我的表格只有四栏:错误、背景、解决方案和下次注意事项。
在这个项目的过程中,我学到了很多教训,希望这篇文章能为你在下一次软件开发中节省一些压力和时间。请在下面的评论中告诉我你的想法,并随时在 Twitter 上与我联系。
如何正确地发布和部署您的机器学习模型
原文:https://towardsdatascience.com/how-to-properly-ship-and-deploy-your-machine-learning-model-8a8664b763c4?source=collection_archive---------4-----------------------
FastAPI、Docker 和 GitHub 操作实用指南

汤姆·菲斯克在像素上拍摄的照片
作为一名数据科学家,训练你的机器学习模型只是为客户提供解决方案的一部分。除了生成和清理数据、选择和调整算法之外,您还需要交付和部署您的结果,以便它可以在生产中使用。这本身就是一个很大的领域,有着不断发展的工具和标准。在这篇文章中,我的目标是提供一个实用的指南,告诉你如何使用当前可用的最先进的工具和最佳实践来完成这项工作。我们将构建一个系统,它可以作为您部署任务的起点,而不考虑实际的机器学习问题本身!我的目标是介绍最佳实践和展示高级特性,而不是一个仅仅触及所用工具表面的最小化应用程序,这样你就不必学习艰难的方法。从你自己的错误中学习固然很好,但是提前思考并且不犯那些错误要好得多。
为了创建我们的部署就绪应用程序,我们将使用两个工具作为我们的主要构建块: Docker 和 FastAPI 。Docker 可能不需要介绍,它是一个容器化工具,允许您在任何环境中轻松打包和运行您的应用程序。它与 FastAPI 配合得特别好,FastAPI 在过去的几个月里获得了令人难以置信的流行。它使得围绕您的模型构建 web 框架和根据您客户的需求进行定制变得容易。
[## 您应该现在就开始使用 FastAPI
如果您还没有尝试过 FastAPI,现在是时候了
towardsdatascience.com](/you-should-start-using-fastapi-now-7efb280fec02)
我们的玩具问题将是一个简单的回归,我们将根据犯罪率、财产税率等 13 个特征来预测房地产价格。为此,我们将使用波士顿房价数据集作为我们的训练数据。关于模型选择,我们将使用来自牛逼的 scikit-learn 包的随机森林回归器。当然,您并不局限于 scikit-learn,您可以使用 TensorFlow、PyTorch 或任何您喜欢的工具。为了简单起见,我选择了这个,因为它几乎不需要额外的工作,比如大量的数据预处理,而且它的依赖性相对较轻,易于安装。
在这篇文章中,我将展示如何
- 打包您的模型并构建一个 API 来与之通信,
- 设计一个方便简单的用户界面,
- 用
virtualenv设置合适的开发环境, - 使用 FastAPI,
- 通过包装你的机器学习模型为将来的代码变化做准备,
- 使用依赖注入使测试更容易,
- 验证用户输入,
- 用模拟测试 API,
- 用 Docker 和 Docker compose 打包,
- 最后是如何使用 GitHub 动作来自动化测试。
要遵循这个指南,你根本不需要有使用 Docker 或 FastAPI 的经验!熟悉 scikit-learn 和 NumPy 将是有益的,但我们不会非常集中地关注这些部分。我们将要构建的应用程序可以在https://github.com/cosmic-cortex/fastAPI-ML-quickstart找到,随时可以使用。在我们直接进入开发之前,让我们评估需求并设计应用程序的架构!
如何设计一个小型的机器学习 app
部署期间的一个主要考虑因素是客户的需求。在我们的例子中,我们假设他们不需要理解算法是如何工作的,也不想重新训练算法。他们只想发送数据,然后马上得到答案。

与机器学习模型通信
用技术术语来说,我们将构建一个应用程序,它以 HTTP 请求的形式接收数据,并以 HTTP 响应的形式发回预测。除了接口简单之外,作为微服务很容易集成到更大的应用中,这是一个巨大的优势。

来自高层的应用程序
我们的应用程序将通过 API 进行通信,该 API 将被打包在 Docker 容器中。在这个简单的例子中,在应用程序本身中,我们需要做三件事:处理输入、进行预测、处理输出并将其返回给用户。使用 FastAPI,输入将是一个 JSON,如下所示:
{"data":[[0.00632,18,2.31,0,0.538,6.575,65.2,4.09,1,296,15.3,396.9,4.98]]}
这将由 FastAPI 在内部转换成适当的 Python 对象。(稍后将详细介绍这一点,因为这是 FastAPI 中最简洁的特性之一。)我们需要为 scikit-learn 模型处理它,这意味着将它转换成一个 NumPy 数组。它可以用来计算我们的预测,我们将再次把它转换成 FastAPI 使用的格式。最后,用户将收到一个类似输入的 JSON:
{"data": [25.813999999999993]}
马上投入开发吧!我们的首要工作是建立适当的开发环境。
设置开发环境
如果您曾广泛使用 Python,那么您可能使用过虚拟环境。如果没有,要点如下。Python 虚拟环境是 Python 的独立安装,您可以在其中安装项目所需的特定包。当您有许多项目具有可能冲突的依赖关系时(比如一个项目要求 NumPy ≥ 1.13,而另一个项目要求 NumPy ≤ 1.10),您最好使用虚拟环境来避免完全混乱。要创建虚拟环境,请使用
virtualenv /path/to/venv --python=/path/to/python3
在这里可以找到全局 Python3 解释器的路径
which python3
如果你在 Linux 下。(如果不显式提供解释器,就会回退到别名为python的 Python 解释器,有些情况下可以是 Python 2.7。不要使用 Python 2.7:)虚拟环境可以用
source /path/to/venv/bin/activate
在这之后,如果你用 pip 安装包,它将只在虚拟环境活动时可见。在您克隆了包含我们将要构建的应用程序的库之后,您可以使用
pip install -r requirements.txt
在根文件夹中时执行命令。尽管您不需要将您的依赖项收集到一个单独的需求文件中,但是强烈建议您这样做。这使得维护你的应用程序更加容易,而且当你把应用程序打包成 Docker 镜像时,你可以使用同一个文件。
构建应用程序的框架
粗略地说,每个 FastAPI 应用程序都由一个主文件组成,该主文件负责启动应用程序/定义端点和端点使用的附加模块。(可以在主文件之外的其他地方定义端点,但是在最简单的情况下,这种结构是更可取的。)
.
├── api
│ ├── __init__.py
│ ├── main.py
│ └── ml
│ ├── __init__.py
│ ├── model.joblib
│ └── model.py
└── requirements.txt
当 FastAPI 应用程序的结构清晰后,我们先构建main.py的框架,然后实现ml模块!
我们基本上需要导入两个类:为我们的 API 提供所有功能的FastAPI类和来自 awesome Pydantic 库的BaseModel,它充当 HTTP 请求和响应的模型。
在实例化一个FastAPI对象后,我们可以通过使用它的适当方法来修饰描述端点逻辑的函数,从而向它注册端点。例如,这里我们有
这意味着我们的应用程序期望一个对/predict端点的POST请求,该请求包含一个由PredictRequest对象描述的 JSON 有效负载,并将返回一个由PredictResponse描述的 JSON 有效负载的响应。这些都是由函数前的@app.post装饰器指定的,它将这个函数注册到名为app的FastAPI实例,并将请求路由到这个函数的/predict URL。predict的input参数的类型注释描述了请求数据的适当格式。
在这个例子中,PredictRequest对象有一个名为data的属性,它必须是一个 floats 列表的列表。(由于数据通常是成批传递的,所以外部列表中的每个列表都是一个数据点。)Pydantic 非常重视类型检查:如果类型不匹配,它会无情地抛出一个异常。这种用 Pydantic 进行的类型检查是 FastAPI 的一个极其强大的特性,使我们的生活变得更加容易。如果请求的格式不正确,您会立即收到一个 422 不可处理的实体状态代码作为响应。而你要为此做几乎为零的工作!如果您已经使用请求和响应模型指定了模式,FastAPI 和 Pydantic 会为您执行验证。
您可以立即使用此应用程序
uvicorn api.main:app
并且通过检查由 FastAPI 生成的自动文档来试用端点,默认情况下可以在http://localhost:8000/docs找到该文档。或者,您可以使用curl来发布请求,例如
curl -X POST “[http://localhost:8000/predict](http://localhost:8000/predict)" -H “accept: application/json” -H “Content-Type: application/json” -d “{\”data\”:[[0]]}”
会管用的。目前,这个简单的框架将总是返回一个伪响应
{"data":[0]}
但是,一旦我们的模型到位,这种情况很快就会改变。既然框架已经建立并运行,我们就可以开始实现机器学习模型了!
创建机器学习算法
正如我提到的,我们将使用 Boston 数据集训练一个简单的随机森林回归器,两者都可以在 scikit-learn 中找到。尽管直接使用 scikit-learn 对象很有吸引力,但我更喜欢为我们的模型构建一个抽象接口,它将由 API 端点使用,而不是由 scikit-learn 对象本身使用。其背后的原因是该接口在整个代码库中是可重用的,如果您希望替换您的底层模型(比如使用 PyTorch 模型而不是 scikit-learn 的随机森林回归器),您只需要更改该类的实现,而不是更改实际使用该模型的所有函数和端点。
我们需要四个基本方法:一个用于训练模型,一个用于计算预测,两个用于保存和加载模型。当界面清晰时,我们就可以开始具体的实现了,这非常简单。
除了模型接口本身,我们还将在api.ml.model模块中定义模型对象。这个特定的实例将在整个应用程序中使用。这被称为单例,是最重要的 OOP 模式之一。虽然在这里使用是安全的,但是在大型应用程序中必须小心使用单例变量,因为它们基本上是全局变量。通过调用get_model()函数,可以在应用程序的其余部分访问这个模型对象。这有两个原因。首先,这个函数在代码中到处都是可重用的,因此如果以后我们决定添加额外的逻辑来获取模型(如检查等),在一个地方修改代码就足够了。第二,稍后将会解释,如果我们在端点中使用依赖注入,那么为应用程序编写单元测试会更好。(如果你现在不明白这一点也不要担心,后面会解释的。)
为了准备我们的应用程序,在执行这个脚本时,一个模型被训练并保存到磁盘上。这将在以后用于预测。
构建 API 端点 I:处理 JSON 输入
在应用程序框架和机器学习算法到位后,我们就可以实施端点背后的逻辑了。让我们切换回main.py模块!预测是一个相对简单的过程,只需要几行代码就可以实现。
在函数体中,有三件事情正在进行:
- 输入(是
PredictRequest的一个实例)被转换成一个 NumPy 数组。 - 计算预测,产生一个 NumPy 数组。
- 结果被转换成一个
PredictResponse对象并返回。
FastAPI 将返回值转换为正确的响应。有一个重要的变化可能已经引起了您的注意:我们向我们的predict函数传递了一个额外的参数:
model: Model = Depends(get_model)
其中get_model函数是返回模型的函数,在api.ml.model模块中定义。这种技术被称为依赖注入。虽然model是函数的一个参数,但是每次调用predict函数,都会执行get_model并传递返回值。为什么这很有用,这一点可能并不明显,但是这对于编写正确的单元测试非常重要。想想看:我们的端点依赖于一个 scikit-learn 对象,它背后有数千行代码。例如,它可以在软件包的新版本中进行磨合。(就像最近发生在 pip 上的一样:https://github.com/pypa/pip/issues/7217,影响了相当一部分用户。)一般来说,不管它们有多重要,外部依赖都会带来潜在的错误。当我们想要对我们的应用程序进行单元测试时,我们不希望结果依赖于一些可能超出我们控制的对象的正确性。因此,这些通常在单元测试中被嘲笑。mock 是一个伪对象,实现了与原始对象相同的接口,具有 100%可预测的行为。有了依赖注入,通过覆盖依赖,这些模拟可以很容易地注入到代码中。如果您没有马上明白这一点,请不要担心,在测试部分会有更详细的解释。
永远不要相信用户的输入
既然端点本身已经实现,让我们考虑一些可能的用例。如果你尝试
curl -X POST “[http://localhost:8000/predict](http://localhost:8000/predict)" -H “accept: application/json” -H “Content-Type: application/json” -d “{\”data\”:[[0]]}”
使用当前的实现,您将得到一个内部服务器错误,应用程序将崩溃。这是因为由于模型是使用 13 个特征训练的,所以它需要 13 个特征来进行预测。虽然 uvicorn 很聪明,会在这种情况下重启你的应用程序,但是内部服务器错误听起来很糟糕,你肯定不想在生产中遇到这种情况。为了解决这个问题,我们将在 Pydantic 请求模型中添加额外的验证。默认情况下,它们只检查 JSON 有效负载是否有一个“data”键,其值是一个 floats 列表的列表。在我们的定制验证器(除了默认验证之外还运行)中,我们检查数据的维度是否正确,也就是说,每个子列表都准确地包含了n_features元素。(也就是 13。)
当传递了错误的数据并且验证失败时,应用程序不会崩溃,而是返回 422 不可处理的实体错误代码。虽然这对最终用户来说不一定是更好的结果,但对你和你的 devops 团队来说肯定是更愉快的。一般来说,当您构建处理数据的应用程序时,您不应该相信用户输入。事情可能会意外出错,也可能会受到恶意攻击,比如 SQL 注入,这是黑客工具包中一个流行而危险的工具。
最终的模块会是这样的:https://github . com/cosmic-cortex/fastAPI-ML-quick start/blob/master/API/main . py
下一节将添加predict_csv端点。
构建 API 端点 II:处理。csv 文件
如果您想接收另一种格式的数据,如 csv 文件,您可以这样做。你应该使用[File](https://fastapi.tiangolo.com/tutorial/request-files/) 和 [UploadFile](https://fastapi.tiangolo.com/tutorial/request-files/)来代替使用 Pydantic 模型作为输入。
注意,这一次,Pydantic 没有为我们执行验证,因此我们必须手动执行。有两件事需要验证。
- 该文件包含表格形式的数据。
- 该数据正好包含 13 个特征。
我们在函数体内手动完成这两项工作。当出现问题时,我们会抛出一个异常,由 FastAPI 在一个适当的 HTTP 响应中返回。
测试 API
现在我们已经准备好了一切,是时候测试我们的应用程序了!使用未经测试的代码就像打地鼠游戏:你修复了一个 bug,另一个 bug 马上就会出现。就个人而言,我是测试的大力支持者,我认为你也应该是一个。尽管测试需要最初的时间投入,但它将在开发的后期得到指数回报。
为了测试 API,我们将使用pytest,这是 Python 中单元测试的标准工具。我们将把测试模块放在api旁边,因此文件结构将如下所示:
.
├── api
│ ├── __init__.py
│ ├── main.py
│ ├── ml
│ │ ├── __init__.py
│ │ ├── model.joblib
│ │ └── model.py
│ └── tests
│ ├── api
│ │ ├── __init__.py
│ │ └── test_api.py
│ ├── conftest.py
│ ├── __init__.py
│ └── mocks.py
└── requirements.txt
我们要构建的第一件事是一个模拟的Model对象,这样我们的端点测试就不依赖于 scikit-learn。正如我所提到的,这是不可取的,因为我们希望将代码中的错误和外部代码中的错误分离开来。
这个类相对简单,完全模仿我们的api.ml.model.Model类的接口,但是基本上它不执行任何有意义的计算,并且返回随机数据。(尽管随机数据将在形状上匹配预期的输出。)
接下来,我们将根据pytest需求添加位于conftest.py模块中的测试配置。在我们的情况下,我们应该做两件事。
- 覆盖端点中使用的依赖注入,以使用一个
MockModel对象来代替真实模型。 - 定义测试中使用的 fixtures,它们本身就是依赖注入。(我们很快会看到一个例子。)
首先,我们从我们的main模块导入实际的app对象。要覆盖对get_model()的依赖,我们只需提供一个新函数,并用新函数在app.dependency_overrides字典中设置适当的键。这段代码不会在部署期间执行,因此我们的依赖关系不会被意外覆盖,它是特定于测试的。接下来,我们准备一个 Starlette TestClient,它“允许你对你的 ASGI 应用程序做出请求”,一个非常方便的测试工具。这个定义意味着使用TestClient实例,我们可以向端点发送请求并接收响应,这正是我们想要测试的。
首先,我们用有效数据测试用户输入。为了看到它在多批量(从 1 到 9)下工作良好,我们添加了数据点的数量作为n_instances参数。在测试函数中遍历所有可能的大小被认为是不好的做法,因为如果它对某个特定的大小失败了,您会想知道它失败的确切位置。因此,我们可以使用@pytest.mark.parametrize装饰器,它为参数的每个值自动生成一个新的测试函数。在测试函数中,我们简单地生成一些假数据,并使用TestClient将其发送到应用程序。我们要检查两件事:1)响应代码是 200,这是 HTTP-okay 的说法 2)响应包含的预测与输入数据集的大小一样多。
然而,测试端点的正确输入数据是不够的。如果是这样,更重要的是确保我们的应用程序在出现不正确的数据时表现正常。这在下面介绍。
为了完整起见,我已经为predict_csv端点添加了测试,这些测试与之前的测试相似,所以我不再详述。
一旦测试准备好了,您就可以通过在 bash 中从项目的根目录执行pytest来运行它们。输出将如下所示:

毕竟测试模块应该是这样的:https://github . com/cosmic-cortex/fastAPI-ML-quick start/tree/master/API/tests。
打包您的应用程序
当应用程序经过适当的测试并在您的本地机器上正确运行时,就该将它打包成可移植的格式了。如果没有这一点,在另一台机器上设置它将是一个缓慢而痛苦的过程。为此,我们将使用 Docker。

Docker 架构。来源:https://docs.docker.com/engine/docker-overview/
Docker 将应用打包成镜像,镜像是自包含的应用,甚至是操作系统。它们由 Docker 容器运行,Docker 容器是隔离的执行环境。它们在原理上非常类似于虚拟机。尽管它们不像虚拟机那样提供严格的隔离,但当您第一次使用 Docker 时,这是一个很好的模型。
Docker 映像由Dockerfile定义,它基本上是 Docker 如何构建映像的一组指令。映像通常不是独立的,它们是从其他基础映像构建的。这些图像在 https://hub.docker.com 有它们自己的存储库,你可以在那里推送你的图像和拉取其他图像。打个比方,这些图像就像 git 存储库。使用基本映像就像分叉一个存储库,并将一些提交推到您自己的分叉上。
我们将使用包含 19.10 版本 Ubuntu 的ubuntu:19.10映像来打包我们的应用程序。(这是 Ubuntu docker 官方图片。)选择基础映像会显著影响后面的大部分工作流程。对于 Python 应用程序,基于 Alpine Linux 的映像也是一个很好的选择,Python 甚至有一些基于 Alpine 的官方映像。然而,将 NumPy 和某些机器学习库安装到基于 Alpine 的映像可能会很困难,所以我们将坚持使用 Ubuntu。
这是我们的 Dockerfile,包含在项目的根文件夹中。我们将一行一行地走一遍。
第一行描述了基本图像,如前所述是ubuntu:19.10。在构建时,这个映像从中央存储库中取出。完成后,Docker 将把./api文件夹复制到图像中。(每个映像都有自己的文件系统。)然后我们准备安装 Python3 以及 FastAPI 等所需的包。在图像内执行RUN后的命令。在这之后,我们正确地设置PYTHONPATH变量和工作目录。
为了服务于我们的应用程序,我们将向主机映像公开容器的端口 8000。出于安全原因,默认情况下不会这样做,您必须手动这样做。最后,我们告诉 Docker 在容器运行时要做什么:我们要启动uvicorn并为应用程序提供服务。ENTRYPOINT指定每次执行容器时将运行的命令,而CMD指定其参数。
图像本身可以用
docker build --file Dockerfile --tag fastapi-ml-quickstart .
命令。构建可能需要一段时间,但完成后,您可以使用
docker run -p 8000:8000 fastapi-ml-quickstart
在 run 命令中,您需要指定 Docker 将容器的 TCP 端口 8000 映射到主机中的同一个端口。如果您在浏览器中打开 http://localhost:8000 ,您可以看到应用程序正在运行,并且您可以正确地连接到它。
组合容器
在这个简单的例子中,我们的应用程序不依赖于其他服务,比如 Redis 或 PostgreSQL。在这种情况下,docker-compose可以用来组合容器。与Dockerfile类似,docker-compose 需要一个名为docker-compose.yaml的 YAML 配置文件来描述要启动哪些服务。
在这之后,只需执行
docker-compose up
从项目根目录。Docker compose 将在图像不可用时自动构建图像。我发现即使你只有一个容器,每次用这个手动调用docker build和docker run也要简单得多。
与 GitHub 动作的持续集成
维护良好的代码的支柱之一是持续集成。即使我们有测试,实际上也没有强迫程序员在提交变更之前使用它们。我们可以通过在某些触发条件下自动执行测试来解决这个问题,比如对特定分支的 push 和 pull 请求。这样,向共享代码库的主线推送更改可以比通常更快地完成。与旧的学校开发工作流程相比,当合并每周进行一次,并需要团队的大部分人员来监督时,通过适当的持续集成设置,代码交付可以由一个人完成,甚至每天几次。
在这个项目中,我们将使用 GitHub Actions,它允许您根据预定义的触发器自动执行操作。它要求您在 GitHub 托管的存储库的.github/workflows子目录中定义您的动作脚本。以下是该项目的 YAML 配置文件。
如您所见,配置文件有两个主要部分:第二部分定义将要发生什么,第一部分定义何时发生。在这个例子中,我们希望脚本在对master分支的每个 push 和 pull 请求上执行。
动作本身是根据工作定义的,并给出了每个步骤。这个名为build的特定作业在 Ubuntu 实例中运行,如runs-on参数所示。首先它检查存储库,然后它使用docker-compose.test.yaml文件启动 Docker compose,这是专门为测试目的而制作的。
与我们之前使用的相比,这个 Docker compose 只有一行不同:它覆盖了fastapi-ml-quickstart容器的入口点,启动了pytest而不是uvicorn。完成后,容器退出,Docker 编写被中止,从fastapi-ml-quickstart容器返回退出代码。这些事情都不是docker-compose的默认行为,所以你要特别指示它这么做:
docker-compose -f docker-compose.test.yaml up --abort-on-container-exit --exit-code-from fastapi-ml-quickstart
就个人而言,我是 GitHub Actions 的忠实粉丝。它是非常通用的,你甚至可以用它将更新推送到产品中,在 PyPI 中发布,以及许多其他任务。它明显的缺点是只对 GitHub 用户开放。然而,也有替代者,例如 Jenkins、CircleCI、Travis CI、GitLab CI 等等。
包扎
在本指南中,我的目标是为机器学习应用程序构建一个小应用程序,并遵循最佳实践和使用现代工具对其进行适当的打包。但是,总有进步的空间!如果你有任何想法,欢迎在https://github.com/cosmic-cortex/fastAPI-ML-quickstart提出来!我希望你觉得这个指南有用。现在去开始构建令人敬畏的人工智能应用程序:)
如果你喜欢把机器学习概念拆开,理解是什么让它们运转,我们有很多共同点。看看我的博客,我经常在那里发表这样的技术文章!
如何在 Docker 容器中正确使用 GPU
原文:https://towardsdatascience.com/how-to-properly-use-the-gpu-within-a-docker-container-4c699c78c6d1?source=collection_archive---------1-----------------------
注意:我们也在博客上发布了如何在 Docker 中使用 GPU。在这篇文章中,我们将介绍在 Docker 容器中访问机器的 GPU 所需的步骤。
在你的机器上配置 GPU 可能非常困难。配置步骤会根据您机器的操作系统和 NVIDIA GPU 的种类而有所不同。更困难的是,当 Docker 启动一个容器时,它几乎是从零开始的。某些东西,比如 CPU 驱动程序是为你预先配置的,但是当你运行 docker 容器时,GPU 并没有被配置。幸运的是,您已经找到了这里解释的解决方案。它叫做 NVIDIA 容器工具包!

Nvidia 容器工具包(引文)
Docker 中的潜在错误
当您试图在 Docker 中运行需要 GPU 的容器时,您可能会收到以下任何错误。
错误:Docker 找不到 Nvidia 驱动程序
docker: Error response from daemon: Container command 'nvidia-smi' not found or does not exist..
错误:tensorflow 无法访问 Docker 中的 GPU
I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:150] kernel reported version is: 352.93
I tensorflow/core/common_runtime/gpu/gpu_init.cc:81] No GPU devices available on machine.
错误:pytorch 无法访问 Docker 中的 GPU
RuntimeError: cuda runtime error (100) : no CUDA-capable device is detected at /pytorch/aten/src/THC/THCGeneral.cpp:50
错误:keras 无法访问 Docker 中的 GPU
The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
您可能会收到许多其他错误,表明您的 Docker 容器无法访问机器的 GPU。在任何情况下,如果您有任何类似上面的错误,您已经在这里找到了正确的位置。
首先,确保你的基本机器有 GPU 驱动程序
您必须首先在您的基本计算机上安装 NVIDIA GPU 驱动程序,然后才能在 Docker 中使用 GPU。如前所述,由于操作系统、NVIDIA GPU 和 NVIDIA GPU 驱动程序的分布过多,这可能很困难。您将运行的确切命令会因这些参数而异。这里有一些资源,你可能会发现在你的基本机器上配置 GPU 有用。
- NVIDIA 官方工具包文档
- 在 Ubuntu 指南上安装 NVIDIA 驱动程序
- 从命令行安装 NVIDIA 驱动程序
一旦你完成了这些步骤,通过运行 nvidia-smi 命令并查看如下输出,你就会知道你成功了。

我已经成功地在我的谷歌云实例上安装了 GPU 驱动程序
现在,我们可以保证我们已经成功地保证 NVIDIA GPU 驱动程序安装在基础机器上,我们可以移动到 Docker 容器的更深一层。
接下来,向 Docker 公开 GPU 驱动程序
为了让 Docker 识别 GPU,我们需要让它知道 GPU 驱动程序。我们在图像创建过程中这样做。Docker 映像创建是一系列命令,用于配置 Docker 容器将要运行的环境。
强力方法— 强力方法包括您在基本机器上用来配置 GPU 的相同命令。当 docker 构建映像时,这些命令将会运行并在您的映像上安装 GPU 驱动程序,一切都会好的。在你的 docker 文件中,暴力方法看起来会像这样(代码归功于栈溢出):
FROM ubuntu:14.04
MAINTAINER Regan <[http://stackoverflow.com/questions/25185405/using-gpu-from-a-docker-container](http://stackoverflow.com/questions/25185405/using-gpu-from-a-docker-container)>RUN apt-get update && apt-get install -y build-essential
RUN apt-get --purge remove -y nvidia*ADD ./Downloads/nvidia_installers /tmp/nvidia > Get the install files you used to install CUDA and the NVIDIA drivers on your host
RUN /tmp/nvidia/NVIDIA-Linux-x86_64-331.62.run -s -N --no-kernel-module > Install the driver.
RUN rm -rf /tmp/selfgz7 > For some reason the driver installer left temp files when used during a docker build (i don't have any explanation why) and the CUDA installer will fail if there still there so we delete them.
RUN /tmp/nvidia/cuda-linux64-rel-6.0.37-18176142.run -noprompt > CUDA driver installer.
RUN /tmp/nvidia/cuda-samples-linux-6.0.37-18176142.run -noprompt -cudaprefix=/usr/local/cuda-6.0 > CUDA samples comment if you don't want them.
RUN export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64 > Add CUDA library into your PATH
RUN touch /etc/ld.so.conf.d/cuda.conf > Update the ld.so.conf.d directory
RUN rm -rf /temp/* > Delete installer files.
强力方法的缺点— 首先,每次你重新构建 docker 镜像时,你都必须重新安装镜像,这会减慢开发速度。第二,如果您决定将 docker 映像从当前机器中取出,放到一台具有不同 GPU、操作系统的新机器上,或者您想要新的驱动程序,那么您将不得不每次都为每台机器重新编码这一步骤。这违背了建立码头工人形象的目的。第三,您可能不记得在您的本地机器上安装驱动程序的命令,并且在 Docker 中重新配置 GPU。
最佳方法— 最佳方法是使用 NVIDIA 容器工具包。NVIDIA 容器工具包是一个 docker 映像,它支持自动识别您的基本计算机上的 GPU 驱动程序,并在运行时将这些相同的驱动程序传递给您的 Docker 容器。因此,如果你能够在你的基本机器上运行 nvidia-smi ,你也将能够在你的 Docker 容器中运行它(并且你的所有程序将能够引用 GPU)。为了使用 NVIDIA Container Toolkit,您只需将 NVIDIA Container Toolkit 映像放在 Dockerfile 的顶部,就像这样— nano Dockerfile :
FROM nvidia/cuda:10.2-base
CMD nvidia-smi
这是你需要向 Docker 公开 GPU 驱动的所有代码。在该 docker 文件中,我们已经导入了 10.2 驱动程序的 NVIDIA 容器工具包映像,然后我们指定了一个在运行容器来检查驱动程序时要运行的命令。现在我们用 docker build 构建图像。-t 英伟达-测试:

构建 docker 映像,并将其命名为“nvidia-test”
现在,我们通过使用命令docker run-GPU all NVIDIA-test 从映像运行容器。请记住,我们需要—GPU all,否则 GPU 不会暴露给运行的容器。

成功!我们的 docker 容器看到了 GPU 驱动程序
从这个基础状态开始,您可以相应地开发您的应用程序。在我的情况下,我使用英伟达容器工具包来支持实验性深度学习框架。完整构建的 docker 文件的布局可能如下所示(其中/app/包含所有 python 文件):
FROM nvidia/cuda:10.2-base
CMD nvidia-smi#set up environment
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y curl
RUN apt-get install unzip
RUN apt-get -y install python3
RUN apt-get -y install python3-pipCOPY app/requirements_verbose.txt /app/requirements_verbose.txtRUN pip3 install -r /app/requirements_verbose.txt#copies the applicaiton from local path to container path
COPY app/ /app/
WORKDIR /appENV NUM_EPOCHS=10
ENV MODEL_TYPE='EfficientDet'
ENV DATASET_LINK='HIDDEN'
ENV TRAIN_TIME_SEC=100CMD ["python3", "train_and_eval.py"]
上述 Docker 容器使用基础机器 GPU 基于规范训练和评估深度学习模型。相当酷!
在 Dockerfile 中需要不同的基础图像
假设您一直依赖 docker 文件中的不同基础映像。然后,你可以安装 NVIDIA 容器运行时。
apt-get install nvidia-container-runtime
docker run -it --rm --gpus all ubuntu nvidia-smi
现在你可以用 nvidia 容器运行时运行其他基础镜像(这里我们运行 ubuntu 基础)。
NVIDIA 容器工具包的威力
现在,您已经编写了映像以通过基础机器的 GPU 驱动程序,您将能够从当前机器中提取映像,并将其部署到在您想要的任何实例上运行的容器中。
更新:需要 Docker 上的 CuDNN 和 NVCC cuda 工具包吗?
只有当你需要从其他 NVIDIA Docker 基础映像中获得cuDNN或nvcc --version时,nvidia/cuda:10.2-base才会获得nvidia-smi.,即:nvidia/cuda:10.2-devel-ubuntu18.0.(获得 nvcc cuda 工具包)和nvidia/cuda:10.2-cudnn7-devel-ubuntu18.04.(获得 cuDNN)。
结论
恭喜你!现在,您知道如何使用 NVIDIA 容器工具包将 GPU 驱动程序暴露给正在运行的 Docker 容器。
想使用你的新 Docker 功能做一些很棒的事情吗?你可能会喜欢我们关于训练一个最先进的物体检测模型、训练一个最先进的图像分类模型的其他帖子,或者只是通过查看一些免费的计算机视觉数据!
如何保护您的数据免受未经授权的访问
原文:https://towardsdatascience.com/how-to-protect-your-data-from-unauthorized-access-bd74105d2ce4?source=collection_archive---------38-----------------------

澳门图片社在 Unsplash 上拍摄的照片
数据保护是当今世界各地组织主要关注的问题之一。信息安全(InfoSec)主要是禁止未经授权访问信息,它使数据保护成为可能。
到 2020 年,安全信息和事件管理(SIEM)等安全服务和其他托管服务预计将占网络安全预算的近50。这意味着企业越来越重视网络安全,并实施更好、更强大的安全实践来防止攻击者或恶意内部人员的未授权访问。
您的数据是否足够安全,可以防止未经授权的访问?在本文中,让我们看看您可以做些什么来提高安全性。
防止未经授权的数据访问:帮助您提高网络安全的 9 个技巧
但首先,要学会收集相关数据,对其进行分析,并将其转化为可操作的情报资源。
您可以决定聘请第三方分析师来监控、利用和保护您的数据,或者让您的团队参加专业的分析课程来提高他们的知识。
这样,他们不仅可以依赖分析和数据安全工具,还可以保护和利用数据来做出有益的业务决策。
想要确保您的洞察力数据是 100%安全的吗?以下是我们帮助您防止未经授权的数据访问的建议:
1.保持所有安全补丁的最新状态
对于任何组织来说,防止未经授权的数据访问的第一步是更新所有的安全补丁。
原因如下:
安全补丁解决软件、操作系统、驱动程序等中的漏洞。,攻击者可能会利用它来访问您的设备和数据。Windows、Linux、Android、iOS 等操作系统的安全补丁是必不可少的,因为操作系统漏洞会带来严重后果。此外,随着新补丁的推出,不断更新驱动程序和软件应用程序。
WannaCry 病毒导致 150 个国家超过 40 万台计算机系统瘫痪,是近年来最严重的攻击之一。它攻击了 Windows 的 SMB V1(服务器消息块)协议中的漏洞,并通过使用 EternalBlue exploit 启动。
有趣的是,早在攻击发起之前,这些漏洞的安全补丁就已经存在了。但是有成千上万的用户没有更新他们的安全补丁,因此成为攻击的受害者。
通过使用更新的安全补丁,用户可以防止对系统攻击进行未经授权的访问。
请务必为您的操作系统和其他软件下载最新的安全补丁和更新,以保护其免受网络攻击。您还可以启用自动更新,以便每当发布安全修补程序或更新时,系统都会自动安装它。
通过保持准备和更新,您可以保护您的数据免受那些试图获得未经授权的访问。
2.快速检测和响应入侵
当然,您需要保持警惕,并做好准备防止黑客未经授权访问数据。
但是如果您无法检测到入侵呢?
前进的方向是什么?
您越早检测到入侵,就能越早做出响应。预防无疑是重要的,但是监控用户活动、登录尝试、日志和其他活动也可以让您了解系统的安全性。
有几种方法可以快速检测和响应入侵:
入侵检测系统/入侵防御系统
IDS 使用已知的入侵迹象或行为试探法来评估网络流量中的可疑活动。
入侵检测是监控和分析您的网络或系统中的活动的过程,以发现入侵事件的可能迹象,如即将发生的威胁、违规或对您的安全策略的威胁。
另一方面,IPS 通过主动监控系统的传入流量来识别恶意请求,对 IDS 起到了补充作用。IPs 通过阻止未授权或违规的 IPS、禁止恶意数据以及提醒安全人员注意潜在的安全威胁来防止入侵攻击。
安全事故事件经理
安全事故事件管理器(SIEM)是一种安全管理方法,使安全专业人员能够深入了解 IT 环境中的活动。SIEM 软件收集和分析公司技术基础设施生成的日志数据,从应用程序、主机系统、网络到安全设备。
然后,该软件会对事件和事故进行检测和分类,并对其进行分析。SIEM 主要有两个目标:
- 跟踪记录并提供有关安全相关事件和事故的报告,例如失败和成功的登录尝试、恶意软件活动或任何其他可疑活动。
- 如果检测到任何表明存在安全威胁的可疑活动,请通知安全人员。
- 实施用户和事件行为分析(UEBA)
- 为了防止未经授权的数据访问,您需要掌控您的分析游戏。
如果与用户的“正常”行为模式存在偏差,用户和事件行为分析有助于检测任何异常行为或实例。例如,如果用户每天定期下载 10MB 大小的文件,但突然下载千兆字节的文件,系统会检测到这种异常并立即向管理员发出警报。
用户和事件行为分析使用算法、统计分析和机器学习来确定与既定模式的偏差,显示哪些异常正在发生以及它们如何可能导致潜在威胁。通过这种方式,您可以得到关于未经授权的数据访问的警告。
此类分析侧重于您系统内的用户和实体,尤其是内部威胁,如可能滥用其权限实施有针对性的攻击或欺诈企图的员工。
3.实现最小特权原则(最小化数据访问)
最低特权是将帐户、用户和计算进程的访问权限限制为仅执行合法的日常活动所需的特定资源的做法。2019 年全球数据风险报告称,平均而言,一名员工可以访问 1700 万个文件。
实现最低特权可以帮助您保护数据免受未经授权的访问。最小特权原则(POLP)强制实施最低级别的用户权限,允许用户访问仅履行其角色所需的特定资源。它降低了被未经授权的用户、应用程序或系统利用的风险,而不会影响组织的整体工作效率。
虽然最小特权有助于仅为完成手头工作所需的特定资源提供权限,但它也实施更好的安全实践并降低您的组织成为网络攻击受害者的可能性。
4.使用多因素身份验证
对于公司来说,除了多因素身份认证之外,还必须通过实施强大的密码策略来使用强身份认证。这对于防止未经授权的数据访问大有帮助。
顾名思义,多因素身份认证要求用户提供多条信息,并在被授权访问系统之前由系统进行验证。这使得攻击者很难侵入用户的帐户,因为这比简单地破解密码需要更多的努力。
多因素身份验证可能使用通过带外通信渠道发送的一次性密码,例如自动电话呼叫或 SMS 文本消息发送给用户的授权设备、用户设置的安全问题或生物特征身份验证。虽然这使得身份验证有点麻烦,但它确保了更好的安全性,并迫使攻击者不仅要破解密码,还要破坏第二个因素。这使得攻击者破解身份验证变得更加困难。
想要一个专业的提示,以防止未经授权的访问您的数据?
利用密码。
虽然肯定应该使用多因素身份验证,但是您也可以使用通行短语来代替密码。密码短语是一系列随机单词或一个句子,单词之间也可以包含空格,如“十群大象经常在坦桑尼亚打保龄球!!"
密码短语不一定要语法正确;它可以是任意单词的组合,也可以包含符号。记住复杂的密码比记住复杂的密码更容易。仍然必须小心生成强有力的密码短语。只使用日常词汇的简单密码仍然很容易被破解。
5.实施 IP 白名单
另一种防止未经授权的数据访问的方法是通过 IP 白名单。
IP 白名单有助于限制和控制仅受信任用户的访问。它允许您创建可信和授权的 IP 地址列表,用户可以从这些地址访问您的网络。通常,公司通过一组定义好的 IP 地址使用互联网,因此他们可以添加一个允许访问的所有可信 IP 地址的列表。
通过将 IP 地址列入白名单,您可以仅向特定 IP 地址范围内的受信任用户授予访问特定网络资源(如 URL、应用程序、电子邮件等)的权限。
如果有人使用不受信任的 IP 地址试图访问您的网络,他们将被拒绝访问。IP 白名单还使组织能够保护对网络的远程访问,包括允许员工使用自己设备的自带设备(BYOD)。
6.加密系统内部的网络流量
通过加密网络流量,您可以确保它不会被窥探网络流量的攻击者截获。
然而,服务器间通信和数据中心内部的网络流量通常不加密。如果攻击者获得了对这种网络的访问权,他们就可以拦截多机集群中服务器之间传输的数据。
为了防止攻击者通过未经授权的访问窥探数据,组织越来越多地监控自己的网络流量以检测入侵。公司可能会在其监控系统中长时间存储网络流量的副本。
如果所有网络存储受隐私保护的数据,那么使用加密是至关重要的。这适用于授权用户从数据中心外部建立的访问系统的连接,以及多服务器系统中节点之间的网络链接。
您可以在用户和系统之间使用 VPN 层,或者实施 SSL/TLS 来加密网络流量。在系统内部,可以使用 IPsec、SSL/TLS 或其他 VPN 技术来保护通信。
7.加密静态数据
静态数据加密可确保数据安全存储,而不是以纯文本形式存储。当数据被写入磁盘时,它通过一组只有系统的授权管理员知道的秘密密钥被加密。
对这些密钥的访问受到限制和控制,以确保只有特权用户才能访问和使用加密数据。这种技术保护数据免受攻击者的攻击,攻击者可能试图获得对系统的远程访问,并保护数据不被破坏。
这是保护您的数据免受任何人未经授权访问的有效方法。静态加密需要对所有可能存储数据的地方进行适当的审计,比如缓存服务器或临时存储设备。
8.确保防恶意软件保护/应用程序白名单
恶意软件是最常见的网络攻击形式之一。事实上,每 13 个网络请求中就有 1 个会导致恶意软件。这是一个困扰众多计算机系统的严重问题,并且因出现在用户不知道的不显眼位置而臭名昭著。
恶意软件是设计用来在未经用户同意或授权访问的情况下攻击或渗透计算机的软件。特洛伊木马、计算机病毒、蠕虫、恶意软件和间谍软件是一些最常见的恶意软件攻击类型。它们可以出现在电子邮件和网站上,或者隐藏在附件、视频和照片中。
这种恶意软件很容易给黑客提供未经授权的数据访问。
反恶意软件保护非常重要,因为它为您的设备建立了安全基础。运行良好的防病毒程序,避免点击可疑的电子邮件或下载不明来源的附件,并定期扫描间谍软件。
或者,更强的控制是利用应用程序白名单。它可以非常有效地防止未经授权的数据访问。
这样,您就可以识别允许在您的计算机系统上运行的已知和可信的应用程序,并拒绝所有其他应用程序。即使有人获得未经授权的访问,如果该应用程序尚未被批准为白名单应用程序,他们也无法在您的系统上运行恶意软件。
9.跟踪和管理您的风险
风险可能是对项目的绩效、预算或时间表有潜在影响的任何事情。如果这些风险变得很大,它们就会成为必须解决的漏洞,以避免网络安全攻击。
组织以有效和及时的方式识别、分类、优先化和减轻风险是至关重要的。通过在风险升级之前跟踪它们,您可以防止它们成为问题。此外,您应该制定一个应对计划来立即应对风险。
最后的想法
数据保护不是一个线性过程或一次性活动。您需要不断投入资源、时间和精力来确保安全,防止未经授权的数据访问。
网络犯罪分子每天都在变得越来越先进,他们使用最新的技术来锁定组织并获得未经授权的数据访问。
随着数据泄露事件的增加,您需要提高警惕。您必须在企业中集成强大的安全措施,每位员工都必须将网络安全放在首位。
如果您想对您现有的安全实践进行快速安全审计,请告诉我们,我们将帮助您确保您受到良好保护,免受未经授权的数据访问和其他网络威胁。
关于作者:
Steve Kosten 是 Cypress Data Defense 的首席安全顾问,也是“Java/JEE 中的 SANS DEV541 安全编码:开发可防御应用程序”课程的讲师。
新冠肺炎期间如何保护自己的心理健康?
原文:https://towardsdatascience.com/how-to-protect-your-mental-health-during-the-covid-19-3840e4015435?source=collection_archive---------53-----------------------
该项目获得了加州大学戴维斯分校 MSBA 新冠肺炎挑战赛的二等奖和最有价值的数据集。这是由、、【黄毅军】戴、凯拉邹、王浩男合作完成的。python 编码的分步指导已经在 Github 分享:https://github.com/jennnh/4G_COVID-19_Challenge
概观
新冠肺炎疫情给人们的身体健康和福祉带来了极大的威胁。然而,许多精神疾病在不被注意的情况下被同时唤醒。在美国,每个人都面临着这场 COVID 危机中的精神健康问题,这是由工作机会消失、企业倒闭以及与朋友和家人分离引起的。更糟糕的是,前国会议员 Patrick J Kennedy 说,随着资源转移到新冠肺炎救援,自杀热线电话增加了 800%。
在这种情况下,这个项目旨在对隔离期间释放人们情绪紧张的活动提出详细的建议。具体来说,我们的团队首先在不同地区和日期的 Twitter 上收集标签为 #StayHome 的推文作为数据源。第二,我们利用情绪分析和词云来理解和可视化人们的情绪。第三,我们使用主题建模找到了 13 个与活动相关的主题,并将它们与其他专栏进行交叉分析,以确定导致人们积极和消极情绪的因素。最后,我们向人们提出了建议,告诉他们应该参加什么活动,应该避免什么活动来保持快乐。
网页抓取
首先,我们需要通过网络抓取从 Twitter 上抓取数据。我们没有使用 Twitter 的免费 API,因为它只提供过去 7 天内的推文,但我们从一个月前就需要推文了。因此,我们使用了一个名为“ GetOldTweets3 ”的包,它为我们的分析提供了足够多的 Tweets。
我们想选择一些有代表性的城市进行分析。为此,我们根据约翰·霍普斯金大学 2020 年 4 月 13 日的数据,选择了 10 个既有大量人口,又有大量确诊病例的城市进行刮痧。这 10 个城市是纽约市(纽约州)、波士顿(马萨诸塞州)、芝加哥(伊利诺伊州)、底特律(密歇根州)、洛杉矶(加利福尼亚州)、休斯顿(得克萨斯州)、纽瓦克(新泽西州)、迈阿密(佛罗里达州)、费城(宾夕法尼亚州)和新奥尔良(路易斯安那州)。
之后,我们搜集了这些城市附近发布的推文。对于每条推文,我们都收集了用户的姓名、文本、推文的日期和时间、转发次数、收藏夹数和标签。刮完数据后,我们还做了一个基于每个城市新增用户比例的分层抽样。新用户由用户是否第一次发布关于#StayHome 的帖子来定义。
探索性数据分析
拿到数据集后,我们开始做一些探索性的分析。我们收集的数据集包含 2020 年 3 月 5 日至 2020 年 4 月 11 日的推文,其中包括 11631 条推文和 6741 个独立用户。下图显示了不同城市的推文数量随时间的分布情况。

不同城市的推文数量
根据图表,在大多数城市,三月下旬左右推特数量会突然增加。这是大多数城市宣布避难所到位的时候。比如蓝线之后灰色区域大大增加,纽约刚刚宣布了命令。这意味着避难所到位的公告增加了人们对新冠肺炎的认识和关注,因此人们开始非常重视“呆在家里”,并在推特上更多地谈论它。几天后,推文的数量减少了,这表明人们开始不那么关注这个问题,他们习惯了呆在家里。
自然语言处理分析
文本预处理
在 EDA 之后,我们进行了文本预处理以提高 NLP 模型的性能,包括:
- 让一切都变成小写。
- 文本去收缩。例如,将“不会”替换为“不会”,将“有”替换为“有”,将“有”替换为“会”。
- 移除奇怪的符号、网址、表情符号和#标签
- 使用 NLTK 词干的单词词条化。词汇化是将一个词的不同屈折形式组合在一起的过程,这样它们就可以作为一个项目进行分析。例如,在词汇化之后,“哭”就是“哭”。
文本预处理前后的评论比较如下:
在之前
A sunny day haiku #quarantinepoetry for an old friend down in Texas summerdaenen THANK YOU!!! VENMO @randsomnotes for a poem of your very own! #quarantinelife #stayhome #summer @New York, New York [https://www.instagram.com/p/B-29p1rp1la/?igshid=12yeaszfhp7o2](https://www.instagram.com/p/B-29p1rp1la/?igshid=12yeaszfhp7o2%27)
在之后
A sunny day haiku for an old friend down in Texas summerdaenen THANK YOU!!! VENMO @randsomnotes for a poem of your very own! @New York, New York
情感分析
我们使用“Textblob”软件包为每条推文分配一个名为“极性”的情感分数,以衡量评论的积极或消极程度。之后,我们将情绪分为积极情绪和消极情绪,阈值为 0。极性分数大于 0 的推文是正面的,极性小于 0 的是负面的,极性等于 0 的是中性的。不同情绪的推文比例如下:

根据图表,一半的推文是正面的,只有一小部分推文是负面的。这意味着没有多少人因为新冠肺炎而呆在家里做坏事。
我们还绘制了一个线形图来观察情绪如何随着时间的推移而变化,图表显示,人们在适应这种情况后开始感觉好一点了。

一段时间内推特的平均情绪
世界云
为了了解负面推文和正面推文中最常见的词是什么,我们在这两个情绪类别中分别创建了两个词云。

左:正世界云/右:负世界云
在删除这两个词云中的常用词后,我们可以看到积极的推文通常包含积极的词,如“安全”、“朋友”或“快乐”。还有像“视频”、“音乐”这样暗示积极活动的词。相反,在否定词云中,我们可以推断推文主要是在表达对生病的担忧,或者是抱怨在家待久了无聊。另外,“游戏”这个词也出人意料地出现在负面词汇 cloud 中。
主题建模
自然语言处理分析的第三部分是主题建模。首先,我们进一步预处理文本以提高主题建模的性能,包括:
- 标记化:将每个句子标记成一个单词列表
- 删除标点符号。
- 使用 NLTK 库删除停用词。停用词是非常常见的词,如“如果”、“但是”、“我们”、“他”和“他们”。我们还在这个语料库的基础上增加了多个新的常用词。
在预处理之后,我们通过 Mallet 使用潜在的 Dirichlet 分配(LdaMallet)从所有 Tweets 中提取主题。首先,我们尝试了不同数量的主题,并使用一致性值来选择最佳数量的主题。在确定选择 30 个话题后,我们得到了每个话题的关键词,并筛选出了 13 个与人们的活动相关的话题进行进一步分析。
随后,我们结合情感分析和话题建模的结果,分析哪些话题有助于人们的积极情绪,哪些会导致消极情绪。更具体地说,我们计算了每个主题的平均极性,并将结果可视化在下面的树形图中。

显示 13 个活动相关主题的平均情绪的树形图
面积和颜色由每个话题的极性决定,也就是说面积越大越暗,话题越积极。因此,左上方的活动是最积极的活动,如观看视频、捐赠以及通过文字和消息进行交流。另一方面,右下角的活动是最不积极的,比如做饭和打扫房子。
除了话题的情绪,我们还分析了不同城市最受欢迎的活动。因此,我们根据与话题相关的推文数量,列出了每个城市排名前三的活动。

不同城市的前 3 项活动
根据图表,我们得到了几个有趣的发现:
- 在许多城市,观看视频、锻炼和送货是受欢迎的活动。
- 纽约人更喜欢与朋友和家人呆在一起,而洛杉矶人最喜欢看表演和电影。
- 通过文字、信息和图片进行交流在波士顿非常流行。
- 芝加哥人特别喜欢祈祷。
除了话题,我们还想了解更多影响人们感受的具体词汇,所以我们从这些话题中挑选了一系列高频词,并计算了包含每个词的所有推文的平均极性。条形图根据单词的极性对其进行排序。浅红色的单词是最积极的,然后是暗红色和灰色的。

包含关键词的所有推文的平均极性
与主题建模结果一致,观看视频、虚拟连接和去健身房与极其积极的情绪相关。此外,像唱歌、收快递、喝酒和祈祷这样的活动也是非常积极的。值得注意的是,“游戏”一词在条形图中排名最后,这与我们认为玩游戏有助于人们感觉更好的知识不一致。
推荐
基于对话题和单字的分析,我们给感到精神不适的人以下建议:
你可以花更多的时间在这些活动上:听歌、唱歌、看电影或电视剧、锻炼、阅读,以及虚拟地与你的家人和朋友联系,即使你在物理上是遥远的。
此外,根据我们的分析,这些活动对你的情绪非常有益:
- 帮助他人,无论是分享免费食物还是捐款帮助。
- 祈祷确实有助于释放你的情绪不适。
- 网上订餐比做饭对你的情绪有更积极的影响,所以当你想享受美食时,可以考虑点外卖
- 不要整天玩游戏。没有你想的那么积极。
如何修剪决策树以充分利用它们
原文:https://towardsdatascience.com/how-to-prune-decision-trees-to-make-the-most-out-of-them-3733bd425072?source=collection_archive---------25-----------------------
用可视化来解释。

加里·本迪格在 Unsplash 上的照片
决策树是受监督的机器学习算法,通过迭代地将数据集划分为更小的部分来工作。划分过程是构建决策树的最关键部分。
分区不是随机的。目的是在每次分区时尽可能提高模型的预测性,以便模型不断获得有关数据集的信息。
例如,下面是一个深度为 3 的决策树。

深度为 3 的决策树(图片由作者提供)
第一个分区基于特征 6 (X[6]),并且能够将属于第一类(59)的所有数据实例放在树的右侧。
这清楚地表明,最大化信息增益的分区被优先考虑。信息增益可以用熵或基尼系数来量化。一般来说,信息增益与纯度的增加(或杂质的减少)成正比。
节点的纯度与该节点中不同类的分布成反比。
考虑这样一种情况,您选择一个数据实例并随机标记它。基尼系数衡量你的随机标签出错的频率。如果所有数据点都有相同的标签,那么标签总是正确的,基尼系数将为零。另一方面,如果数据点平均分布在多个标签中,随机标签通常是不正确的。因此,基尼系数随着随机性的增加而增加。
熵是不确定性或随机性的另一种度量。一个变量的随机性越大,熵就越大。

熵 vs 随机性(图片由作者提供)
选择产生更纯节点的分区。因此,当选择一个特征来划分数据集时,决策树算法试图实现:
- 更多的预测
- 杂质少
- 低熵
决策树需要仔细调整,以充分利用它们。太深的树可能会导致过度拟合。Scikit-learn 提供了几个超参数来控制树的生长。
我们将看到这些超参数是如何使用 scikit-learn 的 tree 模块的 plot_tree 函数实现的。
我将使用 scikit-learn 的 datasets 模块下的 wine 数据集。让我们首先导入库并加载数据集。
import numpy as np
import pandas as pdfrom sklearn import tree
from sklearn.datasets import load_wineimport matplotlib.pyplot as plt
%matplotlib inlineX, y = load_wine(return_X_y=True)
数据集包括属于 3 个不同类别的 178 个观察值。有 13 个特征描述了观察结果。
X.shape
(178,13)np.unique(y, return_counts=True)
(array([0, 1, 2]), array([59, 71, 48]))
我们现在可以开始用不同的超参数值构建决策树。最明显的一个是 max_depth,它在指定的深度级别停止树的生长。
clf = tree.DecisionTreeClassifier(criterion='gini', max_depth=2)\
.fit(X, y)plt.figure(figsize=(16,8))
tree.plot_tree(clf, filled=True, fontsize=16)

深度为 2 的决策树(图片由作者提供)
基于 Gini 杂质选择分区,并且树的深度是 2。Max_depth 提供了一种简单的方法来控制树的增长,这在更复杂的情况下可能是不够的。
min_samples_split 指定节点中要进一步分割的最小样本数。
clf = tree.DecisionTreeClassifier(criterion='gini', min_samples_split=10).fit(X, y)plt.figure(figsize=(20,8))
tree.plot_tree(clf, filled=True, fontsize=16)

min_samples_split=10(图片由作者提供)
我只放了一部分可视化,我们可以看到当前超参数的效果。右边的节点没有进一步分割,因为其中只有 5 个样本。如果没有 min_samples_split=10,它将被进一步拆分如下。

(图片由作者提供)
控制树生长的另一个超参数是 min _ infinity _ decrease,它设置杂质减少的阈值以考虑分区。这是一个比最大深度更好的方法,因为它考虑了分区的质量。
clf = tree.DecisionTreeClassifier(criterion='gini', min_impurity_decrease=0.1).fit(X, y)plt.figure(figsize=(10, 6))
tree.plot_tree(clf, filled=True, fontsize=16)

min _ 杂质 _ 减少=0.1(图片由作者提供)
所有隔板都实现了超过 0.1 的杂质减少。在设置这个值时,我们还应该考虑标准,因为基尼系数杂质和熵具有不同的值。
max_leaf_nodes 也可以用来控制树的生长。它限制了决策树可以拥有的叶节点的数量。叶节点是决策树末端的节点。

决策树的结构(图片由作者提供)
该树以最佳优先的方式不断增长,直到达到最大数量的叶节点。基于杂质的减少来选择最佳分区。
clf = tree.DecisionTreeClassifier(criterion='gini', max_leaf_nodes=5).fit(X, y)plt.figure(figsize=(14, 8))
tree.plot_tree(clf, filled=True, fontsize=16)

max_leaf_nodes=5(图片由作者提供)
我们已经介绍了 5 种不同的超参数,它们可以用来控制树木的生长。
- 标准
- 最大深度
- 最小 _ 样本 _ 分割
- 最小 _ 杂质 _ 减少
- Max_leaf_nodes
我们对它们逐一进行了调整,以查看各自的效果。然而,在现实生活中,这些超参数需要一起调整,以创建一个稳健和准确的模型。
如果我们过多地种植一棵树,我们很可能会有一个过度适应的模型。当一棵树与训练集拟合得太好时,就会发生过度拟合。在训练集和测试集上具有非常不同的精确度是过度拟合的强烈指示。在这种情况下,我们应该控制树的生长以获得一个通用的模型。
感谢您的阅读。如果您有任何反馈,请告诉我。
如何发布闪亮的应用程序:以 shinyapps.io 为例
原文:https://towardsdatascience.com/how-to-publish-a-shiny-app-example-with-shinyapps-io-ec6c6604d8?source=collection_archive---------20-----------------------
查看如何使用 shinyapps.io 在线部署和发布闪亮应用的分步指南(带截图)

介绍
病毒导致许多人创建了交互式应用程序和仪表盘。一位读者最近问我如何发布她刚刚创建的闪亮应用。类似于之前的一篇文章,我向展示了如何在 GitHub 上上传 R 代码,我认为这对一些人来说是有用的,看看我是如何发布我闪亮的应用程序的,这样他们也可以这样做。
在完成在线部署闪亮应用程序所需的不同步骤之前,您可以在这里查看我的应用程序的最终结果。
注 1:截图都是在 MacOS 上拍的,没有在 Windows 上测试过。请在评论中告诉我它在其他操作系统上是否相似。
注 2:有其他方法可以发布你的应用程序(比如用 Docker),但下面显示的方法(在我看来)很简单,而且效果很好。
先决条件
我个人使用 shinyapps.io 平台来部署我的闪亮应用。因此,为了遵循这个指南,你首先需要创建一个帐户(如果你还没有)。
他们提供免费计划,但你被限制在 5 个活动应用程序和每月 25 个活动小时的使用。
供你参考,如果你让你的应用程序面向广泛的受众,预计会很快超过每月活跃时间的上限。要增加每月限额(或发布 5 个以上的应用程序),您需要将您的计划升级为付费计划。
逐步指南
下面是图片中要遵循的步骤。
第一步:打开 RStudio 并创建一个新的闪亮应用程序:

第二步:给它一个名字(没有空格),选择保存它的位置,然后点击创建按钮:

第三步:以同样的方式,当你打开一个新的 R Markdown 文档时,一个基本的闪亮应用程序的代码就创建好了。单击运行应用程序按钮运行应用程序,查看结果:

步骤 4:基本应用程序打开,发布它:

第五步:如果这是你的第一个闪亮的应用程序,“从账户发布”框应该是空的。点击“添加新帐户”链接您刚刚创建的 shinyapps.io 帐户:

第六步:点击第一个备选项(ShinyApps.io):

第七步:点击你的 ShinyApps 账户链接:

第 8 步:单击仪表板按钮登录您的帐户:

第九步:点击你的名字,然后点击代币

步骤 10:如果这是你的第一个应用程序,应该还没有创建令牌。通过单击“添加令牌”按钮创建一个。然后点击显示按钮:

第 11 步:点击显示秘密按钮:

第 12 步:现在代码完成了(不再隐藏任何东西)。点击复制到剪贴板按钮:

步骤 13:复制代码并点击 OK 按钮:

步骤 14:返回 RStudio,将代码粘贴到控制台中并运行它:

您的计算机现在已被授权将应用程序部署到您的 shinyapps.io 帐户。
第 15 步:返回到可以发布应用程序的窗口,选择一个标题(不带空格)并点击发布按钮:

步骤 16:几秒钟后(取决于你的应用程序的重量),闪亮的应用程序应该出现在你的互联网浏览器中:

第 17 步:你现在可以编辑应用程序(或者用你的另一个应用程序替换整个代码),点击运行应用程序按钮再次运行应用程序。对于这个示例,我只是在侧面板中添加了一个链接以获取更多信息:

步骤 18:检查修改是否被考虑(链接如预期出现在侧面板中)并重新发布你的应用程序:

第 19 步:点击发布按钮:

第 20 步:你的应用程序是活的!您现在可以共享它,每个拥有该链接的人都可以使用它:

附加注释
您的应用程序的设置
如果您需要更改您的 Shiny 应用程序的设置,请转到您的 shinyapps.io 仪表板,然后单击您刚刚创建的应用程序来访问设置:

查看位于窗口顶部的选项卡中的不同设置,并查看 URL 字段旁边的应用程序链接:

发布数据集
通常情况下,你的闪亮应用程序使用一个默认情况下没有加载到 R 中的数据集(例如,它使用一个保存在本地计算机上的数据集)。
要使应用程序处理您的数据,您还需要在发布应用程序时发布数据(选中与您的数据对应的复选框):

将数据集与应用程序一起发布
如果您希望拥有更大的灵活性,在应用程序中使用外部数据集的另一种方法是在线托管它:
- 如果你有一个网站,你可以很容易地通过你的网站发布
- 如果你没有网站,你可以通过 GitHub 托管数据集(如果你没有账户,现在是创建一个的好时机!)
最后一步是通过新的 URL 导入数据(将数据导入到应用程序的代码中)。
感谢阅读。我希望这篇教程能帮助你发布你的第一个闪亮的应用。
和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。
相关文章
- 如何在 GitHub 上上传 R 代码:MacOS 上的 R 脚本示例
- 新型新冠肺炎冠状病毒前 50 名资源
- R 中的相关图:如何突出显示数据集中最相关的变量
- 一个闪亮的手工线性回归应用程序
- 如何在 blogdown 中嵌入闪亮的 app?
原载于 2020 年 5 月 29 日 https://statsandr.com。
如何使用 Python 请求从 API 中提取数据
原文:https://towardsdatascience.com/how-to-pull-data-from-an-api-using-python-requests-edcc8d6441b1?source=collection_archive---------0-----------------------
技术应用编程接口指南

从 API 中自动检索数据至关重要。
我被反复要求做的事情是从 API 中自动提取数据。尽管我拥有“数据科学家”的头衔,但我在一个小团队中,所以我不仅负责构建模型,还负责提取数据、清理数据,以及将数据推送到任何需要的地方。你们中的许多人可能都在同一条船上。
当我第一次开始学习如何发出 HTTP 请求、取回 JSON 字符串、解析它,然后将它推入数据库时,我很难找到清晰、简洁的文章来解释如何实际完成这项非常重要的任务。如果你曾经为了解决一个技术问题而陷入谷歌黑洞,你可能会发现非常技术化的人喜欢使用技术语言来解释如何执行给定的任务。问题是,如果你像我一样是自学的,你不仅要学习如何完成要求你做的任务,还要学习一门新的技术语言。这可能会令人非常沮丧。
如果你想避免学习技术术语,直接切入正题,那你来对地方了。在本文中,我将向您展示如何从 API 中提取数据,然后自动执行每 24 小时重新提取数据的任务。对于这个例子,我将利用 Microsoft Graph API 并演示如何从电子邮件中提取文本。我将避免使用预先准备好的 API 包,而是使用 Python Requests 包来处理 HTTP 请求——这样,您就可以将您在这里学到的知识应用到您需要使用的几乎任何其他 RESTful API 上。
如果你在本教程中遇到 API 请求的问题,这里有一个提示:使用邮递员。Postman 是一个非常棒的应用程序,它允许你通过一个干净的界面来设置和调用 API。它的美妙之处在于,一旦您让 API 调用工作,您就可以用 Python 导出代码,然后将其直接粘贴到您的脚本中。太神奇了。
*注意:本教程旨在提供一种简单易懂的访问 API 的方法,仅此而已。它可能无法满足您的具体情况或数据需求,但应该有望让您走上正确的道路。我发现下面的方法是最容易理解的快速获取数据的方法。如果你有让事情变得更简单的建议,请在评论中提出来。
API 文档
没有办法浏览 API 文档。要使用 Outlook,您需要到这里。如果您成功地完成了本教程,并希望使用 API 做更多的事情,请使用该链接作为参考。
授权
大多数 API,包括 Microsoft Graph,在给你一个允许你调用 API 的访问令牌之前都需要授权。对于不熟悉从 API 中提取数据的人来说,这通常是最困难的部分(对我来说就是这样)。
注册你的应用
按照这里的说明注册你的应用(这些很简单,使用 Azure GUI ),你需要一个学校、工作单位或个人的微软账户来注册。如果你使用工作邮件,你需要 Azure 实例的管理员权限。如果你是为了工作而这样做,请联系你的 IT 部门,他们可能会为你注册该应用程序。选择“web”作为你的应用类型,并为你的重定向 URI 使用受信任的 URL(只有你有权访问底层 web 数据的 URL)。我使用了 franklinsports.com,因为只有我的团队可以访问那个网站的数据。如果您正在构建一个应用程序,您将重定向到您的应用程序,在那里您的应用程序可以获取代码并授权给用户。
启用 Microsft 图形权限
应用注册后,请转到应用注册门户:

点按显示您的应用名称的位置:

在接下来的页面中,单击“查看 API 权限”。
最后,选择 Microsoft Graph,然后选中“委托权限”消息下的所有复选框(注意,在本例中,我将只从单个登录用户处获取电子邮件,要获取某个组织的电子邮件数据,您需要应用程序权限,请遵循此处的流程)。

好了—您已经准备好开始进行 API 调用了。
授权步骤 1:获取访问代码
您将需要一个访问代码来获得访问令牌,这将允许您调用 MS Graph API。为此,请在您的浏览器中输入以下 URL,用您的应用程序页面上显示的信息交换相应的凭据。
放在 URL 中:
将代码片段输出的 URL 粘贴到您的浏览器中。点击回车键,你将被要求授权你的微软账户进行授权访问。使用您用来注册应用程序的 Microsoft 帐户。
如果授权不起作用,则您选择的重定向 URL 或应用程序注册有问题。我以前在这一部分遇到过麻烦——所以如果你第一次尝试没有成功,不要担心。如果授权成功,您将被重定向到您在应用程序注册中使用的 URL。追加到 URL 的参数将包含您将在下一步中使用的代码,它应该是这样的:

获取完整的代码,并将其保存在 python 脚本中。
授权步骤 2:使用您的访问代码获取一个刷新令牌。
在继续之前,确保您已经安装了最新版本的 Python 请求包。最简单的方法是使用 pip:
在这一步中,您将使用步骤 1 中生成的代码,并向 MS Graph OAuth 授权端点发送一个 POST 请求,以获取一个刷新令牌。(*注意:出于安全考虑,我建议将 client_secret 存储在不同于用于调用 API 的脚本中。您可以将这个秘密存储在一个变量中,然后导入它(或者使用 pickle,您将在下面看到)。
将代码片段中的######与您自己的应用程序信息和您在步骤 1 中收到的代码交换,然后运行它。(*注意:重定向 URI 必须是 url 编码的,这意味着它看起来像这样:“https % 3A % 2F % 2 ffranklinsports . com”)
您应该会收到类似如下的 JSON 响应:
{ ' access _ token ':' # # # # # # # # # # # # # # # # # #,' refresh _ token ':' # # # # # # # # # # # # # # # ' }
授权步骤 3:使用您的刷新令牌获取访问令牌
此时,您已经有了一个访问令牌,可以开始调用 API,但是,该访问令牌将在一段时间后过期。因此,我们希望设置我们的脚本,在每次运行它时获取一个新的访问令牌,这样我们的自动化就不会中断。我喜欢将步骤 2 中的新 refresh_token 存储在 pickle 对象中,然后在脚本运行时加载它以获得新的 access_token:
filename = ####path to the name of your pickle file#######
print(filename)
filehandler = open(filename, ‘rb’)
refresh_token = pickle.load(filehandler)url = “https://login.microsoftonline.com/common/oauth2/v2.0/token" payload = “””client_id%0A=##########& redirect_uri=##################& client_secret=##################& code={}& refresh_token={}& grant_type=refresh_token”””.format(code,refresh_token)
headers = { ‘Content-Type’: “application/x-www-form-urlencoded”, ‘cache-control’: “no-cache” } response = requests.request(“POST”, url, data=payload, headers=headers)
r = response.json()
access_token = r.get(‘access_token’)
refresh_token = r.get(‘refresh_token’) with open(filename, ‘wb’) as f:
pickle.dump(refresh_token, f)
调用 API 并清理和解析 JSON
有了 access_token,就可以调用 API 并开始提取数据了。下面的代码片段将演示如何检索最近 5 封带有特定主题参数的电子邮件。将 access_token(下面加粗)放在头中,并在 get 请求中将其传递给电子邮件消息端点。
import json
import requestsurl = ‘[https://graph.microsoft.com/v1.0/me/messages
$search=](https://graph.microsoft.com/v1.0/me/messages?$search=)"subject:###SUBJECT YOU WANT TO SEARCH FOR###”’headers = {
‘Authorization’: ‘Bearer ‘ +**access_token**,
‘Content-Type’: ‘application/json; charset=utf-8’
}r = requests.get(url, headers=headers)files = r.json()print(files)
上面的代码将返回一个包含您的数据的 json 输出。
如果你想要 5 封以上的邮件,你需要对结果进行分页。大多数 API 都有自己的方法来实现结果的最佳分页(在英语中,大多数 API 不会只通过一次 API 调用就提供您想要的所有数据,所以它们提供了进行多次调用的方法,允许您在结果中逐块移动,以获得您想要的全部或尽可能多的数据)。MS Graph 很好,因为它提供了获取下一页结果所需的确切端点,使分页变得容易。在下面的代码片段中,我演示了如何使用 while 循环对 api 进行连续调用,并将每封电子邮件的主题和文本添加到列表列表中。
emails = []
while True:
try:
url = files[‘[@odata](http://twitter.com/odata).nextLink’]
for item in range (0,len(files[‘value’])):
emails.append(files['value'][item]['Subject'],[files[‘value’] [item][‘bodyPreview’])
r = requests.get(url, headers=headers)
print(r.text)
files = r.json()
except:
break
把数据放在某个地方
最后,我将展示一个例子,展示如何将 JSON 数据放入 CSV 文本文件,然后可以用 excel 对其进行分析或将其放入数据库。这段代码将演示如何将我们的列表中的每一行写入一个 CSV 文件。
import csv write_file =‘###LOCATION WHERE YOU WANT TO PUT THE CSV FILE###’
with open(write_file,’w’, newline = ‘’) as f:
writer = csv.writer(f, lineterminator = ‘\n’)
writer.writerows(emails)
使自动化
既然我们的剧本已经写好了。我们希望将其自动化,这样我们就可以在每天收到新消息时,在我们的参数范围内获取它们。
我用两种方法做到了这一点,然而,还有许多自动化的方法:
- 在 Ubuntu 服务器上使用 Crontab
这很简单。如果你用的是 Ubuntu,在你的控制台上输入“crontab -e ”,它会在一个文本文件中打开你的 cronjobs。转到新的一行,键入:
0 1 * * * /full path to python environment/python /full path to file/example.py
假设 cron 设置正确,上面将脚本设置为每天在 1 UTC 自动运行(或者服务器所在的时区)。您可以通过更改代码中的 1 来更改时间。如果你想了解 cron 计时的复杂性,这个网站是一个不错的资源。
2.使用 Windows 任务调度器
这是在使用任务计划程序的 windows 中实现自动化的一种简单又好的方法。只需打开任务计划程序,然后单击右侧的“创建任务”。这个应用程序非常简单,允许你使用 GUI 设置时间表和你想运行的程序。
当您在“操作”中感到痛苦时,选择 Python 作为程序,然后在“添加参数”选项卡(旁边带有“(可选)”的选项卡)中,将路径放入您的。py 文件。

就是这样!
在本演练中,我向您展示了如何从 Microsoft Graph API 中提取电子邮件数据。这里演示的原则可以用于几乎任何 RESTful API,或者使用 Microsoft Graph 执行更复杂的任务(我已经使用 MS Graph API 将文件推入和推出我们公司的 sharepoint,将 sharepoint 文件夹中的数据推入我们的数据库,以及发送自动电子邮件和报告)。
有问题或意见吗?你可以给我发电子邮件,地址是 cwarren@stitcher.tech,或者在 Linkedin 上关注我,地址是https://www.linkedin.com/in/cameronwarren/
我还提供数据服务,你可以在 http://stitcher.tech/了解更多。
如何量化数据质量?
原文:https://towardsdatascience.com/how-to-quantify-data-quality-743721bdba03?source=collection_archive---------9-----------------------
入门
从单独的数据质量指标到统一的分数。
在本文中,我将解释计算统一数据质量分数背后的概念,因为它在IBM Cloud Pak for Data和IBM Information Server/Information Analyzer中用于量化结构化数据的质量。

图卡皮克关于 https://pixabay.com/users/tookapic-1386459/的图片
需要一个简单的数据质量分数
衡量数据质量并不是一个新领域。 IBM Information Analyzer 和其他数据分析工具已经上市十多年了,帮助数据工程师更好地了解他们的数据中有什么,以及他们可能需要修复什么。
在数据概要分析的早期,尽管这些工具可以提供丰富的功能来查看数据集的质量,但回答这些简单的问题并不容易:
这个数据集的整体质量有多好?
这两个数据集哪个数据质量更好?
与上月相比,该数据集的数据质量如何?
即使像早期一样使用单一的数据分析工具,如 IBM Information Analyzer,您也可以通过使用不同的特性从完全不同的角度来评估数据集的质量:
- 您可以使用数据探查器收集的统计信息来确定在数据集中检测到的哪些值或格式应该在每一列中被视为有效或无效。
- 您可以将每一列的域有效性定义为有效值的最小/最大范围,或者将它指向一个引用值列表。
- 您可以为每一列检测或分配数据类,并搜索与预期数据类不匹配的值。
- 您可以查看缺失的值。
- 您可以识别主键候选项并搜索意外的重复值。
- 您可以识别表之间的主键-外键(PK-FK)关系,并在外键列中搜索在该关系的主键中找不到的孤立值。
- 您可以定义数据规则来设置对数据的任何非平凡的额外期望。
此列表仅涵盖了信息分析器的数据分析和质量特性可以告诉您的数据。 IBM Information Server 套件的其他组件,如 QualityStage 可以为您提供其他数据质量信息,如重复的行,或缺乏适当标准化的值等
尽管这些特性本身都很强大,并且可以为专家提供有趣的单个指标,但是它们的结果并不适合回答本文引言中列出的简单问题。其主要原因是人类不擅长相互比较多维度量,特别是如果那些结果不包括完全相同的度量,或者是从具有不同数量的行、列的不同数据集计算的,或者具有它们应该匹配的不同约束/规则。
随着数据湖、数据科学、数据治理和所有这些围绕数据的新型活动的出现,数据目录变得越来越重要,数据质量变得不仅对专家用户重要,而且需要让非专家也能理解。
在之前的文章中,我展示了如何自动获取、分析、编目、管理大量数据集,并提供给数据科学家或数据分析师等消费者。这些用户需要在自助服务模式下找到具有正确质量的正确数据集。在这种情况下,很明显需要一个更简单的指标来更好地了解数据集的质量水平,而不必查看细节,即使这些细节在第二次查看时仍然可用。
这就是为什么数据质量的概念在 IBM Information Server 和现在的IBM Cloud Pak for Data/Watson 知识目录中引入的原因。

数据质量分数显示在数据 UI 的云包中
但是如何设计一个好的数据质量评分呢?
考虑到数据质量可以从非常不同的角度来看,并且可以用非常不同的度量标准来衡量,例如我前面列出的几个度量标准,计算质量分数的公式不一定是显而易见的。为了更好地理解它在 IBM 产品中是如何计算的,让我们先来看看我们对这样一个分数的要求:
- 数据质量分数应该简单易懂:当查看目录中的大量数据集时,应该可以快速识别高质量或低质量的数据集,而不必查看细节。
- 数据质量分数应该不依赖于数据集上设置的行数、列数或约束条件:例如,如果通过分析数据集的所有行来计算,就像在较小的样本上计算一样,则大型数据集的数据质量分数应该或多或少是相同的——假设采样足够好,足以具有统计代表性。
- 数据质量分数应该与其他数据质量分数具有可比性,即使每个分数使用的指标不同和/或比较的数据集具有不同的行数和列数——请参见前面的要求。
- 数据质量得分应该是标准化的:它应该提供一个清晰的最低和最高可能得分的范围,以便用户可以看到数据集的数据质量离理想值有多远。
为了定义一个公式,将各种数据质量函数计算出的不同指标转换为符合这些要求的分数,我们首先需要将我们所理解的数据质量(一般而言)和数据质量分数(具体而言)的概念形式化。
数据质量有许多定义。你可以在维基百科上看到其中的一些。但是一个简单的定义可以是:
衡量数据集的数据质量就是衡量数据集与您对数据的期望的匹配程度。
这意味着数据质量分数只能取决于您对数据的期望,而不是一些原始的调查结果。
这听起来可能是显而易见的,但这意味着,如果我们在一列中发现大量缺失值,但我们确实期望该列中有缺失值,或者我们不关心那里的缺失值,那么数据集的数据质量分数不应因发现的缺失值而降低。
这也意味着,如果我们对数据没有具体的期望,那么数据质量分数应该是最大的,不管数据中有什么。
这些简单明了的事实对于建立乐谱的架构非常重要。
约束的概念和数据质量问题
让我们定义几个在数据质量分数计算中起重要作用的概念:
我们对数据的期望就是我们所说的约束。约束可以用非常不同的形式表示:
- 它可以是在列上设置的简单标志,以指示该列中的值不应该为空,或者应该是不同的,或者不应该是有符号的。
- 它可以是列的域有效性的定义,设置为最终的最小或最大允许值,或者是指向定义列的可接受域的参考值列表的指针
- 它可以是分配给列的数据类,不仅描述列的内容,还可以用于识别不符合列的预期域的值。
- 它可以是两个数据集之间的标识关系,设置多个列之间的相关性或函数依赖关系。
- 它可以是一个数据规则,表达一个非平凡类型的约束,甚至可能涉及多个表。
只要数据不满足其中一个约束条件,我们就会遇到数据质量问题。
一个数据质量问题是一个特定的数据质量问题类型的报告,或者是一个数据集的一个单元格,或者一行,或者一列或者一组列,或者是整个数据集。数据质量问题报告的数据质量问题类型取决于数据不满足的约束类型。
数据质量问题可以在列或数据集上以一定的频率检测到。相对频率,计算为有质量问题的列/数据集的所有值的百分比,我们称之为问题的普遍性。
例如,如果数据集有 100 行,并且在标记为强制或不可空的列中检测到 15 个缺失值,则在此列上报告问题类型 【缺失值】的数据质量问题,其发生率为 15% 。
隐式或显式约束以及数据质量问题的置信度概念
除了流行度之外,数据质量问题可能与置信度相关联。置信度表示报告的问题是真实问题的概率。
为了更好地理解这一概念,您需要理解,并非所有对数据设置的约束都是由人指定或确认的明确约束——我们将这种指定或确认的约束称为显式约束。
如果数据质量仅基于显式约束来衡量,那么我们就不需要置信度的概念,因为所有由人指定的约束,如果不被某些数据所尊重,就会导致 100%置信度的数据质量问题——我们肯定知道这个问题是一个真实的问题,因为有人已经指定任何不满足这个约束的东西都应该被认为是数据质量问题。
但是,如果我们只查看显式约束,那么所有数据集都将以 100%的分数开始,直到有人花时间查看它并指定约束。这将导致大量数据集出现高质量的假象,或者导致需要管理员仔细检查每个摄取的数据集的过程,这对于大规模导入来说不太适合。
因此,在数据质量分析期间,系统可能会根据数据中看到的内容,尝试猜测一些约束条件。例如,如果一列的大部分数据不为空,或者它们使用相同的格式或者具有任何类型的可识别模式——即使一些值不遵循这些模式——那么系统可以假设存在隐含约束,并且不满足该约束的值可能是数据质量问题。
由于一个隐含约束是由系统从数据中看到的推断出来的,它与一个置信度的概念相关联,确定系统有多确定这应该是一个真实约束。
例如,如果一列中 95%的值是 5 位数,但是 5%的值具有完全不同的格式,则系统可以——根据设置——假设在该列上有一个隐式约束,即值应该具有 5 位数,置信度为 95%。如果用户检查这个隐式约束并确认它,那么它将成为一个显式约束,其置信度为 100%。
检测到的质量问题的普遍性和可信度将用于计算实际质量分数。
将它们放在一起形成一个统一的质量分数
既然我们已经介绍了在数据质量分数中起作用的所有重要概念,让我们看一个简单的例子,看看如何在 IBM Cloud Pak for Data 或 Information Analyze r:
让我们假设一个简单的数据集,有 3 列 6 行,以及以下确定的数据质量问题:

已识别的数据质量问题及其可信度
- 第 1 行违反了数据规则。由于数据规则是由用户指定的,所以它是一个显式约束,问题的置信度为 100% 。
- 行#3 是一个重复行,但是没有明确的约束表明不允许重复行。但是,根据数据,分析确定有 70%的可能性该数据集不应该出现重复行。= >数据集上有一个隐含约束,用 70%的置信度表示不应该有任何重复记录。
- 第 2 行第 1 列的单元格不满足隐含约束,其置信度为 80% 定义了有效域应该是什么。例如,如果分析确定该列的推断数据类的置信度为 80%,并且该单元格中的值与该数据类不匹配,则可能会出现这种情况。
- 列 Col 2 已经设置了一个显式约束,表示该列中的所有值都应该不同,但是分析发现其中有 20%的重复值。这导致了一个数据质量问题,其置信度为 100% 且发生率为 20% 。
- 除此之外,行#4 中第 2 列的值缺失,并且存在置信度为 90% 的隐含约束,即该列中不应出现缺失值。
- 最后,第 5 行/第 3 列的单元格似乎是该列的异常值,其置信度为 60%** 。离群值总是隐含的约束,因为没有硬性的规则来定义一个值何时是离群值。**
单个细胞的数据质量得分
请注意,单个单元格、列或行可能有一个以上的数据质量问题,如果可能,不应重复计算该问题:如果单个值违反了其预期的数据类和预期的格式,则不应加倍惩罚该列或数据集的数据质量分数,因为无论该值有多少个问题,都只有一个值是无效的。
基于此,数据集的单个单元格的得分可以计算为该值完全没有问题的概率。这可以计算为 100%减去在单元上检测到的每个问题的置信度的乘积。举例来说:如果我们有 90%的把握某个单元格存在问题,那么这些值没有问题的概率是 100–90 = 10%。如果问题的置信度为 100%(对于显式约束),则该值没有问题的概率为 100–100 = 0%
对于在数据集的单个单元格上报告的数据质量问题,计算单元格得分的公式如下。

单个单元的质量分数,仅考虑单元级别报告的问题
如果一个单元有两个问题,一个置信度为 80%,另一个置信度为 60%,那么第一个问题不真实的概率是 100%-80%=20%,第二个问题不真实的概率是 100%-60%=40%,根据概率定律,这些问题都不真实且该单元没有数据质量问题的概率仅为 20%乘以 40% = 8%。
请记住,我在本文开头提到过,数据质量问题也可以针对完整的行、完整的列或完整的数据集进行报告。我们需要分配这些问题对细胞得分的影响。
对于针对完整行报告的问题,这很容易,因为如果该行无效,我们可以假设该行的所有值都无效。这些问题对细胞评分的影响可以计算如下:

仅考虑行级别报告的问题的单元的质量分数
conf(pb[row]) 在这里表示为被测量的单元的行报告的一个行级数据质量问题的置信度。
但是,整个列报告的问题需要通过使用问题的普遍性在该列的所有值中平均分布。普遍性告诉我们, n% 的价值观受到了问题的影响,尽管我们并不确切知道哪些价值观有问题,哪些没有。因此,每个值的得分将降低一个系数,该系数等于流行率乘以问题真实存在的置信度,如下式所示:

仅考虑在列级别报告的问题的质量分数
conf(pb[col]) 表示针对被测量单元的列报告的一个列级数据质量问题的置信度,而 prev(pb[col]) 表示其出现率——具有该问题的列中的值的百分比。
针对整个数据集报告的数据质量问题的影响以相同的方式分布在所有像元中:

仅考虑在数据集级别报告的问题的质量分数
考虑到单元本身、其列、其行或数据集上报告的所有问题,单个单元的最终数据质量得分可计算如下:

考虑所有问题的单元的质量分数
列的数据质量分数
前面的公式为数据集的每个单个像元计算 0%到 100%之间的标准化数据质量分数奠定了基础。基于这一点,计算任何列的数据质量分数就像计算该列的每个值的数据质量分数的平均值一样简单。

列的质量分数
行的数据质量分数
同样,可以通过对该行的每个单元格计算的分数进行平均来计算数据集的任何行的分数。

行的质量分数
数据集的数据质量分数
计算数据集的数据质量分数就像计算每列分数的平均值或每行分数的平均值一样简单。

数据集的质量分数
请注意,这也等同于计算所有单元格得分的平均值。由于公式的对称性,所有这些计算将返回相同的结果,这使得它很优雅。
示例:
让我们将这些公式应用到之前的具体例子中:

计算的数据质量分数
使用前面的公式,您可以计算每个单元格、每列或每行的质量分数,对单元格分数、列分数或行分数进行平均,您将返回代表数据集数据质量分数的相同结果(55%)。
然后,报告可以深入查看任何列或行,并显示有关其数据质量分数的更多详细信息,哪些行或列对数据集分数的影响最大,等等。这种深入查看功能对于数据清理操作非常有用。
摘要
我们已经看到了为每个数据集建立统一的标准化数据质量分数的重要性,这样非数据质量专家也可以使用它。我们已经看到,这样的数据质量分数应该满足什么要求,即使在具有不同结构或约束的数据集需要相互比较的重要情况下也是有用的。我们终于看到了这个数据质量分数是如何在 IBM 产品组合中实现的。
利用蒙特卡罗量化模型预测误差
原文:https://towardsdatascience.com/how-to-quantify-the-prediction-error-made-by-my-model-db4705910173?source=collection_archive---------19-----------------------
蒙特卡洛模拟证明
预测是非常困难的,尤其是关于未来的时候。—尼尔斯·玻尔
作为一名在工程领域工作的数据科学家,我经常与物理学方面的其他研究工程师合作,任务是开发定量模型来预测感兴趣的物理现象。然而,获得可靠的预测从来都不容易,主要是因为我很少能确定模型超参数的正确值。那些传达特定物理解释的超参数通常通过噪声实验来校准。因此,由于校准过程中固有的随机性,无法确定它们的精确值。简单来说,那些超参数是不确定的。
我通常有两个选择:一,我可以只选择超参数的名义值(或最可能值)并基于它们进行预测,希望获得的结果是准确的或至少接近事实;第二,我可以接受这些超参数不确定的事实,并使用适当的不确定性传播技术将不确定性从模型超参数传播到模型的预测误差/不确定性。
在实践中,第二种选择通常是首选。在这种情况下,预测输出将不仅仅是一个值。相反,我们将得到它的完整的概率分布。这是有利的,因为该选项的结果提供了更多的信息,因为它为我们提供了与我们的预测相关联的置信度,从而实现了我们量化预测误差的目标。

图 1 虽然选项(a)仅选取单个输入值,但选项(b)承认输入是不确定的,并通过模型将这些不确定性传播到输出。(图片由作者提供)
在本文中,我们将介绍一种有用的技术来实现预测误差的不确定性传播和量化。文章的其余部分结构如下:
- 动机:什么是前向不确定性传播?
- 解决方案:基于抽样的蒙特卡罗方法
- 插图:一个简单的案例研究
- 摘要:挑战和应对措施
所以让我们开始吧!
1.正向不确定性传播
如前所述,建模者经常需要解决不确定的超参数问题,这很容易损害模型预测的可靠性。在此背景下,提出了前向不确定性传播策略,以充分考虑输入参数的不确定性,量化诱导的预测不确定性。
形式上,前向不确定性量化的主要目标是评估在各种输入不确定性的影响下输出的变化。
Forward 这里指的是不确定性信息从输入,通过正在研究的物理模型,流向输出。根据分析师的目标,向前不确定性传播的重点可能是简单地估计基本统计数据(例如,平均值、方差等)。)或输出值超过某个阈值的概率(即风险分析),或输出的整个概率密度函数(PDF)。
前向不确定性传播属于计算科学与工程中不确定性管理的一个更大的研究领域,其中传播构成了朝向管理目标的一个主要步骤。读者可以在我之前发表的博客中找到不确定性管理的更多细节:计算科学与工程中的不确定性管理。
在实践中,设计了几种方法来传递期望的前向不确定性传播。这些方法包括概率分析法、摄动法、谱方法等。通常,这些方法涉及大量的数学推导,并且它们的实现远非简单明了。除此之外,它们可能只对特定问题有效,并且可能只在超参数的不确定性水平较小时才是准确的。因此,这些方法还没有在工业实践中广泛采用,本文也不讨论。相反,我们将关注一个更受欢迎的方法:蒙特卡洛模拟。
2.蒙特 卡罗模拟
直观易懂,易于实现,无需对模型进行额外的修改(或者如果您喜欢技术术语的话,称为非侵入式),高度并行化,对模型及其相关的超参数做最少的假设。听起来像是每个从业者都会喜欢的方法,对吗?事实上,正是这些特性使得蒙特卡罗模拟成为实现不确定性传播的最流行的方法。
从技术上讲,蒙特卡罗模拟包括从输入概率分布中抽取随机样本,并使用自己的模型计算每个样本的相应响应。然后可以基于获得的结果集合来推断输出的统计。
蒙特卡洛模拟的工作流程可总结如下:
- 从模型超参数的分布中随机抽取个样本。这里,每个样本对应于模型超参数的特定组合。
- 对于模型超参数的每个组合,将它们插入到模型中,并使用这个新配置的模型进行预测。在这一步的最后,我们将获得一组预测。
- 基于这种预测的集合,我们可以很容易地估计各种感兴趣的统计数据,从简单的平均值和方差到完整的概率密度函数。
您可能已经注意到,要开始蒙特卡罗模拟,我们需要知道不确定模型超参数的概率分布。这一点很重要,因为如何对输入进行统计建模将直接影响输出的不确定性。在实践中,贝叶斯统计通常用于从现有数据(例如,实验的和计算的)中导出目标概率分布。在其他情况下,这些概率分布可以由领域专家根据他们的经验和判断简单地分配。在这种情况下,认知的不确定性可能被引入不确定超参数的统计建模中。
3.案例研究:大炮射击
现在,让我们看看蒙特卡洛模拟在实践中是如何使用的。这里我们考虑一个抛体运动问题,我们感兴趣的是计算大炮的射程。在现实生活中,这种分析可以用来推导成功摧毁敌方目标的概率。
我们的物理模型很简单,其中射击距离 R 由初速度 v ₀、射击角度 θ 以及重力加速度 g 、决定,如图 2 所示(如果你对如何推导这个方程感兴趣,这里是链接)。这是一个简单的模型,因为没有考虑空气阻力的影响。然而,对于我们的演示目的来说,这已经足够好了。

图 2 火炮射击案例研究示意图。(图片由作者提供)
现在,假设我们不太确定 v ₀和 θ 的值,但我们知道 g =9.8m/s。因此,在我们当前的案例研究中, v ₀和 θ 被视为不确定模型超参数。为了描述它们的不确定性,我们为 v ₀选择了一个正态分布,为 θ 选择了一个均匀分布:

图 3 我们给 v ₀分配一个正态分布,给 θ分配一个均匀分布。(图片作者 )
对于初速度 v ₀,其平均值为 150m/s,标准偏差值为 5m/s,对于射击角度 θ ,其不确定度范围从 40ᵒ到 50ᵒ.由于模型超参数( v ₀和 θ )中嵌入的不确定性,我们对射程 R 的预测也将是不确定的。现在我们的目标是准确量化我们的 R 预测的不确定性,并推导出它的全概率分布。
是时候应用蒙特卡罗程序了。按照上一节概述的步骤,我们首先从各自的分布中抽取 10000 个随机样本 v ₀和 θ (图 3)。为此,可以使用 Numpy 的随机数生成器。随后,对于 v ₀和 θ 的每个组合,我们计算相应的 R 值。
图 4(a)描绘了基于 v ₀和 θ 的一些选定样本的几个计算轨迹。我们可以看到,当初始拍摄条件(即 v ₀和 θ )变化时,这些轨迹有很大不同。这表明 v ₀和 θ 的不确定性的影响是不可忽略的。

图 4 我们的火炮射击案例的蒙特卡罗结果。(a)中的红线代表使用 v ₀和 θ的标称值计算的火炮弹道。其计算的 R 值在(b)中用红色虚线表示。(图片作者 )
R 对应的直方图如图 4(a)所示。在这里,我们可以看到射击场 R 的分布呈钟形,中心在 2270 米左右。另一方面,红色虚线的 R 值为 2296 米,是利用 v ₀和 θ 的标称值,即 150m/s 和 45ᵒ.计算出来的请注意,这两个 R 值并不相同。当基础模型是非线性的时,这是很常见的(就像我们当前的情况)。这一观察还告诉我们,简单地插入输入的最可能值一般不会产生输出的最可能值。这表明执行严格的不确定性传播分析的重要性。
4.挑战和解决方案
正如每个硬币都有两面一样,蒙特卡洛方法也有其自身的缺点。在本节中,我们将讨论在实践中实施蒙特卡罗技术时的主要挑战和可能的补救措施。
对蒙特卡罗方法的主要批评在于它的收敛速度慢。这意味着我们需要大量的样本(∼ o(10⁴)来确保蒙特卡罗结果的可靠性。因此,我们需要重复计算每个样本的模型预测,从而潜在地导致令人望而却步的计算成本。在下文中,我们介绍两种流行的方法来解决这个收敛问题。
4.1 智能采样方案
当使用蒙特卡罗方法时,我们可以做的第一件事是改进抽样方案。简单的蒙特卡罗方法利用随机抽样来完成这项工作。该采样方案不是特别好,因为它在参数空间中产生了明显的“簇”和“洞”(我们将在后面说明这一点)。因此,我们需要大量样本来覆盖整个参数空间。
相反,研究人员提出了更先进的采样方案,具有更好的“空间填充”属性,这意味着这些方案可以在参数空间中更均匀地生成样本。这一类的例子有拉丁超立方体采样,还有 Sobol 序列和 Halton 序列,都是低差异序列。
图 5 比较了应用于 2D 参数空间的各种采样方案,样本数量相同。这里我们可以看到,随机采样方案往往会形成团块并留下空隙,而其他高级采样方案能够生成更多的“空间填充”样本。

图 5 在 2D 参数空间中由各种采样方案产生的样本。(图片由作者提供)
4.2 代理建模技术
另一种避免高计算成本问题的方法是采用代理建模技术。这背后的核心思想是训练廉价的统计模型来近似(或“替代”)原始物理模型,例如图 2 中的抛射体运动模型。之后,蒙特卡罗方法可以直接应用于训练的统计模型。由于统计模型的一次评估涉及可忽略不计的计算成本,蒙特卡罗程序的总费用变得可以承受。
代理建模的核心是监督机器学习,因为目标是基于输入数据和相应的标记输出数据来训练代理模型。许多机器学习技术,如支持向量机、高斯过程、神经网络等。已经被用于加速蒙特卡罗模拟。随着越来越多强大的机器学习技术不断被开发出来,我们可以期待蒙特卡洛模拟的准确性和效率将会进一步提高。
5.关键要点
- 前向不确定性传播对于估计由不确定模型超参数引起的模型预测误差/不确定性是至关重要的。
- 蒙特卡罗模拟是实现不确定性传播的最流行的方法之一。
- 蒙特卡洛模拟在计算上可能是昂贵的,因为可能需要许多样本来确保准确性。
- 更智能的采样方案和代理建模技术有助于减轻与蒙特卡罗模拟相关的高计算成本
延伸阅读:
[1]阿特·b·欧文,蒙特卡洛理论、方法和实例,2013 年
关于作者
我是一名博士研究员,致力于航空航天应用的不确定性量化和可靠性分析。统计学和数据科学是我日常工作的核心。我喜欢分享我在迷人的统计世界中学到的东西。查看我以前的帖子以了解更多信息,并在 中 和Linkedin上与我联系。
如何在 BigQuery 中查询和计算 GA4 事件数据
原文:https://towardsdatascience.com/how-to-query-and-calculate-ga-app-web-event-data-in-bigquery-a77931176d3?source=collection_archive---------5-----------------------
Google Analytics 4 基于事件的报告示例(之前为 App + Web)
应用程序和网络分析的未来就在这里:谷歌在谷歌分析中宣布了一种新的衡量方式。虽然仍处于测试阶段,但这是网络和应用分析的一次小革命。
最重要的是:所有(甚至非 360)谷歌分析账户都有一个原始数据 BigQuery 导出。让我们开始吧!
注:你喜欢这篇文章吗?那么你也会喜欢我的新网站GA4BigQuery.com:一个关于如何在 BigQuery &摇滚你的数字营销分析中查询谷歌分析数据的数字指南🤘
您可能也会对我与 Mari 和 Simo Ahava 共同设计的数字课程感兴趣,该课程面向希望深入查询世界的营销专业人士,以及需要掌握 GA4 特定知识的数据专业人士:
[## 在 Google BigQuery 中查询 GA4 数据
关于如何使用 Google BigQuery 访问 Google Analytics 4 生成的原始数据的在线课程。一门必学的课程…
www.teamsimmer.com](https://www.teamsimmer.com/checkout/ga4-google-bigquery/bq-course-page/) 
图片由柏柏尔人 Bijlsma
在本文中,我将只关注 web 数据。我将向您展示如何计算新的 GA4 参与度指标,以及如何复制在 GA4 用户界面中再也找不到的“经典”Google Analytics 维度和指标。但是要小心…
这不是万能分析。尝试将新的测量模型视为超越 Universal Analytics 所能做到的机会,而不仅仅是填充 GA 古老数据模型的另一种方式。(来源)

App 和 web 统一(来源)
如果你是 BigQuery 的新手,我推荐你阅读我之前关于如何在 BigQuery 中查询 Google Analytics(通用分析)数据的文章的第一部分。
目录
–这是怎么回事?
–文档
–新参与度指标
–Google Analytics 4 big query 导出模式
–嵌套字段
–获取所有唯一事件和参数
–示例查询:“标准”维度&指标
–示例查询:计算维度&指标
这是怎么回事?
谷歌前分析倡导者克里斯塔·塞登在一系列博客中解释了为什么新的谷歌分析 4 属性是一大进步:
目前,如果你同时拥有应用程序和网站数据,你需要分别收集和分析这些数据,在 Google Analytics for web 和 Google Analytics for Firebase for apps 中。虽然平台不同,但在理解数据和报告方面,许多 KPI 和业务需求是相同的,因此是时候将这些数据整合到一个分析属性中了!(来源)

谷歌分析 4 报告用户界面
这一发展对收集和分析数据的方式有着严重的影响。
这种新的测量类型使用与 Google Analytics for Firebase(GA4F)相同的数据模式(……)关于这种新的数据模式,最重要的是它脱离了传统的会话+页面视图方法,传统的 Google Analytics 已经使用了 15 年以上。相反,它使用事件+参数模型。这是不同的,但它打开了一个全新的可能性世界,就您可以跟踪的内容以及您可以通过相关参数添加到每个事件操作的所有附加细节而言。(来源)
返回目录
证明文件
如果所有这些对您来说都是新的,请在继续查询之前阅读所有关于 GA4 属性的内容。
[## 关于 Google Analytics 4 (GA4)属性的最佳资源
GA4BigQuery 将主要关注如何在 BigQuery 中利用你的谷歌分析数据。由于 GA4 对…来说相当新
www.ga4bigquery.com](https://www.ga4bigquery.com/best-resources-on-google-analytics-4-ga4-properties/)
新的参与度指标
在 Google Analytics 4 属性中,我们看到了一些以前没有的新指标:
参与会议
持续时间超过 10 秒、有转换事件、有 2 个或更多屏幕或页面视图的会话数。(来源:GA4 UI 中的定义)
以下是克里斯塔·塞登的一些背景资料:
参与式会话的概念源于希望从会话计数中删除反弹,因此,只有在用户在网站上停留 10 秒钟后,参与式会话才会被计数。如果他们在此之前离开,这将被视为反弹,而不是参与会议。(来源)
弗洛里安·佩尔补充道:
这或多或少与通用分析反弹相反。参与式会话是指至少有两次浏览量,或一次浏览量+一次互动,或一次持续时间为 10 秒的浏览量。目前,10 秒超时不能更改。(来源

参与度指标
每个用户参与的会话数
每个用户参与的会话数,因此,如果我们看到相同的用户 ID 返回多次,则每个用户可能有 3、4 或 5 个会话,然后在您的总用户数中取平均值,得出平均值大于 1,实际数量取决于您的内容有多少新用户与返回用户(或删除的 cookies)。(来源)
订婚时间
这可能是我最喜欢的新指标。为什么?多年来,我一直在谈论为什么我讨厌通用谷歌分析中的“跳出率”和“页面时间”这两个指标。这种不喜欢有很好的理由:这些指标在计算方式上有缺陷,因为自 15 年前这些指标问世以来,网络的使用发生了变化。(…)在 Firebase 的谷歌分析中,有一个指标叫做“参与时间”,我更喜欢这个指标,因为它是作为应用程序在前台的实际时间计算的,比通用谷歌分析中的“页面时间”可靠得多。
对于 A+W,我们想引入类似的逻辑,但由于浏览器和标签的工作方式,这要困难得多。我们的小团队花了相当多的时间来讨论计算对分析有意义的指标的最佳方法,最终得出了“web 参与时间”,这意味着它是如何在应用程序中计算的同义词,使用一些新的处理程序来密切关注前台标签、屏幕睡眠时间等。本质上,一个更好的计算时间的页面。(来源)
订婚率
参与会话的百分比(参与会话数除以会话数)。(来源:GA4 UI 中的定义)
转换策略
如果我们打算在 App+Web 中复制 Universal Analytics 报告,这些不会立即有用:转换是标记为转换的事件计数,而不是在会话级别进行重复数据删除(因此它不是真正的会话范围指标)。更重要的是,现在没有办法指定我们想要查看哪个转换——它们都被扔进了同一个锅里。最有可能的用例是当我们只跟踪单个转换事件时,那么报告将更有意义。(来源)
返回目录
GA4 大查询导出模式
由于没有谷歌分析 4 属性的样本数据集(还没有?),我将使用一个来自 OrangeValley 的出口数据集(仅限网络),这是我在撰写本文时工作的数字营销机构。除了通过' enhanced measurement 收集的标准事件之外,您可能会在我们的数据集中看到一些自定义事件参数,如事件' page_view '中的' wordCount '。这不会以任何方式影响我们的模式。

GA4 在 BigQuery 中导出数据
让我们来看看 GA4 BigQuery 导出模式:
GA4 大查询导出模式
你会注意到,数据集主要围绕事件和用户数据组织,并辅以一些设备、地理、应用和交通来源数据。
根据不同的定义,您可以预期 Google Analytics 4 用户界面和 BigQuery 导出数据查询的结果之间存在一些相对较小的差异。了解用户计数或维度&度量定义的差异。
返回目录
嵌套字段
在通用分析导出模式中,数据集中的每一行代表一个会话。因为 GA4 属性是基于事件的,所以数据集中的每一行都代表一个事件。每个事件又可以包含多个事件参数和相应的值。为了向您展示这在 BigQuery 中是如何工作的,我们查询我们的嵌套样本集:
SELECT
*
FROM
`ga4.analytics_1234567890.events_*`
LIMIT
3
这给了我们 3 行,表示为平面表,如下所示:
记住,在这个例子中,只有第 2、9 和 15 行是我们表中真正的行。其他“行”实际上是嵌套字段,大多数情况下是NULL值。只有event.params列填充了值。
为了处理这些字段,并能够查询我们的表以满足我们的需求,我们需要UNNEST函数。
这里的问题是它本质上是一个数组(实际上在 BigQuery 中它是一个“重复的记录”,但是你可以把它看作一个数组)。(…)这就是
*UNNEST*函数的用武之地。它基本上允许你在一个数组中获取元素,然后展开每一个单独的元素。然后,可以将原始行与每个未嵌套的元素连接起来,将它们添加到表中。(来源)

取消嵌套事件 _ 参数(来源)
我强烈推荐阅读这篇文章,它以 Firebase Analytics 样本数据集为例详细解释了UNNEST概念。
您只需UNNEST包含“重复字段”的记录。对于我们的 Google Analytics 4 数据集,这些可能涉及:
- 事件参数
- 用户属性
- 项目
返回目录
获取所有唯一的事件和参数
因为每个数据集都可能包含不同数据类型的不同事件和事件参数,所以查询实际的表来找出答案是非常有帮助的。尤其是当您缺少关于数据收集方式的文档时。要获得所有唯一的事件和参数,您可以使用如下查询:
受罗伯特·萨赫林启发的疑问
在我们的数据集的情况下,这导致所有唯一事件和参数的列表及其相应的数据类型。这些重复的字段包含大量数据,我们将使用这些数据来计算维度和指标。
返回目录
“标准”维度和指标
许多数据可以直接从表中导出,而不需要对数据进行计算。借助UNNEST和PARSE获取日期或时间戳,我们可以做到这一点。
查看示例查询中的-- comments的名称和定义,并从SELECT子句中复制您需要的部分。确保您还添加了正确计算结果所需的任何附加条件(即WITH、FROM、WHERE、GROUP BY、HAVING和ORDER BY)。
—
用户维度
user _ id
user _ pseudo _ id
user _ first _ touch _ timestamp
user _ string _ value
user _ set _ timestamp _ micros
user _ ltv _ revenue 货币
用户指标
用户整数值
用户浮点值
用户双精度值
[## 用户:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/user-dimensions-metrics-ga4/)
—
设备尺寸
device . category
device . mobile _ brand _ name
device . mobile _ model _ name
device . mobile _ marketing _ name
device . mobile _ OS _ hardware _ model
device . operating _ system
device . operating _ system _ version
device . vendor _ id
device . advertising _ id
device . language
device . is _ limited _ tracking
device . time _ zone _ offset _ seconds
device . browser
[## 设备、应用、网络、流和平台:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/device-app-web-stream-platform-dimensions-metrics-ga4/)
—
地理维度
地理大陆
地理亚大陆
地理国家
地理区域
地理城市
地理地铁
[## 地理位置:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/geo-location-dimensions-metrics-ga4/)
—
应用程序维度
app _ info . id
app _ info . version
app _ info . install _ store
app _ info . firebase _ app _ id
app _ info . install _ source
[## 设备、应用、网络、流和平台:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/device-app-web-stream-platform-dimensions-metrics-ga4/)
—
流量来源维度
traffic_source.name(用户)
traffic_source.medium(用户)
traffic_source.source(用户)
[## 流量来源:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/traffic-source-dimensions-metrics-ga4/)
—
事件维度
event _ date
event _ timestamp
event _ name
event _ key
event _ previous _ timestamp
event _ bundle _ sequence _ id
event _ server _ timestamp _ offset
stream _ id
平台
event_dimensions.hostname
事件度量
事件 _int_value
事件 _float_value
事件 _double_value
事件 _value_in_usd
[## 事件:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/events-dimensions-metrics-ga4/)
返回目录
电子商务维度
commerce.transaction_id
电子商务指标
ecommerce . total _ item _ quantity
ecommerce . purchase _ revenue _ in _ USD
ecommerce . purchase _ revenue _ value _ in _ USD
ecommerce . refund _ value _ in _ USD
ecommerce . shipping _ value _ in _ USD
ecommerce . shipping _ value
ecommerce . tax _ value _ in _ USD
ecommerce . tax _ value
ecommerce . unique _ items
[## 电子商务:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/ecommerce-dimensions-metrics-ga4/)
返回目录
项目尺寸
items . item _ id
items . item _ name
items . item _ brand
items . item _ variant
items . item _ category 2
items . item _ category 3
items . item _ category 4
items . item _ category 5
items . coupon
items . affiliation
items . location _ id
items . item _ list _ id
项目度量
items . price _ in _ USD
items . price
items . quantity
items . item _ revenue _ in _ USD
items . item _ revenue
items . item _ refund _ in _ USD
[## 项目:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/items-dimensions-metrics-ga4/)
返回目录
计算维度和指标
你在谷歌分析分析和报告中习惯的其他维度和指标有点难以获取。您必须使用自己的查询来计算它们。
由于我已经尝试整理出了最常用的维度和指标,我希望我能对下面的示例查询有所帮助。有很多其他的,甚至可能更好的方法来实现这些结果,但这里是我的两美分。
这些示例查询(按类别排序)包含以下所有 Google Analytics 维度和指标。如果您只需要一个维度或度量,请查看示例查询中的-- comments的名称和定义,并从SELECT子句中复制您需要的部分。确保您还添加了正确计算结果所需的任何附加条件(即WITH、FROM、WHERE、GROUP BY、HAVING和ORDER BY)。
—
用户维度
用户类型
会话计数
用户指标
用户
新用户
%新会话
每个用户的会话数量
每个用户的事件计数
[## 用户:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/user-dimensions-metrics-ga4/)
—
会话指标
会话
参与会话
参与率
参与时间
反弹
反弹率
每次会话的事件计数
[## 会议:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/sessions-dimensions-metrics-ga4/)
—
高级:定制您参与的会议
上述参与会话的计算基于事件“user_engagement”。更具体地说:当参数' session_engaged' = '1 '时。根据 GA4 用户界面,参与会话的定义是:
持续时间超过 10 秒、有转换事件、有 2 个或更多屏幕或页面视图的会话数。
您可以在 UI 中设置转换事件,但如果您使用事件“user_engagement ”,则不能更改会话长度或页面浏览量的定义。但是,如果我们想要自定义参与式会话的定义,该怎么办呢?您可以使用这个高级查询(的变体)。
—
时间维度
日期
年份
ISO 年份
年份月份
年份月份
年份星期
年份星期
ISO 年份星期
ISO 年份星期
月份日期
星期日期
星期名称
小时
分钟
日期小时和分钟
[## 日期和时间:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/date-and-time-dimensions-metrics-ga4/)
备注:时区格式
BigQuery 通常以 UTC 显示数据。这在使用日期格式化函数时会导致问题,因为日期和时间可能会不一致。将日期时间格式转换为正确的时区可以解决这些问题。
( 出处&如何)
—
交通来源维度
默认频道分组(用户或会话)
源/媒体(用户或会话)
活动(用户或会话)
完整推荐人
[## 流量来源:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/traffic-source-dimensions-metrics-ga4/)
—
页面跟踪尺寸
主机名
页面
上一页路径
页面路径一级
页面路径二级
页面路径三级
页面路径四级
页面标题
登陆页面
第二页
退出页面
页面跟踪指标
入口
浏览量
独特浏览量
页面/会话
出口
%出口
[## 页面跟踪:维度和指标(GA4)
许多 Google Analytics 4 数据可以直接从表格中导出,而无需对数据进行计算…
www.ga4bigquery.com](https://www.ga4bigquery.com/page-tracking-dimensions-metrics-ga4/)
—
电子商务维度和指标
由于到目前为止我还没有访问过 GA4 的任何电子商务数据集,我建议看看 Bounteous 查询 GA4 数据指南中的电子商务交易和产品的查询示例。
返回目录
如何使用 Python(带 SSH)通过 3 个步骤查询 PostgreSQL
原文:https://towardsdatascience.com/how-to-query-postgresql-using-python-with-ssh-in-3-steps-cde626444817?source=collection_archive---------13-----------------------

图片由 Pixabay 提供
-这个故事描述了如何使用这个脚本在有或没有 SSH 的情况下快速建立与远程 PostgreSQL 数据库的连接。pem 认证。-
数据通常存储在远程服务器上的 PostgreSQL 等数据库中,这使得数据分析师很难快速访问数据。有时,有中间团队协助分析师从数据库中检索数据。在这个故事中,我们将讨论如何使用 Python 直接查询数据,而不需要中间媒介。
如果你知道如何使用 Python(主要用于分析和可视化),但没有数据库经验或如何与它们交互,那么这篇文章就是为你准备的!
有各种各样的工具供我们使用,使您能够自己从数据库中交互/检索数据,并花更多的时间来提取见解。
- 第一步:安装所有需要的包。
- 第二步:将 query.py 的内容导入或粘贴到笔记本中。
- 第三步:开始查询!
这个故事假设如下:
- 您已经在本地环境中安装了 Python
- 您正在使用像 Jupyter 笔记本这样的实时代码环境
- 已经获得了 SSH 到远程服务器的必要凭证。pem 证书)并查询 PostgreSQL 数据库(用户名和密码)。
步骤 1:安装所有必需的软件包:
首先,我们需要从终端安装几个软件包。
pip3 install paramiko
pip3 install sshtunnel
pip3 install SQLAlchemy
pip3 install pandas
步骤 2:将 query.py 内容导入或粘贴到笔记本中
接下来,您需要将 repo 中的 query.py 文件保存到您的工作目录(Jupyter 笔记本文件所在的目录)中,或者直接将该文件的内容复制到您的笔记本中。
如果将 query.py 文件放在工作目录中,则在笔记本中包含以下导入行:
from query.py import *
或者,只需将下面的代码复制并粘贴到笔记本的代码单元格中:
第三步:查询!
现在我们可以开始查询了!定义的类只提供了少量的基本函数。让我们看一下如何使用这个类,以及我们可以用它做什么。
首先,我们需要指定 PostgreSQL 连接参数和 SSH 参数(如果访问远程服务器需要 SSH 隧道)。
我们将 pgres 定义为我们的连接,以简化每次我们想要查询数据库或探索数据库的组织结构。还会提示您输入 PostgreSQL 用户名和密码,它们存储为临时变量(最佳实践是将这些变量保存为环境变量)。
接下来,我们可以探索名为' database_name '的给定数据库的模式,使用找到我们感兴趣的模式。schemas() 函数。
如果我们想探索名为' schema_name '的模式,我们可以使用返回模式中的表名。tables()【函数。
最后可以用。query() 运行标准的 SQL 查询(针对 PostgreSQL)。在本例中,我们从名为' ey_test_table '的表中查询列名和数据类型
尝试用您自己的查询替换 sql_statement 的内容,并从中获得乐趣!
如何使用 Arctic 更有效地查询时间序列数据
原文:https://towardsdatascience.com/how-to-query-your-time-series-more-efficiently-using-arctic-40cb1c7b2680?source=collection_archive---------14-----------------------
加快 Python 时序数据处理脚本的速度
有没有想过在处理大型时间序列数据集时,如何提高数据分析过程的时间效率? 北极 也许就是你要找的。

史蒂文·勒勒姆在 Unsplash 上拍摄的照片
Arctic 是一个为 Python 设计的数据库,目的只有一个:性能。使用 Mongo DB 作为底层数据库,高效存储数据,使用 LZ4 压缩,每秒可以查询上亿行。
除了性能数字之外,它还提供了一些非常有说服力的特性:
- 可以处理熊猫、 Numpy 和 Python 对象(通过酸洗);
- 可以拍摄对象的多个版本的快照;
- 为您提供“大块”数据;
- 可以利用 MongoDB 的认证;
- 拥有三种不同类型的商店。
什么?商店?
存储引擎 是直接与底层 MongoDB 数据库交互的机制。他们被称为斗牛士。为了使您的查询获得最佳性能,您可以选择 S tores: 中的三个内置参数之一
- 版本存储 默认存储。基于键值和时间序列。它使创建数据快照和检索数据变得容易,而不会损失任何性能。
- tick store 面向列,支持动态字段。适用于高频金融数据或任何持续跳动的数据。不支持快照。
- chunk store 允许以预定义的块大小存储数据。不支持快照。
您也可以将自己的存储实现和插件放入 Arctic,以更好地适应您自己的数据。
“好的,我明白了,非常有说服力的观点,但是我不知道是否值得使用一个新的数据库……”你,读者,还没有被说服。
入门指南
那么,让我们看看使用 Arctic 有多简单,看看我是否能让你,读者,更深入地了解使用另一个数据库的想法。这将是一个非常简单的演练,只是为了说明北极的一些核心功能。
安装
首先,你需要安装并运行 MongoDB。你可以在官方 MongoDB 文档页面阅读你的操作系统的说明。
完成后,我们可以使用 pip 安装 Arctic
pip install git+https://github.com/manahl/arctic.git
我们需要安装熊猫库,因为我们将处理[DataFrames](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)
pip install pandas
编码
首先:让我们将北极导入到我们的空 Python 脚本中
from arctic import Arctic
现在,我们需要将 Arctic 连接到它的底层 MongoDB 实例。您可以将 Arctic 连接到托管在云上或本地网络中的任何 MongoDB 实例。因为我在笔记本电脑上运行 MongoDB,所以我将使用localhost 作为我的实例的地址。
db = Arctic('localhost')
太好了!现在我们需要创建一个库。
Arctic 使用库的概念分离不同的数据。 他们可以是市场、地区、用户等。
在本例中,我将使用一个大约 160MB 的 CSV 文件,其中包含一些财务数据。让我们创建一个财务库来存储它。通过不向initialize_library方法传递一个lib_type值,Arctic 将默认这个库使用版本存储存储引擎。对于我们的例子来说,这很好。
db.initialize_library('Finance')
我们需要访问刚刚创建的库,以便向其中写入一些数据。让我们用库名索引我们的db对象。
finance_library = db['Finance']
在写入数据之前,让我们打开时间序列数据文件。在本例中,我将使用一个名为[finance.csv](https://github.com/tgcandido/time-series-with-arctic/blob/master/finance.csv)的文件(本例中使用的 CSV 结构的演示文件)。
让我们使用 Pandas 库打开 CSV 文件。首先,我们需要导入库,然后使用[read_csv](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html)方法将内容读入一个熊猫DataFrame。
在将string转换为datetime之后,我们还会将unix列设置为DataFrame的索引。
import pandas as pd
df = pd.read_csv('finance.csv')
df['unix'] = pd.to_datetime(df['unix'])
df.set_index('unix', inplace=True)
好吧!我们准备将数据写入北极。为此,我们需要定义一个符号。
一个符号是一个字符串,我们将使用它在一个库中读取或写入我们的数据。
让我们使用符号Stocks将我们加载的df的内容存储到库finance_library中。
finance_library.write('Stocks', df)
我们可以通过使用方法read并访问返回对象的data属性以获得结果DataFrame来验证数据是否被正确插入。
new_df = finance_library.read('Stocks').data
要执行查找特定时间间隔的查询,我们可以使用read方法中的date_range参数。
首先,我们需要从arctic.date导入DateRange:
from arctic.date import DateRange
我们可以将一个DateRange的实例传递给date_range参数。我们可以通过调用它的构造函数并将开始日期和结束日期作为参数传递来创建它。
custom_range = DateRange('2020-01-01', '2020-01-02')
现在我们可以运行查询:
range_df = finance_library.read('Stocks', date_range=custom_range).data
就是这样!在这个非常简单的例子中,我们通过实现一个处理一些财务数据的 Python 脚本看到了 Arctic 的主要特性。
官方文档真的很好,几乎包含了所有需要的信息,从基础到高级特性。没有必要阅读软件包的源代码,但是如果您有兴趣了解 Arctic 的工作方式以及它是如何实现其高性能的,我鼓励您这样做。
但恐怕我不会说服你,读者,除非我给你看一些业绩数字,对吗?
基准
这些数字都是在我的 2.3 GHz 双核 13 英寸 2017 Mac Book Pro 上运行脚本获得的。
请记住,这绝不是北极数据库的完整基准。这是用 Python 的时间库在 Arctic、MongoDB、SQLite 和普通 CSV 文件之间进行的简单比较。
性能比较
下面是运行一个简单的 Pandas read_csv、一个 PyMongo 查询、 SQLAlchemy 查询(使用 SQLite 数据库)和一个 Arctic read查询(使用大约 160 MB 的财务数据作为源)的结果。
在引擎返回结果后,PyMongo 和 SQLAlchemy 查询结果被解析成一个DataFrame ,这个时间在基准测试中被考虑。两个数据库都由unix列索引。
- 熊猫
read_csv:4.6 秒 - PyMongo 查询:~28 秒
- SQLite 查询:大约 30 秒
- 北极
read: ~1.45 秒
这些结果来自于一个“get all”类型的查询。让我们尝试添加一个范围参数,看看结果是否成立。
new_df = finance_library.read('Stocks', date_range=DateRange('2020-01-01', '2020-01-02')).data
- 熊猫
read_csv:4.9 秒 - PyMongo 查询:~1.66 秒
- SQLite 查询:~0.7 秒
- 北极
read与DateRange: ~0.12 秒
在使用了DateRange之后,结果仍然支持 Arctic,这是我们在处理时间序列数据时使用的主要查询类型。
磁盘压缩
同一个 CSV 文件用于播种每个数据库。
这是每个备选方案使用的磁盘空间量:
- 普通 CSV 文件:160.8 MB
- MongoDB 集合:347.31 MB
- SQLite: 297.9 兆字节
- 北极:160.59 兆字节
结论
在处理大型时间序列数据集时使用 Arctic 使我们能够实现显著的速度和压缩改进。凭借其简单的设置和使用,它可以提高生产力和节省一些宝贵的时间。
即使不使用其更高级的功能,如快照或其他存储引擎,我们也可以为使用 Arctic 处理时间序列数据提供有力的支持。
演练和基准测试的代码可以在这里找到。出于许可的原因,它不包含完整的 CSV 文件,但是我鼓励您使用您自己的一些数据来运行,看看您的结果是否与我的相似。
我希望你喜欢阅读这篇文章。
如果你有,可以考虑在 推特 上关注我。
谢谢你的时间。保重,继续编码!
如何快速创建和打开熊猫列表
原文:https://towardsdatascience.com/how-to-quickly-create-and-unpack-lists-with-pandas-d0e78e487c75?source=collection_archive---------15-----------------------
大蟒
使用 df.explode()解决使用熊猫数据框架时的常见问题

当你需要打开清单时,很快你就会像这个人一样微笑
预处理和“数据争论”占用了大量时间,但这并不总是数据分析项目中最有趣的部分。
当涉及到重新格式化初始数据时,必须解包一个列表。幸运的是,Pandas 提供了许多常见问题的矢量化解决方案,所以我们不必为在数据帧中解包列表而感到太大压力。
在这篇文章中,我们将关注两件事:
- 如何使用
df.explode()取消数据帧中带有列表值的列嵌套; - 如何使用
Series.str.split()从一个字符串创建一个列表。
我们将使用这个视频游戏销售数据的修改版本,所以如果你想跟进的话,可以下载 csv 文件。这一次,我在最底部加入了代码来获取每个示例的初始表。我建议先浏览一遍这段代码,然后复制代码以获得输入,然后再尝试示例。
如何在熊猫数据框架中取消嵌套(分解)一列
我们的初始表格如下所示:

目标是分隔“流派”列中的所有值,以便每行只有一个值。就数据库规范化而言,这将是实现“第一范式”的一个步骤,在第一范式中,每一列只包含原子(不可分的)值。
为此,我们需要做的就是使用df.explode()功能。我们只需要传递一个参数,它是包含列表 like 值的列的名称。
我们的代码是这样的。
df2 = df2.explode('Genre').drop_duplicates()
结果数据帧的子集如下所示:

现在我们有了一个包含每个出版商所有不同类型的表格。我们还通过在数据帧上传递.drop_duplicates()来确保只有唯一的值。
您会注意到原始数据帧中的索引值是为每一行保留的,这表明df.explode()函数所做的只是在 iterable 中分离元素,同时保持所有其他行的值不变。如果我们想要新的索引值,我们也可以轻松地通过.reset_index()。
如何在 Pandas 数据框架中创建(和解包)一个具有列表式值的列
在最后一个问题中,我们使用了一个包含一列列表的数据帧。然而,您经常会处理不完全符合预定义的 Pandas 函数的数据。例如,假设我们有一个类似于上一个问题的表格,如下所示:

你能看出区别吗?
“流派”列中仍有一堆值,但它们不再在 Python 列表中。df.explode()函数不起作用,因为根据它的文档:
这个例程(df.explode)将分解类似列表的内容,包括列表、元组、序列和 np.ndarray。
我们目前对每个列值都有多个条目,但是它们不是“类似列表”的格式。我们只有一堆很长的字符串。
为了将子字符串组合成一个列表,我们将使用一行简单的代码将字符串转换成一个列表:
df3['Genre'] = df3['Genre'].str.split(',')
这里,我们在“流派”列上使用了Series.str.split()方法来创建一个列表。顾名思义,这个方法在您指定的分隔符上分割字符串,在我们的例子中是逗号。如果你不向split()传递任何东西,这个方法将试图在空白上分割一个字符串,但是我们的字符串没有空白。
生成的表格如下所示:

现在,我们有了一个与前一个几乎相同的表,只是这次所有不同的值都在一个列表中。
我们现在要做的就是运行与第一个问题中相同的代码行:
df3 = df3.explode('Genre')


姐姐创作的漫画
我希望你发现这个快速浏览df.melt对你的熊猫工作有用!如果你需要在你的数据框架中创建或者解压列表,你可以分别使用Series.str.split()和df.explode()方法。
正如所承诺的,下面是设置这两个示例的代码:
import pandas as pddf = pd.read_csv('vgsales.csv').dropna()
df['Year'] = df['Year'].astype(int)# problem 1
df2 = df.groupby('Publisher')['Genre'].apply(','.join).reset_index()
df2 = df2.loc[(df2['Publisher']=='Nintendo') | (df2['Publisher']=='Ubisoft') | (df2['Publisher']=='Activision')]
df2['Genre'] = df2['Genre'].str.strip().str.split(',')# problem 2
df3 = df.groupby('Publisher')['Genre'].apply(','.join).reset_index()
df3 = df3.loc[(df3['Publisher']=='Infogrames') | (df3['Publisher']=='Wanadoo')]
你可以看到我使用了.loc[]函数为我的数据帧设置了一些条件,所以如果你还不熟悉使用它,你可以看看这个:
[## 你不需要总是在熊猫的行列中循环!
用向量化解决方案看一下“for 循环”的替代方案。
towardsdatascience.com](/you-dont-always-have-to-loop-through-rows-in-pandas-22a970b347ac)
我在这里也使用了.apply(),这是一种沿着数据帧的轴执行函数的简单方法。对于逐行编辑数据帧的另一种方法(我建议只在遇到问题没有的矢量化熊猫解决方案时才使用),请查看以下内容:
[## 一个非常简单的方法来编辑熊猫数据帧中的一行一行
使用 pd.loc 根据条件更改数据的子集。
towardsdatascience.com](/a-really-simple-way-to-edit-row-by-row-in-a-pandas-dataframe-75d339cbd313)
祝你和熊猫的冒险之旅好运!
如何快速找到最适合直方图的条柱
原文:https://towardsdatascience.com/how-to-quickly-find-the-best-bin-width-for-your-histogram-4d8532f053b0?source=collection_archive---------11-----------------------
数据探索是每个数据科学项目中的关键步骤,通常从查看单个变量的分布开始。这就是直方图的亮点。
直方图对于可视化列的分布非常有用,这有助于理解数据的重要方面。例如,通过简单地查看直方图,我们可以立即识别数据中的异常值甚至错误(例如,包含患者年龄的列中的负值)。
当处理直方图时,我们几乎总是最终调整条柱宽度,这是一个关键参数,因为它决定了我们可以从图中提取多少信息和什么类型的信息。
在本文中,我将向您展示如何通过在 Jupyter Notebook 或 JupyterLab 中使用 plotly 和 ipywidgets 创建一个交互式直方图来快速找到您的最佳 bin 宽度。
注意:尽管我用 plotly 展示了交互式重新绑定,但是您可以将我所展示的逻辑应用于任何绘图库,比如 seaborn 和 matplotlib。
为了可视化,我将以分钟为单位显示 2013 年从纽约出发的 300,000 多个航班的飞行时间( NYCflights13 数据)。你可以在 GitHub 上找到这篇文章的完整代码。
交互式宁滨直方图

在这张图中,你可以看到最终的结果。如果我们通过一个滑块改变箱的宽度,plotly 图会自动调整。
为了实现这个行为,我们将plotly.graph_objs(创建 plotly 图)与ipywidgets.Floatslider结合起来。
这是创建可重组直方图的代码。
让我们一行一行地过一遍。
逐行解释代码
0.功能签名
注意,我们的函数有两个参数:series一只熊猫。Series 和initial_bin_width,指定我们希望在绘图中将 a 作为默认值的 bin 宽度。在我们的例子中,它是 10 分钟的广播时间窗口。
1.创建图形
我们生成一个新的FigureWidget实例。FigureWidget物体是 plotly 的新“魔法物体”。你可以在 Jupyter 笔记本或 JupyterLab 中显示它,就像任何普通的 plotly 图形一样。但是,这种方法有一些优点:
- FigureWidgets 可以与 ipywidgets 相结合,以创建更强大的结构(事实上,这就是 FigureWidgets 的设计目的)
- 您可以在 Python 中以各种方式操作
FigureWidget - 您还可以收听一些事件和
- 当事件被触发时,您可以执行更多的 Python 代码
FigureWidget接收属性data,该属性指定了我们想要显示的所有轨迹的列表。在我们的例子中,我们只想显示一个直方图。直方图的 x 值来自series。我们通过将字典传递给xbins来设置 bin 宽度。当我们在字典中设置size=None时,plotly 会为我们选择一个 bin 宽度。
2.创建滑块
我们使用ipywidgets库生成一个FloatSlider。通过这个滑块,我们稍后将能够操纵我们的直方图。
3.保存对直方图的引用
我们获取对直方图的引用,因为我们想在最后一步操作它。特别是,我们将更改对象的xbins属性,我们可以通过histogram_object.xbins访问它。
4.编写并使用回调
我们已经实现的FloatSlider带有一些魔力。每当它的值改变时(即我们移动滑块),它就触发一个事件。我们可以使用该事件来更新直方图中的区间宽度。从技术上来说,您可以通过调用 bin 滑块上的observe方法来实现这一点,向它传递您想要调用的函数(在我们的例子中是set_bin_size,并告诉它何时调用该函数(name="value"意味着每当滑块的value改变时我们都会调用该函数)。现在,每当滑块的值改变时,它就会调用set_bin_size。set_bin_size通过魔术参数change访问滑块的值,魔术参数是一个字典,包含关于由bin_slider触发的事件的数据。例如,change["new"]包含滑块的新值,但是您也可以使用change["old"]来访问它以前的值。注意,你不必使用参数名change。你可以给它取任何你想要的名字。
在回调函数set_bin_size中,我们可以看到它简单地采用了引用histogram_object,以便通过覆盖xbins来更新FigureWidget的 bin 设置(即改变 bin 宽度)。
当我们把上面的所有部分放在一起时,我们就有了第一个漂亮的交互式直方图的原型。
结论
直方图是开始探索数据集的单个列的一个很好的方法。使用 plotly,我们可以创建强大的交互式可视化,并可以使用 ipywidgets 进一步增强。
在本文中,我向您展示了在 Jupyter Notebook 或 JupyterLab 中使用 plotly 和 ipywidgets 时,如何交互式地快速找到直方图的(主观)最佳条宽。
在 8080 实验室,我们使用我们的 python 工具 bamboolib 中的重新绑定特性。与许多其他交互式功能一起,它帮助我们的用户更快地获得洞察力。
如果您对本文有任何反馈或建设性的批评,或者想讨论如何为直方图添加更多功能,请随时通过 LinkedIn 联系我。
原载于 2020 年 02 月 06 日 https://8080labs.com**。
如何根据语义相似度对文本内容进行排序
原文:https://towardsdatascience.com/how-to-rank-text-content-by-semantic-similarity-4d2419a84c32?source=collection_archive---------1-----------------------
使用 NLP、TF-idf 和 GloVe 查找 Python 中的相关内容并进行排名
搜索是查找内容的标准工具——无论是在线还是设备上的——但是如果你想更深入地根据单词的含义来查找内容呢?为自然语言处理开发的工具会有所帮助。

帕特里克·托马索在 Unsplash 上拍摄的照片
内容
在本文中,我们将介绍两种计算文本相似度的方法:
- 术语频率-逆文档频率(TF-idf) : 这查看在两个文本中出现的单词,并根据它们出现的频率对它们进行评分。如果你希望两个文本中出现相同的单词,这是一个有用的工具,但是有些单词比其他的更重要。
- 语义相似度:根据单词的相似程度来评分,即使它们并不完全匹配。它借用了自然语言处理(NLP)的技术,比如单词嵌入。如果文本之间的单词重叠是有限的,这是很有用的,例如,如果您需要将'水果和蔬菜'与'西红柿'联系起来。
对于第一部分,我们将单独使用scikit-learn中的 TF-idf 实现,因为它非常简单,只需要几行代码。对于语义相似性,我们将使用来自gensim的一些函数(包括它的 TF-idf 实现)和来自手套算法的预训练单词向量。此外,我们还需要一些来自nltk的工具。这些软件包可以使用 pip 安装:
pip install scikit-learn~=0.22
pip install gensim~=3.8
pip install nltk~=3.4
或者,您可以从 GitHub 存储库中获取示例代码,并从需求文件中安装:
git clone [https://github.com/4OH4/doc-similarity](https://github.com/4OH4/doc-similarity)cd doc-similaritypip install -r requirements.txt
[## 4oh 4/doc-相似性
使用 Python - 4OH4/doc-similarity 中的语义相似度对文档进行排序
github.com](https://github.com/4OH4/doc-similarity)
快速入门
- 运行
examples.ipynb,中的演示代码 - 使用
tfidf.rank_documents(search_terms: str, documents: list)功能根据重叠内容对文档进行评分, - 使用
docsim.DocSim()类对使用doc2vec和GloVe单词嵌入模型的文档进行相似性评分。
术语
文档 :字符串形式的一段文本。这可能只是几句话,也可能是一整部小说。
文集 :文件的集合。
术语 :文档中的一个词。
1.TF-idf
术语频率-逆文档频率(或 TF-idf)是一种基于文档共享单词的重要性对文档相似性进行评分的既定技术。非常高层次的总结:
- 如果某个术语(单词)在文档中频繁出现,则该术语在该文档中可能很重要。
- 但是,如果一个术语在许多文档中频繁出现,则该术语通常可能不太重要。
TF-idf 分数根据一个单词出现的频率来估计这两种启发式方法之间的权衡。这里有更详细的总结。
我们可以用几行代码从scikit-learn中创建并装配一个 TF-idf 矢量器模型:
在这里,我们创建模型并使用文本语料库进行“拟合”。TfidfVectorizer使用其默认的记号赋予器处理预处理——这将字符串转换成单个单词“记号”的列表。它产生包含频率项的文档向量的稀疏矩阵。
然后,我们用文档的第一个向量(包含搜索项)的点积(线性核)来确定相似性。我们必须忽略第一个相似性结果([1:]),因为这是比较搜索词本身。
这对于一个简单的例子来说很有效,但是在现实世界中可能会因为一些原因而失败。
首先,在匹配过程中使用诸如['and ',' on ',' the ',' are']这样的词没有多大意义,因为这些停用词不包含上下文信息。在确定相似性之前,这些单词应该被剔除。
其次,我们希望“水果”和“水果”被认为是相关的,尽管上面的模型只能找到精确的匹配。解决这个问题的一个方法是将每个单词简化为最简单的 引理 — 为此我们需要一个引理器。
在这种情况下,第二个文档中的“tomatos”被 lemmatizer (tokenizer)简化为“tomato ”,然后与搜索词中的相同单词进行匹配。
从概念上讲,每个文档都是高维空间中的一个点,其中维度的数量等于文本语料库中唯一词的数量。这个空间通常是非常空的,因为文档包含各种各样的单词,所以点(文档)之间的距离很大。在这种情况下,点之间的角度作为相似性的度量比距离相关的度量(如欧几里德距离)更有意义。
这里的相似度被称为余弦相似度。TfidfVectorizer的输出(默认情况下)是 L2 归一化的,因此两个向量的点积是向量所表示的点之间角度的余弦。
摘要:TF-idf
- 当文档很大和/或有很多重叠时,它速度很快,效果很好。
- 它寻找精确的匹配,所以至少你应该使用一个 lemmatizer 来处理复数。
- 当比较短的文档和有限的术语种类时——比如搜索查询——有一个风险,就是在没有精确的单词匹配时,你会错过语义关系。
2.语义相似度
一种更高级的方法是根据单词的相似程度来比较文档。例如,“苹果”和“橙子”可能比“苹果”和“木星”更相似。大规模判断单词相似性是困难的——一种广泛使用的方法是分析大量文本,将经常一起出现的单词排序为更相似。
这是单词嵌入模型 GloVe 的基础:它将单词映射到数字向量——多维空间中的点,以便经常一起出现的单词在空间上彼此靠近。这是一种无监督学习算法,由斯坦福大学于 2014 年开发。
在前面的例子中,我们使用了来自nltk包的WordNetLemmatizer对我们的数据进行词干化和标记化(转换成单个单词串的list)。这里我们在gensim中做了类似的预处理,也删除了任何可能存在的 HTML 标签,比如我们从网上抓取了数据:
然后,我们创建一个相似性矩阵,其中包含每对单词之间的相似性,使用术语频率进行加权:
最后,我们计算查询和每个文档之间的软余弦相似度。与常规余弦相似度不同(对于没有重叠项的向量,它将返回零),软余弦相似度也考虑单词相似度。
代码库中的笔记本中有完整的示例。还有一个自包含的DocSim类,可以作为模块导入,用于运行语义相似性查询,而无需额外的代码:
from docsim import DocSimdocsim = DocSim(verbose=True)similarities = docsim.similarity_query(query_string, documents)
GloVe word 嵌入模型可能非常大——在我的机器上,从磁盘加载大约需要 40 秒。然而,一旦它被加载,随后的操作会更快。该类的多线程版本在后台加载模型,以避免长时间锁定主线程。它以类似的方式使用,尽管如果模型仍在加载时会引发一个异常,所以应该首先检查model_ready属性的状态。
from docsim import DocSim_threadeddocsim = DocSim_threaded(verbose=True)similarities = docsim.similarity_query(query_string, documents)
概述:使用 GloVe 的语义相似性
- 它更加灵活,因为它不依赖于寻找精确的匹配。
- 涉及的计算要多得多,所以可能会慢一些,而且单词嵌入模型可能会相当大,需要一段时间来准备第一次使用。这很容易扩展,但是运行单个查询很慢。
- 大多数单词与其他单词有某种程度的相似性,因此几乎所有文档都会与其他文档有某种非零的相似性。语义相似性有利于按顺序排列内容,而不是对文档是否与特定主题相关做出具体判断。
我们已经研究了两种比较文本内容相似性的方法,例如可能用于搜索查询或内容推荐系统的方法。第一个(TF-idf)基于共有词的出现频率对文档关系进行评分。当文档很大和/或有很多重叠的术语时,这种方法速度很快,效果很好。第二种技术寻找表达相似概念的共有词,但不要求完全匹配:例如,它将“水果和蔬菜”与“番茄”联系起来。这种方法速度较慢,有时会产生不太清晰的结果,但对于较短的搜索查询或单词重叠度较低的文档很有用。
我在现实世界的应用程序中检查了这两种方法:我需要知道某个<collection of documents>是否与一小部分<search terms>相关。最初,我认为我需要使用语义相似性匹配——搜索词来自不受控制的用户输入,因此可能存在一些非常微妙的关系。文档排序是一个有用的功能,但总体目标是应用一个决策阈值,以便生成一个二进制的是/否结果。
对于那个特定的应用,我发现单独使用 TF-idf 就足够了。文档集合通常足够大,以至于在确实应该找到匹配的情况下,与搜索词有足够的重叠。以色列国防军工作队对正面和负面案例进行了更明确的区分,尽管它确实遗漏了一些也是相关的文件。
值得采取数据驱动的方法,看看什么最适合你的应用程序。
你有什么想法?你在工作中使用过这些工具吗,或者你喜欢不同的方法?在下面留下你的评论吧!
鲁珀特·托马斯 是一名技术顾问,专门研究机器学习、机器视觉和数据驱动产品。@ Rupert Thomas
参考
Sci-kit 学习:tfidf 矢量器
手套:单词表示的全局向量
Gensim:软余弦教程
如何高效地从 TensorFlow 2.0 中读取 BigQuery 数据
原文:https://towardsdatascience.com/how-to-read-bigquery-data-from-tensorflow-2-0-efficiently-9234b69165c8?source=collection_archive---------22-----------------------
使用 tensor flow _ io . big query . bigqueryclient 创建 tf.data.dataset
TensorFlow 的 BigQueryClient 使用存储 API 直接从 BigQuery 存储中高效地读取数据(即,无需发出 BigQuery 查询)。在本文中,我将向您展示如何在 Keras/TensorFlow 2.0 模型中使用该类来创建 tf.data 数据集。你可以在 GitHub 上跟随这个笔记本。

使用 BigQuery 作为数据湖:将数据直接从 BigQuery 读入 TensorFlow
作为示例,我将使用信用卡交易的数据集。这些交易中约有 0.17%是欺诈性的,挑战在于在这个非常非常不平衡的数据集上训练一个分类模型。因此,在这个过程中,您还将学习一些如何处理不平衡数据的技巧。
基准
开发机器学习模型的最佳实践是拥有一个简单的基准。在这种情况下,我将使用 BigQuery ML 开发基准模型:
CREATE OR REPLACE MODEL advdata.ulb_fraud_detection
TRANSFORM(
* EXCEPT(Amount),
SAFE.LOG(Amount) AS log_amount
)
OPTIONS(
INPUT_LABEL_COLS=['class'],
AUTO_CLASS_WEIGHTS = TRUE,
DATA_SPLIT_METHOD='seq',
DATA_SPLIT_COL='Time',
MODEL_TYPE='logistic_reg'
) ASSELECT
*
FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection`
请注意,我在这个超级简单的模型中做了几件事情:
- 我正在训练一个逻辑回归模型(或线性分类器)——这是这个问题最简单的可能 ML 模型,可以作为对更复杂模型的检查。
- 我使用时间列划分数据,因此前 80%的事务是训练数据集,后 20%是评估数据集。这样,我们就不会在欺诈活动存在时间依赖性的情况下泄露信息。
- 我要求 BigQuery ML 根据它们在训练数据集中的出现频率自动对这些类进行加权。
- 我正在使用 log 函数转换范围很大的 Amount 列,这样它也是一个相对较小的数字。我使用 BigQuery ML 的 TRANSFORM 子句来实现这一点。
- 因为在某些情况下金额为零,所以我用 SAFE。记录以避免数字错误。
这给了我一个 AUC(曲线下面积)为 0.9863 的模型,说明了 BigQuery ML 有多么强大。让我们看看我们是否可以用 Keras 编写的更复杂的机器学习模型来击败这一点。
创建 tf.data.dataset
为了将 BigQuery 数据读入 Keras,我将使用 BigQueryClient 。下面是创建数据集的代码:
import tensorflow as tf
from tensorflow.python.framework import dtypes
from tensorflow_io.bigquery import BigQueryClient
from tensorflow_io.bigquery import BigQueryReadSessiondef features_and_labels(features):
label = features.pop('Class') # this is what we will train for
return features, labeldef read_dataset(client, row_restriction, batch_size=2048):
GCP_PROJECT_ID='your_project_name' # CHANGE
COL_NAMES = ['Time', 'Amount', 'Class'] + ['V{}'.format(i) for i in range(1,29)]
COL_TYPES = [dtypes.float64, dtypes.float64, dtypes.int64] + [dtypes.float64 for i in range(1,29)]
DATASET_GCP_PROJECT_ID, DATASET_ID, TABLE_ID, = 'bigquery-public-data.ml_datasets.ulb_fraud_detection'.split('.')
bqsession = client.read_session(
"projects/" + GCP_PROJECT_ID,
DATASET_GCP_PROJECT_ID, TABLE_ID, DATASET_ID,
COL_NAMES, COL_TYPES,
requested_streams=2,
row_restriction=row_restriction)
dataset = bqsession.parallel_read_rows()
return dataset.prefetch(1).map(features_and_labels).shuffle(batch_size*10).batch(batch_size)client = BigQueryClient()
train_df = read_dataset(client, 'Time <= 144803', 2048)
eval_df = read_dataset(client, 'Time > 144803', 2048)
本质上,我们使用 client.read_session()创建一个会话,传入要读取的表、要读取的表的列,以及对我们关心的行的简单限制。这些数据被并行读入 tf.data.dataset,我用它来创建一个训练数据集和一个评估数据集。
请注意,上面的代码使用了一些 tf.data.dataset 最佳实践,如预取、混排和批处理。
创建 Keras 模型输入层
创建 Keras 模型来读取结构化数据涉及到特性列。要了解更多,请参阅我的文章,关于在 Keras 中创建宽深模型和保持 T2 转换代码与输入分离。因此,不重复我自己,下面是创建 Keras 的输入层的代码:
# create inputs, and pass them into appropriate types of feature columns (here, everything is numeric)
inputs = {
'V{}'.format(i) : tf.keras.layers.Input(name='V{}'.format(i), shape=(), dtype='float64') for i in range(1, 29)
}
inputs['Amount'] = tf.keras.layers.Input(name='Amount', shape=(), dtype='float64')
input_fc = [tf.feature_column.numeric_column(colname) for colname in inputs.keys()]# transformations. only the Amount is transformed
transformed = inputs.copy()
transformed['Amount'] = tf.keras.layers.Lambda(
lambda x: tf.math.log(tf.math.maximum(x, 0.01)), name='log_amount')(inputs['Amount'])
input_layer = tf.keras.layers.DenseFeatures(input_fc, name='inputs')(transformed)
处理阶级不平衡
处理 Keras 模型中的类不平衡包括两个步骤:
- 指定对数输出图层的初始偏差(正/负)
- 以总权重等于训练样本数量的方式,对不频繁类进行比频繁类大得多的加权
我们可以使用 BigQuery 计算必要的值:
WITH counts AS (
SELECT
APPROX_QUANTILES(Time, 5)[OFFSET(4)] AS train_cutoff
, COUNTIF(CLASS > 0) AS pos
, COUNTIF(CLASS = 0) AS neg
FROM `bigquery-public-data`.ml_datasets.ulb_fraud_detection
)SELECT
train_cutoff
, SAFE.LOG(SAFE_DIVIDE(pos,neg)) AS output_bias
, 0.5*SAFE_DIVIDE(pos + neg, pos) AS weight_pos
, 0.5*SAFE_DIVIDE(pos + neg, neg) AS weight_neg
FROM counts
这给了我以下数字:Keras 模型的输出偏差需要设置为-6.36,类权重需要为 289.4 和 0.5。
创建 Keras 模型
然后,我们可以创建一个 Keras 模型,其中包含两个隐藏的全连接层和一个丢弃层(以限制过拟合),并注意为输出层提供初始偏差,为损失函数提供类权重:
# Deep learning model
d1 = tf.keras.layers.Dense(16, activation='relu', name='d1')(input_layer)
d2 = tf.keras.layers.Dropout(0.25, name='d2')(d1)
d3 = tf.keras.layers.Dense(16, activation='relu', name='d3')(d2)
output = tf.keras.layers.Dense(1, activation='sigmoid', name='d4', bias_initializer=tf.keras.initializers.Constant())(d3)model = tf.keras.Model(inputs, output)
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=metrics)class_weight = {0: 0.5, 1: 289.4}
history = model.fit(train_df, validation_data=eval_df, epochs=20, class_weight=class_weight)
结果呢?经过 20 次迭代,我得到了:
val_accuracy: 0.9718 - val_precision: 0.0401 - val_recall: 0.8831 - val_roc_auc: 0.9865
这比标准的逻辑回归模型要好,但只是勉强好。我们将需要进一步超参数调整节点数、掉线等。深度学习模型比这做得更好。
将张量流模型加载到 BigQuery 中
可以将训练好的 TensorFlow 模型加载到 BigQuery 中,用它来做推理。要加载模型,请从 Keras 调用:
model.save('gs://{}/bqexample/export'.format(BUCKET))
然后,在 BigQuery 中,执行以下操作:
CREATE OR REPLACE MODEL advdata.keras_fraud_detection
OPTIONS(model_type='tensorflow',
model_path='gs://BUCKETNAME/bqexample/export/*')
您可以使用此模型进行预测,就好像它是一个原生的 BigQuery ML 逻辑回归模型一样:
SELECT d4, Class
FROM ML.PREDICT( MODEL advdata.keras_fraud_detection,
(SELECT * FROM `bigquery-public-data.ml_datasets.ulb_fraud_detection` WHERE Time = 85285.0)
)
上面将其称为 d4 的原因是我的 Keras 输出节点被称为 d4。
摘要
在本文中,您看到了如何:
- 直接从 BigQuery 读入 TensorFlow 2.0/Keras 模型
- 如何将训练好的模型加载到 BigQuery 中
在这个过程中,您还看到了如何在高度不平衡的数据上训练 BigQuery ML 模型和 Keras 模型。
后续步骤:
- 本文中的代码在 GitHub 上的一个笔记本里。在 AI 平台笔记本上试用一下。
- 关于 BigQuery 的更多信息,请阅读由 O'Reilly Media 出版的《BigQuery:权威指南》一书:
注意:根据贵公司的定价方案,使用超过一定限制的 存储 API 可能会产生 BigQuery 费用 。在我写这篇文章的时候,采用统一费率计划的客户如果每月的读取量超过 300 TB,就会开始产生这些费用。
如何使用 Pandas 将 CSV 文件读入 Python
原文:https://towardsdatascience.com/how-to-read-csv-file-using-pandas-ab1f5e7e7b58?source=collection_archive---------0-----------------------
在本帖中,我们将讨论如何将 CSV 文件导入 Python。

由 Unsplash 上的absolute vision拍摄的照片
简短回答
最简单的方法是:
import pandas as pddf = pd.read_csv ('file_name.csv')
print(df)
如果您想要导入列的子集,只需添加usecols=['column_name'];
pd.read_csv('file_name.csv', usecols= ['column_name1','column_name2'])
如果想用另一个分隔符,只需添加sep='\t';默认分隔符是','。
pd.read_csv('file_name.csv', sep='\t')
概述熊猫数据框架
Pandas DataFrames 是一个类似 excel 的数据结构,带有标记轴(行和列)。下面是一个熊猫数据帧的例子,我们将把它作为下面的例子:
生成数据帧的代码:
将 CSV 文件导入数据帧
Pandas read_csv()函数将 CSV 文件导入到 DataFrame 格式。
以下是一些选项:
文件路径或缓冲区:这是文件名或文件路径
df.read_csv('file_name.csv’) # relative position
df.read_csv('C:/Users/abc/Desktop/file_name.csv')
header :这允许您指定哪一行将被用作数据框的列名。应为 int 值或 int 值列表。
默认值是header=0,这意味着 CSV 文件的第一行将被视为列名。
如果您的文件没有标题,只需设置header=None。
df.read_csv('file_name.csv’, header=None) # no header
没有标题的输出:

sep :为 CSV 输入指定一个自定义分隔符,默认为逗号。
pd.read_csv('file_name.csv',sep='\t') # Use Tab to separate
index_col: 这允许您设置哪些列将用作数据帧的索引。默认值是 None,pandas 将从 0 开始添加一个新列来指定索引列。
它可以设置为列名或列索引,将用作索引列。
pd.read_csv('file_name.csv',index_col='Name') # Use 'Name' column as index
nrows: 仅从文件中读取第一行的数量。需要一个 int 值。
使用列:指定将哪些列导入数据框架。它可以是 int 值或列名的列表。
pd.read_csv('file_name.csv',usecols=[1,2,3]) # Only reads col1, col2, col3\. col0 will be ignored.
pd.read_csv('file_name.csv',usecols=['Name']) # Only reads 'Name' column. Other columns will be ignored.
转换器:通过定义的函数帮助转换列中的值。

na_values :缺省值为 NaN。如果您希望其他字符串被视为 NaN,请使用此选项。预期的输入是字符串列表。
pd.read_csv('file_name.csv',na_values=['a','b']) # a and b values will be treated as NaN after importing into dataframe.
如何和熊猫“读 _csv”
原文:https://towardsdatascience.com/how-to-read-csv-with-pandas-e91ea6016e76?source=collection_archive---------11-----------------------
使用 read_csv 作为通用工具
数据科学项目中最耗时的部分是数据清理和准备。Pandas 是一个非常强大和通用的 Python 数据分析库,可以加速项目的预处理步骤。我们通常倾向于使用带有默认参数的函数,这使得我们无法充分利用函数的优势。

米卡·鲍梅斯特在 Unsplash 上的照片
熊猫最广泛使用的功能之一是 read_csv ,它读取逗号分隔值(csv)文件并创建一个数据帧。在这篇文章中,我将重点介绍 read_csv 函数的许多不同参数以及如何有效地使用它们。
Pandas 的基本数据结构是 DataFrame ,它以表格的形式表示数据,带有标记的行和列。
一如既往,我们从进口熊猫开始。
import numpy as np
import pandas as pd
我创建了一个示例数据框架,旨在显示参数的效果和有用性,因此这些值可能没有意义。
让我们从使用不带可选参数的 read_csv 开始:
df = pd.read_csv("SampleDataset.csv")
df.head()

唯一需要的参数是文件路径。我们需要告诉熊猫文件在哪里。如果 csv 文件在同一个工作目录或文件夹中,您可以只写文件名。如果没有,我们可以如下指定位置:
df = pd.read_csv(r"C:\Users\soner\Downloads\SampleDataset.csv")
index_col
默认情况下,从 0 开始的整数索引被分配给数据帧。我们可以显式定义一个列作为索引。例如,我们可能希望使用“ID”列作为索引:
df = pd.read_csv("SampleDataset.csv", index_col='ID')
df.head()

数据类型
有浮点 ID 号有点奇怪。我觉得没有哪家公司是这样分配身份证号的。我们可以使用 dtype 参数指定 read_csv 函数中任何列的数据类型:
df = pd.read_csv("SampleDataset.csv", index_col='ID',
dtype={'ID':np.int32})df.head()

用途
在某些情况下,根据我们对日期的计划,我们可能不需要所有的特性(列)。我们可以在读取所有数据后删除不必要的列。然而,更好的选择是只读取我们需要的列,这可以通过 usecols 参数轻松完成:
cols = ["ID","Deparment","Salary","StartDate","Location"]
df = pd.read_csv("SampleDataset.csv", usecols=cols)df.head()

我们也可以使用列的索引作为参数来使用 cols 参数。以下代码可以很好地完成这项工作:
df = pd.read_csv("SampleDataset.csv", usecols=[2,3,4,5,6])
解析日期
让我们检查列的数据类型:
df = pd.read_csv("SampleDataset.csv")df.dtypes
Unnamed: 0 int64
RowNumber int64
ID float64
Deparment object
Salary int64
StartDate object
Location object
dtype: object
StartDate 列的数据类型是 object,但是我们知道该列包含日期,所以我们可以通过使用 parse_Dates 参数将值读取为 date。
df = pd.read_csv("SampleDataset.csv", parse_dates=[5])df.dtypes
Unnamed: 0 int64
RowNumber int64
ID float64
Deparment object
Salary int64
StartDate datetime64[ns]
Location object
dtype: object
日期现在有了更合适的格式。
na_values

缺失值有时不是熊猫可以检测为“缺失”的格式。例如,在位置列中,'?'是一个缺失值,但是 read_csv 函数无法知道这一点,除非我们指定它。我们可以使用 na_values 来指示要被识别为“缺失”的附加值:
df = pd.read_csv("SampleDataset.csv", na_values=['?'])df.head()

船头和船尾
如果我们有一个非常大的数据帧,并且只想读取其中的一部分,我们可以使用 nrows 参数,并指出我们想读取多少行并放入数据帧:
df = pd.read_csv("SampleDataset.csv")
df.shape
(30,7)df = pd.read_csv("SampleDataset.csv", nrows=10)
df.shape
(10,7)
在某些情况下,我们可能希望跳过文件开头的一些行。我们可以把要跳过的行数传递给skip prowsparameter,或者传递一个带有整数的列表,指示要跳过的行:
- skiprows=5:跳过前 5 行
- skiprows=[1,3]:跳过第一行和第三行
原始数据帧:

df = pd.read_csv("SampleDataset.csv", skiprows=3)
df.head()

跳过前三行,数据帧从第四行开始。然而,这里有一个问题。第 4 行用作列名。
表头
我们可以使用头参数来解决这个问题。在大多数情况下,csv 文件中的第一行包括列名,并推断为标题。因此,如果没有指定列名,csv 文件的默认行为是采用header=0,并且从文件的第一行推断列名。
如果header=None ,列名被指定为整数索引,文件的第一行被读取为数据帧的第一行:
df = pd.read_csv("SampleDataset.csv", header=None)
df.head()

所以我们可以设置header=None并使用 skiprows,但是记住第一行包括列名。如果skiprows=3,数据框的第一行变成有ID=127的人。
df = pd.read_csv("SampleDataset.csv", header=None, skiprows=3)
df.head()

姓名
如果我们想改变列名或者文件中没有一行包含列名,我们可以使用 names 参数:
cols=["Drop1","Drop2","Employee_ID","Department","Salary", "StartDate"]df = pd.read_csv("SampleDataset.csv", names=cols, skiprows=1)
df.head()

read_csv 函数还有很多附加参数。我试着解释我常用的参数,但是你可以在这里查看所有的参数列表。
感谢您的阅读。如果您有任何反馈,请告诉我。
如何从亚马逊 SageMaker 上读取 S3 的数据文件
原文:https://towardsdatascience.com/how-to-read-data-files-on-s3-from-amazon-sagemaker-f288850bfe8f?source=collection_archive---------1-----------------------
将您的数据科学工作流保存在云中

萨彦纳特在 Unsplash 上的照片
亚马逊 SageMaker 是由亚马逊网络服务公司(AWS)提供的强大的云托管 Jupyter 笔记本服务。它用于创建、训练和部署机器学习模型,但它也非常适合进行探索性数据分析和原型制作。
虽然它可能不像一些替代品那样对初学者友好,如 Google CoLab 或 Kaggle Kernels ,但有一些很好的理由让你想在 Amazon SageMaker 内从事数据科学工作。
我们来讨论几个。
托管在 S3 的私有数据
机器学习模型必须在数据上训练。如果您正在处理私有数据,那么在访问这些数据进行模型训练时必须特别小心。将整个数据集下载到您的笔记本电脑上可能违反您公司的政策,或者可能是轻率的。想象一下,您的笔记本电脑丢失或被盗,而您知道其中包含敏感数据。顺便提一下,这是你应该总是使用磁盘加密的另一个原因。
云中托管的数据也可能太大,不适合放在你个人电脑的磁盘上,所以更简单的做法是将数据托管在云中,直接访问。
计算资源
在云中工作意味着您可以访问强大的计算实例。AWS 或您首选的云服务提供商通常会允许您选择和配置您的计算实例。也许你需要高 CPU 或高内存——比你的个人电脑所能提供的更多。或者您可能需要在 GPU 上训练您的模型。云提供商提供了许多不同类型的实例。
模型部署
如何直接从 SageMaker 部署 ML 模型是另一篇文章的主题,但是 AWS 为您提供了这个选项。您不需要构建复杂的部署架构。SageMaker 将剥离一个托管计算实例,该实例在一个用于执行推理任务的 API 后面托管一个经过训练的 ML 模型的 Dockerized 版本。

由考特尼·摩尔在 Unsplash 上拍摄的照片
将数据加载到 SageMaker 笔记本中
现在让我们进入这篇文章的主题。我将向您展示如何使用 Python 加载保存为文件的数据到 S3 桶中。示例数据是我想加载到我的 SageMaker 笔记本中的 Python 字典。
加载其他数据类型(如 CSV 或 JSON)的过程类似,但可能需要额外的库。
第一步:知道你把文件放在哪里
你需要知道 S3 桶的名字。文件在 S3 桶中被表示为“键”,但是从语义上来说,我发现仅仅从文件和文件夹的角度来考虑更容易。
让我们定义文件的位置:
bucket = 'my-bucket'
subfolder = ''
步骤 2:获得从 S3 桶中读取的权限
SageMaker 和 S3 是 AWS 提供的独立服务,一个服务要对另一个服务执行操作,需要设置适当的权限。谢天谢地,预计 SageMaker 用户将从 S3 读取文件,所以标准权限是没问题的。
尽管如此,您仍然需要导入必要的执行角色,这并不难。
from sagemaker import get_execution_role
role = get_execution_role()
步骤 3:使用 boto3 创建一个连接
Python 库旨在帮助用户以编程方式在 AWS 上执行操作。它将有助于连接 S3 桶的 SageMaker 笔记本。
下面的代码列出了 S3 存储桶上特定子文件夹中包含的所有文件。这对于检查存在什么文件很有用。
如果要遍历许多文件,可以修改这段代码,用 Python 创建一个列表对象。
第 4 步:直接从 S3 存储桶加载经过酸洗的数据
Python 中的pickle库对于将 Python 数据结构保存到文件中很有用,以便以后可以加载它们。
在下面的例子中,我想加载一个 Python 字典,并将其赋给data变量。
这需要使用boto3来获得我想要加载的 S3 上的特定文件对象(pickle)。注意例子中的boto3客户端如何返回包含数据流的响应。我们必须用pickle库将数据流读入data对象。
与使用pickle加载本地文件相比,这种行为有点不同。
因为这是我总是忘记如何做好的事情,所以我将这些步骤编入了本教程,以便其他人可以受益。
替代方法:下载文件
有时,您可能希望以编程方式从 S3 下载文件。也许您想将文件下载到本地机器或连接到 SageMaker 实例的存储器中。
为此,代码略有不同:
结论
在这篇文章中,我主要关注 Amazon SageMaker,但是如果你在本地机器上正确安装了boto3 SDK,你也可以从 S3 那里读取或下载文件。由于我自己的大部分数据科学工作都是通过 SageMaker 完成的,您需要记住设置正确的访问权限,所以我想为其他人(以及我未来的自己)提供一个资源。
显然 SageMaker 不是镇上唯一的游戏。如今有各种不同的云托管数据科学笔记本环境可供选择,与五年前(2015 年)我完成博士学位时相比,这是一个巨大的飞跃
我没有提到的一个考虑是成本:SageMaker 不是免费的,而是按使用量计费的。完成后,记得关闭笔记本实例。
如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。一个月 5 美元,这样你就可以接触到我所有的作品以及成千上万其他作家的作品。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。
[## 通过我的推荐链接加入 Medium 米哈伊尔·克拉森
阅读米哈伊尔·克拉森(以及媒体上成千上万的其他作家)的每一个故事。您的会员费直接支持…
mikhailklassen.medium.com](https://mikhailklassen.medium.com/membership)
如何使用 AWS S3/Lambda 在 bubble.io 中读取 Excel/CSV 文件
原文:https://towardsdatascience.com/how-to-read-excel-csv-file-in-bubble-io-using-aws-s3-lambda-a9af89153d2a?source=collection_archive---------29-----------------------
入门
代码少的数据 ETL 管道;)

照片由 ETA+ 在 Unsplash 上拍摄
嗨大家好,今天我将在 bubble.io 中演示一个非常简单的方法来实现从 Excel/csv 文件到 SQL 数据库的数据提取。
此工作流使用 AWS S3/Lambda 函数作为连接桥梁,与手动输入相比,它既节省时间,如果您使用 AWS 自由层服务,也节省成本。
唯一的成本是在 bubble 中安装一个名为 AWS 文件上传器的插件(35 美元),仅此而已。很神奇,对吧?
现在让我们深入研究一下,看看它是如何工作的。
第一步:确认您输入的数据,并据此建立数据库
这其实是一个蛋和鸡的问题。通常,当您发现 Excel/Access 不再能满足您快速管理和检索数据的目的时,就会发生这种情况,这时您就开始构建关系型(和/或)非关系型数据库。

迪伦·吉利斯在 Unsplash 上的照片
例如,作为一名负责全球或地区市场的高级项目经理,使用 Excel 作为分发和提取数据的标准模板将非常有用,特别是当您的项目经理遍布世界各地,并且您希望集中项目信息并从整体角度监控进度时。
第二步:创建你的泡泡页面来反映项目信息

测试用项目数据库
假设我想更新这个项目信息。

演示项目信息的气泡页
我知道这个页面看起来很丑,但它只是所列信息的一个非常基本的演示。您可以在此基础上开发许多变体。
这里有一些额外的注释:
- 允许用户下载 excel 模板,确保所有用户将输入统一的数据,并易于更新;
- 您可以为文件添加前缀,这样我们就不会被各种不同的文件名所困扰,也可以从文件名中提取关键信息作为关键标识符;
- 我建议选择 uuid_filename 作为文件结构,因为这样更容易看到每个上传的文件。

文件上传功能调整
第三步:部署 bubble 插件——AWS 工作流程
AWS 文件上传插件👉S3 水桶👉希腊字母的第 11 个👉SQL 数据库
S3 桶和 Lambda 之间的微妙联系是通过触发器实现的,所以一旦任何东西上传到 S3 桶,就会有一个事件生成,你的代码将从这里开始。

新 Excel 文件信息

已将文件上传到 uuid 为的 S3 桶中
在我的方法中,我使用两层来提取数据。
第一层,“文件上传”S3 存储桶触发“提取功能”Lambda 功能,该功能在“csv 接收器”S3 存储桶中输出新的 CSV 文件。

为加载生成的 CSV

λ接口
第二层,“csv 接收器”S3 存储桶触发“CSV 到 RDS”Lambda 函数,该函数从 CSV 中提取数据并将其输入到 SQL 数据库中。
这背后的原因:
- 这个中间步骤允许用户检查是否有不规则的数据;
- 如果它是非常大的 excel 文件,它转移了 1 lambda 函数的计算压力;
- 如果需要,你可以在第一个 lambda 函数中写一些简单的代码来创建一个文件上传日志,跟踪所有用户的上传历史;
成功上传文件并刷新页面后,项目信息就成功更新了!

更新的项目信息页面
实际上,AWS 生态系统中有许多有趣的部分,围绕 Lambda 也有许多有用的工具,但由于文章的长度,我将只提到几个:
- 如果你正在使用 pandas 或 pymysql 库,在 Lambda 中部署一个层;
- CloudWatch 非常非常有用,可以记录你所有的 lambda 活动;
- 如果你在 bubble 中使用 AWS 文件上传插件,请确保调整你的 S3 存储桶权限策略,否则它将无法工作。
参考:https://docs.zeroqode.com/plugins/aws-file-uploader-plugin
感谢大家阅读这篇文章,我将继续在 bubble.io 中分享有用的工具和技巧。
如何阅读科技论文
原文:https://towardsdatascience.com/how-to-read-scientific-papers-df3afd454179?source=collection_archive---------2-----------------------
使用三重方法提高效率

放在我自己桌子上的高亮纸
本文的目标
这篇文章应该作为如何阅读科学论文的粗略指南,因为这种技能在大学里很少教授,可能会导致巨大的挫折。大多数时候,人们认为学生们已经知道了一些阅读研究论文的方法,但是我不得不承认,一开始我一个也不知道。
当我不得不阅读我的第一篇论文时,我只是开始从头到尾阅读它们。像一本书。我看了每一个表格,数字和数学方程式,试图从中找出意义。我想了解这一切,不要错过任何一条信息!恰好对此有一个合适的术语:对错过的恐惧(FOMO) 。但当我在几个小时的沮丧和背景阅读后来到结尾时,我意识到这篇论文并没有我一开始想象的那么有帮助。我已经忘记了大局或者从一开始就没有大局。我迷失在细节中。这不是一种非常有效的阅读论文的方式,尤其是当你在做一项文献调查或者一天之内必须阅读多篇论文的时候。
但是似乎有一个更好的方法来解决这个问题:三关方法。
本文的其余部分结构如下,并更详细地解释了每个主题:
- 三关做法(TL; ) 博士
- 第一关:鸟瞰图
- 第二关:抓住内容
- 第三关:虚拟重新实现论文
- 做文献调查
- 可选扩展
- 小盒子
- 荧光笔
- 思维导图
- 番茄时段
- 费曼技术与橡皮鸭调试
- 帕金森定律和帕累托原理
三步法(TL;博士)
在 Srinivasan Keshav 的“如何阅读论文”[1]中,他描述了作为过滤系统的三遍方法。这是一种阅读论文的迭代和增量方式。这种演绎方法从总体概述到具体细节,而每一步都比前一步花费更多的时间,并在每次迭代中给你更深刻的见解。
- 第一关:在这里你得到了论文的鸟瞰图或“大图”。这一步通常需要 5 到 10 分钟。你浏览论文的结构,忽略任何细节,比如数学方程,但是你应该完整地阅读摘要、标题、引言和结论。这一步作为第一步检查论文是否值得一读。通过遵循这种方法,你已经可以丢弃那些没有帮助的论文,例如文献综述。
- 第二遍:这里你试着通过整体阅读来理解论文的内容。这一步可能需要 1 个小时。你仍然可以忽略像数学方程式这样的细节,但是试着在空白处做些笔记,写下要点。试着用你自己的话重新表述要点。
- 第三关:在继续这一步之前,你必须非常确定这篇论文值得你花时间,因为作为初学者,它可能需要长达 5 个小时。更有经验的读者可能能在 1 小时内完成这一步。现在是时候阅读完整的论文及其所有的数学公式和细节了。尝试虚拟地重新实现论文或使用任何你喜欢的工具来重现结果。如果你是一个评论者,那么你可能需要采取这个步骤来给出详细的反馈。
我想指出的是,这篇文章不是关于论文的评论。然而,如果你正在寻找任何复习指南,那么看看这篇文章末尾的参考文献[2]、[3]、[4]。
以下部分更详细地描述了三步法的每个步骤。
第一关:鸟瞰
"第一遍是快速浏览,获得论文的鸟瞰图."斯里尼瓦桑·凯沙夫
第一遍的目标是了解论文的全貌,并且不应该超过 10 分钟。你不必深入细节,甚至不必通读整篇论文。
浏览一下这篇论文,看看它是如何组织的。查看小节和子小节,但忽略它们的内容。当你阅读章节和小节时,你的大脑已经为即将到来的内容做好了准备,你的大脑中可能已经出现了一些模糊的问题。这将使你更容易发现重要或有趣的段落,如果你决定继续下去。
尽管您只是浏览了一下结构,但您应该完整地阅读以下部分:
- 摘要
- 标题
- 简介
- 结论
这些部分会给你足够的信息,让你知道这篇论文是关于什么的,是否值得进一步阅读。在阅读这些章节的时候,你也可以看一下参考文献,看看有些东西你是否熟悉,或者有些东西你以前读过的其他论文中已经提到过。
在第一遍结束时,你应该能够回答 Keshav[1]所说的所谓的“5c ”:
- 类别:类别描述了论文的类型。这篇论文是关于原型的吗?关于一种新的优化方法?是文献调查吗?
- 上下文:上下文使这篇论文成为其他论文的视角。还有哪些论文与此有关?你能把它和别的东西联系起来吗?你也可以把上下文看作一棵语义树,在这里你可以给文章赋予特定的重要性。是重要的枝干还是无趣的叶子?也许你在这个领域没有任何先验知识,因此你仍然需要从头开始构建你的语义树。这在开始时可能会让人失去动力,但这是正常的。
- 正确性:正确性,顾名思义,是一种有效性度量。假设成立吗?大多数情况下,第一遍不会给你足够的信息来肯定地回答这个问题,但你可能有一种预感,这在开始时就足够了。
- 大多数论文都在引言部分列出了他们的来稿。这些贡献有意义吗?它们有用吗?它们解决了哪些问题?这些投稿新颖吗?
- 根据您刚刚阅读的部分,您认为这篇论文写得好吗?你发现语法错误了吗?有错别字吗?
这一步应该作为快速的第一步过滤。当你读完第一遍时,你可以决定继续读第二遍,或者你决定不继续读,因为:
- 你缺乏背景信息
- 你对这个话题了解不够
- 这篇论文你不感兴趣或者对你没有好处
- 这篇论文写得很差
- 作者做了错误的假设
如果那篇论文不属于你的专业领域,但在以后可能会变得与你相关,那么这第一遍就足够了,你可能不必继续阅读。如果不是这样,那么你可以继续第二遍。
第二关:抓内容
"有时,即使在第二遍结束时,你也不会理解一篇论文."斯里尼瓦桑·凯沙夫
第二遍可以持续 1 个小时,在这里你应该阅读完整的论文。忽略诸如证明或方程式等细节,因为大多数时候你不需要那些特定的知识,而且这会耗费你宝贵的时间。在纸边上做些笔记,写下要点。用自己的话在空白处写下小的总结或关键点是一个很好的方法,可以看出你是否真正理解了你刚刚读过的内容;你会记得更久。
查看论文中任何类型的插图,如表格和数字,看看你是否能发现任何错误或差异。插图有意义吗?它们传达了什么样的信息?轴的标签是否正确?图表有适当的标题吗?像这样草率的工作已经是一篇整体写得很差的论文的一个强有力的指标。
你可以标记相关的未读参考文献,以便进一步阅读,这是了解更多背景知识的好方法。建立你的语义树,看看哪些论文是重要的分支,哪些是不重要的叶子。
在第二遍结束时,你可能仍然不理解你刚刚读到的内容。这可能是由许多原因造成的。也许这不是你的专业领域,或者你缺乏背景信息。不要感到气馁,因为这种事情经常发生;甚至对教授也是如此…有人告诉我。
请记住,研究小组经常花几个月甚至几年来进行他们的研究。现在,他们必须将他们的结果和知识压缩到一篇论文中,该论文可能必须满足某些要求才能被会议接受,例如,一定的页数。如果你这样想的话,当你在一个小时内没有理解所有事情的时候,你就不会那么沮丧了。
当你写下你不理解的东西时,有时会有帮助。然后你就有了一个很好的起点,可以通过阅读一些背景知识来填补知识空白。
您现在有不同的选择:
- 你可以停止继续读下去,因为出于几个原因,这篇论文对你没有好处
- 读完一些背景材料后,把纸放在一边继续读
- 继续第三遍
第三关:虚拟地重新实现论文
“这一关需要非常注意细节。你应该识别并质疑每一句话中的每一个假设。”斯里尼瓦桑·凯沙夫
如果你是初学者,这一关可能需要 4 到 5 个小时。这是大量的工作,你应该仔细考虑这一步是否值得你花时间。另一方面,如果你已经是一个有经验的读者,那么这一步可能只需要你 1 个小时。如果您是指定的审阅者,或者您已经确定您必须理解论文的所有细节,则这一步是强制性的。
通读这篇论文,质疑每一个细节。现在是时候进入本质的数学方程,并试图理解发生了什么。做与作者相同的假设,从零开始重新创作作品。你可以在头脑中重新执行这些步骤,或者使用任何你认为合适的工具。用一张纸画出不同步骤的流程图,或者使用伪代码。这真的取决于你。大部分时间我都在阅读与人工智能和计算机科学相关的论文,因此用原始 Python 或使用 Jupyter 笔记本重新实现东西是有意义的。这真的取决于你的领域。
在这一轮结束时,你应该是一个专家,知道论文的优点和缺点。你可以对遗漏的引用和潜在的问题进行陈述。你可以重建结构,用简单的语言向某人解释这篇论文的内容。
通过教别人来学习的概念被称为“费曼技巧”,是发现你理解中的任何差距的好方法。
[## 向费曼技术学习
他们称费曼为“伟大的解释者”
medium.com](https://medium.com/taking-note/learning-from-the-feynman-technique-5373014ad230)
做一个文献调查
做一个文献调查和阅读一篇论文有点不同,但是你仍然可以应用三重方法。
第一关
第一遍你必须收集可能有用的文件。你可以使用像谷歌学术这样的搜索引擎,输入关键词找到 3 到 5 篇最近的论文。我通常做的是创建一个简单的论文列表,按照论文的主题、出版年份和引用次数进行分类。引用次数通常是一篇论文重要的良好指标。仅仅在谷歌中输入你的关键词也能得到令人惊讶的好结果。

当你准备好你的初始论文小集合时,你可以继续对它们进行通常的第一遍,以获得大的图片。你也可以浏览参考文献,看看这些论文是否有共同的引用。常见的引用是包含在你的调查中的很好的候选。
第二遍
当你确定了常见的引用和重复的作者,你可以访问他们的网站,看看你是否能发现任何最近的工作。也下载常用的论文,并再次应用单篇论文的三关方法。
第三遍
在这里,你可以尝试访问顶级会议或期刊的网站,浏览最近的会议记录。尝试确定相关的高质量工作,并再次应用单个论文的三关方法。
可选扩展
请记住,这些可选步骤可能会给三重方法增加一些时间。如果你只是浏览文件,看看它们是否有帮助,它们可能对你没有好处。另一方面,如果你已经知道你必须完整地阅读和理解这篇论文,并且没有其他的方法,那么这些步骤也可以帮助你。这些是我的个人实践,我一直在努力改进它们。
小盒子
当你看下面的图片时,你可以看到我用盒子围住了数学方程式、数字和表格。我喜欢用明显分开的盒子来看论文,并把正文和其他部分分开。我通常在第一遍浏览时这样做。这有助于我量化在数学方程式方面的细节,我可以期待在以后,它只是看起来更愉快。

数学方程式周围的小盒子
荧光笔
荧光笔是一个很好的工具来标记你论文中的部分,并赋予它们独特的意义。你可以试着想出自己的高亮系统或者使用现有的系统。试着赋予每一种颜色与众不同的意义,并坚持下去。

一套漂亮的荧光笔
在第二遍时,我通常用黄色表示有趣或重要的句子。橙色代表引用,绿色代表定义或标语。然而,请随意使用您喜欢的任何系统。请记住,高亮显示并不能代替记笔记!在第二遍的时候,你可以在空白处做笔记,画一些小图表以便更好地理解,并结合使用荧光笔。

每种颜色都有独特的含义
论文末尾有趣或重要的参考文献获得和之前一样的颜色。

用橙色标记参考文献
思维导图
如果你更注重视觉,想更好地了解论文,思维导图可能是一个合适的选择。创建思维导图没有严格的规则,我只是从中间的论文标题开始。大箭头指向主要部分的标题,并用橙色突出显示。这些是大树枝。第一级子部分用绿色突出显示。其他任何东西都不会突出显示。随意想出自己的系统。
这一步通常会在第一遍的基础上增加 25 分钟,我仍然不确定这是否值得。另一方面,如果你继续第二遍,想写下一个重要的笔记,你可以直接把它放到思维导图的相应节点上。这可能有助于你更直观地了解全局。过了一段时间后,这也可能是一种更快的方法来刷新你对一篇论文的记忆。

番茄时段
如果你缺乏动力,番茄工作法是一个很好的工具。有时候,并不是你不知道如何阅读一篇论文,而是你被它吓倒,甚至缺乏开始阅读的动力。拖延症开始了,你错过了一个重要的回顾截止日期。
拿一个计时器,设置为 25 分钟。不要期待任何结果。设置为 25 分钟就可以开始了。排除一切干扰,遵循三步走的方法,直到 25 分钟结束。你可能无法完成整个三关方法,但在 25 分钟结束时,你可能会惊讶于你所取得的成就。你现在知道这篇论文是关于什么的了,你可能不那么害怕了。你可能会觉得你可以把计时器再调 25 分钟。
通过使用这种计时方法,你可以获得动力,并可以更容易地遵循三步法。好的一面是:你可以将番茄工作法应用于任何任务。
费曼技术与橡皮鸭调试
如前所述,费曼学习技巧是发现你理解中的差距的一个很好的工具。一般步骤是:
- 选择一个你想学习的概念,并把它的名字写在一张纸的顶端。
- 假装你正在向一个事先没有相关知识的人教授这个概念。尽量使用简单的语言,不要简单地背诵。用你自己的话!
- 回顾你的解释。尽管使用了简单的语言,Was 是准确的吗?找出你解释中的弱点,并写在纸上。回到你的学习材料,看看你是否能阐明这些观点。
- 如果你在解释中使用了大量的专业术语或复杂的语言,简化你的解释。
如果你想应用费曼技巧,但手头没有第二步的小兄弟,那么橡胶鸭可能适合你。
橡皮鸭调试背后的想法源于软件工程,最早出现在安德鲁·亨特和戴维·托马斯的《实用程序员》一书中。在这本书里,一个程序员带着一只橡皮鸭,一行一行地向这只鸭子解释代码,以找出任何错误。您也可以为此使用任何其他对象。你有一只猫吗?我敢肯定她一直想知道汉密尔顿蒙特卡罗抽样[6]是如何工作的。

向对你的话题一无所知的人解释
帕金森定律和帕累托原理
下面的两种方法不仅仅局限于阅读论文的任务,也适用于其他任何任务。如果你把这两者结合起来,你就有了一个限定时间的方法,例如,为整篇论文计划 10 次番茄大战,然后停止。你也可以试着给自己一个完全不切实际的时间框架来阅读一篇论文,然后检查你的进展。
帕金森定律 陈述如下:
“工作扩大以填补完成工作的时间”——西里尔·诺斯古德·帕金森
如果你计划花 10 个小时读一篇论文,做笔记,写总结等等,那么它可能会花掉你 10 个小时。
另一方面, 帕累托法则 (也称为 80/20 法则)指出:
"对许多事件来说,大约 80%的结果来自 20%的原因."—维尔弗雷多·帕累托
这意味着你可能要花 20%的精力和时间去理解 80%的文章。这种 80/20 的比例不是固定的,而是一个粗略的估计。也可能是 70/30 左右。
你有没有在临近最后期限的时候,只剩下 30 分钟去做一件你认为要花几个小时的事情?然后你意识到你实际上做得相当好?帕金森定律迫使你进入 30 分钟的时间框架,帕累托原则确保你只做对最终结果贡献最大的任务。通过给自己设定不切实际的、紧迫的截止日期来模拟这种情况。
我希望你喜欢这篇文章,并且我能在你的学术旅程中帮助你。
你对我的文章或项目的更新感兴趣吗?我的简讯每月一次让你了解最新动态!
如果你想支持我,并且你还不是一个中等会员,那么请考虑通过我的推荐页注册:https://medium.com/@christoph.schmidl/membership
参考
[1]s .凯沙夫(斯里尼瓦桑)(2007 年)。如何阅读一篇论文? ACM SIGCOMM 计算机通信评论, 37 (3),83–84。(网址:https://dl.acm.org/doi/pdf/10.1145/1273445.1273458)
[2] Cormode,G. (2009 年)。如何不评论一篇论文:敌对评论者的工具和技术? ACM SIGMOD 记录, 37 (4),100–104。(网址:https://dl.acm.org/doi/pdf/10.1145/1519103.1519122)
[3]迈耶,A. (1992 年)。如何审阅一篇技术论文?能源与建筑, 19 (1),75–78。(网址:https://eta-intranet . LBL . gov/sites/default/files/how-to-review-a-technical-paper _ 0 . pdf)
[4]t .罗斯科(2007 年)。为系统会议写评论。(网址:https://www . cl . cam . AC . uk/teaching/1011/R01/review-writing . pdf)
[5]西里洛,F. (2018)。番茄工作法:改变生活的时间管理系统。兰登书屋。
[6]贝当古,M. (2017)。哈密尔顿蒙特卡罗的概念介绍。 arXiv 预印本 arXiv:1701.02434 。(网址:https://arxiv.org/pdf/1701.02434.pdf)
corona 疫情期间如何用 Python 实现地理可视化
原文:https://towardsdatascience.com/how-to-realize-geo-visualization-with-python-during-corona-pandemic-f822d3cbf4fe?source=collection_archive---------28-----------------------
基于 GeoPandas 和 Matplotlib 的德国 web 刮削日冕信息的地理演示

乔纳森·博尔巴在 Unsplash 上的照片
在这个故事中,我尝试分享我用 Python 包(Geopandas,pandas,Matplotlib)制作 Corona 信息地理可视化的经验。电晕信息是通过网刮提取的。由于 web 抓取并不是我们的目标,而是一种获取信息的方法,所以我不会花太多时间解释这部分代码🌚。
编者注:towardsdatascience.com是一家以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
社会背景:科罗纳·疫情
截至 2020 年 3 月 13 日,当新增病例数超过中国时,世界卫生组织(世卫组织)开始认为欧洲是新冠肺炎疫情的活跃中心。[1][2]
我的父母住在中国,他们目睹了疫情的严重性。在一月、二月和三月,他们不得不总是呆在家里😷。只有我的父亲一周两次去市场购买全家基本生活所需的必需品。后来在欧洲,许多城市也实行了封锁。我住在德国,那些日子太可怕了。在欧洲爆发之前,我呆在家里,做了一个在德国感染的电晕的地理可视化,以消磨时间😇。https://github.com/Kopfgeldjaeger/Covid-19_in_germany,于 2020 年 2 月 28 日提交。

存储库的简介图像
代码上传至今已经半年多了。现在在欧洲,第二波疫情来势凶猛。我将为抗击疫情贡献自己的力量,用可视化的日冕信息警告人们。
在疫情开始的时候,关于日冕的视觉信息很少。我和朋友每天打开网站了解德国 16 个州有多少感染者。后来,更多的 Dash 网站被建立来可视化相同的信息,甚至 YouTube 上的 Corona 实时计数器。
今天我打开了每天早些时候访问的 www.coronavirus.jetzt/karten/deutschland/网站。那里关于日冕的信息是以表格的形式呈现的。

网站截图
它非常清晰和简洁,然而,对于不熟悉德国地理的人来说,很难想象每个州的日冕分布情况。因此,我们需要添加这些地理信息,最好是在图像中与日冕信息一起展示。
抓取日冕信息的 HTML 表格
我们目标的第一步是收集所有 16 个州的感染和死亡人数。这部分作品与另一个媒介故事非常相似[3]。
下面的代码可以让我们得到信息,我把这些信息保存在一个 Numpy 数组中,这个数组很容易转换成 Pandas 数据帧。
import requestsimport lxml.html as lhimport pandas as pd
import numpy as npurl='https://www.coronavirus.jetzt/karten/deutschland/'page = requests.get(url)doc = lh.fromstring(page.content)tr_elements = doc.xpath('//tr')tr_elements = doc.xpath('//tr')col=[]#For each row of 16 states, store the name of state, the numbers of infected and deathsfor n in range(1,len(tr_elements)):row =[]for t in tr_elements[n]:name=t.text_content()row.append((name))col.append(row)col= np.array(col)df = pd.DataFrame({'Bundesland': col[:,0], 'Infizierte': col[:,1], 'Todesfälle':col[:,2]})df
数据帧(df)看起来像:

查找德国的 shapefile
最后一步完成后,我们寻找德国 16 个州的地理信息🌴🌋🌅。使用地理定位数据时,地图是交流和比较信息的一种很好的方式。如何用 Python 展示地图?答案是 GeoPandas[4],这是一个开源项目,旨在简化 python 中地理空间数据的处理。它结合了 pandas 和 shapely 的功能,在 pandas 中提供地理空间操作,并为 shapely 提供多种几何图形的高级接口。
为了生成德国地图,我们需要下载必要的形状文件。这个链接并不是唯一为我们提供德国形状文件的链接。不同类别的 shapefiles 有很多种。我在这里使用的是解压 zip 文件后的文件名“geomap/vg2500_bld.shp”。
import matplotlib.pyplot as pltimport geopandas as gpdfp = "geomap/vg2500_bld.shp"map_df = gpd.read_file(fp)map_df.head()map_df.plot()
map_df 展示了德国各州的地图。

map_df.plot()的结果
我们可以用 plt.annotate 添加州名,代码如下
fig, ax = plt.subplots(1, figsize=(10, 6))map_df['coords'] = map_df['geometry'].apply(lambda x: x.representative_point().coords[:])map_df['coords'] = [coords[0] for coords in map_df['coords']]map_df.plot(ax=ax)for idx, row in map_df.iterrows():plt.annotate(s=row['GEN'], xy=row['coords'],horizontalalignment='center')plt.xticks(np.array([]))plt.yticks(np.array([]))

带注释的德国各州地图
最后一个插图有一个小问题,柏林和勃兰登堡的注释相互重叠。我们可以对 if 句使用一个技巧:
fig, ax = plt.subplots(1, figsize=(10, 6))map_df.plot(ax=ax)for idx, row in map_df.iterrows():if idx ==10: # the idx of Brandenburg is 10plt.annotate(s=row['GEN'], xy=row['coords'],verticalalignment='top',horizontalalignment='right')continueplt.annotate(s=row['GEN'], xy=row['coords'],verticalalignment='bottom',\horizontalalignment='center')plt.xticks(np.array([]))plt.yticks(np.array([]))
如果注释是针对勃兰登堡或柏林的,我们可以设置它们注释的属性,以使它们不再重叠。

带有清晰注释的德国各州地图
由于柏林在地理上被勃兰登堡包围,两个州的注释很容易重叠,所以我们后来又使用了这个技巧。
信息融合
我们既有日冕信息,也有德国各州的地理信息。然而,这两条信息并不相关。我们需要将它们合并成一个表格或数据帧。和熊猫一起🐼连接方法[5],我们可以将它们合并成一个数据帧。
merged = map_df.set_index('GEN').join(df.set_index('Bundesland'))merged

结合日冕信息和地理信息的合并数据帧
用 Matplotlib 从数据帧到插图
令人兴奋的是,我们已经到了用 Matplotlib 绘制结果的最后一步。
Matplotlib 是 Python 编程语言及其数字数学扩展 NumPy 的绘图库。它提供了一个面向对象的 API,使用 Tkinter、wxPython、Qt 或 GTK+等通用 GUI 工具包将绘图嵌入到应用程序中。还有一个基于状态机(如 OpenGL)的过程化“pylab”接口,设计得与 MATLAB 非常相似,尽管不鼓励使用它。[6]“维基百科”
在我的最后一个故事中,也是关于如何利用 Matplotlib 对研究结果进行可视化[7]。
https://towards data science . com/how-to-draw-a-bar-graph-for-your-scientific-python-a 6 C2 a5 E6 BCD 7
在这里,我们继续利用 Matpotlib 实现地理可视化,因为数据帧包含所需的地理信息。
column = df['Infizierte']max_Infizierte = column.max()column = df['Todesfälle']max_Todesfälle = column.max()vmin, vmax = 0, max_Infiziertemerged['coords'] = merged['geometry'].apply(lambda x: x.representative_point().coords[:])merged['coords'] = [coords[0] for coords in merged['coords']]# create figure and axes for Matplotlibfig, ax = plt.subplots(1, figsize=(10, 6))merged.plot(column='Infizierte', cmap='YlOrRd', linewidth=0.8, ax=ax, edgecolor='0.8')for idx, row in merged.iterrows():if idx =='Berlin':plt.annotate(s=row['Infizierte'], xy=row['coords'],horizontalalignment='right',fontsize=8)continueplt.annotate(s=row['Infizierte'], xy=row['coords'],horizontalalignment='center',fontsize=8)# remove the axisax.axis('off')# add a titleax.set_title('Coronavirus infected in Germany (18.09.2020)', \fontdict={'fontsize': '18','fontweight' : '3'})ax.annotate('Source: [https://www.coronavirus.jetzt/karten/deutschland/',](https://www.coronavirus.jetzt/karten/deutschland/',)xy=(0.2, .06), xycoords='figure fraction',horizontalalignment='left', verticalalignment='top',fontsize=10, color='#555555')sm = plt.cm.ScalarMappable(cmap='YlOrRd', norm=plt.Normalize(vmin=vmin, vmax=vmax))sm._A = []cbar = fig.colorbar(sm)fig.savefig('testmap_1.png', dpi=300)
使用上面的代码,我们得到如下的图

截至 2020 年 9 月 18 日,德国最新的冠状病毒感染病例数
同样,我们也可以绘制德国直到今天 2020 年 9 月 18 日的死亡人数。为了使这个图与上一个不同,我从 Matplotlib [8]中选择了另一个调色板。

截至 2020 年 9 月 18 日,德国最新的电晕死亡病例数
正如上图“带有清晰注释的德国各州地图”所示,我们使用相同的技巧为柏林和勃兰登堡的数字设置了不同的注释格式,这样两个注释几乎不会重叠。
结论
在这个故事中,我介绍了一种制作地理可视化的方法,通过解释我的工作流程,使德国地图中显示的日冕情况直观且易于访问,从 web 抓取开始,到日冕地图的插图结束。所有相关文件上传到 GitHub:https://GitHub . com/Kopfgeldjaeger/Medium _ blogs _ code/tree/master/1 _ corona _ visualization。
最后但同样重要的是,我希望疫情将很快结束。我们可以一起在未来取得进步🚀,不管你现在住在哪里,也不管外面的日冕情况有多糟糕。
参考
[1]弗雷德里克斯 2020 年 3 月 13 日)。“世卫组织称欧洲是疫情冠状病毒的新中心”。纽约邮报纽约邮报T5。2020 年 5 月 9 日检索。
[2] “世卫组织宣布南美为新新冠肺炎震中”。巴西报道。2020 年 5 月 22 日。检索于 2020 年 6 月 1 日。
[3]https://towards data science . com/we b-scraping-html-tables-with-python-C9 Baba 21059
https://geopandas.org/
https://pandas.pydata.org/docs/
https://matplotlib.org/
[7]https://towards data science . com/how-to-draw-a-bar-graph-for-your-science-paper-a 6 C2 a5 E6 BCD 7
[8]https://matplotlib . org/3 . 1 . 1/tutorials/colors/colormaps . html
如何识别和纠正谷歌分析报告中的(未设置)值
原文:https://towardsdatascience.com/how-to-recognize-and-correct-the-not-set-value-in-google-analytics-reports-1441ff26cd2f?source=collection_archive---------43-----------------------

来源:沉积照片
了解更多关于 Google Analytics 报告中(未设置)值出现的信息,为什么它会出现在那里,以及如何减少该值的百分比。
你有没有注意到谷歌分析中的(未设置)值而不是实际值?这意味着 Google Analytics 没有关于这个值的数据,或者无法解读它。很明显,这个值对你这个营销专员来说是个美中不足的地方。你有数字,但不清楚它们是什么意思,以及如何在你的数据分析中使用它们。
此外,在一些标准的谷歌分析报告中获得一个(未设置的)值是一个警告信号,表明在你的网站上如何实现分析存在一些错误。在第一次设置分析和添加新功能时,观察这个值尤其重要。
观众报告
地理和移动报告组
Google Analytics 借助 cookies、移动设备的广告标识符等自动获取这些报告的数据。
您可以在地理语言报告中找到(未设置的)值。例如,在这张截屏显示的报告中,Google Analytics 无法为 1.24%的网站访问者定义语言:

图片由作者提供
地理位置报告几乎相同:

图片由作者提供
移动设备报告显示,3%的访问者的设备无法识别:

图片由作者提供
一般来说,你至少可以找到 1%访问者的(未设置)值。显示该值有各种原因,遗憾的是,我们无法影响这些原因:
- 删除的 cookies
- 用户浏览器中禁用了 JavaScript
- 无法检测到基于 IP 的位置或根本无法检测到 IP
- 各种拦截器(广告拦截器等。)
技术报告小组
这里有一个更有趣的报告:技术——浏览器和操作系统。每次访问者进入网站,他们的浏览器都会发送一个带有用户代理的字符串。该字符串包含有关发送请求的平台的信息,包括浏览器上的数据。GA 接收该信息,但有时它可能不可用。结果,我们在报告中得到(未设置的)值:

图片由作者提供
如果报表中具有(未设置)值的独立访问者的数量少于 5%,这被认为是正常的。如果更高,你应该检查你的流量——可能是由垃圾邮件引起的。在测量协议的帮助下,他们可以向 GA 发送任何虚假点击。要做到这一点,让他们知道你的谷歌分析资源 ID 就足够了。
有两种垃圾邮件。第一个访问你的网站,并产生虚假的流量。这些机器人可以发送带有虚假推荐人标题的 HTTP 请求来掩盖自己。为此,他们甚至可以在 URL 中使用另一个流行网站的名称。由于它们执行 JavaScript 代码的能力,它们不会被 GA 过滤为机器人。
第二种垃圾邮件发送虚假点击,而不访问您的网站。这种垃圾邮件被称为幽灵垃圾邮件。
在我们的例子中,高达 14.95%的访问者的浏览器是未定义的。事务的平均会话持续时间接近两分钟。为了调查这种可疑情况,我们需要更深入地打开采集-所有流量-转介:

图片由作者提供
注意跳出率接近 0%或 100%且会话数超过 10 的推荐源。正如我们所看到的,这发生在字符串 5 到 9 中。最有可能的是,这些是机器人。垃圾邮件的第二个迹象是奇怪的来源名称:在我们的例子中,有我爱你和我想约你。
另外,注意字符串 8 中源名称为 spamcampaign22 的访问者。他们进行了 264 次交易——每位访问者一次。如果我们没有手动将这些数据放入属性中,我们对垃圾邮件流量的猜测将被证明是正确的。
让我们添加主机名作为第二个维度:

图片由作者提供
在这种情况下,我们的网站叫做 example。com。确切地说,该主机需要出现在报告的所有行中。但是所有可疑的推荐源都有值(未设置),正如我们所看到的。我们终于找到了幽灵垃圾邮件!事实上,脸书和 Instagram 的流量也有一部分是垃圾邮件。这意味着这些机器人向 GA 发送虚假的点击,并试图使它们尽可能真实。
如果所有的机器人都发送一个主机值,就像报告中的字符串 9(hostnameghost),我们永远不会知道我们有过多的访客和推荐数据。
在这些报告中忽略(未设置)会导致销售数据损坏,向物业发送虚假交易。因此,您会看到不在您的规格中的事件和您从未销售过的产品视图。
如果您已经设置了从 Google Analytics 到 Google BigQuery 的数据导出(无论是 standard 还是在 OWOX BI Pipeline 的帮助下),这些虚假数据将增加数据库表的权重。因此,数据处理将会变慢,你将会在数据存储和处理上花费更多。
如何摆脱垃圾邮件流量
首先,您必须排除 bot 流量。打开查看设置,在僵尸过滤设置中勾选排除已知僵尸和蜘蛛的所有点击。这将排除可见的机器人。

图片由作者提供
您也可以将过滤器应用于推荐来源。为此,打开视图设置,转到滤镜子菜单,然后点击添加滤镜。现在将过滤器的类型设置为自定义,选中排除,并选择推荐过滤器字段。在过滤器模板字符串中,输入您要从报告中排除其通信的可疑来源的名称。

图片由作者提供
这种方法的局限性在于,我们无法利用真实网站的网址来排除来自僵尸程序的流量。否则,来自这些网站的合法流量也会被过滤掉。在这种情况下,我们可以尝试基于 IP 地址而不是来源进行阻止。如果你已经在 OWOX BI Pipeline 中建立了一个流,那么获取僵尸工具的 IP 地址就不是什么大事了。但是如果机器人不访问网站,IP 屏蔽就没有效果。
要消除幽灵垃圾邮件,请尝试使用主机名过滤器。设置过滤器时,选择包含,然后在过滤器模式字段中输入您网站的域名。

图片由作者提供
流量来源报告
流量来源报告帮助您评估广告来源和渠道的效率。在这些报告的帮助下,您可以比较您发起的每个活动的费用和收入,分析流量质量,并最终增加销售额。如果您看到这些报告中的值(未设置),您将无法确定在哪些方面投入更多,哪些活动需要更改,以及哪些活动应该简单地结束。
如果您没有值得信赖的数据,您就无法正确设置重新定位或为某个活动选择受众群体。显然,不可信的数据也不能应用于队列分析、收入预测、客户终身价值(CLV) 等增强型报告。
所有交通报告
让我们看一些所有交通报告的例子。让我们假设你想知道哪个频道给你最新的访问者。为了找到答案,让我们打开“所有流量-通道”报告,选择通道作为主要参数。我们可以在字符串 4 中观察到 7.19%的新访问者的值(未设置)。但是在这个字符串中隐藏了哪个或哪些特定的频道还不清楚。

图片由作者提供
在“所有流量—源/媒体”报告中,您可以看到类似的情况:

图片由作者提供
为什么此报告显示(未设置的)值?因为部分渠道和来源是由 Google Analytics 自动识别的:有机搜索、其他网站的推荐、直接流量。但是对于一个特殊的活动或广告服务,你需要 UTM 标签。如果 UTM 标签包含错误,就会出现问题。
UTM 标签是包含在来自广告消息的 URL 中的代码片段,并且引导到目标网站。这里有一个例子:
site.com/?UTM _ source = Google & UTM _ medium = CPC & UTM _ campaign = test
有三个必需的 UTM 参数:utm_source、utm_medium 和 utm_campaign。还有两个可选参数:utm_term 和 utm_content。这些参数的值可以是 google、cpc 或 test。
UTM 代码中导致(未设置)报告的典型错误包括:
- 拼错的参数。
- 参数和它的值之间没有等号。
- 没有用&符号分隔的参数和值对。
- 其他语法错误:重复的问号等。
为了避免这些错误,使用专门的 URL 创建工具来帮助自己标记 URL。
活动报告
在“营销活动-有机关键词”报告中,您可能会看到两种有趣的值:(未设置)和(未提供)。

图片由作者提供
(未设置)值意味着 Google Analytics 无法准确定义哪个请求为您的网站带来了有机流量。这可能是由以下原因造成的:
- 一些不发送关键字信息的旧搜索系统
- 忘记在使用手动 UTM 标签的活动中设置关键字
- 来自电子邮件中链接的流量
(未提供)值通常在此报告中更常见。这意味着访问者在 HTTPS 协议的帮助下进行了搜索。根据其隐私政策,谷歌必须在这种情况下隐藏关键词信息。
谷歌广告报告
这组报告将帮助你估计你的广告在谷歌展示网络中的效率,并让你知道用户点击广告后做了什么。(未设置)值帮助您优化付费流量的费用。

图片由作者提供
Google Ads 报告中的一个(未设置的)值可能是由几个原因造成的
1.不恰当的谷歌广告和谷歌分析的整合(检查你是否在 GA 中连接了正确的视图和广告中的账户。)
2.谷歌广告中的自动标记被关闭。当访问者点击广告消息时,谷歌点击标识符(GCI)值被添加到目标 URL。它保存在该网站域名的一个新的谷歌分析 cookies 文件中。由于这一功能,我们可以在谷歌分析报告中看到谷歌广告的活动和费用数据。
如果您的网站没有自动标记功能,您可以手动标记链接。为此,打开 Google Analytics 资源首选项并选中复选框允许手动标记。

图片由作者提供
3.同时使用手动和自动标记。
4.无效点击。Google Ads 认为这些是机器人或恶意软件的点击,或者是对广告商没有任何用处的两次或三次点击。你可以在谷歌帮助中心找到更多关于无效点击以及如何处理的信息。
5.重定向。当从一个 URL 重定向到另一个 URL 时, gclid 可能会丢失。结果,你会看到(未设置)。你可以用 Chrome 开发者工具检测并修复这个问题。在谷歌分析帮助中心阅读更多信息。
6.语法和 gclid 问题,例如,如果 URL 中的寄存器发生变化,或者如果您的网站因为超过 100 个符号而删除了 gclid 参数,或者如果您的网站设置禁止处理正确处理标签所需的请求。您可以通过确保所有脚本正确运行来解决此问题。
行为报告
您可以在“网站内容-登录页面”报告中找到(未设置的)值:

图片由作者提供
此报告显示访问者从哪些页面开始他们的会话。登录页面是新访问者熟悉您的网站的页面。在这里检查跳出率。跳出率是在页面上没有采取任何行动就离开的访问者的百分比。
如果你在这个报告中没有数据,你就无法在高跳出率的基础上定义哪些页面需要改进。
如果选择主要维度“内容分组”,您还可以在“网站内容报告”组的其他报告中找到(未设置的)值。

图片由作者提供
您可以将网站内容分成逻辑组,如品牌或产品类别,以便在一份报告中比较它们的效率。很明显,如果你发现(未设置)代替了类别名,那么比较将毫无意义。
在行为报告中,如果出现以下情况,可能会出现(未设置)
1.会议在午夜或访客等待 30 分钟后结束。这 30 分钟后完成的任何操作都将被标记为新会话。如果此操作是会话中的唯一点击,则登录页面值将为(未设置)。
2.会话没有页面或屏幕视图。如果您设置了删除特定页面视图的过滤器,或者屏幕和页面跟踪设置错误,则可能会发生这种情况。查看谷歌帮助中心来解决这个问题。
3.您一次使用了两个跟踪代码(分析。js 和 gtag。js),在这种情况下,一个会话框架中的点击将不会被链接。你应该使用一个代码。谷歌分析推荐使用 gtag。js 。
4.如果(未设置)值出现在内容分组报告中,可能是由于页面标题中的
转换报告
这些报告有助于跟踪你的网站上的转换,并分析买家的行为。它们包含关于交易、产品、目标等的有用信息。
电子商务报告小组
电子商务-产品列表性能报告中的(未设置)值使得无法知道哪些产品最受欢迎,哪些列表应该移动或需要改进,以及哪些应该从该网站部分删除。

图片由作者提供
没有准确的数据,你就无法针对受众群体开展个性化的营销活动。例如,您不能在产品卡上设置折扣块,然后将那些在购买其他产品时查看折扣的访问者分隔开来,并向他们发送包含特殊优惠的电子邮件。
让我们仔细看看另一个例子。假设您在网站上发起了一项内部推广活动,创建了一个对您的活动感兴趣的细分市场,发送带有个人优惠的电子邮件。如果你打开电子商务——营销——内部推广,看到(未设置)值,这意味着你的部分受众没有定义。因此,你失去了将这些用户添加到你的细分市场并赚取更多的机会。

图片由作者提供
通常,(未设置的)值出现在电子商务报告中,因为增强型电子商务跟踪代码缺少单独参数的值:产品列表、订单优惠券、产品优惠券等。要解决这个问题,您需要正确地设置增强的电子商务,以便将必要参数的值和点击发送到 Google Analytics。
目标报告
目标-反向目标路径报告显示访问者在哪个页面上实现了他们的目标,以及在此之前他们访问的三个页面。

图片由作者提供
(未设置的)值将始终出现在此报告中,因为访问者可以在不到三步的时间内实现他们的目标。如果访问者进入网站并立即注册,第 2 步和第 3 步将(未设置),如上面截图中的字符串 2 所示。
结论
(未设置的)值可以在大多数谷歌分析报告中找到。表示系统要么没有数据,要么不识别。发生这种情况有各种原因。有些我们可以解决,有些我们不能,但我们可以在分析数据时考虑到这一点。
如果您忽略报表中的(未设置的)值,您的业务将会付出高昂的代价。谁喜欢把钱投在低效的措施上?数据损坏会导致曲解报告和不可靠的决策。
表格识别中如何识别和修复断线
原文:https://towardsdatascience.com/how-to-recognize-and-fix-broken-lines-in-table-recognition-1a19f22d59f2?source=collection_archive---------13-----------------------
使用 OpenCV / Python 修复表格的孔洞和缺失轮廓

来源:unsplash(agrêBarros)。
当文档通过扫描或照片数字化时,图像质量可能会受到错误设置或恶劣条件的影响。在表格识别的情况下,这可能导致表格结构损坏。因此,一些线条可能会有轻微的瑕疵,甚至有洞,并且桌子作为一个整体不能被认为是一个连贯的系统。有时创建的表格在单元格的某些边上没有线条。在这种情况下,系统会用上面单元格的行来关闭这些行。有各种各样的表格和单元格类型,因此建议的代码可能并不完全适用于所有情况。尽管如此,只要稍加修改,它在许多情况下都是有用的。
大多数细胞识别算法是基于线和细胞结构。由于“遗忘”的细胞,没有线导致识别率差。这种方法也是如此。台词是必须的。如果你的桌子没有清晰可辨的线条,那就没用了。但是现在,让我们来看看代码!
首先,我们需要进口。在这种情况下,它仅限于两个导入:OpenCV 和 NumPy。
import cv2
import numpy as np
然后我们需要加载包含表格的图像/文档。如果它是一个完整的文档,文本围绕着表格,你需要首先识别表格,然后将图像剪切到表格大小。(要了解更多关于表格识别和切割到表格尺寸的信息,点击此处。)
**# Load the image** image = cv2.imread(‘/Users/marius/Desktop/holes.png’, -1)

输入图像。
正如您在输入图像中看到的,第二行中的单元行没有完全连接。在表格识别中,算法不会识别和考虑第二行,因为单元格不是封闭的方框。本文提出的解决方案不仅适用于这种间隙情况。它也适用于表格中的其他折线或孔洞。
现在,我们需要获取图像的大小(高度和宽度)并将其存储在变量 hei 和 wid 中。
(hei,wid,_) = image.shape
下一步是通过高斯滤波器进行灰度和模糊处理。这有助于识别线条。关于灰度的更多信息,点击这里。
**#Grayscale and blur the image**
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
然后我们需要设定图像的阈值。如果你想了解更多关于阈值处理的知识,你可以阅读这篇文章:点击这里(一直到二值化图像)。
**#Threshold the image**
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
然后使用 OpenCV 的 findContours 算法获得所有轮廓的位置。对于所有轮廓,绘制边界矩形以创建表格的框/单元。然后,这些框与四个值 x,y,width,height 一起存储在列表框中。
**#Retrieve contours**
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)**#Create box-list**
box = []**# Get position (x,y), width and height for every contour** for c in contours:
x, y, w, h = cv2.boundingRect(c)
box.append([x,y,w,h])
然后,所有的高度、宽度、x 和 y 分别存储在列表中,并计算最小高度、宽度以及 x 和 y。此外,y 和 x 的最大值是必要的。
**#Create separate lists for all values**
heights=[]
widths=[]
xs=[]
ys=[]**#Store values in lists** for b in box:
heights.append(b[3])
widths.append(b[2])
xs.append(b[0])
ys.append(b[1])**#Retrieve minimum and maximum of lists** min_height = np.min(heights)
min_width = np.min(widths)
min_x = np.min(xs)
min_y = np.min(ys)
max_y = np.max(ys)
max_x = np.max(xs)
存储的值现在用于了解表的位置。最小 y 值可用于获取表格的最上面一行,该行可视为表格的起点。最小 x 值是表格的左边缘。为了获得大概的大小,我们需要检索最大的 y 值,也就是表格底部的单元格或行。最后一行的 y 值表示单元格的上边缘,而不是单元格的底部。要考虑单元格和表格的整体大小,需要将最后一行的单元格高度加上最大值 y,以获得表格的完整高度。最大值 x 将是表格的最后一列和最右边的单元格/行。x 值是每个单元格的左边缘,我们需要连续地将最后一列的宽度加上最大 x 值,以检索表格的整个宽度。
**#Retrieve height where y is maximum (edge at bottom, last row of table)**
for b in box:
if b[1] == max_y:
max_y_height = b[3]**#Retrieve width where x is maximum (rightmost edge, last column of table)** for b in box:
if b[0] == max_x:
max_x_width = b[2]
在下一步中,提取所有水平线和垂直线并分别存储。这是通过创建一个内核来实现的,该内核设定阈值并应用形态学操作。水平内核的大小为(50,1)。你可以根据图片的大小来调整尺寸。垂直内核的大小为(1,50)。
形态学操作根据其几何形状对检测到的结构进行变换(Soille,第 50 页,1998)。膨胀是应用最广泛、最基本的形态学操作之一。如果内核下至少有一个像素是白色的,则原始图像中正在查看的像素将被视为白色。因此,白色区域被扩大。请注意,由于反转,背景是黑色的,前景是白色的,这意味着表格线目前是白色的。扩张可以被看作是最重要的一步。孔洞和断线现在已修复,为了进一步识别表格,将考虑所有单元格。
**# Obtain horizontal lines mask** horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50,1))
horizontal_mask = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=1)
horizontal_mask = cv2.dilate(horizontal_mask, horizontal_kernel, iterations=9)**# Obtain vertical lines mask**
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,50))
vertical_mask = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=1)
vertical_mask= cv2.dilate(vertical_mask, vertical_kernel, iterations=9)


表格的水平和垂直掩码。
然后使用 OpenCV 的 bitwise_or 操作将水平和垂直两个掩码合并到一个表中。为了检索原始的背景和前景,通过从 255 中减去 cv2.bitwise_or 来反转图像。
**# Bitwise-and masks together**
result = 255 — cv2.bitwise_or(vertical_mask, horizontal_mask)

合并和反转水平和垂直遮罩。
如果表格被文本包围,而不是孤立的(在我的例子中,它没有被包围),我们把它剪下来,放在白色背景上。现在我们需要之前检索的表的大小。我们通过使用最小 y(它是顶部的边缘)、最大 y +最大 y 单元的高度(它是底部的边缘)、最小 x(它是左侧边缘)和最大 x +最大 x 单元的宽度(它是右侧边缘)将最终图像切割成表格大小。然后,图像被裁剪为表格的大小。创建文档原始大小的新背景,并用白色像素完全填充。检索图像的中心,修复后的表格与白色背景合并,并设置在图像的中心。
**#Cropping the image to the table size**
crop_img = result[(min_y+5):(max_y+max_y_height), (min_x):(max_x+max_x_width+5)]**#Creating a new image and filling it with white background** img_white = np.zeros((hei, wid), np.uint8)
img_white[:, 0:wid] = (255)**#Retrieve the coordinates of the center of the image**
x_offset = int((wid — crop_img.shape[1])/2)
y_offset = int((hei — crop_img.shape[0])/2)**#Placing the cropped and repaired table into the white background**
img_white[ y_offset:y_offset+crop_img.shape[0], x_offset:x_offset+crop_img.shape[1]] = crop_img**#Viewing the result**
cv2.imshow(‘Result’, img_white)
cv2.waitKey()

修复了虚线的结果图像。
这就是结果。该方法可用于表格中多种类型的折线、间隙和孔洞。这个结果是进一步表格识别的基础,在我的另一篇文章中有解释。所解释的方法应用于一个空表。您也可以将它应用于包含文本或被文本包围的表格。对于包含文本的表格,仍然需要将包含具有数据的表格的原始图像与具有修复的孔洞的最终图像合并。这可以通过 OpenCV 位运算来完成,并且不会太复杂。
我希望你喜欢我的教程,并能将其用于你自己的项目。
想看更多这样的故事?
上手
如何招(和留!代表不足群体的个人
原文:https://towardsdatascience.com/how-to-recruit-and-keep-members-of-under-represented-groups-on-your-team-d0df50bae431?source=collection_archive---------29-----------------------
十七(..和计数..)提高公司多样性的策略
这份名单是与朋友、同事和其他社交媒体关系合作创建的。有些观点特别关注招募女性的方式,因为这是我最了解和理解的,但我相信这也是从其他代表性不足的群体中引入个人的有用方式。
- 看看你的招聘启事中的语言。寻找不经意的性别术语,并利用在线资源进行筛选。
- 将“需求”改为“首选技能”——除非它们是真正的需求。urg 成员倾向于只申请那些拥有大部分所需技能的职位,而白人 cis 性别的男性更愿意申请那些只有少量要求的职位。
- 针对代表性不足的人口统计向职务公告板发布。这不仅会给你带来更多来自这些群体的申请人,还会向你的申请人表明你对多样性的重视。(作为一名白人女性数据科学家,我熟悉编写代码的女性和女性以及机器学习和数据科学,但还有更多,谷歌搜索会帮助你找到适合你职位的发布位置)
- 在您的办公室为[在此插入字段]的女性举办一次活动。看看你是否能在你的领域找到一个有兴趣在活动中发言的摇滚女明星,即使她不在你的公司工作。这同样适用于在你的领域招聘黑人,LGBTQIA 等。依我看,最好是单独举办针对特定群体的活动,而不是为几个代表性不足的群体举办一次联合活动,以专注于特定的事情。(我当然愿意接受其他观点!)
- 如果你喜欢用内部引荐,那就找你所在领域的女性朋友引荐。他们可能认识很多有才华的女性。(同样,这也适用于其他人口统计)。
- 不要让它看起来像一件坏事,你需要“走出你的方式”来招募那些不像你的团队已经有的人。这是一个问题,解决它的唯一方法是走出自己的路。
- 给新员工真正的机会,让他们在你的公司茁壮成长,展示他们的技能。
- 表扬好的工作。对需要改进的地方给予一致和建设性的反馈。
- 为所有候选人设立一个多元化的面试小组。这有助于你筛选候选人中有问题的态度或偏见,告诉你的员工他们的意见是有效的,并给候选人一个更平等的机会。
- 聘用一名多元化、公平和包容(DEI)主管。
- 设定明确的多元化目标。追踪你在这些方面的进展,注意哪些策略对实现你的目标最有效。
- 向推荐来自代表性不足的背景的候选人的员工提供奖金。
- 进行无意识偏见训练。
- 在你的公司建立员工资源组(亲和组)。
- 使推广标准不分性别。关注你需要从个人身上得到的结果,而不是你在这些方面描述候选人的方式。
- 浏览你发送给候选人、新员工和雇员的所有信息,寻找性别代词(例如,“他将具备以下技能…”)
- 对于每个职位,至少面试两个来自代表名额不足的候选人,以防止一个候选人相对于一群同质的候选人来说看起来像局外人。
我作为 STEM 女性的就业背景
通过自由职业和全职工作,我在很多团队工作过。大多数时候,团队成员都是异性恋、独联体性别的白人或亚裔男性。有几次,我是队里唯一的女性。在一家公司工作的 9 年里,我是第一个加入 7 人团队的女性。(在我的第一天,有人评论说我是“试验品”,以决定团队是否有能力让一名女性加入。)
三年前,我为自己制定了一个规则。我不会参加所有白人或亚裔男性面试小组的面试。当招聘人员给我安排了一次面试时,我礼貌地要求他们在面试者名单中特别添加一名女性或非二元个体。
这一要求对招聘人员产生了两极分化的影响。我已经让招聘人员感谢我提出这个要求,并把令人印象深刻的女性列入我的面试名单。
我的要求也激怒了招聘人员。我被告知这个要求是不可能满足的。有人告诉我,我不愿意加入一个全是男性的大型团队,这是他们的团队中没有女性的原因,我是真正的问题所在。
在 Instagram 上吸引我的朋友
几天前,我和一位招聘人员进行了一次特别糟糕的交流,我在 Instagram stories 上发泄了一下。让我特别沮丧的是,有一种观点认为面试名单缺乏多样性的原因是“管道问题”,是雇主无法控制的。我的机械工程专业毕业班女生比男生多。我不知道他们还需要这条管道走多远。
在发泄情绪的过程中,我遇到了意想不到的转机。我收到了很多人真诚的请求,询问如何让他们的申请人多样化。我开始张贴我对我的故事的回答,然后张贴别人发给我的想法。我从一个女性的角度写了一些吸引女性的方法,然而,我认为这些是吸引来自任何代表不足群体(URG)的候选人的有用技巧:

我的 insta rant
(9b 的荣誉归于凯西·韦塞尔。10-15 的荣誉属于兰登·迪基。)
朋友的反馈
一个朋友要求澄清什么会被认为是“不经意的性别术语”我很难准确定义这些是什么,但我认为任何暗示“兄弟”文化的东西,无论是说所有员工都是“摇滚明星忍者”,还是要求候选人喜欢“努力工作,努力聚会”。
我众包了一些更好的方法来描述无意中性别化的术语, Maddie Mirzoeff 向我推荐了这篇文章。她还在列表中添加了下面的第一个要点。
这些截图之后,我收到的一些建议包括:
- 使推广标准不分性别。为了做到这一点,你必须确保你描述的是结果而不是个人。所以不要说“有高管风度”,而要说“能够主持会议,并得出结果。”
- 通过软件发布招聘信息,这些软件会检查有问题的措辞,比如 Textio ( 劳伦·毕晓普)
- 浏览你所有的表格回答中的性别代词,确保不要用“他将具备这些技能”来描述一个好的候选人
- 面试至少两个 urg 的候选人,而不是一个。这篇文章解释了为什么会显著增加 URGs 的候选人获得该角色的公平机会。
后续步骤:
我希望继续补充这个列表。我也希望通过分享我的白人男性朋友的问题来帮助我制定这个列表,那些不是 URGs 成员的人会觉得加入对话和提问很舒服。我对其他人的想法很感兴趣,他们可以创建一个名单,任何人都可以添加到名单中,同时也给人们的贡献带来荣誉。
成功地包容未被充分代表的群体,尤其是处于这些群体交汇点的个人,将需要一些创造力来颠覆现状。确定可操作的清晰的后续步骤并不容易。但我相信 STEM 领域的专业人士能够应对这一挑战。
如何使用 tf.data 减少深度学习模型的训练时间
原文:https://towardsdatascience.com/how-to-reduce-training-time-for-a-deep-learning-model-using-tf-data-43e1989d2961?source=collection_archive---------8-----------------------
学习为图像创建输入管道,以高效地使用 CPU 和 GPU 资源来处理图像数据集,并减少深度学习模型的训练时间。
在这篇文章中,你将学到
- 在模型训练中,CPU 和 GPU 资源是如何以一种天真的方式使用的?
- 如何高效利用 CPU 和 GPU 资源进行数据预处理和训练?
- 为什么要用 tf.data 构建高效的输入管道?
- 如何使用 tf.data 为图像建立高效的输入数据管道?
一个朴素的方法如何为输入数据管道和模型训练工作?
在创建输入数据管道时,我们通常执行 ETL(提取、转换和加载)过程。

- 提取、从不同的数据源提取数据,如本地数据源、可以从硬盘或远程数据源提取数据,如云存储。
- 转换,你将洗牌数据,创建批次,应用矢量化或图像放大。
- 加载数据包括清理数据并将其塑造成一种我们可以传递给深度学习模型进行训练的格式。
数据的预处理发生在 CPU 上,模型通常在 GPU/TPU 上训练。
在简单的模型训练方法中, CPU 预处理数据,为模型训练做好准备,而 GPU/TPU 处于空闲状态。当 GPU/TPU 开始训练模型时,CPU 是空闲的。这不是管理资源的有效方式,如下所示。

原始数据预处理和训练方法
有哪些方法可以加快培训过程?
为了加快训练,我们需要优化数据提取、数据转换和数据加载过程,所有这些都发生在 CPU 上。
数据提取:优化从数据源读取的数据
数据转换:并行化数据扩充
数据加载:在训练前一步预取数据
这些技术将有效地利用 CPU 和 GPU/TPU 资源进行数据预处理和训练。
怎样才能实现输入管道的优化?
优化数据提取
通过同时处理多个文件来优化数据提取。 tf.data.interleave()通过交错读取文件的 I/O 操作和应用数据预处理的 map()优化数据提取过程。

来源:https://www . tensor flow . org/guide/data _ performance # parallelising _ data _ extraction
要重叠的数据集数量由 cycle_length 参数指定,而并行度由num _ parallel _ calls参数设置。您可以使用 AUTOTUNE 来决定要实现的并行级别。
num _ parallel _ calls产生多个线程,利用机器上的多个内核,通过使用多个 CPU 来并行化数据提取过程。
如何知道要用多少个 CPU 或核心?
您可以找到机器上的内核数量并指定,但更好的选择是使用tf.data . experimental . auto tune .将并行级别委托给 TF . data
- 自动调优将要求 tf.data 在运行时动态调优该值。
- tf.data 将在所有可调操作中找到正确的 CPU 预算。
- 自动调优决定缓冲区大小、CPU 预算以及 I/O 操作的并行级别。
并行数据转换
图像增强是预处理的一部分,发生在 CPU 上。图像的每一次放大、归一化、重新缩放都是一种代价高昂的操作,并且会减慢训练过程。
如果你能通过并行处理利用所有内核来运行所有这些图像操作。
tf.data.map() 可以采用用户定义的函数,该函数包含您想要应用于数据集的所有图像增强。
tf.data.map()有一个参数 num_parallel_calls 来产生多个线程,以利用机器上的多个内核来使用多个 CPU 并行化预处理。
缓存数据
cache() 允许将数据缓存在指定文件或内存中。
- 在内存中缓存时,第一次迭代数据时,将缓存数据,所有后续迭代,将从缓存中读取数据。
- 当缓存一个文件时,即使是第一次迭代数据也会从缓存的文件中读取。
- 缓存为每次迭代产生相同的元素,在缓存数据后,使用 shuffle()随机化迭代中的元素。
通过重叠数据处理和训练来预取数据
TF . data 中的预取功能重叠了数据预处理和模型训练。数据预处理比训练提前一步运行,如下所示,这减少了模型的总训练时间。

来源:https://www . tensor flow . org/guide/data _ performance #预取
要预取的元素数量应该等于或大于用于单个训练步骤的批量大小。我们可以使用 AUTOTUNE 来提示 tf.data 在运行时动态分配缓冲区大小值。
所有的操作:映射,预取,交错,批量,重复,混洗,和缓存都是 tf.data 的一部分,可以让你构建
- 通过使用计算资源、GPU、CPU 和 TPU,更快、更高效地建立数据管道,高效地从数据源获取数据。
- 灵活处理不同的数据格式,如文本数据、图像和包含数字和分类数据的结构化数据。
- 通过应用数据扩充、混排数据集和创建用于训练的批量数据,轻松构建复杂的输入数据管道
如何使用 tf.data 为自定义影像数据集构建数据管道?
在本节中,您将为来自 Kaggle 的流行的 C ats 和 Fogs 数据集构建一个数据输入管道。
这里我们将使用 MobileNetV2 和 TensorFlow 2.3 进行迁移学习
导入所需的库
**import tensorflow as tf
config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.compat.v1.Session(config=config)
import numpy as np
import pandas as pd
import pathlib
import os
from os import getcwd
import pandas as pd
from glob import glob
import multiprocessing
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input**
为数据集设置 train 和 val 目录
**train_dir=r'\dogs-vs-cats\train_data'
val_dir=r'\dogs-vs-cats\validation_data'**
将文件转换为数据集对象
使用TF . data . dataset . list _ files()根据匹配的 glob 模式返回文件名。这里我们希望所有的文件都来自 train_dir 和 val_dir 文件夹下的子文件夹,所以我们指定了“*\*”
**train_files = tf.data.Dataset.list_files(str(train_dir + '\\*\\*'), shuffle=False)**
**val_files = tf.data.Dataset.list_files(str(val_dir + '\\*\\*'), shuffle=False)**#getting the number of files in train and val dataset
**train_num_files=len([file for file in glob(str(train_dir + '\\*\\*'))])
val_num_files=len([file for file in glob(str(val_dir + '\\*\\*'))])** print("No. of files in Train folder: ",train_num_files)
print("No. of files in Val folder: ",val_num_files)

预处理训练和验证数据集
设置参数
epoch=10
batch_size = 32
img_height = 224
img_width = 224
应用 MobileNet 的预处理技术
**#Get class names from the folders
class_names = np.array(sorted([dir1 for dir1 in os.listdir(train_dir)]))
class_names**#To process the label
**def get_label(file_path):**
# convert the path to a list of path components separated by sep
** parts = tf.strings.split(file_path, os.path.sep)**
# The second to last is the class-directory
**one_hot = parts[-2] == class_names**
# Integer encode the label
**return tf.argmax(tf.cast(one_hot, tf.int32))**# To process the image
**def decode_img(img):**
# convert the compressed string to a 3D uint8 tensor
** img = tf.image.decode_jpeg(img, channels=3)**
# resize the image to the desired size
**return tf.image.resize(img, [img_height, img_width])****def process_TL(file_path):
label = get_label(file_path)**
# load the raw data from the file as a string
**img = tf.io.read_file(file_path)
img = decode_img(img)
img = preprocess_input(img)
return img, label**
通过交错优化数据提取和数据转换过程
Interleave() 将通过交错读取文件的 I/O 操作和 map() 将数据预处理应用到数据集的内容来并行化数据加载步骤。
#Interleaving the train dataset to read the file and apply preprocessing **train_dataset = train_files.interleave(lambda x: tf.data.Dataset.list_files(str(train_dir + '\\*\\*'), shuffle=True), cycle_length=4).map(process_TL, num_parallel_calls=tf.data.experimental.AUTOTUNE)**#Interleaving the val dataset to read the file and apply preprocessing **val_dataset = val_files.interleave(lambda x: tf.data.Dataset.list_files(str(val_dir + '\\*\\*'), shuffle=True), cycle_length=4).map(process_TL, num_parallel_calls=tf.data.experimental.AUTOTUNE)**
要重叠的数据集数量设置为 4,这由 cycle_length 参数指定。并行级别由 num_parallel_calls、 指定,后者设置为 AUTOTUNE
加载数据集进行训练
在内存中缓存数据集
##Cache the dataset in-memory
**train_dataset = train_dataset.cache()
val_dataset = val_dataset.cache()****train_dataset = train_dataset.repeat().shuffle(buffer_size=512 ).batch(batch_size)
val_dataset = val_dataset.batch(batch_size)**
TF . data . dataset 类的 repeat() 方法用于重复数据集中的张量。
shuffle () 使用大小为 512 的缓冲区对 train_dataset 进行混洗,以便挑选随机条目。
batch() 将根据设置的批量大小获取前 32 个条目,并从中进行批量处理
**train_dataset = train_dataset.repeat().shuffle(buffer_size=512 ).batch(batch_size)****val_dataset = val_dataset.batch(batch_size)**
TF . data 中的预取功能重叠了数据预处理和模型训练
**train_dataset =train_dataset.prefetch(tf.data.experimental.AUTOTUNE )
val_dataset =val_dataset.prefetch(tf.data.experimental.AUTOTUNE )**
创建用于垂直和水平翻转图像、旋转图像、缩放和应用对比度的数据增强。
**data_augmentation = tf.keras.Sequential([ tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal'), tf.keras.layers.experimental.preprocessing.RandomFlip('vertical'), tf.keras.layers.experimental.preprocessing.RandomRotation(0.45), tf.keras.layers.experimental.preprocessing.RandomContrast(0.2), tf.keras.layers.experimental.preprocessing.RandomZoom(0.1),])**
通过首先应用数据扩充来创建迁移学习模型
**def create_model():
input_layer = tf.keras.layers.Input(shape=(224, 224, 3))
x= data_augmentation(input_layer)
base_model = tf.keras.applications.MobileNetV2(input_tensor=x, weights='imagenet',include_top=False)
base_model.trainable = False
x = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)
x = tf.keras.layers.Dense(2, activation='softmax')(x)
model = tf.keras.models.Model(inputs=input_layer, outputs=x)
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model****model= create_model()**
创建检查点阈值,训练将继续,直到我们获得 99.96%的验证准确率,或者直到完成指定数量的时期。
**class MyThresholdCallback(tf.keras.callbacks.Callback):
def __init__(self, threshold):
super(MyThresholdCallback, self).__init__()
self.threshold = threshold****def on_epoch_end(self, epoch, logs=None):
val_acc = logs["val_accuracy"]
if val_acc >= self.threshold:
self.model.stop_training = True****my_callback = MyThresholdCallback(threshold=0.9996)**
将训练数据集拟合到模型中
**import time
start_time= time.perf_counter()
history_tfdata =model.fit(train_dataset,
steps_per_epoch=int((train_num_files)/batch_size),
validation_data= val_dataset,
validation_steps=int(val_num_files/batch_size),
callbacks=[my_callback],
epochs=epoch)****print(time.perf_counter()-start_time)**
如果我们使用如下所示的 ImageDataGenerator 训练数据集,我们可以比较训练时间的差异。
**from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img, array_to_img
from tensorflow.keras.models import load_model
from tensorflow.keras import optimizers, callbacks**#Creating Image Train DataGenerator
**image_gen_train = ImageDataGenerator(rescale=1./255,
zoom_range=0.1,
rotation_range=45,
shear_range=0.1,
horizontal_flip=True,
vertical_flip=True)
train_data_gen = image_gen_train.flow_from_directory(batch_size=batch_size, directory=train_dir,
shuffle=True, target_size=(224,224), class_mode='sparse')**# Val data generator
**image_gen_val = ImageDataGenerator(rescale=1./255)
val_data_gen = image_gen_val.flow_from_directory(batch_size=batch_size,directory=val_dir, target_size=(224,224),class_mode='sparse')****def create_model():
input_layer = tf.keras.layers.Input(shape=(224, 224, 3))
input_layer=preprocess_input(input_layer)
base_model = tf.keras.applications.MobileNetV2(input_tensor=input_layer,
weights='imagenet',
include_top=False)
base_model.trainable = False
x = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)
x = tf.keras.layers.Dense(2, activation='softmax')(x)
model = tf.keras.models.Model(inputs=input_layer, outputs=x)
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model****model_idg=create_model()****start_time2= time.perf_counter()
history = model_idg.fit(
train_data_gen,
steps_per_epoch=len(train_data_gen),
epochs=10,
callbacks=[tboard_callback],
validation_data=val_data_gen,
validation_steps=len(val_data_gen)
)
print(time.perf_counter()-start_time2)**
将使用 tf.data 输入管道完成训练的时间与使用 ImageDataGenerator 完成训练的时间进行比较

您可以看到使用 tf.data 完成训练的时间是 290.53 秒,而使用 ImageDataGenerator 完成相同数据的训练是 2594.89 秒,这在训练时间方面是一个很大的进步
代码可用此处
结论:
tf.data 允许您通过高效地使用 GPU、CPU 和 TPU 等计算资源,为不同的数据格式构建高效的输入数据管道,从而减少训练时间。
参考资料:
[## tf.data:构建 TensorFlow 输入管道| TensorFlow 核心
创建数据集有两种不同的方法:将 TensorFlow 作为 tf 导入 pathlib 导入 os 导入…
www.tensorflow.org](https://www.tensorflow.org/guide/data) [## 使用 tf.data API | TensorFlow 核心提高性能
GPU 和 TPU 可以从根本上减少执行单个训练步骤所需的时间。实现最佳性能…
www.tensorflow.org](https://www.tensorflow.org/guide/data_performance)
https://github . com/tensor flow/docs/blob/master/site/en/guide/data . ipynb
如何重构 Jupyter 笔记本
原文:https://towardsdatascience.com/how-to-refactor-a-jupyter-notebook-ed531b6a17?source=collection_archive---------31-----------------------
现实世界中的 DS
使用这些技术改进您的代码库并变得更加高效

(TL;DR——这张图片总结了整篇文章)
在 ML 世界中,代码会很快变得混乱。
最初令人惊叹的 ML 模型很容易变成一大堆难以理解的代码。修改代码变得痛苦且容易出错,对于 ML 从业者来说,发展他们的 ML 解决方案以满足新的{业务需求、特征工程策略、数据}变得越来越困难。
在这篇文章中,我将与你分享我重构 Jupyter 笔记本的过程,并向你展示我是如何将它从不可维护的状态提升到{可读、测试、可维护}的状态。一旦我们的代码库经过全面测试并且容易理解,扩展和发展我们的 ML 解决方案就容易多了。
注意:如果你不确信需要重构你的 Jupyter 笔记本,看看这篇文章👻
1.支持重构的六个准备步骤
重构是改变代码,使其更容易理解和修改,而不改变其可观察到的行为。(转述自重构 —马丁·福勒)
代码并不总是可重构的。
很长一段时间以来,我一直盯着我的 Jupyter 笔记本,思考如何让它变得更好。我知道我应该写测试和重构我的代码。但是有一些阻碍我迈出第一步的障碍:(1)担心我可能会破坏一些东西,(2)担心我可能会删除其他人需要的代码,(Jupyter 笔记本中繁琐的重构机制(例如,尝试重命名变量)。
在运行了两次重构研讨会之后,我发现了六个启动和加速重构的准备步骤:
- 从头到尾运行笔记本,确保一切正常。
- 这将为您省去不必要的麻烦,即必须弄清楚我们是否在重构时破坏了某些东西,或者代码是否已经被破坏了。
2.制作原始笔记本的副本。
- 这是令人惊讶的重要一步。它将把我们从任何情感依恋中解放出来(“嗯,我不知道,有人可能需要这个图表”),并允许我们无情地清理任何不必要的代码。
- 通过分离这些关注点(即,核心数据转换和表示),我们可以有两个独立的东西来很好地处理每个关注点,而不是一个巨大的笔记本同时以灾难性的方式处理这两个问题。
3.将 Jupyter notebook 转换成普通的 Python 文件。
- 这将使您获得使用 IDE 的所有好处(例如,自动完成、智能感知、内联文档、格式化、自动重命名、林挺、键盘快捷键等)。这让你在重构中更有效率。
- 命令:
jupyter nbconvert —-to script mynotebook.ipynb
4.删除打印报表,如print(...)、df.head()、df.plot(...)
- 这消除了噪音和视觉混乱,使下一步变得更加容易。
5.看笔记本,列出代码气味。
- 您识别的代码气味列表成为您重构中的待办事项列表(参见示例)。这也将为您节省一些精神资源,避免您不断思考下一步要重构什么。
6.定义重构边界,并添加一个特征测试。
- 一个特征测试将你的程序视为一个黑盒,而描述它的行为(例如,我的笔记本输出一个准确率为 68%的模型)并断言该特征(例如,如果我们运行我们的代码,得到一个准确率低于 68%的模型,测试失败)
- 这可以说是👏这👏最👏重要的👏迈步!
- 进行特征测试会给你快速的反馈,因为它可以在你重构的时候持续运行。如果你不小心引入了突破性的变化,它会在几秒钟内告诉你。
- 如果没有特性测试,你将不得不经常手动重启和重新运行整个 Jupyter 笔记本——这很麻烦,对你的流程有很大的破坏性,所以 2019 年。
- 这一步有点难以用文字来解释,所以我录制了这个演示来告诉你如何定义重构边界并编写一个特性测试来支持你的重构。
2.重构周期(耶!)

在重构循环中,我们通过(I)添加单元测试和(ii)将复杂的实现细节抽象成模块化和可读的函数,增量地和迭代地改进我们的代码。
重构周期如下:
1.确定可以提取到纯函数中的代码块(例如,无论何时何地运行,对于给定的输入都返回完全相同的输出的函数)。
2.编写一个单元测试。(参见演示)
- 在观察模式下运行单元测试:例如
nosetests -—with-watch —-rednose - 为代码块编写单元测试
3.让测试通过。
- 定义一个新函数,并将其放在一个新的 Python 模块/文件中(或者一个现有的模块/文件,如果您的代码中有合适的模块/文件的话)
- 将现有实现从笔记本移到该功能中
- 让失败的测试通过
4.在笔记本中,用新定义的函数替换原来的代码块。
5.确保特性测试仍然通过。
6.将您的更改提交给 git。
现在,如果你觉得你刚刚提取的代码还可以再改进一些,你可以用你的新单元测试的安全网进一步重构它。
否则,您可以在 Jupyter 笔记本中的另一个代码块上重复重构周期,并重复直到代码库被全面测试并重构为可读和可维护的状态。
3.我们费了那么大劲得到了什么?
简而言之,你可以从一个凌乱难读的笔记本变成一个经过测试的模块化代码库。🎉🎉🎉
自动化测试和重构的结合可以极大地帮助我们:
- 缩短反馈周期。有了自动化测试,您现在可以立即知道错误和缺陷是如何引入的。如果测试覆盖面是全面的,它还会给你信心,让你知道一切都准备好了,并且节省你手动测试整个 Jupyter 笔记本的时间。
- 减少浪费。通过测试和模块化功能,您可以减少花费在以下方面的精力:(I)阅读与您的任务无关的实现细节,(ii)即使我们只想更改一个简单的东西,也要记住整个 Jupyter 笔记本,(iii)修复我们昨天不小心引入的错误,以及(iv)[插入让您连续几个小时盯着笔记本看的东西]。
- 增加流量。所有这些意味着您可以专注于手头的任务(例如,集成一组新功能)并交付价值,而不是上面提到的乏味、浪费的任务😎
谢谢你读到这里!我希望这对你有所帮助🚀🚀🚀
要查看我如何重构 Jupyter 笔记本的实际例子,请查看这个演示!
这是数据科学家的 编程习惯 系列教程的一部分,旨在帮助数据科学家通过学习良好的编程习惯变得更有生产力。
为您的 SQL 数据库构建回归测试框架
原文:https://towardsdatascience.com/how-to-regression-test-your-sql-database-c6c8d66848c5?source=collection_archive---------12-----------------------
了解如何使用 Python 构建 SQL 回归框架

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片
当谈到测试软件时,有无数种方法可以做。回归测试就是其中的一种方法,它本质上是一种比较软件的两个不同版本的输出的方法。
比较软件的两个版本的输出将很快突出相同点和不同点。如果软件中的一个变化导致了一个意想不到的不同,它会立即被突出显示。这同样适用于预期有差异但没有发现的情况。
随着解决方案规模的增长,以及它们的输出在数量和复杂性上的增加,必须建立一个框架来允许这种类型的测试快速、轻松地执行。手动测试容易出错且耗时。
这个想法

由活动创作者在 Unsplash 上拍摄的照片
这个想法非常简单。构建一个 python 脚本,允许我们快速有效地比较两个 SQL 数据库。该脚本需要尽可能可扩展和可配置。
更具体地说,该脚本应该允许多环境设置和多数据集比较。换句话说,用户应该能够设置不同的环境和要执行的 SQL 命令,然后通过几个配置更改就可以运行它。
事不宜迟,让我们进入细节。
魔力
连接到 SQL Server
连接到 SQL server 很简单,但是根据 SQL server 的类型,您需要使用不同的库。对于这个例子,我使用的是 Microsoft SQL server,因此使用的是 pyodbc 库。
import pyodbc
import pandas as pd
Env1 = pyodbc.connect('Driver = {SQL Server}; Server = ServerName; Database = DatabaseName; Trusted_Connection = yes;')
SQL = 'SELECT * FROM Table1'
print(pd.read_sql_query(SQL, con = Env1)
比较两个数据帧
这里没有必要重新发明轮子;我们将使用现有的库来比较数据集。
import datacompy
import pandas as pd
df1 = pd.read_csv('FL_insurance_sample.csv')
df2 = pd.read_csv('FL_insurance_sample - Copy.csv')
compare = datacompy.Compare(
df1,
df2,
join_columns='policyID', #You can also specify a list of columns eg ['policyID','statecode']
abs_tol=0, #Optional, defaults to 0
rel_tol=0, #Optional, defaults to 0
df1_name='Original', #Optional, defaults to 'df1'
df2_name='New' #Optional, defaults to 'df2'
)
print(compare.report())
有趣的是
这个练习有趣的部分是把所有的东西放在一起。本质上,我们需要创建一个要执行的 SQL 语句列表,以及用于比较的结果的相关数据键。
一旦定义好,我们就可以遍历 SQL 语句列表,在我们的两个环境中执行每个语句。一旦我们得到结果,使用我们的比较库,我们可以评估是否有任何差异。为了提高效率和减少返回的数据,我们将在尝试获得更细粒度的反馈之前,首先进行“哑”的同类比较。
代码
import pyodbc, datacompy
import pandas as pd###############Set up your Environment connections#########################
Env1 = pyodbc.connect('Driver = {SQL Server}; Server = ServerName; Database = DatabaseName; Trusted_Connection = yes;')
Env2 = pyodbc.connect('Driver = {SQL Server}; Server = ServerName2; Database = DatabaseName2; Trusted_Connection = yes;')########Environment Set Up###################################
Original = Env1
Target = Env2######SQL Statements to Execute#############################
SQLStatement = [
#[ReportName, Stored Proc, [data keys]]
['Report1','EXEC StoredProc1 [@Var1](http://twitter.com/Var1) = "Woop" , [@Var2](http://twitter.com/Var2) = "Woop2"', ['Key1', 'Key2']],
['Report2','EXEC StoredProc2 [@Var1](http://twitter.com/Var1) = "Woop", [@Var2](http://twitter.com/Var2) = "Woop2"', ['Key3','Key4']]
]###############################
def compareResults(reportName, df1, df2, joinOnKeys):
if df1.equals(df2) == True:
print('###########################################################')
print(reportName, 'Success')
else:
print('###########################################################')
print(reportName, 'Fail')
compare = datacompy.Compare(
df1,
df2,
join_columns= joinOnKeys,
abs_tol = 0,
rel_tol = 0,
df1_name= 'Original',
df2_name= 'Target'
)
print(compare.report(sample_count=20))for i in SQLStatement:
results1 = pd.read_sql_query(i[1], con = Original)
results2 = pd.read_sql_query(i[1], con = Target)
compareResults(i[0], results1, results2, i[2])
示例输出
###########################################################
Report1 Success###########################################################
Report2 FailDataComPy Comparison
--------------------
DataFrame Summary
-----------------
DataFrame Columns Rows
0 Original 18 36634
1 New 18 36634Column Summary--------------
Number of columns in common: 18
Number of columns in Original but not in New: 0
Number of columns in New but not in Original: 0Row Summary
-----------
Matched on: policyid
Any duplicates on match values: No
Absolute Tolerance: 0
Relative Tolerance: 0
Number of rows in common: 36,634
Number of rows in Original but not in New: 0
Number of rows in New but not in Original: 0
Number of rows with some compared columns unequal: 2
Number of rows with all compared columns equal: 36,632Column Comparison
-----------------
Number of columns compared with some values unequal: 2
Number of columns compared with all values equal: 16
Total number of values which compare unequal: 2Columns with Unequal Values or Types
------------------------------------
Column Original dtype New dtype # Unequal Max Diff # Null Diff
0 eq_site_limit float64 float64 1 190601.40 0
1 hu_site_limit float64 float64 1 79375.76 0Sample Rows with Unequal Values
-------------------------------
policyid eq_site_limit (Original) eq_site_limit (New)
2 206893 190724.4 123.0
policyid hu_site_limit (Original) hu_site_limit (New)
3 333743 79520.76 145.0
结论
好了,伙计们!用不到 50 行代码,您就有了一个完整的 SQL 回归测试框架来帮助您确定下一个候选版本的有效性。
您所需要做的就是选择正确的两个环境,并定义您想要执行的存储过程的列表。
你会用不同的方式做事情吗,或者对改进这段代码有什么建议吗?让我知道!
如果你觉得这篇博客有用,你可能也会喜欢:
[## 构建用于比较数据的 Python UI
如何快速让您的非技术团队能够比较数据
towardsdatascience.com](/building-a-python-ui-for-comparing-data-13c10693d9e4) [## 用 Python 中的 PyAutoGUI 实现自动化 UI 测试
回归测试你的用户界面的一个快速简单的方法
towardsdatascience.com](/automate-ui-testing-with-pyautogui-in-python-4a3762121973) [## 从 Excel 和 Pandas 数据框架到 SQL
如何使用您的 SQL 知识来利用 Python 的熊猫
medium.com](https://medium.com/financeexplained/from-excel-and-pandas-dataframes-to-sql-f6e9c6b4a36a)
如何删除拥有内容的 Tableau 服务器用户
原文:https://towardsdatascience.com/how-to-remove-tableau-server-users-who-own-content-bb84fbd6948d?source=collection_archive---------52-----------------------
TABLEAU REST API: TABLEAU-API-LIB 教程
使用 Python 和 REST API 彻底删除内容所有者

通过几个 REST API 调用彻底打破这种局面(由 Unsplash 上的 Kelly Sikkema 拍摄)
这个在我们的 YouTube 频道(Devyx)也有报道: 看看 。
分手很难。Tableau 用户来来去去,幸运的是,我们手边有一些工具,可以帮助我们彻底摆脱处理孤立内容时令人不快的细微差别。
本文探索了一种使删除 Tableau 服务器用户变得轻松的方法。无论您的团队是手动添加和删除用户,还是采用一点自动化,本教程中涵盖的主题都有助于简化这一过程,确保被删除的用户不再拥有服务器上的任何内容,防止用户进入“未经许可”的墓地,并确保服务器上的内容不属于未经许可的用户。
本教程介绍了如何使用 Python tableau-api-lib 包,并且是如何像使用小桶一样使用 tableau 服务器的系列教程的一部分,让您能够控制 Tableau 服务器的 REST API。
这些教程假设您已经安装了 Python 3。如果你还没有 Python 3,这将帮助你入门:安装 Python 的指南。
搭建舞台
当你删除一个不拥有任何内容的 Tableau 用户时,这是小菜一碟。不会弹出任何错误,您所看到的只是一条愉快的确认消息,表明用户已被成功删除。
但是,如果您尝试删除拥有内容的 Tableau 用户,您将收到一条错误消息,通知您不能删除该用户,因为他们在服务器上被列为内容的所有者。
当我们试图删除拥有内容的用户时,该用户反而变成了某种 Tableau 僵尸,被放逐到“未经许可”的用户角色,但仍然拥有其内容的所有权。Tableau 不会让任何内容成为孤儿,因此所有者的精神会在 Tableau 服务器上徘徊,直到其未完成的业务(内容所有权)得到处理,用户可以完全移除。
构建解决方案
那么我们能做些什么呢?在本教程中,我们将演示如何使用 REST API 来完成以下任务:
- 确定被删除的用户是否拥有任何内容
- 如果用户拥有内容,请指定另一个用户作为新的所有者
- 删除用户
让我们也强调一下用户在 Tableau 服务器中可以拥有哪些对象:
- 工作簿
- 数据源
- 流
- 项目
目前,Tableau Server REST API 不支持更改项目所有者。如果您的用户拥有一个项目,您将需要在删除用户之前手动更改该项目的所有权(对不起,请不要杀死 messenger)。
如果你像我一样,希望能够使用 REST API 来改变项目所有者,请出去在 Tableau 论坛上投票支持这个想法。
步骤 1:确保你已经安装了 tableau-api-lib
即使你是这些教程的专家,帮自己一个忙,下载最新版本的库。
pip install --upgrade tableau-api-lib
不熟悉 Python 这个东西?别担心,你会很快明白的。跟随这个入门教程。该教程将引导您使用 tableau-api-lib 连接到 Tableau 服务器。
步骤 2:进入 Tableau 服务器环境
使用下面的代码作为连接到您的服务器的模板。在接下来的步骤中,我们将使用一次性代码行来构建这个 boiler 板。在本文的最后,您会发现一个合并的代码块,为了方便起见,您可以复制/粘贴它。
from tableau_api_lib import TableauServerConnection
from tableau_api_lib.utils.querying import queryingtableau_server_config = {
'my_env': {
'server': '[https://YourTableauServer.com'](https://tableaupoc.interworks.com%27/),
'api_version': '<YOUR_API_VERSION>',
'username': '<YOUR_USERNAME>',
'password': '<YOUR_PASSWORD>',
'site_name': '<YOUR_SITE_NAME>',
'site_url': '<YOUR_SITE_CONTENT_URL>'
}
}conn = TableauServerConnection(tableau_server_config, env='my_env')
conn.sign_in()
有趣的事实:你也可以使用个人访问令牌,假设你在 Tableau Server 2019.4 或更新版本上。如果你对访问令牌很感兴趣,请查看我的文章了解如何使用它们的细节。
步骤 3:建立服务器上所有内容所有者的列表
这个难题的第一部分是为我们自己建立一个服务器上所有内容所有者的列表。一旦我们有了这个,我们可以做一个简单的检查,看看我们计划删除的用户是否是服务器上任何内容的所有者。
为了建立内容所有者的完整列表,我们需要:
- 获取所有项目所有者
- 获取所有工作簿所有者
- 获取所有数据源所有者
- 获取所有流所有者
- 整合上述各项的相关信息
完整的代码作为 GitHub 要点提供在本文的最后,所以我不会在这里详细描述每个步骤,但是让我们强调一下 tableau-api-lib 在这里是如何派上用场的。
让我们以工作簿为例。这里有一个模式,我们可以用它来提取所有工作簿的信息,这也允许我们提取关于工作簿所有者的信息。
workbooks_df = querying.get_workbooks_dataframe(conn)
结果 workbooks_df 将如下所示:

现在,放大“所有者”栏,我们希望从中提取一些有价值的信息。这个金块就是拥有内容的用户的“id”值。让我们通过使用 tableau-api-lib 的 flatten_dict_column util 函数来提取嵌套的 dict / JSON 值。
workbooks_df = flatten_dict_column(workbooks_df, keys=['id'], col_name='owner')
如果您看一看文章末尾的完整代码,您会注意到我们还为创建的每个数据帧添加了一个“content_type”列。
workbooks_df['content_type'] = 'workbook'
这只是为了当我们迭代用户拥有的所有内容时,我们可以识别要使用的适当的 REST API 端点。更新工作簿、数据源和流有不同的端点,我们需要根据更新的内容类型调用正确的 tableau-api-lib 方法。
如果我们对我们的工作簿、数据源、流程和项目遵循这种模式,那么我们可以很容易地组合结果数据(请参见文章末尾的代码中的例子)。
步骤 4:指定一个将接受孤立内容的用户
因为我们要更改内容的所有权以便删除一个用户,所以我们需要指定另一个 Tableau 用户来获得内容的所有权。这个过程有几种有效的方法。
您可以随机选择任何一个服务器管理员用户,并将内容分配给他们中的一个,您可以按名称选择用户,或者您可以挑选用户 ID 值,并选择您喜欢的任何一个。
对于这个例子,我的测试环境总共有…两个用户。所以我只是叫出了另一个用户的名字,就像这样:
new_owner_id = list(users_df[users_df['name'] == 'estam']['id']).pop()
用户名为“estam”的用户将成为被删除用户以前拥有的任何内容的新所有者。
说到被删除的用户,我也在我的工作流中进行了定义:
user_id_to_remove = list(users_df[users_df['name'] == 'estam2']['id']).pop()
同样,有许多有效的方法来定义这些值。重要的是,您有一个新所有者的用户 ID,以及一个被删除用户的用户 ID。
步骤 5:定义一个改变内容所有权的函数
我运行的实现遍历被删除用户拥有的所有内容。对于该用户拥有的每一条内容,都会调用一个名为的函数 change_content_owner 。
关于如何定义该函数的确切细节,请参见本文末尾的完整代码。
总之,该函数包含一些 if 语句,这些语句根据正在处理的内容类型执行不同的 REST API 更新调用。如果工作簿需要所有权变更,那么将调用'更新工作簿 ' REST API 端点。如果一个流需要一个所有权,那么就调用' Update Flow ' REST API 端点。等等,等等。
现在,鉴于项目还不能通过 REST API 调用来更新,这对我们来说有点不方便。在将这种能力添加到 REST API 的可能性领域之前,我们将需要手动更改这种所有权。如果您真的对自动化感兴趣,您可以修改我在这里定义的函数,以便在拥有项目的用户被删除时触发 Slack 消息或电子邮件。该消息可能会提醒您的服务器管理员团队,该用户需要一些手动操作才能从服务器中成功删除。
第六步:证明流程有效
下面是我的流程运行的一些示例输出。在本演示中,被删除的用户拥有一个工作簿和一个数据源。

Tableau 服务器的 JSON 响应确认了我们的所有权交换是成功的。
步骤 7:总结局限性
在我们结束之前,让我们回顾一下这个过程的局限性以及这些局限性来自哪里。
- 您不能删除拥有内容的用户
- 在成功删除用户之前,您必须更改用户拥有的所有内容的所有权
- 您不能通过 REST API 调用来改变项目的所有权(希望这个功能将很快被添加进来;去投票吧!)
- 试图删除拥有内容的用户将导致用户的角色被修改为“未经许可”,但他们仍将拥有内容。
- 当您更改工作簿或数据源的所有者时,任何嵌入的凭据都将失效。
想了解更多?查看 Tableau 关于改变内容所有权的文档。
包装它
这就是关于删除拥有内容的 Tableau 用户的教程。归根结底,在内容所有权方面不能留下任何漏洞。
如果你的用户不拥有任何内容,这是小菜一碟!
如果您的用户确实拥有内容,请更改您的工作簿、数据源和流的所有权。如果您的用户拥有项目,您需要手动更改所有者,然后才能从服务器中成功删除用户。
感谢收听!如果您的团队需要 Tableau Server REST API 自动化方面的帮助,请联系我们。
合并代码
使用这个 GitHub 要点作为模板,将本教程中的概念整合到你自己的工作流程中。
如何用 21 行 Python 在 Mac 上重命名截图
原文:https://towardsdatascience.com/how-to-rename-screenshots-on-mac-with-21-lines-of-python-c3c2366f6eec?source=collection_archive---------85-----------------------
大蟒
使用操作系统和日期时间模块,通常重复的任务现在只需点击一下。

小姐姐为这个项目创作的原创图片
在 Mac 上截屏很简单,只需点击 Command-Shift-3 进行全屏截图,或者点击 Command-Shift-4 进行部分屏幕截图。你也可以用终端为你的截图设置一个自定义标签,但是有时候你需要更多的自定义。
作为一个为不同项目拍摄批量截图的人,我经常需要重命名截图以适应这种格式:
project name _ date created _ screenshotcount . png
只有 21 行 Python 代码,现在我只需点击桌面上的一个可执行文件,所有的截图都会被重命名以匹配上面的格式。

使用 Python 脚本在 Mac 上重命名屏幕截图
每当我需要重命名一批 20-30 个截图时,这可以节省我大约一分钟的时间。但是随着时间的推移,这种情况会越来越多,所以我决定使用 Python 来自动化这些枯燥的东西!
下面看看这个脚本是如何工作的,以及如何让它在 Mac 上可执行。
使用 Python 的 os 和 datetime 模块在 Mac 上重命名屏幕截图
在写这个脚本之前,我没有改变任何预先构建的截图设置。默认情况下,我的截图如下:

我电脑上的截图示例
因为我为不同的项目拍摄了一批截图,所以我希望每个文件名都以项目标签开头。我还想保留截图拍摄的原始日期,但我不需要时间。最后,为了确保没有重复,每个截图的文件名后面都应该有一个数字。
配置您的截图标签和当前工作目录
首先,我们需要导入必要的模块:
import os
from datetime import datetime
操作系统模块允许我们通过 Python 与您的操作系统交互。使用这个模块,我们可以读写文件、操作路径等等。 datetime 模块也内置在 Python 中,它为我们提供了在脚本中操作日期和时间的类。
接下来,我们将添加一个项目名称提示,用于标记每个截图的文件名:
project = input('Enter the project name: ')
然后,我们需要启用我们的脚本来找到截图。为此,我们将当前工作目录更改为我们系统的桌面。我们可以手动找到个人桌面的路径,并将其硬编码到脚本中,但为了避免这样做,我们可以使用这两行代码:
desktop = os.path.join(os.environ['HOME'], 'Desktop')
os.chdir(desktop)
我们来分析一下。
“ os.environ ”将返回我们的“环境变量”的字典,这些变量是我们的 Python 脚本运行所在的系统的特性。写出" os.environ['HOME'] "将返回字典的一个子集,其中只有我们的主目录的路径名。在 Mac 上,根据您配置机器名称的方式,您将得到类似于以下内容的内容:
/Users/firstname.lastname
要获得桌面的路径,我们需要在上面的字符串中添加“/Desktop”。现在,我们可以把两个字符串加在一起,但是一旦你开始把两个以上的字符串加在一起,记住在哪里放反斜线就变得复杂了。
为了避免硬编码反斜杠,我们使用了" os.path.join() "函数。这将我们提供给函数的路径合并成一个文件路径,而不必手动添加必要的反斜杠。我们提供的两个参数是“os.environ['Home']”,它将给出您的系统的主目录,以及字符串“Desktop”。
运行 os.path.join()函数将得到以下结果:
/Users/firstname.lastname/Desktop
接下来,我们需要用“ os.chdir() ”函数改变我们的工作目录,提供“桌面”变量,该变量包含我们机器的桌面路径。这将允许我们的脚本在桌面上搜索截图,我们现在就这样做。
在桌面上查找和重命名屏幕截图
首先,为了避免重复的文件名,我们将把“count”变量赋给 0。在下面的 for 循环中,我们将在每次找到并重命名屏幕截图时给这个变量加 1。
count = 0
现在,这里是 for 循环:
for original_file in os.listdir():
if 'Screen Shot' in original_file:
count += 1
birth_time = os.stat(original_file).st_birthtime
birth_time = datetime.fromtimestamp(birth_time)
birth_time = birth_time.strftime("%d-%m-%Y")
new_file = project + "_" + birth_time + "_" + str(count) + ".png"
os.rename(original_file, new_file)
让我们把这个循环分解成几个部分。
" os.listdir() "输出给定目录中所有条目的文件名列表。默认情况下,它将在我们当前的工作目录中查找所有条目,我们之前将该目录指定为桌面。
例如,如果我们的桌面上有一个 Excel 文件和一个文本文件,os.listdir()会给出:
['samplefile.xlsx', 'samplefile2.txt']
for 循环的目的是遍历每个条目,看看它们的名称中是否有“Screen Shot”。这是因为在 Mac 上,截屏文件名的默认命名约定是总是“截屏”,然后是截屏拍摄的日期和时间。为此,我们只需检查“截图”是否在我们从“os.listdir()”中找到的文件名中,如下所示:
if 'Screen Shot' in original_file:
如果满足该条件,脚本将开始重命名该文件的过程。在 if 语句下的第一行,我们写“count+=1 ”,将前面初始化的计数器变量加 1。这将在以后添加到文件名中。
然后,为了获取截屏拍摄的日期,我们使用" os.stat() "来获取文件的一些元数据,并作为参数传递。
birth_time = os.stat(original_file).st_birthtime
这里,我们传入了“original_file”变量,该变量只包含符合“屏幕截图”条件的每个文件的名称。我们对“st_birthtime”结果特别感兴趣,它返回文件创建时的时间戳。
为了将时间戳转换成更容易阅读的文件名,我们将使用“fromtimestamp()”datetime 类方法将其转换成 datetime 对象。
birth_time = datetime.fromtimestamp(birth_time)
接下来,我们将把我们的 datetime 对象重新格式化为我们希望它打印在屏幕截图的文件名上的样子。为此,我们使用“ strftime ”或“来自时间的字符串”,其中我们获取一个 datetime 对象并解析它以获得我们需要的部分。在本例中,我希望将类似“2019 年 12 月 1 日”的日期显示为“2019 年 1 月 12 日”。为此,我们使用以下 strftime 运算符:
birth_time = birth_time.strftime("%d-%m-%Y")
现在我们有了文件名的所有组成部分。为了把它们放在一起,我们要用这条线把所有的变量结合起来:
new_file = project + "_" + birth_time + "_" + str(count) + ".png"
这里,我们有从一开始的输入中获得的“项目”标签,截图的“出生时间”格式的字符串,以及转换为字符串的“计数”变量。为了使名称看起来更好,我们还在文件名部分之间添加了下划线。然后,我们加上”。png”作为图像扩展名。
为了实际重命名文件,我们使用“ os.rename() ”,它有两个参数:原始文件名和替换文件名。
os.rename(original_file, new_file)
仅此而已!
这个循环将遍历我们桌面上的每个文件,并根据我们刚刚遍历的过程编辑每个名称中带有“Screen Shot”的文件。
使 Python 文件可执行
我们可以从我们的终端运行该脚本,但是要让我们只需单击桌面上的一个文件来重命名我们的屏幕截图,只需遵循以下步骤:
- 把这个添加到你的 Python 脚本的第一行:
#!/usr/bin/env python3
这被称为“shebang ”,它允许执行 python 脚本,而不必在终端的文件名前键入“Python”。
2。将 Python 脚本的文件扩展名更改为“”。命令”。
在我的例子中,Python 文件被称为“screenshots.py”,所以我将其重命名为“screenshots.command”。
3。在终端上,运行下面两行来创建您的"。命令“文件可执行:
cd Desktop
chmod +x filename.command
这假定您已经放置了您的"。命令”文件放在桌面上。如果您将它存储在不同的文件夹中,请将该文件夹的文件路径放在“cd”之后。
现在,您只需点击文件,您的 Python 脚本就会运行!
完整的代码可以在这里看到:
屏幕截图重命名脚本
我发现这是一种快速简单的方法,可以练习使用 os 模块来检查系统上的文件,同时集成 datetime 来定制屏幕截图名称。有很多方法可以进一步缩短这个脚本,比如删除第 7 行和第 8 行,将桌面的路径直接传递给 os.listdir()。为了清楚起见,我按照本文中的解释保留了它,但是当您在自己的任务中使用它时,可以随意调整脚本。
您也可以使用相同的步骤模板来转动一个”。py“将文件转换成可执行文件”。command”文件,每当你需要一个可点击的脚本。
祝你截图好运!
如何渲染 3D 足球传球网络
原文:https://towardsdatascience.com/how-to-render-3d-football-pass-networks-bf889f5ab1b0?source=collection_archive---------32-----------------------

用 Python 和 Cinema4D 实现体育数据可视化
传球网络分析长期以来一直是足球分析师中流行的可视化方法。那么,为什么又有一篇关于它的文章呢?嗯,一个下雨的周日,我认为在我的电脑上运行别人的全面 Python 脚本来提升我的科学自尊是一个好主意,并为自己是一名多么伟大的数据科学家而沾沾自喜。毫不奇怪,该脚本在第一次尝试时成功执行——显然不是因为我的编程天才,而是因为我使用的脚本的优秀质量,即用于使用 Matplotlib 构建可定制的传球网络的 Sergio Llana 的 GitHub 库。所以在一键按下【运行脚本】后,我骄傲地盯着我的第一个“自编程序”的 pass 网络:

2D 通行证网络。图片作者。科迪由塞尔吉奥利亚纳。
但随后一个念头涌上心头:“如果我能沉浸在网络中,看看到底打了多少个低传球或高传球,那不是很好吗?”。就在那时,我开始尝试 Cinema4D 的内置 Python 模块。令我自己惊讶的是,我能够不费吹灰之力就实现我的想法。在这篇文章中,我想分享我的(可能是非传统的)可视化方法。
免责声明:如果你是来寻求分析见解的,恐怕你会失望。这篇文章是关于如何将传统的 2D 传球网络转换成 3D 的。
如何开始
如前所述,我之所以能够取得我的成果,是因为有人慷慨地分享了他/她的代码。我用于数据准备的许多代码段直接取自 Sergio Llana 的 GitHub 页面(特别是statspamb 的开放数据仓库的导入和处理)。人们毕竟是懒惰的,所以复制粘贴代码没有什么可耻的!…对吗?也就是说,你可以在我的 GitHub 上找到我的 Python 脚本和 C4D 项目文件。
数据采集
我很惊讶现在有这么多的球探数据是公开的。对于这个项目,我使用了发生在 2018 年世界杯小组赛期间的比赛葡萄牙 vs 西班牙(3:3) ,。你可以在 StatsBomb 找到 2018 年世界杯所有比赛的赛事数据。另一个值得一提的重要来源是最近在《自然》杂志上发表的一篇文章,其中附有时空匹配事件的公共数据集。
网络基础
足球传球网络由一组通过“边”(即传球)连接的圆形“节点”(即球员)组成。从现在开始,我将使用术语“样条线”来代替“边缘”。以后你就明白为什么了。节点的大小通常代表玩家在游戏中完成的传球总数。每个球员的场地位置(也称为战术阵容)可以通过以下方法获得:(a)根据每个球员的时空跟踪数据(如果可用)计算平均 XY 坐标,或者(b)根据每个球员的侦察事件(即传球)计算平均 XY 坐标。传统上,边的重量(厚度)代表两个球员之间完成传球的次数。
准备数据
我将跳过如何解析 StatsBomb 的 JSON 文件并将完整的 pass 连接提取到单独的数据帧中的部分。塞尔吉奥的剧本非常管用,所以我只做了些小调整。我事先知道我要渲染每个节点,一个一个的通过。这就是为什么我创建了两个数据帧,可以保存为文本文件,并使用内置的 Python 连接器导入 Cinema4D:
- 对于玩家节点,我们需要每个玩家的名字,平均场坐标,以及完成的总遍数:

玩家节点表。图片作者。
- 对于传球样条,我们需要一个列表,包含(a)所有球员配对【pair _ key】, (b)每个球员配对完成的低传球和高传球的数量,以及(c)传球和接球球员的平均场地坐标:

传递值表的一部分。图片作者。
使用 Cinema4D 进行网络渲染
Cinema4D (C4D)是一款 3D 设计、动画和渲染软件,主要用于运动图形、建模和纹理;但是,它附带了一个全面的 Python 模块。也就是说,几乎每个用户操作都可以通过 Python 命令来执行,从而允许设计过程的自动化。下面是一个我自定义的用户界面的例子,显示了三维视口(左上),对象管理器(右上),和材质管理器(右中)。介于两者之间的是 Python 脚本管理器,允许以编程方式创建单个对象以及整个场景。接下来的两段将展示只用几行代码创建任何 3D 对象是多么容易。

Cinema4D Python 接口。图片作者。
生成玩家节点
我将用一个简单的圆盘来代表一个玩家的节点。在 C4D,通过 Python 命令创建一个磁盘并更改其属性非常简单。下面的代码示例在原点(0,0,0)生成一个外径为 100 厘米的圆盘:

Cinema4D 磁盘示例。图片作者。
生成刀路轨迹
我不想显示球员之间的单个加权边(代表传球次数),而是想单独渲染每个传球。为了达到这种效果,我们必须引入一些随机性…
我发现渲染两个球员之间传球轨迹最简单的方法是创建一个样条对象。最初,我认为每个样条应该只包括起点(传球手)和终点(接球手),但这将导致完美的直线——正如我们从传统传球网络中所知的那样。相反,我想创造这样一种印象:( a)每个通道轨迹都略有不同,( b)高通被渲染为一个弧形。这就是为什么我最终为每个通道轨迹使用三个样条点,这使我有可能向高通添加飞行曲线,并向中心样条点引入一些随机偏移(创建每个通道单独显示的假象)。下面的代码示例在两点之间生成十个随机样条线对象。

Cinema4D 随机通过轨迹示例。图片作者。
运行循环
既然我们知道了如何生成球员节点和传球轨迹,那么是时候用我们球员特有的值替换默认值了。这最适合使用一个循环来遍历播放器节点文件,并为每个播放器创建一个名称和磁盘。第二个循环通过传球值文件进行迭代,并在球员配对之间生成随机传球轨迹——取决于他们之间完成的传球次数。
收尾
现在剩下要做的就是添加场线,选择你最喜欢的颜色(又名材料),添加一些信息文本,找到一个合适的相机角度,根据你的喜好调整渲染设置——然后点击【渲染】按钮:

图片作者。

图片作者。

图片作者。
关键外卖?
对于典型的足球分析师来说,可以说很少。但是如果你像我一样,你的兴趣介于数据科学和图形设计之间,你会惊讶于编程语言(Python)和 3D 设计软件(C4D)的结合所能实现的东西。
诚然,C4D 不一定被认为是数据科学家的标准工具,你也需要投入一些时间来学习基础知识。与传统的 2D 网络相比,3D pass 网络是否提供了任何附加值,这仍然是一个有争议的问题。尽管如此,我还是很喜欢在 C4D 尝试 Python,并且我将来肯定会更频繁地集成它。
接下来是什么?
动画! C4D 展示了它在动画方面的真正实力,这很棒,因为有些人可能会认为静态通行证网络提供了对游戏相当肤浅的洞察。相反,展示一个团队的网络动态如何随时间变化(以及它如何对对手的网络做出反应)可以提供更深入的见解。让我们看看有什么可能。我会随时通知你的!
感谢您阅读我的文章!如果您有任何问题或反馈,或者您只是想联系我,请不要犹豫,请联系我。
如何完全在浏览器中呈现交互式天气模型
原文:https://towardsdatascience.com/how-to-render-interactive-weather-models-entirely-in-the-browser-5ff2db881cb8?source=collection_archive---------10-----------------------

WPC 概率冬季降水指导 72 小时降雪模型,在浏览器中渲染并添加到传单地图。
完全使用 JavaScript 将多维地理空间栅格渲染到 web 地图上的技术和用例。
气象爱好者、气象学家和风暴追逐者都知道网络上有无数的气象模型可视化网站。这些平台允许你查看各种参数、级别和几十种不同天气模型的预报时间。例如,当准备一天的风暴追逐时,追逐者可能会查看某个区域的几个参数-早上的露点、当天晚些时候的海角以及下午的 HRRR 模拟反射率。通常提供菜单、按钮和滑块来切换预测时间、模型和参数。

北美模型在离地面两米处的温度,使用杜佩奇学院的模型观察器。
通常,所有这些天气模型查看器都是用户访问预渲染的非空间天气模型的简单方式,尽管原始数据实际上是地理空间数据。尽管界面不同,但天气模型查看器中的许多内容是一致的:
- 地理区域是固定的。您只能查看预设区域,例如城市、州或地区列表。输出图像的大小也是固定的。一些查看器允许您放大某些区域并等待新的渲染。
- 地理图层和信息稀缺或不存在。在天气模型图像上,您可能只有道路或县是可见的,这可能会使特定区域难以精确定位。
- 许多提供者拥有通常不可查询的查看器,这意味着要获得任何给定点的实际值,需要将数据的颜色与图例进行比较。
- 模型层组合和配色方案是静态的。例如,您不能在另一个变量上叠加特定高度的风流线,除非提供商提供了该组合。

TropicalTidbit 的模型查看器。不想让地图上的所有图层同时出现?太糟糕了。
尽管许多提供者已经对数据的呈现进行了认真的考虑和思考,但是上述缺点在某些情况下可能是显著的和恶化的。例如,考虑到降雪量在几英里范围内可能会有几十英寸的差异,如果您只有县边界来确定自己的方位,评估山区的预测降雪量可能会非常具有挑战性。
考虑下图:

即使作为一个拥有地理学位的预测者,我也很难从这张图表中获得有用的数据。看看科罗拉多州:
- 汽船和北科罗拉多黄等带的关系在哪里?它是蓝色的还是绿色的?(这将是 2 英寸和 6 英寸雪的区别)。
- 在 I-70 上,从韦尔山口以东到以西的降雪量分布如何变化?
- 戈尔山脉和它南边的十英里山脉相比,降雪量有多少?
如果你在科罗拉多州做了足够多的预测,你最终会记住精确到英里的县轮廓与山脉的关系,因为当你在许多模型查看器上查看整个州的天气分布时,这通常是你必须做的全部工作。
也就是说,提到这些平台的好处是很重要的——最明显的是使用预先渲染的静态图像。这些都很快,很容易在几秒钟内加载一个模型的所有预测小时数,并且您通常可以很容易地让服务器生成数据的动画 GIF。固定区域防止了数据的“误用”——例如放大到超出天气模型适用范围的分辨率。这两个因素允许一致的天气模型可视化,如果您正在下载图像并将其存档以供比较或重新分发,这将很有帮助。

在杜佩奇学院的浏览器上下载整个模型的预测既快又容易。
构建您自己的模型可视化工具—概述
在上一篇文章中,我讨论了如何构建和自动化自己的天气模型可视化工具。这项技术有一个有趣的变化,尽管服务器仍在渲染数据,但它将数据作为地理空间层(OGC·WMS)提供服务,可以添加到交互式 web 地图中。这在预渲染静态图像的性能和完全地理空间数据的交互性之间取得了良好的平衡。我将向您展示如何更进一步,完全在浏览器中进行渲染,不需要服务器!根据我上面的链接,这篇文章将假设你有 GeoTIFF 格式的天气模型,并投影到 EPSG:4326。只需一个 GDAL 命令,即可将原始天气模型数据(GRIB2 格式)转换为 GeoTIFF。
使用 web 浏览器在客户端呈现天气模型数据的缺点很多,但是这种技术有一些潜在的使用案例。2020 年的 Web 开发似乎已经足够成熟和强大,可以让它成为一个实际可行的提议。以下是我们将会遇到的主要问题:
- 缓慢。JavaScript 并不是将原始多维栅格转换成 RGB 图像或矢量等值线的理想语言。
- 数据使用。原始天气模型数据不像简单的 JPEG 那样紧凑。
- 兼容性。我们编写的最终代码无法在 Internet Explorer 中运行,在较旧的硬件上运行起来也很糟糕。
相比之下,以下是我们将享受的一些好处:
- 在完全交互式的 web 地图上呈现数据的能力,这意味着我们可以实时添加任意数量的地理数据层(或其他模型参数),并按照我们想要的方式设置样式。
- 可以直接访问数据,例如查询原始模型数据的点或区域。这不仅仅是单击地图并获取某一点的数据,一个用例可能是定义一个位置列表或一组点,以表格格式显示数据或在地图上叠加数据。
- 以我们选择的任何方式渲染天气模型数据或数据组合的能力,如栅格、等值线、等值线(等值线/等高线)、流线等。渲染、样式(例如,轮廓的宽度)和色带都可以由用户修改(如果需要),并即时更新可视化。各种模型甚至可以在数学上组合起来,以产生特定的可视化效果,而不是必须提前设置自动化处理脚本来实现。
我们也有一些策略来缓解一些棘手问题:
- 使用 web workers 来处理和渲染地理标记。这将把密集的计算分散到用户 CPU 的各个核心上。
- 使用云优化地理标签 (COGs)或 WCS 标准将原始数据传输给用户,仅限于他们感兴趣的区域和范围。此外,对土工格栅施加适当的压缩可以使它们减小到合理的尺寸。
记住这几点,你能想出一些可以享受客户端渲染好处的用例吗?对我来说,可视化的质量立即浮现在脑海中。我曾经使用定制的 QGIS 项目来导出带有天气模型数据的漂亮地图,但是仍然需要手工劳动。借助一个外观精美的 web 浏览器可视化平台,我可以快速地对多个模型、参数和预报时间进行分析,同时只需点击一下鼠标,就可以导出天气模型图形和地图进行重新分发。
在我之前提到的关于使用 MapServer 分发天气模型数据的文章中,我也遇到了一些具体的问题。这些问题都与可视化产品有关,在这些产品中,图形被从数据本身中大量移除,需要将各种栅格渲染为最终的 RGB 图像(例如,风速栅格上的流线或风倒钩),这与我打算在 MapServer 中采用的比例和样式不可知的模型数据分布策略模型不兼容。然而,当在 web 浏览器中处理时,这些问题很容易解决:
- 天气模型组合计算。几个流行的天气模型可视化是不可能的,简单地分发转换后的数据,而不渲染一个 RGB 图像。最好的例子是复合反射率+降水类型,它显示了您可能期望的模拟雷达——雨显示为绿色-黄色-红色的典型色阶,而雪显示为蓝色阴影。这实际上需要至少三个不同天气模型参数栅格的组合,或者如果要处理所有降水类型(冰粒和冻雨),则需要五个。据我所知,没有办法在 MapServer 中即时完成这项工作,因为需要根据降水类型使用不同的色标,并组合成最终的图像。一个更简单的例子是,大多数模型中的风向不是单个参数,而是两个栅格(水平和垂直矢量分量),需要结合三角学来计算实际方向和速度。

降水类型,由杜佩奇学院渲染。
- 风的流线。MapServer 能够根据栅格生成等值线,甚至可以生成穿过栅格字段的方向箭头,但流线是不可能的。然而,许多受欢迎的产品依靠流线来显示像中层大气风这样的东西。

流线在 weather.us 的渲染中很明显。
在上面的例子中,你可能已经注意到了一件事,那就是尽管可视化效果很好,但看起来并不那么好。图像很小,数据也很狭窄,这对预测者来说并不容易。当重新发布给天气预报读者时,它们甚至更麻烦,这些读者可能不是数据极客,只是想知道他们下周末应该去哪里滑雪。我想人们可能会承认,他们 90 年代后期的像素化审美确实给人一种纯粹的数据权威的感觉,除了传达原始数据,他们当然不会浪费任何时间做任何事情。
构建您自己的模型可视化工具——在实践中
让我们来看看天气模型完全在 web 浏览器中呈现时会是什么样子。这些是从我的网站上摘下来的,用在了我的预测中。首先,这是我用 Angular 为它建立的界面:

下半部分被切掉,以隐藏我在设计中尚未有效实现的按钮墓地:)
一些示例输出图像:

现在,让我们放大交互式地图,并启用其他一些层。当我说可调整时,我的意思是这可以由用户在网页上实时完成:

有流线的图层怎么样?

是的,流线型箭头在工具提示的顶部。我会修好的。
我们甚至有可怕的复合反射率+类型层工作正常。你可以看到落基山脉上空的雪是深蓝色的,内布拉斯加州的小雨是灰色的(嗯,很抱歉有点误导人的浅蓝色)。这都是在浏览器中计算出来的。

在我住的地方没有太多有趣的天气,这是我唯一能找到的两种降水类型的框架。
以下是完成客户端天气模型渲染所需的主要步骤,前提是您已经准备好了 web 地图。我使用传单,但最终需要扩展它这么多,如果你是从零开始,OpenLayers 可能更适合。
Fetch适当的模型、时间戳、参数、级别和预报小时的 GeoTIFF 数据,并将流作为ArrayBuffer读取。- 解析
ArrayBuffer以获得地理信息和原始数据的嵌套数组。Geotiff.js 是这方面的首选库,尽管它不能很好地与 Angular 配合使用,除非您导入缩小版。您需要缓存这些数据,以防需要对其进行查询或重新呈现可视化效果。 - 提取适当波段的数据(对于多维数据,例如一个 TIFF 中的多个预测小时或一个中的多个参数),并使用 web workers 对嵌套数据数组运行行进正方形算法,您可以使用该算法生成等值线(多边形)或等值线(折线),具体取决于您是否想要填充/着色数据或等值线。你可以使用像光栅行进正方形这样的库。对于流线,可以使用光栅流线库。这是计算量最大的一步。一旦计算完成,您将需要缓存所有这些数据。
- 在创建等值线和等值线时,对其应用必要的地理变换,然后将其提供给 web 地图。例如,在传单中,我将这些数据作为一个
L.GeoJSON层。确保为每个波段或线条提供数据值,以便可以适当地设置样式。把它添加到地图上。 - 添加其他功能,如点查询和可视化下载(“另存为 JPEG”)。
让我们深入研究一下细节吧!我将直接从我的代码库中使用 TypeScript 和 ES6 语法,它使用 Angular 框架。
1.检索地理信息数据
这是最简单的部分。一些策略可能是:
- 只需从网络服务器下载文件。
- 创建一个 API,为模型、参数、预测时间、地理区域等检索适当的文件。
- ✔️使用云优化地理标志
- 使用 MapServer 或其他地理数据服务器处理 WCS 请求,并将数据作为 GeoTIFF 返回。
想想你希望你的地理结构是怎样的。为了节省数据,您可能希望为每个模型、参数、级别、预测时间等返回一个 TIFF。但是,如果客户希望预加载所有内容(例如,使用滑块查看所有预测小时数),您可以将多个预测小时数存储为一个 TIFF 中的几个区域。这将创建一个初始的,较长的下载时间,但会稍微加快整体解析时间。
不要忘记压缩。虽然你可以对 TIFFs 使用 JPEG 压缩,把它们的文件大小压缩到和 JPEG 差不多,但是这不是对数据的负责任的使用。这些不是图像,而是原始数据的数组,在渲染之前应该尊重其完整性。另外,我不认为geotiff.js库能够处理这种压缩方法。我发现高水平(zlevel = 9)的deflate在不严重影响解析性能的情况下减少了 50%的大小。
您可能会用fetch或使用geotiff.js的内置函数来检索 GeoTIFF。该库可以原生读取云优化的 GeoTIFFs!如果使用常规的 GeoTIFF,您需要将fetch请求流(如果您创建了一个)作为ArrayBuffer读取:
*const response = await fetch( <the url of your tiff> );
const arrayBuffer = await response.arrayBuffer();*
2.解析 GeoTIFF 数据
按照上面的例子,我们可以使用geotiff.js将ArrayBuffer解析成一个GeoTiff对象。我们可以从该对象中检索实际的图像数据本身:
*const geoTiff = await fromArrayBuffer( arrayBuffer );
const geoTiffImage = await geoTiff.getImage();*
不要忘记获取图像元数据和地理数据,我们稍后会用到它们:
*const tiffWidth = geoTiffImage.getWidth();
const tiffHeight = geoTiffImage.getHeight();
const tiepoint = geoTiffImage.getTiePoints()[ 0 ];
const pixelScale = geoTiffImage.getFileDirectory().ModelPixelScale;
const geoTransform = [
tiepoint.x,
pixelScale[ 0 ],
0,
tiepoint.y,
0,
-1 * pixelScale[ 1 ]
];*
如果图像中有多个波段,您可以轻松获得它们的确切数量:
*const bands = await geoTiffImage.getSamplesPerPixel();*
3.根据数据构建等值线/等值线/流线
除了风倒刺(这对天气预报员来说可能很好,但对普通公众来说几乎没用),除了等深线、等值线或流线,我想不出任何其他方法来呈现天气模型数据。等深线是属于特定数据范围的多边形。您可以使用它们来生成彩色的温度或积雪地图。等值线是在数据区域边界绘制的等高线。流线有助于可视化既有速度又有方向的数据。这些都可以创建为矢量并添加到地图上。
我们需要破解 GeoTIFF 数据来构建我们的地理向量。您也可以将它作为图像渲染到画布上,但我不会在这里介绍(参见致谢部分)。
获取适当波段的图像数据(其中i是波段号):
*const bandData = await geoTiffImage.readRasters({ samples: [ i ] });*
构建原始数据的嵌套数组:
*const dataArr = new Array( tiffHeight );
for ( let i = 0; i < tiffHeight; i++ ) {
dataArr[ i ] = new Array( tiffWidth );
for ( let ii = 0; ii < tiffWidth; ii++ ) {
dataArr[ i ][ ii ] = bandData[ 0 ][ ii + i * tiffWidth ];
}
}*
我们将使用raster-marching-squares库来生成我们的特性,但是出于性能考虑,我想作为一个 web worker 来运行它,这样用户界面就不会锁定。如果你正在使用 Angular,运行ng generate web-worker就可以很容易地用 Angular-CLI 设置一个 web worker。
在 web worker 内部,我们将把raster-marching-squares作为rastertools导入:
*import * as rastertools from 'raster-marching-squares';*
这将等深线和等值线渲染为rastertools.isobands()或rastertools.isolines()。这两个函数都需要以下参数:
- 嵌套数据数组(
dataArr) - 光栅的投影(
geoTransform) - 数据的中断/间隔时间。这些间隔将始终出现在这些函数的输出中,而不管这些函数中实际上是否有任何特征。例如,如果您将
[-5,0,5]作为温度模型的区间,您将会收到三条与-5 度、0 度和 5 度相关的等深线或等值线。如果天气模型具有这些范围内的数据,那么这些等值线或等深线将具有包含这些区域的几何图形。否则,它们将是空特征。
我们最终会想要设计等值线的样式或在等值线上放置标签,所以我做的一件事是为我想要可视化的所有各种参数设置色标,为特定值传递一种颜色。然后,我设置了一个函数,它将从色标中产生固定数量的间隔(比如 100——平滑,但需要一段时间来计算),并使用tinygradient来产生用于图例的色标的 CSS 表示。例如,积雪的色标如下所示:
*"SnowAccumM": [
{ value: 1.8288, color: "#ffcc01" },
{ value: 1.2192, color: "#ff4501" },
{ value: 0.6096, color: "#e51298" },
{ value: 0.3048, color: "#9f0ded" },
{ value: 0.0762, color: "#5993ff" },
{ value: 0.00254, color: "#d6dadd" },
{ value: 0, color: "#ffffff" }
],*
interval 创建函数也用Number.MAX_SAFE_INTEGER和它的负等价物来限定 intervals 数组。如果做得好,并在其中加入一些单位转换,就可以在一个紧凑的类中处理 isoband 的创建、样式和图例。

积雪的等深线,以米为单位,转换成英寸。这有 100 个间隔,其中大部分没有被使用,因此没有被优化。希望很快会有一场用掉所有 100 个间隔的暴风雪…
运行等值线或等值线函数的工作线程将监听三个必要的参数。我们还将传入一个type参数来告诉它使用哪个函数:
*addEventListener( 'message', ( { data } ) => {
try {
const features = rastertools[type](
data.data,
data.geoTransform,
data.intervals
);
postMessage ( { features } );
}
catch ( err ) {
postMessage( { error: err.message } );
}
}*
该函数被包装在一个try...catch中,这是一个好主意,但在实践中没有用,因为当函数出错时,它往往会陷入一个do...while循环中,直到内存耗尽。这可能是由于我一天转换的数千个天气模型栅格中的一些被破坏了,我需要修复这些栅格,但是…有人请求吗?
现在我们可以调用 worker,向它传递必要的参数,并等待响应。您不必使用Promise,它只适合我的特定工作流程:
*const type = 'isobands';const rastertoolsWorker = new Worker(
`../workers/rastertools.worker`, // the worker class ☭
{ type: `module` }
);new Promise( ( resolve, reject ) => {
rastertoolsWorker.postMessage( {
dataArr,
geoTransform,
intervals, // array of numbers
type
} ); rastertoolsWorker.addEventListener(
'message',
event => resolve( event.data )
);
} ).then (...) // the isobands are generated!*
如果你做 100 次间歇,这可能需要一点时间。你的笔记本电脑粉丝可能会以惊人的凶猛速度踢你。

在 web 浏览器中从栅格生成矢量?多么明智的想法。这很好。
注意,我没有提到流线。如果您使用raster-streamlines库,这个计算会非常快,并且可能不需要放在 web worker 中。
4.把它放在地图上
如果你用了raster-marching-squares,这部分就全给你搞定了。基本上,矢量要素是从栅格中生成的,需要与这些像素的实际地理位置联系起来。我们可以使用由geotiff.js提供的geoTransform来获取转换信息(希望您的 GeoTIFF 最初位于 EPSG:4326)。我们还需要 GeoJSON 形式的信息,这是一个不可知的几何集合。同样,库提供了这个集合,我们只需要用L.geoJSON(<the features>)包装它来创建一个我们可以添加到地图的层。raster-streamlines也是如此。
该库还在每个特性的properties中提供 isoband 的数据范围。我们可以用它来设计等值线的样式或者给等值线添加标签。这是这个过程的另一个棘手的部分,我将很快介绍它。
您还需要考虑希望 web 地图使用哪种渲染器。默认情况下,传单使用 SVG。如果你有巨大的,详细的等带,性能将是糟糕的。相反,我选择了使用基于画布的渲染器,这带来了一些麻烦,但是一旦特性被绘制到画布上,就可以获得可接受的性能。
我们现在准备好样式我们的层。
造型等带
这些是最容易造型的。您只需要传递一个样式函数:
*L.geoJSON(<the features>, { style: feature => {
return {
fillColor: getColor( feature.properties[ 0 ].lowerValue ),
weight: 1.5,
opacity: 1,
color: getColor( feature.properties[ 0 ].lowerValue ),
fillOpacity: 1
};
});*
getColor()是我写的一个函数,它获取一个值,并从前面提到的适当色标中获得插值颜色(使用tinygradient)。由于raster-marching-squares,已经用数值范围填充了feature.properties。
你会注意到我还设置了 1.5 的描边/轮廓权重,因为如果多边形没有轮廓的话,它们之间通常会有很小的缝隙。有了轮廓,一个重要的警告是,如果你降低图层的不透明度(通过样式功能),填充和轮廓的重叠将变得明显。相反,您需要将图层放在它自己的地图窗格上,并更改整个窗格的不透明度。

这篇文章不包括适当的制图色标,尤其是色盲。
设计等值线
设计等值线本身非常简单:
*return feature => {
return {
weight: 1.5,
color: '#000000'
}
}*
但是标签呢?这其实很棘手。因为我们使用的是画布渲染器,所以绘制折线标签的传单插件是不可能的,因为它只适用于 SVG。我也不想对每一层使用不同的渲染器,比如在等值线上叠加等高线。
在这种情况下,我发现了一个名称尴尬的插件(fleet . street labels),它通过实际扩展渲染器,在画布渲染器中沿着折线绘制标签(因此它不是一个逐层解决方案)。它有几个依赖项(其中一个不能通过 npm 获得),所以设置它并不简单。
要使标签正常工作,有许多必要的修改。
- 默认情况下,插件不能解析
feature.properties,因为等值线函数将它放在一个数组中。它在寻找一个键,所以它期望feature.properties是一个对象。 - 这个插件有一个过滤器,这样它就不会试图在所有的特征上画标签,只是那些有适当属性对象的特征。出于某种原因,我想可能是由于 GeoJSON 文件可以在野外找到,它通过检查属性是否被设置为字符串值
'undefined'来检查属性是否未定义。因此,如果该键根本不存在,它仍然会尝试在该特征上绘制,这会产生一个错误。我需要修改插件来做到这一点(你可以在这个过程中处理第一个问题)。 - 绘图问题。最大的问题是它喜欢倒着画标签(即使是在其 GitHub 页面的截图中),这是糟糕的制图。一个较小的问题是,标签遵循轮廓的曲线,这很好,除了在标签变得不可读的急转弯处。
最后,我将代码和先决条件下载到我的代码库中,这样我就可以修改插件来更有效地过滤和读取特性属性。为了解决标签颠倒的问题,我修改了基本依赖关系( Canvas-TextPath ),如果所有字母颠倒,就将它们翻转 180 度,同时颠倒它们的顺序。我还在轮廓旋转的最大值上加了一个大夹子,这样就不会在曲线上产生不可读的标签。有效的等高线标注是有争议的——完全水平的标注将等高线一分为二也不一定有什么错。
也有一些关于设置自定义字体的“todo”评论,所以我将 Roboto 放入画布绘制命令中,以匹配我网站布局的其余部分。也许有一天我会提出一个拉取请求:)
对于上面列出的第 1 点,我们可以通过在 isobands GeoJSON 层的初始化中做一些工作来规避数组的问题:
*L.geoJSON( ..., {
style,
onEachFeature: ( feature, layer ) => {
if ( !feature.properties[ 0 ] ) return;
const contour = feature.properties[ 0 ].value;
feature.properties = {
contour // probably want to convert unit, add suffix :)
}
}
}*
最后,在渲染器的初始化中,我让它过滤掉路径过小的形状(压扁的标签),打开标签碰撞,并设置填充/描边颜色。这就是 TypeScript 令人讨厌的地方,因为这些粗略的插件没有定义(尽管我很欣赏它们的存在)。
*const options: any = {
collisionFlg: true,
propertyName: 'contour',
fontStyle: {
...
}
}return new ( L as any ).ContourLabels( options );*
这一切都很烦人,而且非常糟糕,但是渲染器实际上工作得很好——当你平移和缩放时,它会重新绘制标签。

真的有用!(覆盖在相同数据的等带之上)。
造型流线
流线稍微容易一点,因为有一个传单插件,允许沿着折线放置任意形状或标记(但不是文本,这就是为什么我们不得不采用上述等高线策略)。
插件是传单。PolylineDecorator 它做得很好。一旦生成了 streamline 层,就可以解析它以获得插件期望的LineString特性:
*const lines = layer.getLayers()
.filter( ( layer: any ) => {
return layer.feature.geometry.type === "LineString";
} )
.map( (layer: any ) => {
const coordinates = layer.feature.geometry.coordinates;
coordinates.forEach( coordinate => {
coordinate.reverse();
} );
return L.polyline( coordinates );
} );*
是的,你可以看到我的代码库中有一些打字问题。
我们还需要为装饰者设置模式,这可能是沿着这条线的某种箭头。我猜插件会自动处理装饰器的旋转。很好。
*const pattern = {
offset: '10%',
repeat: '20%',
symbol: L.Symbol.arrowHead( {
pixelSize: 8,
polygon: true,
pathOptions: {
stroke: false,
fill: true,
fillColor: '#000000',
fillOpacity: opacity
}
} )
}*
现在把它传递给插件:
*const streamlineArrows = L.polylineDecorator( lines, {
patterns: [ pattern ]
} );*
最后,为了便于管理,您可能希望将装饰器和流线层本身(姑且称之为layer)合并成一个单一的LayerGroup。
*L.layerGroup ([layer, streamlineArrows]);*
搞定了。我遇到的唯一问题是,插件总是将装饰器放在叠加地图窗格上(即使我试图绕过它),这意味着如果你有基于窗格的图层排序,你会遇到一些 z 索引问题。也许需要另一个拉取请求…

10m 风流线覆盖在表面阵风等带上。
5.添加其他功能
我们的地图现在工作得很好,只要你从上面的例子代码中推断出来。但是如果我们想要分发可视化效果呢?我们当然可以使用截图工具(或等效工具)手动截图,但这是不一致的。不幸的是,我们没有什么好的选项来下载我们看到的地图,因为并不是所有的东西都被渲染到画布上(工具提示、注释等等)。).
本着保持̶s̶k̶e̶t̶c̶h̶y̶的精神…我的意思是,在客户端,我们可以进一步增加我们的node_modules目录的密度,达到一个临界质量,并使用像 dom-to-image 这样的库,有希望将我们地图容器的整个 dom 树呈现为一个图像。这实际上开箱即用就能很好地工作,但是对于使用 CORS 的外部 web 字体和地图图层来说会有困难,所以要小心。
一旦你解决了这些问题,你就可以非常无缝地渲染地图了,但是你需要文件保护程序将图像保存到磁盘上。
*import domtoimage from 'dom-to-image';
import { saveAs } from 'file-saver';const image = await domtoimage.toJpeg( document.getElementsByClassName( 'map-container' )[ 0 ], { bgcolor: '#ffffff' } )saveAs( image, `my_weather_model_map_works.jpg` );*
domtoimage的性能不是很好,所以如果你希望自动创建动画 GIF,这似乎不是一个可行的方法,尽管也许有一种方法可以用 web workers 来实现。不幸的是,在使用 JavaScript 做任何事情时,我们肯定会遇到性能限制的阻碍。
你可以用这些数据做很多其他的事情,也许最著名的例子是那些花哨的动画风地图。您可以查询它(提示:使用geoTransform)、生成统计数据、编写一个 Discord 服务器机器人…但是当然,您可以在服务器上更容易地完成这些工作。客户端渲染的亮点在于天气模型的可视化和交互性。除此之外,很难证明在 web 浏览器中做任何事情的开销和性能问题是合理的。
鸣谢和来源
这当然不是处理事情的唯一方式。查看正在做的事情传单。比如 CanvasLayer.Field 。这项技术的潜力正在迅速发展,我相信在未来几年内,将会有更健壮、更高效的工具问世。事实上,甚至还有 GDAL 的 WebAssembly 包装器!
我要感谢 Roger Veciana i Rovira 提供了精彩的资源和库,让我看到了这一切的可能性,让我不用编写低级的光栅处理算法就可以立即开始构建。
如果你试图挖掘我的网站,它不是生产就绪,甚至没有客户端渲染可用。然而,所有代码和示例图像都来自一个工作测试版本。有一天…
如何将 Tableau 图表呈现为 GIF 文件
原文:https://towardsdatascience.com/how-to-render-your-tableau-viz-as-a-gif-file-b0a11ed6acf9?source=collection_archive---------38-----------------------
将动态数据可视化打包为 GIF 的简单步骤

来源:作者
本例的数据来源:
数据中的我们的世界:冠状病毒(新冠肺炎)病例
《世界人口评论:按国家分列的基尼系数》
撰写本文时考虑的时间表:2010 年 3 月 30 日至 2010 年 7 月 26 日
介绍
本文将向您展示两个简单快捷的步骤,您可以通过它们将已经动态的 Tableau 可视化制作成 GIF 文件。
如今,动态和有效的数据通信的激增也使得图表越来越倾向于以与大多数人交流的数字媒体类型相一致的交互方式进行交流。在这方面,gif 无疑是一种趋势,当涉及到增加数据图表的交互性以及向相关受众展示数据图表的方式时,gif 可能会非常有效。
因此,我将通过一个简单的示例向您展示如何将 Tableau 图表转换为 GIF 文件,然后可以通过报告/演示共享该文件,从而为您将与网络共享的任何内容添加一点交互性。
步骤 1:生成动态 Tableau 图表
本图表的目的是检验收入不平等(由基尼系数估计)与一个国家每百万居民的新冠肺炎病例总数(数据来源见页面顶部)之间的相关性,并观察这种相关性如何随着时间的推移而发展。为此,您将利用两个数据集和 Tableau 的 Pages Shelf 向图表中添加第一个交互元素。
首先,您可以输入本例所需的两个数据源,并使用 Tableau 的 data source 选项卡连接它们,如下图所示。您可以使用基尼系数表中的“国家列”与第二个数据源进行左连接,从而得到一个包含基尼系数和新冠肺炎相关列(按日期排列的病例数、测试数等)的单一表格。
为了防止您继续使用这个例子,请注意,您可能需要预处理 country 列的格式(即基尼系数表上国家名称的大写),以便正确执行左连接。

来源:作者
一旦这样做了,你就可以打开一张空白纸,画出你的图表。我在下面分享我的图表,但是你可以根据你自己的喜好随意发展它!
在下面的视图中,你可以画出基尼指数与每个国家每 100 万居民新冠肺炎病例总数的散点图。您可以给图上的每个点涂上颜色,以标出该国的大陆,并根据每个国家的人口来确定点的大小。
然后,您可以使用日期列过滤感兴趣的相关时间段的数据(您还可以过滤掉任何偶然的空值)以及特定洲的数据。

来源:作者
你现在已经画出了图表的基础。为了增加交互性,您可以使用 Pages shelf 来分解该时间段内每一天的散点图(表示 shelf 中的单个“页面”),从而分析相关性如何随时间发展。为了跟踪页面名称(在这种情况下,它实际上是您在页面架的特定框架的图表上看到的日期),您可以添加一个注释来可视化每个散点图框架的日期细分。
为此,右键单击图表上的任意位置,转到“批注”>“区域”>“插入”>“页面名称”;完成后,您还可以根据自己的喜好设置注释的格式。
因此,Pages 搁板是制作图表动画的绝佳方式。这样做会导致以下结果:
来源:作者
现在您已经通过 Pages shelf 绘制了图表并制作了动画,让我们看看如何将它转换为 GIF 文件格式。
步骤 2:录制动画
要记录由 Pages shelf 启用的 Tableau 动画,您可以使用您选择的任何屏幕记录器来视频捕捉图表随时间的发展。我个人使用 MangoApps 的tiny take,但是在这里可以根据你的个人喜好随意选择。使用它,您可以选择屏幕的一部分来录制动画的简短视频。这就是这一步的全部内容!现在,您可以在本地保存您的视频文件,并进入第 3 步,在这里您将把它转换成 GIF!

来源:作者
第三步:将视频转换成 GIF
在这最后一步,你最终把你的视频文件(MP4,WebM,AVI,MPEG,FLV,MOV,3GP 和其他视频文件)转换成 GIF 文件格式。
一个我觉得很方便的在线工具是ezgif.com,它允许你对你的视频进行不同的、有用的编辑。
你可以快速上传你的录像到他们的视频到 GIF 转换器页面。然后你可以调整视频的开始时间、结束时间、大小和帧速率,这些将决定 GIF 运行的最终长度和循环次数。

来源:作者

来源:作者
在这一步之后,最后一个有用的调整是利用网站的速度转换器,让你的 GIF 循环更快和/或更慢。
你现在可以下载并保存你的文件为 GIF 格式,并分享到你喜欢的任何地方!
你可能想在你的数据报告或仪表板、Power Point 演示文稿以及任何其他相关材料和/或网页上添加 GIF 风格,比如这个,我把我的 GIF 作为静态特色图像的简洁替代。
你完了!希望这些简短的步骤将有助于为你的 Tableau 作品增加一点 GIF 的乐趣和互动性。感谢阅读!
访问我的免费数据科学资源清单 这里
[## 通过我的推荐链接加入 Medium-Edoardo Romani
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
edo-romani1.medium.com](https://edo-romani1.medium.com/membership)
如何在新冠肺炎疫情时期重新开启经济
原文:https://towardsdatascience.com/how-to-reopen-an-economy-during-the-covid-19-pandemic-e93923163e03?source=collection_archive---------63-----------------------
试析佛罗里达州重新开放经济的尝试及其对其他州的启示

南佛罗里达州是令人惊叹的市中心场馆和原始海滩的所在地,但新冠肺炎相关的封锁使它们在今年夏天更难进入。图片来源:安东尼奥·库埃拉尔在 Unsplash 上拍摄
南佛罗里达是一个标志性的地方,充满了新鲜的海鲜餐厅,清澈的海滩和穿着宽松的人们。离开学校的暑假是一种享受——我可以整天和一群朋友在一起,在拉斯奥拉斯大道的商店和海滩上放松。
今年对佛罗里达人来说不幸的是,酒吧和海滩的封锁让这个夏天变得不那么令人兴奋,越来越大的压力迫使佛罗里达州的政治家们过早地重新开放。6 月 5 日,州长罗恩·德桑蒂斯开始了他的逐步重新开放计划的第二阶段,该计划旨在减轻病毒的威胁。整整三个星期后,佛罗里达州宣布,他们将重新关闭酒吧,因为新冠肺炎病毒的传播仍在以惊人的速度增长。上周新增病例高达 63,552 例,比截至 6 月 6 日的一周高出 8 倍多!
增加测试并不是案件数量增加的唯一原因
上周末,当我和哥哥在门廊上享用着当地酿造的卡罗莱纳 IPA、一种佛罗里达葡萄柚和 90%黑巧克力,享受着一次远离社交的聚会时,我们争论着病例数量的增加是病毒真正传播的结果,还是增加检测的孤立影响。
我们同意可能会有一些上升,但由于测试的可用性一直在不断上升,真实的死亡率仍然难以捉摸。第二天早上,我在约翰·霍普斯金数据仪表板上做了一些研究,发现了一个奇怪的现象——阳性检测率上升到了 20%,几乎是 5 月低点的四倍!

佛罗里达州在 6 月份大力加强了新冠肺炎检测,但阳性检测率却出现了无法解释的增长。归功于约翰·霍普斯金的。来源:COVID 跟踪项目
在某些情况下,初始关闭期间,阳性测试率稳定地徘徊在 5-10%左右。在这个初始阶段,由于检测短缺,只对极有可能的病例进行检测,这导致了相当高的阳性检测率,约为 11%。孤立地看,让大众更容易接受检测应该会继续降低阳性检测率,但显然还有其他变量在起作用。
这种病毒正在所有年龄组中传播
大多数积极的测试结果是由 50 岁以下的人驱动的,这是一个低风险的人群,他们更有可能仍然在飞机上旅行,在室内餐厅就餐和在酒吧社交,甚至可能没有蒙面。这个群体的死亡率是 5 月份新增病例的 0.25%,所以他们如此自信地恢复正常生活是有道理的。

在过去的几周里,所有年龄组的病例数量都增加了。来源:佛罗里达 DOH;点击查看互动图表
不幸的是,低风险人群并不是生活在真空中,更脆弱的人群也在以惊人的速度被感染。自阵亡将士纪念日周末以来,新的每周感染人数在 50-70 岁人群中增加了 11.5 倍,在 71 岁以上人群中增加了 7.9 倍!
这种病毒仍然非常危险
正如我们从 3 月份以来所看到的,死亡率与病例数量成反比。进行的测试越多,确诊的病例越多,死亡率就越低。这听起来像是好消息,但是还不清楚是病毒越来越弱还是我们越来越擅长治疗它。更有可能的是潜在数据的变化。

6 月份观察到的死亡率继续下降,但不一定表明 7 月份继续下降。来源:佛罗里达州卫生部;点击查看互动图表
观察到的死亡率的下降实际上具有误导性,因为更严格的社会距离标准、免疫缺陷个体更加谨慎以及病例检出率的增加导致了行为的特定变化。
然而,过去死亡率的下降并不是未来死亡率将继续下降的指标。行为上正在发生的变化可能会再次扭曲受感染的人群:佛罗里达州的许多不同场所重新开放,现在仍然开放,对社会隔离和积极信号的疲劳可能会导致一些人取消预防措施,每周新病例创下历史新高,阳性检测率几乎是 4 月份高点的两倍。更不用说,如果严重病例的激增过快地填满医院,有限的医疗能力可能会使病人的结果更糟。
这一切都好说,病毒还是很危险的。为了根据今天的病例数量预测死亡人数,我建立了两个主要假设:未来死亡率和死亡滞后时间。
假设#1:未来死亡率
自 4 月份以来,观察到的 60 岁以上人口的死亡率下降了一半以上,50 岁以下人口的死亡率几乎保持不变。然而,如上所述,新增病例的潜在人口统计数据的持续变化可能会推动死亡率上升,也可能会降低死亡率。
最终,只有时间能证明一切,我不会试图在这里做出复杂的预测。对于本分析中的基线预期,我选择假设死亡率等于 6 月前 3 周每个年龄组的平均死亡率。
假设#2:报告的死亡延迟时间

来源: Covid 跟踪
虽然病例数量的增加预示着一场迫在眉睫的危机,但在医院不堪重负和意大利式的大规模葬礼发生之前,这不是一场真正的危机。在预测佛罗里达何时会真正感受到今天更高的案件数量的后果时,将这一变量作为基础是至关重要的。
平均而言,受感染的患者在症状出现后大约 14 天死亡,直到他们死亡后 7 天才被报告。这些指标也有大量的可变性(例如,一些死亡在死亡后 21 天才被报告),但为了简单起见,我假设所有新病例的固定总滞后时间为 21 天。
佛罗里达州不会经历意大利级别的危机,但…
使用基于上述的假设,佛罗里达州新冠肺炎相关死亡的严重性和时间的预测看起来很严峻。在截至 8 月 1 日的一周中,我的模型预测每周死亡人数为 880 人,即每 10 万人口中约有 4 人死亡。

据预测,到 8 月 1 日,每周死亡人数将翻两番,从 7 月 12 日的 266 人增至 880 人;点击查看互动图表
相比之下,在意大利最糟糕的一周,共有 5691 人死亡,约为每 10 万人口中有 9 人死亡。然而,尽管该州重新关闭已有两周,病例仍在增加。周日,佛罗里达州创下 15,300 例病例的新纪录,比之前 7 天的平均水平高出 66%。希望这是一个异常现象,但如果不是,佛罗里达州可能会发现自己陷入真正的危机比它讨价还价。
重启经济的经济学
关于世界各国政府是应该保持经济开放以保护 GDP,还是应该实施封锁以减少人员死亡,有两种难以置信的两极分化的观点。
许多人关注封锁的直接经济成本,因为它们更容易量化。但是衡量病毒给人类造成的损失也很重要。但是你如何衡量一个人生命的价值呢?你如何将这与封锁造成的 GDP 损失进行比较?信不信由你,政府已经悬赏捉拿你,我将采用现有的框架来衡量未来的最佳路径。
经济成本
2020 年第一季度美国 GDP 总量下降 4.8%(年化)。由于经济在本季度的前两个月运行平稳,估计 3 月份的封锁是这一下降的唯一驱动力。将这些指标外推到佛罗里达州,我假设每月保持完全封锁的经济成本等于其年度 GDP 的 5%,或大约 475 亿美元。
人力成本
你愿意为了经济而牺牲自己的生命吗?
我不这么认为。环境保护署利用统计生命框架的价值来衡量每个人的生命价值为 1000 万美元。这项措施是基于人们接受与特定工作相关的风险津贴的平均意愿。这一数值对所有人都是固定的,与性别、年龄、种族等无关。这种方法长期以来一直被用来确定一项特定法规的成本是否值得它所能挽救的生命。由于其与新冠肺炎难题的相关性,采用这一框架评估开放的总体经济影响是有意义的。

来源:彭博
在这个时候,佛罗里达州实际上可以采取三种不同的方案来决定该如何进行:
场景 A——重启“正常”经济:佛罗里达州开始走上这条道路。但由于它只持续了 3 个星期前,锁定恢复,这种情况已被证明是不切实际的。然而,我已经把它包括在我的分析中,以量化如果佛罗里达州电力通过,这将招致的总成本。
场景 B——向“低接触”经济转型:这是佛罗里达州在重新关闭酒吧和一些室内场馆后的现状,但这尚未被证明是一个可行的解决方案。目前还没有这方面的数据,但这种情况将假设损失的经济成本是全面封锁的一半,案件量将降至 5 月低点和当前高点之间的中点。
情景 C -恢复 4 月/5 月的封锁:这种选择对经济来说极其可怕,尤其是在不确定何时重新开放是安全的情况下。这种疫苗开始看起来像是摆脱疫情的最佳方式,但它可能还需要 6-18 个月才能开发和分发,更不用说最近的一项调查表明只有 50%的美国人会接种疫苗。

根据佛罗里达州处理新增病例数量的能力,截至 8 月底,每周死亡人数可能在 136 至 1254 人之间;点击查看互动图表
基于这些假设,经济上的最佳解决方案是在八月份过渡到低接触经济(见下表)。低接触经济将产生 575.6 亿美元的最低人力成本和 GDP 成本。最不可取的结果是经济恢复正常,因为这种情况下仅人力成本就将产生 1118.8 亿美元。
这两种情况下总成本的差异令人震惊,并要求优先考虑的顺序是首先减少病毒的威胁,然后重新启动经济。

恢复 5 月份实施的全面封锁将最大限度地减少死亡和 GDP 损失带来的负面经济影响;点击查看表格
我对一个严重两极分化的政治问题的非政治性结论
作为低风险人群中的一员,我理解失去工作或被自己的政府禁止与朋友一起喝酒而对我的福祉几乎没有风险是多么令人沮丧。但重要的是退一步,从整体上看待经济。匆忙回归“正常”经济可以让年轻人维持生计,而限制经济活动可以让老年人维持生活。上表反映了这两种后果的权重差异。我们必须要有耐心,因为在 T2 至少 70%的人口通过疫苗或传染病隔离产生抗体之前,这场健康危机不会得到解决。佛罗里达州已经证明,过早启动经济引擎可能会带来致命的后果,迫使他们已经踩下刹车,开始逆转。如果其他正在观望的国家要吸取什么教训的话,那就是谨慎行事。
对于那些对分析感兴趣的人,请随意查看我在 GitHub 上的代码。
如何更快重开,少受点苦
原文:https://towardsdatascience.com/how-to-reopen-faster-and-suffer-less-efac65a0af9a?source=collection_archive---------50-----------------------

估计不同的群体活动何时是安全的,病毒传播的不同下降率在 0.5 和 1 之间。美国大部分地区目前处于或高于 0.92。
当我在 Playdom 领导数据工程时,我使用高级疾病建模进行病毒式增长营销。这篇文章来自那个背景和我过去十年的工作【数据帮助做出更好的决策(在斯坦福、Playdom /迪士尼和绿色厨师)
随着新冠肺炎病毒的传播,患病和死亡人数的指数增长令许多人感到惊讶。这种疾病每隔几天就会增加一倍,多一周的无所作为意味着应对和急诊室超负荷之间的差异。
在美国,大部分讨论都集中在如何度过高峰期,以便病例和死亡人数开始下降。或者换句话说,让 R 小于 1。大多数州几乎没有做到这一步。
这篇文章有一个不同的焦点——它希望给你一个高层次的直觉,如果我们进一步减少传播会发生什么。0.5 到 1 之间的 R 值如何影响我们重新开放的速度?
正如比尔·盖茨指出的那样,“指数下降”比指数上升更不直观。减少一点传播有助于提前几个月重新开放,减少风险和痛苦。
指数下降的直觉
想象一个虚构的地方,上周有 1000 人死于新冠肺炎。如果措施持续抑制传播,那么每个感染者感染的新感染者就会减少,几周后,死亡率就会下降。
如果传播速度足够慢,从一周到下一周的死亡率是 0.5 倍,那么就会发生这种情况:

每周死亡人数和周间比率为 0.5 倍的累计死亡人数图表
从每周 1000 例死亡到 1 例死亡需要 10 周时间。
现在,让我们将 0.5 倍与其他三种周环比比率进行比较:

图表显示了四种不同的周与周之间的比率如何在时间上进行比较,以达到每周低于 1 例死亡和整个疫情期间的总死亡数。
比率的微小变化,尤其是略低于 1 倍的变化,会在时间和痛苦上造成很大差异。
关键外卖
指数下跌的不寻常之处在于,目标阈值是多少并不重要。无论是每周一人死亡还是一百人死亡,同样的直觉也适用:
- 0.71 倍需要两倍于 0.5 倍的时间达到阈值
- 0.84 倍耗时 4 倍
- 0.92 倍需要 8 倍的时间
美国现在在哪里?
在过去的一个月里,每个人都在减少传播方面做了出色的工作。尽管如此,超过一半的美国人生活在周周死亡率为 0.92 倍或以上的州。很少有州接近 0.5x。

截至 2020 年 5 月 3 日,各州死亡人数的周比,显示人口。来自约翰霍普金斯大学的数据。
看看主要的大都市地区,情况大致相同:

截至 2020 年 5 月 3 日,地铁死亡人数的周比,显示人口(对于人口超过 100 万的地铁)。数据来自约翰霍普金斯和维基百科。
我们什么时候能重新开业?
在美国,政策讨论的中心是如何重新开放。首先,社区需要足够的能力来检测和追踪每一个新病例,以防止新的疫情爆发。一旦这一点到位,社区将分阶段重新开放,首先从低风险的公共场所和商业开始,然后转移到高风险的商业。
降低传播率,使每周的病例和死亡减少一半,有助于我们更快地实现所有这些目标,减少人民和经济遭受的痛苦。
测试和跟踪能力
一组无党派专家估计,我们需要将联系人追踪能力提高 13 到 40 倍。我们还需要将测试能力提高 10 到 20 倍,以符合国际最佳实践。这使得检测有症状的人、检测无症状的接触者以及在人群中随机取样成为可能。
这是一项艰巨的任务。在整个 4 月份,我们只增加了 2 倍的测试。
不过还是有希望的,如果我们能减少感染人数,那么我们需要检测和接触的人就更少了。
让我们看看当案例以不同的速度下降时会发生什么。当测试和跟踪能力增加时,我们可以在测试和跟踪能力减少时绘制案例。一开始,假设我们需要 20 倍以上的容量:

该图表显示当测试和跟踪能力每月翻倍时,何时有足够的能力(星形)来处理不同下降率的案例。
改变下降速度很重要。0.5x 和 0.92x 之间的差异意味着在有足够的容量之前需要额外的两个月时间。
开办高风险业务
一个群体中的人数越多,某人被感染的风险就越高。这就是为什么重开一个有 12 个蹒跚学步的孩子的托儿所比一个有 1000 个音乐爱好者的音乐会场地风险更小。
下降率如何影响中等和较高风险企业何时可以开业?
这张图表显示了一个类似于纽约的地方,从每周每百万人 2000 例开始。病例会随着时间的推移而减少,当对一个群体安全时会越过水平虚线:

图表显示了在不同的群体规模和每百万人新增病例下降率下,群体中有人被感染的几率低于 0.1%的情况
这是加州或德克萨斯州的图表,从每周每百万人 200 例开始:

对于达到 0.5 倍比率的社区,餐馆等企业在 1-2 个月内变得相对安全。
对于比率保持在 0.84 倍以上的社区,餐馆、酒吧、教堂和健身房在秋季仍有风险。
要查看美国一个州或主要城市的风险图表和下降率趋势,请查看 Tableau Public 上的这个仪表盘。
我的社区能做什么?
社会距离有效地减少了整个美国的传播,因此在大约一半的州,病毒不再增长。但我希望这篇文章能说明为什么我们做得还不够。更显著地减少每个 COVID 阳性患者感染的人数意味着我们可以更快、更安全地重新开放,同时也拯救了生命。
即使各国考虑缓解社会距离的最具破坏性的方面,它们也应该采取尽可能多的步骤来进一步减少传播。
有许多有效且破坏性较小的步骤,例如
- 测试和接触追踪是否足够
- 在公共场所戴口罩
- 确保重要员工拥有安全的工作环境
- 帮助弱势群体保持社会距离
- 继续避免有传播风险的活动
对于正在发生疫情的社区来说,“过了高峰期”是不够的。
疾病预防控制中心指南建议“14 天内记录病例的下降轨迹”是一个很好的开始,但我们可以做得更好。如果我们能够每周将病例和死亡人数减少一半,将会有足够的检测和追踪能力,我们可以更快地重新开放。
如果这篇文章对你有帮助,请分享。
更好的是,把这个分享给那些决定你的社区减少了多少传播的人。
旁白:关于 R 的复制数
最近一周,关于 R 的讨论很多( NYT 、《卫报》、 BBC 、金融时报)。r 是描述疾病模型中传播率的模型化量。这是不可直接测量的,但它导致了可测量的数量,如病例、住院和死亡的周比。
像 Rt.live 和 Epiforecasts.io 这样的网站试图模拟美国的生育数量。
为新冠肺炎建模很难,因此本文主要关注我们可以在公开数据中看到的可测量的数量。这里所有关于周环比和指数下降的直觉也适用于 r。
当 R 远高于 0.7 时,大多数欧洲和美国现在正计划重新开放。这种策略与将 R 保持在 0.5 以下直到极少情况的方法形成对比。这是几个亚洲国家使用的方法。
关于数据
关于美国各州和大都市死亡率下降的数据来自约翰霍普金斯新冠肺炎 Github repo ,最低限度处理以修复历史数据不一致(例如,从报告确诊死亡到可能死亡的变化)。
如何表示 3D 数据?
原文:https://towardsdatascience.com/how-to-represent-3d-data-66a0f6376afb?source=collection_archive---------6-----------------------
3D 创意
帮助在 3D 点云、网格、参数模型、深度图、RGB-D、多视图图像、体素中选择数据表示的可视化指南……

3D 点云数据集的不同数据表示
我们的计算机化生态系统中的 3D 数据集——其中越来越多的数据集直接来自现实捕捉设备——以不同的形式存在,在结构和属性上都有所不同。有趣的是,由于它的规范性质,它们可以以某种方式成功地映射到点云。当绑定将云指向应用程序时,本文提供了主要的 3D 数据表示模式供您选择。
三维点云

这是 2014 年使用摄影测量学(Gerpho)获得的一座修道院的 3D 点云,位于我的家乡法国南部🙂。分辨率为 1 cm,表示为地面采样距离。
点云是三维坐标系中的一组数据点。这些点在空间上由X, Y, Z坐标定义,通常代表一个对象的包络。现实捕捉设备获取外部表面的三维信息以生成点云。这些通常是通过摄影测量(上面的例子)、激光雷达(陆地激光扫描、移动制图、下面模拟的空中激光雷达)、深度传感以及最近通过生成式对抗网络的深度学习来获得的。

航空激光雷达模拟点云。从自上而下的感知来看,这主要是 2.5D。
每种技术都有几个影响数据质量和完整性的特性,您已经可以看到完整 360°捕获与传统航空激光雷达采集之间的差异。这扩展了本文的范围,将在另一期或 3D 地理数据学院的信息中讨论:
[## 点云处理在线课程- 3D 地理数据学院
编队学习先进的点云处理和三维自动化。开发新的 python 地理数据技能和开源…
learngeodata.eu](https://learngeodata.eu/point-cloud-processor-formation/)
点云提供了简单而有效的 3D 数据表示,下面我总结了它们的主要操作、优点和缺点。
主要经营
- 变换:可以用线性变换矩阵乘以点列表中的点。
- 组合:“对象”可以通过合并点列表来组合。
- 渲染:将点投影并绘制到图像平面上
主要好处
- 快速渲染
- 精确表示
- 快速转换
主要缺点
- 无数的点(obj。曲线,精确表示)
- 高内存消耗
- 有限组合操作
虽然快速渲染和转换使直接检查点云变得很方便,但它们通常不能直接集成到常用的三维应用程序中。然而,最近的发展显示了一种趋势,即使在纯基于网格的渲染平台中也有更好的支持,最近的一个例子是虚幻 4 游戏引擎。
一个常见的过程是使用合适的表面重建技术来导出网格。有几种将点云转换成三维显式表面的技术,其中一些将在下面的文章中介绍。
[## 使用 Python 从点云生成 3D 网格的 5 步指南
生成 3D 网格的教程(。obj,。ply,。stl,。gltf)自动从三维点云使用 python。(奖金)…
towardsdatascience.com](/5-step-guide-to-generate-3d-meshes-from-point-clouds-with-python-36bad397d8ba)
让我们进一步深入 3D 模型作为一种表示,以更好地把握可能性的范围。
3D 模型
几乎所有的 3D 模型都可以分为两类。
- 固体:这些模型定义了它们所代表的物体的体积。实体模型主要用于工程和医学模拟,通常由构造性实体几何图形或体素集合构建。

通过体素化的实体 3D 模型示例。
- 壳或边界 (B-Reps):这些模型代表表面,即物体的边界,而不是它的体积。几乎所有在现实捕捉工作流、游戏和电影中使用的视觉模型都是边界表示。

修道院的贝壳代表的例子。
实体和壳建模可以创建功能相同的对象。它们之间的差异主要是创建和编辑它们的方式的变化,以及在各个领域中使用的惯例,以及模型和现实之间近似类型的差异。
三种主要策略允许通过 3D 模型描述点云。构造实体几何图形、隐式曲面(+参数化建模)和边界表示(B-Reps)。虽然构造性立体几何非常有趣,我们将很快讨论,但最常见的 3D 模型是 B-Reps 作为 3D 网格。让我们首先扩展这些论点。
三维网格
网格是一种几何数据结构,它允许用一组多边形来表示曲面细分。网格在计算机图形学中特别用于表示曲面,或者在建模中用于离散化连续或隐式曲面。网格由顶点(或顶点)组成,通过边连接,形成多边形的面(或小平面)。当所有的面都是三角形时,我们称之为三角形网格。这些是现实捕捉工作流中最常见的。

从上到下:网格的顶点;将顶点连接在一起的边;由顶点和边形成的面填充,大多是三角形。
四边形网格也非常有趣,但通常通过网格优化技术来获得更紧凑的表示。也可以使用体积网格,它通过四面体、六面体(长方体)和棱柱连接顶点。这些所谓的网格是基于边界表示的,这取决于线框模型(对象由 3D 线简化,对象的每条边由模型中的一条线表示)。让我们扩展这个理论。
边界表示法
3D 模型的边界表示主要由两部分组成:拓扑(元素的组织)和几何(曲面、曲线和点)。主要的拓扑项目是面、边和顶点,我在一个立方体的简单 B-Rep 下面进行了图解。

结构下边界表征的图式化
作战
- 变换:所有的点都像线框模型一样进行变换(将点列表中的点与线性矩阵相乘),此外,还可以变换曲面方程或法向量。
- 组合:可以通过将点列表和边分组来组合对象;对多边形的操作(根据交点进行分割,删除多余的多边形,合并它们…
- 渲染:可以使用隐藏表面或线算法,因为对象的表面是已知的,因此可以计算可见性。
好处
- 被广泛采用的表示法
- 通过“新一代扫描”生成模型
- 转换既快速又简单
缺点
- 高内存需求
- 昂贵的组合
- 弯曲的物体是近似的
网格是显示点云几何图形的一种很好的方式,并且通常允许大大减少作为顶点的所需点的数量。最重要的是,它允许通过面的连通性来了解对象之间的关系。然而,网格化是基点云几何的插值,并且只能在一定程度上表示数据,与网格的复杂性相关联。存在多种策略来最佳地网格化点云,但是这通常需要有一些理论背景,并且知道调整哪个参数来获得最佳结果。

点云的 2.5D Delaunay 三角剖分示例。
基于体素的模型
体素可被视为可用于表示 3D 模型的 3D 基本立方体单位。它的 2D 类比是像素,最小的栅格单位。因此,基于体素的模型是“3D 像素”的离散化组合,通常与实体建模相关联。

在点云数据的情况下,可以将每个点表示为大小为x的体素,以获得点之间空白空间的“填充”视图。它主要与八叉树等数据结构相关联,并允许根据所需的细化级别对每个体素单位的一定数量的点进行平均(参见下图中的示例)。这非常有趣,我将在另一篇专门的文章中讨论理论和实现。

基于由点云数据占据的空间的八叉树细分的体素一般化的例子。
虽然这对于渲染和平滑可视化是实用的,但是它近似于初始几何形状,并且伴随有混叠伪影,并且如果不恰当地使用体积信息,则可能给出错误的信息。然而,由于体素模型的非常结构化的网格布局,它可以非常方便地用于处理任务,例如通过 3D 卷积神经网络进行分类。
参数模型(CAD)
“参数化”用于描述通过将参数设置为修改基础几何图形的目标值来改变形状的能力。例如,如果您想通过设置“墙”的方向、长度、宽度和高度来对其建模,这将非常方便。

通过交互设置参数来创建 BIM 模型(建筑信息建模)的墙建模示例
然后,参数化建模适合于使用计算能力,该计算能力可以以真实世界的行为为目标对组件属性进行建模。参数化模型使用基于特征(参数化,如后面部分所述)、实体和曲面建模的组合,以允许操纵模型的属性。

这是一个自动生成的 CAD 模型,没有拓扑修复。
参数化建模的一个最重要的特性是,相互链接的属性可以自动更改值。换句话说,参数化建模允许定义整个“形状类别”,而不仅仅是特定的实例。然而,这通常需要底层点云几何的非常“智能”的结构化,以将模型实体分解成聚集在类中的子实体(例如,段)。

在这篇获奖的开放存取文章【0】中描述了自动分段的例子
这个过程极大地受益于对象检测场景和智能点云基础设施,如下文所定义。
[## 三维点云的未来:一个新的视角
被称为点云的离散空间数据集通常为决策应用奠定基础。但是他们能不能…
towardsdatascience.com](/the-future-of-3d-point-clouds-a-new-perspective-125b35b558b9)
通常,这些参数模型也可以通过组合插入点云形状的 2D CAD 绘图来组合或提取,并根据元素的类别对其进行分层。

分层前来自初始点云的几个原始 CAD 截面的示例。
这些参数模型的创建通常很费时,但却是给 3D 点云数据带来最大价值的模型。这些来自大量的语义丰富和对构成场景的物体之间的关系的额外触发。
深度图
现在,我们跳到基于光栅的点云表示。第一个是深度图。

基于俯视图的点云深度图
深度图是图像或“图像通道”,其包含与从单个视点构成场景的点的距离相关的信息。虽然我们习惯于处理 RGB 图像,但表达深度的最简单形式是在一个通道上用颜色编码,并带有强度值。亮像素具有最高值,暗像素具有最低值。就是这样。深度图像只是根据物体有多远来呈现值,其中像素颜色给出了离相机的距离。
💡 提示: 深度图与 Z-buffer 有关,其中“Z”与相机的中心轴方向有关,与绝对 Z 场景坐标无关。
如果您只需要链接到已知视点的表面信息,这种形式的点云表示就可以了。这是自动驾驶场景的情况,其中您可以通过 360°投影深度图非常快速地绘制每个位置的环境。然而,最大的不同是,你不是在处理 3D 数据,而是 2.5D 数据,因为你不能在视线上表示 2 个不同的值。下面是深度图的操作、优点和缺点:
操作
- 变换:用线性变换矩阵乘以图像中的像素
- 组合:可以通过合并点列表来组合对象。
- 渲染:在图像平面上绘制像素
好处
- 低内存需求
- 非常熟悉光栅格式
- 转换既快速又简单
缺点
- 本质上是 2.5 维的表现
- 无法单独描述完整的 3D 场景
- 弱拓扑
特例:RGB-D
第三,由于 RGB-D 传感器的普及,近年来将 3D 数据表示为 RGB-D 图像已经变得流行。RGB-D 数据通过将深度图与 2D 颜色信息(RGB)一起附加来提供关于捕获的 3D 对象的 2,5D 信息。

这是 RGB 光栅影像

这是相关的深度通道
除了价格低廉之外,RGB-D 数据还是 3D 对象的简单而有效的表示,可用于不同的任务,如身份识别[1]、姿态回归[2]和通信[1]。与点云或 3D 网格等其他 3D 数据集相比,可用的 RGB-D 数据集的数量非常庞大,因此是通过大量训练数据集训练深度学习模型的首选方式。
特例:预测
其次,将 3D 数据投影到另一个 2D 空间是原始 3D 数据的另一种表示,其中投影的数据封装了原始 3D 形状的一些关键属性[3]。

点云的大范围变形圆柱投影示例
存在多个投影,其中每个投影将 3D 对象转换成具有特定信息的 2D 网格。将 3D 数据投影到球形和圆柱形区域(例如[4])已经成为以这种格式表示 3D 数据的常见实践。这种投影有助于投影数据对于围绕投影主轴的旋转是不变的,并且由于所得投影的欧几里德网格结构,简化了 3D 数据的处理。然而,由于投影中的信息损失,这种表示对于复杂的 3D 计算机视觉任务不是最佳的,例如密集对应[5]。
隐性表征
现在,我们转到点云的较小的视觉组件:隐式表示。它只是一种通过一组形状描述符来表示点云的方法,如[6,7]中的文章所述。

基于颜色的点云垂直特征可视化
这些可以被视为 3D 形状的签名,以通过捕捉一些关键属性来提供 3D 对象的紧凑表示,从而简化处理和计算(例如,表示为. csv 文件)
x y z surface volume omn. ver.
9.9 30.5 265.3 334.5 103.3 4.6 0.0
-27.0 71.6 274.2 18.2 12.5 1.3 0.4
-11.8 48.9 273.8 113.2 620.4 3.7 0.7
26.9 43.8 266.1 297.1 283.6 3.9 0.0
42.9 61.7 273.7 0.1 0.0 0.3 0.8
-23.1 36.5 263.3 26.3 14.8 1.6 0.0
-9.5 73.1 268.2 24.0 11.4 2.2 0.0
32.2 70.9 284.0 36.0 139.1 1.7 0.8
-20.5 20.7 263.2 34.0 3.4 1.8 0.8
-2.3 73.6 262.2 28.2 15.6 2.6 1.0
该签名的性质和含义取决于所使用的形状描述符的特征及其定义。例如,全局描述符为整个 3D 形状提供了简明而信息丰富的描述,而局部描述符为形状中较小的小块提供了更局部化的表示。Kazmi 等人[6]、Zhang 等人[7]以及最近 Rostami 等人[8]的工作提供了关于这种 3D 形状描述符的综合调查。
作为处理管道的一部分,隐式表示非常方便,并且可以简化不同基础设施之间的数据传输。对于受益于难以直观表示的信息特征的高级流程,它也非常有用。
多视图

第五,我们可以从多视图图像中访问 3D 信息,多视图图像是基于 2D 的 3D 表示,其中通过匹配来自不同视点的同一物体的若干 2D 图像来访问信息。以这种方式表示 3D 数据可以导致学习多个特征集,以减少噪声、不完整、遮挡和照明问题对捕获数据的影响。然而,多少视图足以模拟 3D 形状的问题仍然是开放的,并且与摄影测量重建的获取方法相关联:视图数量不够少的 3D 对象可能无法捕捉整个 3D 形状的属性(尤其是对于 3D 场景),并且可能导致过拟合问题。体积数据和多视图数据都更适合分析变形最小的刚性数据。
机器学习和深度学习呢?
3D 数据对于构建机器学习系统,尤其是深度学习,有着巨大的潜力。然而,目前,关于另一种深度学习范例,需要考虑诸如 3D 网格的真实 3D 数据表示。
事实上,绝大多数深度学习都是在欧几里得数据上进行的。这包括 1 维和 2 维域中的数据类型。图像、文本、音频和许多其他数据都是欧几里得数据。其中,特别是 RGB-D 数据集,如果想要自动检测场景中的对象,现在能够建立在大规模标记库的基础上。但是网格或结构化的点云可以从利用它们丰富的潜在关系中受益。例如,这是通过将它们嵌入图结构(一种由与边(关系)连接的节点(实体)组成的数据结构)来实现的,但这使得它们是非欧几里德的(网格本质上是这样的),因此不可用于经典的机器学习架构。
为此,一个名为几何深度学习(GDL) 的新兴领域旨在建立可以从非欧几里得数据中学习的神经网络。
正如一位科学家同事 Flawnson Tong 在这篇推荐文章中所说的:
关系、联系和共有财产的概念是自然存在于人类和自然界的概念。从这些联系中理解和学习是我们理所当然的事情。几何深度学习意义重大,因为它允许我们利用具有内在关系、联系和共享属性的数据。
因此,每种 3D 数据表示都可以在机器学习项目中使用,但有些将用于更多的实验项目(非欧几里得表示),而欧几里得数据可以直接在您的应用程序中获取
结论
如果你一直读到现在,那么恭喜你😆!总之,3D 数据表示世界非常灵活,您现在已经掌握了选择数据表示的明智决策:
- 3D 点云简单高效但缺乏连通性;
- 作为 3D 网格、参数模型、体素组件发现的 3D 模型提出了专用级别的附加信息,但近似于基本数据;
- 深度图是众所周知的和紧凑的,但是本质上处理 2.5D 数据;
- 隐式表示包含了上述所有内容,但几乎不是可视化的;
- 多视图是互补的,并利用光栅图像,但在最佳视点选择的情况下容易失败。
和往常一样,如果你想超越,你会发现以下几个参考。您也可以今天就在地理数据学院开始卓越之旅。
[## 点云处理在线课程- 3D 地理数据学院
编队学习先进的点云处理和三维自动化。开发新的 python 地理数据技能和开源…
learngeodata.eu](https://learngeodata.eu/point-cloud-processor-formation/)
参考
0.波克斯,女;基于体素的三维点云语义分割:无监督的几何和关系特征与深度学习方法。 ISPRS 国际地理信息杂志 2019 , 8 ,213。
1.新泽西州埃尔多穆斯;Marcel,s.《2D 的欺骗:使用 3D 面具的人脸识别和使用 Kinect 的反欺骗》.《第六届国际生物统计学会议论文集:理论、应用和系统》(BTAS);IEEE,2013;第 1-6 页。
2.法内利公司;WeiseGall,j;来自消费者深度相机的实时头部姿态估计。 2011 ,101–110。
3.Houshiar,h.《3D 点云处理的文档和制图》,维尔茨堡大学,2012 年。
4.曹;黄;通过球形投影的三维物体分类。 2017 。
5.辛哈,a。白;使用几何图像深度学习 3D 形状表面。《欧洲计算机视觉会议论文集》(ECCV);2016 年德国阿姆斯特丹;第 223-240 页。
6.卡兹米,英国;你,我。和三维形状描述符的综述。第 10 届国际计算机图形学、成像和可视化会议录(CGIV);IEEE,2013;第 1-10 页。
7.申博士;福尔克斯,加州大学;像素、体素和视图:单视图三维物体形状预测的形状表示研究。 2018 。
8.罗斯塔米河;Bashiri,F.S .罗斯塔米湾;数据驱动的三维形状描述符综述。计算机图形学论坛 2018 , 00 ,1–38。
如何表现 2048 年的游戏状态
原文:https://towardsdatascience.com/how-to-represent-the-game-state-of-2048-a1518c9775eb?source=collection_archive---------21-----------------------
用极大极小算法玩 2048
以及如何以面向对象的方式实现它

作者图片
在关于解决这个游戏的上一篇文章中,我已经在概念层面上展示了如何应用极大极小算法来解决 2048 游戏。但是为了将这些想法付诸实践,我们需要一种方法来表示游戏的状态并对其进行操作。我选择以面向对象的方式,通过一个我命名为Grid的类来这样做。这个类保存游戏状态,并为我们提供进一步实现极大极小算法所需的方法(在下一篇文章中)。
如果你错过了我以前的文章,这里是:
[## 如何将 Minimax 应用到 2048 年
2048 年——一个简单的游戏,但是给计算机编程来解决它并不简单
towardsdatascience.com](/playing-2048-with-minimax-algorithm-1-d214b136bffb)
现在,让我们开始用 Python 实现Grid类。
在Grid类中,我们将游戏状态保存为一个矩阵,矩阵中有方块数,在有空方块的地方,我们将保存一个 0。在 Python 中,我们将使用一个列表列表,并将它存储到Grid类的matrix属性中。
这种表示法的一个例子如下所示:

作者图片
在我们的实现中,我们需要稍微传递一下这个矩阵;我们将从一个Grid对象获取它,然后用它实例化另一个Grid对象,等等。因此,为了避免通过引用传递它所带来的副作用,我们将使用deepcopy()函数,因此我们需要导入它。我们将导入的另一个东西是Tuple,以及来自typing的List;这是因为我们将使用类型提示。
from copy import deepcopyfrom typing import Tuple, List
我们可以从创建用于设置和获取类的矩阵属性的方法开始。然后我们将创建一个在棋盘上放置瓷砖的方法;为此,我们只需将矩阵的相应元素设置为瓷砖的编号。输入行/列参数是 1 索引的,所以我们需要减去 1;图块编号按原样分配。
然后我们将定义__init__()方法,它将只是设置矩阵属性。
对于 minimax 算法,我们需要测试Grid对象的相等性。当两个对象的矩阵相同时,我们将认为两个Grid对象是相等的,我们将使用__eq__()魔法方法来做到这一点。我们遍历 2 个矩阵的所有元素,一旦有不匹配,我们就返回 False,否则最后返回 True。
接下来,我们创建一个实用方法。这个方法评估我们的游戏网格“有多好”。对此可能有许多可能的选择,但是这里我们使用下面的度量(如前一篇文章中所述):对矩阵的所有元素求和,然后除以非零元素的数量。
下一段代码有点棘手。我们需要检查 Max 是否能做以下动作之一:上、下、左、右。每一步的代码都非常相似,所以我将只解释其中的一步:up,它是在.canMoveUp()方法中实现的。
当我们想做“向上”移动时,事情只能垂直变化。棋盘的不同列之间没有交互作用。因此,我们可以为每一列独立运行代码。

作者图片
我们可以在 for 循环中这样做:

作者图片
我们不一定需要检查所有的列。一旦我们遇到一个允许在“向上”移动中改变某些东西的列,我们就返回 True。如果没有这样的列,我们最后返回 False。

作者图片
对于每一列,我们执行以下操作:从底部开始向上移动,直到遇到一个非空(> 0)元素。在我们看到这样一个元素之后,我们如何知道一个“向上”的移动是否改变了这个列中的一些东西呢?有两种可能的情况会产生变化:要么有一个空方块可以移动,要么有两个相邻的相同的方块。
举个例子:


作者提供的图片
下面突出显示的代码负责查找最下面的非空元素:

作者图片
下面突出显示的这段代码一旦找到可以移动方块的空方块或两个方块之间可能的合并,就返回 True。

作者图片
下面是所有这些方法的代码,它们与.canMoveUp()方法的工作方式相似。
我们将需要一个方法,返回最大和最小的可用移动。对麦克斯来说,这是动作的子集:上,下,左,右。我们将这些移动表示为整数;每个方向都有一个相关的整数:
- 向上= 0
- 向下= 1
- 左= 2
- 右= 3
在.getAvailableMovesForMax()方法中,我们使用之前创建的方法检查我们是否可以在每个方向上移动,如果某个方向的结果为真,我们将相应的整数附加到一个列表中,我们将在方法结束时返回该列表。
.getAvailableMovesForMin()方法将返回网格上的空位置集和{2,4}集之间的叉积。该返回值将是(row,col,tile)形式的元组列表,其中 row 和 col 是空单元格的 1 索引坐标,tile 是{2,4}之一。
.getChildren()采用一个可以是“最大”或“最小”的参数,并使用前面两种方法之一返回适当的移动。这些是在极大极小算法的树中导致子游戏状态的移动。
对于极大极小算法,我们需要一种方法来确定一个游戏状态是否是终结的。正如我在上一篇文章中所说的,如果没有可用的移动,或者达到了一定的深度,我们将认为游戏状态是终结的。但是在极大极小算法内部检查深度条件会更容易,而不是在这个类内部。因此,通过.isTerminal()方法,我们将只检查最大值或最小值是否有可用的移动。一个简单的方法是使用.getAvailableMovesForMin()或.getAvailableMovesForMax()返回一个包含所有走法的列表,如果是空的则返回 True,否则返回 False。但是更有效的方法是,一旦我们“看到”一个可用的移动就返回 False,最后,如果没有返回 False,则返回 True。
.isGameOver()方法只是.isTerminal(who=”max”)的简写,它将在我们的游戏求解循环中用作结束条件(在下一篇文章中)。
下面的方法是用来上下左右移动的。这次我们实际做这些动作,不要只检查能不能做。每个移动方向的代码是相似的,所以,我将只解释向上移动。
每列都可以独立地向上移动。我们将有一个遍历列的 for 循环。对于每一列,我们将把变量w和k初始化为 0。w保存下一个写操作的位置。k存储最后遇到的非空单元格的平铺值。
该算法运行如下:

作者图片
下面是一个给定列的工作原理示例:

作者图片
下面是包含所有 4 种方法的代码:.up()、.down()、.left()、.right():
然后,我们围绕上述 4 个方法创建了一个包装器,并将其命名为.move(),它按照参数给定的方向移动。
我们需要的另一件事是移动的“逆”方法。.move()将方向代码作为参数,然后进行移动。现在,我们想要一个方法,它将另一个Grid对象作为参数,该对象被假定为对.move()的调用的直接子对象,并返回生成该参数的方向代码。我们将这种方法命名为.getMoveTo()。
这个方法的工作原理是创建当前对象的副本,然后依次调用这些副本上的.up()、.down()、.left()、.right(),并根据方法的参数测试是否相等。当等式成立时,我们返回适当的方向代码。
下面是Grid类的完整代码:
这就是本文的全部内容。在下一部(这是关于 2048 年和 minimax 的最后一部)中,我们将看到我们如何控制这款游戏的网页版游戏板,实现 minimax 算法,并看着它比我们玩得更好(…或至少比我好)。
[## 如何控制 2048 的游戏板
…并完成最小最大算法的实现
towardsdatascience.com](/how-to-control-the-game-board-of-2048-ec2793db3fa9)
我希望这些信息对你有用,感谢你的阅读!
这篇文章也贴在我自己的网站这里。随便看看吧!
如何使用 LSTM 重塑数据并对时间序列进行回归
原文:https://towardsdatascience.com/how-to-reshape-data-and-do-regression-for-time-series-using-lstm-133dad96cd00?source=collection_archive---------5-----------------------
逐步解释如何使用 LSTM 进行时间序列回归,包括多对多和多对一架构的输入整形。
在过去的几年里,一般的递归神经网络,特别是 LSTM,在许多数据科学从业者中变得非常流行。尽管 LSTMs 的主要应用是自然语言处理(NLP ),但对于计算科学家和工程师来说,LSTMs 为数据中存在时间相关性的问题提供了创建强大回归模型的可能性。
你将学到什么
在本文中,您将学习如何:
- 重塑 LSTM 培训的输入数据
- 用 Keras 拟合 LSTM 时间序列数据
- 使用 LSTM 处理单变量和多变量数据集
输入数据形状混乱
撰写本文的主要原因之一是,在 Keras 等神经网络框架中,您需要以 3D 格式提供 LSTM 输入数据,这可能会让许多人感到非常困惑。更令人困惑的是 Keras 中输入维度的命名方式。 根据文档和源代码,Keras LSTM 输入数据的格式必须为:[batch_size,timesteps,input_dim]。 此外,可能不需要指定 batch_size。令人困惑。我知道。让我们看看如何将我们的 1D 和 2D 数据改造成 3D 数据形状,以便 LSTM 能够工作!
LSTM 架构以及与输入数据形状的关系
在开始数据重塑之前,让我们回顾一下存在哪些 LSTM 架构。我们来看下图:

图 1—http://karpathy.github.io/2015/05/21/rnn-effectiveness/ LSTM 网络架构(来源—)
我们不会逐一介绍。在我看来,对于时间序列问题,最有用的是多对一和多对多(图 1 中的最后一个),所以我们将更详细地讨论它们。
在 Keras 中,时间步长的数量等于 LSTM 单元的数量。这就是单词“时间步长”在形状的 3D 张量中的含义[batch_size,time steps,input_dim]。
为了更好地理解这一点,让我们考虑一个玩具(完全随机)数据集,如图 2 所示。在数据集中,我们有 2 个特征和 6 个时间步长(因为我们使用 Python,所以我们从 0 开始计数)。
首先,考虑多对一的例子。
在这种情况下,Keras 希望我们对数据进行整形,以便根据指定数量的先前和当前时间步长特征来计算时间步长 t 处的预测。 在右图所示的 LSTM 架构中,时间步数设置为 3。

图 2 —多对一架构示例
要素的数量等于 2D 数据集中的要素数量。因此,shape [batch_size,timesteps,input_dim]的 3D 张量中的单词“input_dim”表示原始数据集中的要素数量。在我们的例子中," input_dim"=2
为了将我们的原始 2D 数据整形为 3D“滑动窗口”形状,如图 2 所示,我们将创建以下函数:
def lstm_data_transform(x_data, y_data, num_steps=5):
""" Changes data to the format for LSTM training
for sliding window approach """ # Prepare the list for the transformed data
X, y = list(), list() # Loop of the entire data set
for i in range(x_data.shape[0]):
# compute a new (sliding window) index
end_ix = i + num_steps # if index is larger than the size of the dataset, we stop
if end_ix >= x_data.shape[0]:
break # Get a sequence of data for x
seq_X = x_data[i:end_ix]
# Get only the last element of the sequency for y
seq_y = y_data[end_ix] # Append the list with sequencies
X.append(seq_X)
y.append(seq_y) # Make final arrays
x_array = np.array(X)
y_array = np.array(y) return x_array, y_array
形状的 3D 张量中的 batch _ size【batch _ size,timesteps,input_dim】可能不需要指定,可以指定只是为了加速训练过程。
现在,让我们看看我们需要如何为多对多 LSTM 模型重塑数据。为此,请看图 3。这里,我们有 2 个特征,数据集中的 6 个时间步长和 LSTM 神经网络中的 3 个时间步长。因此,为了将 2D 数据转换成所需的 3D 张量,我们可以如下使用 Numpy 功能:
num_steps = 3
num_features = 2
x_shaped = np.reshape(x, newshape=(-1, num_steps, num_features))

图 3—多对多架构示例
现在,让我们考虑两个例子,这样我们就可以完全理解如何重塑数据,并使用多对一和多对多 LSTM 模型。在第一个例子中,我们将有一个正弦波的一维自回归模型,而在第二个例子中,我们将有一个包含 3 个特征的 2D 数据集。
1D 示例—正弦波的自回归模型
在这种情况下,我们要做的是使用指定数量的先前时间步长预测时间步长 t 处的函数值。首先,让我们生成数据。
x = np.arange(0, 200, 0.5).reshape(-1, 1)
y = np.sin(x).reshape(-1, 1)
假设我们想要使用 sin 波的前 10 个时间步长来预测 sin 函数的下一个值。然后,为了将 LSTM 用于此任务,我们使用已经定义的函数来转换数据:
num_steps = 10
x_new, y_new = lstm_data_transform(y, y, num_steps=num_steps)
print ("The new shape of x is", x_new.shape)The new shape of x is (390, 10, 1)
请注意,我们为函数的 x 和 y 参数都传递了 y,因为我们想要创建一个自回归模型。
太好了!现在,我们有了 LSTM 形状,这应该对我们有用。接下来,我们分割数据集,80%用于模型训练,20%用于模型测试。
train_ind = int(0.8 * x.shape[0])
x_train = x_new[:train_ind]
y_train = y_new[:train_ind]
x_test = x_new[train_ind:]
y_test = y_new[train_ind:]
最后,我们定义一个简单的 Keras 模型并训练它!
model = Sequential()
model.add(LSTM(100, activation='tanh', input_shape=(num_steps, 1),
return_sequences=False))
model.add(Dense(units=50, activation='relu'))
model.add(Dense(units=1, activation='linear'))
adam = optimizers.Adam(lr=0.0001)
model.compile(optimizer=adam, loss='mse')
model.fit(x_train, y_train, epochs=20)
然后在测试集上进行预测:
test_predict = model.predict(x_test)
plt.style.use('ggplot')
plt.figure(figsize=(20, 7))
plt.plot(y_test, label="True value")
plt.plot(test_predict.ravel(), label="Predicted value")
plt.legend()

图 4。—用于估计正弦波的多对一 LSTM 模型结果
我们得到了一个很好的 sin 函数!这为您提供了一个如何将 1D 数据重塑为 3D 数据以创建多对一架构的 LSTM 模型的示例。 注意,这里我们做了一个自回归模型,把 y 放在“lstm_data_transform”的 x_data 和 y_data 两个输入上。请随意将您的要素数据转换为 x_data,这样它会将 x_data 转换为所需的形式。
2D 示例——通过节流阀的流量
在这个例子中,我们将考虑有 3 个特性和 1 个目标变量的情况,并将使用多对多和多对一架构。目标变量是通过阻风门的流量。如果您对该流程一无所知,请不要担心,这只是一个说明性的示例,该概念将完全适用于手头的任何问题。
让我们看看数据帧的开头。在“特征”中,我们有节流器前的压力(P_WHCU)、节流器后的压力(P_WHCD)和节流器开口(0 到 1 之间的值)。因此,我们有 3 个特征和 1 个目标变量,即通过节流器的流量。

资料组
在数据集中,我们有 6570 个点。像以前一样,80%用于培训,20%用于测试。最初,我还使用应用于训练数据的标准缩放器来重新缩放数据,并转换训练和测试数据。
拆分:
train_ind = int(0.8 * x_data.shape[0])
x_train = x_data[:train_ind]
x_test = x_data[train_ind:]
y_train = y_data[:train_ind]
y_test = y_data[train_ind:]
缩放:
# scalers
scaler_x = StandardScaler()
scaler_y = StandardScaler()
# scaling
x_train_sc = scaler_x.fit_transform(x_train)
x_test_sc = scaler_x.transform(x_test)
y_train_sc = scaler_y.fit_transform(y_train)
y_test_sc = scaler_y.transform(y_test)
多对多培训
假设我们想要使用 3 个先前的时间步长特征来预测通过节流器的流量的当前值。首先,我们按如下方式重塑数据:
num_steps = 3
# training set
x_train_shaped = np.reshape(x_train_sc, newshape=(-1, num_steps, 3))
y_train_shaped = np.reshape(y_train_sc, newshape=(-1, num_steps, 3))
assert x_train_shaped.shape[0] == y_train_shaped.shape[0]
# test set
x_test_shaped = np.reshape(x_test_sc, newshape=(-1, num_steps, 3))
y_test_shaped = np.reshape(y_test_sc, newshape=(-1, num_steps, 3))
assert x_test_shaped.shape[0] == y_test_shaped.shape[0]
“newshape”参数的最后一个参数等于 3,因为我们有 3 个特征。
现在,我们编译这个模型。请注意,对于多对多模型,我们需要使用 return _ sequences = True:
model = Sequential()
model.add(LSTM(20, activation='tanh', input_shape=(num_steps, 3), return_sequences=True))
model.add(Dense(units=20, activation='relu'))
model.add(Dense(units=1, activation='linear'))
adam = optimizers.Adam(lr=0.001)
model.compile(optimizer=adam, loss='mse')
拟合模型并根据测试数据进行预测:
model.fit(x_train_shaped, y_train_shaped, epochs=10)
test_predict = model.predict(x_test_shaped)

图 5-节流流量的多对多估计结果
我们看到,预测是好的,除了一些波动行为,这可能是由过拟合引起的,并通过更好的模型训练来减少。现在,让我们考虑相同的数据集,但采用多对一架构。
多对一培训
和以前一样,我们需要重塑我们的数据,但现在我们需要使用预建的函数:
num_steps = 3# training set
(x_train_transformed,
y_train_transformed) = lstm_data_transform(x_train_sc, y_train_sc, num_steps=num_steps)
assert x_train_transformed.shape[0] == y_train_transformed.shape[0]# test set
(x_test_transformed,
y_test_transformed) = lstm_data_transform(x_test_sc, y_test_sc, num_steps=num_steps)
assert x_test_transformed.shape[0] == y_test_transformed.shape[0]
之后,数据集就可以进行训练了。我们编译与多对多相同的模型。请注意,对于多对一模型,我们需要使用 return _ sequences = False:
model = Sequential()
model.add(LSTM(20, activation='tanh', input_shape=(num_steps, 3), return_sequences=False))
model.add(Dense(units=20, activation='relu'))
model.add(Dense(units=1, activation='linear'))
adam = optimizers.Adam(lr=0.001)
model.compile(optimizer=adam, loss='mse')
然后,我们拟合模型并对测试集进行预测:
model.fit(x_train_transformed, y_train_transformed, epochs=10)
test_predict = model.predict(x_test_shaped)

图 6-节流流量的多对一估计结果
如我们所见,我们得到了与多对多模型相似的拟合。然而,这是一个简单的数据集,对于许多问题,结果可能不同。
结论
在这篇文章中,我们考虑了如何使用 Keras LSTM 模型进行时间序列回归。我们展示了如何将 1D 和 2D 数据集转换为 3D 张量,以便 LSTM 适用于多对多和多对一架构。在多对多的情况下,我们可以使用 Numpy 功能,而对于多对一,我们需要使用转换函数。此外,对于多对多,Keras 参数 return_sequence 必须等于 True,而对于多对一模型,它必须等于 False。我希望这篇文章对你有用,它将允许你从现在起在研究和日常工作中更多地使用 LSTM 模型!
如何使用 Python 调整图像大小
原文:https://towardsdatascience.com/how-to-resize-images-using-python-8aaba74602ed?source=collection_archive---------13-----------------------
“可扩展”的技术

在 Unsplash 上由阿米拉里·米尔哈西米安拍摄的照片
可以肯定地说,每个“电脑人”都曾经需要调整图像的大小。MacOS 的预览版可以做到; Windows PowerToys 也可以。
如果你懂 Photoshop 或者 Gimp,那么你和我……我们不一样。命令行实用程序?好吧,现在我可以理解了。
幸运的是,图像处理和命令行工具是 Python 的两个专长。
本文旨在向您展示三件事:
- 什么是图像的基础知识。
- 用于处理图像的 Python 库。
- 您可以在自己的项目中使用的代码。
我们将要构建的命令行程序可以一次调整一个或多个图像文件的大小。
让我们跳进来吧!
创建图像
对于这个例子,我们将创建我们自己的图像,而不是找到一个真实的图像来操纵。
为什么?因为我不得不把事情复杂化,这就是原因!
事实上,创造我们自己的图像是一个很好的方式来说明图像到底是什么。这个调整大小的程序可以在 Instagram 上运行。
那么,什么是图像呢?在 Python 数据术语中,图像是整数元组列表的列表。
image = list[list[tuple[*int, float]]]
NumPy esque 定义将是一个 shape (h,w,4)的二维数组,其中h是高(上下)的像素数,w是横(从左到右)的像素数。
换句话说,图像是像素(单元)的列表(行)的列表(整个图像)。每个像素是一个由 3 个整数和 1 个可选浮点数组成的序列:红色通道、绿色通道、蓝色通道、alpha(可选的浮点数)。红色、绿色、蓝色通道(RGB)的值从 0 到 255。
从现在开始,为了简单起见,我们将讨论没有 alpha 通道的彩色图像。Alpha 是像素的透明度。图像也可以只有一个通道,其值从 0 到 255。这就是灰度图像,也就是黑白图像。但这是真实的世界…我们用彩色图像工作!
import matplotlib as plt
pixel: tuple = (200, 100, 150)
plt.imshow([[list(pixel)]])

从 Python 代码渲染的单个像素。
很性感。
用纯 Python 制作图像
Vanilla Python 完全能够创建图像。为了显示它,我将使用matplotlib库,您可以使用:
pip install matplotlib
创建像素:
创建图像:

这是渲染的图像。在幕后,数据看起来是这样的(对于 90x90):
[[[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[234, 162, 33],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[255, 0, 0],
[234, 162, 33],
...
现在我们有了一个图像,让我们开始调整它的大小!
在普通 Python 中调整大小
心理!我们将而不是用 Python 写一个调整图像大小的算法。
为什么?
TLDR:工作量太大了。
图像处理算法中有太多的东西。有些人把他们的生命奉献给了它。重采样——用缩小图像中的一个像素代替高分辨率图像中的许多像素——本身就是一个巨大的话题。如果你想自己看看,在path/to/site-packages/PIL安装 Pillow 的时候可以查看一下 Pillow 的源代码中的Image.py。
还有像抗锯齿和缩小差距这样的优化…这是无止境的。我们将站在巨人的肩膀上,这意味着相信计算机视觉领域的杰出工作,并无耻地调用一行程序来解决我们的问题。
如果您有兴趣了解更多关于处理图像时幕后发生的事情,我鼓励您更多地查看“机器视觉”主题!这绝对是一个蓬勃发展的领域,有比一个人有更多的时间去探索。
变得足够好,有一大群公司愿意为你的计算机视觉专业知识支付高价。自动驾驶、物联网、监控,应有尽有;都是从根本上依赖于处理图片(通常用 Python 或者 C++)。
一个很好的起点是查看 scikit-image 。
OpenCV
OpenCV 是图像处理的终极目标。OpenCV 是用 C++编写并移植到 Python 的,它运行在你自制的自动驾驶汽车的后备箱中,用于车道检测。
用于interpolation参数的选项是cv2包中提供的标志之一:
INTER_NEAREST – a nearest-neighbor interpolation
INTER_LINEAR – a bilinear interpolation (used by default)
INTER_AREA – resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
INTER_CUBIC – a bicubic interpolation over 4×4 pixel neighborhood INTER_LANCZOS4 – a Lanczos interpolation over 8×8 pixel neighborhood
这将返回:

它达到了我们的预期。图像从 900 像素高、900 像素宽变成了 450 X 450(仍然是三个颜色通道)。上面的截图看起来不太好,因为朱庇特实验室的matplotlib着色。
枕头
pillow库在Image类上有一个调整大小的方法。它的论据是:
size: (width, height)
resample: Defaults to BICUBIC. A flag for the resampling algorithm.
box: Defaults to None. A 4-tuple defining a rectangle of the image to work on within parameters (0, 0, width, height).
reducing_gap: Defaults to None. A resampling optimization algorithm to make the output look better.
在这里它是为我们的目的而设的一个函数:
使用 Pillow 的功能与 OpenCV 非常相同。唯一的区别是PIL.Image.Image类有一个属性size来访问图像的(width, height)。
结果是:

注意show方法如何打开操作系统的默认程序来查看图像的文件类型。
创建命令行程序
现在我们有了一个调整图像大小的函数,是时候用一个运行 resize 的界面来完善它了。
调整一个图像的大小是好的。但是,如果我们要经历所有这些麻烦,我们也需要批量处理图像的能力。
我们将要构建的界面将是最简单的:一个命令行工具。
托盘项目是 Flask(Jinja 模板引擎)背后的天才社区,与我们现在相关:点击。
pip install click
Click 是一个制作命令行程序的库。这比使用简单的argparse或者在if __name__ == '__main__':语句中加入一些 if-then 逻辑要好得多。因此,我们将使用点击来装饰我们的图像大小。
这是从命令行调整图像大小的完整脚本!
命令行程序从入口点函数main运行。参数由click.option装饰者传递给main:
pattern使用一个 Python / RE2 样式的字符串来定位相对于脚本运行目录的一个或多个图像。--pattern="../catpics/*.png"将向上一级并找到catpics文件夹,并返回该文件夹中带有.png图像扩展名的任何文件。scale接受一个浮点数或整数,并将其传递给resize函数。这个脚本很简单,这意味着没有数据验证。如果你添加代码,检查scale是一个介于 5 和 99 之间的数字(合理的缩小参数)。现在,你可以通过-s "chicken nuggets",直到 Pillow 停止程序才会抛出异常。quiet是一个选项参数,用于在程序运行时不希望文本打印为标准输出。
从命令行运行程序:
python resize.py -s 35 -p "./*jpg"
结果:
$ py resize.py -p "checkers.jpg" -s 90
resized image saved to checkers_90_810x810.jpg.
正在检查文件夹:
$ ls -lh checkers*
-rw-r--r-- 1 nicho 197609 362K Aug 15 13:13 checkers.jpg
-rw-r--r-- 1 nicho 197609 231K Aug 15 23:56 checkers_90_810x810.jpg
不错!所以程序缩小了图像,给了它一个描述性的标签,我们可以看到文件大小从大约 362KB 变成了大约 231KB!
为了看到程序一次处理多个文件,我们将再次运行它:
$ py resize.py --pattern="checkers*" --scale=20
resized image saved to checkers_20_180x180.jpg.
resized image saved to checkers_90_810x810_20_162x162.jpg.
和文件系统:
$ ll -h checkers*
-rw-r--r-- 1 nicho 197609 362K Aug 15 13:13 checkers.jpg
-rw-r--r-- 1 nicho 197609 1.8K Aug 16 00:23 checkers_20_180x180.jpg
-rw-r--r-- 1 nicho 197609 231K Aug 15 23:56 checkers_90_810x810.jpg
-rw-r--r-- 1 nicho 197609 1.8K Aug 16 00:23 checkers_90_810x810_20_162x162.jpg
好吧,递归运行这个程序只适用于疯狂的人,但是它表明你可以同时运行任意数量的匹配模式的图像。去吧,自动化!
奖金
点击是一个神奇的工具。它可以包装一个函数,并从一个
if __name__ == '__main__':语句“以正常方式”在一个模块中运行。(而实际上,它甚至不需要那个;你可以定义和修饰你想要运行的函数。)但是它真正的亮点是将脚本作为一个包安装。这是通过 Python 自带的
setuptools库完成的。这是我的
setup.py。
使用以下命令构建可执行文件/包装包:
*pip install -e .*现在你可以不使用
python命令来调用这个脚本了。另外——作为一个额外的奖励——如果你将新的可执行文件添加到路径中的一个文件夹中,你可以从你计算机上的任何地方调用这个程序,就像resize -p *jpg -s 75!
结论
本教程变化很大:首先浏览一些第三方 Python 库进行图像处理。然后使用 Python 从头构建一个图像,以更好地理解图像实际上是什么。然后,选择其中一个选项并构建一个脚本来缩小图像,同时保持它们的比例。最后—吸入——将所有这些都放在一个命令行实用程序中,使用click接受可配置的选项。
再多说几句我就完事了,我保证。
我只想说:我和你一起一口气谈完所有这些话题是有原因的。这个原因不是因为我有多动症。
是因为编程思路需要从想法到执行的闭环。关于如何用 Python 做一些事情的一次性概念是好的…但是归根结底,编程语言是一种工具。它需要帮助我们完成有价值的事情。
当你开始觉得教程“又一件你必须学的东西”压得你喘不过气来时,这意味着是时候放下阅读,开始为一些小项目编码了。一次就能完成的事情,感觉自己有进步。
记住,编写代码可能需要几个小时或几天的时间。然而运行只需要几毫秒。你做的程序不一定要大。你做的任何一件事,只要能节省你的时间或让你产出更多,都有可能让你受益终生!
资源
- 点击
- matplotlib
- opencv
- 枕头
- scikit-image
如何恢复您的 Jupyter 笔记本会话
原文:https://towardsdatascience.com/how-to-restore-your-jupyter-notebook-session-dfeadbd86d65?source=collection_archive---------19-----------------------
重新启动计算机时,不要丢失 Jupyter 笔记本会话中的进度。Dill 包可以保存笔记本会话供以后使用。

尼克·舒利亚欣在 Unsplash 上的照片
H 有没有发生过这样的事情,你重启了电脑,却忘记了你打算以后用的那个重要的 Jupyter 笔记本?“花了这么长时间才完成,现在一切都没了”。
我感觉到你了!在我身上发生过很多次。
好吧,我唯一能给你的建议就是“重启内核,重新运行所有的细胞”。但下次就不一定了。
有一个工具可以让您保存 Jupyter 笔记本会话的状态,并在以后用一个命令恢复它。
这里有几个你可能会感兴趣的链接:
- [Labeling and Data Engineering for Conversational AI and Analytics](https://www.humanfirst.ai/)- [Data Science for Business Leaders](https://imp.i115008.net/c/2402645/880006/11298) [Course]- [Intro to Machine Learning with PyTorch](https://imp.i115008.net/c/2402645/788201/11298) [Course]- [Become a Growth Product Manager](https://imp.i115008.net/c/2402645/803127/11298) [Course]- [Deep Learning (Adaptive Computation and ML series)](https://amzn.to/3ncTG7D) [Ebook]- [Free skill tests for Data Scientists & Machine Learning Engineers](https://aigents.co/skills)
上面的一些链接是附属链接,如果你通过它们进行购买,我会赚取佣金。请记住,我链接课程是因为它们的质量,而不是因为我从你的购买中获得的佣金。
如果你错过了我关于 Jupyter 笔记本的其他帖子:
[## 你还在用 JupyterLab 吗?
数据科学城推出了一款新的高端产品。它有优越的编码辅助,调试和更多…是吗…
towardsdatascience.com](/are-you-still-using-jupyterlab-ce1a4339c0a9) [## JupyterLab 2.0
让我们来一窥 Jupyter 笔记本编辑的未来。有了编码等特性,未来看起来一片光明…
towardsdatascience.com](/jupyterlab-2-0-edd4155ab897) [## 3 个必备的 JupyterLab 2.0 扩展
JupyterLab 刚刚成为一个成熟的 IDE,具有代码辅助、调试和 Git 等功能——欢迎来到未来……
towardsdatascience.com](/3-must-have-jupyterlab-2-0-extensions-41024fe455cc) [## 将 Jupyter 笔记本转变为电子书
将你的 Jupyter 笔记本转换成 PDF、EPUB 和 AWZ3 格式的精美电子书的一些技巧。不要花几个小时…
towardsdatascience.com](/transform-jupyter-notebook-to-an-ebook-ef3a9d32ac4f) [## 如何从 Jupyter 笔记本运行 SQL 查询
SQL IDEs 不能可视化数据。您知道吗,您可以使用…运行并可视化查询结果
towardsdatascience.com](/how-to-run-sql-queries-from-a-jupyter-notebook-aaa18e59e7bc)
遇见迪尔

使用 Dill 保存和恢复会话
Dill 使您能够保存 Jupyter 笔记本会话的状态,并通过一个命令恢复它。
安装 Dill 就像安装任何其他 Python 包一样简单:
pip install dill
要保存 Jupyter 笔记本会话,只需执行以下命令:
import dill
dill.dump_session('notebook_env.db')
要恢复 Jupyter 笔记本会话:
import dill
dill.load_session('notebook_env.db')
Dill 也使用 python 解释器会话。

Gif 来自 giphy
缺点
Dill 有一些你应该知道的缺点:
- 这种方法不适用于发电机。
- 保存的会话不包括生成的图形。所以你需要重新运行代码。
- 一些用户报告说,恢复会话在另一台计算机上不起作用。
关于莳萝
Dill 将 python 的 pickle 模块扩展到大多数内置 python 类型,用于序列化和反序列化 Python 对象。序列化是将对象转换为字节流的过程,其逆过程是将字节流转换回 python 对象层次结构。
Dill 为用户提供了与 pickle 模块相同的界面,还包括一些额外的特性。除了 pickling python 对象之外,Dill 还提供了在单个命令中保存解释器会话状态的能力。因此,保存解释器会话、关闭解释器、将标记的文件运送到另一台计算机、打开新的解释器、取消标记会话并因此从原始解释器会话的“保存”状态继续是可行的。
Dill 可用于将 python 对象存储到文件中,但主要用途是通过网络以字节流的形式发送 python 对象。Dill 非常灵活,允许序列化任意用户定义的类和函数。因此,Dill 并不旨在防止错误或恶意构造的数据。由用户决定他们提取的数据是否来自可信的来源。
主要特点
莳萝可以腌制以下标准型[1]:
- none,type,bool,int,long,float,complex,str,unicode,
- 元组、列表、字典、文件、缓冲区、内置、
- 新旧风格的课程,
- 新旧样式类的实例,
- 集合,冷冻集,数组,函数,异常
莳萝也可以腌制更多的“奇异”标准型[1]:
- 有收益的函数,嵌套函数,lambdas
- 单元格,方法,unboundmethod,模块,代码,methodwrapper,
- dictproxy,methoddescriptor,getsetdescriptor,memberdescriptor,
- wrapperdescriptor,xrange,slice,
- 未实现,省略号,退出
莳萝还不能腌制这些标准类型[1]:
- 框架、生成器、回溯
Dill 还提供了以下功能[1]:
- 保存和加载 python 解释器会话
- 从函数和类中保存和提取源代码
- 交互式诊断酸洗错误
参考文献
- [1]https://github.com/uqfoundation/dill
我的选择
莳萝无疑是你工具箱中的一个有用的工具。当我需要在另一个操作系统中重启我的计算机时,或者当我预计 Jupyter 内核可能会因为下一个命令而崩溃时,我会使用它。
IMO Dill 不是你应该在每个 Jupyter 笔记本中自动使用的工具。明智地使用它,只在你需要的时候。此外,如果任何底层代码使用了生成器,也要小心,因为还不能 pickle 它。
在你走之前
在 Twitter 上关注我,在那里我定期发布关于数据科学和机器学习的。

由考特尼·海杰在 Unsplash 拍摄的照片
Polygon.io 查看-检索历史刻度数据
原文:https://towardsdatascience.com/how-to-retrieve-historical-tick-data-from-polygon-71512f224b67?source=collection_archive---------11-----------------------
演练日内策略的分笔成交点数据 API 方法

来源:polygon.io 网站。经许可使用
在过去的几个月里,我的主要目标之一,也是最耗时的任务之一,是从分笔成交点数据中提取优势,用于日内操作。
在这种情况下,高质量的数据输入变得极为重要。我已经开始使用 Polygon.io 从 SPY 获取分笔成交点数据,因为我想测试我在过去几个月中学习的一套自主策略。这些策略旨在对期货进行操作,但我想评估它们是否适用于其他资产/工具,如间谍 ETF 和外汇工具。
本文涵盖了通过 REST API 检索历史数据。我还将简要介绍一下所涉及的数据量。
报价和交易
您需要理解的第一件事是,分笔成交点数据通常涉及两个独立的数据源。一个覆盖账簿的顶部,包括最佳买价和最佳卖价,另一个覆盖实际交易。在股票市场(SPY 是一种 ETF,但 ETF 是作为股票交易的),可以在不同的交易所进行交易。这意味着没有交易发生的中心点。美国目前有 13 家上市交易所。并非所有的资产都在每个交易所交易,但它们也不会只在一个交易所交易。还有暗池和私人交易所,机构玩家可以跨单,大型券商也可以在客户之间跨单。
这意味着单一、统一、连续和独特的报价和交易流的简化视图在现实世界中并不存在。
所有市场信息由证券信息处理器(SIPs)整合,SIPs 是受监管的实体,整合并提供统一的股票数据。它们定义了一套清晰而确定的交易合并规则。美国的两家运营中的 sip 是联合磁带协会 (CTA)和非上市交易特权 (UTP)。这些 sip 分别巩固了纽约证券交易所和纳斯达克上市的代码。关于它们如何工作的很好的信息可以在这篇博客文章中找到。
虽然这些信息对散户交易者来说并不重要(很少有人理解这些晦涩难懂的东西是如何运作的),但有几个重要的要点需要了解:
- 股票在不同的地方交易,所以它们不是完全集中的。你所看到的高质量的实时数据只是市场上实际发生的事情的一个像样的代理。
- 不同的时间戳在 SIP 和交换机处关联信息。它们与零售无关,但与交易的买价/卖价相关(如订单流和 Delta 分析所要求的)。
对于书的深度来说,情况是一样的,但是我不会去讨论它,因为现在我不会在我的任何策略中分析书的深度。
历史报价(NBBO 出价/要价)
为了获得历史报价,使用/v2/ticks/stocks/nbbo/{ ticker }/{ date }请求
可以通过它们的 REST API 接口从 Polygon 中检索历史数据。服务器将为每个请求提交最多 50,000 条记录。虽然 OHLC 每日数据的 50,000 条记录代表了 200 多年的股票市场历史,但这只是分笔成交点数据的每日数据量的一小部分。
URL 中包含基本的日期和报价器参数:
ticker:string, ticker name (i.e. SPY for SPDR S&P500 ETF)date:string, date in YYYY-MM-DD format. Notice that the API assumes Eastern Time by default, so 2020-06-15 means 2020-06-15 00:00 New York time.
经过长期(通常是痛苦的)时区工作后,我得出结论,一个简单且一致的方法是在 et 中存储和处理你所有的市场数据。它被广泛用作市场数据的参考时区(有时甚至用于欧洲资产/工具),也是金融市场的标志性时间参考(纽约证券交易所 RTH 开盘是每个人每天都可以观察到的事件)。这不适用于加密数据,因为它 24x7 全天候运行,当从夏令时切换到非夏令时时,您将面临问题。在这种情况下,建议使用 GMT。
API 在这里有完整的文档,但是我强调/评论以下参数。注意,这些被指定为 HTTP GET 参数,而不是 URL 的一部分。
timestamp:long value, represents the first epoch timestamp (with nanoseconds resolution) for which data is requested. timestampLimit:long value, represents the last epoch timestamp (with nanoseconds resolution) for which data is requested, provided that the hard limit of 50,000 (or the custom limit) is not reached first. Note that this timestamp is returned, so the value is included.limit:integer value, maximum number of records to be retrieved, 50,000 if not specified.apiKey:string, your API key, required in every request.
因为我们有 50,000 项的限制,所以需要执行分页。为了执行分页,我们将简单地使用时间戳参数。算法非常简单:如果我们收到 50,000 个条目,我们假设需要一个额外的请求,我们指定最近收到的时间戳作为下一个请求的参数。我们这样做,直到最后一个请求收到少于 50,000 个项目。这意味着没有更多的请求要做。
必须考虑三个具体细节:
- 将 timestampLimit 设置为第二天的 00:00 时间是个好主意。由于 API 将 timesetampLimit 作为有效的返回项,我们需要稍后从返回的结果中排除该值。
- 用于连续请求的时间戳被包含两次,因为它是第 n 和第 n+1 个请求之间的边界。因此,当计划一个 n+1 请求时,将其从 n 请求中移除是很重要的。
- 可能的情况是,我们收到 50,000 个项目,而这些正是所有可用的数据。在这种情况下,我们的算法将请求一个只返回一个结果的新批次。这不是问题,这是算法分页的一部分。
一种替代方法是为连续请求的时间戳请求增加 1 纳秒;理论上,这将避免在后续请求中出现重复。因为我不能 100%确定可以接收到相同纳秒时间时间戳的两个记录,所以我决定不走这条路,因为前一条路可以处理相同时间戳的多个记录的情况。
报价和交易都使用完全相同的算法(并且可以在单独的共享方法/例程中编码)。
历史贸易
为了获得历史交易,使用/v2/ticks/stocks/trades/{ ticker }/{ date }请求
如前所述,历史交易可以类似地检索。同样的条件和参数也适用。
内存/存储要求的简要回顾
历史交易几乎总是在本地存储和处理,以避免开销。可以按需请求更高的时间范围,但是在每次回溯测试迭代中按需请求几个月的历史 tick 数据是不切实际的。
我总是试图用原始数据存储一个易于阅读和解析的文件,如果可能的话,使用 ASCII 文本文件。在这个例子中,我们创建了两个文件(报价和交易)。
user[@almaz](http://twitter.com/almaz):~/NetBeansProjects/SealionPolygonAdapter % java -jar dist/SealionPolygonAdapter.jar
1592387342715007986
1592393505203343776
1592398291430866793
...
1592419244447798705
1592421981410064896
1592423485600194378
1592423485600194378[user@almaz](http://twitter.com/almaz):~/NetBeansProjects/SealionPolygonAdapter % ls -lh data/*
-rw-r--r-- 1 user user 399M Jun 21 19:04 data/SPY.2020-06-17.quote.json
-rw-r--r-- 1 user user 54M Jun 21 19:05 data/SPY.2020-06-17.trade.jsonuser[@almaz](http://twitter.com/almaz):~/NetBeansProjects/SealionPolygonAdapter % head data/SPY.2020-06-17.quote.json
{"p":313.9,"P":315,"q":9801,"c":[1,81],"s":2,"S":1,"t":1592380800048084434,"x":12,"X":11,"y":1592380800047963904,"z":1}
{"p":313.9,"P":315,"q":9901,"c":[1,81],"s":2,"S":5,"t":1592380800048834673,"x":12,"X":11,"y":1592380800048768512,"z":1}
{"p":313.9,"P":315,"q":10001,"c":[1,81],"s":2,"S":6,"t":1592380800048839409,"x":12,"X":11,"y":1592380800048774400,"z":1}
...
数据被存储为每行一个 JSON 对象,这很容易解析(注意,这在存储和性能方面也是低效的)。它每天使用大约 450Mb,每年大约 100Gb 的数据。如果您存储许多资产,一个关键因素是要注意整数压缩算法。使用专有和优化的数据库将节省空间,尽管作为一种权衡,它在开发和调试工作方面有成本,并且增加了操作的复杂性。我仍然喜欢对可读数据进行简单的备份,即使我进一步将数据转换成性能更友好的格式。
我们还可以注意到每个交易日涉及的数据量:
user@almaz:~/NetBeansProjects/SealionPolygonAdapter % wc data/SPY.2020-06-17.quote.json
3060489 3060489 418579482 data/SPY.2020-06-17.quote.jsonuser@almaz:~/NetBeansProjects/SealionPolygonAdapter % wc data/SPY.2020-06-17.trade.json
435989 435989 56996300 data/SPY.2020-06-17.trade.json
SPY 在一天之内有 300 万个报价点和超过 40 万个交易点。
为了在任何回溯测试或定制工具中使用数据,可能需要进一步的处理,但是正如本文开头提到的,将数据存储在简单的 ASCII 可读数据中作为永久备份是有用的。这将简化开发和转换时间,并将数据历史提供者从我们分析工具链中分离出来。
一个简单而有效的改进方法是压缩两个档案。在这种情况下,我们得到:
user@almaz:~/NetBeansProjects/SealionPolygonAdapter % gzip data/SPY.2020-06-17.quote.json
user@almaz:~/NetBeansProjects/SealionPolygonAdapter % gzip data/SPY.2020-06-17.trade.json
user@almaz:~/NetBeansProjects/SealionPolygonAdapter % ls -lh data/*
-rw-r--r-- 1 user user 54M Jun 21 19:04 data/SPY.2020-06-17.quote.json.gz
-rw-r--r-- 1 user user 9.2M Jun 21 19:05 data/SPY.2020-06-17.trade.json.gz
仅仅通过使用标准的 gzip 工具,我们每天只能得到 64Mb,每年需要大约 16Gb。更友好的存储大小,无需特殊资源即可轻松实现。
压缩和解压缩需要时间,因此这只能用作永久数据备份。
源代码
下面是检索历史报价(报价和交易)的源代码的基本版本,作为参考。请注意,该代码是测试版,没有经过优化,它旨在展示 Java 中的一个用例,阐明如何访问历史分笔成交点数据。它可以很容易地移植到其他语言。
数据以 JSON 格式检索,这种格式便于调试。代价是 JSON 远不是一种有效格式。对于一个历史数据检索 API,我认为这是不相关的,尤其是在为了回溯测试的目的而以批处理方式检索数据的情况下。在这种情况下,JSON 提供的简单性和可维护性是明显的优势。
对于这个特定的实现,我使用了 simple-json v1.1.1 作为解析 json 的配套库。这个库在它的版本 1 中不再被维护,但是它是一个完全工作的库,使用起来非常简单,并且是轻量级的。
主类:检索并存储 2020 年 6 月 17 日 SPDR 间谍 ETF 的 BidAsk 和 Trades
HistoricalRequest 类包含检索每日竞价和交易并将它们存储到磁盘的方法。
如何重用您的 Python 模型而无需重新训练它们
原文:https://towardsdatascience.com/how-to-reuse-your-python-models-without-retraining-them-39cd685659a5?source=collection_archive---------15-----------------------

Python 的对象序列化库简介
注:在计算机科学中,保存一个对象以备后用的过程叫做 序列化 ,而加载一个保存的对象叫做 反序列化 。
作为一名数据科学家,您可能希望重用您的一个模型,而不必重新训练它。
避免需要重新训练你的模型是特别有用的,因为它允许“部署”模型,即把你训练好的模型转移到一个公共服务器上,任何有互联网连接的人都可以查询预测。
例如,假设您已经创建了一个简单的 scikit-learn 模型,您希望保存它并在以后重用它。
>>> from sklearn.datasets import load_iris
>>> from sklearn.tree import DecisionTreeClassifier
>>> model = DecisionTreeClassifier()
>>> X, y = load_iris(return_X_y=True)
>>> clf = model.fit(X,y)
在这种情况下,我们的训练模型存储在 Python 对象clf中。
为了保存clf对象供以后重用,我们将使用内置的pickle库。
>>> import pickle
>>> with open('clf.pickle', 'wb') as f:
... pickle.dump(clf, f)
我们通过指定wb用“写字节模式”打开了一个名为clf.pickle的文件,并且我们已经在变量f中存储了对该文件的引用。
然后,我们使用pickle.dump方法将对象clf保存在文件clf.pickle中。在幕后,Python 实际上将clf对象转换成一系列字节,稍后它可以将这些字节转换回原始的clf对象。
您可以检查工作目录的内容现在包含一个名为clf.pickle的文件。
>>> import os
>>> os.listdir()
['clf.pickle']
如果您通过键入exit()退出当前的 Python 会话,然后启动一个新的 Python 提示符,那么您可以重新加载clf对象来恢复训练好的模型。
>>> import pickle
>>> with open('clf.pickle', 'rb') as f:
... clf = pickle.load(f)
>>> type(clf)
sklearn.tree._classes.DecisionTreeClassifier
注意我们如何通过指定rb以“读取字节”模式打开文件clf.pickle,然后将对该文件的引用存储在变量f中。
然后,pickle.load能够读取文件clf.pickle并返回一个新的对象,该对象与我们最初传递给pickle.dump的clf对象完全相同。
任何 Python 对象都可以使用 pickle.dump 保存到一个文件中,并且可以使用
**pickle.load**从文件中加载完全相同的对象
因此,我们可以使用从文件中加载的新的clf对象在中进行预测,就像我们使用原始的clf对象进行预测一样。
>>> clf.predict([
... [1,1,0,0],
... [1,0,1,1]
... ])
[0,0]
当然,将训练好的模型保存到本地目录中的文件意味着其他人将不能重用该模型。将训练好的模型保存到其他程序可以访问的数据库中会更方便。
将腌制模型保存到数据库中
pickle 模块允许将对象转换为内存中的字节,然后我们可以用它将训练好的模型保存在数据库中。
>>> pickled_clf = pickle.dumps(clf)
>>> type(pickled_clf)
bytes
请注意我们如何使用pickle.dumps方法,即“ dump s tring”,而不是pickle.dump方法。
dumps方法直接返回一个字节的对象pickled_clf,而不是将其写入文件。(dumps方法的命名被选择为与其他序列化库一致,并且它不返回str类型对象)。
我们现在可以将pickled_clf字节对象直接保存到数据库中。
例如,假设我们有一个名为db.sqlite3的 sqlite3 数据库,其中包含一个名为models的表,该表带有一个BLOB(即字节)字段。
sqlite3 db.sqlite3 "create table models(name TEXT, data BLOB);"
为了将经过酸洗的模型保存到那个表中,我们可以使用sqlite3模块。
>>> import sqlite3
>>> conn = sqlite3.connect('db.sqlite3')
>>> query = 'insert into models values (?, ?)'
>>> conn.execute(query, ['clf', pickled_clf])
>>> conn.commit()
然后,我们可以从数据库中重新加载 pickled 对象,然后将 bytes 对象转换回原始模型。
>>> cursor = conn.execute('select * from models')
>>> name, pickled_clf = cursor.fetchone()
>>> clf = pickle.loads(pickled_clf)
注意我们是如何使用pickle.loads方法加载分类器的。正如我们使用pickle.load来恢复用pickle.dump保存的对象一样,我们也可以使用pickle.loads来恢复用pickle.dumps保存的对象。
现在,您可以重用该模型,而无需重新训练它。
>>> clf.predict([
... [1,1,0,0],
... [1,0,1,1]
... ])
[0,0]
感谢阅读!如果你觉得这个教程有用,我在 Medium 上写了关于 Python 和数据科学的技巧,所以你可以关注我来获得更多类似的文章。
[## 熊猫 1.0 的主要特性
您今天就可以开始使用的新改进
towardsdatascience.com](/top-features-of-pandas-1-0-26abff08d1b6) [## 你可能还不知道的 3 个 Python 列表理解技巧
列表理解不仅仅是为了列表
levelup.gitconnected.com](https://levelup.gitconnected.com/3-python-list-comprehension-tricks-you-might-not-know-yet-5891d904ee76)
如何修改你的营销组合模型来捕捉新冠肺炎的影响?
原文:https://towardsdatascience.com/how-to-revise-your-marketing-mix-model-to-capture-covid-19-impact-863b65982408?source=collection_archive---------25-----------------------
现实世界中的数据科学
你可以做 5 件事来评估新冠肺炎的影响力,并让你的营销组合模型重新发挥作用
C OVID-19 震惊了世界,不可避免地改变了人们的工作、购物和生活方式。它不仅推动了经济的发展,还对广大广告客户的营销方式产生了重大影响。Influencer Marketing Hub 最近公布的新冠肺炎营销报告称,69%的品牌表示他们将在 2020 年减少广告支出。他们调查的公司中有 74%放慢了社交媒体发布的速度。

照片由联合国新冠肺炎回应在 Unsplash
毫无疑问,削减营销支出将确保短期生存,并给陷入困境的企业带来微弱的复苏机会。然而,严格衡量你的营销业绩,让每一美元都推动更多的销售比以往任何时候都更加重要和必要。在今天的帖子中,我们将讨论如何更好地评估新冠肺炎·疫情领导下的营销效率。

照片由托尼克在 Unsplash 上拍摄
衡量营销效率的方法
为了评估营销绩效和优化渠道组合,我们需要回答的最重要的问题是,我们在每个渠道上投入的资金获得了什么样的投资回报(ROI)。营销组合模型和多接触归因是流行的技术,往往能提供回答这个问题所需的深度见解。
我更倾向于使用营销组合模型来评估新冠肺炎疫情期间的营销投资回报率,原因有二。
首先,多点接触归因是一种自下而上的评估营销效果的方法。它专注于在线营销和销售,更擅长分析实时用户数据。营销组合建模更多地采用自上而下的宏观视角,而不是评估用户最终转化的每个接触点。因此,不仅可以检查和捕捉营销相关因素,还可以检查和捕捉宏观经济、季节性、天气和竞争影响等因素。从这个角度来看,前所未有的新冠肺炎疫情不在每个人的正常控制范围内,MMM 可以更好地捕捉到它的影响。
此外,MTA 主要专注于数字生态系统,而 MMM 可以轻松覆盖更多线下渠道。鉴于冠状病毒,人们被困在家里。这最终推动了电视收视率的上升。根据 eMarketer 的最新预测,传统电视预计今年将增加 830 万美国观众,这将是自 2012 年以来传统电视观众首次增加👀。因此,与 MTA 相比,MMM 在衡量电视节目效果方面可能做得更好。
建立营销组合模型简介
一般来说,MMM 采用多元线性回归原理,试图在您的目标 KPI(因变量)和一组将影响您的 KPI 的驱动因素(自变量)之间形成一个方程。

您的候选驱动因素最终可分为以下两大类:
- 不可控因素:我们无法控制的外部因素,包括宏观经济、季节性、节假日、天气等。
- 可控因素:我们可以调整和优化的媒体和营销相关指标。
通常,那些不可控因素与你的目标 KPI 呈线性关系,这意味着这些因素每增加一个单位都会改变你的 KPI 一定的量(这种改变可以是负的,也可以是正的)。然而,对于媒体和营销相关的驱动因素,它们的影响是非线性的,必须考虑三个独特的参数。它们是滞后效应、结转效应(Adstock)和收益递减。
- 滞后效应意味着你的广告转化顾客需要多长时间。如果我们将销售收入作为目标 KPI,来自社交媒体参与等漏斗下端渠道的滞后效应将比来自电视和广播等漏斗上端渠道的滞后效应更短,这些渠道旨在提高知名度和激发兴趣。

Jakob Owens 在 Unsplash 上拍摄的照片
- 结转效应(Adstock) 本质上被描述为广告将随着时间的推移而扩散,并在发生后对你的 KPI 产生持续的影响。比方说,如果你在 Instagram 上看到一个购物广告,在接下来的日子里,你仍然会记得那些创意图片,但记忆已经褪色。
Adstock 的公式为: At = Xt + Adstock Rate * At-1
要查看更多关于 Adstock 的详细信息,请点击这里查看群邑在消费电子、零售、金融、汽车和消费品行业的营销组合模式
- 收益递减原本是一个经济学原理,这里有一个非常经典的例子来阐述它:当你饥饿的时候,你从吃第一个汉堡中获得的效用会高于下一个汉堡带给你的效用。
将这一定律应用到营销绩效的测量中,它表明每花一美元在广告上,它将提升你的 KPI,但以递减的速度。

照片由 Denys Nevozhai 在 Unsplash 上拍摄
这三个参数的值因通道而异。并且当驱动不同的 KPI 时或者在不同的时间段期间,即使对于相同的通道,它们也不会相同。因此,它们不是预先决定或预先假设的。相反,它涉及迭代模型训练和测试,以获得在特定时期影响特定 KPI 的每个渠道的这三个参数的最理想组合。
多元回归模型使我们能够轻松识别影响您的目标 KPI 的重要驱动因素,并用系数量化它们的影响。
如何捕捉新冠肺炎的影响力并修改你的 MMM?
由于新冠肺炎是一个前所未有的情况,类似的影响从未在您的模型中捕获和评估过,因此会使您的 MMM 不能很好地运行。您可能已经意识到,如果应用冠状病毒爆发前建立的 MMM 进行预测,您将会看到与实际相比的极高错误率。如果不考虑冠状病毒的影响,你的营销效率也会被错误地评估。
如何修改我们的 MMM 来捕捉新冠肺炎的影响?这里有一些你可以尝试的选择。
- 新冠肺炎虚拟变量
这是将冠状病毒影响作为外部因素纳入你的模型的一种非常直接和简单的方法。哑变量最大的警告是,它只取值 0 或 1 来表示某些因素的存在或不存在。然而,我们不知道疫情什么时候会走到尽头,它很有可能永远不会消失。此外,新冠肺炎的影响是动态的,它使曲线变平,而不是固定值。因此,具有 0 或 1 的虚拟变量不能完全和准确地拾取衰减的影响。

*图片由作者提供:0/1 虚拟变量。为了便于说明,图表中的数字是任意的
- 新冠肺炎相关指标
为了更好地捕捉来自新冠肺炎的动态影响,我们可以直接获取疫情相关指标,如每日增量和累积确诊病例数、恢复或死亡等。作为代理人。谷歌已经在谷歌云平台中提供了免费的公共数据集。你可以去这里查看更多细节。
- 宏观经济指数
冠状病毒,一个黑天鹅事件,导致了严重的经济萎缩。因此,除了新冠肺炎相关指标,我们还可以间接利用一些宏观经济指数来估计影响。最直观的就是失业率。由于冠状病毒,4 月份美国失业率飙升至 14.7%,为大萧条以来的最高水平。数据可以从美国劳工统计局获得,也可以很容易地下载。
使用失业率的一个限制是,数据通常按月刷新和公布。因此,它可能无法完全反映每日或每周的波动和变化。
除此之外,考虑到股市一直被视为经济晴雨表,股市中的指数如 S & P 500 和道琼斯也是潜在的候选。雅虎财经是我经常去下载这些指数数据的地方。

由 Markus Spiske 在 Unsplash 上拍摄的照片
- 反事实分析
上述代理可能有助于捕捉你的业务一般上下。事实上,他们可能无法完美地捕捉到你的趋势。另一种获得特定于您的业务的新冠肺炎影响指标的潜在方法是利用冠状病毒爆发前建立的 MMM 进行反事实估计。具体来说,反事实分析测量没有新冠肺炎会发生什么,因此我们可以通过比较实际观察到的表现和反事实结果来量化其影响。

*作者图片:反事实分析。为了便于说明,图表中的数字是任意的
你可能会问,如果你以前没有做过 MMM,如何进行反事实分析?我们可以使用疫情之前的历史数据来利用 R 中的预测包。以下是进行预测的示例代码。
library(forecast)#Step 1: Convert sales data into time series. Here is using 2-year data to forecast next yearts <- ts(sales$Sales[sales.Period >= '2018-01-01' & sales.Period <='2019-12-31'])#Step 2: Fitting an auto.arima model in R using the Forecast package
sales<- auto.arima(ts)
pred <- forecast(object = sales, h = 365)
到目前为止,我们已经讨论了四种方法来得出新冠肺炎指标,并衡量其作为外部因素的影响。然而,新冠肺炎不仅从外部影响我们的业务,而且从根本上影响营销效率和效果。有鉴于此,你还需要做些什么来修改你的营销组合模式,以适应疫情期间不同的营销效果?
您需要通过将媒体和营销指标分成两部分,用最新数据重新训练您的营销组合模型。通过这样做,我们可以在新冠肺炎前后获得不同的系数,并跨营销渠道计算相应的投资回报率。

*作者图片:拆分营销指标。为了便于说明,图表中的数字是任意的
在下一篇文章中,我们将讨论如何利用 R 来建立一个基于你的营销组合模型结果的迷你优化器,并提高你的营销效率。💖
如何用熊猫用 Python 重写 SQL 查询
原文:https://towardsdatascience.com/how-to-rewrite-your-sql-queries-in-python-with-pandas-8d5b01ab8e31?source=collection_archive---------9-----------------------
在 Python 中再现相同的 SQL 查询结果

照片由 Hitesh Choudhary 在 Unsplash 上拍摄
我们中的一些人熟悉 SQL 中的数据操作,但不熟悉 Python,我们倾向于在项目中频繁地在 SQL 和 Python 之间切换,导致我们的效率和生产力降低。事实上,我们可以使用 Pandas 在 Python 中实现类似的 SQL 结果。
入门指南
像往常一样,我们需要安装熊猫包,如果我们没有它。
conda install pandas
在本次会议中,我们将使用 Kaggle 著名的泰坦尼克号数据集。
在安装包和下载数据之后,我们需要将它们导入到 Python 环境中。
我们将使用 pandas 数据帧来存储数据,并使用各种 pandas 函数来操作数据帧。
选择、不同、计数、限制
让我们从我们经常使用的简单 SQL 查询开始。
titanic_df[“age”].unique()将在这里返回唯一值的数组,所以我们需要使用len()来获得唯一值的计数。
选择,WHERE,OR,AND,IN(带条件选择)
学完第一部分后,你应该知道如何用简单的方法探索数据框架。现在让我们尝试一些条件(也就是 SQL 中的WHERE子句)。
如果我们只想从数据框中选择特定的列,我们可以使用另一对方括号进行选择。
注意:如果您选择多列,您需要将数组
["name","age"]放在方括号内。
isin()的工作方式与 SQL 中的IN完全相同。要使用NOT IN,我们需要使用 Python 中的否定(~)来达到相同的结果。
分组依据、排序依据、计数
GROUP BY和ORDER BY也是我们用来探索数据的流行 SQL。现在让我们用 Python 来试试这个。
如果我们只想对计数进行排序,我们可以将布尔值传递给sort_values函数。如果我们要对多列进行排序,那么我们必须将一个布尔值数组传递给sort_values函数。
sum()函数将为我们提供数据帧中的所有聚合数字总和列,如果我们只需要一个特定的列,我们需要使用方括号指定列名。
最小值、最大值、平均值、中间值
最后,让我们尝试一些在数据探索中很重要的常用统计函数。
由于 SQL 没有中位数函数,所以我将使用 BigQuery APPROX_QUANTILES来获得年龄的中位数。
熊猫聚合功能.agg()还支持sum等其他功能。
现在你已经学会了如何用熊猫用 Python 重写你的 SQL 查询。希望这篇文章对你有用。如果我犯了任何错误或错别字,请给我留言。
可以在我的 Github 中查看完整的脚本。干杯!
如果你喜欢读这篇文章,你可能也会喜欢这些:
[## 使用 Conda 管理您的 Python 虚拟环境
轻松在 Python 2 和 Python 3 环境之间切换
towardsdatascience.com](/manage-your-python-virtual-environment-with-conda-a0d2934d5195) [## 如何使用 Python 发送带附件的电子邮件
作为一名数据分析师,我经常会收到这样的请求:“你能每周给我发一份报告吗?”或者…
towardsdatascience.com](/how-to-send-email-with-attachments-by-using-python-41a9d1a3860b)
你可以在 Medium 上找到我其他作品的链接,关注我 这里 。感谢阅读!
如何在 Kubernetes (AWS EKS)运行 PySpark 作业
原文:https://towardsdatascience.com/how-to-run-a-pyspark-job-in-kubernetes-aws-eks-d886193dac3c?source=collection_archive---------19-----------------------
关于使用 Terraform 部署 EKS 集群和使用 Spark 操作符运行 PySpark 作业的完整教程

萨姆森在 Unsplash.com 拍摄的照片
在本教程中,我们将重点关注在 AWS EKS 上端到端部署 Spark 应用程序。我们将执行以下步骤:
- 在 AWS 中的定制 VPC 内部署 EKS 集群
- 安装火花操作器
- 运行一个简单的 PySpark 应用程序
TL;博士: Github 代码回购
步骤 1:部署 Kubernetes 基础设施
要在 AWS 上部署 Kubernetes,我们至少需要部署:
- VPC、子网和安全组负责集群中的网络
- EKS 控制平面主要运行 Kubernetes 服务,如
etcd和Kubernetes API - EKS 工人节点能够运行 pod 和更具体的针对我们案例的 spark 作业
让我们深入研究 Terraform 代码。首先,让我们看看 VPC:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.6.0"name = join("-", [var.cluster_name, var.environment, "vpc"])
cidr = var.vpc_cidr
azs = data.aws_availability_zones.available.names
private_subnets = [var.private_subnet_az_1, var.private_subnet_az_2, var.private_subnet_az_3]
public_subnets = [var.public_subnet_az_1, var.public_subnet_az_2, var.public_subnet_az_3]
enable_nat_gateway = true
single_nat_gateway = false
one_nat_gateway_per_az = true
enable_dns_hostnames = true
enable_dns_support = truetags = {
"kubernetes.io/cluster/${var.cluster_name}" = "shared"
}public_subnet_tags = {
"kubernetes.io/cluster/${var.cluster_name}" = "shared"
"kubernetes.io/role/elb" = "1"
}private_subnet_tags = {
"kubernetes.io/cluster/${var.cluster_name}" = "shared"
"kubernetes.io/role/internal-elb" = "1"
}
}
VPC 是一个孤立的网络,其中可以有不同的基础架构组件。我们可以将这个网络分解成更小的块,在 AWS 上我们称之为子网。有些子网可以访问互联网,这就是我们称之为公共子网的原因,而有些子网不能访问互联网,则称为私有子网。我们将在网络流量上下文中使用的另一个术语是出口和入口。出口是指从网络内部流向外部世界的流量,以及从外部世界流向网络的入口流量。如您所料,这些规则可能会因用例而异。我们还使用安全组,这是 VPC 内部的流量规则,它定义了 EC2 实例如何相互“对话”,基本上是在哪些网络端口上。
对于 Spark EKS 集群,see 将为工作线程使用专用子网。所有的数据处理都是在完全隔离的情况下完成的。但是我们需要到互联网的出口流量,以进行更新或安装开源库。为了支持互联网流量,我们在 VPC 中使用 NAT 网关。我们必须将它们添加到公共子网中。在地形代码中,这是使用标志enable_nat_gateway.完成的
我们可以注意到的另一件事是,我们使用了三个公共和私有子网。这是因为我们希望拥有网络容错能力。子网部署在一个区域的不同可用性区域中。
标签是按照 AWS 的要求创建的。控制平面需要它们来识别工作节点。我们可以更详细地介绍网络,但这超出了本教程的范围,所以如果您需要更多的细节,请查看 Github 代码,在那里您可以找到完整的示例。
让我们看看 EKS 集群的设置:
module "eks" {
source = "terraform-aws-modules/eks/aws"
cluster_name = join("-", [var.cluster_name, var.environment, random_string.suffix.result])
subnets = module.vpc.private_subnetstags = {
Environment = var.environment
}vpc_id = module.vpc.vpc_id
cluster_endpoint_private_access = truecluster_enabled_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]worker_groups = [
{
name = "worker-group-spark"
instance_type = var.cluster_instance_type
additional_userdata = "worker nodes"
asg_desired_capacity = var.cluster_number_of_nodes
additional_security_group_ids = [aws_security_group.all_worker_mgmt.id, aws_security_group.inside_vpc_traffic.id]
}
]workers_group_defaults = {
key_name = "eks_key"
subnets = module.vpc.private_subnets
}
}
在这个代码片段中,我们可以看到我们在私有子网内声明了集群。我们为控制面板的所有组件启用 Clowdwatch 日志。我们为配置var模块设置 EC2 实例类型和数量,默认情况下,我们使用m5.xlarge作为实例类型和 3 个节点。如果我们需要 ssh 进入工作节点,我们设置一个 EC2 键eks_key。
为了能够运行本教程中的代码,我们需要安装一些工具。在 Mac 上,我们可以使用brew:
brew install terraform aws-iam-authenticator kubernetes-cli helm
为了达到 AWS,我们还需要设置我们的 AWS 凭证。
现在,我们可以开始初始化 Terraform,以获得部署基础设施所需的所有依赖项:
cd deployment/ && terraform init
如果一切运行成功,您应该能够看到类似于下图的内容:

我们已经准备好部署基础设施。为此,请运行:
terraform apply
部署完成还需要一段时间,所以我们可以高枕无忧了。
完成后,您应该会看到消息Apply complete! Resources: 55 added, 0 changed, 0 destroyed.和部署的资源的名称。
检查部署是否正确的另一个步骤是查看工作节点是否已经连接到集群。为此我们设置了kubectl:
aws --region your-region eks update-kubeconfig --name your-cluster-name
当我们运行以下命令时,应该能够看到三个节点:
kubectl get nodes
步骤 2:安装 Spark 操作器
通常,我们使用spark-submit部署 spark 作业,但是在 Kubernetes 中,我们有一个更好的选择,与环境更加集成,称为 Spark 操作符。它带来的一些改进包括自动重新提交应用程序、使用自定义重启策略自动重启、自动重试失败的提交,以及与 Prometheus 等监控工具的轻松集成。
我们可以通过helm:安装它
helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
helm install spark-op incubator/sparkoperator
如果我们在终端中运行helm list,那么spark-op图表应该是可用的。此外,我们应该有一个运行的火花操作员吊舱。我们可以使用命令kubectl get pods.来观察在default名称空间中运行的 pods
步骤 3:运行 PySpark 应用程序
现在我们终于可以在 K8s 中运行 python spark 应用了。我们需要做的第一件事是创建一个spark用户,以便让 spark jobs 访问 Kubernetes 资源。为此,我们创建了一个服务帐户和一个群集角色绑定:
apiVersion: v1
kind: ServiceAccount
metadata:
name: spark
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: spark-role
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: edit
subjects:
- kind: ServiceAccount
name: spark
namespace: default
要执行角色的创建:
kubectl apply -f spark/spark-rbac.yml
您将收到serviceaccount/spark created和clusterrolebinding.rbac.authorization.k8s.io/spark-role created.的通知
星火操作员工作定义:
apiVersion: "sparkoperator.k8s.io/v1beta2"
kind: SparkApplication
metadata:
name: spark-job
namespace: default
spec:
type: Python
pythonVersion: "3"
mode: cluster
image: "uprush/apache-spark-pyspark:2.4.5"
imagePullPolicy: Always
mainApplicationFile: local:////opt/spark/examples/src/main/python/pi.py
sparkVersion: "2.4.5"
restartPolicy:
type: OnFailure
onFailureRetries: 2
driver:
cores: 1
memory: "1G"
labels:
version: 2.4.5
serviceAccount: spark
executor:
cores: 1
instances: 1
memory: "1G"
labels:
version: 2.4.5
我们在一个yml文件中定义我们的 spark run 参数,类似于 Kubernetes 上的任何其他资源声明。基本上,我们定义我们正在运行一个Python 3 spark 应用程序,我们是映像uprush/apache-spark-pyspark:2.4.5.我推荐使用这个映像,因为它带有一个更新版本的 yarn,可以更有效地处理对s3a的写入。我们有一个重试策略,如果作业失败,它将重新启动。驱动程序和执行器的一些资源分配。由于工作非常简单,我们只使用一个执行程序。我们可以注意到的另一件事是,我们使用了之前定义的spark服务帐户。我们使用的 To 代码是计算pi数的经典例子。
要提交我们再次使用的代码kubectl:
kubectl apply -f spark/spark-job.yml
完成后,如果我们再次检查豆荚,我们应该有类似的结果:

如果我们通过运行kubectl logs spark-job-driver来检查日志,我们应该会在日志中找到一行给出 pi 的近似值Pi is roughly 3.142020.
那是所有的人。我希望你喜欢这个教程。我们已经看到了如何使用 terraform 创建我们自己的 AWS EKS 集群,以便在不同的环境中轻松地重新部署它,以及如何使用更友好的 Kubernetes 语法提交 PySpark 作业。
如何使用 PySpark 结构化流在 AWS Kinesis 中运行实时管道
原文:https://towardsdatascience.com/how-to-run-a-real-time-pipeline-in-aws-kinesis-using-pyspark-structured-streaming-1b6bc5e6edc9?source=collection_archive---------25-----------------------
使用 Python 结构化流应用程序从 AWS Kinesis 消费数据,并在 Jupyter 笔记本中运行

照片由 Aron 视觉效果在 Unsplash 上拍摄
在本教程中,我们将使用 Spark 的最新流技术,结构化流,从 AWS Kinesis 流中使用JSON数据。
我们将执行以下步骤:
- 使用 boto3 在 AWS 中创建 Kinesis 流
- 将一些简单的
JSON消息写入流中 - 消费 PySpark 中的消息
- 在控制台中显示消息
TL;DR: Github 代码回购
步骤 1:为 Jupyter 设置 PySpark
为了能够在笔记本上运行 PySpark,我们必须使用findspark包。我们需要添加另一个包,允许 PySpark 从 Kinesis 获取消费者数据。对于此功能,我们在笔记本的开头添加了:
import os
os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages=com.qubole.spark/spark-sql-kinesis_2.11/1.1.3-spark_2.4 pyspark-shell'import findspark
findspark.init()
步骤 2:创建一个动力流
AWS Kinesis 是使我们能够实时读取和处理数据的基础设施。与其他类似的技术(Kafka)相比,它更容易建立。在 python 中,我们可以使用boto3库:
client = boto3.client('kinesis')
stream_name='pyspark-kinesis'client.create_stream(
StreamName=stream_name,
ShardCount=1)
这将创建一个流分片,它本质上是控制吞吐量的单元。更多的碎片意味着我们可以接收更多的数据,但是对于本教程来说,一个就足够了。
如果我们打开 AWS 控制台,导航到 Amazon Kinesis board(服务-> Amazon Kinesis),我们应该会看到类似的内容:

步骤 3:将信息写入 Kinesis
要将一些消息写入我们刚刚创建的 Kinesis 流,我们可以再次使用boto3:
messages = [
{'message_type': 'message1', 'count': 2},
{'message_type': 'message2', 'count': 1},
{'message_type': 'message1', 'count': 2},
{'message_type': 'message3', 'count': 3},
{'message_type': 'message1', 'count': 5}
]for message in messages:
client.put_record(
StreamName=stream_name,
Data=json.dumps(message),
PartitionKey='part_key')
我们有一个字典列表,我们将其序列化到JSON中,并使用put_record函数编写。一个字典代表我们信息的模式。因为我们只使用一个碎片,所以如何定义分区键并不重要。
第四步:阅读信息
当使用结构化流读取数据时,我们需要注意 Kinesis 的一些特殊性。
首先,我们需要定义format Kinesis,以便使用正确的连接器。我们还必须使用端点和区域,这取决于我们部署基础架构的位置。我的情况是爱尔兰eu-west-1.
我们使用设置startingposition作为TRIM_HORIZON,这意味着当我们重启应用程序时,我们总是会读取 Kinesis 中所有可用的数据。如果我们只想处理最新的可用数据,我们可以将该标志改为LATEST。
我已经为 AWS 凭证创建了环境变量。我们也可以直接使用它们,但这样更安全。
kinesis = spark \
.readStream \
.format('kinesis') \
.option('streamName', stream_name) \
.option('endpointUrl', '[https://kinesis.eu-west-1.amazonaws.com')\](https://kinesis.eu-west-1.amazonaws.com')\)
.option('region', 'eu-west-1') \
.option('awsAccessKeyId', os.environ['KINESIS_ACCESS_KEY'])\
.option('awsSecretKey', os.environ['KINESIS_SECRET_KEY']) \
.option('startingposition', 'TRIM_HORIZON')\
.load()\
一旦我们执行了这段代码,我们将能够读取数据帧中的运动数据。
步骤 5:在控制台中显示消息
我们现在设置的好处是我们可以执行标准的数据帧操作。
我们的数据在 JSON 中,所以我们需要转换它。前三个 select 语句就是关于这个的。我们使用from_json将 JSON 列转换为包含所有字段的结构,使用data.*的技巧是将一列分成单独的列,因此在我们的例子中,一列用于message_type,一列用于count。
schema = StructType([
StructField("message_type", StringType()),
StructField("count", IntegerType())])kinesis\
.selectExpr('CAST(data AS STRING)')\
.select(from_json('data', schema).alias('data'))\
.select('data.*')\
.writeStream\
.outputMode('append')\
.format('console')\
.trigger(once=True) \
.start()\
.awaitTermination()
因为我们使用选项trigger(once=True),我们将只读取一批数据,这不是一个连续的操作。如果我们删除这个标志,那么处理将是无限的。
在我们启动 Jupyter 笔记本的终端中,我们将能够看到数据:

一批运动数据
最后,我们可以删除我们在 AWS 中使用的资源,即我们部署的 Kinesis 流:
client.delete_stream(StreamName=stream_name)
仅此而已!我希望您喜欢来自精彩的流处理世界的另一个教程。我们已经看到了如何通过几个步骤在 Kinesis 的 PySpark 中连接和处理数据。
在 Google Colab 上运行并分享深度学习网络应用
原文:https://towardsdatascience.com/how-to-run-and-share-your-deep-learning-web-app-on-colab-a13f9d2cbc4e?source=collection_archive---------34-----------------------
使用 Streamlit 快速构建原型,并在 Google Colab 上部署,只需几行代码

KOBU 机构在 Unsplash 上拍摄的照片
介绍
在我之前的工作中,我使用 Fastai 建立了一个深度学习模型,对黑白照片进行彩色化,并使用 Streamlit 建立了一个 web 应用原型。我希望与我的同事和朋友分享它,以获得一些反馈,所以我试图将 web 应用程序部署到 AWS 和 Heroku。
[## 人工智能给黑白照片上色。
利用 Fastai 的生成性对抗网络(GAN)使黑白照片变得丰富多彩
towardsdatascience.com](/colorize-black-and-white-photos-by-ai-cc607e164160)
我能够将我的应用程序部署到这些云服务提供商并运行它,但是,他们的免费层帐户没有为我的应用程序提供足够的内存,它总是崩溃。为了让至少一些东西在网上运行,我不得不把照片的尺寸做得很小,结果质量很差。我不想在这个早期阶段花很多钱升级账户。我只是想要一个功能齐全的快速原型运行,这样我就可以测试它,并得到一些反馈。
从那以后,我一直在寻找其他解决方案来部署和共享应用程序。我找到的一个解决方案是在 Google Colab 上运行这个应用程序,使用其免费且强大的计算服务。在这篇短文中,我将描述我如何在 Colab 上运行 web 应用程序。
斯特雷姆利特
如果您不熟悉 Stremlit ,它是用 Python 创建简单 web 应用程序的强大工具。对于我这样没有 web 开发背景和技能的人来说非常方便。
他们为初学者提供了很好的教程。
[## 简化/演示-自动驾驶
该项目展示了 Udacity 自动驾驶汽车数据集和 YOLO 物体检测到一个互动的流线…
github.com](https://github.com/streamlit/demo-self-driving)
在这篇文章中,我还记录了我使用 Stremlit 构建 web 应用程序的工作:
[## 生成性对抗网络:构建一个用 Streamlit 给 B&W 照片着色的 web 应用程序
使用 Streamlit 快速将生成式对抗网络模型转换为 web 应用程序,并部署到 Heroku
towardsdatascience.com](/generative-adversarial-network-build-a-web-application-which-colorizes-b-w-photos-with-streamlit-5118bf0857af)
在 Colab 上运行应用程序
一旦你在本地成功运行了网络应用程序,你可以试着在 Google Colab 上运行它
首先把 app 克隆到 colab,进入目录。
!git clone [http://github.com/xxx/xxxxx.git](http://github.com/xxx/xxxxx.git) color
cd color
然后安装需求
!pip install -r requirements_colab.txt
在我的例子中,它包含 stremlit、opencv、fastai 和 scikit_image。
然后我们需要安装 pyngrok。
!pip install pyngrok
要通过 Colab 上的公共 URL 运行和共享应用程序,我们需要使用 ngrok,这是一种安全的隧道解决方案。详情可以在这里找到。
安装完成后,我们可以在后台运行应用程序。
!streamlit run run.py &>/dev/null&
然后使用 ngrok 创建公共 URL。
from pyngrok import ngrok
# Setup a tunnel to the streamlit port 8501
public_url = ngrok.connect(port='8501')
public_url
你应该会得到这样一个网址“http://ea41c 43860 D1 . ngrok . io”。
就是这样!非常简单的步骤。现在,这款网络应用可以通过强大的 Google Colab 免费在线使用。

照片由阿齐兹·阿查基在 Unsplash 上拍摄
在 Colab 上运行 web 应用程序的优势在于,应用程序不会受到自由层帐户的有限计算的限制,您甚至可以使用 GPU 运行。然而,它的主要缺点是 URL 只是临时的,一旦 Colab 断开,URL 将被禁用。所以你只能在短时间内分享链接(< 12 小时)。但是我认为这仍然是一个快速部署、测试和共享 web 应用原型的好方法。
感谢阅读。欢迎提出建议和意见。
如何使用 Linux“systemd”将 Apache Airflow 作为守护进程运行
原文:https://towardsdatascience.com/how-to-run-apache-airflow-as-daemon-using-linux-systemd-63a1d85f9702?source=collection_archive---------5-----------------------

由拍摄的在 Pixabay
CentOS 上的气流守护程序教程。从安装、下载、配置到使用 systemctl 运行。
自从 Airflow 从孵化器成为顶级 Apache 项目后,它作为一个具有简洁 Web UI 的工作流调度管理器越来越受欢迎。
在一个典型的用例中,Airflow 需要两个必须持续运行的组件,web 服务器和调度器。前者是用于管理和监控工作流的 Web UI,后者负责在预定义的时间戳正确触发工作流。
但是,使用 Linux 中提供的命令来运行这两个组件并不是一个好主意,例如:
$ airflow scheduler
$ airflow webserver
缺点显而易见:
- 如果任何组件崩溃,服务将被终止,没有任何通知。
- 这些服务的日志被打印在 stdout 中,如果 crush 的话,这些日志将会丢失,所以要找出发生了什么是很困难的
- 当 Linux 系统重新启动时,它不会自动启动运行。
为了解决这些问题,我们需要将 Apache Airflow 作为守护进程运行。Apache Airflow GitHub repo 已经提供了支持systemd和upstart的守护程序服务定义。在本文中,我们将使用前者。
官方文档只给出了非常简要的解释,没有可以遵循的教程。对于一些没有太多 Linux 经验的数据工程师或数据科学家来说,这相对比较困难。本文将一步步演示如何将 Airflow 作为守护进程运行。从安装到启动和运行。
安装阿帕奇气流

照片由 teru_teru 在 Pixabay 上拍摄
在 Medium 上已经有一些关于如何安装 Airflow 的教程,比如这个,如果你在 Ubuntu 上的话:
[## 如何使用 python 解释器在 Ubuntu 上安装 apache airflow
在这篇博文中,我将向您展示如何在 ubuntu 上安装 apache airflow,
medium.com](https://medium.com/@shaikzillani/how-to-install-apache-airflow-on-ubuntu-using-python-interpreter-20f10348e7bd)
然而,对于 CentOS 等基于 Red Hat 的 Linux,似乎还没有这样的教程,依赖项的名称和安装方式可能与基于 Debian 的 Linux 略有不同。
首先,强烈建议为气流创建一个特定的用户
useradd airflow
此外,您的 Linux 可能会也可能不会绑定 Airflow 所需的一些依赖项。典型的,我发现有以下三种缺失是相当普遍的。
- (同 groundcontrolcenter)地面控制中心
- Python 开发
- MySQL 开发(如果你需要连接到 MySQL)
请注意,Ubuntu 和 CentOS 中的库名并不相同。例如,Python Dev 包在 Ubuntu 的apt-get中是python-dev,而在 CentOS 的yum中,它被称为python-devel。如果你使用 Python3,确保你安装了python3-devel。此外,MySQL Dev 在apt-get中被称为libmysqldev,而在yum中被称为mysql-devel。
yum install gcc
yum install python3-devel
yum install mysql-devel
然后,让我们安装气流和额外的软件包,如有必要,如:
pip3 install apache-airflow
pip3 install 'apache-airflow[crypto]'
pip3 install 'apache-airflow[mysql]'
气流守护程序的准备

由汉斯在 Pixabay 上拍摄的照片
在我们能够为气流配置我们的systemd服务之前,我们需要做一些准备。第一步是从 Airflow GitHub Repo 下载服务定义文件。
https://github . com/Apache/air flow/tree/master/scripts/systemd
下载守护程序服务文件
让我们为下载文件创建一个临时文件夹。
mkdir /tmp/airflow-daemon
cd /tmp/airflow-daemon
然后,将文件下载到这个临时文件夹中。
# wget [https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow](https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow)
# wget [https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow-scheduler.service](https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow-scheduler.service)
# wget [https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow-webserver.service](https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow-webserver.service)
# wget [https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow.conf](https://raw.githubusercontent.com/apache/airflow/master/scripts/systemd/airflow.conf)
在 GitHub 回购中,有一个简短的解释如下:
该目录中的 systemd 文件是在基于 RedHat 的系统上测试的。将它们复制(或链接)到/usr/lib/systemd/system
并将 airflow.conf 复制到/etc/tmpfiles . d/or/usr/lib/tmpfiles . d/。复制 airflow.conf 确保/run/airflow 是用正确的所有者和权限创建的
( 0755 air flow air flow)然后,您可以使用 systemctl start
启动不同的服务器。启用服务可以通过发出
systemctl enable <服务>来完成。默认情况下,环境配置指向/etc/sysconfig/airflow。你可以复制这个
目录下的“气流”文件,根据自己的喜好进行调整。经过一些小的改动,它们可能可以在其他 systemd 系统上工作。
嗯,我想对于大多数没有 Linux 背景的人来说,上面的文档可能会非常模糊和误导。所以,我画了这个图来显示哪个文件应该放在哪个路径上。

根据图中所示的路径,让我们将文件复制到正确的位置。
cp *.service /usr/lib/systemd/system/
cp airflow.conf /usr/lib/tmpfiles.d/
cp airflow /etc/sysconfig/
创建必要的目录
我们还需要创建一些守护进程需要的目录。首先,它需要一个专用的目录来存储运行时信息,比如pid。让我们在/run目录下创建目录,并更改权限。
mkdir /run/airflow
chown airflow:airflow /run/airflow
chmod 0755 airflow -R
请注意,权限被设置为0755,因为实际上我们可能有其他多个用户来开发 Dag(工作流)。有了0755权限,它确保所有其他用户都有他们的次要组,因为airflow将有足够的权限。
我们需要创建的另一个目录是 Airflow 主目录,它包括:
- 气流配置
- 气流使用的 SQLite
- 熟练的技艺
- Dag 日志
通常如果没有export AIRFLOW_HOME=...,这些会在当前用户的主目录下自动生成,比如/home/airflow/airflow/。如果您正在测试气流或开发一些 Dag,这很好。但是,不建议这样做,而且在生产中也不方便,因为其他用户不容易访问airflow用户的主目录。
在我的例子中,我想把 Airflow 主目录放在/opt下,所以让我们创建它。
mkdir /opt/airflow
chown airflow:airflow airflow -R
chmod 775 airflow -R
同样,更改权限以允许airflow组中的所有用户不仅可以读取目录,还可以写入目录,因为他们需要修改 Dag。
初始化气流主目录
一切准备就绪。我们需要初始化气流的主目录。将主目录导出到AIRFLOW_HOME环境变量是很重要的。否则,如上所述,将在用户的主文件夹中自动生成主目录。
export AIRFLOW_HOME=/opt/airflow
airflow initdb
配置气流守护程序

由摄影师 7 在图片栏上拍摄
现在,所有的服务文件、配置文件和必要的目录都准备好了。我们需要配置守护进程,以确保在守护进程正常运行之前,一切都指向正确的路径。
首先,让我们仔细检查一下airflow二进制文件的路径,因为稍后需要在服务定义中指定它。
$ which airflow
/usr/local/bin/airflow
我的情况是/usr/local/bin/airflow。请记下你的,很可能是一样的,但以防万一要注意一下。不要直接抄我的。
然后,我们来修改一下airflow-webserver的定义。
vi /usr/lib/systemd/system/airflow-scheduler.service
如下更改ExecStart值。
ExecStart=/usr/local/bin/airflow scheduler
同样的,我们也在airflow-scheduler里改一下吧。
vi /usr/lib/systemd/system/airflow-webserver.service
请注意,pid需要写入我们刚刚创建的目录/run/airflow。
ExecStart=/usr/local/bin/airflow webserver --pid /run/airflow/webserver.pid
然后,我们需要修改气流的系统配置。否则,服务将不知道 Airflow 主目录在哪里。
vi /etc/sysconfig/airflow
根据我们刚才准备的内容,需要对下面的两个配置进行如下修改。
AIRFLOW_CONFIG=/opt/airflow/airflow.cfg
AIRFLOW_HOME=/opt/airflow
作为服务配置的最后一步,我们需要在运行这些服务之前启用它们。
systemctl enable airflow-scheduler
systemctl enable airflow-webserver
运行配置的气流守护程序

照片由 suju 在 Pixabay 上拍摄
有了root权限(root 用户或 sudo),我们可以
- 运行气流守护程序
systemctl start airflow-scheduler
systemctl start airflow-webserver
- 检查其状态
systemctl status airflow-scheduler
systemctl status airflow-webserver
- 停止守护进程
systemctl stop airflow-scheduler
systemctl stop airflow-webserver
- 重新启动守护程序
systemctl restart airflow-scheduler
systemctl restart airflow-webserver
- 查看守护程序服务日志(最近 50 行,行数可使用
-n参数定制)
# journalctl -u airflow-scheduler -n 50
# journalctl -u airflow-webserver -n 50
摘要

由摄影师在图片栏上拍摄
本文介绍了如何在 CentOS 系统上安装 Airflow。然后,我认为如果我们简单地在命令行运行 Airflow 会有缺点,所以我们需要通过将它作为守护进程来解决这个问题。
我们首先需要从 Apache Airflow GitHub repo 下载服务定义文件,然后将它们放入正确的系统目录中。我们还需要创建一些文件夹,因为守护进程需要它们来正确运行。
最后,我们需要配置服务定义文件,以确保守护程序可以在正确的位置找到资源。之后,我们可以将 Apache Airflow 作为守护进程运行,这样它将收集适当的服务运行日志,并在出现问题时自动重启服务。
[## 通过我的推荐链接加入 Medium 克里斯托弗·陶
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
如何在 Docker 上运行 Jupyter 笔记本
原文:https://towardsdatascience.com/how-to-run-jupyter-notebook-on-docker-7c9748ed209f?source=collection_archive---------0-----------------------
不再有 Python 环境和包更新

图片由来自 Pixabay 的斯蒂芬·凯勒拍摄
**Table of Contents**[**Introduction**](#093d) 1\. [Installing Docker Desktop](#09a3)
2\. [Docker help](#4802)
3\. [Running Jupyter Docker Stacks](#9927)
4\. [Formatting Docker ps](#f597)
5\. [Entering the Docker container and using bash](#b42d)
6\. [Stopping and removing containers and images](#256b)
7\. [Connecting the local directory to a Docker container](#0ba2)
8\. [Inspecting a container](#08c1)
9\. [Getting started with Docker file](#a6ca)
10\. [Publishing an image to Docker Hub](#999d)[**Conclusion**](#556f)
介绍
Docker 简化并加速了您的工作流程,同时让开发人员可以自由地为每个项目选择工具、应用程序堆栈和部署环境。—从开始用 Docker 开发
Docker 为您的开发提供了一个包含的环境。通过使用 Docker,您可能不需要在计算机上安装 pyenv/pipenv/virtualenv 或任何编程语言。你只要用一个 Docker 容器!在本文中,您将学习如何在 Docker 上运行 Jupyter。
TL;速度三角形定位法(dead reckoning)
$ docker run -p 8888:8888 -v $(pwd):/home/jovyan/work jupyter/minimal-notebook
$ docker run -p 8888:8888 -v $(pwd):/home/jovyan/work jupyter/scipy-notebook
上面的第一个命令将运行 Jupyter minimal-notebook,将本地目录连接到 Docker 容器。
第二个命令与第一个命令相同。唯一不同的是运行 Jupyter Scipy-notebook。
安装 Docker 桌面
安装 Docker 桌面,当你启动 Docker 时,你会在菜单栏中看到一个图标。

Mac 上的 Docker 菜单。作者图片
Docker 首选项菜单允许您配置 Docker 设置,如安装、更新、版本频道、Docker Hub 登录等。打开“偏好设置”并转到“资源”来更改 CPU、内存和其他设置。默认情况下,Docker Desktop 被设置为使用主机上可用处理器数量的一半。

Docker 首选项。作者图片
你可以在这个页面上阅读更多关于 Mac 和 Windows 的细节。
Docker 帮助
在您的终端中运行docker,您将看到所有命令:
$ docker
Usage: docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Options:
--config string Location of client config files (default "/Users/shinokada/.docker")
-c, --context string Name of the context to use to connect to the daemon (overrides
DOCKER_HOST env var and default context set with "docker context use")
-D, --debug Enable debug mode
... MORE LINES
Docker 将命令逻辑地分组为管理命令。以下是顶级命令。
Management Commands:
builder Manage builds
config Manage Docker configs
container Manage containers
context Manage contexts
image Manage images
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumesCommands:
attach Attach local standard input, output, and error streams to a running container
... MORE LINES
您可以使用--help获得更多关于管理命令的信息。
$ docker container --help
$ docker image --help
让我们开始创建 Docker 容器。
运行 Jupyter Docker 堆栈
Jupyter Docker Stacks 是一组准备运行的 Docker 映像,包含 Jupyter 应用程序和交互式计算工具。
官方 Jupyter 创建了不同的 Docker 图像,我们将使用[jupiter/minimal](https://hub.docker.com/r/jupyter/minimal-notebook/tags/)来学习如何使用 Docker。这个映像基于[jupyter/base-notebook](https://hub.docker.com/r/jupyter/base-notebook),它有命令行工具、TeX Live、git、emacs、vi、jed 等等。
$ docker run -p 8888:8888 jupyter/minimal-notebook
在输出的末尾,您可以找到带有标记的 URL。你用cmd +click 在浏览器上打开网址。

带有令牌的 URL 的 Docker 输出。作者图片

单击 URL 后,您会看到这一点。作者图片
打开另一个终端标签并检查容器 id 号。
$ docker container ls
# or
$ docker ps

docker ps 的输出。作者图片
格式化 Docker ps
阅读上面的输出有点困难。让我们创建一个格式。
将以下内容添加到您的~/.zshrc或~/.bash_profile中。
FORMAT="\nID\t{{.ID}}\nIMAGE\t{{.Image}}\nCOMMAND\t{{.Command}}\nCREATED\t{{.RunningFor}}\nSTATUS\t{{.Status}}\nPORTS\t{{.Ports}}\nNAMES\t{{.Names}}\n"
您可以通过将它添加到 docker 的--format选项来使用它:
$ docker ps --format=$FORMAT
# or
$ docker container ls --format=$FORMAT

docker 容器 ls 的输出— format=$FORMAT。作者图片

docker ps — format $FORMAT 的输出。作者图片
如上图所示,有无=标志都可以使用。
进入 Docker 容器并使用 bash
docker exec在运行容器中运行命令。-i选项允许我们交互地使用它,-t分配一个伪 TTY。我们使用/bin/bash来运行 bash shell。
$ docker exec -it cb8b /bin/bash
cb8b是我的容器的前 4 个字母。您有不同的容器 id。
使用docker exec --help可以找到更多信息。
$ docker exec --help
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
Options:
-d, --detach Detached mode: run command in the background
--detach-keys string Override the key sequence for detaching a container
-e, --env list Set environment variables
... MORE LINES
一旦进入容器,就可以运行普通的 bash 命令。

在容器中运行 ls 命令。作者图片
让我们检查一下容器 Python 和 pip 版本:
(base) jovyan@cb8b4579b2a6:~/work$ python -V
Python 3.8.5
(base) jovyan@cb8b4579b2a6:~/work$ pip -V
pip 20.2.3 from /opt/conda/lib/python3.8/site-packages/pip (python 3.8)
该图像也有ipython和conda。让我们检查一下:
(base) jovyan@cb8b4579b2a6:~$ ipython --version
7.18.1
(base) jovyan@cb8b4579b2a6:~$ conda info -aactive environment : base
active env location : /opt/conda
shell level : 1
user config file : /home/jovyan/.condarc
populated config files : /opt/conda/.condarc
conda version : 4.8.5
conda-build version : not installed
--- MORE LINES
您可以找到安装了哪些 Python 包:
(base) jovyan@cb8b4579b2a6:~$ pip list

运行容器中的运行 pip 列表。作者图片
熊猫,numpy 等不装。您可以使用pip install pandas numpy安装它们:
(base) jovyan@cb8b4579b2a6:~/work$ pip install pandas numpy
您可以使用exit退出 bash。CTRL-C 退出一个正在运行的容器。
停止和移除容器和图像
让我们停止一个正在运行的容器:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb8b4579b2a6 jupyter/minimal-notebook "tini -g -- start-no…" 4 hours ago Up 4 hours 0.0.0.0:8888->8888/tcp suspicious_allen
您可以使用docker container stop <container-id>停止容器:
$ docker container stop cb8b
您可以找到包括非活动容器在内的所有容器:
$ docker container ls -a
# or
$ docker ps -a
您可以列出 docker 图像:
$ docker images
您可以使用docker rmi <image-id>删除图像。
$ docker rmi -f <image-id>
-f在不停止容器的情况下强制移走正在运行的容器。
如果您想要一次移除所有图像:
$ docker rmi $(docker images -a -q)
-a允许我们删除所有图像,删除后-q显示数字 id。
您可以用同样的方式使用“移除所有容器”:
$ docker rm $(docker ps -a -q)
使用 **--rm** 可以用[--rm](https://docs.docker.com/engine/reference/run/#clean-up---rm)运行一个容器,当退出容器时自动清理容器。
$ docker run --rm jupyter/minimal-notebook
退出容器后,您不需要运行docker ps -a和docker rm <image-id>。
您可以将选项与-it结合使用。
$ docker run -it --rm jupyter/minimal-notebook bash
(base) jovyan@c803e897b718:~$
当您运行这个命令时,您可以在容器中使用 bash,当您退出时,它将清理容器。
将本地目录连接到 Docker 容器
Docker 卷是默认 Docker 文件系统之外的目录(或文件),作为普通目录和文件存在于主机文件系统中。卷不会增加使用它的容器的大小,并且卷的内容存在于给定容器的生命周期之外。
我们可以使用-v选项创建一个卷。
$ docker run -p 8888:8888 -v /Users/yourname/yourdirectory:/home/jovyan/work jupyter/minimal-notebook
如果要使用当前工作目录,使用$(pwd)。
$ docker run -p 8888:8888 -v $(pwd):/home/jovyan/work jupyter/minimal-notebook

使用卷运行 docker run。作者图片

Jupyter 笔记本在浏览器上显示本地目录。
无论您在 Jupyter 笔记本中做了什么更改,它也会更改您的本地文件。
检查集装箱
您可以检查码头集装箱:
$ docker inspect <container-id or container-name>
它返回 docker 对象信息。
Docker 文件入门
让我们在创建容器时安装所有 Python 包。
创建一个新目录和一个名为 Dockerfile 的文件,内容如下:
ARG BASE_CONTAINER=jupyter/minimal-notebook
FROM $BASE_CONTAINERLABEL author="Shinichi Okada"USER rootRUN pip install pandas numpy matplotlib plotly# Switch back to jovyan to avoid accidental container runs as root
USER $NB_UID
然后运行docker build:
$ docker build -t shinokada/jupyter-notebook .
$ docker run -p 8888:8888 -v /Users/shinokada/DataScience:/home/jovyan/work shinokada/jupyter-notebook
打开另一个终端标签:
$ docker ps
$ docker exec -it <container-id> /bin/bash
(base) jovyan@a56262d7eabc:~$ pip list
...
matplotlib
...
numpy
...
pandas
我们使用docker exec进入一个正在运行的容器,并列出 Python 包,看看我们的包是否已安装。
将图像发布到 Docker Hub
在 hub.docker 注册,然后在您的终端:
$ docker login
Username: your username
Password: your password
...
$ docker push shinokada/jupyter-notebook

我在码头中心的回购。作者图片
更多 docker 命令
# Show the history of image
docker history <image-id>
# Display system-wide information
docker info | more
结论
[jupyter/scipy-notebook](https://hub.docker.com/r/jupyter/scipy-notebook)是一个 Jupyter 笔记本科学 Python 堆栈,它包含了科学 Python 生态系统中的流行包。如果你想尝试深度学习,那么[jupyter/tensorfolow-notebook](https://hub.docker.com/r/jupyter/tensorflow-notebook)适合你。它包括流行的 Python 深度学习库。你可以在这些 链接找到更多图片。
你不仅可以把 docker 用于 Jupyter 笔记本,也可以用于你的一般开发。Docker Hub 上有许多存储库。尝试找到你可以信任的官方网站,或者创建你自己的网站,然后推送至 Docker Hub。您将不再需要在您的系统上更新 Python 包。
通过 成为 会员,获得媒体上所有故事的访问权限。

请订阅。
如何使用 Docker 运行 MySQL 和 phpMyAdmin
原文:https://towardsdatascience.com/how-to-run-mysql-and-phpmyadmin-using-docker-17dfe107eab7?source=collection_archive---------5-----------------------
Docker 简化了 MySQL 管理

照片由 bongkarn thanyakij 从 Pexels 和 Guillaume Bolduc 在 Unsplash
对于许多人来说,使用命令行界面管理 MySQL 服务器可能很困难。当我们可以使用图形界面时,事情就变得简单多了。数据库管理工具 phpMyAdmin 解决了这个问题。我们可以在网络界面上使用这个工具。它支持 MySQL 和 MariaDB 的各种操作,比如导入数据、导出数据、执行 SQL 语句等等。
我们将使用 Docker 进行设置,因为在不同的机器上运行和管理 phpMyAdmin 对于环境管理来说是一件令人头疼的事情。Docker 通过使用其容器化技术解决了这个问题,该技术使用 Docker 图像。之前,我已经讨论过如何使用 Docker 运行 MySQL。你可以阅读下面的帖子,我在里面讲述了 MySQL 和 Docker 的一些基本概念和命令。
[## 如何使用 Docker 运行 MySQL
轻松运行 MySQL
towardsdatascience.com](/how-to-run-mysql-using-docker-ed4cebcd90e4)
从这篇文章中,你将学习如何使用 Docker 将 phpMyAdmin 连接到 MySQL 服务器。这种方法将节省您的时间和精力,因为您不必安装或配置 phpMyAdmin 和 MySQL。
设置
有两种方法我们可以使用 Docker 连接 phpMyAdmin 和 MySQL。在第一种方法中,我们将使用单个 Docker 合成文件。对于第二个,我将向您展示如何连接到一个已经运行的 MySQL Docker 容器。首先,你需要安装 Docker 。两种方法我都用 macOS。
方法 1
在这个方法中,我们将使用一个 Docker 编写文件。我们需要将docker-compose.yml放入一个文件夹中。这个设置中使用的文件夹名是 phpMyAdmin 。让我们来分解一下docker-compose.yml文件的各个成分。
version: '3.1'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
ports:
- "3308:3306"
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
restart: always
environment:
PMA_HOST: db
PMA_USER: root
PMA_PASSWORD: root
ports:
- "8080:80"
首先,我们使用版本标记来定义合成文件格式,即 3.1。还有其他文件格式— 1、2、2.x 和 3.x。从 Docker 的文档中获取有关合成文件格式的更多信息,请点击。
我们通过服务散列来跟随我们的版本标签。在这里面,我们必须定义我们的应用程序想要使用的服务。对于我们的应用程序,我们有两个服务, db、和 phpmyadmin 。
为了使我们的设置过程快速简单,我们使用预先构建的官方图片 MySQL 和 phpMyAdmin 作为图片标签。
当我们使用 always 作为重启标签时,容器总是重启。这样可以节省时间。例如,您不必在每次手动重启机器时都启动容器。当 Docker 守护进程重新启动或者容器本身被手动重新启动时,它会重新启动容器。
我们已经在环境标记下定义了环境变量,我们将使用这些变量进行数据库和 phpMyAdmin 认证。
最后,ports 标记用于定义主机和容器端口。对于 db 服务,它将主机上的端口 3308 映射到 MySQL 容器上的端口 3306。对于 phpmyadmin 服务,它将主机上的端口 8080 映射到 phpMyAdmin 容器上的端口 80。
现在从docker-compose.yml文件所在的目录运行下面的命令。命令docker compose up启动并运行你的整个应用。如果您遇到以下错误,这意味着您已经在端口 3308 上运行 Docker 容器。要解决这个问题,您必须更改到不同的端口,或者您可以停止另一个容器。
Bind for 0.0.0.0:3308 failed: port is already allocated
现在选择任意一个网络浏览器,进入以下地址。
http://localhost:8080
瞧啊。您应该会在浏览器上看到如下所示的网页。

管理面板
正如你所看到的,在底部有一个警告信息。让我们现在就解决这个问题。

首先,点击找出原因链接

现在点击创建链接
您已经准备好管理您的数据库了!
方法 2
在这个方法中,您将学习如何将 phpMyAdmin docker 容器连接到已经运行的 MySQL 容器。当 docker-compose 文件中没有 phpMyAdmin 服务时,这很有帮助。
首先,我们需要使用以下命令列出所有当前的 Docker 网络。
docker network ls
现在你应该可以从列表中看到phpmyadmin_default。我们的目标是找到我们在方法一中使用 docker-compose 文件创建的应用程序网络。由于我们没有在 docker-compose 文件中为我们的应用程序指定一个网络名称,docker 将根据目录名给出网络名称,并在末尾加上_default。在这种情况下,phpmyadmin_default。如果你对 Docker networks 感兴趣,点击查看。
干得好,您已经成功识别了网络!最后,我们可以运行一个独立的 phpMyAdmin Docker 容器,它连接到我们想要的网络。
docker run --name stand-alone-phpmyadmin --network phpmyadmin_default -p 8081:80 phpmyadmin/phpmyadmin:latest
docker run命令用于从映像运行容器。这里我们使用的是phpmyadmin/phpmyadmin:latest图像。
--name标志(可选)用于给容器一个特定的名称。如果不想提供,Docker 会随机分配一个名字。
—-network标志用于连接到 Docker 网络。
-p标志已经在这篇文章中讨论过了。
现在选择任意一个网络浏览器,进入以下地址。使用root作为用户名和密码登录。
http://localhost:8081/index.php
当您想要连接多个 Docker 容器时,这种方法很有用。
包裹
当我们使用命令行界面时,数据库管理可能是一项艰巨的任务。基于网络的工具 phpMyAdmin 解决了这个问题,Docker 使整个过程更加顺畅。我使用这个设置来试验 MySQL 查询,这样可以节省很多时间。通过使用 Docker,我不必担心 MySQL 和 phpMyAdmin 的设置。我希望这能帮助你开始使用 MySQL、phpMyAdmin 和 Docker。
相关帖子
[## 如何在 Docker 容器中挂载目录
专注于编写代码,无需担心环境管理
towardsdatascience.com](/how-to-mount-a-directory-inside-a-docker-container-4cee379c298b)
如何使用 Docker 运行 MySQL
原文:https://towardsdatascience.com/how-to-run-mysql-using-docker-ed4cebcd90e4?source=collection_archive---------1-----------------------
轻松运行 MySQL

图片来自推特:@jankolario 在 Unsplash
如果你是数据库管理员、数据科学家或开发人员,你可能必须使用 MySQL 来存储和操作数据。由于 Docker 近年来已经成为一个流行的 DevOps 工具,你最终需要知道如何在 Docker 容器中运行 MySQL。
由于环境管理的原因,在不同的机器上运行您的应用程序可能会令人头疼。Docker 通过使用其容器化技术解决了这个问题,该技术使用 Docker 图像。如果你是 Docker 的新手,或者想提高你的技能,请阅读下面的帖子,我已经介绍了一些基础知识。
[## 如何在 Docker 容器中挂载目录
专注于编写代码,无需担心环境管理
towardsdatascience.com](/how-to-mount-a-directory-inside-a-docker-container-4cee379c298b)
一旦你完成了本教程,你就可以使用 Docker 测试任何 MySQL 查询了。这种方法将节省您的时间和精力,因为您不必安装或配置 MySQL。
设置
首先,你需要安装 Docker 。对于这个例子,我们将使用一个 Docker 组合文件,一个包含引导数据的 SQL 文件,也称为 mysql-dump 和 macOS。我们需要将docker-compose.yml和school.sql文件放在同一个文件夹中。这个设置中使用的文件夹名是 MySQL-Snippets 。
- Docker Compose: 我们可以使用 Docker Compose 运行多个容器,并在一个 YAML 文件中定义它们的属性。这些容器被称为服务。当您的应用程序有多个堆栈时,比如一个 web 服务器和一个数据库服务器,这是很有帮助的。
- MySQL-dump:MySQL-dump 包含纯文本格式的 MySQL 查询。MySQL 命令行客户端可以运行这些命令,并将它们发送到 MySQL 服务器。
让我们来分解一下docker-compose.yml文件的各个组成部分。
version: '3.1'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test_db
ports:
- "3307:3306"
volumes:
- $HOME/Desktop/MySQL-Snippets/school.sql:/school.sql
首先,我们使用版本标记来定义合成文件格式,即 3.1。还有其他文件格式— 1、2、2.x 和 3.x。从 Docker 的文档中获取更多关于合成文件格式的信息此处。
我们通过服务散列来跟随我们的版本标签。在这里面,我们必须定义我们的应用程序想要使用的服务。对于我们的应用程序,我们只有一个名为 db 的服务。
为了使我们的设置过程快速简单,我们使用预先构建的官方图片 MySQL 作为图片标签。
当我们使用 always 作为重启标签时,容器总是重启。这样可以节省时间。例如,您不必在每次手动重启机器时都启动容器。当 Docker 守护进程重新启动或者容器本身被手动重新启动时,它会重新启动容器。
在环境标签下,我们定义了环境变量,我们将使用这些变量进行数据库认证。
ports 标记用于定义主机端口和容器端口。它将主机上的端口 3307 映射到容器上的端口 3306。
最后,卷标签用于将文件夹从主机挂载到容器。它包含由冒号分隔的两个字段。第一部分是主机中的路径。第二部分是容器中的路径。如果您不想将 mysql-dump 挂载到容器中,请删除这一部分。
很好,你已经完成了这篇文章的设置。现在从docker-compose.yml文件所在的目录运行下面的命令。命令docker compose up启动并运行你的整个应用。
docker compose up

现在在主机上运行docker ps命令,查看正在运行的容器列表。正如我们所看到的,我们有一个名为mysql-snippets_db_1的运行容器。

docker ps
我们还可以看到一个图像是通过运行docker images命令创建的。

docker images
通过运行以下命令来访问正在运行的容器mysql-snippets_db_1。
docker exec -it mysql-snippets_db_1 bash
docker exec命令允许我们进入正在运行的容器。标志-i -t(通常写为-it)用于以交互模式访问容器。现在我们提供想要访问的容器的名称,在本例中是mysql-snippets_db。bash命令用于获取容器内部的 bash shell,因此我们可以访问 MySQL 命令行并执行 MySQL 查询。
您刚刚完成了容器的设置。现在,我们将演练如何连接到 MySQL 服务器。

连接到 MySQL 服务器
使用您的用户名和密码root连接到 MySQL 服务器。一旦连接到服务器,您就可以运行 MySQL 命令。
mysql -uroot -proot
这里有一个例子,你可以试试:

显示数据库;
我们可以看到名为 test_db 的数据库,它定义在我们的 Compose 文件中。要选择数据库,运行USE test_db;命令。使用SHOW TABLES;命令显示我们数据库 test_db 的所有表格。键入ctrl + L清除控制台。

因为我们没有任何表,所以命令SHOW TABLES;返回了一个空集。现在您已经确认您已经连接到 MYSQL 服务器,您可以进入下一步。
从文件中加载数据
现在我们可以将 MySQL 转储加载到我们的test_db数据库中。在这种情况下是school.sql。它在容器内部是可访问的,因为我们已经从主机装载了它。
mysql -uroot -p test_db < school.sql
使用用户名root连接到 MySQL 服务器。输入密码root 进行验证。现在我们将默认数据库设置为test_db。<和文件名一起用于向服务器发送命令。

将 mysql 转储导入到 sql server
如果我们运行 MySQL 命令SHOW TABLES,我们可以在数据库test_db中看到两个名为 marks 和 students 的表,它们是在school.sql中定义的。

包裹
像 MySQL 这样的关系数据库在行业中经常使用,所以这是一个您想要彻底了解的主题。现在您已经完成了这个基础教程,您可以使用 Docker 更深入地探索 MySQL。你可以在这里找到更多的 MySQL 命令。Docker 彻底改变了我们管理环境的方式,包括开发、测试和生产。这就是为什么你必须为个人和工业目的获得这种技能。希望这能帮助你入门 MySQL 和 Docker。
如何从脚本运行 Scrapy
原文:https://towardsdatascience.com/how-to-run-scrapy-from-a-script-ff07fd6b792b?source=collection_archive---------13-----------------------

未飞溅
忘掉 Scrapy 的框架,全部用使用 Scrapy 的 python 脚本来写。
Scrapy 是一个用于抓取项目的很好的框架。但是,您知道有一种方法可以直接从脚本运行 Scrapy 吗?
查看文档,有两种方法可以运行 Scrapy。使用 Scrapy API 或框架。
在本文中,您将了解到
- 为什么你会用剧本里的 scrapy
- 理解基本脚本,每次你想从一个单独的脚本访问 scrapy
- 了解如何指定定制的 scrapy 设置
- 了解如何指定 HTTP 请求供 scrapy 调用
- 了解如何在一个脚本下使用 scrapy 处理这些 HTTP 响应。
为什么要用剧本里的 Scrapy?
Scrapy 可以用于繁重的刮擦工作,但是,有很多项目非常小,不需要使用整个 scrapy 框架。这就是在 python 脚本中使用 scrapy 的原因。不需要使用整个框架,你可以从一个 python 脚本中完成所有工作。
在充实一些必要的设置之前,让我们看看这个的基本情况。

https://unsplash.com/@contentpixie
基本脚本
在 python 脚本中运行 scrapy 的关键是 CrawlerProcess 类。这是一个爬虫类模块。它提供了在 python 脚本中运行 scrapy 的引擎。在 CrawlerProcess 类代码中,导入了 python 的 twisted 框架。
Twisted 是一个 python 框架,用于输入和输出过程,例如 HTTP 请求。现在它通过一种叫做龙卷风事件反应堆的东西来做到这一点。Scrapy 是建立在 twisted 之上的!我们在这里不会涉及太多的细节,但是不用说,CrawlerProcess 类导入了一个 twisted reactor,它监听像多个 HTTP 请求这样的事件。这是 scrapy 工作的核心。
CrawlerProcess 假设 twisted 反应器没有被其他任何东西使用,例如另一个蜘蛛。
有了这些,我们就有了下面的代码。
import scrapy
from scrapy.crawler import CrawlerProcessclass TestSpider(scrapy.Spider):
name = 'test'if __name__ == "__main__":
process = CrawlerProcess()
process.crawl(TestSpider)
process.start()
- 现在我们要使用 scrapy 框架,我们必须创建我们的蜘蛛,这是通过创建一个继承自 scrapy.Spider. scrapy 的类来完成的。蜘蛛是所有 scrapy 项目中我们必须衍生的最基本的蜘蛛。有了这个,我们必须给这个蜘蛛一个名字让它运行/蜘蛛将需要几个函数和一个 URL 来抓取,但是对于这个例子,我们将暂时省略它。
- 现在你看
if __name__ == “__main__”。这在 python 中被用作最佳实践。当我们编写一个脚本时,你希望它能够运行代码,而且能够将代码导入到其他地方。关于这一点的进一步讨论,请参见这里的。 - 我们首先实例化类 CrawlerProcess 来访问我们想要的函数。CrawlerProcess 有两个我们感兴趣的函数,爬行和启动
- 我们使用爬行来启动我们创建的蜘蛛。然后,我们使用 start 函数启动 twisted reactor,这个引擎处理并监听我们想要的 HTTP 请求。

https://unsplash.com/@jplenio
在设置中添加
scrapy 框架提供了一个设置列表,它将自动使用,但是为了使用 Scrapy API,我们必须明确地提供设置。我们定义的设置是我们如何定制我们的蜘蛛。蜘蛛。蜘蛛类有一个变量叫做custom_settings。现在这个变量可以用来覆盖 scrapy 自动使用的设置。我们必须为我们的设置创建一个字典来做到这一点,因为使用 scrapy 将custom_settings变量设置为无。
你可能想使用 scrapy 提供的一些或大部分设置,在这种情况下,你可以从那里复制它们。或者,可以在这里找到内置设置列表。
class TestSpider(scrapy.Spider):
name = 'test'
custom_settings = { 'DOWNLOD_DELAY': 1 }

https://unsplash.com/@ericjamesward
指定要抓取的 URL
我们已经展示了如何创建一个蜘蛛并定义设置,但是我们还没有指定任何要抓取的 URL,或者我们想要如何指定对我们想要从中获取数据的网站的请求。例如,参数、头和用户代理。
当我们创建 spider 时,我们还启动了一个叫做start_requests()的方法。这将为我们想要的任何 URL 创建请求。现在有两种方法可以使用这个方法。
1)通过定义start_urls属性
2)我们实现了我们的函数start_requests
最短的方法是通过定义start_urls。我们将它定义为我们想要获取的 URL 列表,通过指定这个变量,我们自动使用start_requests()遍历我们的每个 URL。
class TestSpider(scrapy.Spider):
name = 'test'
custom_settings = { 'DOWNLOD_DELAY': 1 }
start_urls = ['URL1','URL2']
但是请注意,如果我们这样做,我们不能指定我们的头,参数或任何其他我们想随请求?这就是实现我们的start_requests方法的原因。
首先,我们定义我们希望与请求一致的变量。然后我们实现我们的start_requests方法,这样我们就可以利用我们想要的头和参数,以及我们想要响应去哪里。
class TestSpider(scrapy.Spider):
name = 'test'
custom_settings = { 'DOWNLOD_DELAY': 1 }
headers = {}
params = {} def start_requests(self):
yield scrapy.Requests(url, headers=headers, params=params)
这里我们访问 Requests 方法,当给定一个 URL 时,它将发出 HTTP 请求并返回一个定义为response变量的响应。
你会注意到我们没有指定回调。也就是说,我们没有指定 scrapy 应该将response 发送到哪里,我们只是告诉它为我们获取请求。
让我们来解决这个问题,默认情况下,scrapy 希望回调方法是解析函数,但它可以是我们想要的任何东西。
class TestSpider(scrapy.Spider):
name = 'test'
custom_settings = { 'DOWNLOD_DELAY': 1 }
headers = {}
params = {} def start_requests(self):
yield scrapy.Requests(url, headers=headers, params=params,callback = self.parse) def parse(self,response):
print(response.body)
这里我们定义了接受响应变量的函数parse ,记住这是在我们让 scrapy 执行 HTTP 请求时创建的。然后,我们要求 scrapy 打印响应正文。
至此,我们已经有了在 python 脚本中运行 scrapy 的基础。我们可以使用所有相同的方法,但我们只需要事先做一些配置。
练习
- 为什么你会使用 scrapy 框架?在 python 脚本中导入 scrapy 什么时候有用?
CrawlerProcess班是做什么的?- 您能回忆起 python 脚本中用于启动 scrapy 的基本脚本吗?
- 如何在你的 python 脚本中添加 scrapy 设置?
- 为什么你会使用
start_requests函数而不是start_urls?
请参见这里的了解我在博客和其他帖子上关于项目的更多细节。更多技术/编码相关内容,请点击这里订阅我的简讯
我将非常感谢任何评论,或者如果你想与 python 合作或需要帮助,请联系我。如果你想和我联系,请在这里联系。
你可能喜欢的其他文章
[## 你应该知道的 5 个 Python 技巧
如何轻松增强 python 的基础知识
medium.com](https://medium.com/swlh/5-python-tricks-you-should-know-d4a8b32e04db) [## 揭开杂乱物品装载器的神秘面纱
自动清理和扩展你的垃圾蜘蛛
towardsdatascience.com](/demystifying-scrapy-item-loaders-ffbc119d592a)
如何从 Jupyter 笔记本运行 SQL 查询
原文:https://towardsdatascience.com/how-to-run-sql-queries-from-a-jupyter-notebook-aaa18e59e7bc?source=collection_archive---------5-----------------------
SQL IDEs 不能可视化数据。您知道吗,您可以使用 Jupyter 笔记本运行并可视化查询结果?

本·怀特在 Unsplash 上的照片
如果你在数据科学领域工作,你很可能会使用 SQL 来提取和预处理数据。我使用 JetBrains DataGrip 作为我的主要 SQL 编辑器已经有一段时间了。虽然 DataGrip 做得不错,但它没有提供可视化数据的方法。有没有更好的办法?
这里有几个你可能会感兴趣的链接:
- [Complete your Python analyses 10x faster with Mito](https://trymito.io/) [Product]- [Free skill tests for Data Scientists & ML Engineers](https://aigents.co/skills) [Test]- [All New Self-Driving Car Engineer Nanodegree](https://imp.i115008.net/c/2402645/1116216/11298)[Course]
你愿意多看一些这样的文章吗?如果是这样,你可以点击上面的任何链接来支持我。其中一些是附属链接,但你不需要购买任何东西。
用于 SQL 的 ide

Gif 来自 Giphy
SQL 的集成开发环境通常不具备可视化查询结果的能力。在我看来,这是一件好事,因为每个 IDE 都有自己专有的方式来可视化数据,这是我们需要学习的。
我可视化数据的工作流程是:在 SQL IDE 中开发并执行查询,将数据导出到 CSV 并在 Jupyter 笔记本中可视化。
在 Jupyter 笔记本中运行查询

Gif 来自 Giphy
当查询结果太大而无法在单个查询中处理时,该怎么办?一种解决方案是以更短的时间间隔运行查询,而不是一整年,您可以按月运行查询。
按月运行一个查询需要一年运行 12 次,这对于手工来说是不可行的——因为循环在这里很有用。
拥有多种工具总是好的
当面临这样的问题时,我一直使用 SQLAlchemy 连接到数据库,并将数据提取到 pandas DataFrame,如下例所示:
import sqlalchemy
import pandasengine = sqlalchemy.create_engine(
sqlalchemy.engine.url.URL(
drivername="postgresql",
username="username",
password="password",
host="host",
port="port",
database="database",
),
echo_pool=True,
)
print("connecting with engine " + str(engine))
connection = engine.connect()query = "select * from table"df = pd.read_sql_query(query, connection)
正如您在上面看到的,SQL 查询是用字符串编写的。即使您将查询字符串放在 Jupyter 笔记本的一个单独的单元格中,并且安装了格式化的 SQL 代码,它也不会格式化查询,因为它仍然是一个 Python 字符串。
有没有更好的办法?
认识 ipython-sql
ipython-sql 使我们能够直接从 Jupyter 笔记本上运行 sql 查询。无需编写多行代码来连接数据库或将查询包装在字符串中。ipython-sql 使得从 Jupyter Notebook 查询数据库更加“干净”。

使用 ipython-sql 查询 SQLite 数据库
要安装 ipython-sql,只需在 Jupyter 笔记本中运行以下命令:
!pip install ipython-sql
然后加载 SQL 模块:
%load_ext sql
我们需要一个连接字符串来连接数据库。对于 SQLite,它非常简单:
%sql sqlite://
如果您以前使用过 SQLAlchemy 连接到数据库,您可以使用下面的代码来获得连接字符串:
print("connecting with engine " + str(engine))
注意,每个单元格都需要用%%sql 注释。这告诉 Jupyter 笔记本,单元格中的代码是 SQL。
让我们将示例数据添加到 SQLite 数据库中:
%%sql
CREATE TABLE sales
(
key varchar(6),
ts timestamp,
product integer,
completed boolean,
price float
);
INSERT INTO sales
VALUES ('sale_1', '2019-11-08 00:00', 0, TRUE, 1.1),
('sale_2', '2019-11-08 01:00', 0, FALSE, 1.2),
('sale_3', '2019-11-08 01:00', 0, TRUE, 1.3),
('sale_4', '2019-11-08 01:00', 1, FALSE, 1.4),
('sale_5', '2019-11-08 02:00', 1, TRUE, 1.5),
('sale_6', '2019-11-08 02:00', 1, TRUE, 1.5);

现在,让我们查询数据库
%%sqlselect * from sales;

非常管用!
我们只运行了查询,但是结果没有分配给任何变量,这没有多大用处。幸运的是,Jupyter Notebook 使我们能够将一个单元格的先前输出设置为一个变量:
result = _
让我们检查结果变量的类型:
type(result)# sql.run.ResultSet
现在,让我们使用以下方法将结果集直接转换为 pandas 数据帧:
df = result.DataFrame()

这使我们能够交互式地探索数据。

在你走之前
在推特上关注我,在那里我定期发关于数据科学和机器学习的推特。

照片由Courtney hedge在 Unsplash 上拍摄
如何对数据进行采样(使用代码)
原文:https://towardsdatascience.com/how-to-sample-data-with-code-327359dce10b?source=collection_archive---------23-----------------------
使用 Cochran 公式采样——在 Python、R 和 Excel 中

凯文·Ku 在 Unsplash 上的照片
对于任何处理数据的人来说,采样都是一项至关重要的技能。尽管如此,令人惊讶的是很少有人做对。通常,取样是根据判断而不是逻辑进行的。
对我们来说幸运的是——对数据集进行采样是一项极其简单的任务。
在本文中,我们将介绍计算样本大小的 Cochran 公式,它不会使我们的测试无效。
我们将包括简单的数学方法和符号,展示我们如何手动计算它们——然后继续用 Python、R 和 Excel 实现。
最后,我们将组装一个快速样本大小计算器来演示采样有多简单。
关键参数
- confidence level
- margin of error
- target proportion
所以,我们有一个数据集。我们需要对这个数据集的一部分进行采样,以便进行一些手动的定性分析。
从统计学上来说,我们需要足够大的样本量,才能确信我们所取的样本准确地代表了原始总体(数据集)。这个置信度被称为置信度。
95%的置信度是最常见的——这是我们将在本文通篇使用的。但是,如果需要更多/更少的置信度,我们只需调整我们的公式输入。
通常,我们的分析对样本和总体代表之间的微小差异不敏感。因此,我们接受一定程度的灵活性,我们称之为误差幅度。同样,典型值约为 5%。
将两者放在一起,我们可以 95%确信我们计算的样本平均值在 5%的范围内等于总体平均值。
最后一个参数目标比例是提供目标属性的样本的百分比。当这一点不清楚时(几乎总是如此),简单地使用 50% —最坏的情况。
对我们的数据进行采样
我们现在需要为我们的测试或开发过程提取这些数据的样本。
我们如何知道我们的样本应该有多大才能准确地代表我们的总体?
这就是我们可以使用科克伦公式的地方:

使用该公式,我们可以计算满足我们要求的误差范围和置信水平所需的样本量。如果我们要查看数据集中的特定属性,我们还可以指定包含该属性的估计人口比例,尽管这不是必需的。
因此,我们有一个包含 100,000 条记录的数据集。我们的样本中应该包括多少这样的样本?
假设我们希望我们的样本有 95%的把握正确代表总体。我们也可以接受 5%的误差率。
population size: 100K - **N = 100000**
confidence level: 95% - **cl = 0.95**
margin of error: 5% - **e = 0.05** target proportion: 50% - **p = 0.5**

首先,我们有了计算 n₀ 所需的所有参数,除了z(z 分数)。为了找到 z 分数,我们将从0.95到0.475的置信水平减半,然后在 z 分数表中查找这个值,这给出了1.96。

我们在表中发现我们的置信水平减半为 0.475。z 值由坐标轴上的值给出, 1.9 + 0.06 ,得出 1.96 。在这里找到表格。
或者,我们可以使用 Python、R 或 Excel 来计算。
**Python**
-----
import scipy.stats as st
st.norm.ppf(1-(1-**0.95**)/2)
**[Out]:** 1.959964
**R**
-----
qnorm(1-(1-**0.95**)/2)
**[1]:** 1.959964
**Excel**
-----
=NORMSINV(1-(1-**0.95**)/2)
1.959964
注意,在每个代码中,我们执行相同的1-(1-0.95)/2计算。这是因为每个实现都会计算左尾单分布的 z 得分,如下所示:

相反,我们想要的是一个居中对齐的区域,看起来像这样:

现在我们有了所有需要的值,我们计算 n₀:

为了满足我们的抽样需求,我们应该将这个数据四舍五入为385个记录。我们取整,因为这是我们的阈值——任何低于384.15的都将具有低于 95%的置信水平,或者大于 5%的误差幅度。
要在代码中执行此计算,我们需要执行以下操作:
**Python**
-----
z**2 * p * (1 - p) / e**2
**[Out]:** 384.15
**R**
-----
z^2 * p * (1 - p) / e^2
**[1]:** 384.15
**Excel** *(replace each letter with the respective cell)*
-----
=z^2*p*(1-p)/e^2
384.15

第二个公式是我们用于小数据集的公式;它根据总体规模 N 调整我们所需的样本规模。
较小的数据集将减少所需样本的数量,而较大的数据集则不会。
使用我们的总体规模**N = 100,000**会导致我们所需的样本规模略有减少:

给我们一个最终所需的**383**记录的样本量。在代码中再次执行同样的计算,我们得到:
**Python**
-----
n_0 / (1 + (n_0 - 1) / N)
**[Out]:** 382.68
**R**
-----
n_0 / (1 + (n_0 - 1) / N)
**[1]:** 382.68
**Excel** *(replace each letter with the respective cell)*
-----
=n_0/(1+(n_0-1)/N)
382.68
这样,我们就有了一个简单的、可重复的方法来计算样本量。如果我们更进一步,我们可以用代码实现整个过程,使我们未来的采样更加容易。
在 Python 中,我们可以构建一个简单的样本大小计算器,如下所示:
使用前面示例中的相同参数,我们可以轻松计算样本大小:
sample(100000, 0.95, 0.05, 0.5)
[Out]: 383
我们还可以看到人口规模如何影响较小样本的计算:
sample(**500**, 0.95, 0.05, 0.5)
**[Out]:** 218
sample(**20**, 0.95, 0.05, 0.5)
**[Out]:** 20
sample(**1e8**, 0.95, 0.05, 0.5)
**[Out]:** 385
当然,我们在 R 和 Excel 中也是这样做的,将我们之前讨论过的代码串连在一起。
我们已经从理论和实现两方面介绍了样本量计算的基础知识。
对于不同数据专业中的大多数采样要求,您不需要比这更复杂的东西——Cochren 的公式广泛适用,并且非常容易实现。
如果您有任何问题或建议,请在下面的回复中告诉我!
感谢阅读!
如何在 PyTorch 中保存和加载模型,并附有完整的示例
原文:https://towardsdatascience.com/how-to-save-and-load-a-model-in-pytorch-with-a-complete-example-c2920e617dee?source=collection_archive---------0-----------------------
如何在 PyTorch 中保存和加载模型的实例。我们将看看如何继续训练和加载模型进行推理

詹姆斯·哈里逊在 Unsplash 上拍摄的照片
T 这篇文章的目的是告诉你如何保存一个模型,并在上一个时期后加载它继续训练,并做出预测。如果你正在阅读这篇文章,我假设你熟悉深度学习和 PyTorch 的基础。
你有没有经历过这样的情况,你花了几个小时或几天训练你的模型,然后它在中途停止?还是对自己的模特表现不满意,想重新训练模特?我们可能需要一种灵活的方式来保存和加载我们的模型,这有多种原因。
Kaggle、Google Colab 等大多数免费云服务都有空闲超时,会断开你的笔记本,加上笔记本一旦达到限制时间就会断开连接或中断。除非你用 GPU 训练少量的纪元,否则这个过程需要时间。能够保存模型会给你带来巨大的优势并扭转局面。为了灵活起见,我将保存最新的检查点和最佳的检查点。
时尚 _ MNIST _ 数据将被用作我们的数据集,我们将从导入数据编写一个完整的流程来进行预测。在这个练习中,我将使用一个 Kaggle 笔记本。
步骤 1:设置
- 在 Kaggle 中,你正在操作的笔记本默认叫做 notebook。ipyn
- 创建两个目录来存储检查点和最佳模型:
步骤 2:导入库和创建助手函数
导入库
保存功能
创建 save_ckp 是为了保存检查点,最新的和最好的检查点。这就产生了灵活性:要么您对最新检查点的状态感兴趣,要么对最佳检查点感兴趣。
在我们的例子中,我们希望保存一个检查点,使我们能够使用这些信息来继续我们的模型训练。以下是所需的信息:
- 时期:所有训练向量被使用一次来更新权重的次数的度量。
- valid_loss_min :最小验证损失,这是需要的,以便当我们继续训练时,我们可以从这个而不是 np 开始。Inf 值。
- state_dict :模型架构信息。它包括每一层的参数矩阵。
- 优化器:您需要保存优化器参数,尤其是当您使用 Adam 作为优化器时。Adam 是一种自适应学习率方法,这意味着,它计算不同参数的个人学习率,如果我们想从我们离开的地方继续我们的训练,我们将需要这些参数[2]。
加载功能
load_chkp 是为加载模型创建的。这需要:
- 保存的检查点的位置
- 要将状态加载到的模型实例
- 优化器
步骤 3:导入数据集时尚 _ MNIST _ 数据并创建数据加载器
步骤 4:定义和创建模型
我使用的是来自[1]的简单网络
输出:
FashionClassifier(
(fc1): Linear(in_features=784, out_features=512, bias=True)
(fc2): Linear(in_features=512, out_features=256, bias=True)
(fc3): Linear(in_features=256, out_features=128, bias=True)
(fc4): Linear(in_features=128, out_features=64, bias=True)
(fc5): Linear(in_features=64, out_features=10, bias=True)
(dropout): Dropout(p=0.2)
)
步骤 5:训练网络并保存模型
训练功能使我们能够设置时期数、学习率和其他参数。
定义损失函数和优化器
下面,我们使用 Adam 优化器和交叉熵损失,因为我们把字符类分数作为输出。我们计算损耗并进行反向传播。
定义培训方法
训练模型
输出:
Epoch: 1 Training Loss: 0.000010 Validation Loss: 0.000044
Validation loss decreased (inf --> 0.000044). Saving model ...Epoch: 2 Training Loss: 0.000007 Validation Loss: 0.000040
Validation loss decreased (0.000044 --> 0.000040). Saving model ...Epoch: 3 Training Loss: 0.000007 Validation Loss: 0.000040
Validation loss decreased (0.000040 --> 0.000040). Saving model ...
让我们关注一下上面使用的几个参数:
- start_epoch:训练的值 epoch 的开始
- n_epochs:训练的值 epoch 的结束
- 有效 _ 损失 _ 最小 _ 输入= np。中程核力量
- checkpoint_path:保存训练的最新检查点状态的完整路径
- 最佳模型路径:训练的最新检查点的最佳状态的完整路径
验证模型是否已保存
- 列出 best_model 目录中的所有文件
输出:
best_model.pt
- 列出检查点目录中的所有文件
输出:
current_checkpoint.pt
步骤 6:加载模型
重建模型
输出:
FashionClassifier(
(fc1): Linear(in_features=784, out_features=512, bias=True)
(fc2): Linear(in_features=512, out_features=256, bias=True)
(fc3): Linear(in_features=256, out_features=128, bias=True)
(fc4): Linear(in_features=128, out_features=64, bias=True)
(fc5): Linear(in_features=64, out_features=10, bias=True)
(dropout): Dropout(p=0.2)
)
定义优化器和检查点文件路径
使用 load_ckp 函数加载模型
我打印出了我们从 load_ckp 得到的值,只是为了确保一切都是正确的。
输出:
model = FashionClassifier(
(fc1): Linear(in_features=784, out_features=512, bias=True)
(fc2): Linear(in_features=512, out_features=256, bias=True)
(fc3): Linear(in_features=256, out_features=128, bias=True)
(fc4): Linear(in_features=128, out_features=64, bias=True)
(fc5): Linear(in_features=64, out_features=10, bias=True)
(dropout): Dropout(p=0.2)
)
optimizer = Adam (
Parameter Group 0
amsgrad: False
betas: (0.9, 0.999)
eps: 1e-08
lr: 0.001
weight_decay: 0
)
start_epoch = 4
valid_loss_min = 3.952759288949892e-05
valid_loss_min = 0.000040
加载完所有需要的信息后,我们可以继续训练,start_epoch = 4。以前,我们从 1 到 3 训练模型
第七步:继续训练和/或推断
继续训练
我们可以继续使用 train 函数训练我们的模型,并提供我们从上面的 load_ckp 函数中获得的检查点的值。
输出:
Epoch: 4 Training Loss: 0.000006 Validation Loss: 0.000040
Epoch: 5 Training Loss: 0.000006 Validation Loss: 0.000037
Validation loss decreased (0.000040 --> 0.000037). Saving model ...
Epoch: 6 Training Loss: 0.000006 Validation Loss: 0.000036
Validation loss decreased (0.000037 --> 0.000036). Saving model ...
- 注意:纪元现在从 4 点到 6 点开始。(开始时间= 4)
- 验证丢失从最后一个训练检查点开始继续。
- 在时期 3,最小验证损失是 0.000040
- 这里,最小验证损失从 0.000040 开始,而不是 INF
推理
请记住,在运行推理之前,您必须调用 model.eval()将丢弃和批处理、规范化图层设置为评估模式。不这样做将产生不一致的推理结果[3]。
输出:
Accuracy of the network on 10000 test images: 86.58%
在 Kaggle 笔记本中哪里可以找到输出/保存的文件
在您的 Kaggle 笔记本中,您可以向下滚动到页面底部。在之前的操作中保存了一些文件。

这是我在 Kaggle 的笔记本:
https://www . ka ggle . com/vortanasay/saving-loading-and-cont-training-model-in-py torch
参考:
- [1] S. David,在 PyTorch 中保存和加载模型(2019),https://www . ka ggle . com/davidashraf/Saving-and-Loading-Models-in-py torch
- [2] J. Rachit,保存并加载您的模型以在 PyTorch 中恢复培训(2019),https://medium . com/analytics-vid hya/Saving-and-Loading-Your-Model-to-Resume-Training-in-py torch-CB 687352 fa 61
- [3]一、马修,保存和加载模型(2017),https://py torch . org/tutorials/初学者/saving_loading_models.html
如何对无用的数据科学项目说不,并开始从事你想要的工作
原文:https://towardsdatascience.com/how-to-say-no-to-projects-d6f88641ab3c?source=collection_archive---------34-----------------------
如何对无意义的忙碌说不并开始做你想做的事情的 5 个技巧:创新和增值的数据科学项目。
应利益相关者的要求,数据科学家和分析师开始用大部分无附加值的工作来溢出他们的杯子。许多人没有勇气或信心对此说“不”。这也适用于其他垂直行业和职业中的许多工作和商业专业人士。简而言之,你需要建立自信,不再懦弱,开始对无意义的工作说“不”。
数据科学家可以成为公司的新决策者,应该选择自己的增值项目
当公司雇佣数据科学团队时,该团队的客户通常是非技术利益相关者。他们对自己想从数据科学中获得什么有一个大致的想法,但他们不知道自己具体想要什么。大多数时候,业务部门认为“数据科学和分析”只是运行报告并在需要时获取数据的团队(像狗或猴子一样)。数据科学和分析团队的核心职责不是在 Tableau 和 PowerBI 中构建报告;这是商业智能团队的工作(奇怪的是,许多商业智能专业人士已经开始自称为分析师或数据科学家)。数据科学家的工作基本上是:
- 综合和挖掘数据,从中创建可行的业务建议
- 使用统计、机器学习和人工智能模型自动化决策
- 为最终用户创建数据科学产品和工具(我们在 Remix Institute 喜欢称之为 Prefab AI 或 AI Augs——类似于 Deux Ex 视频游戏系列)。像RemixAutoML这样的开源工具就是例子。
- 通过寻找收入增长、成本节约、运营效率和业务流程优化的机会来提高利润
如果业务部门的利益相关方让您的数据科学团队从事列表上没有的任何工作,或者不提供价值或增长的任何工作,那么您不应该从事这些工作。数据科学团队应该根据利益相关者的反馈和痛点挑选自己的项目。数据科学不是 IT 或 BI,不应构建报告或处理票证请求。(下面有更多相关信息)
非增值工作不断堆积的原因
许多数据科学家和非技术利益相关者没有意识到规划谬误。计划谬误是一种心理现象,它表明我们对完成一项任务需要多少时间的预测过于乐观,而低估了实际需要的时间。由于我们很难估计事情需要多长时间,这意味着我们对项目说“是”的次数比我们应该说的要多,因为我们认为完成项目需要的时间更少。这导致我们变得捉襟见肘,精疲力竭,拼命寻找最稀缺和最有价值的资源之一:时间。对项目说“是”感觉很好,因为它可能会加强你和利益相关者之间的联系,但有时人们说“是”是因为害怕被认为是低效的、消极的、工作缓慢的和非团队成员。
拒绝和选择自己项目的 5 种方法
有很多实用的方法可以对非增值项目说不,同时仍然能够被理解为一个团队成员,并且能够选择你喜欢的项目。以下是 5 种实用的拒绝方式:
1。将霍夫施塔特定律确立为您的数据科学团队的指导运营原则之一。霍夫施塔特定律是一个递归公理,它表明所花费的时间总是比你预期的要长,即使你把霍夫施塔特定律考虑在内。作为一个简单的启发,你应该把完成一个项目的时间增加两倍或三倍。这是针对规划谬误的对策。
2。礼貌地对项目请求说“不”,但是立场要坚定,不要做受气包。业务利益相关者将来自许多部门,具有相互竞争的优先级和激励机制。当他们带着对他们来说“高度优先”的项目来找你时,对公司的整体业务目标来说,这可能不是高度优先或高增长潜力的项目。一封类似这样的邮件或信息是一种礼貌的拒绝方式
“你好,我们理解对这个项目的独特渴望,它看起来像一个有趣的商业问题。在审查了需求之后,我们估计了项目完成的时间。不幸的是,这不是我们团队目前能做的事情,因为我们目前正专注于其他高优先级的增长计划,但我们可以在未来进行规划讨论。如果你有这个项目的投资回报率分析,这将有助于我们把它放在队列的顶部。”
立场坚定很重要,因为很多时候利益相关者不喜欢接受否定的答案,他们会试图甜言蜜语,说服你为什么你真的应该参与他们的项目。听他们说完,但仍然礼貌地说不。
3。通过将所有项目放在一个选择图表上来区分它们的优先级。一个选择图表是一个精益六适马工具,由洛克希德·马丁公司开发,用于组织和优先化项目想法。PICK 代表可能,实现,挑战,杀死。以下是每一项的细目分类:
- (P)可能。如果这个项目容易做,但回报低,可能会参与其中
- (一)实施。如果这个项目容易做并且回报高,那就一定要去做,并优先考虑它
- (C)挑战。如果这个项目很难做但是回报很高就挑战它
- (K)杀。杀死所有难做且低回报的项目并扔进垃圾桶

选择图表
最好的方法是选择关注左上角象限的 1 到 2 个关键项目。这种项目优先级排序就是我们在 Remix Institute 所说的“帕累托最优项目管理。”
为此,你需要将项目优先级外包给你的经理,以获得政治掩护。当然,告诉他/她你认为应该优先考虑什么(左上象限),以便从事你想从事的项目。作为一名数据科学家,你应该建议优先考虑人工智能自动化或机器学习用例的项目,并降低分析和报告请求的优先级。

帕累托最优项目管理
4。推迟任何武断的截止日期。大部分期限都只是凭空扯出来的,只是提供了不必要的压力。在过去,我看到过来自高级管理层的项目请求,附带一个任意的截止日期,过了一段时间没有听到项目的状态,高级管理层忘记了他们在第一时间分配它。在这种情况下,这个项目肯定是没有意义的无用功,没有最终期限。
这是关于高层管理的一个不为人知的事实:很多时候,他们只是故意把无用功分配给你。
然而,即使这是真的,你也不能告诉你的利益相关者。相反,你需要用一种政治上更容易接受的方式来表达这一点。类似这样的电子邮件或信息更适合推迟任意的截止日期:
“你好,我知道在截止日期前完成任务很重要。您能否将这一时间延长 X 天/周,因为我们目前正在进行高管们非常感兴趣的 PICK CHART 左上角的项目]。”
或者
"如果你想让 X 由 Y 完成,我可以给出 X 的 A 和 B,但不能给出 X 的 C 和 D。"

开始做你想做的事情。创新和高投资回报率的项目。
5。将奥卡姆剃刀确立为你的机器学习模型开发的指导性操作原则之一。这个主题本身需要另一篇博文,但是奥卡姆剃刀(或简约原则)认为模型应该是最低限度的,最简单的模型是可能的最好模型。请记住,机器学习应该简化业务流程和自动化决策,因此制作一个具有大型代码库的庞然大物模型只意味着它是一艘敏捷性低、维护成本高的军舰。这意味着你要花费大量的空闲时间来维护它,这减少了你做其他事情的时间。你还应该向你的利益相关者介绍奥卡姆剃刀,这样他们也不会使机器学习模型开发过于复杂。
如上所述,简约原则是一个有趣的话题,它本身将是另一篇博文。最简单并不总是意味着最少的技术债务或最低的维护。有时候项目确实需要复杂性。这就是为什么确定规模合适的“最低要求”解决方案非常重要。如果在 Excel 中只需要一条趋势线,那么真的需要深度学习模型吗?
结论
只要首席管理人员开始看到他们对损益的影响,数据科学家就可以成为公司及其最有价值部门的新决策者。为了做到这一点,数据科学团队必须立场坚定,树立信心,并有效地优先处理高价值工作,同时降低优先级,甚至扼杀非增值工作。这包括学习有效项目管理的技巧,礼貌地对涉众说“不”。通过这样做,数据科学团队可以专注于高投资回报率、增加收入的项目,如可以集成到业务流程中的机器学习和自动化产品。这引起了最高管理层的注意,并提升了数据科学的地位。
本文原载于 RemixInstitute.com 的
如何在每个主要的云提供商上扩展 Python
原文:https://towardsdatascience.com/how-to-scale-python-on-every-major-cloud-provider-5e5df3e88274?source=collection_archive---------41-----------------------
使用 Python 进行云计算的最佳实践
用皮雷恩创造者艾瑞克·乔纳斯、 的话说,“云太他妈硬了!”

云中的 Python。
一旦你在笔记本电脑上开发了一个 Python 应用程序,并希望在云中扩展它(可能需要更多的数据或更多的 GPU),接下来的步骤就不清楚了,除非你有一个已经为你设置好的基础设施团队,“只使用 kubernetes”并不那么简单。
因此,您将选择 AWS、GCP 和 Azure 中的一个,并导航到管理控制台来筛选实例类型、安全组、现货价格、可用性区域、实例限制等等。一旦你解决了所有这些问题,并设法租了一些虚拟机,你仍然需要弄清楚如何在这些虚拟机上运行你的应用程序。我的 Python 脚本如何在一个 10 台机器的集群中准确地分配工作?此时,您可以尝试使用 PySpark 或 mpi4py 或 Celery 来重写您的应用程序。
如果失败了,你将建立一个全新的分布式系统,就像优步和 Lyft 最近用 Fiber 和 Flyte 所做的那样。在这两种情况下,要么重写应用程序,要么构建新的分布式系统,或者两者兼而有之。这一切都是为了加速你在云中的 Python 脚本。
我们将介绍如何使用 Ray 在这些云提供商上启动集群和扩展 Python,只需几个命令。
这是图表。第一步是开发你的 Python 应用。这通常发生在您的笔记本电脑上,但是如果您愿意,也可以在云中进行。第二步是在你选择的云提供商上启动一个集群。第三步是在任何你想去的地方运行你的应用程序(你的笔记本电脑或者云端)。

通过三个步骤在任何云提供商上扩展您的 Python 应用程序。第一步:在本地开发你的应用程序(或者在云中,如果你愿意的话)。步骤 2: 在您选择的云提供商上启动集群。步骤 3: 在集群上运行您的应用程序!
设置
首先,安装一些 Python 依赖项。
**pip install -U ray \
boto3 \
azure-cli \
azure-core \
google-api-python-client**
接下来,为您选择的云提供商配置凭证。如果您已经设置为从命令行使用云提供商,则可以跳过这一步。
- AWS: 按照boto 文档中的描述在
~/.aws/credentials中配置您的凭证。 - Azure: 用
az login登录,然后用az account set -s <subscription_id>配置你的凭证。 - GCP: 按照文档中的描述设置
GOOGLE_APPLICATION_CREDENTIALS环境变量。
射线簇发射器使用了一个配置文件,看起来像这样
与射线簇发射器一起使用的最小簇配置文件。
在这里,您可以指定所有内容,包括要运行的设置命令、要使用的实例类型、要 rsync 的文件、自动缩放策略等等。
获取一个稍微完整一点的示例,带有如下的附加可配置字段。
**# AWS**
wget [https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/dafd4c6bd26fe4599dc3c6b05e80789188b3e2e5/aws-config.yaml](https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/dafd4c6bd26fe4599dc3c6b05e80789188b3e2e5/aws-config.yaml)
**# Azure**
wget [https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/dafd4c6bd26fe4599dc3c6b05e80789188b3e2e5/azure-config.yaml](https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/dafd4c6bd26fe4599dc3c6b05e80789188b3e2e5/azure-config.yaml)
**# GCP**
wget [https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/1846cbf971d1cd708b3d29d9ae50ad882fbaac50/gcp-config.yaml](https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/1846cbf971d1cd708b3d29d9ae50ad882fbaac50/gcp-config.yaml)
您需要对上面的配置文件做一些小的修改:
- 用合适的密钥文件替换
~/.ssh/id_rsa和~/.ssh/id_rsa.pub。 - GCP: 设置合适的
project_id。
步骤 1:创建一个 Python 应用程序
定义一个我们想要扩展的简单 Python 脚本。
一个简单的 Python 应用程序,可以在你的笔记本电脑或云中运行,并跟踪执行任务的机器的 IP 地址。这个脚本使用射线来并行化计算。
您可以如下运行这个示例(实际上是一个稍微完整的示例)。
**# Fetch the example.**
wget [https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/4313660c0bd40f8bd909f70c1e0abc4be8584198/script.py](https://gist.githubusercontent.com/robertnishihara/a9ce1d0d434cd52dd9b07eb57f4c3476/raw/4313660c0bd40f8bd909f70c1e0abc4be8584198/script.py)**# Run the script.**
python script.py
您将看到以下输出。
This cluster consists of
1 nodes in total
16.0 CPU resources in totalTasks executed
10000 tasks on XXX.XXX.X.XXX
现在,在光线簇上运行相同的脚本。这些说明适用于 AWS。要使用 Azure 或 GCP,只需将两行中的aws-config.yaml替换为azure-config.yaml或gcp-config.yaml。
步骤 2:启动集群
**# AWS**
ray up -y aws-config.yaml
**# Azure**
ray up -y azure-config.yaml
**# GCP**
ray up -y gcp-config.yaml
步骤 3:在集群上运行脚本
**# AWS**
ray submit aws-config.yaml script.py
**# Azure**
ray submit azure-config.yaml script.py
**# GCP**
ray submit gcp-config.yaml script.py
您将看到以下输出。
This cluster consists of
3 nodes in total
6.0 CPU resources in totalTasks executed
3561 tasks on XXX.XXX.X.XXX
2685 tasks on XXX.XXX.X.XXX
3754 tasks on XXX.XXX.X.XXX
如果它说只有一个节点,那么您可能需要多等一会儿,让其他节点启动。
在这种情况下,10,000 个任务在三台机器上运行。
您还可以连接到集群,使用以下命令之一进行探索。
**# Connect to the cluster (via ssh).# AWS**
ray attach aws-config.yaml
**# Azure**
ray attach azure-config.yaml
**# GCP**
ray attach gcp-config.yaml
关闭集群
完成后,不要忘记关闭集群!
**# AWS**
ray down -y aws-config.yaml
**# Azure**
ray down -y azure-config.yaml
**# GCP**
ray down -y gcp-config.yaml
进一步的细节
想要增加对新云提供商的支持吗?只需扩展 NodeProvider 类,这通常需要 200-300 行代码。看看 AWS 的实现。
- 了解更多关于射线集群发射器的信息。
- 从文档、 GitHub 和 Twitter 中了解更多关于 Ray 的信息。
- 了解如何缩放机器学习训练、超参数调优、模型服务、强化学习。
原贴 此处 。
如何自信地扩展您的数据团队
原文:https://towardsdatascience.com/how-to-scale-your-data-team-with-confidence-ffcbfe00bbc3?source=collection_archive---------32-----------------------
提示:这需要一些复杂的算法

供图 弗拉德 上un splash。
新冠肺炎迫使许多公司勒紧裤腰带,只投资最必要的功能——幸运的是, 数据往往是其中之一 。然而,数据团队的成功不仅仅取决于他们处理数据和构建预测模型的能力。
在过去的十年中,数据团队对于保持公司的竞争优势变得越来越重要,导致了更大的创新和更智能的决策。尽管这种指数级的崛起,然而,数据科学应用于工业 的概念直到 2000 年代初才出现。数据工程现在是许多数据驱动的技术公司不可或缺的一部分,甚至更晚才被纳入词典。
新冠肺炎让数据的影响更加明显。数据不仅对遏制致命病毒的传播至关重要,而且公司越来越依赖数据来更好地了解不断变化的客户趋势,并做出更明智的支出决策。
尽管 50%的数据分析组织 还没有调整他们的人员配备和招聘计划来应对疫情的经济影响,但初创公司已经被迫解雇了数万到数千名员工,其中许多是数据分析师、科学家和工程师。随着行业适应这种新常态,让您的数据团队为成功做好准备非常重要。
为了帮助你自信地扩展你的团队,我总结了四条简单的指导方针,让你的团队成为整个组织的力量倍增器:
定义团队的 1-2 项核心职责。相应地划分优先级。
与我交谈过的许多数据领导者都感到被落在他们肩上的各种责任所困扰。《哈佛商业评论》最近发表了一份报告,定义了 CDO 的七种不同工作,从“首席数据和分析官”和“数据管理者”到“数据企业家”和“数据伦理学家”做好一项工作已经够难的了——想象一下七项工作!
同样,麦肯锡 2018 年的一项研究表明,ROI 和数据分析之间的这种脱节是因为团队“难以从在少数成功用例中使用分析转向在整个企业中扩展分析,将其嵌入组织文化和日常决策中。”

这位数据副总裁根据其 CEO 的 OKRs 为团队设定了明确的目标,从而能够利用数据科学释放真正的商业价值。图片由this is engineering raengonUnsplash。
Rebel的高级数据科学家,一家专注于可持续和包容性交通的国际咨询公司,优步大学的前高级数据科学家,建议数据领导者在衡量数据科学如何使他们的公司受益时深入挖掘。
“从高层次考虑你公司的数据需求,”她说。“他们关心什么?他们需要更好地理解什么,什么数据会给他们这些见解?”
****和 Amy 一样,我建议使用贵公司的最高优先级来确定如何最好地利用您团队的技能组合。根据公司的核心目标,坚持 1 到 2 个主要角色。如果您的公司使用 2020 年第三季度来决定向您的用户部署哪些新产品,也许您的 KPI 应该与生成更及时的客户行为分析相关联;如果你的 CEO 希望你在欧盟推出你的服务,一个关键的职责应该是将合规工作与 GDPR 的要求对应起来。
一旦这些目标被确定,并且被你的利益相关者和 CEO 签署,只要你对你的业务需求保持灵活性,就更容易证明你的团队的成长和花费是合理的。正如我们在过去几个月中所见证的那样,任何事情都可能在瞬间改变(或者我应该说,一个数据点)。
不要纠结于头衔。
鉴于“数据科学家”和“数据分析师”这两个术语相对较新,根据您所在的行业、公司甚至团队的不同,它们可能意味着许多事情,承认这种模糊性很重要。
事实上,根据 Figma 的数据科学主管 Annie Tran 的说法,直到 2000 年代末,LinkedIn 和其他大型科技公司才开始雇佣数据科学家来更好地了解他们平台上的用户行为。在加入优步成为他们产品部门的第一位数据分析师之前,Annie 在 Willis Towers Watson 和后来的 Zynga 担任数据分析师。
“当我被优步聘用时,我的角色是数据分析师,但其他人也是如此,”她说。“在我们的市场团队工作的一些数据科学家也是数据分析师。几个月后,他们把每个人的头衔都改成了数据科学家。”
您的数据团队看起来像什么(以及您使用什么头衔)将取决于您公司的规模和您使用的数据量。如果你是一家小公司,你可以雇佣一些数据通才,随着时间的推移,他们可以开始专攻不同的学科或领域。如果你正在一家 500 人的广告公司组建一个数据团队,你可能想从雇佣营销分析专家开始,这些专家可以使用他们花哨的 Marketo 仪表盘立即投入工作。
我的建议是:除非你知道自己真正在解决什么问题,以及数据如何对你的业务产生最大影响,否则不要聘用专家。考虑引进具有数据分析或数据工程专业知识的饥渴的部分堆栈通才,并随着需求的发展对他们进行专业化培训。你不会想把钱浪费在你不需要的东西上,结果只是错过了你的目标。
贪婪地交流和记录数据知识。
多年来,我采访过的几位数据领导者表示,他们在数据管道的长期可持续性(以及数据团队的成功)方面的头号障碍是缺乏文档。很多时候,团队依赖部落知识和过时的维基页面来记录他们的数据,这是不可扩展或不可持续的。
根据艾米·史密斯的说法,确保你的数据团队步调一致的最佳方式是通过知识共享,尽早且经常地共享。
“许多数据科学家的早期成功是通过加入一个愿意花必要的时间写下他们的知识的团队,”她说。“将团队的集体知识转化为新人可以阅读并快速掌握的形式非常重要。”
更具体地说,缺乏关于数据和元数据的可靠信息是团队的一个主要痛点,但这是可以解决的。使这些见解更容易获得的一些解决方案有:
- 数据目录 :规模较小的团队(2-5 人)也许可以使用 Excel 电子表格,但是随着数据堆栈的成熟,可以考虑投资一个内部的、第三方的、甚至开源的解决方案。
- 数据库管理系统(DBMS):DBMS 是一个软件应用程序或软件包,用于管理数据库中的数据,包括数据的格式、字段名称、记录结构和文件结构。虽然这不会在提供上下文方面取代数据目录,但它将帮助您组织数据以便于访问。
- 数据建模工具 :数据建模工具赋予团队发现和可视化数据资产的能力。这些产品还可以帮助团队理解您的数据堆栈的各种元素之间的关系。
- 数据可观测性解决方案 :只有你的数据可信,你的数据知识才重要。数据可观测性解决方案解决了许多与数据目录、DBMSs 和数据建模工具相同的问题,但是利用了一种基于软件工程最佳实践的更新的数据管理方法。它是指组织全面了解其系统中数据运行状况的能力,从而通过将 DevOps 可观察性的最佳实践应用于数据管道来消除数据停机。
此外,想要将知识转移和可访问性推进一步的团队可以提出用缺失的信息和其他上下文来构建他们的数据操作。为此,数据主管应该鼓励他们的分析师在发现数据时添加缺失的维度,而不仅仅是在需要时添加。你现在不用它并不意味着你或你的同事以后不会用它。
推动贵公司所有数据用户采用数据。
Annie Tran 指出,像 Figma 这样的许多公司都采取了数据第一的方法来构建他们的文化,让公司的每个人都可以使用他们的数据解决方案,并鼓励所有职能部门的员工探索相关的仪表板。
“在我们每周一次的全体会议上,有专门的时间来审查指标,”她说。“数据是我们文化中普遍存在的东西,每个人都有能力看到和接受。这种开放性增强了数据对我们运营的重要性。”
****然而,只有当您能够信任自己的数据时,您公司的数据解决方案才有用。除了促进数据向前发展的文化,让数据可访问、可信赖和自助服务对于让新团队成员更舒适地探索贵公司的数据生态系统至关重要。事实上,当数据可靠时,传统数据科学方法(统计分析、A/B 测试和模型训练等)的自动化可以释放出生产力、速度、可访问性和准确性的新水平,否则是无法实现的。

2012 年,《哈佛商业评论》评选出“数据科学家”21 世纪最性感的工作 。自动化可以让他们的工作更加性感。图片由 斯蒂芬道森 上Unsplash。**
根据 Eli Brumbaugh 的说法, Airbnb 的数据设计负责人和该公司data portal数据目录的共同创建者,当谈到让数据用户成功时,最重要的事情之一是确保他们的数据是准确和相关的。****
“提高用户的信心,让他们相信他们已经找到了正确的信息或数据来采取行动,这是至关重要的,”他说。“我们需要确保驱动我们业务决策的数据是可信的,并且我们知道这些数据是否可以应用于给定的用例。”
处理数据管理解决方案有多种方法,包括数据目录、数据可靠性、合规性、安全性等,因此选择对您的业务最有意义的方法非常重要。像【Airbnb】【优步】【网飞】 这样的大型科技公司有能力花费预算和工程资源构建内部解决方案来解决这些问题。另一方面,专门的质量检查和 Excel 表格跟踪程序很容易建立,但缺乏真正产生影响所必需的全面性。
扩展数据团队既有趣又具有挑战性。希望这些建议不仅能帮助你在旅途中树立信心,还能让你远离公园!
想了解更多,联系 巴尔摩西和蒙特卡洛团队 。
如何用 Python 刮仪表板
原文:https://towardsdatascience.com/how-to-scrape-a-dashboard-with-python-8b088f6cecf3?source=collection_archive---------13-----------------------
我们将学习如何使用 Python 中的 Selenium 和 Beautiful Soup 包从仪表板中抓取数据。
当与您需要的数据交互的唯一方式是通过仪表板时,仪表板抓取是一项有用的技能。我们将学习如何使用 Python 中的 Selenium 和 Beautiful Soup 包从仪表板中抓取数据。Selenium 包允许您编写 Python 代码来实现 web 浏览器交互的自动化,而 Beautiful Soup 包允许您轻松地从生成您想要抓取的网页的 HTML 代码中提取数据。
我们的目标是刮出本德堡县仪表板,它可视化了得克萨斯州本德堡县的新冠肺炎情况。我们将提取已执行的全部检测的历史记录和每日报告的病例数,以便我们可以估计本德堡县阳性病例的百分比。
请注意,本教程中的所有代码都是用 Python 3 . 6 . 2 版编写的。
步骤 1:导入 Python 包、模块和方法
第一步是导入仪表板抓取所需的 Python 包、模块和方法。下面列出了本教程中使用的包的版本。
第二步:抓取 HTML 源代码
下一步是编写 Python 代码来自动化我们与仪表板的交互。在编写任何代码之前,我们必须查看仪表板并检查其源代码,以识别包含我们需要的数据的 HTML 元素。仪表板源代码是指告诉您的浏览器如何呈现仪表板网页的 HTML 代码。要查看仪表板源代码,导航到仪表板并使用键盘快捷键Ctrl+Shift+I。将出现一个包含仪表板源代码的交互式面板。
请注意,只有在分别单击“在县站点执行的测试总数”面板中的“历史”选项卡和“已确认病例”面板中的“每日病例计数”选项卡后,才能看到已执行的测试总数的历史记录和报告的每日病例数。这意味着我们需要编写 Python 代码来自动点击“History”和“Daily Case Count”选项卡,以便 Beautiful Soup 可以看到执行的所有测试的历史和报告的每日案例数。

本德县新冠肺炎堡仪表盘2020 年 7 月 10 日
要找到包含“历史”标签的 HTML 元素,使用快捷键Ctrl+Shift+C,然后点击“历史”标签。您将在源代码面板中看到,“History”选项卡位于 ID 为“ember208”的 div 元素中。

历史选项卡源代码
按照与“每日案例计数”选项卡相同的步骤,您将看到“每日案例计数”选项卡位于 ID 为“ember238”的 div 元素中。

每日病例计数页签源代码
现在我们已经确定了我们需要的元素,我们可以编写代码:
- 在 Chrome 中启动仪表板
- “历史记录”标签加载完成后,单击“历史记录”标签
- “每日病例计数”选项卡完成加载后,单击“每日病例计数”选项卡
- 提取仪表板 HTML 源代码
- 退出铬合金
步骤 3:解析 HTML 中的数据
现在,我们需要解析 HTML 源代码,以提取执行的全部测试的历史记录和报告的每日案例数。我们将从查看仪表板源代码开始,以识别包含数据的 HTML 元素。
要找到包含所有已执行测试历史的 div 元素,使用Ctrl+Shift+C快捷方式,然后单击“Testing Sites”图的常规区域。您将在源代码中看到,整个情节位于 ID 为“ember96”的 div 元素中。

测试站点图的源代码
如果您将鼠标悬停在特定数据点上,将会出现一个标签,其中包含所执行测试的日期和次数。使用Ctrl+Shift+C快捷键并点击特定的数据点。您将看到标签文本被存储为一个g元素的aria-label属性。

测试站点数据标签的源代码
对报告的每日案例计数执行相同的步骤,您将看到每日案例计数图位于 ID 为“ember143”的 div 元素中。

基于报告日期图的每日案例源代码
如果您将鼠标悬停在特定数据点上,将会出现一个标签,其中包含日期和报告的阳性病例数。使用Ctrl+Shift+C快捷键,您会注意到数据也存储在g元素的aria-label属性中。

基于报告日期数据标签的每日案例源代码
一旦我们有了包含数据的元素,我们就可以编写代码:
- 查找包含已执行的总测试图的 div 元素,并提取已执行的总测试数据
- 查找包含每日案例计数图的 div 元素,并提取每日案例计数数据
- 将数据合并到 pandas 数据框架中,并将其导出到 CSV
第四步:计算阳性率
现在,我们终于可以估算出本德堡县的新冠肺炎阳性率了。我们将划分测试报告的案例,并计算 7 天移动平均值。从仪表板中不清楚报告的阳性病例是否包括通过非本县进行的检测(如在医院或诊所进行的检测)确定的病例。也不清楚阳性病例的检测是何时进行的,因为仪表板只显示报告的病例日期。这就是为什么从这些数据中得出的阳性率仅被认为是对真实阳性率的粗略估计。

参考
- https://www.fbchealth.org/ncov/
- https://www . fortbendcountytx . gov/your-county/fort-bend-county-expanses-新冠肺炎-testing-site-to-all-residents
- https://gov . Texas . gov/news/post/governor-Abbott-announces-phase-one-to-open-Texas-establishment-state-wide-standard-health-protocols
- https://gov . Texas . gov/news/post/governor-Abbott-announces-phase-two-to-open-Texas
- https://gov . Texas . gov/news/post/governor-Abbott-announces-phase-iii-to-open-Texas
如何用 python 和美汤刮任何网站(静态网页)
原文:https://towardsdatascience.com/how-to-scrape-any-website-with-python-and-beautiful-soup-bc84e95a3483?source=collection_archive---------4-----------------------
Python 美汤任意网页抓取教程,带 youtube 视频

图片来自作者
注意:这是一个纯技术教程。在进行任何刮擦之前,请检查网站的政策。
对于那些想亲眼目睹这一切的人,可以看看我在页面底部的 YouTube 视频。
抓取网页的原因有很多。
你想得到你的足球队的数据吗,这样你就可以用算法来管理你的梦幻球队了?嘣,做一个刮 ESPN 的刮网器。跟踪竞争对手在不同社交媒体上的活动?太好了,这也包括在内。
或者,也许你是一名开发者拥护者,正在寻找衡量他参与黑客马拉松的 OKR 的好方法,但目前还没有好的工具,所以你想开发自己的工具。
最后一个非常特别,也是我们要寻找的!本教程展示了如何根据关键字blockchain从 devpost 获取所有将在未来 50 天内结束的黑客马拉松。
无论如何,让我们直接进入如何用 python 来抓取任何东西。我将假设您有空间可以编码,并且熟悉如何使用 python。
这方面的文档非常强大,所以一定要在本教程结束后检查一下!
*注 *
Beautiful soup 非常适合静态网页。如果你这样做并得到奇怪/糟糕的结果,你可能需要一个网络驱动来清理这个网站。我发表了这样做的高级版本,但是对于 95%的情况,下面的方法将会奏效。
1.皮普安装请求和美丽的汤
pip install requests
pip install beautifulsoup
运行这两个程序,这样您就可以使用这些包了。
2.找到你想刮的地方的网址

图片来自devpost.com
这一个不是一成不变的。如果你想浏览多个网站,你需要多个 URL。本教程的重点是只刮单个网站。一旦你理解了抓取单个页面的工作原理,你就可以移动到更多的页面。
在我们的教程中,我们将使用:
[https://devpost.com/hackathons?utf8=%E2%9C%93&search=blockchain&challenge_type=all&sort_by=Submission+Deadline](https://devpost.com/hackathons?utf8=%E2%9C%93&search=blockchain&challenge_type=all&sort_by=Submission+Deadline)
因为它给了我们所有的参数。区块链关键词和黑客马拉松结束的时间。
3.检查页面,并找到您正在寻找的标签

图片来自作者
每个页面都是由 HTML/CSS/javascript 组成的(嗯…大部分情况下),显示在屏幕上的每一点数据都显示为文本。你可以随时查看这个页面!只需右键单击,并点击“检查”。
这将显示页面用来呈现的所有代码。这是网络抓取的关键。你看到“元素”标签了吗?那里有你需要的所有 HTML/CSS 代码。

“检查”按钮的外观。图片来自作者。
现在你不需要知道 HTML/CSS 是如何工作的(虽然,如果你知道的话,它真的会很有帮助)。唯一需要知道的是,你可以把每一个 HTML 标签看作一个对象。这些 HTML 标签有您可以查询的属性,并且每一个都是不同的。
图像中以<footer>、<script>或<div>开头的每一行代码都是标签的开始,它们分别以</footer>、</script>或</div>结尾。介于这些标签之间的所有内容也是可查询的,并作为该标签的一部分。一旦你有了一个标签,你就可以得到标签里面的任何东西。
4.开始做一些 python 吧!
因此,我们通过使用 requests 对象获取我们想要的网站来开始抓取:
import requests
from bs4 import BeautifulSoupresult = requests.get("https://devpost.com/hackathons?utf8=%E2%9C%93&search=blockchain&challenge_type=all&sort_by=Submission+Deadline")
src = result.content
soup = BeautifulSoup(src, 'lxml')
我们将结果存储在一个名为soup的BeautifulSoup对象中。
这只是锅炉板的任何汤刮,接下来是可定制的部分。
5.选择你想要的标签和属性
你现在可以开始找出你想要的标签,这是你需要一点创意的地方,因为你通常可以用许多不同的方法来处理这个问题。对于我们的例子,我们想要找到所有的 hackathon 列表,我们发现它们都被包装在一个a标签中,并且有一个featured_challenge属性。下面是他们的 HTML 代码:
<a class=”clearfix” data-role=”featured_challenge” href=”[https://utonhack.devpost.com/?ref_content=default&ref_feature=challenge&ref_medium=discover](https://utonhack.devpost.com/?ref_content=default&ref_feature=challenge&ref_medium=discover)">
.
.
.
</a>
3 个.代表该标签内的其他标签。我们现在将忽略这些,因为我们要寻找的数据就在这个标记中。我们想要那个网址。如您所见,这是一个a标签,因为它以<a开头,并且它有一个属性data-role="featured_challenge",这就是我们将要用来识别它的。
我们可以用这个通过使用find_all函数找到一个列表,每一个都是中的一个。
featured_challenges = soup.find_all('a', attrs={'data-role': 'featured_challenge'})
现在的featured_challenges是一个a标签对象的列表,我们可以从中获取 URL。
如果我们遍历这个列表,我们可以这样做:
print(featured_challenge.attrs['href'])
attrs是每个标签的属性图。如果你回头看看我们提取的a标签,你会看到有一个href属性保存着我们正在寻找的黑客马拉松的 URL,万岁!
这些标签对象中的每一个都算作另一个 HTML 对象,所以你也可以对每个对象做find_all!如果只想得到第一个结果,可以使用find功能。
另外,如果您只想获得对象的文本,您可以只查找标记对象的text属性,就像这样:
featured_challenge.text
就是这样!
如果你想要在这个演示中使用的真正简单的刮刀的代码,在这里查看。
带网络驱动的多黑客马拉松铲运机的完整代码
如何用 Python 和美汤刮任何网站(动态网)
原文:https://towardsdatascience.com/how-to-scrape-any-website-with-python-and-beautiful-soup-part-2-of-2-77560fcd30fc?source=collection_archive---------40-----------------------
Python Beautiful soup 用于抓取任何网页的教程,带有 youtube 视频——并专注于网络驱动程序

图片来自作者
注意:这是一个纯粹的技术教程。在进行任何刮擦之前,请检查网站的政策。在我用的例子中,刮地盘是不合法的:。请不要使用。
对于那些想亲眼目睹这一切的人,可以看看我在页面底部的 YouTube 视频。
现在如果你没看我的第一部,回去看!这是基于在那里学到的概念。记住,这方面的文档非常强大,所以一定要在本教程结束后查看!
我们现在要学习如何处理 动态 网页或者有很多正在进行的网页,不仅仅是 HTML/CSS。用 beautifulsoup 来抓取这些页面更难,因为有时候,代码发生在服务器端,beautifulsoup 需要让浏览器来运行它。
如果有一种方法让我们编码并让我们的代码假装它是一个浏览器,那不是很好吗?…好吧,碰巧这正是这篇文章的内容!
现在,我第一次在这篇文章中读到了这一点,我将这篇文章的重点放在了具体的实现上,所以要了解更多的细节,请务必查看!
1.下载 Chrome 或 Firefox
这是目前我所知道的仅有的两个有这个功能的,所以一定要使用其中的一个。对于这篇文章,我们使用的是 Firefox 。
2.下载网络驱动程序
我们将使用的网络驱动是 geckodriver ,你可以在那个链接的底部找到所有的下载。下载后,从下载文件中提取文件(只需双击 zip 文件)。
Web 驱动有点挑剔,和操作系统玩的不太好,所以我们需要:
把 geckodriver 移到一个路径可执行文件所在的地方。请查看这篇文章了解如何在 windows 上做到这一点。
我们可以通过运行以下命令找到我们的可执行路径:
*echo $PATH*
然后我们可以:
cp将 geckodriver 文件从 zip 压缩到你的$PATH变量告诉你的一个位置(在运行echo $PATH之后)- 向您的
$PATH环境变量添加一个新的$PATH位置,并将可执行文件 geckodriver 放在那里。你可以在这里看到如何操作。
然后重新启动您的终端以使更改生效。如果你使用 MacOS(我就是),你可能还需要公证这个应用程序。您可以通过运行以下命令来实现:
*xattr -r -d com.apple.quarantine geckodriver*
3.开始用 python 编码吧!
运行之后:pip install selenium,现在可以开始使用 web 驱动了!您将使用driver.get来获取动态网页 URL,而不是使用requests.get来获取,就像这样:
*from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from bs4 import BeautifulSoupoptions = Options()
# Make it go faster by running headless
# This will remove the web browser GUI from popping up
options.headless = True
driver = webdriver.Firefox(options=options)
# Enter whatever URL you like
driver.get("https://gitcoin.co/{}".format(link.attrs['href']))
# Let the code on their end run
time.sleep(20)
# Save it to a variable
html = driver.page_source
driver.quit()
# And then just paste it right back into beautifulsoup!
projects_soup = BeautifulSoup(html, 'lxml')*
你可以在 Alpha Chain demos repo 上看到完整的代码示例,在我的 hackathon-scraper 项目上看到一个完整的示例,在这里有一个视频向你展示如何做。
而且记住,你可以一直快进:)
如何使用 Selenium 通过 Python 节省航班费用
原文:https://towardsdatascience.com/how-to-scrape-flight-prices-with-python-using-selenium-a8382a70d5d6?source=collection_archive---------14-----------------------
在这篇文章中,你将学会用 Selenium 和 ChromeDriver 来降低 Expedia 航班的价格

作者照片(尼泊尔卢卡拉)
本文由 罗伊·弗氏 和 奥菲尔·因巴尔 撰写
背景
新冠肺炎疫情期间困在家里?你喜欢旅游和数据科学吗?
你可以把两者结合起来买便宜的航班。本教程将教你如何创建一个 web scraper,它将为你找到你想要的任何目的地的航班价格。
在本教程中,你将了解到 Expedia 是世界上最大的在线旅行社之一。它由 Expedia 集团拥有和运营,在收入最高的旅游公司排行榜上排名第一。
如果你想知道新冠肺炎疫情如何影响航班价格,看看我们的媒体 邮报 。
需要注意的是,网络抓取违反了大多数网站的服务条款,所以你的 IP 地址可能会被禁止进入网站。
环境设置
对于这个刮刀,请确保您使用的是 Python 3.5 版本(或更新版本)。确认您的环境包含以下软件包和驱动程序:
- Selenium 包:一个流行的网络浏览器自动化工具
- ChromeDriver: 允许你打开浏览器,像人类一样执行任务。
- 熊猫套餐
- 日期时间包
这篇 TDS 帖子是对 Selenium 的一个很好的介绍。
刮擦策略
在进入代码之前,我们先简单描述一下抓取策略:
- 插入到一个 CSV 文件的确切路线和日期,你想刮。您可以插入任意多的路线,但是使用这些列名很重要。铲运机只在往返时工作。

CSV 路线文件。dep =出发,arr =到达。
- 运行完整的代码。
- 每个航班的输出是一个 CSV 文件。它的文件名将是执行抓取的日期和时间。
- 相同路线的所有航班将自动由刮刀定位在适当的文件夹(路线的名称)中。
听起来很复杂……其实不然!让我们看一个例子。
这些是 CSV 文件中定义的抓取路径(抓取器会自动创建这些文件夹):

废弃的路线
在这里,您可以看到雅典—阿布扎比航线上的多个刮掉的日期:

刮掉的日期:雅典—阿布扎比
下面的屏幕截图展示了雅典-阿布扎比航线的每个刮擦样本的单个 CSV 文件。它的名字代表了刮刀被执行的日期和时间。

特定日期的单个 CSV 输出文件
我们希望流程清晰!
输出特征
铲运机输出将包括以下特性:
- 出发时间
- 到达时间
- 航空公司
- 持续时间(飞行时间)
- 停靠站(停靠站数量)
- 中途停留
- 价格
- 飞机类型
- 离开蔻驰
- 抵达蔻驰
- 出发机场名称
- 到达机场名称
- 执行擦除的确切时间
如果不是直飞,scraper 会给你额外的数据(机场,航空公司名称等)。)用于每个连接。
密码
在这一节中,我们将检查代码的主要部分。你可以在这里 找到完整的代码
首先,像往常一样,需要导入相关的库,定义 chrome 驱动程序并设置往返类型。
在下一步中,您将使用 Selenium 工具定义一些函数,以便在网页上找到各种功能。函数的名字暗示了它们的作用。
CSV routes 文件中的每一行(航班)都经过以下过程:
是时候从网上收集数据并把它插入熊猫的数据框架中了。
最后,将数据以 CSV 文件直接导出到所需的文件夹中。
结论
总之,你学会了如何用 Selenium 包来节省 Expedia 航班的价格。理解基础知识后,你将能够为任何其他网站构建你的抓取工具。
就个人而言,作为爱好绘画的旅行者,我们喜欢使用数据科学来寻找全球各地令人惊叹的目的地的优惠。
如果您有任何问题、评论或担忧,请不要忘记联系 Linkedin 上的 Roee 和 Offir 。
祝你好运!
参考
** [## 使用 Selenium 的网页抓取简介
在本教程中,你将学习如何用 Selenium 和 ChromeDriver 抓取网站。
medium.com](https://medium.com/the-andela-way/introduction-to-web-scraping-using-selenium-7ec377a8cf72)
https://en.wikipedia.org/wiki/Expedia
[## 使用 Python 的 Selenium Webdriver:带示例的教程
Selenium 支持 Python,因此可以与 Selenium 一起用于测试。与其他相比,Python 很容易…
www.guru99.com](https://www.guru99.com/selenium-python.html)
https://www . scrape hero . com/scrape-flight-schedules-and-prices-from-Expedia/**
如何通过网络数据提取来获取谷歌购物价格
原文:https://towardsdatascience.com/how-to-scrape-google-shopping-prices-with-web-data-extraction-5a0a9b92406f?source=collection_archive---------34-----------------------

刮谷歌购物产品
谷歌购物是营销你的在线业务和转化更多销售的良好开端。然而,如果你是一个新来者,有必要观察和学习你的竞争对手如何通过使用 网络数据提取工具(网络抓取工具) 从谷歌购物品牌化和营销他们的产品。
为什么你应该在你的电子商务业务中使用谷歌购物?
谷歌购物转化率明显很高。这是因为谷歌购物只吸引有购买意向的顾客。例如,一个用户想买一双跑鞋作为生日礼物送给她的母亲。她可能会从搜索“跑鞋”开始,然后谷歌会提供所有相关的产品信息。用户可以在几秒钟内比较价格和功能。
谷歌购物不仅让消费者的购物过程更加方便,也让商家的营销活动更准确地匹配目标。难怪谷歌购物会在成功的电子商务企业家中广受欢迎。如果你能充分利用它,这确实是提高你销售额的有效方法。
谷歌购物是如何工作的?
为了更好地优化您的谷歌购物活动,我们需要首先了解它是如何工作的。谷歌购物非常容易开始,因为你可以按照官方的指导方针在谷歌商业中心设置你的帐户。一旦您准备好帐户,我们就可以同步您的在线商店。然后,当特定的产品搜索词出现时,你的产品信息将通过谷歌购物上线。谷歌购物在一个拍卖竞价系统和产品页面质量评分中发挥作用。也就是说,为了让谷歌购物将你的活动广告放在给定搜索结果的第一位,你必须:
- 出价高于竞争对手的出价,
- 创建转换-磁性清单描述以提高 CTR
对于大多数新手来说,他们不知道如何创建一个成功的活动。在这方面,最好的开始方式是观察别人,尤其是你的竞争对手,如何在谷歌购物上销售。

照片由克里斯蒂安·威迪格在 Unsplash 上拍摄
为什么要提取 Web 数据?
有句谚语说,“亲近你的朋友,更要亲近你的敌人。” Google Shopping 拥有大量有价值的信息,可以为您的营销活动提供素材。市面上有很多价格和产品监测平台。然而,在你测试出一个有效的营销策略并做好准备之前,如果投资这些花哨的监控工具,你就是在浪费钱。大多数监控工具是为在各种渠道中拥有大规模产品线的成熟在线企业设计的。
这就是数据提取发挥作用的方式。它可以从网站上自动提取任何数据,并转换成 excel 等可行的格式进行分析。优化策略依赖于从 Google Shopping 收集的足够数量的产品数据。
如何使用网络数据提取抓取谷歌购物
Web 数据提取需要很高的技术技能才能完成。幸运的是,有一些网页提取工具,任何人点击一下就可以直观地提取网页数据。 Octoparse 作为领先的网页抓取软件脱颖而出,对于初学者来说是绝对不需要动脑筋的。任何人都可以定制和设置一个刮刀,从大多数网站获取数据。
- 要使用 Octoparse 从 Google Shopping 中提取产品信息,我们需要定制一个新任务,方法是单击右上角的加号,然后将 URL 扔进框中。
- 它有一个内置的浏览器,应该加载网页,让我们点击。OP 8 的新版本。x 将自动读取网页并识别数据字段。
- 按照指南提示,点击“保存设置”。它会自己生成工作流
- 单击“开始提取”执行任务。
这将需要几分钟的时间来增加列表的数量。完成提取后,将文件下载到 excel 或 CSV 文件中。
当我们获得足够的信息时,我们可以进一步分析结果。您可以构建图形图表来直观地显示数据。
你能从竞争对手身上学到什么:
- 低价提高点击率:
有竞争力的价格总是会获得更高的点击率,这让谷歌购物在给定的搜索产品上更频繁地带来你的产品。你获得的印象会加强你的点击率。然而,你能走多低是有限度的。这就是为什么密切关注竞争对手的价格有助于保持竞争力。
- 不要用鸡蛋砸石头:
关注像亚马逊、塔吉特和沃尔玛这样的大公司。如果某个产品有很多大玩家,不要试图通过提高出价来超过他们。相反,你可以选择一个利基产品,他们不会出价很高。
- 优化图像质量:
产品图片在谷歌购物中可有可无。一张好的照片可以吸引更多的用户点击。你的照片应该足够清晰简单。在这方面,密切注意你可能需要 Photoshop 技巧,使你的照片看起来更有吸引力。
- 关注推广文字:
如果你的转换率下降,很可能你的竞争对手正在进行促销。推广文本更有吸引力,这将推动更多的点击率。你的促销可以是季节性的,比如“冬季大甩卖”甚至“所有订单免运费”对获得更多客户也很有帮助。然而,狡猾的零售商会通过把运费留给顾客来降低他们的价格。有的客户没意识到其实是自己掏钱付运费,后来生气了。所以只要确保顾客对促销活动非常清楚,不会引起任何麻烦。
包裹
谷歌购物很容易上手,但你仍然需要更加积极主动,保持警惕。来自谷歌的其他信息也是如此,例如 Google Play 评论。谷歌有大量信息可供挑选,这就像去相亲一样。网络数据提取是你的圣杯,可以毫不费力地自动跟踪你的竞争对手。自动调整你的市场策略,这样你就可以专注于获得竞争优势。
原载于 2020 年 4 月 13 日http://www . data extraction . io。
如何从 Twitter 上的推文中获取更多信息
原文:https://towardsdatascience.com/how-to-scrape-more-information-from-tweets-on-twitter-44fd540b8a1f?source=collection_archive---------4-----------------------
一个深入的 Twitter 抓取教程
当抓取文本和使用简单的查询是不够的,你想从 Twitter 上的推文中得到更多

照片来源
概观
有时候,仅仅抓取文本和使用简单的搜索查询是不够的。在收到大量关于我的基本 Twitter 抓取文章中没有完全涵盖的主题的询问后,我决定值得写一篇后续文章,解释 Tweepy 和 GetOldTweets3 提供的许多属性和方法,以进一步完善人们对推文的搜索查询。希望这篇文章将涵盖任何挥之不去的问题或提供新的想法。像我之前的文章一样,我将使用 Tweepy ,一个用于访问 Twitter 的 API 的 python 库,以及 Dmitry Mottl 的 GetOldTweets3 ,一个不需要 API 键就能抓取数据的 python 库。
本教程旨在成为一篇直截了当的文章,直接进入编码,展示来自每个库的各种对象中可用的数据和方法,以便在抓取 tweets 时进一步细化查询。
由于对抓取推文的非编码解决方案感兴趣,我的团队正在创建一个应用程序来满足这一需求。是的,这意味着你不必编写代码来收集数据!我们目前正在对我们的应用 Socialscrapr 进行 Alpha 测试。如果您想参与或在下一个测试阶段开放时被联系,请注册我们下面的邮件列表!
继续/先决条件之前
本文假设您熟悉 Python 和 Tweepy 或 GetOldTweets3。如果这是您第一次使用这些库,或者您需要复习,我推荐您阅读我的前一篇文章,它涵盖了基础知识和设置。
在我们开始之前,快速概述一下我将在本文中使用的两个库。
十二周:
- 可以与 Twitter 的 API 交互并创建推文、收藏夹等。
- 需要注册才能接收凭据
- 获取更深入的推文信息和用户信息
- 在抓取大量推文以及使用标准搜索 API 访问超过一周的推文方面存在限制
GetOldTweets3
更新:由于 TWITTER 的 API 发生变化,GETOLDTWEETS3 不再运行。SNSCRAPE 已经成为一个免费库的替代品,你可以使用它来清除 TWEEPY 的免费限制。我的文章在这里可用为SNSCRAPE。
- 仅用于抓取推文
- 不需要注册
- 对用户信息的有限访问
- 抓取大量推文或访问旧推文没有限制
这些是这两个库的主要特征,如果你感兴趣,我在我的上一篇文章中提供了更详细的比较。如果你发现自己想要对大量数据的信息进行二级访问,我建议看看 Twitter 的高级/企业搜索 API。这篇文章很好地展示了一个名为 searchtweets 的库,它允许你在 Python 中使用这些 API。如果你觉得 Twitter 的 Premium/Enterprise API 太贵,有一个变通方法,你可以一起使用 Tweepy 和 GetOldTweets3,我在本文的最后讨论了这个方法。
这篇文章涵盖了不同的主题领域,正因为如此,我不建议从头到尾阅读,除非你绝对想对 Tweepy 和 GetOldTweets3 都有深刻的理解。因此,我将包含一个链接的目录,这样您就可以决定哪些信息与您相关,并跳转到相应的部分。此外,正如你将看到的,我的大多数功能都设置为抓取 150 条推文。我建议首先在较小的样本上测试你的查询,然后收集你想要的 tweet 数量,因为大型查询可能需要一些时间才能完成。
快速注意,如果你正在抓取私人账户或以前的私人账户,你可能会发现你无法访问推文,或者你可以抓取的推文数量有限。
如果你想提前检查我的代码,或者在阅读每一部分时有所遵循,我已经创建了一个文章笔记本,遵循本文中给出的代码示例;以及一个配套的笔记本,它提供了更多的例子来更好地充实代码。你可以在我的 GitHub 这里 访问我的 Jupyter 笔记本来获取这个教程。
事不宜迟,让我们投入战斗吧!

照片来源
目录:
用 Tweepy 刮更
- 从推文中获取更多信息,例如收藏、转发
- 从推文中获取用户信息,例如关注者数量、推文数量
- 使用高级查询进行抓取,例如从特定位置或以特定语言进行抓取
- 综合考虑
用 GetOldTweets3 刮更
- 从推文中获取更多信息,例如收藏、转发
- 从推文中获取用户信息,有限
- 使用高级查询进行抓取,例如从特定位置或以特定语言进行抓取
- 把所有的放在一起
如何将 Tweepy 与 GetOldTweets3 一起使用
用 Tweepy 刮得更多
如果你想让代码跟随这一部分,我这里有一篇文章 Jupyter 笔记本。如果你想要更多的代码示例和易于使用的功能,我在这里创建了一个配套的 Jupyter 笔记本。
入门
在使用 Tweepy 之前,它需要授权。我不会详细介绍如何设置,因为我在之前的文章中已经介绍过了。
consumer_key = "XXXXX"
consumer_secret = "XXXXX"
access_token = "XXXXX"
access_token_secret = "XXXXXX"auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth,wait_on_rate_limit=True)
从推文中获取更多信息
下面提供的图片虽然不是一个详尽的列表,但涵盖了 Tweepy 的 tweet 对象中的大部分可用信息。如果你对其他可用的数据感到好奇,Twitter 开发者网站上的这里显示了完整的信息列表。正如您将在本部分和用户信息部分看到的。为了保持数据的完整性,我使用字符串版本的 Ids,而不是 integer,因为存储 integer 值可能会导致以后访问它时数据丢失。

Tweepy 提供的推文信息列表
大多数情况下,每个 tweet.attribute 都有一定的价值,并且容易访问。但是,tweet.coordinates 和 tweet.place 属性需要一些提取,因为它们是包含其他数据的数据字典。此外,因为它们可能是空的,所以首先检查 tweet 是否有信息是很重要的。下面的函数检查属性是否有数据,并提取相关信息。这段代码假设您遵循了我的列命名约定,我们将在下一节中看到这一点。如果你改变了 Tweet 坐标或位置信息的命名方式,你需要相应地调整下面的代码。
# Function created to extract coordinates from tweet if it has coordinate info
# Tweets tend to have null so important to run check
# Make sure to run this cell as it is used in a lot of different functions below
def extract_coordinates(row):
if row['Tweet Coordinates']:
return row['Tweet Coordinates']['coordinates']
else:
return None# Function created to extract place such as city, state or country from tweet if it has place info
# Tweets tend to have null so important to run check
# Make sure to run this cell as it is used in a lot of different functions below
def extract_place(row):
if row['Place Info']:
return row['Place Info'].full_name
else:
return None
现在我们可以继续前进,能够从 tweet.coordinates 和 tweet.place 属性中提取有用的信息。让我们开始实际刮削。
从用户的推文中提取所有推文相关信息的搜索查询示例:
username = 'random'
max_tweets = 150
tweets = tweepy.Cursor(api.user_timeline,id=username).items(max_tweets)
# Pulling information from tweets iterable object
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.text, tweet.created_at, tweet.id_str, tweet.user.screen_name, tweet.coordinates, tweet.place, tweet.retweet_count, tweet.favorite_count, tweet.lang, tweet.source, tweet.in_reply_to_status_id_str, tweet.in_reply_to_user_id_str, tweet.is_quote_status] for tweet in tweets]
# Creation of dataframe from tweets_list
# Add or remove columns as you remove tweet information
tweets_df = pd.DataFrame(tweets_list,columns=['Tweet Text', 'Tweet Datetime', 'Tweet Id', 'Twitter @ Name', 'Tweet Coordinates', 'Place Info', 'Retweets', 'Favorites', 'Language', 'Source', 'Replied Tweet Id', 'Replied Tweet User Id Str', 'Quote Status Bool'])
# Checks if there are coordinates attached to tweets, if so extracts them
tweets_df['Tweet Coordinates'] = tweets_df.apply(extract_coordinates,axis=1)
# Checks if there is place information available, if so extracts them
tweets_df['Place Info'] = tweets_df.apply(extract_place,axis=1)
上面的查询从 Twitter 用户@random 获取 150 条 tweets,并利用 extract_coordinates 和 extract_place 函数检查是否有信息,如果有,就提取相关信息。如上所示,tweet 对象中有很多可用的信息。要修改信息,你只需要添加或删除 tweets_list 中显示的任何 tweet.attribute。为此,在创建 dataframe tweets_df 时调整列名也很重要。
访问多达 280 个字符的推文文本
出于兼容性的考虑,Tweepy 默认情况下只提取最多 140 个字符的 tweet 文本,因为这是 Twitter 的旧 tweet 字符限制。这可能很烦人,因为你可能想要所有可用的信息,而不是被缩短的推文。要取消此限制,您必须修改 tweepy.Cursor 中的 tweepy _ mode 参数。如果您正在使用 Tweepy,请务必将此 tweet_mode 设置为“extended ”,因为如果您不在查询中包含此选项,您将始终会抓取缩短到原始 140 个字符限制的 tweet。当 Tweepy 设置为扩展 tweet 模式时,这也会将 tweet.text 属性改为 tweet.full_text。因此,如果您使用这种扩展的 tweet 模式,请确保相应地调整您的代码。下面的代码片段展示了 tweepy 中的变化。光标和 tweets_list 来访问超过 140 个字符的 tweets。Tweepy 文档中的此处提供了关于扩展 Tweepy 模式的更多信息。
username = 'BillGates'
max_tweets = 150
# Creation of query method using parameters
tweets =
tweepy.Cursor(api.user_timeline, id=username, tweet_mode='extended').items(max_tweets)
# Pulling information from tweets iterable object
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.full_text, tweet.created_at, tweet.id_str, tweet.user.screen_name, tweet.coordinates, tweet.place, tweet.retweet_count, tweet.favorite_count, tweet.lang, tweet.source, tweet.in_reply_to_status_id_str, tweet.in_reply_to_user_id_str, tweet.is_quote_status] for tweet in tweets]
# Creation of dataframe from tweets_list
# Did not include column names to simplify code
tweets_df = pd.DataFrame(tweets_list)
从推文中获取用户信息
用户信息是 Tweepy 优于 GetOldTweets3 的地方。下面提供的图片虽然不是一个详尽的列表,但涵盖了 Tweepy 的用户对象中可用的大部分信息。如果你对其他可用的数据感到好奇,完整的信息列表可以在 Twitter 的开发者网站上这里找到。

Tweepy 提供的用户信息列表
从推文中提取所有用户相关信息的搜索查询示例:
text_query = 'Coronavirus'
max_tweets = 150
# Creation of query method using parameters
tweets = tweepy.Cursor(api.search,q=text_query).items(max_tweets)
# Pulling information from tweets iterable object
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.text, tweet.created_at, tweet.id_str, tweet.user.name, tweet.user.screen_name, tweet.user.id_str, tweet.user.location, tweet.user.url, tweet.user.description, tweet.user.verified, tweet.user.followers_count, tweet.user.friends_count, tweet.user.favourites_count, tweet.user.statuses_count, tweet.user.listed_count, tweet.user.created_at, tweet.user.profile_image_url_https, tweet.user.default_profile, tweet.user.default_profile_image] for tweet in tweets]
# Creation of dataframe from tweets_list
# Did not include column names to simplify code
tweets_df = pd.DataFrame(tweets_list)
上面的查询搜索了 150 条包含单词冠状病毒的最近的推文。类似于前面显示的其他代码片段。要修改可用的信息,可以在 tweets_list 中显示的列表理解中添加或删除任何 tweet.user.attribute。
高级查询刮除
Tweepy 提供了几种不同的方法来优化您的查询。下图显示了可通过 Tweepy 访问的搜索参数列表。同样,虽然这不是详尽的清单,但它涵盖了大部分。如果你想了解更多关于搜索 API 的信息,可以在 Twitter 的开发者网站这里找到。正如您可能注意到的 geocode,Tweepy 没有一个方法可以接受城市的字符串版本并在它们周围进行搜索。您必须输入一对特定的纬度、经度坐标来限制地理位置的查询。

Tweepy 提供的搜索参数列表
使用高级查询的搜索查询示例:
# Example may no longer show tweets if until_date falls outside
# of 7-day period from when you run cell
coordinates = '19.402833,-99.141051,50mi'
language = 'es'
result_type = 'recent'
until_date = '2020-08-10'
max_tweets = 150
# Creation of query method using parameters
tweets = tweepy.Cursor(api.search, geocode=coordinates, lang=language, result_type = result_type, until = until_date, count = 100).items(max_tweets)
# List comprehension pulling chosen tweet information from tweets iterable object
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.text, tweet.created_at, tweet.id_str, tweet.favorite_count, tweet.user.screen_name, tweet.user.id_str, tweet.user.location, tweet.user.url, tweet.user.verified, tweet.user.followers_count, tweet.user.friends_count, tweet.user.statuses_count, tweet.user.default_profile_image,
tweet.lang] for tweet in tweets]
# Creation of dataframe from tweets_list
# Did not include column names to simplify code
tweets_df = pd.DataFrame(tweets_list)
上面的查询用西班牙语提取了 150 条最近在墨西哥城发布的推文,最新日期是 2020 年 8 月 10 日。这个代码片段与之前展示的另外两个略有不同。为了优化搜索参数,您必须将上图所示的不同参数添加到 tweepy 中。光标(geocode =坐标,lang =语言等。)并给它传递一个变量或者硬编码。这样你就可以根据地点、语言或者任何你想做的事情来优化你的搜索。
把所有的放在一起
太好了,我见过很多单独的东西,但这有什么关系呢?无论您是想从搜索关键词的特定用户那里收集推文,还是搜索在内华达州拉斯维加斯(Lat 36.169786,Long-115.139858)50 英里半径范围内具有关键词冠状病毒的推文。您的 Tweepy 抓取仅受您的想象力和 Tweepy 中可用的属性和方法的限制。下面我将通过显示上面提到的查询向您展示挑选您想要的方法和信息是多么容易。
使用高级查询提取推文和用户信息的查询示例:
text_query = 'Coronavirus'
coordinates = '36.169786,-115.139858,50mi'
max_tweets = 150
# Creation of query method using parameters
tweets = tweepy.Cursor(api.search, q = text_query, geocode = coordinates, count = 100).items(max_tweets)
# Pulling information from tweets iterable object
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.text, tweet.created_at, tweet.id_str, tweet.favorite_count, tweet.user.screen_name, tweet.user.id_str, tweet.user.location, tweet.user.followers_count, tweet.coordinates, tweet.place] for tweet in tweets]
# Creation of dataframe from tweets_list
# Did not include column names to simplify code
tweets_df = pd.DataFrame(tweets_list)
正如您在上面看到的,只需修改 tweepy 中的代码。Cursor(api.search,)带有搜索参数,可以根据位置、top_tweets 等进一步优化搜索。如果您想修改从 tweets 中收到的信息,只需在我在 query 方法下创建的 tweets_list 列表理解中添加或删除 tweet.chosen _ attribute。
使用 GetOldTweets3 获取更多信息
更新:由于 TWITTER 的 API 发生变化,GETOLDTWEETS3 不再运行。SNSCRAPE 已经成为一个免费库的替代品,你可以使用它来清除 TWEEPY 的免费限制。我的文章在这里可用为sn scrape。
GetOldTweets3 只需要安装一个 pip。导入库后,您应该能够立即使用它。如果你想让代码跟随这一部分,我这里有一篇文章 Jupyter Notebook。如果你想要更多的代码示例和易于使用的功能,我在这里创建了一个配套的 Jupyter 笔记本。
从推文中获取更多信息
下面提供的图片是通过 GetOldTweets3 的 tweet 对象向您提供的信息的详尽列表。正如你所看到的,一条 tweet 包含了相当多的信息,访问它一点也不困难。

GetOldTweets3 提供的 tweet 信息列表
从用户的推文中提取所有推文相关信息的搜索查询示例:
username = 'jack'
count = 150
# Creation of tweetCriteria query object with methods to specify further
tweetCriteria = got.manager.TweetCriteria().setUsername(username)\
.setMaxTweets(count)
# Creation of tweets iterable containing all queried tweet data
tweets = got.manager.TweetManager.getTweets(tweetCriteria)
# List comprehension pulling chosen tweet information from tweets
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.id, tweet.author_id, tweet.username, tweet.to, tweet.text, tweet.retweets, tweet.favorites, tweet.replies, tweet.date, tweet.formatted_date, tweet.hashtags, tweet.mentions, tweet.urls, tweet.permalink,] for tweet in tweets]
# Creation of dataframe from tweets_list
# Did not include column names to simplify code
tweets_df = pd.DataFrame(tweets_list)
上面的查询提取了 twitter 用户@jack 最近的 150 条推文。如上所示,要修改可用信息,您只需添加或删除 tweets_list 中显示的列表理解的任何 tweet.attribute。
从推文中获取用户信息
与 Tweepy 相比,GetOldTweets3 的可用用户信息有限。这个库的 tweet 对象只包含 tweet 作者的用户名和 user_id。如果您想要比现有的更多的用户信息,我建议您要么使用 Tweepy 进行所有的抓取,要么使用 Tweepy 方法和 GetOldTweets3,以便充分利用两个库的优势。为此,我在下面的“如何使用 Tweepy 和 GetOldTweets3”一节中展示了一些解决方法。
使用高级查询抓取
下面提供的图片是通过 GetOldTweets3 优化查询的详尽方法列表。

GetOldTweets3 可用的搜索方法列表
使用高级查询的搜索查询示例:
username = "BarackObama"
text_query = "Hello"
since_date = "2011-01-01"
until_date = "2016-12-20"
count = 150
# Creation of tweetCriteria query object with methods to specify further
tweetCriteria = got.manager.TweetCriteria().setUsername(username)\
.setQuerySearch(text_query).setSince(since_date)\
.setUntil(until_date).setMaxTweets(count)
# Creation of tweets iterable containing all queried tweet data
tweets = got.manager.TweetManager.getTweets(tweetCriteria)
# List comprehension pulling chosen tweet information from tweets
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.id, tweet.author_id, tweet.username, tweet.text, tweet.retweets, tweet.favorites,tweet.replies,tweet.date] for tweet in tweets]
# Creation of dataframe from tweets list
# Did not include column names to simplify code
tweets_df = pd.DataFrame(tweets_list)
上面的查询试图从巴拉克·奥巴马那里提取 150 条 tweetss,这些 tweet 在日期范围 2011 年 1 月 1 日到 2016 年 12 月 20 日之间打招呼。如上面的代码片段所示,如果您想使用任何方法来创建更具体的查询,您需要做的就是将它们添加到 TweetCriteria()的末尾。例如,我可以在上面的代码中添加。塞特尼尔(“华盛顿特区”)在年底。setMaxTweets(),如果我想查询该地区周围的推文。
把所有的放在一起
太好了,我可以从 2016 年开始发布推文信息或推文。为什么重要?无论您是想从搜索关键词的特定用户那里收集所有可用信息,还是搜索华盛顿特区在 2020 年 8 月 5 日至 2020 年 8 月 10 日之间以冠状病毒为关键词的热门推文。您的 tweet 抓取只受您的想象力和该包中可用的属性和方法的限制。下面我将向您展示通过创建上面提到的查询来挑选您想要的方法和信息是多么容易。
使用高级查询提取推文和用户信息的查询示例:
text_query = 'Coronavirus'
since_date = '2020-08-05'
until_date = '2020-08-10'
location = 'Washington, D.C.'
top_tweets = True
count = 150
# Creation of tweetCriteria query object with methods to specify further
tweetCriteria = got.manager.TweetCriteria()\
.setQuerySearch(text_query).setSince(since_date)\
.setUntil(until_date).setNear(location).setTopTweets(top_tweets)\
.setMaxTweets(count)
# Creation of tweets iterable containing all queried tweet data
tweets = got.manager.TweetManager.getTweets(tweetCriteria)
# List comprehension pulling chosen tweet information from tweets
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.id, tweet.author_id, tweet.username, tweet.to, tweet.text, tweet.retweets, tweet.favorites, tweet.replies, tweet.date, tweet.mentions, tweet.urls, tweet.permalink,] for tweet in tweets]
# Creation of dataframe from tweets list
# Add or remove columns as you remove tweet information
tweets_df = pd.DataFrame(tweets_list)
正如最后一个例子所示,改进您的查询或修改您可用的 tweet 数据相当简单。通过在末尾添加 set 方法并传入值来修改 tweetCriteria 对象,可以优化查询。您可以通过修改 tweets_list 中列出的 tweet 属性来删除或添加更多信息。
如何将 Tweepy 与 GetOldTweets3 一起使用
如果你使用 GetOldTweets3 但是想要访问用户信息会怎么样?或者你使用 Tweepy,但需要访问旧的推文。还好,有一个变通办法,你可以使用 Tweepy 的方法来访问更多的 Tweepy 或用户信息。允许您一起使用这两个库。
重要的是要记住,Tweepy 的 API 总是要求用户注册以接收凭证,如果你需要这样做的话我以前的文章讨论过这个问题。此外,这些方法仍然受到 Tweepy 的请求限制,所以我不建议对大于 20k tweets 的数据集使用这种变通方法,除非您不介意让您的计算机运行几个小时。我个人使用了这两个库和一个 5000 条 tweets 的数据集,花了我大约 1-2 个小时来运行所有的东西。如果你没有时间等待或者不介意付费,那么利用 Twitter 的 Premium/Enterprise API 是值得的。这篇文章涵盖了 searchtweets,一个 Python 中的库,如果你决定走这条路,它允许访问高级/企业 API。
如果你想让代码跟随这一部分,我有一个 Jupyter 笔记本可用在这里。
凭证
在使用 Tweepy 之前,它需要授权。我不会详细介绍如何设置,因为我在之前的文章中已经介绍过了。
# consumer_key = "XXXXX"
# consumer_secret = "XXXXX"
# access_token = "XXXXX"
# access_token_secret = "XXXXXX"auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth,wait_on_rate_limit=True)
准备
Tweepy 的 API 提供了两种方法,允许 GetOldTweets3 用户访问更多信息。
api.get_status()接受一个 tweet id,并返回与该 tweet 相关的所有信息
api.get_user()接受用户 id 或用户名,并返回与该用户相关的所有信息
因此,让我们确保这些数据可用,并使用 GetOldTweets3 获取 tweet.id、tweet.author_id 和 tweet.username。
text_query = 'Hello'
since_date = "2020-7-20"
until_date = "2020-7-21"count = 150
# Creation of tweetCriteria query object with methods to specify further
tweetCriteria = got.manager.TweetCriteria()\
.setQuerySearch(text_query).setSince(since_date)\
.setUntil(until_date).setMaxTweets(count)
# Creation of tweets iterable containing all queried tweet data
tweets = got.manager.TweetManager.getTweets(tweetCriteria)
# List comprehension pulling chosen tweet information from tweets
# Add or remove tweet information you want in the below list comprehension
tweets_list = [[tweet.id, tweet.author_id, tweet.username, tweet.text, tweet.retweets, tweet.favorites, tweet.replies, tweet.date] for tweet in tweets]
# Creation of dataframe from tweets list
# Add or remove columns as you remove tweet information
tweets_df = pd.DataFrame(tweets_list, columns = ['Tweet Id', 'Tweet User Id', 'Tweet User', 'Text', 'Retweets', 'Favorites', 'Replies', 'Datetime'])
功能
很好,我们已经得到了一些包含 tweet.id、tweet.author_id 和 tweet.username 的数据。让我们测试一下 Tweepy 中的这些方法,以确保它们能够工作。
api.get_status(1285363852851511301)api.get_user(811267164476841984)api.get_user('realJakeLogan')
正如您在上面的代码中看到的,有许多信息来自请求。还需要注意的是,Tweepy 的 tweet 对象已经包含了一个用户对象。如果你只需要 Tweepy 的用户信息,你可以使用任何一种方法,但是如果你想要 Tweepy 的 tweet 信息,你必须使用 get_status 方法。让我们更进一步。上面的代码只对一次搜索一个东西有用,如果你有一个完整的数据集,你需要创建一个函数来提取数据。
def extract_tweepy_tweet_info(row):
tweet = api.get_status(row['Tweet Id'])
return tweet.source
tweets_df['Tweet Source'] = tweets_df.apply(extract_tweepy_tweet_info,axis=1)
这很好,但是,如果您想从 tweet 对象返回多个属性,会发生什么情况呢?也许你还想要 tweet.user.location 和 tweet.user.followers_count。有两种方法可以解决这个问题。创建一个函数将数据存储在列表中,然后将所有数据添加到数据框中。或者创建一个将创建一个系列并返回它的函数,然后使用 panda 的 apply 方法在数据框上使用该函数。我将展示前者,因为它更容易掌握。
# Creation of list to store scrape tweet data
tweets_holding_list = []
def extract_tweepy_tweet_info_efficient(row):
# Using Tweepy API to request for tweet data
tweet = api.get_status(row['Tweet Id'])
# Storing chosen tweet data in tweets_holding_list to be used later
tweets_holding_list.append((tweet.source, tweet.user.statuses_count,
tweet.user.followers_count, tweet.user.verified))
# Applying the extract_tweepy_tweet_info_efficient function to store tweet data in the tweets_holding_list
tweets_df_test_efficient.apply(extract_tweepy_tweet_info_efficient, axis=1)
# Creating new columns to store the data that's currently being held in tweets_holding_list
tweets_df_test_efficient[['Tweet Source', 'User Tweet Count', 'Follower Count', 'User Verified Status']] = pd.DataFrame(tweets_holding_list)
太好了,不用每次都请求 Tweepy 的 API,您可以发送一个请求,然后一次性修改您的数据框。如果您发现自己需要多种属性,这将更加高效,并最终为您节省大量时间。
以上就是我关于 Tweepy 和 GetOldTweets3 的高级教程,以及使用 Tweepy 和 GetOldTweets3 的方法。希望你的大部分问题能在我之前的文章或者这篇文章中得到解答。如果你有具体的问题,在谷歌上找不到答案,或者想联系我。我在 LinkedIn 上有空。
参考
如果你感兴趣,注册我们的 Socialscrapr 邮件列表:【https://upscri.be/3kcmqx
如果你想要一个 GetOldTweets3 替代品的 snscrape 抓取文章:https://medium . com/better-programming/how-to-scrape-tweets-with-snscrape-90124 ed 006 af
之前的基础 twitter 抓取文章:https://towardsdatascience . com/how-to-scrape-tweets-from-Twitter-59287 e 20 f0f 1
包含本教程的 Twitter scraper 的 GitHub:https://GitHub . com/martink beck/TwitterScraper/tree/master/adv scraper
GitHub 包含了我的基础和高级教程 Twitter scraper 的:https://github.com/MartinKBeck/TwitterScraper
随 Tweepy 提供的各种 API:https://developer.twitter.com/en/products/products-overview
tweepy GitHub:【https://github.com/tweepy/tweepy
getoldtweets 3 GitHub:【https://github.com/Mottl/GetOldTweets3
使用 searchtweets 访问 Twitter 的 Premium/Enterprise API 的教程文章:https://Luca hammer . com/2019/11/05/collecting-old-tweets-with-the-Twitter-Premium-API-and-python/
如何刮暗网
原文:https://towardsdatascience.com/how-to-scrape-the-dark-web-53145add7033?source=collection_archive---------4-----------------------
在 Mac OSX 上使用 Python、Selenium 和 TOR 清理黑暗网络

资料来源:Pexels.com
警告:访问黑暗网络可能是危险的!请自担风险继续,并采取必要的安全预防措施,如禁用脚本和使用 VPN 服务。
介绍
对大多数用户来说,谷歌是探索互联网的门户。但是,deep web 包含不能被 Google 索引的页面。在这个空间中,隐藏着黑暗网络——匿名网站,通常被称为隐藏服务,从事从毒品到黑客到人口贩运的犯罪活动。
黑暗网络上的网站 URL 不遵循惯例,通常是由字母和数字组成的随机字符串,后跟。洋葱子域。这些网站需要 TOR 浏览器解析,无法通过 Chrome 或 Safari 等传统浏览器访问。
查找隐藏服务
抓取黑暗网络的第一个障碍是找到要抓取的隐藏服务。如果你已经知道你想要抓取的网站的位置,你很幸运!这些网站的 URL 通常是不可搜索的,并且是在人与人之间传递的,无论是面对面的还是在线的。幸运的是,有几种方法可以用来找到这些隐藏的服务。
方法 1:目录
包含指向隐藏服务的链接的目录在暗网和明网上都存在。这些目录可以给你一个很好的方向,但往往会包含更多众所周知的服务,更容易找到的服务。
方法 2:滚雪球抽样
雪球抽样是一种抓取方法,它获取一个种子网站(比如您从目录中找到的网站),然后抓取该网站以查找其他网站的链接。收集完这些链接后,爬虫将继续对这些站点进行搜索。这种方法能够找到目录中没有列出的隐藏服务。此外,这些网站更有可能吸引严重的罪犯,因为它们的存在并不透明。
虽然推荐使用滚雪球抽样方法来查找隐藏的服务,但是它的实现超出了本文的范围。我已经在这里写了第二篇关于雪球取样黑暗网络的文章。
环境设置
在确定了要收集的隐藏服务之后,需要设置环境。本文涵盖了 Python、Selenium、TOR 浏览器和 Mac OSX 的使用。
TOR 浏览器
TOR 浏览器是一种使用 TOR 网络的浏览器,允许我们使用. onion 子域解析网站。TOR 浏览器可以在这里下载。
虚拟专用网络
在爬行黑暗网络时运行 VPN 可以为您提供额外的安全性。虚拟专用网络(VPN)不是必需的,但强烈建议使用。
计算机编程语言
对于本文,我假设您已经在自己的机器上安装了 python,并使用了自己选择的 IDE。如果没有,网上可以找到很多教程。
熊猫
Pandas 是一个数据操作 Python 包。Pandas 将用于存储和导出刮到 csv 文件的数据。通过在终端中键入以下命令,可以使用 pip 安装 Pandas:
pip install pandas
硒
Selenium 是一个浏览器自动化 Python 包。Selenium 将用于抓取网站和提取数据。Selenium 可以通过在终端中键入以下命令来使用 pip 进行安装:
pip install selenium
壁虎
为了让 selenium 自动化浏览器,它需要一个驱动程序。因为 TOR 浏览器在 Firefox 上运行,我们将使用 Mozilla 的 Geckodriver。你可以在这里下载驱动。下载后,解压驱动程序,并将其移动到您的~/中。本地/bin 文件夹。
Firefox 二进制文件
TOR 浏览器的 Firefox 二进制文件的位置也是需要的。要找到它,右键单击应用程序文件夹中的 TOR 浏览器,然后单击显示内容。然后导航到 Firefox 二进制文件并复制完整路径。将此路径保存在某个地方以备后用。
履行
现在你已经设置好了你的环境,你可以开始写你的 scraper 了。
首先,从 selenium 导入 web 驱动程序和 FirefoxBinary。还进口熊猫当 pd。
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
import pandas as pd
创建一个变量“binary ”,并将其设置为您之前保存的 Firefox 二进制文件的路径。
binary = FirefoxBinary(*path to your firefox binary*)
设置 web 驱动程序使用 Firefox 并传递二进制变量。
driver = webdriver.Firefox(firefox_binary = binary)
创建一个变量“url ”,并将其设置为您希望抓取的隐藏服务的 url。
url = *your url*
打开 TOR 浏览器并获取 url。
driver.get(url)
你现在可以像抓取任何网站一样抓取隐藏的服务!
基本刮硒技术
无论你是初学 Selenium 还是需要刷一下,你都可以使用这些基本技巧来有效地刮网站。其他硒刮教程可以在网上找到。
查找元素
Selenium 抓取的一个关键部分是定位 HTML 元素来收集数据。在 Selenium 中有几种方法可以做到这一点。一种方法是使用类名。为了找到一个元素的类名,可以右键单击它,然后单击 inspect。下面是一个通过类名查找元素的例子。
driver.find_element_by_class_name("postMain")
还可以通过元素的 XPath 来查找元素。XPath 表示元素在 HTML 结构中的位置。您可以在 inspect 界面的 HTML 项目的右键菜单中找到元素的 XPath。下面是一个通过 XPath 查找元素的例子。
driver.find_element_by_xpath('/html/body/div/div[2]/div[2]/div/div[1]/div/a[1]')
如果要查找多个元素,可以用“find_elements”代替“find_element”。下面是一个例子。
driver.find_elements_by_class_name("postMain")
获取元素的文本
您可以使用 text 函数检索元素的文本。下面是一个例子。
driver.find_element_by_class_name('postContent').text
存储元素
您可以通过将元素保存在变量中,然后将该变量追加到列表中来存储元素。下面是一个例子。
post_content_list = []
postText = driver.find_element_by_class_name('postContent').text
post_content_list.append(postText)
在页面间爬行
一些基于页面的网站会在 URL 中包含页码。您可以在一个范围内循环并更改 url 来抓取多个页面。下面是一个例子。
for i in range(1, MAX_PAGE_NUM + 1):
page_num = i
url = '*first part of url*' + str(page_num) + '*last part of url*'
driver.get(url)
导出到 CSV 文件
在抓取页面并将数据保存到列表中之后,您可以使用 Pandas 将这些列表导出为表格数据。下面是一个例子。
df['postURL'] = post_url_list
df['author'] = post_author_list
df['postTitle'] = post_title_listdf.to_csv('scrape.csv')
防爬行措施
许多隐藏服务采用反爬行措施来保持信息秘密和避免 DDoS 攻击。你会遇到的最常见的措施是验证码。虽然存在一些验证码自动解算器,但隐藏服务经常会使用解算器无法传递的独特验证码类型。下面是一个在论坛上找到的验证码的例子。

来源:暗网论坛
如果在特定的时候需要验证码(比如第一次连接到服务器),可以使用 Selenium 中的隐式等待功能。该功能将等待预定的时间,直到可以执行下一个动作。下面是一个使用中的例子,Selenium 将一直等待,直到找到类名为“postMain”的元素。
driver.implicitly_wait(10000)
driver.find_element_by_class_name("postMain")
其他时候,如果服务器识别出你是机器人,它就会停止为你服务。为了绕过这一点,将网站分块抓取,而不是一次全部抓取。您可以将数据保存在不同的 csv 文件中,然后使用 Pandas concat 函数将它们与额外的 python 脚本相结合。下面是一个例子。
import pandas as pddf = pd.read_csv('scrape.csv')
df2 = pd.read_csv('scrape2.csv')
df3 = pd.read_csv('scrape3.csv')
df4 = pd.read_csv('scrape4.csv')
df5 = pd.read_csv('scrape5.csv')
df6 = pd.read_csv('scrape6.csv')frames = [df, df2, df3, df4, df5, df6]result = pd.concat(frames, ignore_index = True)result.to_csv('ForumScrape.csv')
讨论
与刮擦表面网相比,刮擦暗网具有独特的挑战。然而,它相对尚未开发,可以提供出色的网络犯罪情报操作。虽然隐藏服务通常采用反爬行措施,但这些措施仍然可以被绕过,并提供有趣和有用的数据。
我想重申,刮暗网可能是危险的。确保你采取了必要的安全措施。请继续研究黑暗网络上的安全浏览。我对发生的任何伤害不负任何责任。
