提交 6c7661c2 编写于 作者: W wizardforcel

2021-03-10 17:14:49

上级 24dfddfc
......@@ -120,7 +120,7 @@
![](img/6257dac5-b9be-45d2-a9dc-58ad1ac9d705.png)
现在,由于我们要在桌面上本地运行脚本,所以这没什么大不了的,我们不需要真正安装 Hadoop。 这只是绕过了另一个在 Windows 上运行 Spark 的怪癖。 因此,现在我们有了它,让我们在`Downloads`文件夹中找到它,`Ctrl + C`复制它,然后转到`C`驱动器并创建一个位置 为了生存
现在,由于我们要在桌面上本地运行脚本,所以这没什么大不了的,我们不需要真正安装 Hadoop。 这只是绕过了另一个在 Windows 上运行 Spark 的怪癖。 因此,现在我们有了它,让我们在`Downloads`文件夹中找到它,`Ctrl + C`复制它,然后转到`C`驱动器并创建一个位置来放置
![](img/dccddda5-a8d8-47c0-b4ec-d9c636fe4513.png)
......@@ -267,7 +267,7 @@ Spark 是一项非常热门的技术,并且相对来说还很年轻,因此
让我们更深入地了解 Spark 的工作方式。 我们将讨论称为 RDD 的弹性分布式数据集。 这是您在 Spark 中编程时使用的核心,我们将提供一些代码片段来尝试使其成为现实。 我们将在这里为您提供 Apache Spark 速成班。 除了我们在接下来的几节中将要介绍的内容之外,它还涉及很多其他内容,但是我只是向您提供一些基本知识,您需要它们才能真正理解这些示例中发生的事情,并希望可以开始并指向正确的方向。
如上所述,Spark 的最基本部分称为弹性分布式数据集(RDD),它将成为您用来实际加载和转换并从正在尝试的数据中获取所需答案的对象 处理。 了解这是非常重要的事情。 RDD 中的最后一个字母代表数据集,而到了最后,一切都结束了。 它只是一堆信息行,可以包含几乎所有内容。 但是关键是 R 和第一个 D。
如上所述,Spark 的最基本部分称为弹性分布式数据集(RDD),这将是您用来实际加载和转换并从尝试处理的数据中获取所需答案的对象。 了解这是非常重要的事情。 RDD 中的最后一个字母代表数据集,而到了最后,一切都结束了。 它只是一堆信息行,可以包含几乎所有内容。 但是关键是 R 和第一个 D。
* **弹性**:这是有弹性的,因为 Spark 可以确保如果您正在集群上运行此服务器,并且其中一个集群发生故障,它可以自动从中恢复并重试。 现在,请注意,这种恢复力到目前为止还没有达到。 如果您没有足够的资源来尝试运行该作业,则该作业仍然会失败,因此您必须向其添加更多资源。 它可以从中恢复很多东西。 重试给定任务的次数有限制。 但是,它确实尽最大努力来确保面对不稳定的群集或不稳定的网络,它仍将继续尽最大的努力来完成任务。
* **分布式**:显然,它是分布式的。 使用 Spark 的全部目的是可以将其用于大数据问题,在此您可以实际在整个 CPU 和计算机集群的内存能力之间分配处理。 它可以水平分布,因此您可以根据需要将任意数量的计算机扔给给定问题。 问题越大,计算机越多; 在那里您可以做什么实际上没有上限。
......@@ -333,7 +333,7 @@ hiveCtx = HiveContext(sc) rows = hiveCtx.sql("SELECT name, age FROM users")
让我们先谈谈转换。 转换正是它们的本质。 这是一种采用 RDD 并将 RDD 中的每一行转换为基于您提供的函数的新值的方法。 让我们看一下其中的一些功能:
* `map()``flatmap()``map``flatmap`是您最常看到的功能。 两者都将具有您可以梦想的任何功能,将 RDD 的一行作为输入,并且将输出转换后的行。 例如,您可能会从 CSV 文件中获取原始输入,并且您的`map`操作可能会将该输入获取并基于逗号分隔符将其分解为各个字段,然后返回 Python 列表,该列表以更结构化的方式包含该数据 您可以对其进行进一步处理的格式。 您可以将映射操作链接在一起,因此一个`map`的输出可能最终会创建一个新的 RDD,然后对其进行另一次转换,依此类推。 再次,关键是,Spark 可以将这些转换分布在整个群集中,因此它可能会包含 RDD 的一部分并在一台机器上进行转换,而 RDD 的另一部分又会在另一台计算机上进行转换。
* `map()``flatmap()``map``flatmap`是您最常看到的功能。 两者都将具有您可以梦想的任何功能,将 RDD 的一行作为输入,并且将输出转换后的行。 例如,您可能会从 CSV 文件中获取原始输入,并且您的`map`操作可能会将该输入获取并基于逗号分隔符将其分解为各个字段,然后返回 Python 列表,该列表以更结构化的格式包含该数据,您可以对其进行进一步处理。 您可以将映射操作链接在一起,因此一个`map`的输出可能最终会创建一个新的 RDD,然后对其进行另一次转换,依此类推。 再次,关键是,Spark 可以将这些转换分布在整个群集中,因此它可能会包含 RDD 的一部分并在一台机器上进行转换,而 RDD 的另一部分又会在另一台计算机上进行转换。
就像我说的,`map``flatmap`是您将看到的最常见的转换。 唯一的区别是`map`仅允许您为每一行输出一个值,而`flatmap`则允许您实际为给定行输出多个新行。 因此,实际上您可以创建比使用`flatmap.`时更大的 RDD 或更小的 RDD。
......@@ -526,7 +526,7 @@ def createLabeledPoints(fields):
您可以看到 Excel 实际上将其导入到表中,但是如果您要查看原始文本,则会看到它由逗号分隔的值组成。
第一行是每列的实际标题,因此我们上面的内容是在先经验的年限,是否在职的候选人,以前的雇主人数,受教育程度,是否达到最高 小学,他们在学校期间是否有实习机会,最后是我们要预测的目标,他们是否最终获得了工作机会。 现在,我们需要将该信息读入 RDD,以便可以对其进行处理。
第一行是每列的实际标题,因此我们上面的内容是在先经验的年限,是否在职的候选人,以前的雇主人数,受教育程度,是否上了最好的学校,他们在学校期间是否有实习机会,最后是我们要预测的目标,他们是否最终获得了工作机会。 现在,我们需要将该信息读入 RDD,以便可以对其进行处理。
让我们回到我们的脚本:
......@@ -541,9 +541,9 @@ rawData = rawData.filter(lambda x:x != header)
确保将文件的路径更改为实际安装该文件的位置,否则它将无法正常工作。
现在,我将使用`first`函数从该 RDD 中提取第一行,即第一行。 因此,现在标题 RDD 将包含一个条目,该条目仅是列标题的这一行。 现在,看看上面的代码中发生了什么,我在包含该 CSV 文件中所有信息的原始数据上使用`filter`,并且正在定义`filter`函数,该函数将仅允许行通过 如果该行不等于该初始标题行的内容。 我在这里所做的是,我已经获取了原始 CSV 文件,并通过仅允许与第一行不相等的行继续存在而删除了第一行,然后将其返回给`rawData` RDD 变量再次。 因此,我将使用`rawData`,过滤掉第一行,并创建一个仅包含数据本身的新`rawData`。 到目前为止和我在一起? 没那么复杂。
现在,我将使用`first`函数从该 RDD 中提取第一行,即第一行。 因此,现在标题 RDD 将包含一个条目,该条目仅是列标题的这一行。 现在,看看上面的代码中发生了什么,我在包含该 CSV 文件中所有信息的原始数据上使用`filter`,并且正在定义`filter`函数,该函数仅当该行不等于该初始标题行的内容时,将允许行通过。 我在这里所做的是,我已经获取了原始 CSV 文件,并通过仅允许与第一行不相等的行继续存在而删除了第一行,然后将其返回给`rawData` RDD 变量再次。 因此,我将使用`rawData`,过滤掉第一行,并创建一个仅包含数据本身的新`rawData`。 到目前为止和我在一起? 没那么复杂。
现在,我们将使用`map`函数。 接下来,我们需要开始从此信息中构造出更多结构。 现在,我的 RDD 的每一行都只是一行文本,它是逗号分隔的文本,但是它仍然只是一个巨大的文本行,我想采用逗号分隔的值列表并将其实际拆分成单个文本 领域。 归根结底,我希望将每个 RDD 从一行包含一堆用逗号分隔的信息的文本行转换为 Python 列表,该列表对我拥有的每列信息都有实际的单独字段。 因此,这就是 Lambda 函数的作用:
现在,我们将使用`map`函数。 接下来,我们需要开始从此信息中构造出更多结构。 现在,我的 RDD 的每一行都只是一行文本,它是逗号分隔的文本,但是它仍然只是一个巨大的文本行,我想采用逗号分隔的值列表并将其实际拆分成单个文本字段。 归根结底,我希望将每个 RDD 从一行包含一堆用逗号分隔的信息的文本行转换为 Python 列表,该列表对我拥有的每列信息都有实际的单独字段。 因此,这就是 Lambda 函数的作用:
```py
csvData = rawData.map(lambda x: x.split(","))
......@@ -599,7 +599,7 @@ def createLabeledPoints(fields):
```
首先,它接受我们准备好将其转换为`LabeledPoints``StringFields`列表,其中标签是目标值-此人是否被雇用? 0 或 1 后跟一个包含我们关心的所有其他字段的数组。 因此,这就是创建`DecisionTree MLlib`类可以使用的`LabeledPoint`的方式。 因此,在上面的代码中,您看到我们正在将多年的经验从字符串转换为整数值,对于所有的是否字段,我们都将其称为`binary`函数,该函数是我在顶部定义的 代码,但我们尚未讨论:
首先,它接受我们准备好将其转换为`LabeledPoints``StringFields`列表,其中标签是目标值-此人是否被雇用? 0 或 1 后跟一个包含我们关心的所有其他字段的数组。 因此,这就是创建`DecisionTree MLlib`类可以使用的`LabeledPoint`的方式。 因此,在上面的代码中,您看到我们正在将多年的经验从字符串转换为整数值,对于所有的是否字段,我们都将其称为`binary`函数,该函数是我在顶部定义的代码,但我们尚未讨论:
```py
def binary(YN):
......@@ -734,7 +734,7 @@ from sklearn.preprocessing import scale
```
我们将从集群`MLlib`包中导入`KMeans`包,我们将从`numpy`中导入`array``random`,因为同样,我们可以自由使用您想要的任何东西,这是一个 最终,Python 脚本需要使用`MLlib`数组作为输入,因此`MLlib`经常需要输入。 我们将要导入`sqrt`函数和通常的样板内容,我们需要`SparkConf``SparkContext`,几乎每次都需要从`pyspark`中引入。 我们还将从`scikit-learn`导入`scale`函数。 同样,只要确保将`scikit-learn`安装在要运行此作业的每台计算机上,就可以使用`scikit-learn`,并且不要以为`scikit-learn`会神奇地自我扩展 在 Spark 上运行它。 但是,由于我仅将其用于缩放功能,因此可以。 好吧,让我们继续进行设置。
我们将从集群`MLlib`包中导入`KMeans`包,我们将从`numpy`中导入`array``random`,因为同样,我们可以自由使用您想要的任何东西,这是当天最后的 Python 脚本,并且`MLlib`需要使用`numpy`数组作为输入。 我们将要导入`sqrt`函数和通常的样板内容,我们需要`SparkConf``SparkContext`,几乎每次都需要从`pyspark`中引入。 我们还将从`scikit-learn`导入`scale`函数。 同样,只要确保将`scikit-learn`安装在要运行此作业的每台计算机上,就可以使用`scikit-learn`,并且不要以为`scikit-learn`会神奇地自我扩展,仅仅因为你在 Spark 上运行它。 但是,由于我仅将其用于缩放功能,因此可以。 好吧,让我们继续进行设置。
我将首先创建一个全局变量:
......@@ -783,7 +783,7 @@ resultRDD = data.map(lambda point: clusters.predict(point)).cache()
在执行 Spark 时,重要的一点是,每当您要在 RDD 上调用多个动作时,首先对其进行缓存很重要,因为当您在 RDD 上调用动作时,Spark 会熄灭并弄清楚 DAG,以及如何最佳地获得该结果。
它将关闭并实际执行所有操作以获得该结果。 因此,如果我在同一个 RDD 上调用两个不同的动作,它实际上将最终对该 RDD 进行两次评估,并且如果要避免所有这些额外的工作,则可以缓存 RDD 以确保它不会重新计算 它不止一次
它将关闭并实际执行所有操作以获得该结果。 因此,如果我在同一个 RDD 上调用两个不同的动作,它实际上将最终对该 RDD 进行两次评估,并且如果要避免所有这些额外的工作,则可以缓存 RDD 以确保它不会不止一次重新计算
这样,我们确保随后的这两个操作可以正确执行操作:
......@@ -929,7 +929,7 @@ fields = rawData.map(lambda x: x.split("\t"))
我将基于它们的制表符分隔符将每个文档拆分为一个 Python 列表,并创建一个新的`fields` RDD,它代替原始输入数据,现在包含该输入数据中每个字段的 Python 列表。
最后,我将映射该数据,获取每个字段列表,提取第三个字段`x[3]`,我碰巧知道它是文章本身,实际文章文本,而我依次是 将基于空格进行拆分:
最后,我将映射该数据,获取每个字段列表,提取第三个字段`x[3]`,我碰巧知道它是文章本身,实际文章文本,而我将反过来基于空格进行拆分:
```py
documents = fields.map(lambda x: x[3].split(" "))
......@@ -1149,7 +1149,7 @@ fullPredictions = model.transform(testDF).cache()
我将调用`model.transform(testDF)`,这将根据我的测试数据集中的权重来预测高度。 我实际上有已知的标签,即实际的正确高度,这将向该数据框添加一个称为预测的新列,该列具有基于该线性模型的预测值。
我将缓存这些结果,现在我可以提取它们并将它们进行比较。 因此,让我们像在 SQL 中一样使用`select`来抽出预测列,然后我将实际转换该数据框并从中抽出 RDD,并使用它将其映射到一个普通的旧 在这种情况下,RDD 充满浮点高度:
我将缓存这些结果,现在我可以提取它们并将它们进行比较。 因此,让我们像在 SQL 中一样使用`select`来抽出预测列,然后我将实际转换该数据框并从中抽出 RDD,并使用它将其映射到一个普通的旧 RDD,在这种情况下,它充满浮点高度:
```py
predictions = fullPredictions.select("prediction").rdd.map(lambda x: x[0])
......@@ -1175,7 +1175,7 @@ spark.stop()
```
这是一种复杂的操作方式。 我这样做是为了与前面的示例更加一致,但是一种更简单的方法是实际上选择预测并将其一起标记到单个 RDD 中,该 RDD 将这两列映射在一起,然后不必压缩它们,但是 无论哪种方式。 您还将注意到,在最后,我们需要停止 Spark 会话。
这是一种复杂的操作方式。 我这样做是为了与前面的示例更加一致,但是一种更简单的方法是实际上选择预测并将其一起标记到单个 RDD 中,该 RDD 将这两列映射在一起,然后不必压缩它们,但是无论哪种方式都有效。 您还将注意到,在最后,我们需要停止 Spark 会话。
因此,让我们看看它是否有效。 让我们转到“工具”,“Canopy 命令提示符”,然后输入`spark-submit SparkLinearRegression.py`,看看会发生什么。
......
......@@ -22,7 +22,7 @@
什么是 A/B 测试? 好吧,这是一个通常在网站上运行的受控实验,它也可以应用于其他环境,但是通常我们谈论的是网站,并且我们将测试该网站的某些更改的效果, 与以前相比。
基本上,您有一个*对照*组查看旧网站的人,以及一个*测试*组查看该网站更改的人,其目的是衡量行为差异 在这两组之间进行比较,并使用该数据来实际确定此更改是否有益。
基本上,您有一个*对照*组查看旧网站的人,以及一个*测试*组查看该网站更改的人,其目的是在这两组之间进行比较来衡量行为差异,并使用该数据来实际确定此更改是否有益。
例如,我拥有一家拥有网站的公司,我们向人们授权软件,现在我有一个漂亮,友好的橙色按钮,人们在想购买许可证时可以单击该按钮,如下图左图所示 。 但是,如果将按钮的颜色更改为蓝色(如右图所示),会发生什么?
......@@ -32,7 +32,7 @@
我的意思是,从直觉上讲,也许可以更吸引人们的注意力,或者从直觉上讲,也许人们更习惯于看到橙色的购买按钮,并且更有可能点击该按钮,我可以任意选择旋转,对吗? 因此,我自己的内部偏见或成见并不重要。 重要的是人们如何对我实际网站上的更改做出反应,这就是 A/B 测试的目的。
A/B 测试会将人们分成看到橙色按钮的人们和看到蓝色按钮的人们,然后我可以衡量这两组之间的行为以及它们之间的差异,并决定按钮的颜色 应该基于该数据
A/B 测试会将人们分成看到橙色按钮的人们和看到蓝色按钮的人们,然后我可以衡量这两组之间的行为以及它们之间的差异,并应该基于该数据决定按钮的颜色
您可以使用 A/B 测试来测试各种事物。 这些包括:
......@@ -110,13 +110,13 @@ A/B 测试会将人们分成看到橙色按钮的人们和看到蓝色按钮的
现在,这确实假设您的行为是正常分布的,并且当我们谈论诸如人们在网站上花费的金额之类的事情时,通常这是一个不错的假设。 确实有多少人支出呈正态分布。
但是,对于其他特定情况,您可能需要查看 T 统计的更多精炼版本。 例如,当您谈论点击率时,有一个名为 **Fisher 的精确测试**,当您在谈论每个用户的交易时,有**电子测试**,例如有多少网络 他们看到的页面数,以及**卡方**测试,这通常与您查看订单数量有关。 有时,您会希望查看给定实验的所有这些统计信息,然后选择最适合您要尽力而为的实验。
但是,对于其他特定情况,您可能需要查看 T 统计的更多精炼版本。 例如,当您谈论点击率时,有一个名为 **Fisher 的精确测试**,当您在谈论每个用户的交易时,有 **E 测试**,例如他们看到了多少页面,以及**卡方**测试,这通常与您查看订单数量有关。 有时,您会希望查看给定实验的所有这些统计信息,然后选择最适合您要尽力而为的实验。
# p 值
现在,谈论 p 值要比 T 统计量容易得多,因为您不必考虑,我们在谈论多少个标准差? 实际值是什么意思? 人们容易理解 p 值,这使它成为更好的工具,可以将实验结果传达给企业中的利益相关者。
p 值基本上是该实验满足原假设的概率,即对照和治疗行为之间没有真正差异的概率。 p 值低表示没有效果的可能性很低,有点双重负数,因此有点直觉,但是到最后,您只需要了解 p 值低 价值意味着您的更改很有可能产生真正的效果。
p 值基本上是该实验满足原假设的概率,即对照和治疗行为之间没有真正差异的概率。 p 值低表示没有效果的可能性很低,有点双重负数,因此有点直觉,但是到最后,您只需要了解低 p 值意味着您的更改很有可能产生真正的效果。
您想要看到的是高 T 统计量和低 p 值,这将意味着显着的结果。 现在,在开始实验之前,您需要确定成功的门槛,这意味着与业务负责人一起确定门槛。
......@@ -130,7 +130,7 @@ p 值基本上是该实验满足原假设的概率,即对照和治疗行为之
请记住,当实验结果为负数时,运行 A/B 测试会产生实际成本。 因此,您不想将其运行太久,因为您可能会亏钱。
这就是为什么您要每天监控实验结果的原因,因此,如果有早期迹象表明更改对网站造成了可怕的影响,也许其中存在错误或可怕的东西,您可以拉 如有必要,请过早插上电源,并限制损坏。
这就是为什么您要每天监控实验结果的原因,因此,如果有早期迹象表明更改对网站造成了可怕的影响,也许其中存在错误或可怕的东西,如有必要你可以过早拔插头,并限制损坏。
我们来看一个实际示例,看看如何使用 Python 测量 T 统计量和 p 值。
......@@ -161,7 +161,7 @@ stats.ttest_ind(A, B)
请记住,为了声明重要性,我们需要看到较高的 T 值 T 统计量和较低的 p 值。
这就是我们在这里看到的,我们看到的是 -14,它是 T 统计的绝对值非常高,为负则表明这是一件坏事,而 p 值却非常低,告诉我们实际上存在 这不可能是随机变化的结果。
这就是我们在这里看到的,我们看到的是 -14,它是 T 统计的绝对值非常高,为负则表明这是一件坏事,而 p 值却非常低,告诉我们实际上这不可能是随机变化的结果。
如果您在现实世界中看到了这些结果,则将尽快拔出该实验的插头。
......@@ -315,7 +315,7 @@ stats.ttest_ind(A, A)
结果,您最终所衡量的只是新客户与旧客户之间行为上的差异。 审核系统以确保在实际分配给对照组或治疗组的人员中没有选择偏见非常重要。
您还需要确保分配是粘性的。 如果要衡量更改在整个会话中的影响,则要衡量他们是否在 A 页上看到了更改,但是,在 C 页上他们实际上进行了转换,因此必须确保他们没有切换组 在这些点击之间。 因此,您需要确保在给定的会话中,人们保持在同一组中,并且如何定义会话也可能变得晦涩难懂。
您还需要确保分配是粘性的。 如果要衡量更改在整个会话中的影响,则要衡量他们是否在 A 页上看到了更改,但是,在 C 页上他们实际上进行了转换,因此必须确保他们在这些点击之间没有切换组。 因此,您需要确保在给定的会话中,人们保持在同一组中,并且如何定义会话也可能变得晦涩难懂。
现在,所有这些问题都可以使用已建立的现成框架(例如 Google Experiments 或 Optimizely)或其中的一个来解决,因此您不必为解决所有这些问题而费力。 如果您的公司确实有内部开发的内部解决方案,因为他们不愿意与外部公司共享数据,那么值得检查是否存在选择偏见。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册