破解数据科学访谈:基本的机器学习概念
破解数据科学面试
赢在 2021 年:数据科学家/工程师的必读之作,第 1 部分
美国宇航局在 Unsplash 拍摄的照片
介绍
数据科学面试涵盖了广泛的主题:测试候选人总体统计流畅性的统计部分,关于候选人各种 ML 算法和权衡的机器学习部分,以及锻炼我们现场编码技能的编程部分。
更不用说每个面试官最喜欢的“向我介绍你的解决方案”和几十次后续互动了。更重要的是,在 DS 社区中有一个新发现的趋势,即转向像数据结构和算法这样的计算机科学基础(查看的精彩文章 Emma Ding @Airbnb)。
综合来看,它们似乎太令人生畏而难以处理。
如果我们把大块分成小块,每一块都变得更“可咀嚼”和易于管理。
就像算法“各个击破”
一语双关!
这是关于基本概念的两篇文章的第一章。在第一章中,我将重点放在机器学习部分,并解释 DS 面试中的这些常见问题。在第二章中,我转换话题,详细阐述统计方面的内容。这是:
概念 1:偏差和方差
1.1 什么是偏见?
偏差是对估计值与其真实值之间的差异的估计。用简单的语言来说,它衡量我们的模型与实际数据点有多“接近”。
其数学公式表示如下:
偏差与特征选择和模型复杂性直接相关,过于简化的模型往往具有较高的偏差。
1.2 什么是方差?
方差是指由于模型过于复杂和训练数据的选取而导致的建模误差。它衡量的是模型对噪声的拟合程度,而不是数据中的模式。使用不同训练集训练的模型具有不同的方差。与数据的选择直接相关。具有高方差的模型在训练数据中表现良好,但在新数据集中表现不佳。
其数学形式表示如下:
总的来说,灵活的(复杂的)模型倾向于具有低偏差但高方差,aka。过度适应训练集中的噪声,并且刚性(简单)模型具有高偏差但低方差,aka。欠拟合真实数据模式。
顺便提一下,任何机器学习算法都有三种误差来源:偏差、方差和不可约误差,如下所示。
总误差=偏倚+方差+不可约误差
概念 2: L1 和 L2 正规化
2.1。什么是正规化?
正则化是一种回归形式,它通过将系数估计值约束或缩小到零来产生简约的模型。它通过向成本函数添加惩罚来实现这个目标。在机器学习算法中,如果我们包括太多可能的特征,我们会使模型过度适应训练数据中的噪声。过度拟合会降低未来数据(测试集)的模型精度。正规化解决了这个问题。
2.2 什么是拉索回归(L1 正则化)?L1 是如何导致稀疏的?
什么
LASSO 回归(L1 正则化)包括一个超参数α乘以系数绝对值之和,作为其成本函数中的惩罚项,如下所示(用红色标记):
截图 1:来自数据科学家实用统计
一方面,如果我们不应用任何惩罚(设置α =0),上述公式变成常规的 OLS 回归,这可能会过度拟合。
另一方面,如果我们应用一个非常大的惩罚(或者,一个大的α值),模型可能会欠拟合,因为我们错误地惩罚了所有的系数(包括最重要的系数)。
如何
L1 被称为稀疏正则化。如果我们运行梯度下降来计算权重,L1 正则化迫使任何权重更接近于 0,而不管其大小。在每次迭代中,L1 从权重中减去一个小值,一些系数最终收敛到 0。因此,L1 通过将不太重要的特征的系数缩小到 0 来导致模型稀疏。
(关于 L1 如何导致稀疏的原因,特别归功于索纳·耶尔德勒姆的邮报。
2.3。什么是山脊(L2)?L2 是如何工作的?
岭回归采用系数乘以λ的“平方值”作为罚项,如下所示。
截图 2:来自数据科学家实用统计
如果 lambda λ为 0,则公式变为常规 OLS 回归。成本函数的惩罚项(用红色标出)增加了模型的偏差,并使对训练数据的拟合更差。
为了简单起见,L2 被称为正则化。随着速率趋向于 0,L2 正则化速度减慢,而不是收缩到 0。在每次迭代中,L2 移除一小部分权重,因此永远不会收敛到 0。
2.4。L1 和 L2 的异同
相似之处
这两种方法都用于避免过度拟合。L1 正则化处理特征的数量,L2 正则化处理特征的权重。
差异
L1 正则化最小化残差平方的和(回归部分:屏幕截图 1 的左边部分)和超参数乘以斜率的绝对值。
L2 正则化最小化残差平方和(回归部分:屏幕截图 2 的左边部分)和λ乘以斜率平方(在红框中标出)。
L1 更稳健,有多种解决方案,而 L2 不那么稳健,只有一种解决方案。
2.5。如何选择 L1 和 L2?
套索回归(L1)可以处理变量选择和参数收缩。因此,当很少有变量具有相当大的实质性影响时,我们更喜欢套索回归。
岭回归(L2)很好地处理了参数收缩,但保留了模型中的所有系数。当存在许多具有小/中等实质性影响的变量时,这是优选的(【ISLR】)作者:Hastie & Tibshirani,2013)。
此外,当存在共线要素时,L2 是首选。一个简单的例子是女性和怀孕。由于这两个特征共线,系数方差往往很大,这进一步损害了估计的稳定性(Terence Parr 教授的帖子)。
Adomas Aleno 在 Unsplash 上拍摄的照片
概念 3:机器学习算法和距离度量
3.1 什么是欧氏距离?你为什么选择它去 KNN?
定义:为了让 KNN 工作,我们需要根据一些度量来确定两个记录之间的相似性。欧几里德距离是距离度量之一。为了计算欧几里得距离,我们取两个向量之差的平方根,如下所示:
截图 3:来自数据科学家实用统计
我们选择欧氏距离有两个原因。
- 欧几里德距离在计算上是高效的。KNN 涉及 K*n 两两比较(K:特征的数量;n:行数)。对于大型数据集,计算量可能相当大。
- 输入变量在类型和规模上是相似的(例如,宽度、高度)。换句话说,我们假设一个向量中一个单位的增加(减少)与另一个向量中一个单位的增加(减少)相同。(这个超级重要。我被一个 FAANG 问过这个问题)。
3.2 维度的诅咒
维数灾难是指当输入变量/特征过多时,很难找到最优解。
每个特征提供了一个维度来聚类数据点,并且当有太多维度(例如,特征、输入变量)时,使得每个观察彼此等距变得困难。
3.3 决策树和随机森林有哪些权衡?
决策树是一种基于树的模型,它根据不同的特征做出预测决策。它易于应用,快速,可解释,但往往适得其反。
随机森林是一种集成学习算法,它通过自举样本在每个节点组合多个决策树。RF 有一个集体决策过程,并采用每个 DT 做出的所有预测的大多数类别。
因此,RF 具有更高的精度。但是相对于 DT 来说计算量很大,我们也不知道它是如何工作的(像黑盒一样)。
3.4 什么是决策树的基尼杂质?
基尼系数是衡量每一部分数据的同质性或杂质的一种方法。测量杂质以分割每个分区中的数据,并最终计算加权平均值:选择导致最低加权平均值的分区。
3.5 I 型和 II 型误差、阿尔法和贝塔水平
第一类错误是指当零假设(H0)为真时,我们错误地拒绝了它。这是一个假阳性。例如,电子邮件过滤算法错误地声称一封电子邮件是垃圾邮件,但实际上它不是。我们使用α水平来表示当 H0 为真时错误拒绝它的概率,也就是 I 型错误。
第二类错误是指当替代假设(Ha)正确时,我们未能拒绝零假设的情况。这是一个假阴性。例如,电子邮件过滤算法无法检测垃圾邮件。我们使用β水平来表示类型 II 错误,即当它为真时拒绝 Ha。
外卖食品
有人要求我解释一些概念,但我无法对所有的概念给出满意的答案。像任何其他数据科学实践者一样,我过于关注 ML 算法的应用/生产方面,而忘记了最基本的概念,这对于面试来说并不理想。
唯一的出路就是分解算法,理解每一块是如何工作的,就像为什么选择欧几里德距离而不是其他度量一样。
Medium 最近进化出了自己的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。
https://leihua-ye.medium.com/membership
我的数据科学面试顺序:
</4-tricky-sql-questions-for-data-scientists-in-2021-88ff6e456c77>
喜欢读这本书吗?
还有,看看我其他关于人工智能和机器学习的帖子。
破解数据科学访谈:基本统计概念
破解数据科学面试
赢在 2021 年:数据科学家/工程师的必读之作,第 2 部分
照片由 Adomas Aleno 在 Unsplash 上拍摄
介绍
数据科学面试涵盖广泛的主题,面试官经常要求我们解释最基本的概念。它更可能会问这样的问题,比如你为什么选择 L1 而不是 L2,而不是从头开始建立一个机器学习算法。
我的数据科学专业网络反复告诉我,他们不期望求职者知道每一种算法。相反,他们期望对基本面有很高的熟悉度。完全说得通。在打下坚实的基础后,你可以很快学会一种新的算法。
统计学和机器学习是密不可分的双胞胎,在这两个领域中有许多概念可以互换使用。在另一章中,我阐述了机器学习中最基本的概念。如果你还没有机会,这里是:
在今天的帖子中,让我们转向统计学,解决数据科学访谈中最常见的 10 个概念。
概念 1:缺失数据
关于缺失数据的面试问题看起来很容易,但很有挑战性。你必须根据数据类型和上下文来定制你的答案。我们中的许多人,包括我在内,未能认识到缺失数据的本质,并相应地调整他们的回应。
我对这个话题做了深入的研究,想出了应对策略。
面试问题:缺失数据有多少种?每种类型的解决方案如何?
总的来说,有三种类型的缺失数据,我们应该针对每种情况分别处理。
第一种:完全随机缺失(MCAR)。
- 缺失数据和其他变量之间没有关系。换句话说,一些数据丢失是没有原因的。它的发生完全是由于随机性。
- 解决方案:我们可以删除缺失值,只关注完整的观察值。然而,MCAR 假设在现实生活中很少是正确的,删除缺失值可能会给参数估计带来偏差。
类型 2:随机缺失(MAR)
- 缺失值不是随机的。它取决于其他变量,但不取决于丢失的数据本身。听起来很困惑?别担心,我需要一段时间来理解要点。
- 这里有一个有用的例子。有两个变量:学生的 GPA 和学生的专业(STEM 和非 STEM)。STEM 学生的绩点有缺失,但非 STEM 学生没有。这里,缺失值(GPA)与另一个变量(major)有关,但与自身无关。
- MAR 是唯一的,不同于第三种类型的缺失值(稍后讨论)。
- 解决方案:由于其他变量会导致缺失值,我们可以使用高级插补方法(如 KNN、线性回归、平均值、众数、中位数)来插补缺失值。然而,代价是我们可以减少数据差异。
第三类:非随机缺失(MNAR)
- 由于变量本身的原因,数据丢失。
- 上例中有两个变量:学生的 GPA 和专业(STEM 和非 STEM)。在这个时间里,绩点高的同学不存在价值观缺失,绩点低的其他同学存在价值观缺失,无论专业如何。
- 变量本身不可观察的特性导致了值的丢失!换句话说,有有效输入和没有有效输入的人是根本不同的。
- 解 : MNAR 引入了一个非常微妙的情况。简单的插补不起作用,因为其他变量不会导致缺失值。完全删除会导致模型偏差。我们应该分析数据丢失的原因,并尽可能收集更多的数据。
缺失数据是一个宽泛的问题,答案可能很长,也可能因上下文而异。请解释丢失的数据有不同的类型,并且您希望在提出解决方案之前了解更多有关业务问题的信息,并从那里着手。
参考
https://www.displayr.com/different-types-of-missing-data/ https://github.com/zhiqiangzhongddu/Data-Science-Interview-Questions-and-Answers-General-
概念 2:装袋和增压
制袋材料
面试问题:什么是装袋?它是如何工作的?赞成?缺点?
Bagging, Bootstrap Aggregating ,是一种集成学习算法,通过替换随机生成新的训练数据,适合多个模型。由于 bootstrap 过程,每个模型都是相互独立的。
对于回归问题,bagging 采用所有模型的平均值。对于分类问题,它采用模型的大多数类。
优点
- Bagging 结合了几个弱学习器,提高了模型性能。
- 它减少了方差并避免了过度拟合。
- 装袋可以并行进行。
缺点
- Bagging 将高偏差引入到具有高偏差的数据集的聚合中。
- 它是不可解释的,并且计算量很大。
助推
面试问题:什么是助推?它是如何工作的?赞成?缺点?
Boosting 是一种集成学习算法,它使用原始数据的子集来生成弱模型。然后,boosting 将它们依次组合成一个更强的模型**。为了创建子集数据,boosting 会评估以前模型的性能,并为以前模型中的错误分类事例增加更多权重。**
赞成的意见
- 当数据有偏差时,提升效果很好。
- 它照顾到了以前模型的重量。
骗局
- 如果数据具有很高的方差,它的性能会很差。
- 计算开销很大。
参考
**</20-machine-learning-related-questions-to-prepare-for-interviews-93bcba72f911> https://en.wikipedia.org/wiki/Bootstrap_aggregating https://stats.stackexchange.com/questions/18891/bagging-boosting-and-stacking-in-machine-learning
概念三:什么是 Bootstrap?
Bootstrap 是一种从原始数据集中重复抽取随机样本的重采样方法。Bootstrap 允许我们甚至用一个样本来对总体参数进行统计推断。在机器学习中,bootstrap 广泛用于集成学习算法,如随机森林。
参考
概念 4:多重共线性
面试问题:什么是多重共线性?怎么检测出来的?解决方案?
当回归模型中的独立变量相互关联时,就会发生多重共线性。它会产生有偏见的估计。
检测多重共线性有两种方法。首先,我们可以画一个相关矩阵,检查两个或两个以上的变量是否高度相关。
第二,我们可以使用方差膨胀因子。VIF 测量回归模型中多重共线性的数量。数学上是模型总方差和只包含单个自变量的方差之比。高 VIF 表示高度共线性。
解决方案
- 丢弃相关变量,保留最重要的变量。
- 转换数据以避免变量相关性。
- 利用主成分分析进行降维。
参考
https://www.investopedia.com/terms/v/variance-inflation-factor.asp
概念 5:维度的诅咒
每个变量都为聚类数据提供了一个维度。太多的变量提供了太多的维度,使得数据稀疏地分布在这些维度上。稀疏分布使数据点距离相等,并使依赖于距离度量的机器学习算法无效,例如,欧几里德距离 ( 统计学习介绍)。
例如,K 最近邻算法采用欧几里德距离作为度量,并且在高维空间中表现不佳,因为它不能找到局部邻居。
参考
https://www.amazon.com/Introduction-Statistical-Learning-Applications-Statistics/dp/1461471370
概念 6:第一类和第二类错误
第一类错误,也称为假阳性,是当零假设(H0)为真时拒绝它。简单地说,第一类错误是指声称某事已经发生,但实际上它并没有发生。
第二类错误,又称假阴性,是指当替代假设(Ha)为真时,拒绝零假设的失败。简而言之,第二类错误是指声称什么都没发生,但实际上却是这样。
以下示例最能说明这两种类型的错误:
效果大小常见问题 作者保罗·埃利斯
毫无疑问,这是我见过的最生动的例子。
概念 7:统计能力
它是当替代假设为真时,检验拒绝零假设的概率。用通俗的语言来说,如果真实的效果存在,我们就不会错过一个效果。
(统计功效是实验研究的一个关键概念,我将结合统计模拟和统计功效再写一篇帖子。敬请期待!)
概念 8:辛普森悖论
它描述了存在于子组中的一种趋势,当这些组聚集在一起时,这种趋势消失或逆转。辛普森悖论可能错误地导致统计推断中误导性的因果主张。
它是由混杂变量引起的,我们必须在分析中包括缺失的变量。
参考
</22-statistics-questions-to-prepare-for-data-science-interviews-d5651a8b3c56> https://medium.com/the-innovation/the-so-called-simpsons-paradox-6d0efdca6fdc https://en.wikipedia.org/wiki/Simpson's_paradox
概念 9:大数定律
在概率论中,LLN 描述了大量重复试验 的结果随着试验次数的增加而接近 的真实期望值。
在英语中,这意味着我们将获得总体参数的真实值(例如,平均值、标准差等)。)经过大量的试验。
一个简单的例子。如果你掷一枚公平硬币 10,000 次,你得到的正面总数大约是 5,000 次,或者大约 50%的概率。然而,如果你只抛 6 次硬币,出现的正面总数可能是 6 或 0,而不是 50-50。
概念 10:中心极限理论
即使总体分布不是正态分布,重复样本的形状也接近正态分布。中心极限理论在统计学和机器学习中有着广泛的应用,特别是在假设检验和统计推断中。
外卖食品
- 技术面试要求彻底理解最基本的概念。我们可以把最复杂的问题分解成这些基本组成部分。
- 在 FAANG 的一次面试中,我被要求从一个样本中构建一个置信区间。读完这篇文章后,你会知道你可以引导样本来创建额外的数据,并使用中心极限理论来进行假设检验。
- 在另一次旅游采访中,有人问我如何处理缺失数据的解决方案。读完这篇文章后,你会知道你应该要求澄清,并决定丢失数据的性质。
Medium 最近进化出了它的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。
https://leihua-ye.medium.com/membership
我的数据科学面试顺序:
</5-python-coding-questions-asked-at-faang-59e6cf5ba2a0>
喜欢读这本书吗?
还有,看看我其他关于人工智能和机器学习的帖子。**
破解数据科学访谈:数据科学家的五项 SQL 技能
破解数据科学面试
Leetcode 助你获得高薪数据职位
介绍
结构化查询语言 SQL 是数据从业者用来检索存储在关系数据库中的数据的首选编程语言。对于数据科学家来说,编写有效的查询请求不再被认为是一项不错的技能,而是一项基本技能。这种趋势可以通过在 DS 招聘信息和面试环节中具体包含 SQL 经验得到支持。
除了编程( Python )、机器学习、 A/B 测试和统计,数据科学家经常被要求定义和从多个来源提取数据,以构建感兴趣的指标。不幸的是,SQL 仍然是一项不受重视的技能,没有足够的数据科学家充分认识到它的多功能性和重要性。
在过去的几个月里,我一直与主要技术公司的高级数据科学家和招聘经理保持密切联系。我收到的评价最高的建议和推荐之一是掌握 SQL 技能,并知道如何有效地提取数据。
为此,我创建了一个三部曲帖子,专为初级程序员量身定制。它从简单到中等难度的问题逐步进行。如果你最近开始了你的 SQL 之旅,我建议在阅读这篇文章之前先看看这三篇文章:1。容易,2。容易/中等和 3。中等。
问题 1:不同性别的累计总数
https://leetcode.com/problems/running-total-for-different-genders/
编写一个 SQL 查询来查找每种性别每天的总分。
按性别和日期排序结果表
查询结果格式如下:
Scores table:
+-------------+--------+------------+--------------+
| player_name | gender | day | score_points |
+-------------+--------+------------+--------------+
| Aron | F | 2020-01-01 | 17 |
| Alice | F | 2020-01-07 | 23 |
| Bajrang | M | 2020-01-07 | 7 |
| Khali | M | 2019-12-25 | 11 |
| Slaman | M | 2019-12-30 | 13 |
| Joe | M | 2019-12-31 | 3 |
| Jose | M | 2019-12-18 | 2 |
| Priya | F | 2019-12-31 | 23 |
| Priyanka | F | 2019-12-30 | 17 |
+-------------+--------+------------+--------------+
Result table:
+--------+------------+-------+
| gender | day | total |
+--------+------------+-------+
| F | 2019-12-30 | 17 |
| F | 2019-12-31 | 40 |
| F | 2020-01-01 | 57 |
| F | 2020-01-07 | 80 |
| M | 2019-12-18 | 2 |
| M | 2019-12-25 | 13 |
| M | 2019-12-30 | 26 |
| M | 2019-12-31 | 29 |
| M | 2020-01-07 | 36 |
+--------+------------+-------+
穿过我的思维
这是那种你第一眼就能解决或者感觉完全迷失的问题。它很容易把你引入歧途。
原因如下。
问题要求“*每个性别每天的总分,”*我的第一反应是计算累计总和,然后按性别和天分组。所以,我错误地试图在 SQL 中找到一个不存在的计算累积和的语法。
经过一番努力之后,我意识到我们可以应用 SUM() OVER( PARTITION BY… )语句来计算按性别分组的累计总和。然后,按天排序结果。
解决办法
# Write your MySQL query statement below
SELECT gender, day, SUM(score_points) OVER(PARTITION BY gender ORDER BY day) AS total
FROM Scores
经验法则:
- 许多 SQL 命令遵循相同的语法,如 SUM() OVER()、ROW_NUMBER() OVER()、LEAD() OVER 等。理解了其中一个命令的用法,您就为其他命令做好了准备。
- 你一定要把你的测试结果分组吗?如果是这样,请使用 PARTITION BY。
- 成绩排名怎么样?如果是这样,请使用 ORDER BY。
问题 2:找出连续范围的起始数和结束数
https://leetcode.com/problems/find-the-start-and-end-number-of-continuous-ranges/
由于 *Logs*
中删除了部分 id。编写一个 SQL 查询来查找表 *Logs*
中连续范围的开始和结束编号。
按 *start_id*
顺序排列结果表。
查询结果格式如下:
Logs table:
+------------+
| log_id |
+------------+
| 1 |
| 2 |
| 3 |
| 7 |
| 8 |
| 10 |
+------------+Result table:
+------------+--------------+
| start_id | end_id |
+------------+--------------+
| 1 | 3 |
| 7 | 8 |
| 10 | 10 |
+------------+--------------+
穿过我的思维
亚马逊在面试过程中包括了这个问题。
此问题询问缺少数字的连续范围的开始和结束。识别连续范围的起点和终点相对容易,可以分别使用 MIN(log_id) 和 MAX(log_id) 找到。棘手的部分是识别两个范围之间的不连续性。例如,我们如何辨别这两个连续范围之间的不连续性:1–3 和 7–8?在这里,我们遗漏了 5、6 和 7。
解决方案在于我们如何对结果进行分组。**如果存在不连续,我们将观察到 log_id 和每个观察的行排名之间的差距。**对于连续范围,观测值应具有相同的范围;如果有任何差距,那么我们观察到组差异的跳跃。
Logs table:
+------------+
| log_id |
+------------+
| 1 |
| 2 |
| 3 |
| 7 |
| 8 |
| 10 |
+------------+
在 Logs 表中,数字 1、2、3 构成了一个连续的范围,log_id 与行排名之差在同一范围内是一致的,为 0(即 log_id —行排名,1–1 = 2–2 = 3–3 = 0)。同样的规则也适用于 7 和 8,两者相差 3(即 log _ id-row ranking = 7-4 = 8–5 = 3)。正如所看到的,当我们从第一范围移动到第二范围时,我们观察到差异的跳跃(不连续)(从 0 到 3)。
解决办法
# Write your MySQL query statement below
SELECT MIN(log_id) AS start_id, MAX(log_id) AS end_id
FROM (
SELECT log_id, ROW_NUMBER() OVER(ORDER BY log_id) AS row_id
FROM Logs
) sub
GROUP BY log_id — row_id
ORDER BY start_id
经验法则:
- 分析手头的问题,把它分解成不同的部分。如果需要,使用子查询来完成次要任务,并移至外部查询。
- ROW_NUMBER() OVER(ORDER BY …):获取每个单元的行号。
- GROUP BY:log _ id 和行号之间的差值,用于标识不连续性。
问题 3:部门最高工资
https://leetcode.com/problems/department-highest-salary/
*Employee*
表包含所有雇员。每个雇员都有一个 Id,一份薪水,还有一个部门 Id 列。
*+----+-------+--------+--------------+
| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1 | Joe | 70000 | 1 |
| 2 | Jim | 90000 | 1 |
| 3 | Henry | 80000 | 2 |
| 4 | Sam | 60000 | 2 |
| 5 | Max | 90000 | 1 |
+----+-------+--------+--------------+*
*Department*
表包含公司的所有部门。
**+----+----------+
| Id | Name |
+----+----------+
| 1 | IT |
| 2 | Sales |
+----+----------+**
编写一个 SQL 查询来查找每个部门中工资最高的雇员。对于上面的表,您的 SQL 查询应该返回下面的行(行的顺序无关紧要)。
**+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT | Max | 90000 |
| IT | Jim | 90000 |
| Sales | Henry | 80000 |
+------------+----------+--------+**
穿过我的思维
亚马逊在面试过程中包括了这个问题。
在给出具体细节之前,让我浏览一下总体分析。问题问的是各部门工资最高的员工。因此,自然的问题是可能有多个工资最高的雇员,我们需要返回匹配的雇员。
下面是具体的细分。我将使用一个子查询来获取按部门 Id 分组的最高(最大)薪金,然后在匹配部门 ID 和薪金之前连接雇员和部门表。
解决办法
**# Write your MySQL query statement below
SELECT d.Name AS Department, e.Name AS Employee, Salary
FROM Employee e
JOIN Department d
ON d.Id = e.DepartmentIdWHERE (DepartmentId,Salary) IN (
SELECT DepartmentId, MAX(Salary)
FROM Employee
GROUP BY DepartmentId
)**
经验法则:
*Department*
表只包含两列,其唯一的功能是返回部门名称为部门 id。这应该会变成看问题提示时的第二本能。- 如果问题是返回每个组(如 department)的最大/最小值,典型的方法是应用子查询为每个组创建一对最大/最小值,然后将该对与外部查询进行匹配(如 WHERE 子句中所示)。
问题 4:第二高的薪水
**https://leetcode.com/problems/second-highest-salary/submissions/
编写一个 SQL 查询,从 *Employee*
表中获取第二高的薪水。
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
例如,给定上面的雇员表,查询应该返回 *200*
作为第二高的薪水。如果没有第二高的薪水,那么查询应该返回 *null*
。
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
穿过我的思维
亚马逊和苹果在他们的采访循环中包含了这个问题。
我在另一篇博文中介绍了如何解决这个问题:
</4-tricky-sql-questions-for-data-scientists-in-2021-88ff6e456c77>
这是一个简单的问题,可以通过以下步骤解决:
1\. Rank Salary in a descending order2\. LIMIT result by 1 and OFFSET 1, which returns the second highest salary3\. Use DISTINCT to deal with duplicates 4\. Include the IFNULL statement in the outer query
查看其他帖子了解详细解释。包含它的唯一原因是为问题 5 提供基线分析,并允许我们比较和对比解决方案。
解决办法
SELECT IFNULL(
(SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1
OFFSET 1),
NULL) AS SecondHighestSalary
经验法则:
- 理解 OFFSET 和 IFNULL 是如何工作的。
问题 5:第 n 高工资
https://leetcode.com/problems/nth-highest-salary/
编写一个 SQL 查询,从 *Employee*
表中获取第 n 份最高工资。
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
例如,给定上面的员工表,其中 n = 2 的第 n 个最高工资是 *200*
。如果没有第 n 个最高工资,那么查询应该返回 *null*
。
+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200 |
+------------------------+
穿过我的思维
这是一个普遍的问题,几乎所有的 FAANG 公司都希望求职者表现出色。
它要求第 n 个最高工资,如果没有这样的值,则返回*null*
。例如,如果我们输入 n=2,则返回第二高的值;n=3,第三高。
第一步,我们需要根据薪水值(降序)在子查询中创建一个排名索引。在采访中,我们需要澄清我们应该如何处理平局:我们应该跳过下一个指数还是返回一个连续的数字?
对于我们的例子,我们选择 DENSE_RANK 来确保连续的排名;说出排名排名 _ 薪资。
在外部查询中,我们选择 DISTINCT Salary 并在 WHERE 子句中设置 n = rankings_salary ,这将返回排名第 n(最高)的薪金。
解决办法
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
RETURN (
# Write your MySQL query statement below.
SELECT IFNULL((SELECT DISTINCT Salary
FROM (
SELECT Salary, DENSE_RANK() OVER(ORDER BY Salary DESC) AS rankings_salary
FROM Employee
) AS aaa
WHERE n = rankings_salary), NULL) AS getNthHighestSalary)
;
END
经验法则:
- 如果您必须编写嵌套查询请求,请不要惊慌。推荐的方法是首先编写子查询中最里面的部分,然后一层一层地移动到外部查询。
- 一个常见的错误是:忘记命名子查询。
- 不要忘记使用 DISTINCT 和 IFNULL。
外卖食品
熟能生巧。
当我开始用 SQL 编码时,我能执行的唯一查询是对表中的唯一值进行计数。快进到今天,我已经习惯了需要子查询、窗口函数和其他高级应用程序的更高级的编码任务。
我想与我的数据同事们分享的最大收获是从小处着手,从错误中学习,并相信增量学习的价值。做那种成长,变得比昨天好 1%的人。你最终会得到回报的。
感谢你的读者,祝一切顺利。
Medium 最近进化出了它的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。
https://leihua-ye.medium.com/membership
我的数据科学面试序列
喜欢读这本书吗?
还有,看看我其他关于人工智能和机器学习的帖子。**
如何赢得 A/B 测试数据科学面试(Doordash 案例示例)
逐步指导模拟面试
布鲁斯·马斯在 Unsplash 上的照片
介绍
A/B 测试是一项受欢迎的技能,经常在数据科学面试中进行测试。同时,帮助准备 A/B 测试面试的资源非常少。在我 15 年的职业生涯中,作为数据科学领域的招聘经理,我发现大多数候选人在这些面试中表现不佳。事实上,实验领域一直在发展,每年都有新的概念和方法变得更加相关。这意味着,即使是多年前做过 A/B 测试的经验丰富的数据科学家,也经常在面试中被难倒。
在本帖中,我们将进行一次模拟面试,这将有助于你理解面试官想要什么,以及如何应对这些面试。你可能会问,为什么要模拟面试?嗯,作为数据科学家,我们有时会在沟通方面遇到困难,在头脑中有一个模板会有很大的帮助。就我个人而言,我还发现,当我能够想象高风险的情况以及它可能如何发展时,它有助于我更好地做好心理准备,更好地处理压力,并在整体上表现得更好。
我们将使用一个来自的送餐公司 Doordash 的例子,该公司的移动应用程序目前在 iPhone 应用程序商店中排名第一。他们通过实验不断改进他们的应用程序,并在数据科学面试中寻找强大的实验技能,特别是对于产品数据科学或产品分析角色。
问题
采访者——door dash 正在扩展到其他领域,比如便利店送货。他们的通知在过去取得了很好的成功,他们正在考虑发送一个应用程序内通知来推广这个新推出的类别。
你将如何设计和分析一个实验来决定他们是否应该推出通知?
解决办法
第 1 部分——提出澄清性问题,以更好地理解业务目标和产品功能细节
面试官想要什么-
- 在深入实验细节之前,你是否先陈述了产品/业务目标?在不知道产品目标的情况下谈论实验是一个危险信号。
受访者——在我们开始实验细节之前,我想确保我对背景的理解是清楚的。像这样的功能可能有多个目标,例如增加新用户获取量、增加该类别的转化率、增加该类别的订单数量或增加总订单价值。你能帮我理解这里的目标是什么吗?
面试官——这是一个合理的问题。对于应用内通知,我们主要是试图提高新类别的转化率,即在所有登录应用的用户中,在新类别下订单的用户的百分比。
受访者——好的,这很有帮助。现在,我还想了解更多关于通知的信息——信息是什么,目标受众是谁?
面试官——目前我们不提供任何折扣。信息只是让他们知道我们有一个新的类别,他们可以开始订购。如果实验成功,我们打算向所有用户推出通知。
受访者——好的。谢谢你的背景介绍。我现在准备好深入研究实验细节了。
第 2 部分—陈述业务假设、零假设并定义要评估的指标
面试官想要什么-
- 您认为除了主要指标之外,还要考虑次要指标和护栏指标
受访者——为了陈述业务假设——我们预计,如果我们发送应用内通知,那么新类别的日订单数量将会增加。这意味着我们的零假设(Ho) 是转换率没有因通知而改变。
现在,让我说明我们希望在实验中包含的不同指标,因为通知的目标是提高新类别的转化率。这将是我们的主要指标。就**次要指标而言,**我们还应该观察平均订单值,看看有什么影响。转换率可能会增加,但平均订单价值会降低,从而导致整体收入下降。这是我们可能需要注意的事情。
我们还应该考虑护栏指标 —这些指标对业务至关重要,我们不希望通过实验影响它们,例如花在应用程序或应用程序卸载上的时间。在这种情况下,我们是否应该包括任何这样的指标?
面试官——我同意你对主要指标的选择,但在这个练习中,你可以忽略次要指标。就护栏指标而言,你是对的——door dash 希望对他们的应用程序的任何功能或版本做出明智的判断,因为我们知道安装了该应用程序的客户的 LTV 要高得多。我们要小心,以免驱使用户卸载应用程序。
受访者——好的——很高兴知道这一点。因此,我们将把卸载的百分比作为我们的护栏指标。
第 3 部分—选择显著性水平、功效、MDE,并计算试验所需的样本量和持续时间
面试官在寻找什么-
- 您对统计概念的了解以及样本量和持续时间的计算
- 您是否考虑了网络效应(常见于双边市场,如 Doordash、优步、Lyft、Airbnb 或社交网络,如 FB、LinkedIn)、星期效应、季节性或新奇性效应等因素,这些因素可能会影响测试的有效性,需要在进行实验设计时加以考虑
受访者——现在我想谈谈实验的设计。
让我们首先看看我们是否需要考虑网络效应——当控制的行为受到给予测试组的处理的影响时,就会出现这种情况。由于 Doordash 是一个双边市场,它更容易看到网络效应。在这种特殊情况下,如果对试验的处理增加了试验组的需求,可能会导致供应不足(即缓冲剂),进而影响对照组的表现。
为了考虑网络效应,我们将需要选择不同于我们通常所做的随机化单元。有许多方法可以做到这一点——我们可以进行**基于地理的随机化或基于时间的随机化或网络集群随机化或网络自我中心随机化。**您想让我详细介绍一下吗?
采访者——我很高兴你提到了网络效应,因为它实际上是我们在 Doordash 实验中仔细寻找的东西。为了节省时间,我们假设这里没有网络效应,然后继续。
受访者——因此,如果我们假设没有网络效应需要考虑,那么实验的随机化单元就是用户——也就是说,我们将随机选择用户,并将他们分配到治疗组和对照组。治疗将收到通知,而控制将不会收到任何通知。接下来,我想计算一下样本量和持续时间。为此,我需要一些投入。
- 基线转换——这是更改前质控品的现有转换
- 最小可检测差异或 MDE —这是我们感兴趣检测的转化率的最小变化。比这更小的更改对业务来说实际上并不重要—通常选择这样的更改,即预期结果的改进将证明实现和维护该功能的成本是合理的
- 统计功效——测试正确拒绝零假设的概率
- 显著性水平——当假设为真时,拒绝零假设的概率
通常选择 5%的显著性水平和 80%的功效,我将假设这些,除非你另有说明。我还假设对照组和治疗组各占一半。一旦我确定了这些输入,我将使用功效分析来计算样本大小。我会为此使用一种编程语言。例如,在 R 中,有一个名为“pwr”的包可用于此目的。
采访者——是的,假设根据分析,我们得到的样本量是每个变化需要 10,000 个用户。你将如何计算测试的持续时间?
受访者——当然,为此我们需要每天登录该应用程序的用户数量。
采访者—假设我们有 10,000 名用户每天登录该应用程序。
受访者——好吧,在这种情况下,我们至少需要 2 天时间来进行实验——我是通过将控制和治疗的总样本量除以每日用户数得出的。但是,在确定期限时,我们还需要考虑其他因素-
- 一周中的某一天效应— 周末的用户群可能与平日不同—因此,运行足够长的时间以捕捉每周周期是很重要的。
- 季节性— 有些时候用户的行为会有所不同,这一点很重要,比如节假日。
- 新奇效应——当你引入一个新功能,尤其是一个容易被注意到的功能时,最初它会吸引用户去尝试。一个测试组开始可能表现良好,但随着时间的推移,效果会迅速下降。
- 外部影响— 例如,假设市场表现非常好,更多人可能会忽略通知,期望获得高回报。这将导致我们从实验中得出虚假的结论
由于上述原因,我建议至少进行一周的实验。
面试官——好的,这很公平。你会如何分析测试结果?
第 4 部分—分析结果并得出有效的结论
面试官想要什么-
- 您对不同场景中使用的适当统计检验的了解(例如,样本均值的 t 检验和样本比例的 z 检验)
- 你检查随机化——这会给你一些印象分
- 你提供最终建议(或实现最终建议的框架)
受访者——当然。分析有两个关键部分-
- 检查随机化 —作为最佳实践,我们应该在分配试验和对照时检查随机化是否正确。为此,我们可以查看一些我们预计不会受到测试影响的基线指标,并对两组进行比较。我们可以通过比较两组之间这些指标的直方图或密度曲线来进行比较。如果没有差异,我们可以得出结论,随机化是正确的。
- 所有指标的显著性检验(包括主要指标和护栏指标)——我们的主要指标(转化率)和护栏指标(卸载率)都是比例。我们可以使用 z 检验来检验统计显著性。我们可以使用诸如 R 或 Python 这样的编程语言来做到这一点。
如果转换率有统计上的显著增加,并且卸载率没有受到负面影响,我会推荐实施这个测试。
如果转换率有统计上的显著增加,并且卸载率受到负面影响,我建议不要进行测试。
最后,如果转换率没有显著增加,我建议不要进行测试。
面试官——听起来不错。感谢您的回复。
结论
在 A/B 测试或实验性面试中表现出色,将为你在招聘过程中提供优势,让你从其他候选人中脱颖而出。所以我强烈建议花时间学习 A/B 测试中的关键概念,并为这些面试做好准备。我组织了一个 2.5 小时的课程,用真实世界的例子和作业深入地涵盖了这些概念。查看— 完成关于产品 A/B 测试的课程,并附上面试指南 ( 使用此链接获得折扣价)
学习和面试愉快!
如果您希望继续看到我关于数据科学和分析采访准备的内容,您可以关注我的Medium。
如果你在寻找数据科学职业相关的指导或者一对一的导师,可以联系我Linkedin。
破解数据科学家的商业案例访谈—第 2 部分
图片由黄敏哈
如果您错过了上一篇文章,下面显示了本系列第 1 部分的链接。
欢迎回到“数据科学家的商业案例访谈”的“第二部分”在这篇文章中,我将讨论解决问题方法的 7 个步骤的其余部分。本文将涵盖:
(1) 第四步:制定问题分析和工作计划——使用问题分析工作表和工作计划来“计划”行动
(2) 第五步:进行分析——简单案例的样本分析(一个玩具的例子)
(3) 第六步:综合发现——构建故事情节金字塔(“分组”结构与“论证”结构)
(4) 第 7 步:制定建议 —将故事金字塔转化为大纲和最终演示文稿
(5) 总结:关键要点
步骤 4:制定问题分析和工作计划
一旦我们对要分析的问题进行了优先排序,我们需要(1)设计详细的分析,( 2)进行适当的工作规划。解决问题方法的 7 个步骤中的第 4 步有助于计划行动。图 28 显示了问题分析和工作计划如何帮助准备行动。
图 28:黄敏哈拍摄的图像
图 29 显示了“工具#4A”:问题分析工作表。“这有助于我们思考您需要通过什么样的分析和活动来证明或否定在步骤 2 和 3 中生成并排列优先级的假设。此外,我们应该写下潜在的数据来源或数据提供者,以明确我们期望从哪里获得相关数据或信息。请注意,相关数据或信息可以是定量的(如 CRM 数据库中的交易数据表),也可以是定性的(如消费者焦点小组访谈、业务利益相关者访谈)。这个阶段的“分析和活动”的描述不必太详细。最好简短扼要。
图 29:黄敏哈拍摄的图像
图 30 显示了“工具#4B:工作计划工作表”这有助于我们指定最终产品(即关键交付成果)并为每个关键任务分配责任和期限。请注意,工作计划工作表(以及问题分析工作表)对于数据科学经理非常有用,可以确保最终交付成果的总和有助于团队找到他们想要找到的答案。此外,让负责任的所有者和截止日期在团队成员中明确期望。重要的是与团队成员共同开发这一工具,以建立和达成共识。最后,我要推荐 2 个实用的小技巧:(1)请避免共同承担责任。将一项关键任务分配给两个以上的人,不清楚谁对结果负责。如果您必须将一项关键分析或任务分配给两个以上的人,您仍然可以明确领导和支持角色。(2)对于时间线,请确保您已经包括了一些缓冲区。将会出现意外事件和数据问题,这可能会延迟整体时间表(例如,数据质量问题、基础设施问题、招聘问题、关键利益相关方的可用性等)。)在初始工作计划中包含缓冲区有助于您减少意外问题造成的潜在延迟。
图 30:黄敏哈拍摄的图像
图 31-图 33 显示了一个简单的“问题分析工作表”的例子以约翰章鱼为例。请注意,这一步有助于我们定义单独的工作流,并确定相关的数据和信息提供者。
图 31:由黄敏哈拍摄的图像
图 32:由黄敏哈拍摄的图像
图 33:黄敏哈拍摄的图像
步骤 5:进行分析
在步骤 4 中定义了关键的分析和活动之后,您终于可以进行实际的分析了。这是一部分,可能会因项目和问题而有很大不同。我将通过一个简单的案例来展示这个阶段是如何随着时间的推移而发展的。对于大多数商业问题,从基线(没有采取任何行动的状态)和目标开始是有帮助的。如果您同意度量这两种状态的标准,那就更好了。如果没有,您可能需要额外的工作来清楚地定义要使用的度量标准,并与相关的利益相关者建立共识。对于约翰章鱼的例子,我们可以从当前状态的评估开始。“瀑布图”非常有用,可以直观地显示基线和目标,以及要缩小的差距。图 34 显示了 John Octopus 示例的基线、差距和目标。为了购买一台售价 900 美元的 MacBook Pro 电脑,John Octopus 需要弥补 240 美元的缺口。
图 34:黄敏哈拍摄的图像
对减少开支的影响的第一次分析如图 35 所示。收集多个时间段的数据通常很重要,因为数据中可能存在季节性或趋势性。图 35 中的月支出数据表确实显示了支出随时间的波动。与单个月的估计相比,使用 3 个月的平均值(32 美元)将是对平均月支出更可靠的估计。图 36 中每月平均花费的细目证明了最初的假设是错误的。咖啡和漫画书是最大的两项支出,而不是视频游戏和 CD。让我强调一下,最初的假设不一定是正确的。这个阶段的数据和分析将证明或否定一个假设,这是一个有助于集中分析的工具。
图 35:由黄敏哈拍摄的图像
图 36:由黄敏哈拍摄的图像
找出哪些项目是支出最高的项目是一回事,但你还需要考虑减少支出的可行性。图 37 显示了定性开支削减可行性评估的示例。举个例子,章鱼哥约翰决定不削减咖啡开支,因为早上没有咖啡他无法正常工作。根据图 36 中项目的平均月支出(即对减少支出的影响)以及图 37 中削减支出的可行性(按高/中/低评估),我们可以在图 38 中创建一个“优先化”矩阵。这表明,电子游戏和光盘是约翰没有太多困难就能减少开支的物品。我们可以反映这一分析的结果,并评估我们缩小了多少差距。图 39 显示,在视频游戏和光盘上的支出削减可以在未来 6 个月贡献 80 美元,这将差距缩小到 160 美元。
图 37:黄敏哈拍摄的图像
图 38:由黄敏哈拍摄的图像
图 39:由黄敏哈拍摄的图像
作为第二项分析,约翰·章鱼评估了他可以通过出售不必要的资产(如二手漫画书)赚多少钱。图 40 总结了这一分析的结果,通过出售不必要的资产,确定了 50 美元的额外节约。图 41 回顾了增加额外节省后与目标的差距。由于增加了 50 美元,剩余的差额现在减少到 110 美元。请注意,量化每次分析的影响并将其与目标进行比较有助于您判断何时可以停止。如果整体影响大到足以实现你的目标,你可以早点停止,而不是做所有的活动或分析。
图 40:黄敏哈拍摄的图像
图 41:由黄敏哈拍摄的图像
图 42 和图 43 总结了分析# 3——朋友和邻居访谈的结果:约翰调换工作能增加多少收入。在仔细研究了他的发现后,约翰意识到他每小时只能挣 6-8 美元。图 44 总结了他的发现。通过换工作来增加他收入的假设似乎行不通。我们被困在这里了吗?我们如何缩小剩下的差距?
图 42:由黄敏哈拍摄的图像
图 43:由黄敏哈拍摄的图像
图 44:由黄敏哈拍摄的图像
这是多重迭代开始发生的地方。有时候,最初的假设可能不足以实现你的目标。我们需要考虑其他可能的想法。通常,到目前为止进行的数据和分析为新想法提供了基础。图 45 显示了该过程的输出示例。章鱼哥约翰意识到他可以同时遛多只狗。这可以让他的月收入增加 32 美元,而不需要投入更多的时间。在反映了他月收入的增加后,图 46 显示他现在可以买一台 982 美元的电脑,这超过了他 900 美元的目标。一个问题就解决了!
图 45:由黄敏哈拍摄的图像
图 46:黄敏哈拍摄的图像
图 47 总结了一些在“进行分析”步骤中有用的技巧让我再次强调多次迭代的重要性。与其试图以缓慢的速度达到完美,不如快速高效地多次迭代。快速失败是非常受鼓励的,你总是可以迭代多次来改进。
图 47:黄敏哈拍摄的图像
第六步:综合调查结果
一旦你完成了第 5 步的分析,第 6 步就是交流的重要开始:“综合发现”。请注意,合成不同于总结。图 48 对比了基于相同基本事实的综合与汇总的不同之处。合成倾向于更关注“那又怎样?”
图 48:黄敏哈拍摄的图像
金字塔原理(芭芭拉·明托)有助于综合潜在的事实。图 49 显示了合成过程与交流的不同之处。合成通常是自下而上的。从潜在的事实、数据和分析出发,分组有助于找到一种模式或相似性。通过问“那又怎样”,你最终可以将这些综合成统治思想。相比之下,沟通通常是以自上而下的方式进行的。
图 49:由黄敏哈拍摄的图像
图 50 介绍了“工具#5:故事情节金字塔”你可以有一个“分组”结构,其中一个主导思想由独立但连贯的想法支持。另一个替代方案是“论证”结构,在这种结构中,主导思想由一系列想法支持。图 51 和图 52 提供了这两种逻辑结构的更多细节和优缺点。
图 50:由黄敏哈拍摄的图像
图 51:黄敏哈拍摄的图像
图 52:由黄敏哈拍摄的图像
为了使这些更具体,图 53 和图 54 提供了一个“分组”结构的例子。“分组”结构对注重行动的观众来说很有效。另一个主要好处是,如果一个点被拒绝,其余的点仍然有效。然而,对于某些观众来说,这可能被认为是太强有力了。
图 53:由黄敏哈拍摄的图像
图 54:黄敏哈拍摄的图像
图 55 提供了一个“参数”结构的例子。这对抗拒的观众可能是有效的。但是,如果听众不同意这种情况或评论,论点可能无法说服。
图 55:黄敏哈拍摄的图像
图 56 提供了一些有用的综合技巧。组织和结构是建立一个坚实的故事情节的关键。保持信息的重点是值得的。即使你的分析中有有趣的事实,如果这些事实与关键问题无关,也应该避免离题。
图 56:黄敏哈拍摄的图像
步骤 7:提出建议
一旦你在第 6 步制定了一个“故事情节”,7 步解决问题方法的最后一步就是“制定建议”我来强调一下这个阶段最后沟通的重要性。有时,由于缺乏令人信服的沟通,非常畅销的分析和令人信服的数据无法产生业务影响。在某些情况下,有效的沟通者甚至可以用不那么令人信服的数据和分析成功地说服听众。图 57 显示了你在步骤 6 中开发的故事情节金字塔如何转化为最终报告或演示的大纲。
图 57:黄敏哈拍摄的图像
讲述故事的一种流行方式是 SCR:情境、复杂、解决。这种方法非常有效,尤其是在观众比较抗拒的情况下。此外,东方文化的观众往往喜欢这种讲故事的方式(即建立)。相比之下,西方文化的观众通常更喜欢“自上而下”的讲故事方式。更多高层领导受众倾向于“自上而下”的讲故事方式。然而,这些在很大程度上取决于具体的受众和情况。图 58(6 号工具)显示了 SCR 的细节。
图 58:由黄敏哈拍摄的图像
图 59 提供了一家资产管理公司基于情景、复杂性和解决方案讲述故事的示例。对情境和复杂性的认同对于受众接受决议中的建议至关重要。
图 59:由黄敏哈拍摄的图像
总结:关键要点
我介绍了一个 7 步解决问题的方法,它可以用于业务问题和数据科学问题(尤其是决策科学问题或更面向应用的数据科学问题。)希望您发现这种结构化的问题解决方法有助于(1)为数据科学家的业务案例面试做准备,以及(2)作为数据科学家处理日常活动和任务。在图 60 中,总结了 7 步解决问题方法中每一步的要点。
图 60:黄敏哈拍摄的图像
*本文中的约翰·章鱼例子改编自渡边谦的《解决问题 101:给聪明人的一本简单的书》。
免责声明:我并不代表麦肯锡建议的解决问题的方法,这里有所描述。我只是分享我的观点。
参考
- 金字塔原理:写作和思考中的逻辑,ISBN-13:978–0273710516,芭芭拉·明托
- 解决问题 101:一本给聪明人的简单的书,**ISBN-13:**978–1591842422,渡边谦
原载于 2021 年 12 月 11 日【http://bigdataco.blogspot.com】。
破解数据科学家的商业案例访谈:第 1 部分
问题定义、结构化和优先级排序
图片由黄敏镐
商业案例研究面试问题往往是面试过程中最难的部分,尤其是对于没有工作经验的早期数据科学家。即使在得到一份工作后,从其他团队和利益相关者那里获得一种结构化的方式来制定和解决业务问题也是有益的。
基于我作为前麦肯锡顾问和数据科学家超过 10 年的学习,我分享一个“解决问题的 7 个步骤”的方法。这种结构化的业务案例/问题解决流程以及相关的框架和模板将帮助您更轻松地处理和解决新的业务问题。
在本文中,我将讨论:
(1) 问题解决方法的 7 步概述
(2) 第一步:定义一个问题——如何通过解决一个恰当的问题来避免第三类错误
(3) 第二步:构建问题——如何将问题分解成可管理的子问题
(4) 第三步:确定问题的优先级— 如何确定要解决的子问题的优先级
下面显示了其余步骤的“第 2 部分”的链接。
破解数据科学家的商业案例访谈—第二部分| Minha Hwang |迈向数据科学
概述“解决问题的 7 个步骤”方法
解决业务问题本身就是一项艰巨的任务。然而,应用结构化的问题解决方法对于数据科学家来说非常有帮助,可以使这变得更加愉快。这个在大学或者研究生院还没有教好。像麦肯锡这样的顶级管理咨询公司已经开发了这种方法,这也是他们成功的秘诀之一。本着分享的精神,我将在这一系列的两篇文章中详细描述这种方法。本文将有助于(1)数据科学家准备业务案例面试,(2)数据科学家及其业务合作伙伴解决业务问题并产生业务影响,(MBAs 准备管理咨询公司的业务案例研究面试,以及(4)博士生和研究人员采用假设驱动的方法并提高研究效率。解决业务问题的 7 个关键步骤如下:
(1)定义一个问题
(2)构造一个问题
(3)优先处理问题
(4)制定问题分析和工作计划
(5)进行分析
(6)综合研究结果
(7)提出建议
这不是一个线性过程。因此,你需要重复几次来得到一个更好的解决方案,直到你确信进一步迭代的好处是有限的。定期修改和重新评估是非常重要的。这些步骤听起来非常直观和简单。在这一点上,你可能想知道这是否有帮助。魔鬼在细节中。现在,让我深入研究每一个步骤,展示它是如何工作的。我在图 1 中总结了“解决问题的 7 个步骤”。
图 1:图片由 黄敏哈 拍摄
第一步:定义问题
解决业务案例的最重要的步骤是“问题定义”,这一点经常被忽视如果机器学习工程师解决了错误的问题,那么用复杂的自然语言处理模型完美解决问题还有什么意义?信不信由你,这种“第三类错误”(解决一个错误的问题)在实践中经常发生。如果有一个合适的问题定义阶段,这是完全可以避免的。
在描述这个阶段的关键要素之前,我想指出一个可以解决的“定义明确的问题”与我们通常所说的“问题”有很大的不同在日常互动中,我们通常所说的“问题”是指认识到“有些事情不对劲”发生的事情和应该发生的事情(即目标)之间存在差距。)或者已经发生的和可能发生的有差距(即机会。承认“问题”是困难的,而且会产生焦虑。它往往非常“笼统”,可以只是“陈述事实”。这仅仅是对形势的认识,需要采取行动。
可以解决的“明确定义的问题”具有以下特性:
- 一个发人深省的问题,而不是一个事实
- 具体,不笼统
- 可测量
- 行动导向
- 相关(针对关键问题)
- 有时间限制的
此外,它是
- 有争议的(非事实陈述或无争议的主张)
- 关注决策者需要什么才能前进
定义明确的问题的这些性质通常可以用一个“聪明”原则来概括。这个原理如图 2 所示。
图 2:图片由 黄敏哈 拍摄
为了使“明确定义的问题”更具体,让我用一个简单的玩具例子来对比“明确定义的问题”和我们通常所说的“问题”。下面总结了这个玩具例子的背景:约翰章鱼。
- 事情经过:约翰上周六和朋友去看了《Ready Player One》(虚拟现实上的电脑生成动画电影(即 CGI),他很喜欢。
- 目标:约翰看完电影后印象深刻。因此,他想成为好莱坞 CGI 电影导演。
- 需要采取行动的情况(典型意义上的问题):
- 约翰对如何制作电脑动画电影毫无头绪。
- 他甚至没有电脑。
- 首先,他需要弄清楚如何买一台电脑,以便开始工作。
我们有足够的信息来正确定义这个问题吗?不,还没有!我已经在图 3 中总结了我们目前所拥有的信息。
图 3:图片由 黄敏哈 拍摄
让我介绍第一个问题定义工具,来阐明我们需要哪些额外的信息来“正确地定义”问题。**“问题定义工作表”**是一份很好的清单,可以确保我们拥有正确定义问题所需的所有信息。关键要素是:
(1)问题定义:请强迫自己把这个当成一个“问题”。
(2)背景:了解问题的历史和组织背景很重要。
(3)关键利益相关者:谁是关键决策者?谁会受到这个决定的影响?
(4)成功的标准:没有这个,你怎么知道自己是否成功解决了业务问题?请确保在解决问题之前正确定义“成功指标”。你解决不了问题,这是无法衡量的。
(5)约束:把甚至不应该考虑的写下来也是有帮助的。
(6)解决方案空间的范围:通常,对于问题的地理或业务线焦点有明确的要求。检查时间要求也很好(即 4 周、3 个月、1 年后的答案?).有时候,80/20 方向性的答案是渴望的。其他时候需要非常精准的回答(网站流量增加 1%或者网站流量增加 1.1%)。明确所需的准确性有助于正确衡量提议的方法或解决方案是否合适。
为了便于将来使用,第一个工具“问题定义工作表”如图 4 所示。
图 4:图片由 黄敏哈 拍摄
现在,让我们为 John Octopus 玩具示例收集更多信息。这些是:
- 时机:John 希望在暑假期间从 8 月份开始获得一些设计实践,而暑假只有 6 个月的时间。
- 计算机的类型和价格范围:
- 约翰发现 MacBook Pro 很适合 CGI 使用。
- 二手 MacBook Pro 售价约 900 美元
- 其他上下文:
- 约翰不想借或租电脑。
- 约翰有 140 美元的存款。他的父母每月给他 100 美元的零花钱,他每周帮邻居遛狗一次,每小时挣 15 美元,相当于每月 60 美元。
- 约翰平均每月花费 80 美元。
- 如果约翰想在 10 个月内拥有一台电脑,他可以通过存钱来买。
有了额外的必需信息,我们可以正确地定义 John Octopus 的问题,如图 5 所示。
图 5:图片由 黄敏哈 拍摄
看到问题定义的坏例子通常是有帮助的。图 6 显示了同一个 John Octopus 例子中有缺陷的问题定义的三个例子。
图 6 图像由 黄敏哈 组成
作为最后一个练习,我们可以再考虑一个例子,这个例子不太基于个人经验,但更多地来自商业案例。
图 7 显示了洋葱银行有缺陷的问题定义的更多例子。
图 7:图片由 黄敏哈 拍摄
相比之下,图 8 显示了洋葱银行的一个明确定义的问题的例子。
图 8:图片由 黄敏哈 拍摄
希望本文能帮助您理解定义良好的业务问题的关键要素。一个好的问题定义是 60%以上的解决问题的努力。请确保您在数据科学家访谈或作为数据科学家的日常任务中正确定义了问题。
第二步:构建问题
一旦你恰当地定义了一个问题,下一步就是“构建一个问题”通常,已定义的问题太大,即使在问题定义之后也无法有效解决。将一个问题分解成子问题(即问题)的更小和可管理的组成部分非常有助于使问题解决可行和有效。这允许将工作划分并分配给不同的团队成员,并进行适当的责任分配。此外,这一步是确定问题优先级的后续步骤的基础,在这一步中,将根据解决问题的重点来确定优先级。“逻辑树”(2 号工具)在问题结构化的过程中非常有用。图 9 介绍了一个逻辑树。
图 9:图片由 黄敏哈 拍摄
一个“逻辑树”(2 号工具)帮助我们确保待维护问题的完整性。通过检查离散的组块(即子问题)是互斥的,并且是集体穷举的(即“MECE”),我们可以确保解决问题的部分最终将真正解决问题。由于这些部分没有重叠,我们可以避免重复工作。事实上,没有差距(集体详尽)确保我们没有遗漏任何重要的东西。这也有助于作为一个通信设备。在团队中创建逻辑树有助于建立共识,这也可以在团队之外以结构化的方式共享。最后,这有助于集中使用框架和理论。验证提出的框架和理论通常会揭示逻辑上的差距或尚未考虑的方面。
有两种不同类型的逻辑树。在解决问题的初始阶段,一个"问题树 " ( 什么/如何树)更有助于思考整个解决方案空间。一旦你对问题有了足够的了解(例如,经过几次反复的探索性分析、最初的二手数据研究,或者访谈和会议),一个“假设驱动树”(为什么树)就变得更加相关了。该树更适合基于假设集中解决问题的努力,并作为确定优先级的基础。数据科学领导者成功的秘诀是尽早建立良好的假设并正确安排工作的优先级。图 10 总结了两种类型的逻辑树。
图 10:图片由 黄敏哈 拍摄
为了使“逻辑树”的使用更加具体,让我们通过使用 John Octopus 的一个简单案例来开始一个练习。图 11 是一个样例“问题树”,您可以创建它来为 John Octopus 解决问题。请注意,我们正在询问“如何”开发该树的问题。图 11 显示了最高的两个级别。由于我们的目标是在 6 个月内拿出 900 美元购买一台二手 MacBook Pro 电脑,我们可以开始将问题分为增加收入和减少储蓄。为了开发下面的分支,我们必须考虑一下约翰·章鱼哥是如何获得收入的,他的大部分钱都花在了哪里。
图 11:图片由 黄敏哈 拍摄
一旦我们开发了顶层,我们就可以进一步开发上层和下层分支的问题树。如果你想练习,我会建议你不要看下面的解决方案。在实践之后,你可能会意识到开发一个“MECE”树需要大量的思考,即使是像这样一个简单的问题。图 12 和图 13 分别显示了上分支和下分支的潜在问题树。
图 12:图像由 黄敏哈 拍摄
图 13:图片由 黄敏哈 拍摄
什么会被认为是不好的“问题树”?看到不好的例子有助于理解好的解决方案需要什么。图 14 显示了 John Octopus 问题的有缺陷的问题树示例。你可以看到,通过混合不同的水平,这是不一致的——增加收入与许多支出类别细分处于同一水平。此外,这不是“MECE”,因为咖啡和糖果等重要的消费类别没有显示出来。
图 14:图片由 黄敏哈 拍摄
到目前为止,我们已经看到了 John Octopus 问题的“问题树”(如何/什么树)的例子。如果您创建一个“假设驱动树”(为什么树),它与您创建的问题树有什么不同?图 15 显示了 John Octopus 问题的“假设驱动树”示例。请注意,这可以通过问一系列“为什么”的问题来展开。
图 15:图像由 黄敏哈 拍摄
现在,让我们通过使用一个更加面向业务的示例来做另一个创建“问题树”的练习。假设你被可口可乐公司聘为管理顾问,该公司试图解决全球盈利能力下降的问题。有许多方法可以开发“问题树”。这些将帮助你考虑给定问题的不同维度和方面。图 16、图 17 和图 18 显示了针对给定问题开发问题树的三种不同方式:利润驱动、地理位置和业务线。
图 16:图片由 黄敏哈 拍摄
图 17:图片由 黄敏哈 拍摄
图 18:图像由 黄敏哈
最后再考虑一个例子,是 A/B 测试的数据科学问题。我们试图解决的问题是“如何提高 A/B 测试的灵敏度。”对于许多大型科技/互联网公司来说,这是一个重要的问题,这些公司使用基于 A/B 测试的数据驱动决策来做出产品功能发布决策。通过提高指标敏感度,公司可以用更少的数据进行精确的推断(即,更短的实验持续时间或更小的实验样本量)。)典型的 A/B 检验依赖于一个独立的 2 样本 t 检验作为检验统计量。对 A/B 测试中驱动测试统计量的因素有一个直观的理解,将有助于您开发一个问题树,并集思广益以提高度量敏感度。提醒一下,A/B 测试的测试统计如下所示。从更直观的角度来看这个公式,你可以意识到 3 件事很重要:效果大小(即你的治疗组和对照组之间的均值差异)、方差(即噪音水平)和样本大小。请注意,我在顶部简化了一个更通用的公式,假设治疗组和对照组之间的方差相同(即混合方差),治疗组和对照组之间的样本量相同,以方便直观。
图 20:图片由 黄敏哈 拍摄
图 20 显示了增加 A/B 测试灵敏度问题的潜在“问题树”。
图 20:图片由 黄敏哈 拍摄
希望你已经对如何应用逻辑树将问题分解成更易管理的块(即子问题)有了很好的理解。总之,好的逻辑树是(1)一致的,(2)相关的,(3)“MECE”。图 21 在一张图中更清楚地说明了这一点。
图 21:图片由 黄敏哈 拍摄
最后,我将通过提供一些关于“如何制作逻辑树”的提示来结束这一部分图 22 显示了技巧,以及基本原理(即为什么)。
图 22:图片由 黄敏哈 拍摄
第三步:区分子问题的优先级
一旦你把一个问题分解成子问题,下一步就是“优先化”。这实质上是砍掉问题树或假设驱动树的分支,把注意力集中在最重要的事情上。图 23 以图形的形式展示了这个过程。
图 23:图像由 黄敏哈
我们可以使用哪些潜在的标准来确定优先级?潜在(业务)影响、技术或执行可行性、风险通常是有用的标准。个人或公司的价值观也可以作为指导。在实践方面,参考高层管理议程以确保您的项目将从领导和高层管理获得所需的支持是一个不错的主意。检查 okr 在这方面会有帮助。图 24 总结了您可以考虑的潜在标准。
图 24:图片由 黄敏哈 拍摄
图 25 显示了“工具#3”,它对于解决问题的优先化步骤非常有用。优先级矩阵(2 x 2 矩阵),其中一个轴是潜在影响,另一个轴是可行性,是一个有用的可视化工具,可以对要关注的子问题进行优先级排序。在图 25 中,我使用了 John Octopus 问题来使它更加具体。
图 25:图片由 黄敏哈 拍摄
为了更熟悉解决问题的第三步:优先化,让我们再次使用约翰章鱼问题。在图 26 中,我展示了问题树的上层分支,以及如何应用优先级。类似地,在图 27 中,问题树的较低分支显示了类似的优先级排序练习。
图 26:图片由 黄敏哈 拍摄
图 27:图片由 黄敏哈 拍摄
到目前为止,结构化问题解决方法的前 3 个步骤:(1)定义问题,(2)构建问题,以及(3)区分问题的优先次序,都是通过例子来介绍的,使它们更加具体。
在后续文章(第 2 部分)中,我将详细描述解决问题过程的其余部分。下面显示了下一篇文章的链接。
*本文中的 John Octopus 例子改编自《解决 101 个问题:聪明人的一本简单书》渡边谦的书。我会推荐那本书,尤其是给学生看的。
免责声明:我并不代表麦肯锡建议的解决问题的方法,这里有所描述。我只是分享我的观点。
原载于 2021 年 9 月 6 日 http://bigdataco.blogspot.comhttp://bigdataco.blogspot.com/2021/09/cracking-business-case-interviews-for.html。
破解微软 Power BI: DA-100 考试!
最近,我通过了微软 Power BI: DA-100 考试的数据分析,并将微软数据分析师助理认证添加到我的技能桶中。
在 Unsplash 上由 Adeolu Eletu 拍摄的照片
在这篇文章中,我将分享我的个人经验,学习 BI 和清除 DA-100 考试。我希望这能帮助其他有志之士。我不会妥协的签署 NDA,因此没有问题将在这篇文章中披露。
Power BI 是最常用的商业智能和数据可视化工具之一。在这个数据驱动的世界中,该认证有助于展示您的数据分析技能。
关于考试 DA-100
微软现在正从基于工具的认证转向基于角色的认证,如数据分析师、数据工程师、数据科学家、开发人员等。
使用 Microsoft Power BI (DA-100)分析数据是 Microsoft 数据分析师助理认证的要求。考试费用是 165 美元。从 2021 年 6 月起,认证有效期缩短至 1 年。但是可以在微软学习网上免费续借。
该考试测试设计和构建可扩展数据模型、清理和转换数据以及启用高级分析功能(通过易于理解的数据可视化提供有意义的商业价值)的知识。
考试分为 5 个部分:
- 准备数据(20-25%)
- 对数据建模(25–30%)
- 可视化数据(20–25%)
- 分析数据(10-15%)
- 部署和维护可交付成果(10-15%)
点击此处查看详细技能概要。衡量的技能不断更新。因此,请务必查看考试页面。
这是一个 180 分钟的在线考试。考试由两部分组成:MCQs 和案例分析。第一部分大约有 45-50 个选择题,在 2-3 个案例研究中每个大约有 4-5 个问题。最高总分可能是 1000,及格分数是 700。考试刚结束,成绩就出来了。
目前,微软为受新冠肺炎影响的求职者和学生提供 15 美元的考试。
备考
谈到我使用 Power BI 的经验,我使用该工具完成了几个小型学术项目。除此之外,我在考前真的没有任何行业经验。所以我真的不得不振作起来通过考试。
我发现备考最好的就是微软提供的官方学习路径。学习路径包括每个主题的详细阅读材料和精心设计的练习概念的实验室。相信我,你不会厌倦阅读这些材料。为了更清晰起见,我还曾经在 Youtube 频道上回顾过一些概念,比如“立方体中的家伙”和“T2”。
此外,我参加了 Udemy 上的 MICROSOFT POWER BI DA-100 考试:高级 2021 模拟测试课程。它由不同主题的样题组成,解决它们可以让你了解真正的考试。此外,你可以谷歌转储不同网站上发布的问题集,它们值得练习。
其他一些重要的提示…
- 在开始考试之前,你必须上传周围的照片。做好准备。
- 提供的时间足够完成考试。所以,不要急着通读每个问题,不要错过任何一个微小的细节。
- 如果你在 DAX 上很弱,不要害怕,没有多少高级 DAX 被评估。
- 区段提交后无法重新访问。所以,在提交之前,重新核实一下答案。
最后,我想说,微软官方文档是关键!!如果你完成了学习材料,没有人能阻止你通过考试。我希望我的经历能帮助 DA-100 的有志之士。我最美好的祝愿伴随着每个备考的人:)
如有任何其他疑问,请随时评论。
疯狂简单的异常检测帮助客户取得成功
如何检测使用情况的变化,及时做出反应并让您的客户满意
异常检测这个话题很吸引人。有大量的方法可以使用,从简单的统计到更复杂的无监督学习方法。此外,异常检测的影响是巨大的。当事情没有按计划进行时,检测的能力是一个奇妙的工具,并且具有拯救生命的潜力(例如在预防性维护中)。
在本文中,我们将探索一种极其简单的异常检测方法。有时候最简单的解决方案可能会产生最大的影响。在这种情况下,我们将使用中位数绝对偏差或 MAD 来检测企业交易的 WhatsApp 消息数量中可能的异常值。
介绍
在客户成功领域,特别是在 SaaS B2B 公司,衡量我们客户的产品使用是至关重要的。本质上,SaaS 企业希望了解他们的客户如何使用他们的产品,以及他们使用了多少。背后的原因是,如果客户不使用你的产品,很可能他们遇到了某种麻烦。这可能是因为他们不知道如何使用它,他们没有从中获得价值,或者他们遇到了某种产品缺陷。在任何情况下,使用率下降都会导致客户流失。除其他事项外,客户成功团队的角色是识别可能发生这种情况的案例,并帮助这些客户最终引领他们走向成功。
除了使用 MBR 或 QBRs(月度或季度业务回顾)进行定期检查之外,客户成功团队还可以通过了解客户何时较少使用他们的产品来采取积极的态度。这是一个实现异常检测的完美例子。这个想法是检测每个客户的使用数据中的异常,并让客户成功团队联系那些放弃使用的客户。
数据
要使用的数据类型因业务而异。如果你是 Shopify 这样的电子商务平台,你可能会对跟踪销售感兴趣,如果你是 MailChimp 这样的电子邮件营销平台,你会对发送的电子邮件感兴趣。当我在 Sirena 工作时,我会使用 WhatsApp messages 的使用数据,Sirena 是一款让企业通过 WhatsApp 与客户沟通的应用。在本文中,我将使用从一个非常简单的模拟中随机生成的 WhatsApp 消息数据。这个数据集在我的 Github 中公开:fake data/whatsapp messages
该数据集包含 4 个不同客户在 10 周内处理的邮件数量。为了简单起见,我们将只关注一个客户;顾客 3。
异常检测
疯了
中位数绝对偏差(MAD)是一个非常简单的样本变异度量。从这个意义上来说,它非常类似于衡量统计离差的标准偏差。MAD 被定义为每个观测值和中值之间的残差绝对值的中值:
然而,与标准偏差相比,MAD 的一个很大的优点是其对异常值的稳健性或不敏感性。平均值和标准偏差都受到异常值的严重影响,因此对异常检测极为不利。在他们的论文中,Leys 等人(2013)表明,许多研究人员仍然使用标准差来表示离差,并建议转向 MAD。在这篇文章中,我将向您展示如何在 Python 中使用它来检测异常或离群值。
实施
我们将从单个客户开始,在本例中为客户 3:
您可能会惊讶于它的实现是如此简单。事实上,计算 MAD 基本上只是 python 的一行代码:
这一行所做的是定义一个(lambda)函数,该函数接受一个 numpy 数组(x ),并计算每个 x 与 x 的中值之差的元素绝对值的中值,这正是 MAD 的定义。简单。
在计算 MAD 时,我们面临的唯一(非常微小的)复杂情况是,我们实际上想要计算滚动 MAD。但是使用 numpy 也很简单:
如你所见,首先我们计算滚动中值,然后我们加上滚动平均值。我们可以绘制出它与数据的关系,从而了解我们正在做的事情:
我们可以看到 MAD 是高度滞后的,这没关系。请记住,我们不是要一个非常复杂的异常检测器或预测模型。我们只需要了解对我们的客户来说什么是“正常的”使用变化。
很好,现在我们有了 MAD,我们需要定义标准来理解一个观察是否是一个实际的异常。为此,我们将添加一个阈值,并为我们的滚动 MAD 创建上限和下限:
太好了!现在,我们可以将这些边界添加到图表中,看看我们在处理什么:
看起来不错!现在我们有了 MAD 和一个边界,它可以帮助我们确定一个观察是否是异常。这意味着,对于每个时间点,如果观测值高于滚动 MAD 的上限或低于下限,我们就说这是一个异常。
在这种特定情况下,50%的阈值似乎有点太紧了。我们可以尝试改变这种情况,直到我们对假阳性的数量感到满意为止。我们可以用 70%试试。
使用这些数据,我们可以很容易地获得 MAD 实现检测到的所有异常的列表:
结果向我们显示了每天的使用情况(值)、我们期望看到的情况(MAD)和时间间隔(MAD 上限和下限)。
结论
在这篇文章中,我们探索了一种非常简单的方法,使用中值绝对偏差或 MAD 来实现使用数据的异常检测。当然,您可以做很多修改来适应您的特定用例,比如滚动窗口、阈值或者决定何时通知您的团队。我敢肯定,您可以想象当客户的一个帐户停止使用时,一个松散的集成会通知客户成功管理人员。但是,如果您的产品使用有相关的季节性,请考虑调整通知服务。例如,在我们的例子中,如果使用率下降发生在周末(使用率预计会在周末下降),通知 CSE 没有太大意义。另一种选择是有两个 MAD 界限,一个是周末的更宽松的界限,另一个是工作日的更严格的界限。可能性是无限的。
参考文献
莱斯大学、莱伊大学、克莱恩大学、伯纳德大学和利卡塔大学(2013 年)。检测异常值:不要使用平均值周围的标准偏差,使用中位数周围的绝对偏差。《实验社会心理学杂志》,49 期 (4),764–766 页。
使用 Wtfutil 在您的终端中创建一个漂亮的仪表板
现在你可以在你的终端上查看你的日程表,待办事项,系统信息,Docker,Git 等等。
动机
作为一名数据科学家或程序员,终端可能是您大部分工作的随身工具。如果你能像下面这样查看你的日程表、待办事项、系统信息、docker、git 和你最喜欢的博客的更新,那不是很好吗?
作者图片
这就是 WTF 派上用场的时候。
WTF 是什么?
WTF 允许您监控系统、服务和重要信息。以下是您可以使用 WTF 查看的一些内容:
- 谷歌日历
- 码头工人
- 饭桶
- 资源使用
- 系统
- 您最喜爱的网站的更新
还有更多!在本文中,我将向您展示如何使用 WTF 将这些信息添加到终端仪表板中。
装置
公司自产自用
您可以使用 Hombrew 安装 WTF
brew install wtfutil
wtfutil
二进制的
如果这个方法对你不起作用,从 GitHub 下载最新的二进制。如果您使用的是 Linux,您可以通过键入以下命令来检查您使用的是哪个 ARM 版本
dpkg --print-architecture
由于我的 ARM 版本是 amd64,所以在Downloads
下载了wtf _ 0 . 36 . 0 _ Linux _ amd64 . tar . gz,解压文件,然后将文件wtfutil
移动到 /usr/local/bin
:
mv ~/Downloads/wtf_0.36.0_darwin_amd64/wtfutil /usr/local/bin
然后设置执行文件的权限
chmod a+x /usr/local/bin/wtfutil
现在它应该工作了!
wtfutil
作者图片
如果这两种方法都不适合你,在这里查看其他方法。
自定义仪表板
现在我们的仪表板看起来有点无聊。让我们向仪表板添加一些有用的模块。要在终端中编辑配置文件,请键入
nano ~/.config/wtf/config.yml
或类型
gedit ~/.config/wtf/config.yml
使用代码编辑器编辑文件。
谷歌日历
如果你像我一样,使用谷歌日历来提醒自己即将到来的事件或约会,如果你不用打开谷歌日历就可以在终端上浏览一周,那不是很好吗?幸运的是,WTF 允许你这样做。
要将 Google Calendar 添加到您的仪表板,首先通过在步骤 1 中点击“启用 Google Calendar API”来启用 Google Calendar API。
作者图片
下载完credials.json
后,将其移动到本地机器的一个保存位置。例如,您可以将您的credentials.json
文件移动到~/.config/wtf/
:
sudo mv ~/Downloads/credentials.json ~/.config/wtf
然后将 Google 日历的凭证文件路径添加到~/.config/wtf/config.yml
删除或禁用~/.config/wtf/config.yml
中的textfile
部分,因为其位置与gcal
重叠
保存文件,然后键入wtfutil
,您应该会看到一个提示“转到您的浏览器中的以下链接,然后键入授权码”。单击链接并将代码复制到终端。
现在,您应该可以在终端上看到 Google 日历的事件和约会,如下所示!
作者图片
提要阅读器
如果你想获得你喜欢的网站如 Medium 的每日更新,只需将feedreader
添加到~/.config/wtf/config.yml
,然后在feedreader
下添加他们的 RSS 源。
您可以按照本说明或本说明在媒体上查找个人资料、出版物和主题的 RSS 源,或使用本说明查找任何其他网站的 RSS 源。
保存上面的配置后,您的仪表板应该如下所示:
作者图片
如果您想要选择特定的部分,请在该部分的顶部键入数字。由于数字 2 紧挨着提要阅读器标题,我们将键入2
来访问提要阅读器部分。
然后使用向上或向下箭头在不同的文章之间移动。键入o
在浏览器上打开文章。现在你可以在你的终端中获得你喜欢的网站的每日更新!
作者 GIF
CmdRunner
如果您想在仪表板上显示终端命令的输出,如nvidia-smi
,将cmdrunner
添加到您的~/.config/wtf/config.yml
:
cmd
:要运行的终端命令。在这种情况下,它是nvidia-smi
args
:添加命令的参数。由于nvidia-smi
没有任何参数,数组为空。
我禁用了clocks_a
和clocks_b
部分,为我的新部分留出了空间。如果您希望保留clocks_a
和clocks_b
部分,可以通过编辑position
中的参数随意改变nvidia-mi
的位置。
保存配置文件后,您的仪表板应该类似于下图。
作者图片
饭桶
了解您最近使用 git 更改或提交了哪些文件也很有用。要显示关于本地 git 存储库的信息,请将下面的代码添加到您的~/.config/wtf/config.yml
中:
您应该会看到如下所示的内容:
作者图片
码头工人
如果您正在使用 docker,了解 Docker 容器和映像的信息可能会很有用,比如卷、内存限制、磁盘使用等。
要将 Docker 的信息添加到您的终端仪表板,请将以下代码添加到您的~/.config/wtf/config.yml
:
保存配置文件后,您的仪表板应该如下所示:
作者图片
资源使用
要在仪表盘上显示关于 CPU 和内存使用情况的信息,请将resourceusage
添加到您的~/.config/wtf/config.yml
:
您应该能够在仪表板中看到您的 CPU 和内存使用情况!
作者图片
待办事项列表
您也可以通过将todo
添加到您的~/.config/wtf/config.yml
来将待办事项列表添加到您的终端:
您应该会看到如下所示的内容:
作者图片
您的待办事项列表中还没有任务。让我们通过键入4
来添加一个任务,然后键入n
来添加一个新任务。添加任务后,点击“保存”将任务添加到列表中。
作者图片
一个新项目被添加到您的列表中!
作者图片
要检查任务,请使用向上或向下键选择任务,然后键入 Space。若要取消选中该任务,请再次键入 Space。
作者图片
就是这样!现在,您有了一个有用且漂亮的仪表板,可以在您的终端中查看。您的仪表板现在应该如下所示:
作者图片
点击查看添加到终端的其他选项。
结论
恭喜你!您刚刚学习了如何使用 WTF 创建一个漂亮的终端仪表板!能够使用一个命令查看所有重要信息可以每周节省时间。希望这篇文章能给你建立自己的终端仪表盘的动力。
本文中显示的完整的~/.config/wtf/config.yml
文件可以在这里找到。
https://github.com/khuyentran1401/Data-science/blob/master/terminal/wtf/config.yml
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上联系我。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
创建一个仪表板来跟踪任何与 Plotly 和 Dash
或者“我如何停止使用第三方应用程序来跟踪我的投资”!自己的模板真的很容易上手。
剧透警告:这不是我的实际投资组合!
早期的探索
自从我开始投资我的血汗钱,我就痴迷于拥有某种仪表板或工具,让我能够快速了解事情的进展。
我对 Excel 并不陌生,我曾经有一个交易日志,很快就变得太无聊而无法填写…还有一些工作涉及到标准化来自我当时使用的两个经纪人的交易数据,这没有帮助。
所以在浪费了一些时间尝试定制一些有趣的仪表盘和在线模板后,我得出结论: Python 是我的最佳选择!
请注意:投资组合数据仅仅是一个例子,但是我们将创建的模板可以非常容易地适应其他数据— 我将向您展示如何实现。本文中的任何内容都不应被视为财务建议!
我已经知道我想要看到什么样的指标和图表,所以这帮助我在头脑中已经有了几个目标的情况下开始这个项目。从一开始,我就设想在我的仪表板上至少有两页纸。主页面会给我一个投资组合总价值的视图,而第二个页面会让我浏览每只股票的进出情况。
我能想到十几个这样的应用程序,但通常你必须付费才能使用这些很酷的功能…
那么,为什么不构建您自己的仪表盘并根据您的需求进行定制呢?我将帮助你开始布局和基本功能,我们将看看我们如何能发展它。在跳到仪表板之前,我们需要做一些预处理,但我保证这是值得的!
可以跟着笔记本里面的 资源库 一起看。我还录制了一个教程,在那里我可能会更详细地解释一些部分。
如果你想要一个更高级的仪表盘来分析你的投资组合,我推荐你参加 高级课程 !
如果你是 Python 和 Plotly 的新手,我有自己的 免费 Plotly 速成班 让你快速上手!
准备我们有史以来最好的仪表板
对于这个项目,我决定混合使用 Plotly、Dash 和一些引导主题。有了 Python 的一些基本概念,您应该能够很快理解并构建自己的仪表板!我现在将把重点放在主页上,因为已经做了很多工作。
以下是我们今天的目标:
- 准备交易和股票价格
- 我们全球投资组合价值随时间变化的图表
- 对比我们与 S&P500 的回报
- 多个 KPI,如 7D/15D/30D/YTD 绩效
- 我们投资组合中的顶级股票
- 用 Dash 和 Plotly 创建我们仪表板的第一个版本
为了获得所有这些信息,我们需要我们的交易历史和我们交易的股票的历史价格。
https://medium.com/@fneves/membership
交易—2.0 版
我们首先从我们的代理导出交易历史(希望您也能以 CSV 格式获得它)。然后,我们需要获取该表并计算一些额外的列。大多数情况下,您会看到常见的“日期、股票、买入/卖出、价格、价值”列,我会添加其他列,如股票的累计头寸和累计成本、交易损益等。
这些计算是一个独立项目的一部分,我有一个 python 脚本来完成它。代码有点难解释,但是我已经把它作为我准备的整个项目的课程的一部分。稍后会有更多信息。
尽管如此,我还是在 存储库 中包含了一个改进的事务历史的工作示例。您可以使用它来帮助您计算自己的增强数据集。
因此,从存储库中获取代码,首先确保您拥有所有必需的包并导入它们。
收集价格
第二部分相对简单,我将向您展示如何快速获得任何股票的价格历史。你甚至可以保存价格,以后再用,或者你可以进行一次强迫症的冒险,开始用 1 分钟蜡烛建立你自己的数据库!
这部分我准备用一个在其他文章里看到很多的知名包!它叫 yfinance ,真的很好用,还有熊猫 datareader 。在用下面的日期变量定义了我们分析的开始之后,我们可以创建并运行函数 get_prices ,如下所示。
我建议从一两年前开始,然后尝试从 1920 年开始每天都点蜡烛。你交易历史中的股票越多,提取它们的时间就越长,但通常很快。
完成后,您将获得一个名为 all_data 的变量,它本质上是一个数据框架,包含每个股票及其日线图的多索引。
我们会马上把它变成一本字典,使它更容易与我们的交易历史信息合并。
“团结”和征服
这是我们把头寸规模和股价放在一起的部分。这使我们能够获得全球投资组合价值和其他重要指标。
关于 Python 字典的一个很酷的事情是,你可以创建一个循环来给它们提供几个数据帧,这非常方便,因为你可以稍后只使用 mega_dict[‘AAPL’]调用一个特定的 ticker。下面,我将遍历过滤后的报价器列表中的每一个报价器,并在没有交易的日子里填补空白。
看看那本词典中的任何一个关键词,看看有什么信息。每个列名都以 ticker 开头,所以我们以后可以使用它。
我们还需要包含“mktvalue”的每一列来计算我们投资组合的总价值**。出于这个原因,我们还需要一个漂亮的数据框架,其中包含每个股票的所有列。你猜对了——它叫 mega_df !**
有价值的专栏
为了获得代表每只股票在任何给定日期的市场价值的每一列,我们使用一个过滤器,然后对每行中的所有值求和。“portf_value”列现在是您的全球投资组合价值。
获取 S&P500 的价格也很简单,我们可以将它与之前的数据框架结合起来。我们已经可以计算一些有用的东西,比如每日百分比变化,以及价值差异。
我在下面添加了一些额外的指标,我计划稍后在我们的仪表板上使用,作为我们指标部分的一部分。
用 Plotly 绘制我们自己的图表
如果你有使用 matplotlib 的经验,Plotly 可能看起来很奇怪。对我来说是,当我开始的时候!但事实是,您可以创建交互式图表,然后将它们与 Dash 这样的框架结合起来,以生成真正强大的仪表板。
Dash 使用 Flask 做后端(在你的电脑上创建一个本地服务器,用 dashboard 本身托管一个“页面”),所以如果你已经了解 Flask,你肯定有优势。对 HTML 如何工作的一些基本理解可能也会派上用场。
但在我看来,这个项目最棒的部分是这个布局可以回收用于不同的项目。当我在做这个的时候,我实际上做了一些调整,以便能够跟踪我的加密组合。如果你感兴趣,请在评论中告诉我!
对于 Seaborn 的粉丝来说,Plotly 乍一看可能显得过于简单和局限。不要让他们网站上的 3 行示例欺骗了你…有很多你可以定制的。为了供您参考,我将留下一些我经常使用的设置,您应该有一个很好的起点来尝试这些设置。
投资组合价值
我喜欢让代码保持整洁,所以我将创建一个新的数据框架,我们可以参考这个特定的图表。我还将定义一个开始日期,以使图表更加清晰。
不要害怕评论和编辑这些参数。您可以简单地按照逻辑顺序分解更新**。**我留下了几行,在那里我改变了布局边距,或者布局高度,以及其他。
解决这个问题的一个好方法是记住每个图表都是以一个图形对象开始的。一旦你声明了那个变量,你就向它添加了元素,比如图表。您还可以添加新的行来添加更多的内容,包括对其格式的更改。完成定制后,运行“show()”方法来显示图表。
现在看起来有点“赤裸裸”,但我更喜欢以后将标题作为 HTML 元素添加进去。当我们开始冲刺时,我会告诉你怎么做。随意取消示例中标题更新的注释(第 30 行),看看它是如何显示的。使用这段代码,我们刚刚创建了第一个仪表板图表。检查如何交互式地选择图表的特定部分!
我希望代码中的注释容易理解,但是如果你迷路了,或者想尝试更高级的东西,一定要去他们的网站。他们有大量的例子供你探索!
对比我们与 S&P500 的增长
对于我们的第二个图表,我们将比较我们的月收益和 S & P500 收益。我打算在这里使用日线时间框架,但是如果你有超过几个月的交易,柱线会变得很小。因此,我不得不为这个图表设计一个新的列,并进行一些操作来为我们的下一个 Plotly 图表获得正确的格式。
一旦我们得到了新的数据框架,就很容易创建一个条形图。如果你花一些时间浏览代码,请注意我们正在做和以前一样的事情。首先,我们声明一个 Figure 对象变量。
然后我们给它添加两条迹线,这将是我们图表中的系列。然后,我们用一些额外的线条使图表看起来更好。不要忘记使用“barmode”作为组(第 27 行)。
在 X 轴上使用“时间周期”变量
KPI 卡
这部分将给你的仪表板一个非常漂亮的触感。我希望能够看到我的投资组合相对于标准普尔的表现。我将在下一个数字中添加四个元素。这些被称为指示器,如果你喜欢仪表和速度计,文档中也有一些。
请注意,底部的数字是“百分点”
这四个要素将包含我们投资组合在 7、15、30 和 200 天内的表现。
另外,我将为每个元素添加一个 delta 参数,参考标准普尔指数相同的时间框架表现。
如果您使用“数字+增量”模式,我们的指示器将显示我们的性能,并与我们的参考进行比较。
出于本文的目的,我将添加与 S&P 性能相同的四个元素,但是这里没有增量。这两列稍后将并排显示在我们的仪表板上!
我们投资组合中的顶级股票
这篇文章已经有点长了,但是我觉得我还需要给你看一样东西!根据你持有的股票数量,你可能想看看你持有的最多的股票是什么。这是我们主页的另一个很酷的功能,但是我们必须获得当前价格才能计算我们的当前头寸。
出于多样性的考虑,我将分享一种不同的获取股票信息的方法——这次是“常规市场价格”。这是一个简单的循环,使用了 yfinance 包,但这不是最有效的方法,因为它在返回我们需要的信息之前,为每个股票获取了大量信息。
尽管如此,请随意使用它进行试验,并获取更多的信息,如部门和行业信息,我将在下一篇文章中介绍。
如果你想让这个仪表板更上一层楼,我准备的课程可能会让你感兴趣。在此查看更多详情!
快速提示:如果你和我一样,只是不能忍受饼图,我决定给这个一个转折,把它变成一个甜甜圈。你可以用参数“孔”来达到这个效果。不客气!
用破折号组合所有元素
快到了!
现在,我们已经拥有了仪表板第一部分所需的所有图表,并准备将它们放入 Dash 应用程序中。
如果你是 Dash 的新手,就把它想象成一个在你的电脑上运行的服务器,它在那个服务器上托管一个网页,上面有你发送到那里的信息。您可以通过您最喜欢的浏览器访问它,运行方法""时它会提供链接。run_server() ”。
使该页面看起来像仪表板的最简单的方法是使用 Bootstrap 模板(带有许多样式选项的预建模板),并将 Plotly 图表添加到 Dash 应用程序中。您将能够像编写网页一样编写代码,向其中添加组件,采用块结构—就像 HTML 一样。
我在 视频 中回顾了一些技术方面的内容**,但你需要记住的主要事情是,我们仪表盘上的所有组件都在一个容器内。**
这个容器可以有行和列。每行和每列都可以包含多个组件(HTML、Dash 核心组件(dcc)、Dash 引导组件(dbc))。最后,一个组件可以是一个简单的文本段落,或者一个标题,一个图表(像 plotly 图表),一个下拉菜单,以及许多其他东西。
这将是我们的网格。绿色的三个主要行,以及第 2 行和第 3 行的一些列
Dash 甚至允许您使用回调函数,这将使仪表板对用户输入做出响应,如选择日期、切换、下拉菜单中的项目以及许多其他事情。这些特性将在下一篇文章中添加,因此用户可以更改日期,例如选择特定的股票进行分析。
再看一下我们正在创建的网格,然后看看下面的代码。你应该很容易找到这三行(第 5 行、第 7 行和第 31 行)。
这是告诉您行在列之前的最佳时机。如果你反过来做,你会得到一些错误!
如果这是你的第一个 Dash 教程,我知道这可能是一个令人生畏的代码片段!如果你不能理解每一句话,试着去读每一行甚至。如果你能把它和我放在上面的仪表盘或布局图并排比较,会有所帮助。
如果你喜欢黑暗模式,你可以很快改变主题。在第 1 行,我使用 Bootstrap 的内置 FLATLY 主题。这个网站有一个很酷的方式来查看所有可用的主题。你只需要把名字改成你想尝试的(比如 MINTY,SLATE 等。)—但为此您需要dash _ bootstrap _ components。
下一步是什么?
我们现在有了自己的仪表板,可以快速查看我们的全球投资组合。在下一篇文章中,我们将使这个页面与交互,并且添加一个侧边栏以便能够移动到我们的第二个页面。我提到我还想查看每只股票并获得一些关于其表现的指标,所以我们会处理好的。最后,我希望获得有关行业和部门的信息,以便能够分别绘制图表。
如果你想更多地了解 Dash,并学习如何基于这个项目建立一个仪表板, 留下你的电子邮件 ,我会让你知道我的新课程何时准备好。我正在录制视频和创建代码的痛苦过程中,但这将是一个有很多例子和我自己的预处理功能(如交易数据集的额外列)的完整项目。
我确信在发布之前我需要一些反馈,所以有机会我会请你们中的一些人来回顾一下**!**
如果一切按计划进行,我会添加如下功能:
- 为交互性添加日期选择器
- 该仪表板的新页面,我们可以在其中选择一只股票
- 关键指标,如 PnL、累计损益、真实值。/不真实。等等
- 烛台价格图表显示交易和我们的平均成本线
- 烛台模式识别和回溯测试——这太棒了!
我希望你喜欢这个教程,甚至可能在你自己的项目中使用这个模板。
如果你对这里的任何部分感到困惑,不要忘记观看视频教程!
感谢您的阅读!一如既往,我欢迎反馈和建设性的批评。如果你想取得联系,可以在这里联系我https://www.linkedin.com/in/fabioneves/*推文或者回复下面的文章。*
创建快速自动记录、可维护且易于使用的 Python API——CRUD 路由和路由管理
学习如何捕捉请求并获取它们所携带的信息
我们的 API 监听传入的请求(图片由唐纳德·詹纳蒂在 Unsplash 上提供)
在 上一篇文章 中,我们已经用 5 行代码建立了一个 API。我们已经安装了依赖项,并创建了一个工作 API,只有一个简单的路径。在本文中,我们将进一步构建,用多种不同的途径充实 API,向您展示使用 FastAPI 可以做的所有事情。然后,我们将关注如何以简洁明了的方式组织所有这些路线
安装
为了让这篇文章尽可能容易理解,我们将假设我们正在为我们的博客网站编写一个 API。目标是创建一些我们可以 CRUD(创建、读取、更新、删除)的公共路径:
- 添加新文章
- 从数据库中检索文章
- 更新文章以修复打字错误,例如
- 删除一篇文章
我们将专注于捕捉请求和提取信息。我们的 API 如何与我们的数据库通信是另一个主题,在本文的https://mikehuls.medium.com/dramatically-improve-your-database-inserts-with-a-simple-upgrade-6dfa672f1424中有很好的描述。也可以查看本文 中的 来创建一个版本控制的数据库结构。
由于我们的 API 将负责捕捉请求并获取它们携带的信息,所以让我们首先快速检查一下请求是如何工作的,以便我们可以准确地为我们的 API 创建端点来捕捉所有信息。
要求近距离拍摄(图片由 Jassine Khalfalli 在 Unsplash 上拍摄)
请求
让我们稍微简化一下,假设一个请求由一个URL
、一个HTTP method
和一个可选的body
组成。在我们的 API 中实现它们之前,我们将快速浏览每一个。
剖析 URL
我假设你对网址很熟悉,因为你在使用互联网时必须把它们输入浏览器。为了我们的 API,让我们把下面的 URL 分成与我们相关的 3 个部分。
- https://www.github.com
这部分指定网站托管的服务器的位置。 - /mike-huls
路径路径**。这指定了我们想要在网站上访问的资源(文件)的确切位置。把它想象成你计算机上的一个文件系统;就像c:/users/mike/mystuff
一样。** - ?tab=overview&lang=en
问号是查询字符串分隔符。它将到特定资源的路由与将被传递给资源的查询参数分开。参数成对传递,用“&”分隔。
总之:我们向[https://www.github.com](https://www.github.com/mike-huls?tab=overview)
发送一个请求,在/mike-huls
的服务器上搜索我们的资源,然后给资源传递一些查询参数,即tab=overview
和lang=en
。我们将在以后创建路线时使用这些术语。
HTTP 方法
方法(也称为“动词”)用于在发送请求时区分不同的(HTTP)操作。虽然还有很多,但对于本文,我们将使用主要的 4:
- 获取—用于检索数据
- 发布-用于提交数据
- 上传—用于更新数据
- 删除—用于删除数据
我愿意把这些方法看作是区分你的目标的额外数据。
请求正文
主体是我们想要发送的实际数据。在我们的例子中,我们可以发布一篇新文章,这样我们的 API 就可以将它插入到数据库中。
在我们的 API 中路由不同类型的请求(图片由 Javier Allegue Barros 在 Unsplash 上提供)
创建我们的 API
记住,请求由一个 URL 和一个方法组成。为了捕捉这些,我们需要为不同类型的请求创建特定的路由。在路线中,我们需要指定(至少)两件事:
- 路径(捕捉 URL 的路径
- 一个方法(捕捉请求的 HTTP 方法)
让我们来看看创建、读取、更新和删除文章(CRUD)所需的所有操作。我们将从最简单的开始:检索文章。
简单阅读:检索所有文章的路径
最简单的途径是检索所有文章。看起来是这样的:
@app.get("/all_articles")
def get_all_articles():
return function_that_retrieves_all_articles()
两件事很重要。首先注意我们使用了 GET 方法(用@app.get
表示)。第二个是我们指定路径的地方:GET 方法中的articles
部分。这定义了到此路由的路径。对这个路由的 get 请求可能类似于:[www.ourbloggingwebsite.com/all_articles](http://mikehuls.medium.com/)
,它将从数据库中检索我们所有的文章。
使用查询参数读取:检索一篇文章的路线
检索所有文章对于获得我们所有文章的概览来说是非常好的,但是如果用户只想阅读一篇文章呢?让我们创建另一个只检索一篇文章的路径:
@app.get("/article")
def get_one_article(articleId:int):
return function_that_retrieves_article(articleId=articleId)
请注意,这条路线看起来与前一条非常相似。它仍然使用 get 方法,但是路径略有不同:函数现在需要一个参数;我们必须提供一个文章 Id。这称为查询参数。对该路由的 GET 请求如下所示:[www.ourbloggingwebsite.com/article?articleId=1](https://mike-huls.github.io/)
。这将只返回一篇文章,即 articleId =1 的文章。
我们可以在这条路线上增加一点这样的东西
@app.get("/article")
@app.get("/article/{articleId}")
def get_one_article(articleId:int):
return dbConnection.get_one_article(articleId=articleId)
请注意,我们在这里添加了第二行;它允许用户使用查询参数如/article?articleId=1
和路径如/article/1
检索文章。我们可以使用两条线或只用一条线。
删除:删除文章的途径
delete 语句的工作方式与带有查询参数的 GET 完全相同,它使用查询参数进行筛选。
@app.delete("/article")
def delete_one_article(articleId:int):
return dbConnection.delete_one_article(articleId=articleId)
如您所见,它与前面的方法非常相似,唯一的例外是我们在第一行中使用了 DELETE 方法。
创建:发布新文章的途径
让我们来看看现有的东西。插入新文章。路线看起来像这样:
@app.post("/article")
def post_article(body:dict):
return dbConnection.post_article(articleJson=body)
再次注意,我们使用的是发送到/article 路径的帖子。FastAPI 从请求中获取主体数据,并将其传递给负责将其插入数据库的函数。
更新:更新现有文章的途径
更新将来自 GET 的查询参数和来自 POST 请求的主体的查询参数组合在一起:
@app.put("/article")
@app.put("/article/{articleId}")
def update_article(articleId:int, body:dict):
return dbConnection.update_article(articleId=articleId, articleJson=body)
注意,它接收一个 articleId 和一个 body。我们可以用这些来替换数据库中的记录;我们使用 articleId 查找它,然后用 articleJson 中的数据替换它。轻松点。
组织路线
我们刚刚创建的所有路线都是为了一件事:修改文章。如果我们也有故事呢?有了所有这些途径,你可以想象你的项目会很快变得混乱。谢天谢地,组织这些路线很容易。
我们的路线整洁有序(图片由 Martin Lostak 在 Unsplash 上拍摄)
我们将创建一个名为article_routes.py
的文件,并添加以下代码:
from fastapi import APIRouter
router_articles = APIRouter()
添加完这段代码后,我们可以使用路由器来捕捉请求。我们只需将前一章中编写的所有代码片段粘贴到article_routes.py
中。
@router_articles.get("/article")
def get_one_article(articleId:int):
return function_that_retrieves_article(articleId=articleId)
那些对细节有敏锐眼光的人注意到了一件事:在前一部分,我们用@app.get(....)
修饰了函数。在上面的例子中,我们必须使用@router_articles
,因为这是我们的新路由器。点击 查看此文件 的最终版本。
最后一步是转到我们的main.py
文件,告诉它将某些请求重定向到我们的新文件。我们将所有与文章有关的请求重定向到我们的文章路由器,方法是导入它并告诉 FastAPI 重定向某些请求。我们的 main.py 文件现在简洁明了:
from fastapi import FastAPI
from routes.article_routes import router_articles
app = FastAPI()
app.include_router(router=router_articles, prefix='/articles')
当我们开始处理故事时,我们可以轻松地包括一个新的路由器,并在其中编写我们所需的所有代码!轻松又有条理。
结论/TL;速度三角形定位法(dead reckoning)
在这里 查看最终 api 的回购。
本文主要关注什么是请求,以及我们如何在路由中从这些请求中获取不同类型的信息。有了这些知识,你就可以创建一个非常好的 API 了。在下一篇文章中,我们将关注于为我们的路线定义模型**。有了这些,我们就可以在将数据传递给数据库之前对其进行清理和检查。此外,我们将重点关注安全性**;例如,只有经过认证的访问,或者您必须提供密码。订阅敬请关注!****
如果你有建议/澄清,请评论,以便我可以改进这篇文章。同时,查看我的其他关于各种编程相关主题的文章。
编码快乐!
—迈克
页(page 的缩写)学生:比如我正在做的事情?跟我来!
用 FastAPI(第 1 部分)用 5 行代码创建一个快速自动记录、可维护且易于使用的 Python API
非常适合只需要一个完整、有效、快速和安全的 API 的(没有经验的)开发人员
构建和使用我们的 API 就像使用这台自动售货机一样简单(图片由詹娜·哈姆拉在像素上拍摄)
你有一个很棒的 python 程序,你想把它公之于众。使用 FastAPI,您可以快速创建一个超快速的 API,让其他用户可以使用您的 Python 代码。
在这篇文章中,我们将用 5 行代码创建一个 API。什么?五行?!没错;FastAPI 不叫 FastAPI,因为它比 Django 或 Flask 之类的框架快很多倍;设置起来也超级简单快捷。
在我们创建了我们的初始 API 之后,我们将在下一部分扩展它,展示创建一个全功能、超快、生产就绪的 API 所需的所有必要知识。我们来编码吧!
FastAPI 简介
让我们先快速浏览一下我们的框架。FastAPI 是一个现代的、开源的、快速的、高性能的 Python web 框架,用于构建 Web APIs。在 uvicon 下运行的应用程序被列为最快的 Python 框架之一,仅次于 Starlette 和 uvicon 本身(由 FastAPI 内部使用)。听起来不错吧?让我们不再浪费时间,看看如何使用它。
装置
安装非常简单。我们将首先用 PIP 安装 FastAPI。然后我们还需要安装 Uvicorn。这是运行 FastAPI 的 web 服务器。
pip install fastapi uvicorn
建议在虚拟环境中安装 Python 依赖项。这样你就可以让你的项目不再混乱。查看本文 了解如何使用虚拟环境的简单说明。
创建我们的 API
所有必要的工具都已安装,让我们在根处创建一个 API,在 的五个 行中。我们将创建一个名为main.py
的文件:这个文件将是我们应用程序的主要入口点,并将定义我们的 API。插入下面的代码:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def simple_route():
return {"Hello": "There"}
看到这有多简单了吗?我们正在导入fastapi
,创建一个新的实例,我们将把它存储在app
变量中。这是我们已经定义的 API!在最后三行中,我们定义了一条路线。API 已创建!
我们的 API 已经设置好,可以运行了。3, 2, 1…开始!(图片由 Andrea Piacquadio 在像素上拍摄)
启动我们的 API
是时候启动我们的 API 了。打开终端,导航到上一步中的main.py
文件所在的文件夹(如果您没有使用终端的经验,请查看本文https://mikehuls.medium.com/terminals-consoles-command-line-for-absolute-beginners-de7853c7f5e8)。执行以下命令:
uvicorn main:app --reload
这将调用 Uvicorn 并告诉它运行位于main.py
文件中的app
(上一步中定义的变量)。如果我们为了加速开发而保存更改,那么--reload
标志会重新加载;我们不必为了看到变化而手动停止和启动 API。
如果您使用虚拟环境,请确保首先激活它。另一种称呼乌维科恩的方式是python -m uvicorn main:app --reload
。这完全一样,只是你可以指定一个特定的 python.exe,例如:
c:/mike/myProj/venv/scripts/python.exe -m uvicorn main:app --reload
测试我们的路线
如果一切正常,您将看到“应用程序启动完成”。如果你没有另外指定,那么 uvicorn 运行在你的本地主机上,端口 8000。于是打开浏览器,对着localhost:8000
。您应该看到以下内容:
API 上/ route 的返回值(图片由作者提供)
自动文档
关于使用 FastAPI,我最喜欢的一个特性是,它会自动生成如何使用该 API 的说明和概述;有哪些路线,如何调用的例子,你甚至可以测试路线,看看返回值!在localhost:8000/docs
或localhost:8000/redoc
检查一下。这些是相同文档的不同样式。
那是一场又短又快的比赛!(图片由在像素上运行 4 个 FFWP
结论
在大约 5 分钟的时间里,我们已经完成了一个简单的 API,在根上只有一条路由。但是还没有太多的互动性。我们想连接我们的 API,这样它应该能够接收和发送一些消息!
在 的下一部分 中,我们将了解如何接收查询参数和主体。此外,我们将在 API 中创建更多的路由,并以智能的方式组织这些路由。稍后,我们将关注使用 Docker 的数据验证、安全性和部署。
如果你有建议/澄清,请评论,以便我可以改进这篇文章。同时,看看我的关于各种编程相关话题的其他文章。
编码快乐!
—迈克
页(page 的缩写)学生:比如我正在做的事情?跟我来!
用 Python 中的 Flask 创建一个成熟、专业的 API 第 1 部分
专业且安全地允许访问您的 Python 程序-通过 6 个简单的步骤设置基础
我们的 API 正在愉快地连接我们的服务(图片由 Steven Johnson 在 Pexels 上提供)
没有 API 的应用程序就像没有服务员的餐馆。在餐馆里,你不需要和厨房沟通,也不需要等着点菜来享用美食。同样的,一个网站不需要知道如何与你的数据库通信。像一个服务员一样,我们的 API 从我们的网站收到一个命令:“我想要一些带有元数据的用户统计数据”。API 随后检查订单(是否允许您拥有该数据?),说服我们的数据库(厨师)为他烹制一些美味的信息,等待数据库完成,最后将数据返回到网站。
为什么需要 API 呢?
API 允许两个(或更多)服务以一种分离的方式相互通信。最常见的例子是处理网站和数据库之间通信的 API。它提供访问、便利、安全和额外的功能。让我们来看一下每个要点的简短示例。
1.接近
假设您创建了一个名为 pixelcounter.py 的 Python 程序,它读取一个图像文件并计算像素数。当你把你的图像文件放在 USB 上的时候,走到装有 pixelcounter.py 的电脑前,把图像放在电脑上,然后把它加载到 pixelcounter.py 中,最后开始计数。
这行得通,唯一的问题是:我们是程序员。我们没有时间把东西放到 u 盘上,更不用说走到咖啡机以外的地方了!一个好的解决方案是将 API 和 pixelcounter.py 放在服务器上。这样,人们可以发送图像进行统计…轻松点。
2.便利
API 也提供了很多便利。为了发送电子邮件,只需将收件人、主题和消息发送到 API。如果您可以将数据发送给 API,那么您不需要理解和 SMTP 是如何工作的。
3.额外功能
使用 API 还可以提供额外的功能。例如,您可以计算哪个用户请求了哪些数据。这样你可以限制使用,检查人们最感兴趣的功能,哪些功能根本不会被使用,或者按请求向用户收费。
4.安全性
API 允许两个程序以安全的方式相互通信。像脸书这样的网站要检索你的朋友,需要从数据库中获取数据。你不希望另一个人得到你的个人资料。这就是 API 的用武之地;它检查是谁发出的请求,以及这个人是否被允许获取数据。
如何创建一个 API?
在这篇文章中,我们将开始创建一个 API,它将允许我们做上面描述的所有事情。在这一部分中,我们将着重于设置我们的项目,获得一些基本的功能和测试我们的路线。如果您看到任何您不熟悉的术语,请查看本页底部的词汇表。
按照这些步骤创建一个包含所有必需依赖项的项目,然后我们将创建一个控制器来处理路由上的请求。
第一步。创建您的 python 项目
创建您的根文件夹:将包含项目的文件夹。在这个例子中,我们将使用c:/my_root_folder
步骤 1.1(可选)创建虚拟环境
创建虚拟环境可以帮助您将已安装的软件包保持在一个整洁的包中。本文 中 关于理解和创建 venvs 的更多信息。以下是本项目的操作方法:
导航到您的根文件夹并执行这段代码。
python -m venv c:/my_root_folder/venv
这将创建一个文件夹来存放你所有已安装的软件包。不要忘记:
- 通过导航到
c:/my_root_folder/venv/scripts
并执行activate
,在安装包之前激活您的环境。现在您处于您的环境中,可以在这里安装软件包了 - 通过调用
c:/my_root_folder/venv/Scripts/python.exe
来执行你的脚本。我们稍后会更深入地讨论它
第二步。安装依赖项
我们需要两个包,所以我们需要安装 Flask 和 flask-restful。pip install Flask flask-restful
第三步。构建您的项目
下一步:创建一些文件夹,我们可以把我们的 te API 的不同部分,即我们的配置,路线和控制器:
mkdir config routes controllers
第四步。创建 API
我们的项目已经建立,是时候构建我们的 API 了!在我们的根文件夹中创建一个名为 main.py 的文件,并赋予它以下内容
from flask import Flask
from flask_restful import Apiapp = Flask(__name__)
api = Api(app)if __name__ == "__main__":
# start up api
app.run(port=5000, debug=True)
这里发生了什么事?:
这个脚本导入所有需要的包,并实例化一个 app 和 api。然后,它在本地主机端口 5000 上运行应用程序。执行您的脚本:
`c:/my_root_folder/venv/Scripts/python.exe c:/my_root_folder/main.py``
您会注意到您的脚本正在运行,但没有停止。我们创建的服务器持续监听请求。让我们给它点东西听。
第五步。创建路线和控制器
我们希望转到 localhost:5000/test,并让 API 在我们导航到该页面或向该位置发布内容时执行一些操作。为了做到这一点,我们需要我们的 API 来监听一个路由,即 /test 。
from flask import Flask
from flask_restful import Api
from controllers.testController import TestControllerapp = Flask(__name__)
api = Api(app)
api.add_resource(TestController, '/test')if __name__ == "__main__":
# start up api
app.run(port=5000, debug=True)
上面的代码与第一段代码几乎相同。如你所见,听路线很容易。这发生在第 7 行:api.add_resource(TestController, ‘/test’)
它在 /test 监听请求,并将请求传递给我们的 TestController,这是我们在第 3 行导入的一个类。让我们创建这个控制器。用这个内容创建c:/my_root_folder/controllers/testController.py
:
from flask_restful import Resource, requestclass TestController(Resource):
def get(self):
return {
"message": "get: hello from the testcontroller"
}
从 API 请求数据有多种方式。您可以发送 GET 请求或 POST 请求。GET 用于检索数据,比如检索我的个人资料图片。POST 请求用于提交数据,如提交评论。还有更多的类型,我们将在下一部分讨论。首先让我们测试一个简单的 API。
上面的 TestController 实现了一个 get 方法,该方法处理传递给控制器的 get 请求。现在我们只返回一条简单的消息。
第六步。测试
打开浏览器并导航到 localhost:5000/test。如果一切顺利,您将看到我们在控制器中定义的消息。
假设这个服务员是我们的 API,为我们提供一些数据(图片由pix abayonPexels提供)
结论
祝贺你创建了你的第一个 API!我们的新 API 已经启动并运行,但是它很笨。在下一部分中,我们将实现更多的功能,比如不同类型的请求、使用 JSON web 令牌的安全性以及到数据库的连接。关注我敬请关注!
—迈克
词汇表
一些术语,解释
- API =应用编程接口。允许您连接两个程序
- 发送给 API 的命令。你在请求它做些什么
- **响应=**API 返回的东西;数据、错误或状态
- 某网站上的一条路径。是【www.medium.com】/@ Mike huls****或test.com**/this/is/a/path**中的加粗部分
- 状态代码= 代表 api 状态的代码。大家都听说过 404:没找到!
使用 Python 在 Neo4j 中创建图形数据库
实践教程
从数据清理到图形填充
马丁·格兰让,CC BY-SA 4.0 ,通过维基共享
数据科学家第一次使用 Neo4j 研究图形时,最常问我的一个问题是如何将数据放入数据库。在之前的一篇文章中,我展示了如何使用通过 Docker 设置的 Neo4j 浏览器 UI 以几种不同的方式之一来实现这一点。在这篇文章中,我将展示如何使用 Python 生成的数据来填充数据库。我还将通过 Neo4j 沙箱向您展示如何使用不同的 Neo4j 数据库设置。
有这篇文章代码的 Google Colab 笔记本可以在这里找到。(笔记本上有如何将 Colab 连接到 Kaggle 以便更快下载数据的说明。)
必要的工具
- Neo4j Python 驱动(撰写本文时版本为 4.2)
- Jupyter 笔记本/实验室或 Google Colab 笔记本(可选)
- 熊猫
用 Python 清理数据
现在我们实际上可以开始用 Python 做一些数据管理了。为了这篇文章,我们将使用 Kaggle 上的 arXiv 数据集,它包含了超过 170 万篇学术 STEM 论文。(写这篇帖子的时候,是在 18 版。)您应该继续将数据下载到您本地机器上。
现在转到您的笔记本,我们可以开始考虑我们的数据。我已经通过以下方式加载了数据:
(你不必使用tqdm
,但我发现知道文件大小超过 1.79M 条目对检查我的进度很有帮助。)
您可以通过df.dtypes
看到我们的数据结构如下:
id object
submitter object
authors object
title object
comments object
journal-ref object
doi object
report-no object
categories object
license object
abstract object
versions object
update_date object
authors_parsed object
假设我们想用这个数据框架构建一个图表,我们想知道哪些作者发表了哪些论文,这些论文属于什么类别。然后,我们希望有三种不同的节点类型与之对应:作者、论文和类别。每个节点类型都有一两个属性。对于作者来说,我们知道他们的名字是有意义的。报纸可以有他们的 ID 和他们的标题。最后,类别拥有自己的名称也是有意义的。我们也有一些关系:作者作者论文和论文在某些类别中。
因此,我们的目标是拥有以下数据模型(用 arrows.app 绘制):
数据模型。(图片由作者提供。)
有几个专栏会对我们有用。例如,我计划保留id
,这样我们就可以用它作为每篇论文的唯一索引。之后,我想得到每个作者的个性化列表。此外,authors_parsed
列给了我们一个更清晰的所有作者的列表。我们肯定会将title
专栏作为报纸的主要属性。最后,我想保留categories
列。
下一步是稍微清理一下我们的数据,这样数据帧的每一行都有一个作者,每一行都有一个类别。例如,我们看到authors_parsed
列给出了一个列表,其中每个条目的名称后面都有一个多余的逗号。如果我们简单地将它导入到数据库中,我们将得到这样的作者节点(如一个小示例所示):
╒════════════════════════════════════╕
│"n" │
╞════════════════════════════════════╡
│{"name":["Balázs","C.",""]} │
├────────────────────────────────────┤
│{"name":["Berger","E. L.",""]} │
├────────────────────────────────────┤
│{"name":["Nadolsky","P. M.",""]} │
├────────────────────────────────────┤
│{"name":["Yuan","C. -P.",""]} │
├────────────────────────────────────┤
│{"name":["Streinu","Ileana",""]} │
└────────────────────────────────────┘
由于这不是一件令人愉快的事情(并且将导致不是最优雅的查询),我们需要稍微清理一下。我们还看到categories
列可以有一个类别,也可以有几个不是传统列表格式的类别(如本示例的最后一行所示):
╒═══════════════════════════════════╕
│"c" │
╞═══════════════════════════════════╡
│{"category":"hep-ph"} │
├───────────────────────────────────┤
│{"category":"math.CO cs.CG"} │
├───────────────────────────────────┤
│{"category":"physics.gen-ph"} │
├───────────────────────────────────┤
│{"category":"math.CO"} │
├───────────────────────────────────┤
│{"category":"math.CA math.FA"} │
└───────────────────────────────────┘
我们可以在 Cypher 中这样做,但是为了这篇文章的缘故,我们将在 Python 中进行清理,以便希望说明我们可以使用 Python 做我们想做的或多或少的事情。
让我们创建几个助手函数来清理这两列:
我们得到的数据帧现在看起来像这样:
已清理的数据帧。(图片由作者提供。)
现在我们有可以利用的东西了!
创建 Neo4j 沙盒
Neo4j 沙盒是一个很好的、免费的修补 Neo4j 的方式。您可以启动一个将持续 3 天的实例并开始工作!
出于本文的目的,当您进入沙箱时,您将创建一个基本的空白沙箱,如下所示:
创建空白沙盒。(图片由作者提供。)
正如您在创建窗口中看到的,还有许多其他有用的沙箱,但我们将选择此选项,因为我们将使用自己的数据填充数据库。坐几分钟,让它自己创造。一旦发生这种情况,您将获得您的连接信息,如下所示:
我们的沙箱的 Web 连接信息。(图片由作者提供。)
这个窗口有一些你需要的东西。首先,您将注意到 Bolt URL,以及它的端口号。您将需要它来通过 Python 建立连接。接下来,你还需要密码(这里是“困难-俯卧撑-缺口”)。这将需要在此实例中进行身份验证。我要指出的是,当这个实例被关闭 3 天后,这些信息就不再有效了,所以不要担心试图抓取我的沙盒和它的数据!
连接到 Neo4j 并填充数据库
现在我们需要在本地机器(或者任何有 Python 代码的地方)和沙盒数据库之间建立连接。这就是那些 BOLT URL 和密码的用武之地。
为此,我创建了一个助手类,它从这篇中篇文章稍微修改了一下:
酷毙了。现在我们可以开始填充数据库了。我们首先在数据库中创建一些约束,以确保节点不是重复的,同时还设置一些索引:
现在,我们创建三个函数来为 category 和 author 节点创建数据帧,我们将使用这三个函数分别将它们填充到数据库中:
这些函数将每一列放入变量$rows
中,这些列是列表格式的。UNWIND
命令获取列表中的每个实体,并将其添加到数据库中。在此之后,我们使用一个辅助函数以批处理模式更新数据库,这在您处理超过 50k 的上传时会很有帮助。
加载这些节点后,我们将添加纸张节点以及与以下函数的所有关系:
因此,以类似于类别和作者节点的方式,我们创建每篇论文,然后通过数据帧的每一行的:AUTHORED
或:IN_CATEGORY
关系将其连接起来(根据需要使用UNWIND
列表)。请注意,在这个函数中有更多的数据通过管道传输,因此减小批处理大小可能有助于防止超时错误。
此外,对于这一步,我们可能会尝试在完整的数据帧上使用类似explode.()
的方法,为每个列表的每个元素获取一行,并以这种方式将整个数据帧处理到数据库中。这是可行的,这正是我们将在下面对少量数据做的事情,如在categories
和authors
数据帧中的已删除重复的类别和作者节点列表。然而,对于较大的数据集,将数据加载到 Neo4j 中并不是一种非常有效的方式。因为 Neo4j 是一个事务数据库,我们将创建一个事务数据库,并在数据帧的每一行执行一条语句,这将导致加载过程非常缓慢。它也可能超出可用内存。沙盒实例大约有 500 MB 的堆内存和 500 MB 的页面缓存。因此,这进一步推动了以批处理方式更新数据库。
执行所有这些函数来填充图形,我们得到:
太好了!我们现在有了一个填充的数据库!该图的子样本应该是这样的(通过MATCH (a:Author)-[:AUTHORED]->(p:Paper)-[:IN_CATEGORY]->(c:Category) RETURN a, p, c LIMIT 300
获得):
图表的子示例,在带有 Neo4j Bloom 的沙盒中可视化。蓝色节点是作者,绿色节点是论文,粉色节点是类别。(图片由作者提供。)
让我们确保它里面有我们想要的东西…
查询数据库以获得一些答案
这里有一个提示:当您有一个填充的数据库时,您应该让 Neo4j 处理尽可能多的计算,然后再将答案返回到 Python 中(如果您需要的话)。在这种情况下,假设我们要计算每个类别的入度,并返回前 20 个类别的类别。显然,我们可以用 Python 来做这件简单的事情,但是让我们用 Neo4j 来做吧。在某些时候,您可能想要进行更复杂的计算(比如节点中心性、路径查找或社区检测),这些都可以而且应该在 Neo4j 中完成,然后再将这些结果下载回 Python。
要在 Cypher 中做到这一点,我们可以使用多种方法,但这里有一种快速有效的方法:
这应该会给我们:
按入度排名的前 20 个类别。(图片由作者提供。)
上述数据子集的入度分布如下所示:
图的子样本的入度分布。(图片由作者提供。)
这显示了数据库已经被填充,以及我们如何能够得到结果。值得一提的是,以列表形式返回相同结果的另一种方法是:
摘要
我们已经展示了如何从 Python 连接到 Neo4j 沙箱,并在我们确信数据包含我们想要的内容时上传数据。像编码中的其他事情一样,有许多不同的方法可以做到这一点,我们鼓励感兴趣的用户探索主要用 Cypher 而不是 Python 来做上面的演示。但是通过使用 Neo4j Python 连接器,可以很容易地在 Python 和 Neo4j 数据库之间来回切换,就像对任何其他主要数据库一样。这将开启数据科学和机器学习中各种令人兴奋的可能性,如自动节点分类、链接预测和节点聚类。请继续关注未来关于这些主题的博客帖子!