TowardsDataScience 博客中文翻译 2020(三十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

Julia 优于 Python 的 5 个方面

原文:https://towardsdatascience.com/5-ways-julia-is-better-than-python-334cc66d64ae?source=collection_archive---------1-----------------------

为什么 Julia 比 Python 更适合 DS/ML

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Julia 是一种多范例、主要为机器学习和统计编程而创建的函数式编程语言。Python 是另一种用于机器学习的多范例编程语言,尽管通常 Python 被认为是面向对象的。另一方面,Julia 更基于功能范式。虽然 Julia 肯定没有 Python 流行,但是使用 Julia 进行数据科学有一些巨大的好处,这使它在许多情况下是 Python 的更好选择。

№1:速度

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不谈速度,很难谈朱莉娅。朱莉娅以速度非常快而自豪。Julia 不像 Python 是解释型的,它是一种编译型语言,主要是在自己的基础上编写的。然而,与 C 等其他编译语言不同,Julia 是在运行时编译的,而传统语言是在执行前编译的。Julia,尤其是写得好的,可以和 C 一样快,有时甚至比 C 更快。Just In Time (JIT)编译器的编译速度快得令人难以置信,尽管它的编译更像一种解释语言,而不是传统的低级编译语言,如 C 或 Fortran。

第二:多功能性

你可能已经注意到,我说过 Python 是多才多艺的,这是 Julia 的一个优势,这是真的——有很多事情 Python 可以做,而 Julia 却做不到。当然,这只是从本质上来说,因为我们现在谈论的多功能性是语言的多功能性。Julia 代码在 R、Latex、Python 和 c 中是通用的可执行代码。这意味着典型的数据科学项目有可能只需编写一次,就可以在包装器中从另一种语言编译成 Julia,或者只需发送字符串。

PyCall 和 RCall 也是相当大的交易。考虑到 Julia 的一个严重缺点实际上是包,在需要的时候调用 Python 和 R 真的很方便。PyCall 在 Julia 中得到了很好的实现,确实做得很好,非常有用。

№3:多重派遣

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Julia 是一种类型非常独特的语言,有自己的特点和特性,但其中最酷的特性之一是 Julia 的多重调度。首先也是最重要的,茱莉亚的多次派遣速度很快。最重要的是,使用 Julia 的多态分派允许将函数定义作为结构的属性来应用。当然,这使得遗传在朱莉娅体内变得可行。

不仅如此,使用 Julia 的多重分派使函数具有可扩展性。这对于包扩展来说是一个很大的好处,因为无论何时显式导入一个方法,用户都可以更改它。显式导入您的方法并扩展它以将结构路由到新函数会很容易。

№4:专为 ML 打造

与 Python 不同,Julia 的设计初衷是用于统计学和机器学习。Python 是在 90 年代早期作为一种简单的面向对象语言创建的,尽管从那时起它已经发生了很大的变化。鉴于 Python 的历史,以及 Python 如此流行以来的广泛用途,使用一种专门为高级统计工作而设计的语言可能会带来很多好处。

我认为这比 Python 更有利于 Julia 的一个方面是线性代数。香草 Python 可以突突地完成线性代数,但是香草 Julia 可以飞快地完成线性代数。这当然是因为 Python 从来就不支持机器学习中的所有矩阵和方程。Python 一点也不差,尤其是对于 NumPy,但是就无软件包体验而言,Julia 更倾向于这类数学。Julia 的操作系统比 Python 的更接近 R,这是一个很大的好处。大多数线性代数更快更容易做。让我们展示一个点积等式,以进一步说明这一点:

Python -> y = np.dot(array1,array2)
R -> y <- array1 * array2
Julia -> y = array1 .* array2

№5:包管理器

我要第一个说,Julia 的 Pkg 包管理器比 Python 的 Pip 包管理器高出一个世界。Pkg 自带 REPL 和茱莉亚包,你可以从中构建、添加、删除和实例化包。由于 Pkg 与 Git 的结合,这尤其方便。更新很容易,添加包总是很容易,并且总的来说,任何时候使用 Pkg 超过 Python 的 Pip 都是一件愉快的事情。

结论

使用哪种语言并不重要,不管是 R、Julia、Python 还是 Scala。然而,需要注意的是,每种语言都有它的缺点,没有一种语言会是“完美的语言”如果你在编程方面是多才多艺的,从机器学习到图形用户界面再到 API,这一点尤其正确。也就是说,Julia 当然是我最喜欢的库之一,还有 Python。Python 有更好的包,通常如果项目足够小,我会转向 Python,但是对于有数百万观察值的数据集,甚至很难用 Python 读取这种数据。

总的来说,我期待朱莉娅的未来。Julia 写起来很有趣,将来可能会更适合数据科学。

Python 优于 Julia 的 5 个方面

原文:https://towardsdatascience.com/5-ways-python-is-better-than-julia-89267cbf5b9f?source=collection_archive---------21-----------------------

为什么 Python 比 Julia 更适合 DS/ML

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Python 是世界上最流行的高级编程语言。这是有充分理由的,因为许多代码库实际上是在 Python 内部编写的。另一方面,Python 是用 C. Julia 编写的解释型高级编程语言。在 Julia 出现之前,Python 近年来在数据科学家中更受欢迎。

Julia 是一种高级的、多范例的统计编程语言。与 Python 不同,Julia 主要是为统计计算(像 r)而创建的。Julia 是一种使用自己的编译器的编译语言,被称为“实时”编译器。尽管 Julia 是一种很好的机器学习语言,但相比之下 Python 仍然非常流行。

№1:人气

基于 Python 的项目的最大好处是 Python 是一种通用语言,尤其是在 2020 年的今天。许多语言被用来翻译 Python 代码,这些代码经常被用于许多不同的行业,包括但不限于:

  • 开发运营
  • 网络安全
  • 数据科学家
  • 软件工程师
  • Web 开发人员

Python 受欢迎的另一个巨大好处是文档,因为如果有人在互联网上问过你的问题,通常会更容易找到答案。Julia 的一个大问题是缺乏信息,你经常会发现自己在阅读可怕的 Github-README 文档。不用说,过一段时间后会变得很老。

№2:简单

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

众所周知,Python 很容易,这是一个很大的优势。让我们面对现实吧,损失函数和相关系数被抛来抛去的复杂算法已经够复杂了,不用担心底层语法。例如,即使将相同的代码写入 Lisp,也要花费两倍以上的时间。这带来了快速教育、快速理解以及最重要的快速故障排除的好处。

№3:包装

与 Python 的大量用户相应的是 Python 的大量包。我真正喜欢使用 Python 的地方是能够使用两年前有人在 Github 上制作的 Python 包装器中未记录的端点。诸如此类的事情在 Julia 中并不存在,这使得获取数据更加困难。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

包是语言中非常重要的一部分。如果没有合适的代码库来支持机器学习,你会遇到很多问题,你不得不从非常非常低的层次解决问题。这当然是乏味的,并且在进行的过程中消耗更多的时间。Python 的有趣之处在于能够随时从工具箱中取出任何工具——而不必为自己使用该工具编写程序。

№4: Linux

Python 和 Linux 携手并进已经不是什么秘密了。事实上,只要认识到 Python 最初是在 GPL 许可下发布的,并且直到今天仍然是开源的,这些信息就可以得到验证。这太棒了,因为这意味着我们所有的服务器、基于 Linux 的计算机、甚至苹果设备现在都预装了 Python,并且默认文件夹已经准备就绪。

这适用于定制和修复的另一种情况。不喜欢你的 Gnome 应用程序栏在不用的时候不会消失?好吧,把它编进去!任何你不喜欢的东西都可以用最简单的语言编程。

№5:多功能性

Julia 是一种非常通用的语言,但是也就是说,Python 是以完全不同的方式通用的。Python 是为面向对象和通用编程而创建的(尽管在这些范例中没有特别发现)。)这意味着,虽然 Python 已经证明了它在统计和机器学习方面的能力,但 Python 还能够运行 API、移动文件、提供 GUI、托管 web 服务器、控制微处理器,几乎任何你想做的事情,都是 Python 能够做到的。这当然让 Python 变得非常通用。

将 Python 的多功能性与 Julia 的多功能性进行比较,Julia 的有用性在较低层次上当然会恶化。这没什么大不了的,因为低级编程在未来不会有什么发展,再增加一门语言也是白费力气,但是特别的是,Julia 不会做 GUI(至少现在不会),并且有一个 arduino 包,但是很难注册总线输入。然而,部署 web 服务器、统计数据和低级文件系统工作(如编写文本文件)当然仍然是可行的。

最后

Julia 和 Python 都是我非常喜欢的伟大语言。当谈到两种语言在数据科学方面孰优孰劣时,这两种语言肯定会互相攻击。如果你想从 Julia 的角度阅读一篇类似的文章,这里是我对这篇文章的反驳,我描述了我认为 Julia 优于 Python 的 5 个方面。我迫不及待地想看到 Julia 之路的未来,以及 10 年后数据科学语言的发展方向。

在 PySpark 数据框架中添加新列的 5 种方法

原文:https://towardsdatascience.com/5-ways-to-add-a-new-column-in-a-pyspark-dataframe-4e75c2fd8c08?source=collection_archive---------0-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由来自 Pixabaynickgesell 提供

并且,它们都是有用的

每天都在生成太多的数据。

虽然有时我们可以使用类似于Rapids 并行化 Spark 这样的工具来管理我们的大数据,但如果您正在处理数 TB 的数据,这是一款非常棒的工具。

在我关于 Spark 的上一篇文章中,我解释了如何使用 PySpark RDDs 和 Dataframes。

虽然这篇文章解释了很多关于如何使用 rdd 和基本数据帧操作的内容,但是我错过了很多关于使用 PySpark 数据帧的内容。

只有当我需要更多的功能时,我才会仔细阅读,想出多种解决方案来做一件事情。

如何在 spark 中创建新栏目?

现在,这可能听起来微不足道,但相信我,它不是。由于您可能想对数据做这么多事情,我很确定您最终会在工作流中使用这些列创建过程中的大部分。有时利用 Pandas 的功能,有时使用基于 RDDs 的分区,有时利用成熟的 python 生态系统。

这篇文章的主题是“在 Pyspark 数据框架中创建新列的多种方法”

如果您安装了 PySpark,可以跳过下面的入门部分。

Spark 入门

我知道你们很多人不会在系统中安装 spark 来尝试和学习。但是安装 Spark 本身就很头疼。

既然我们想了解它是如何工作的,我建议你在社区版中使用 Spark on data brickshere。别担心,它是免费的,尽管资源更少,但对于我们现在的学习目的来说是有用的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦您注册并登录,将出现以下屏幕。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你可以在这里开始一个新的笔记本。

选择 Python 笔记本,并为其命名。

一旦您启动一个新的笔记本并尝试执行任何命令,笔记本会询问您是否要启动一个新的集群。动手吧。

下一步将检查 sparkcontext 是否存在。要检查 sparkcontext 是否存在,您必须运行以下命令:

sc

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这意味着我们可以在笔记本上运行 Spark。

数据

在这里,我将处理 movie lensml-100k . zip数据集。1000 个用户对 1700 部电影的 100,000 次评分。在这个压缩文件夹中,我们将专门处理的文件是分级文件。该文件名保存为“u.data”

如果您想要上传此数据或任何数据,您可以单击左侧的 data 选项卡,然后使用提供的 GUI 添加数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后,我们可以使用以下命令加载数据:

ratings = spark.read.load("/FileStore/tables/u.data",format="csv", sep="\t", inferSchema="true", header="false")ratings = ratings.toDF(*['user_id', 'movie_id', 'rating', 'unix_timestamp'])

这是它的样子:

ratings.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好了,现在我们终于可以开始我们感兴趣的部分了。如何在 PySpark Dataframe 中创建新列?

1.使用 Spark 本地函数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

安德鲁·詹姆斯在 Unsplash 上拍摄的照片

在 PySpark 数据帧中创建新列的最简单的方法是使用内置函数。这是创建新列的最有效的编程方式,所以每当我想做一些列操作时,这是我第一个去的地方。

我们可以使用.withcolumn和 PySpark SQL 函数来创建一个新列。本质上,您可以找到已经使用 Spark 函数实现的字符串函数、日期函数和数学函数。我们可以将 spark 函数导入为:

import pyspark.sql.functions as F

我们的第一个函数是F.col函数,它让我们可以访问列。因此,如果我们想将一列乘以 2,我们可以使用F.col作为:

ratings_with_scale10 = ratings.withColumn("ScaledRating", 2*F.col("rating"))ratings_with_scale10.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们也可以使用数学函数,如F.exp函数:

ratings_with_exp = ratings.withColumn("expRating", 2*F.exp("rating"))ratings_with_exp.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个模块还提供了很多其他的功能,对于大多数简单的用例来说已经足够了。你可以点击查看功能列表

2.Spark UDFs

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Unsplash 上的除以零

有时我们想对一列或多列做复杂的事情。这可以被认为是将 PySpark 数据帧映射到一列或多列的操作。虽然 Spark SQL 函数确实解决了许多列创建的用例,但每当我想使用更成熟的 Python 功能时,我都会使用 Spark UDF。

要使用 Spark UDF,我们需要使用F.udf函数将常规 python 函数转换成 Spark UDF。我们还需要指定函数的返回类型。在这个例子中,返回类型是StringType()

import pyspark.sql.functions as F
from pyspark.sql.types import *def somefunc(value):
  if   value < 3: 
      return 'low'
  else:
      return 'high'#convert to a UDF Function by passing in the function and return type of functionudfsomefunc = F.udf(somefunc, StringType())ratings_with_high_low = ratings.withColumn("high_low", udfsomefunc("rating"))ratings_with_high_low.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.使用 rdd

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

瑞安·昆塔尔在 Unsplash 上拍摄的照片

有时,spark UDFs 和 SQL 函数对于特定的用例来说是不够的。您可能希望利用 spark RDDs 带来的更好的分区。或者您可能想在 Spark RDDs 中使用组函数。您可以使用这个,主要是当您需要访问 python 函数内 spark 数据框中的所有列时。

不管是哪种情况,我发现这种使用 RDD 创建新列的方式对于有使用 rdd 经验的人来说非常有用,rdd 是 Spark 生态系统中的基本构建块。

下面的过程利用了在Rowpythondict对象之间转换的功能。我们将一个行对象转换成一个字典。像我们习惯的那样使用字典,并将字典转换回 row。

import math
from pyspark.sql import Rowdef rowwise_function(row):
  # convert row to dict:
  row_dict = row.asDict()
  # Add a new key in the dictionary with the new column name and value. 
  row_dict['Newcol'] = math.exp(row_dict['rating'])
  # convert dict to row:
  newrow = Row(**row_dict)
  # return new row
  return newrow# convert ratings dataframe to RDD
ratings_rdd = ratings.rdd
# apply our function to RDD
ratings_rdd_new = ratings_rdd.map(lambda row: rowwise_function(row))
# Convert RDD Back to DataFrame
ratings_new_df = sqlContext.createDataFrame(ratings_rdd_new)ratings_new_df.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.熊猫 UDF

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

帕斯卡尔·贝纳登在 Unsplash 上的照片

Spark 版本 2.3.1 中引入了这一功能。这就允许你在 Spark 上使用 pandas 的功能。当我必须在 Spark 数据帧上运行 groupby 操作时,或者当我需要创建滚动特征并希望使用 Pandas 滚动函数/窗口函数时,我通常会使用它。

我们使用它的方式是通过使用F.pandas_udf装饰器。这里我们假设函数的输入是一个熊猫数据帧。我们需要从这个函数中依次返回一个熊猫数据帧。

这里唯一的复杂性是我们必须为输出数据帧提供一个模式。我们可以使用下面的格式。

# Declare the schema for the output of our function
outSchema = StructType([StructField('user_id',IntegerType(),True),StructField('movie_id',IntegerType(),True),StructField('rating',IntegerType(),True),StructField('unix_timestamp',IntegerType(),True),StructField('normalized_rating',DoubleType(),True)])# decorate our function with pandas_udf decorator
[@F](http://twitter.com/F).pandas_udf(outSchema, F.PandasUDFType.GROUPED_MAP)
def subtract_mean(pdf):
    # pdf is a pandas.DataFrame
    v = pdf.rating
    v = v - v.mean()
    pdf['normalized_rating'] =v
    return pdfrating_groupwise_normalization = ratings.groupby("movie_id").apply(subtract_mean)rating_groupwise_normalization.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们也可以利用这个来 在每个 spark 节点上训练多个单独的模型。 为此,我们复制我们的数据,并给每个副本一个键和一些训练参数,如 max_depth 等。然后,我们的函数获取 pandas 数据帧,运行所需的模型,并返回结果。该结构如下所示。

# 0\. Declare the schema for the output of our function
outSchema = StructType([StructField('replication_id',IntegerType(),True),StructField('RMSE',DoubleType(),True)])# decorate our function with pandas_udf decorator
[@F](http://twitter.com/F).pandas_udf(outSchema, F.PandasUDFType.GROUPED_MAP)
def run_model(pdf):
    # 1\. Get hyperparam values
    num_trees = pdf.num_trees.values[0]
    depth = pdf.depth.values[0]
    replication_id = pdf.replication_id.values[0]
    # 2\. Train test split
    Xtrain,Xcv,ytrain,ycv = train_test_split.....
    # 3\. Create model using the pandas dataframe
    clf = RandomForestRegressor(max_depth = depth, num_trees=num_trees,....)
    clf.fit(Xtrain,ytrain)
    # 4\. Evaluate the model
    rmse = RMSE(clf.predict(Xcv,ycv)
    # 5\. return results as pandas DF
    res =pd.DataFrame({'replication_id':replication_id,'RMSE':rmse})
    return res

results = replicated_data.groupby("replication_id").apply(run_model)

以上只是一个想法,而不是工作代码。尽管稍加修改就能工作。

5.使用 SQL

对于喜欢 SQL 的人来说,甚至有一种方法可以使用 SQL 创建列。为此,我们需要注册一个临时 SQL 表,然后使用带有附加列的简单选择查询。人们也可以用它来连接。

ratings.registerTempTable('ratings_table')
newDF = sqlContext.sql('select *, 2*rating as newCol from ratings_table')
newDF.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

凯利·西克玛Unsplash 上拍摄的照片

这就是本专栏的结尾(双关语)

希望我已经很好地介绍了专栏创建过程,可以帮助您解决 Spark 问题。如果您需要了解更多 spark 基础知识,请查看:

[## 使用 Spark 处理大数据的指南

不仅仅是介绍

towardsdatascience.com](/the-hitchhikers-guide-to-handle-big-data-using-spark-90b9be0fe89a)

你可以在 databricks 上的 GitHub 资源库 发布的笔记本 中找到这篇文章的所有代码。

还有,如果你想了解更多关于 Spark 和 Spark DataFrames 的知识,我想调出 Yandex 提供的大数据精要 大数据专业化 的一个精品课程。

谢谢你的阅读。将来我也会写更多初学者友好的帖子。在 媒体 关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter@ mlwhiz联系

此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

将数据科学应用于房地产的 5 种方式

原文:https://towardsdatascience.com/5-ways-to-apply-data-science-to-real-estate-e18cdcd0c1a6?source=collection_archive---------3-----------------------

有哪些实实在在的好处,我们在哪里可以学到这些技巧?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据科学是可能对房地产行业产生最大长期影响的技术。(照片由詹尼斯·格拉斯Unsplash 上拍摄)

房地产行业面临着巨大的压力,需要释放大数据的潜力,并将机器学习和基于证据的方法纳入其工作流程。在毕马威全球 PropTech 调查 2018 中,49%的参与者认为人工智能、大数据和数据分析是可能对房地产行业产生长期影响的技术。

因此,一些具有长期经营历史的房地产机构的高瞻远瞩的高管正在推动他们的公司释放他们几十年的交易、估值、资产管理、上市和其他数据记录的潜力。与此同时,随着成功的初创公司如 HouseCanaryReonomy 加入老牌公司如 CoStarReal Capital Analytics ,数据提供空间正在走向成熟(甚至可能过度拥挤,使得任何对房地产感兴趣的公司都有可能快速获得大量相关数据。

然而,正如 NAIOP 最近的一篇文章所指出的,房地产专业人士正面临着如何实际利用数据的挑战。毕马威全球 PropTech 调查 2019 证实,80%的公司仍然没有“大部分或全部”由数据引导决策。同一份报告还暗示了“技能差距”——只有 5%的房地产公司由具有数据分析知识的人领导转型工作。

那么,我们到底该如何将数据科学应用于房地产呢?有哪些实实在在的好处?此外,我们可以从哪里学习技能和技术,从而利用大数据在房地产领域的潜力?

[1]房地产价格指数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

房地产价格指数是一种统计方法,可以分析数百万行嘈杂的交易数据,并获得对次级市场历史表现的详细了解。(图片由作者提供)

正如新闻文章专家评论所报道的,数据科学在投资中的应用已经在金融领域激增,如今数据驱动的计算机模型占交易的 80%。然而,与公开上市的股票不同,每一笔报道的房地产交易都代表着一种独特资产的交换——没有哪两种房地产是完全相同的。即使是在同一栋建筑中的两个单位进行交易,它们也可能大相径庭,价格也可能大相径庭。

这给房地产带来了一个特殊的问题——我们如何利用大型数据集来了解各个子市场的表现?如果每个时期交易的房地产类型不同,对历史交易进行简单的平均可能会有偏差,并且在确定平均中包括或排除哪些房地产时存在主观性,以至于不同的研究人员最终可能会得出不同的历史表现。

数据科学方法提出了该问题的几种解决方案。享乐回归技术(在像新加坡这样的国家使用)的运作原则是,每项资产的个别特征可以单独定价,以控制资产之间的差异。

或者,分析可以仅限于比较不止一次出售的房产的价格变化。这就是所谓的重复销售法,即跟踪同一资产在一段时间内的价格变化。美国 Case-Shiller 指数就是这种技术的一个众所周知的例子。

从根本上说,这些方法允许用户超越人类的能力,处理比任何一个人都无法人工理解的更多数据,以产生准确的房地产市场表现信号。数百万行嘈杂的交易数据可以与关于地点、房产特征、人口统计等信息结合起来,产生精细的子市场指数。例如,指数可以精确定位特定邮政区的物业回报,如伦敦的 WC1 指数或 E1 指数,或特定物业类型,如两床公寓指数与三床公寓指数,同时考虑完整数据集中所有交易的影响。指数化有助于确定历史趋势,进而有助于当前定价和未来回报估计。

[2]自动估价模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自动化估价模型通过利用大型数据集评估公平的当前交易价格,帮助我们了解当前的房地产市场。(图片由作者提供)

统计估值方法在全球范围内越来越受欢迎,例如美国的 Zillow Zestimate ,新加坡的 UrbanZoom ,以及芬兰的 SkenarioLabs 。任何自动估价模型的目标都是利用数据来产生对房产市场价值的估计——在这种情况下,自愿的买方和卖方可以公平交易,而无需强制。

采用了类似于指数化的方法,部署了潜在的更先进的数据科学技术,以利用在线学习和集成方法。但是,最后的输出是不一样的。目标不是指数,而是资产价值的点(或范围)估计。直接的好处是更精确地确定一项财产的公平市场价值,这种价值是瞬间产生的,而且成本很低。这些估价不仅对房产定价有用,而且对评估抵押贷款和支持这些资产的贷款组合也有用。

这项技术的一个有趣应用是在像 Opendoorproper这样的公司,它们自动对房屋进行投标,为业主的资产提供现成的流动性。

自动化估价模型通过帮助评估当前交易的公平交易价格,帮助我们了解当前的房地产市场。

[3]时间序列预测

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

时间序列方法有助于我们理解房地产市场的未来走向。(图片由作者提供)

时间序列方法有助于我们理解房地产市场的未来走向。更好的预测有明显的好处——更好的投资和开发交易,以及更高的财务回报。

如果我们只有一组数据,例如,一个单一市场的房地产价格指数,我们可以使用自回归综合移动平均(ARIMA)模型进行短期预测。这种类型的模型可以评估季节变化,并确定数据中的趋势和模式,以估计未来的表现。

更常见的是,我们会有一组数据,如几个不同(但相关)市场的房地产价格指数,宏观经济系列,如 GDP、失业、通胀等。、金融指标,如利率和抵押贷款利率、股市指数、外汇利率等。这些变量相互之间都有因果影响,在这种情况下,可以使用向量自回归(VAR)和向量误差修正模型(VECM)进行预测。通过这样做,我们在预测房地产价格的未来时,考虑了一系列因素的演变。

许多分析提供商,如 HouseCanaryReal Estate Foresight 使用数据科学方法来预测未来的房地产表现。在宏观经济数据领域, Capital EconomicsOxford Economics 等使用其中一些统计方法来预测 GDP、通胀、利率等的走势,所有这些都是房地产交易评估流程的关键输入。

【4】聚类分析

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聚类分析识别可能表现更相似的属性组。(照片由 Patrick SchreiberUnsplash 上拍摄)

不同地区的房地产表现可能会有很大差异。由于不同的宏观经济形势,不同的国家可能会有所不同。同一国家内的城市可能会因当地因素(如经济活动或供应)而有所不同。在一个城市中,一些社区或子行业(如豪华公寓与大众市场住宅)的表现也可能大相径庭。

聚类分析严格识别数据中的模式,有助于确定哪些属性组的表现可能更相似,哪些属性组的表现更可能不同。

聚类分析的另一个应用是确定房地产市场表现或多或少相似的时间段。许多房地产市场受到政府干预的严重影响。立法可能会有许多重大变化,导致定价和投资行为随时间而变化。聚类分析可以帮助识别定价性能可能更相似的时间段。

聚类分析有助于我们为每个群体(或时间段)建立有针对性的模型,从而提高准确性。它还可以用于指导业务战略——通过确定不同团队应该瞄准哪个细分市场,或者市场可能处于什么投资体制,领导者可以在数据的支持下做出更有利可图的决策。

【5】地理信息系统

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GIS 有助于可视化、理解和分析空间和位置情报。(图片由作者提供)

位置是房地产分析中最重要的因素之一,GIS 工具如 Quantum GISESRI 的 ArcGIS 帮助我们可视化、理解和分析位置情报。随着政府开放数据源的兴起,可以获得比以往任何时候都多的信息,从邻里的人口迁移到公共设施的位置,等等。

使用 GIS 可解决的任务的一个示例是加载给定年份内的所有房产交易,还加载所有火车站的位置,然后自动确定哪些房产在火车站的指定半径内,并统计测试这些房产的每平方英尺价格是否高于远离火车站的房产。

GIS 还可以用来计算通勤时间,或者找到符合特定标准的房产。地理信息系统支持选址,例如,根据人口特征、交通、甚至竞争对手的位置来寻找好的零售点。

行业影响

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将数据科学应用到房地产中,可以带来广泛的商业机会。(照片由塞缪尔·佩雷拉Unsplash 上拍摄)

英国房地产投资信托基金的一句话总结得很好:“如果你不能高效地使用数据,那么你将错过你的业务/市场的大量价值。别人不会犯这个错误,你会越来越没有竞争力。最终,世界只会朝着一个方向发展。”(毕马威全球 PropTech 调查 2019 )

这场革命也发生在其他行业。在金融领域,Bridgewater 和 Renaissance Technologies 是系统投资的早期参与者,几十年来取得了巨大的成功。如今,数据驱动的公开市场量化投资已成为常态,而非例外。甚至体育也变得极其统计驱动,团队草案决策通常由复杂的分析和建模驱动。在某种程度上,房地产行业更加依赖数据驱动的决策是不可避免的。

对于房地产来说,有许多商业机会和趋势值得注意。

数据本身是有价值的这一假设是明确的,并且得到了像 TeranetCompstak 这样的公司的成功支持。但是,即使是整理、清理和组织数据——公开的或不公开的——也是重要价值的来源,正如像 CherreRealyse 这样的公司的崛起所证明的那样。将原始数据转化为可用的分析是另一个价值来源,像 Walk ScoreLocal Logic 这样的公司就是这样做的。

自动估价的兴起给估价工作带来了机遇和挑战。在某些行业,基本估值可能开始转向更依赖统计模型,因为统计模型执行起来更便宜、更快。但与此同时,新的商业模式正在出现,如即时房地产买家。反过来,这可能会对那些依靠中介这些传统上不透明、流动性差的市场为生的人产生影响。

预测和分析为房地产投资带来了新的机遇。Skyline.ai 是使用数据驱动方法进行投资的一个领先但新生的例子,但仍有很大的发展空间。在金融领域,价值 3 万亿美元的对冲基金行业的⅓运用量化策略进行运作。与此同时,前 100 家房地产基金管理着超过 3 万亿美元的资产,但迄今为止,基本上还没有一家进行量化投资。

学习选项

现在可以参加教授房地产数据科学的在线课程。(作者视频)

那么,我们在哪里可以学习这些方法,并利用房地产大数据的潜力呢?

大多数选项都是针对一般的数据科学学习,没有特别关注房地产和上面列出的技术。但是,它们确实提供了一个很好的起点,从中可以继续构建,并尝试自学所需的其他方法。

在这一领域, General Assembly 在全球多个地点提供校园课程(以及在线选项),开展全日制和非全日制通才数据科学课程。Coursera 提供关于 GIS 以及数据科学的预录自学视频。大学也有正式的 1 到 2 年的 T4 项目。

另外, PropertyQuants 提供了一个快速的 11 周实时互动在线课程,专门讲述“将数据科学和机器学习应用于房地产”它包括一个 bootcamp 模块,帮助参与者开始了解编程和数据科学,随后是房地产数据科学和 GIS 模块,因此涵盖了上面列出的所有主要技术。

参与者还可以参与他们选择的顶点项目,使用课程中教授的方法进行真实世界的分析。课堂辅以一对一的会议和分级作业,以确保参与者完全理解课程材料。这可能是当今唯一一门专门关注数据科学在房地产中的应用的课程。

结论

房地产行业可能刚刚开始向更多使用数据和数据驱动的决策转变。各种创业公司和前瞻性机构现在开始释放巨大的机会。如上所述,有一系列具体的方法将数据科学应用于房地产,以帮助从数百万行数据转变为对过去、现在和未来房地产子市场表现的精细理解,并做出卓越的投资和业务决策。

然而,在这个行业中,很大一部分人可能经常缺乏所需的技能。现在有机会学习这些技术和方法——特别是针对房地产——投资时间进行升级可以使一系列参与者受益。房地产研究人员可以开始使用数据和机器学习来产生改变游戏规则的见解,并释放大数据集的价值。那些在 Proptech 行业的人(甚至是投资 Proptech 的人)可以更好地理解这些方法,并建立(或投资)颠覆性的活动。最后,学习这些方法的房地产投资者可以使用数据驱动的方法来寻找特殊的机会,战胜市场。

COVID 之后更有效地交流数据的 5 种方法

原文:https://towardsdatascience.com/5-ways-to-communicate-data-more-effectively-post-covid-c773d3ecd9df?source=collection_archive---------65-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

沃洛季米尔·赫里先科在 Unsplash 上的照片

远程时如何更有效

D 数据科学是一项协作性很强的工作——你不断地与来自各种不同角色和背景的同事互动。在一天之内,您可以与工程师、产品经理、其他数据科学家、运营人员、设计师等会面。面对如此多样化的团队成员,交流数据是一件很难做好的事情。现在协作是虚拟的,交流变得有点困难。

由于我们大多数人现在都在家工作,我们应该采取一些额外的措施来与他人交流数据。这篇文章介绍了一些快速实用的技巧,这些技巧在任何情况下都会对所有的队友和同事有所帮助。其中一些提示可能看起来很明显,所以如果你已经在做了,那就太好了——然而,阅读这篇文章的其他人很可能会发现这些提示真的很有帮助。

通过在你的日常工作流程中实施这些技巧,你能够在几个关键方面使每个人受益:

  • **释放您的时间:**如果您积极投入时间使数据更容易访问/理解,您就能够节省未来回答临时问题或在问题最终出现时撰写问题的时间。
  • **了解你 3 个月前做了什么:**有多少次你不得不翻出几个月前做的一份分析?我个人发现自己一周要做好几次。这些建议应该有助于与未来的自己沟通,因为你可以很容易地从过去寻找一些东西,了解你做了什么,你做了什么假设,这样你就可以做类似的分析,或者用当前的评论分享过去的结果。
  • 授权给你的同事: *这是最重要的一条,因为这是你被团队聘为分析人员的原因。*帮助您的团队成员以他们熟悉的方式访问数据(SQL 代码、Excel 中的汇总/采样数据、仪表板等)。),这使他们能够更多地接触数据,从而提高工作效率。内部数据是公司拥有的最有价值的东西之一,如果你能够帮助你的同事有效地使用这些数据,那将是一个巨大的胜利。

1.简单的仪表板非常有用

了解如何创建仪表板是数据科学家可能拥有的最重要的技能之一。如果数据科学家工作的两个主要方面是分析和交流数据,仪表板是两者结合的完美媒介。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

卢克·切瑟Unsplash 上拍摄的照片

由于现在一切都很遥远,拥有一个简单的仪表板应该可以回答你的队友可能会有的问题,并且应该可以显著减少随机收件箱,以便你可以专注于你的工作。

对于较小的项目和功能来说,创建一个仪表板在一开始看起来似乎有点大材小用。但是,如果您已经精通公司的仪表板工具,那么创建一个只有几个图形和表格的仪表板将会比您本来要编写的查询多花几分钟的时间。不仅如此,为更小的计划指定一个仪表板会给那些想利用自己的时间跟踪和查看数据的同事留下深刻印象。

一旦您创建了仪表板,它就可以很容易地与公司中的任何人共享,并且可以帮助团队在一组集中的指标和统计数据上保持一致。出于更自私的原因,从长远来看,您的仪表板将最终节省您的时间,因为它将有助于避免误解,并减少未来的入站数据请求。

2.慷慨地超链接

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Fré SonneveldUnsplash 上拍摄

无论你是在 Google Sheets 中做分析,写一条松散的信息,写一封电子邮件,还是使用 markdown——有更多的链接几乎总是更好。好的分析应该做两件事:

  1. 引发更多问题
  2. 基于之前的分析/研究

在上述两种情况下,都有相关的东西可以联系起来。拥有可访问的链接更有可能让你的队友理解你的分析。话虽如此,我还是想做一个明确的区分:避免直接粘贴链接,因为这样不美观,会占用很多空间,有时还不可点击——使用超链接!

想象一下,如果维基百科有一堆直接粘贴在文章中的 url,那将是一种可怕的体验!此外,使用维基百科作为灵感,养成超链接的习惯。这些链接不会分散你对文章的注意力,还会激发你的好奇心,因为你可能会因为点击一个超级链接的兔子洞而迷失几个小时。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

看看这些链接!

了解你用来分享数据和分析的所有不同平台的热键和语法,并经常链接。

  • 大多数情况下: ctrl/cmd + k会允许你创建一个超链接
  • 降价: [hyperlink text](url)
  • 懈怠: ctrl/cmd + shift + u

3.总是分享相关的查询/代码

扩展上面的超链接主题,我们想让我们的分析尽可能容易理解。即使你认为没有人会看你的代码,链接它仍然是有用的,以防你回头看它。如果您的同事能够在他们自己的工作中利用您的代码/查询,那么他们会非常感谢这种姿态。

我与我的队友分享我的查询/代码的一些方式:

  • **粘贴:**最简单的方法是,将文档本身的代码粘贴到附录部分的底部。这对于较短的查询来说已经足够了。你也可以看看插件或工具,如代码块(用于谷歌文档)来帮助你。在 slack 和 markdown 中,可以使用``来创建代码块。
  • **链接:**使用剪贴板或粘贴工具,你可以粘贴你的代码并生成一个超链接来共享代码。例如,你有粘贴代码,但是很可能有内部工具可以做到这一点(更安全)。如果你在 Github 上有你的代码,这只是一个 Github 链接。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图来自https://paste.ofcode.org/

  • **附件:**将代码文件直接作为附件共享。一般来说,你希望避免这种情况,因为这确实需要另一方采取一些额外的步骤。
  • **数据:**如果你的队友不知道如何使用 SQL,或者如果查询需要很长时间才能运行,那么以 csv 格式导出数据集或样本可能会有所帮助,将它们发送过来,以便他们可以直接进入数据。

4.语境!

这更适合 Slack、微软团队或其他用于协作的消息平台。如果你在一个频道上分享一个快速更新,预计会有一些人不太参与其中。尤其是在较大的频道上,或者如果你的信息被分享到不同的频道/群组。

思考这些案例,你要养成添加一两个引导句的习惯,以设置**的背景,为什么你要分享某个更新,为什么它很重要,以及自从上次更新以来它有什么变化。**这个手势让分享你的作品变得更加容易。你想让你的团队更加知情而不是困惑。

5.四舍五入你的数字

这是一个更通用的提示,但是这是你能做的最省力的事情来减少误解,让对方明白你的意思。

这是一个非常简单的提示:**你想让你的数据尽可能容易阅读。**如果你的图表/表格有一堆很长的数字,你的队友会很难读懂。花几秒钟时间想想你应该用多少有效数字来表达这个观点。这看起来像是一个小调整,但它是帮助你的队友理解关键指标的最有效的方法之一,因为它将你的队友锁定在正确的关注点上。舍入对于小数字和非常大的数字都很重要。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

小数字:右易于阅读。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

大数:右易读。

结束想法

希望这些提示对你有所帮助,或者已经在你的日常工作中使用了。它们不应该花太多时间去实现,一旦你养成了这样做的习惯,你的队友会更加欣赏你。

Python 中控制属性的 5 种方法。Led 指南示例

原文:https://towardsdatascience.com/5-ways-to-control-attributes-in-python-an-example-led-guide-2f5c9b8b1fb0?source=collection_archive---------13-----------------------

在点上发生了什么。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Unsplash 通过 @joannakosinska 提供

介绍

可以通过控制属性值及其访问来保护数据完整性。当创建一个类时,我们可能希望确保所有将来的对象都具有正确数据类型的属性,和/或合理/适当的值。我们可能还希望确保一旦设置了属性,就不能更改或删除它们的值。为此,必须创建只读和删除证明属性。

接受姓名、年龄和服务年限作为参数的 Employee 类可能希望确保姓名是一个字符串,年龄和服务年限是整数,然后在创建的对象中将它们设置为属性。这个类可能还希望确保像名称这样的属性不能被修改或删除。

属性验证可以帮助确保有效的数据输入,即使在类的用户可能输入不太理想的用户信息的情况下,例如,小写的姓名。这篇教程文章将探索 5 种不同的方法来确保属性验证,即通过 magic/dunder 方法和 decorators。当在类中定义的方法中使用属性本身时,属性完整性非常重要。这就是为什么在对象中设置属性之前,应该检查它的值。

示例 1: dunder _setattrdelattr

Python 中的 magic 或 dunder _setattrdelattr 方法代表了程序员控制属性的一种方式。为了说明,让我们初始化一个名为 Employees 的类。这个类将接受 3 个参数,并将它们设置为对象中的属性。

为了展示我们如何对属性施加控制,让我们建立我们希望为 Employees 对象实现的行为。

  1. _name 属性值应该是大写的,不管用户是否选择以大写格式输入 name 属性。
  2. _name 属性应该只允许设置一次。一旦设置好,名称属性将变成只读的*。*
  3. _age 和 _service_length 属性应该是整数。如果它们不是 TypeError,将引发异常。
  4. 不能删除 _name 属性

dunder setattr

dunder setattr 方法将对象、键以及我们希望在对象中设置的值作为参数。我们首先检查具有属性’ _name '的对象是否已经具有属性 name。如果是这样,我们将引发一个 AttributeError,因为我们不希望 name 属性被重置。在下面的 elif 语句中,如果对象没有 name 属性,我们将设置它,并使用 string title 方法将其大写。

在第一个 if 语句中,我们首先检查是否已经设置了属性’ _name '。如果已经在 init 方法中设置了它,用户将无法重新设置它,然后它将成为一个只读属性。

setattr 方法的第一个 if 和 elif 块中的逻辑解决了上面的第 1 点和第 2 点。现在,让我们检查第 3 点的年龄和服务年限属性的数据类型。

对于’ _age ‘和’ _service_length '属性,我们使用内置的 Python isinstance 函数检查它们的类型是否为 int。如果它们是除 int 之外的任何类型,将引发 TypeError 异常。

最后,让我们解决第 4 点,并实现代码来防止名称属性的删除。为了便于讨论,让我们假设,名字一旦被设定,就不能被删除并永久存在。

因此,当我们试图从对象中删除 name 属性时,会引发一个 AttributeError 异常,通知用户不能删除该属性。在幕后,del 关键字调用 delattr 方法。由于我们在类中定义了它,所以它会调用我们的自定义版本 delattr。但是,我们仍然允许删除任何其他属性的行为。

注意,在所示的代码片段中,我们如下所示设置和删除属性,以避免递归错误。

下面通过 GitHub gist 显示了我们的 Employee 类的代码,可以通过这个链接获得。

为了测试我们已经实现的自定义行为,让我们创建一个 Employees 类的实例,并检查 name 属性是否可以设置、不能重置和不能删除。此外,我们可以检查年龄和服务年限属性的类型。

重置 name 属性失败,并通知用户程序终止的原因。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我们遍历属性字典并打印它们的类型时,我们可以看到年龄和服务年限是 int 类型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,当我们试图删除属性名时,会引发一个 AttributeError 异常,用字符串消息通知用户不能删除该属性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们现在已经成功地制定了我们想要的习俗行为。虽然这些例子是虚构的,但它们确实说明了我们如何使用 Python 中的 setattr 和 delattr 方法来控制属性。如果你想尝试所示的例子,完整的代码可以通过这个链接获得。

控制对象属性的替代方法

以下示例展示了在 Python 中控制属性的替代方法。附带说一句,我并不认为它们是控制属性的最佳方式,相反,替代方式意味着可以增加您在 Python 中使用的工具库。

下一节将介绍使用 decorators 管理属性的示例指南。

使用装饰者

示例 2:使用@staticmethod 装饰器

为了保持连续性,在前面的示例中将初始化相同的雇员类。这里,staticmethod decorator 可以用来检查对象中的属性值。具体来说,我们希望 age 和 service_length 属性值都是 int 类型。

为此,我们可以在我们的类中定义一个 data_type_check 方法,并用 staticmethod decorator 来修饰它。当在 init 构造函数中设置属性时,我们调用对象上的 data_type_check 方法,并传入 age 或 service_length 作为参数。如果年龄和服务年限是 int 类型,它们将被返回并设置为我们的对象中的属性。如果它们不是 int 类型,将引发类型错误异常。

使用 staticmethod 装饰器的一个好处是它的可重用性。例如,如果我们在 init 方法中添加了一个 annual bonus 参数,我们可以简单地再次调用 staticmethod decorator 并将 bonus 作为参数传递。

示例 3:使用自定义装饰器

另一种控制属性值的方法是通过一个自定义装饰器。为了与我们的主题保持一致,让我们创建同一个类,但是这次用一个名为 attr_check 的函数来修饰 init 构造函数方法。

当我们创建 Employee 类的实例时,init 方法将被自动调用。当 attr_check 函数修饰 init 方法时,将调用这个函数。attr_check 将 init 方法作为参数,并返回 inner。当我们用我们的对象 ref、age 和 service 调用 inner 时,我们可以对 age 和 service 执行类型检查。如果年龄和服务的类型是 int,我们将返回带有对象、名称、年龄和服务以及参数的原始 init 方法。

这个实现是用 Python 控制属性值的好方法,因为我们可以选择什么进入 inner 的主体。在这种情况下,我们没有对姓名执行任何类型检查,也没有对年龄执行任何范围限制,但是我们可以通过扩展内部函数中定义的代码来简单地添加这些检查。

示例 4:使用@property/setter/deleter 装饰器

Python 中控制属性值的另一种方法是使用属性装饰器及其相应的 setter 和 deleter 方法。

让我们再次创建我们的雇员类。当用户试图通过 object.attribute 语法访问 name 属性时,将用@property 修饰的 name 方法将被调用,名称将以大写形式返回。

这一次,如果用户想要更改 name 属性,让我们确保他们输入的任何字符串都是大写的。我们可以通过定义一个简单的 name 方法以及相应的 setter 和 deleter 方法来实现这一点。

我们定义了 name 方法,并用@name.setter 修饰它。当用户想要使用 object.attribute 语法设置一个新名称时,对象中设置的新名称现在将被大写。

注意,名称属性’ _name '的基础名称不同于方法的名称,以避免递归错误。我们不能在 setter 方法的主体中包含 self.name = new_name.title()。

示例 init 构造函数中的条件检查

结束这篇关于属性控制的文章,实现属性完整性的最简单的方法实际上可能是在类本身的 init 构造函数中包含条件检查。这里,我们允许员工的年龄大于或等于 18 岁,小于或等于 100 岁。如果满足条件,我们可以将 init 方法中作为参数提供的年龄设置为对象中的属性值。当创建的实例不满足此条件时,将引发 AttributeError 异常,并通过一条有用的字符串消息通知用户所需的条件。

摘要

感谢您的阅读,我希望您喜欢控制属性访问及其值的不同方式。虽然我主要关注的是数据类型检查和范围允许,但是任何可以想象到的条件都可以施加在属性值上。电子邮件地址在设置前可能会使用 regex 进行验证,以符合数据完整性。

我在这里特意使用了一些基本的例子来帮助传达控制属性值和访问的多种方法是如何工作的。此外,描述符是 Python 中管理属性的另一种方式,我希望能写一篇关于如何使用它们的教程。如果你有任何问题,或者想要更多关于这个主题的文章,请通过 LinkedIn 告诉我。

让你的百万美元实验失败的 5 种方法

原文:https://towardsdatascience.com/5-ways-to-fail-your-million-dollar-experiments-da7647e5ba30?source=collection_archive---------35-----------------------

实验和因果推理

A/B 测试方式正确

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上由 Keyur Nandaniya 拍摄的照片

产品发布前的实验已经成为大型科技公司的一个固有部分(例如,和 Airbnb )。俗话说,没有对你的客户进行 A/B 测试,就不能做出任何商业决策。

真的!

业务实验提供了丰富的客户行为信息,帮助我们更好地理解客户思维和行为之间的差距。

人们的想法和行为不同。通常,他们告诉你一件事,却做了相反的事情。

不做实验,就无法知道顾客对新产品的反应。这就像盲人测量大象的大小:我们没有得到完整的画面。

像任何研究方法一样,实验方法也有缺点和假设,但即使假设被违反,行业人士也经常使用它。如果这种情况发生(不幸的是),我们可能会面临最不可取的情况:用虚假证据做出决策。

虚假信息比没有证据更糟糕。

如果没有信息,我们不会做出决定,但是错误的信息会导致错误的决定。在今天的帖子中,我详细阐述了可能会毁掉你价值数百万美元的实验的五个常见错误,以及每种情况下的应对策略

我已经写了几篇关于商业实验的文章。来看看吧: 为什么实验自然实验**,还有 做了 )。****

因果推理和实验

在这里,我会试着给你一个关于因果推断&实验的概述,以及为什么它很重要。在日常工作中,我们会问自己这样的问题:“新的用户界面增加了 DAU 吗?”“是什么因素导致了下一个百万注册?”

因果推理是追溯根本原因并评估其对相关结果的影响的过程

通过保持其他因素不变,同时每次只改变一个变量,实验可以帮助我们找到因果关系。如果不能随机赋值,数据科学家可以选择准实验(五招)和观察方法(如配对、倾向评分匹配)做因果推断。

简单来说,因果推断始于可比的实验组,止于差异化的结果。首先,如果实验组(治疗组和对照组)不相等,那么研究设计就是有缺陷的。

让我们深入研究主菜。

1.仔细选择你的度量标准

数据科学家需要建立一个度量标准来衡量我们实验的性能,一个糟糕的度量标准可能会扼杀实验。

例如,一家零售公司的季度销售数据滞后,但管理团队仍然希望通过大规模促销来实现既定目标。

数据团队提出了一个实验设计,表明 50%的折扣可以达到目的。你应该按计划推出促销活动吗?

大概,不是!

促销可能会增加短期指标,但会降低长期利润,因为客户会购买他们现在需要的所有东西,并且不会很快再次购买。

选择有效的指标和你的研究设计本身一样重要。最不希望看到的就是各个板块之间的自相残杀。

该怎么办?

  • 与主要的商业利益相关者合作,提出主要和次要的利益衡量标准
  • 了解选择的权衡
  • 如有必要,在实验之前、之中和之后,回到指标上来
  • 根据经验,实验讲述了一个关于短期指标的好故事,但是在长期性能方面有所欠缺

2。有问题的实验设计

如上所述,数据科学家需要检查实验组在关键协变量方面是否具有可比性(“同类比较”)。否则,结果可能不成立。

某些设计在业内广受欢迎,但不适用于因果推理。其中,一组前后对比设计治疗组和非治疗组设计脱颖而出!

下面分别是这两种设计的两个例子。在推出新的用户界面后,我们看到一些指标(如 DAU)有所提高,所以更新版本是正确的选择。与对照组相比,治疗组带来了更多的收入,因此治疗有效。

这些设计不提供“苹果对苹果”的比较!治疗组可能与对照组根本不同,这使得任何直接的比较都成问题。这是因果推理中的一个典型问题,叫做选择偏差

此外,没有办法排除其他解释的可能性。例如,除了 UI 更新之外,还有其他重大变化。

该怎么办?

  • 与工程团队一起检查数据的可用性。
  • 治疗组与对照组相似吗?如果没有,你采取了什么措施?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

乔治·贝尔在 Unsplash 上的照片

3。过早结束你的实验

我们仔细选择了反映商业利益的指标,并有意使实验组具有可比性。令人惊喜的是,指标出现了正增长。我们现在可以结束实验了吗?

当有积极的发现时,这样做是很有诱惑力的。顺便说一句,这是一个常见的认知谬误——人类倾向于确认我们所期待的。

不过,我的建议是等一等,看看结果“ 是否回归均值。 “指标的正跳可能只是一个小故障,稍过一会儿就会消失。

做什么?

  • 获得初步结果后继续运行
  • 这里有一个窍门:在数据有限的情况下,我们可以通过分配和取消来创造更多的数据点。多次重复该过程
  • 检查治疗组和对照组如何随时间变化

4。溢出效应和污染

这里,关键问题是:治疗组是否与对照组接触?如果是这样,结果可能会被溢出效应所污染。

假设,实验随机分配治疗给住在附近的个人用户。治疗组和对照组可能会互相交谈,而对照组会无意中接受治疗。

第四个错误和最后一个密切相关,后面可以看出来。

该怎么办?

  • 与您的工程团队交流:您可以在什么级别上随机化您的处理(例如,用户级别、城市范围、URL)?
  • 你的实验小组互相合作吗?如果是这样,改变随机分配的级别。

5.随机化不那么随机

对于 A/B 测试和任何其他采用随机化的实验设计,数据科学家应该问的首要问题是:这真的是随机分配吗?

这听起来很矛盾,但是一个随机的过程并不能保证一个随机的赋值!

有一些外部因素导致一些群体比其他群体更有可能参与治疗组。

与前一点相关,在个体 URL 的随机化过程可能是不可行的交叉污染 b/c。那么,我们将选择市级随机化。

仔细想想最低级的随机分配。

该怎么办?

  • 这是一个具有挑战性的问题!它涉及到对实验平台的透彻理解,并能够区分细微的差别。
  • 单位层面随机化?网址?市级?
  • 你的工程团队更了解什么是可能的,什么是不可能的。

结论

这篇文章涵盖了实验失败的五种主要方式:度量、研究设计、时机、溢出和随机化。古语有云:细节是魔鬼!数据科学家应该在推出实验时检查这五个常见错误。

喜欢读这本书吗?

请在 LinkedInYoutube 上找到我。

还有,看看我其他关于人工智能和机器学习的帖子。

新冠肺炎时代提高数据科学技能的 5 种方法

原文:https://towardsdatascience.com/5-ways-to-improve-your-data-science-skills-in-the-time-of-covid-19-409ba813178a?source=collection_archive---------26-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上由 niklas_hamann 拍摄的照片

*** 披露:下面的一些链接是附属链接,意思是,在没有额外费用的情况下,如果你点击,我会赚取佣金。请记住,我链接这些产品是因为它们的质量。我是一个独立的博客作者,评论是根据我自己的观点完成的。***


世界性的新冠肺炎疫情造成了一个前所未有的、紧张的、不确定的时代。这个世界被完全封锁了,我们都必须尽自己的一份力量,通过练习负责任的社交距离和尽可能待在室内来互相帮助。在目前的情况下,很容易感到不知所措,在新的日常工作中保持高效的感觉会非常困难。

就我个人而言,自从我在家工作以来,我一直在努力将我的“在家工作时间”和“个人时间”分开,这导致我的工作/生活平衡严重倾向于“工作”方面。当我想转换工作模式时,我最喜欢做的事情是在布鲁克林的街区散步,在公园里看书,或者去当地的咖啡店。因为那已经不可能了,我不得不延长工作时间,因为我一直觉得我做得不够。我的个人时间缺乏目标,这促使我重新评估我想如何度过它。隔离让我有时间思考我的职业道路,以及在这场危机结束后,我现在可以做些什么来更好地定位自己,以实现这些目标。

在这个不确定的时刻,有一件事我可以肯定地说:有这种感觉的不止我一个人。这种幽居病的压抑感正在影响着世界上的每一个人。这段时间我一直记得的一个建议是‘控制可控的。这个世界充满了太多我们无法控制的事情,所以重要的是不要不知所措,把注意力放在日常生活中你可以控制的事情上。你能控制的一件事就是每天提高和投资自己!

我为那些有空闲时间并希望推动自己学习新的数据科学技能或温习现有技能的人创建了这个博客。我希望这能让你分心或者鼓励你好好利用你的额外时间!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

艾玛·马修斯数字内容制作在 Unsplash 拍摄的照片

1.通过在线课程学习新的数据科学技能

学习一项新技能最难的部分是知道如何以及从哪里开始。好消息是,有大量的在线课程材料和资源是面向自主学习者的(比如你!).有在线教程和讲座可以学习特定的数据科学工具或更广泛的概念。

以下是众多可用资源中的几个:

骏马

  • 优点:我喜欢 Coursera 的一点是,它提供了大量不同编程语言的免费课程。解释往往非常清晰简洁。也倾向于通过例子和练习来真正掌握概念。
  • **缺点:**反馈和问题评审可能会很慢/延迟,这会令人沮丧。

  • 优点:这里有很多价格低廉(大约 10 美元)的课程可供选择,你可以按照自己的进度进行。
  • ***缺点:*任何人都可以发布课程,所以请确保你选择的课程是由你正在寻找的领域的专家创建的。考之前一定要看班级的评分。

领英学习

  • 优点: Linkedin Learning 是一个易于使用的网站,你可以直接连接到你的 Linkedin 个人资料,这样你就可以跨平台分享你的技能和兴趣。
  • 缺点:这些课程往往主要面向初学者,因此可能没有太多面向高级数据科学家的课程。还缺乏认证,这有点令人失望,因为 Linkedin Learning 是一个付费服务提供商(每月约 30 美元)。

data camp

  • 优点: DataCamp 创建的唯一目的是在线学习数据科学。这个平台在一个易于使用的网站上提供了各种各样的优质内容。定价也是透明的,并提供了多种方案选择。
  • 缺点:大部分内容都是非常沉重的文字,这可能会令人沮丧,尤其是对初学者来说。一些评论指出,这些课程可能有点“手把手”,没有提供足够的练习问题。

无论如何,这些都不是唯一的资源!如果你预算紧张,YouTube 上还有大量免费的数据科学频道,这样你就可以开始学习了!

2.博客

如果你知道你很难理解某个主题或概念,可以在 Medium、Towards Data Science、Analytics Vidhya 等网站上寻找其他数据科学家的博客。你一定会找到一个或多个博客,在 10-15 分钟内清晰简明地解释令人困惑的概念。

如果你真的想挑战自己,我强烈建议你就自己不熟悉的概念写自己的数据科学博客。通过阅读写作过程,它将帮助你更完整地掌握主题方式,从而能够将它传授给其他人。我个人认为这是一个非常有用的方法,虽然很费时间,但却非常有价值,因为当你完成它时,你会有成就感,这也是你可以添加到你未来求职的文件夹中的东西。成为一名博客写手显示了你的创新精神,让招聘人员看到你是如何将复杂的概念传达给更广泛的受众的,这是一项非常有价值的技能!

3.数据科学书籍

在数据科学家教育旅程的各个不同阶段,他们都可以获得大量易于理解且信息量极大的阅读材料。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由王思然·哈德森Unsplash 上拍摄

适合初学数据的科学家:

  • 查尔斯·惠兰著 裸统计——这是一本快速有趣的读物,向你介绍统计学的重要性,并使用数学概念的真实例子。对于刚开始接触数据科学领域的人来说,这是一本非常棒的入门书籍!**
  • Think Stats:Probability and Statistics for Programmers作者 Allen B. Downey- 这是一本学习简单有用的 Python 技术来探索真实世界数据的好书。
  • 数据科学从零开始作者 Joel Grus —这一篇对于完全的初学者来说非常棒。这本书甚至不需要 Python 背景!

对于中级数据科学家:

  • 用于数据分析的 Python作者 Wes McKinney——这是一本向你展示像 NumPy 或 pandas 这样的标准 Python 库的来龙去脉的书。
  • Jake VanderPlas 撰写的 Python 数据科学手册——是一个全面的伟大指南,它介绍了使用的标准 Python 库,如 NumPy、pandas、Scikit-learn 和 Matplotlib。

针对高级数据科学家:

  • 深度学习用 Python 作者 Francois Chollet——Francois Chollet 是 Keras 的创建者,Keras 是 Python 中使用最广泛、最流行的机器学习库之一。这本书是希望利用深度学习的数据科学家的必要读物。
  • 深度学习 由伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔编写- 由该领域三位专家撰写的深度学习综合教材。

4.练习技能

得到一份数据科学家的工作最令人生畏的部分之一是通过技术面试。是时候投入一些时间来温习获得新工作所必需的技术编码技能了!每天只需投入半小时到一小时的练习,你就可以成倍地提高你的自信和编码技能。以下是练习所有不同编程语言的一些资源:

  • hacker rank—是一个来自世界各地的程序员聚集在一起解决广泛的计算机科学领域(如算法、机器学习或人工智能)的问题,以及实践不同编程范式(如函数式编程)的地方。
  • exercim . io——这个平台有 50 种不同的编码语言可供选择!您可以完成不同的编码挑战,并上传您的解决方案供导师审阅。这是学习新技术和新思想的好方法。
  • top coder——是最早上线的竞争性编码平台之一。还有文章和论坛帮助你学习新技能!
  • leet code——提供你可以直接解决的编码挑战。这个平台还有一个“模拟面试”部分,为你下一次工作面试做准备!

如果你正在准备技术面试,并且有更多的时间,Udacity 的 【数据科学面试准备】 等课程都是免费在线提供的。

5.开始一个副业

在我看来,没有比完成兼职项目更好的方法来提高您的数据科学知识或技能。我个人最喜欢的是Kaggle。Kaggle 是一个在线数据科学平台,为数据科学家、数据矿工和统计学家举办预测建模和分析比赛。公司和研究人员发布来自所有不同领域的数据集,人们争夺最佳的探索性数据分析和预测模型。Kaggle 是学习真实世界数据的绝佳资源。它还允许您查看其他数据科学家的笔记本以及他们如何处理数据!这对于那些没有该领域背景,但希望深入了解数据分析背后的思维过程的人来说非常有帮助。它也是一个社区,人们可以在这里提出建设性的批评或新的想法,以创建最佳的可能模式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

法比安·格罗斯在 Unsplash 上拍摄的照片

启动您自己的项目的其他数据资源有:

五三八

UCI 机器学习知识库

Data.gov

谷歌公共数据集

这些只是数据科学家可以公开获得的众多资源中的一小部分。只需选择一个数据集,然后开始行动!这是您建立数据科学技能和项目组合的绝佳机会,您可以在下次面试时谈论/展示这些技能和项目!通过参加数据科学竞赛或独立完成兼职项目,这表明您在个人生活中拥有不断学习和改进的主动性和动力。


谢谢你花时间阅读我的博文!

我祝你在不断提高自己的旅途中好运,我希望你在进入明天的时候知道你已经比前一天做得更好了!

本帖引用:

  1. https://www.coursera.org/
  2. https://www.udemy.com/
  3. https://www.linkedin.com/learning/me
  4. https://www.datacamp.com/
  5. https://www . Amazon . com/Naked-Statistics-Stripping-Dread-Data-ebook/DP/b 007 q 6 xlf 2
  6. https://www . Amazon . com/Think-Stats-Allen-B-Downey/DP/1449307116
  7. https://www . Amazon . com/Data-Science-Scratch-Principles-Python/DP/149190142 x
  8. https://www . Amazon . com/Python-Data-Analysis-Wrangling-IPython/DP/1449319793
  9. https://www.amazon.com/gp/product/1491912057/ref=as_li_tl?ie = UTF8&camp = 1789&creative = 9325&creative asin = 1491912057&link code = as2&tag = petacrunch-20&linkId = 3882 a 97 FD 104467 b 624 bad 3 e 5 ff 5431 b
  10. 【https://www.amazon.com/gp/product/1617294438/ref=as_li_tl? ie = UTF8&camp = 1789&creative = 9325&creative asin = 1617294438&link code = as2&tag = petacrunch-20&linkId = fa 7304 c 5324 df 649 a4ba 536 BD 74927 D2
  11. https://www . Amazon . com/Deep-Learning-Adaptive-computing-Machine/DP/0262035618
  12. https://www.hackerrank.com/dashboard
  13. https://exercism.io/
  14. https://www.topcoder.com/challenges/?pageIndex=1
  15. https://leetcode.com/
  16. https://www.kaggle.com/
  17. https://fivethirtyeight.com/
  18. http://archive.ics.uci.edu/ml/index.php
  19. https://www.data.gov/
  20. https://cloud.google.com/public-datasets

使用 JavaScript 查询关系数据库的 5 种方法

原文:https://towardsdatascience.com/5-ways-to-query-your-relational-db-using-javascript-d5499711fc7d?source=collection_archive---------4-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片在 Shutterstock.com和 T2的许可下使用

如果您正在开发 web 应用程序,您几乎肯定会不断地与数据库进行交互。当需要选择方式互动时,选择会让人不知所措。

在本文中,我们将详细探讨使用 JavaScript 与数据库交互的 5 种不同方式,并讨论每种方式的优缺点。我们将从最底层的选择——SQL 命令——开始,然后进入更高层的抽象。

为 JavaScript 应用程序选择正确的数据库库会对代码的可维护性、可伸缩性和性能产生很大的影响,所以花一些时间来找出您的选择是值得的。

我们的示例应用程序

我们将使用一个托管在 Heroku 上的普通 Express 应用程序作为例子。本文的所有代码都在这个 GitHub 库中。随意克隆它并跟随它。

先决条件

要运行示例应用程序,您的机器上需要以下软件:

  • 一个类似 unix 的终端环境(Mac OSX 和 Linux 都可以。如果你使用的是 Windows,你将需要用于 Linux 的 Windows 子系统
  • git (还有一个 github 账号)。
  • npm (版本 6 或更高版本)。
  • Heroku 命令行工具

如果你还没有 Heroku 账户,你需要注册一个免费账户。如果你不想注册 Heroku,你也可以在本地 Postgres 实例上运行应用程序。如果您对此感到满意,应该很容易看到您需要做哪些更改,而不是部署到 Heroku。

一旦你安装了以上所有的东西,在终端中运行heroku login,你就可以开始了。

构建和部署 Hello World 应用程序

首先,我们将设置以下内容:

  • 一个普通的 Express 应用程序,只提供一个“Hello,World”网页。
  • 一个 Postgres 数据库。
  • 两个表,分别代表“用户”和“评论”(一个用户有很多评论)。
  • 一些样本数据(在这种情况下,通过mockaroo.com生成)。

我已经创建了一个示例应用程序,它将为您设置所有这些(假设您已经如上所述运行了heroku login)。要设置它,请从命令行执行以下命令:

git clone [https://github.com/digitalronin/query-database-javascript.git](https://github.com/digitalronin/query-database-javascript.git)

cd query-database-javascript make setup

这需要几分钟才能完成。在您等待的时候,您可以查看 makefile 来查看相关的命令,这些命令执行以下操作:

  • 创建一个新的 Heroku 应用程序。
  • 添加 Postgres 数据库实例。
  • 将应用程序部署到 Heroku。
  • 在 Heroku 上运行一个命令来设置数据库表并导入 CSV 示例数据。
  • 在新的浏览器窗口中打开 Heroku 应用程序的 URL。

在此过程结束时,您应该会在网页上看到“Hello,World”。

使用 SQL 提取数据

好了,我们都准备好了!我们已经创建了一个包含两个表和一些示例数据的数据库。但是我们还没有做任何事情。下一步是让我们的 web 应用程序能够从数据库中检索数据。

无论何时与关系数据库交互,都是通过向数据库正在监听的网络套接字发送 SQL 命令来实现的。对于本文中我们将要研究的所有库来说都是如此——在最底层,它们都向数据库发送 SQL 命令,并检索返回的任何输出。

因此,我们要考虑的与数据库交互的第一种方式就是这样做——发送 SQL 命令。为此,我们将安装 pg JavaScript 库,它允许我们向 Postgres 数据库发送 SQL 并检索结果。

要安装 pg 库,请执行以下命令:

npm install pg

这将获取并安装这个库,并将它添加到 package.json 和 package-lock.json 文件中。让我们提交这些更改:

git add package.json package-lock.json git

commit -m "Install the pg library"

要与我们的数据库对话,我们需要一些详细信息:

  • 运行 Postgres 的机器的主机名。
  • Postgres 正在监听的网络端口。
  • 我们的数据所在的数据库的名称。
  • 有权访问数据的用户名和密码。

大多数数据库库会让我们建立一个连接,要么通过向库中提供一个对象,该对象包含所有这些细节的键和值,要么通过将它们组合成一个“数据库 URL”,这就是我们将要做的。

当您向 Heroku 应用程序添加数据库时,您会自动获得一个名为 DATABASE_URL 的环境变量,其中包含连接数据库所需的所有详细信息。您可以通过运行以下命令来查看 DATABASE_URL 的值:

heroku config

这将输出您的应用程序可以使用的所有环境变量。现在应该只有一个,所以您应该在输出中看到类似这样的内容:

数据库 _ 网址:postgres://clqcouauvejtvw:1b079cad50f3ff9b48948f15a7fa52123bc6795b875348d668864
07a266c0f5b@ec2-52-73-247-67.compute-1.amazonaws.com:5432/dfb3aad8c026in

在我们的例子中,分解如下:

结构化查询语言

{"hostname": "ec2-52-73-247-67.compute-1.amazonaws.com", "port": 5432, "database": "dfb3aad8c026in","username": "clqcouauvejtvw","password": "1b079cad50f3ff9b48948f15a7fa52123bc6795b875348d66886407a266c0f5b"}

您的 DATABASE_URL 值会有所不同,但结构是相同的。

现在我们已经安装了 pg 库,并且我们知道如何连接到我们的数据库,让我们执行我们的第一个与数据库交互的例子。我们将简单地获取用户列表,并将它们显示在我们的网页上。在 index.js 文件的顶部,我们需要 pg 库,并创建一个数据库连接对象。

Java Script 语言

const { Pool } = require('pg');const conn = new Pool({ connectionString: process.env.DATABASE_URL });

express()块中,我们将修改 get 行来调用显示数据库中用户列表的方法:

.get('/', (req, res) => listUsers(req, res))

最后,我们将实现 listUsers 函数:

Java Script 语言

async function listUsers(req, res) {try {const db = await conn.connect()const result = await db.query('SELECT * FROM users');const results = { users: (result) ? result.rows : null};res.render('pages/index', results );db.release();} catch (err) {console.error(err);res.send("Error " + err);}}

这段代码一直等到与我们的数据库建立了连接,然后使用 query 函数发送一个 SQL 查询并检索结果。

现在,这一步可能由于许多不同的原因而失败,所以在代码中,我们进行测试以确保我们获得了一些数据,如果我们获得了一些数据,我们就将 result.rows 分配给 results 对象的关键用户。接下来,我们将结果传递给 render 函数,然后释放数据库连接。

在 views/pages/index.ejs 中,我们可以访问结果对象,因此我们可以像这样显示我们的用户数据:

超文本标记语言

<h1>Users</h1><ul><% users.map((user) => { %><li><%= user.id %> - <%= user.first_name %> <%= user.last_name %></li><% }); %></ul>

你可以在这里看到这些变化的代码 first_namelast_name是我们数据库的 users 表中两列的名称。

让我们部署这些更改,这样我们就可以在 Heroku 应用程序中看到数据:

git add index.js views/pages/index.ejs

git commit -m "Display a list of users"

git push heroku master

这将需要一两分钟来部署。当该命令执行完毕后,重新加载您的浏览器,您应该会在网页上看到一个用户列表。

MySQL 示例

上面的例子是针对 Postgres 的,但是针对其他常见关系数据库的代码也是类似的。例如,如果您使用的是 MySQL :

  • 使用npm install mysql2而不是npm install pg(使用 mysql2,而不是 MySQL——MySQL 2 更快并且支持异步/等待)
  • 在 index.js 中,您需要 mysql,如下所示:

const mysql = require('mysql2/promise');

  • listUsers 函数如下所示:

Java Script 语言

async function listUsers(req, res) {try {const conn = await mysql.createConnection(process.env.DATABASE_URL);const [rows, fields] = await conn.execute('SELECT * FROM users');const results = { 'users': rows };res.render('pages/index', results );await conn.end();} catch (err) {console.error(err);res.send("Error " + err);}}

视图/页面/索引. ejs 保持不变。

您可以在这里看到带有这些变化的示例项目

现在,让我们研究几个构建在这个基础之上的库,它们添加了抽象层,让您能够以更“类似 JavaScript”的方式读取和操作数据库数据。

到目前为止,我们已经看到了如何将原始 SQL 发送到数据库;像这样的陈述:

SELECT * FROM users

如果我们想得到某个特定用户的评论,比如说 id 为 1 的用户,我们可以使用这样的代码:

SELECT * FROM comments WHERE user_id = 1

以这种方式与您的数据库进行交互没有任何问题,但是可能会感觉有点麻烦,并且需要您在心理上保持“换档”。您用一种方式考虑您的 JavaScript 代码,但是当您需要考虑数据库中的数据时,您必须开始用 SQL 来考虑。

我们要考虑的其余数据库库的目的是让您将数据库中的数据处理得更像应用程序中的 JavaScript 对象和代码。“在引擎盖下”都是 SQL,但是你不需要太在意这些,除非你想。

Knex —抽象出 SQL

我们要讨论的第一个库是 Knex 。文档页面将 Knex 描述为“查询构建器”,其目的是在原始 SQL 之上提供一个抽象层。

安装 Knex

Knex 需要 pg(或者 MySQL,如果您使用 MySQL 数据库的话)。我们已经安装了 pg,所以我们只需像这样添加 knex:

npm install knex

git add package.json package-lock.json

git commit -m "Install the knex library"

使用 Knex

knex 的 NPM 页面将其描述为“查询生成器”Knex 在一定程度上抽象了 SQL,但不是很远。我们仍然需要理解底层的 SQL,但是我们可以用更像 JavaScript 的语法来编写它,而不是将 SQL 字符串分割成小块。更重要的是,我们可以用一种对 JavaScript 程序员来说更舒服的方式使用组合来链接 knex 术语。

所以,当我们使用 pg 时,我们有这样的声明:

const result = await db.query('SELECT * FROM users');

当我们使用 knex 时,我们可以这样写:

const result = await db.select().from('users');

这可能看起来没有太大的区别,但是由于我们可以编写 knex 函数调用的方式,我们也可以这样做:

const result = await db.select().from('users').limit(5).offset(8);

这里,我们得到了 5 个用户记录,从匹配我们查询的所有可能用户记录的第 8 个位置开始。您可以在 knex 文档中看到全套可用选项。

让我们将 Express 应用程序改为使用 knex 来显示数据库中的一些记录。首先,在 index.js 中替换这两行:

Java Script 语言

const { Pool } = require('pg');
const conn = new Pool({ connectionString: process.env.DATABASE_URL });

…有了这个:

Java Script 语言

const db = require('knex')({
client: 'pg',
connection: process.env.DATABASE_URL
});

然后,将listUsers的实现改为:

Java Script 语言

async function listUsers(req, res) {
try {
const result = await db.select().from('users').limit(5).offset(5);
const results = { 'users': (result) ? result : null};res.render('pages/index', results );
} catch (err) {
console.error(err);res.send("Error " + err);
}
}

我们的 views/pages/index.ejs 文件可以保持和以前完全一样。

提交、推送和部署:

git add index.js

git commit -m "Use knex to display user data"

git push heroku master

当您刷新浏览器时,应该会在页面上看到用户记录 6 到 10。

你可以在这里看到修改后的代码

对象关系映射

Knex 为我们提供了一种与数据库交互的方式,这更像 JavaScript,但是当我们需要操作数据时,仍然需要以数据库为中心进行思考。

接下来我们要讲的三个库都是建立在 knex 之上的(knex 是建立在 pg 或者 MySQL 之上的),是“对象关系映射”或者 ORM 库的例子。顾名思义,ORM 库的目的是在关系数据库中的数据和应用程序中的 JavaScript 对象之间进行转换。这意味着,当您编写 JavaScript 代码时,不用考虑 users 表中的记录,您可以考虑用户对象。

反对

我们要看的第一个库是 objection ,它构建在 knex 之上:

npm install objection

git add package.json package-lock.json

git commit -m "Install the objection library"

为了突出 ORM 库的一些效用,我们将修改我们的应用程序来显示用户和他们的评论。Objection 构建在 knex 之上,因此在我们的 index.js 文件中,我们必须保留 knex 块,并添加更多的代码(为了简单起见,我将所有内容都放在 index.js 文件中。在真实的应用程序中,您会将代码分成单独的文件):

const { Model } = require('objection');

Model.knex(db);

这给了我们一个模型类,我们可以继承它来定义两个类 User 和 Comment。我们将首先定义注释:

Java Script 语言

class Comment extends Model {static get tableName() {
return 'comments';
}
}

我们的类需要扩展Model,并且必须实现一个tableName函数来告诉 Objection 哪个数据库表包含底层记录。

User类是类似的,但是我们要给我们的类添加一些行为;一个fullName函数,我们可以在视图模板中使用它。我们还将告诉异议Users拥有Comments(即用户拥有零个或多个评论)。用 ORM 的话来说,这通常被描述为“有许多关系”——即一个用户有许多评论。下面是它的代码:

Java Script 语言

class User extends Model {static get tableName() {
return 'users';
}fullName() {
return `${this.first_name} ${this.last_name}`;
}static get relationMappings() {return {
comments: {
relation: Model.HasManyRelation,
modelClass: Comment,
join: {
from: 'users.id',
to: 'comments.user_id'
}
}
};
}
}

我们在我们的User类中定义了一个relationMappings对象,用一个注释键和一个值告诉异议这是Comment类上的一个HasManyRelation,其中 users 表的 id 列的值与 comments 表的 user_id 列的值相匹配。

现在我们已经定义了我们的类,让我们在代码中使用它们。下面是listUsers的新实现:

Java Script 语言

async function listUsers(req, res) {try {
const users = await User.query().limit(5);for (i in users) {
const user = users[i];
user.comments = await User.relatedQuery('comments').for(user.id);
}const results = { 'users': users };res.render('pages/index', results );
} catch (err) {
console.error(err);res.send("Error " + err);
}
}

在这里,我们获取 5 个用户,然后对于每个用户,我们获取他们的评论,并将其分配给用户对象的 comments 属性。在 views/pages/index.ejs 中,我们可以像这样显示我们的用户及其评论:

超文本标记语言

<h1>Users</h1>
<ul>
<% users.map((user) => { %>
<li><%= user.id %> - <%= user.fullName() %></li>
<ul>
<% user.comments.map((comment) => { %>
<li><%= comment.body %></li>
<% }); %>
</ul>
<% }); %>
</ul>

你可以在这里看到修改后的代码像往常一样,提交并推送部署:

git add index.js views/pages/index.ejs

git commit -m "Show users and comments using Objection"

git push heroku master

现在,当您重新加载页面时,您应该会看到用户和评论。

“N+1 选择”问题

这段代码强调了人们在使用 ORM 库时遇到的一个常见问题,称为“N+1 选择”问题。

这是我们用来获取用户及其评论的代码块:

Java Script 语言

const users = await User.query().limit(5);for (i in users) {
const user = users[i];
user.comments = await User.relatedQuery('comments').for(user.id);
}

这是可行的,但是效率很低。首先,我们获取 5 个用户,然后对于这 5 个用户中的每一个,我们通过再次调用数据库来获取他们的评论*。因此,我们为用户打了 1 个电话,然后又打了 5 个电话来获取评论。这是 5 次呼叫加上前 1 次,即 5+1 或 N+1,其中 N == 5。因此出现了“N+1 选择”问题。*

除非数据库查询非常复杂,否则往返调用数据库所需的时间要比数据库计算和传输查询结果所需的时间长得多。因此,为了保持应用程序的速度,我们需要尽可能减少对数据库的调用。上面的代码与此完全相反。

对于这个微不足道的例子,您不会注意到任何差异,但是对于真实世界的应用程序,性能影响可能非常严重,并导致许多问题。

幸运的是,每个 ORM 库都有可以轻松避免这个问题的特性(前提是你知道它的存在)。以下是异议是如何做到的:在 index.js 中,将上面的代码块替换为:

const users = await User.query().limit(5).withGraphFetched('comments');

这一行代码与上面的代码块做的一样,但是以一种更加高效的数据库方式。Objection 将使用我们提供的关系信息来确定如何在单个查询中获取用户数据和评论数据,并将结果解包并缝合到我们在使用 for 循环之前构建的同一对象结构中。

你可以在这里看到修改后的代码

书架

我们要看的下一个 ORM 库是书架

ORM 库之间的许多差异取决于库针对什么用例进行了优化。在 Bookshelf 的例子中,它的设计显然是为了尽可能容易地呈现数据的分页列表,这在 web 应用程序中是一个非常常见的用例。

让我们在应用程序中将异议替换为书架:

npm uninstall objection

npm install bookshelf

git add package.jsonpackage-lock.json

git commit -m "Replace Objection with Bookshelf"

在 index.js 中,替换这些行:

Java Script 语言

const { Model } = require('objection');
Model.knex(db);

…有了这个:

Java Script 语言

const bookshelf = require('bookshelf')(db);

用这些替换我们的类定义:

Java Script 语言

const Comment = bookshelf.model('Comment', {
tableName: 'comments'
});const User = bookshelf.model('User', {
tableName: 'users',comments() {
// by default, bookshelf infers that the foreign key is 'user_id'
return this.hasMany('Comment');
}});

我们的listUsers函数现在看起来像这样:

Java Script 语言

async function listUsers(req, res) {
try {
const models = await new User()
.fetchPage({
pageSize: 5,
page: 1,
withRelated: ['comments']
});users = [];models.map(m => {
const user = m.attributes;
const comments = m.related('comments');user.comments = comments.map(c => c.attributes);
users.push(user);
});const results = { 'users': users };res.render('pages/index', results );
} catch (err) {
console.error(err);
res.send("Error " + err);
}
}

正如您所看到的,类的定义更简洁一些,但是 Bookshelf 需要一个更详细的定义来说明如何解包我们的数据以构建用户/评论结构。还要注意数据页面的概念是如何直接构建到库的 API 中的。

views/pages/index.ejs 中的代码几乎相同(我已经从 User 类中删除了 fullName 函数):

超文本标记语言

<h1>Users</h1>
<ul>
<% users.map((user) => { %>
<li><%= user.id %> - <%= user.first_name %> <%= user.last_name %></li>
<ul>
<% user.comments.map((comment) => { %>
<li><%= comment.body %></li>
<% }); %>
</ul>
<% }); %>
</ul>

你可以在这里看到这些变化的代码。当然,再次提交和部署。

git add index.js views/pages/index.ejs

git commit -m "Show users and comments using Bookshelf"

git push heroku master

序列

我们要看的最后一个库是 Sequelize

Sequelize 对数据的组织方式非常固执己见。如果你遵循它的惯例,你可以写更少的代码,让 Sequelize 为你做很多工作。特别是,Sequelize 有很多特性可以帮助您创建表格,默认情况下,它会按照自己的结构和命名约定来创建表格。

我们一直在使用的数据库的结构并不完全符合 Sequelize 的预期,所以我们需要添加一些额外的配置来允许 Sequelize 使用它。

安装序列

要删除 bookshelf 并安装 sequelize,请运行以下命令:

npm uninstall bookshelf

npm install sequelize

git add package.json package-lock.json

git commit -m "Replace Bookshelf with Sequelize"

使用序列

在 index.js 中,替换这些行:

Java Script 语言

const db = require('knex')({
client: 'pg',
connection: process.env.DATABASE_URL
});const bookshelf = require('bookshelf')(db)

…有了这些:

Java Script 语言

const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize(process.env.DATABASE_URL);

然后,用以下代码替换 User 和 Comment 的类定义:

Java Script 语言

const User = sequelize.define('User', {
first_name: { type: DataTypes.STRING },
last_name: { type: DataTypes.STRING },
email: { type: DataTypes.STRING }
},
{
tableName: 'users',
timestamps: false
}
);const Comment = sequelize.define('Comment', {
body: { type: DataTypes.STRING }
}, {
tableName: 'comments',
timestamps: false
}
);User.hasMany(Comment, { foreignKey: 'user_id' });

注意,我们向sequelize.define传递了两个对象。第一个对象定义了对象的属性,第二个对象包含一些元数据。

在这种情况下,我们告诉 Sequelize,支撑用户类的数据库表称为“users”(默认情况下,Sequelize 会推断该表称为“Users”),而timestamps: false告诉 Sequelize,我们的表没有名为 createdAt 和 updatedAt 的时间戳列。

Sequelize 使得编写为您创建表的代码变得非常容易,当您向数据库写入数据时,它会添加这些时间戳列并相应地设置它们的值。序列文档非常好,有更多关于这方面的内容。

我们传递给 hasMany 的是另一个我们必须告诉 Sequelize 我们没有遵循其惯例的地方。它期望(并将为我们创建)一个名为 UserId 的列,将评论链接到用户。

在我们的listUsers函数中,我们可以替换所有这些代码:

Java Script 语言

const models = await new User().fetchPage({
pageSize: 5,
page: 1,
withRelated: ['comments']
});users = [];models.map(m => {
const user = m.attributes;
const comments = m.related('comments');user.comments = comments.map(c => c.attributes);
users.push(user);
});

…只有这一行:

Java Script 语言

const users = await User.findAll({ include: Comment });

我们还必须在 views/pages/index.ejs 中做一个微小的更改。替换这一行:

<% user.comments.map((comment) => { %>

…与此(区别在于用户。Comments 而不是 user.comments):

<% user.Comments.map((comment) => { %>

你可以在这里看到修改后的代码

git add index.js views/pages/index.ejs

git commit -m "Show users and comments using Sequelize"

git push heroku master

那么哪个选项是最好的呢?

现在,您有了从 JavaScript 应用程序查询关系数据库的 5 种方法。我们从通过 pg/mysql 库的原始 SQL 开始,然后看了 knex 查询构建器,然后转到三个 ORM 库;反对,书架和顺序。

那么,哪一个才是适合你应用的选择呢?

一如既往,视情况而定。使用 ORM 库,您可以做任何您使用查询构建器甚至原始 SQL 不能做的事情。因为一切都是在“幕后”使用 SQL 工作的。这并不奇怪。此外,即使您决定使用 ORM,大多数库仍然会向您提供将原始 SQL 发送到数据库的方法。所以你使用什么样的抽象层次取决于你试图解决的问题,以及你想关注什么样的代码。

如果您大量使用数据库的特性,可能使用复杂的视图或存储过程,您可能会发现使用 knex 或 raw SQL 更容易。但是,对于大多数 web 应用程序来说,ORM 库很可能会通过抽象出表结构并允许您将应用程序数据视为 JavaScript 对象来简化您的工作。

如果你已经决定使用 ORM,选择使用哪个 ORM 库并不总是一目了然的。JavaScript 库的前景是非常动态的。新的库经常被创建,旧的库就不再受欢迎了。做出选择时,请考虑以下几点:

  • 浏览一下库的文档,看看是否清晰全面。然后,决定 API 的组合方式对您是否有意义。不同的库使用不同的方法,您可能会发现其中一种方法比其他方法更适合您的需求和偏好。如果您正在编写使用现有数据库的代码,或者在开发应用程序时创建数据库,这一点尤其正确。
  • 看看图书馆周围的社区。这是很多人都在积极使用的东西吗?如果是这样,如果你需要的话,可能会有很多帮助和建议。一些库也有广泛的插件生态系统,可能是特定的插件让你的生活变得更容易。
  • 一个相关的问题是图书馆的年龄。如果已经有一段时间了,更有可能是发现并修复了常见问题。如果这是一个相对较新的图书馆,你可能需要自己想出更多的东西(如果你喜欢玩新的闪亮的玩具和解谜,这可能是一件好事)。
  • 性能更可能取决于您如何使用库,而不是库本身。但是,如果您绝对必须从应用程序中挤出最后几微秒的延迟,那么使用 SQL 或 knex 在更接近数据库的地方工作会快一点。请注意,这通常是一个很小的好处,代码可维护性的成本很可能高于基准性能的收益。

查询愉快!

学习计算机视觉的 5 种方法

原文:https://towardsdatascience.com/5-ways-you-can-learn-computer-vision-6dae3f312686?source=collection_archive---------16-----------------------

本文列出了一些可以用来学习计算机视觉的方法,这是一个机器学习相关领域。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Alec Favale 在 Unsplash 上的照片

计算机视觉很酷。

别让任何人告诉你不是这样。

我这么说不仅仅是因为我目前是一名计算机视觉工程师,或者因为我获得了计算机视觉硕士学位(显然,我有偏见)。

想象一下你和一些朋友一起吃饭,你的一个朋友说:嘿在这里插入你的名字 ,你在你的工作岗位上做什么。

你回复

“面部识别、身体跟踪、物体探测……詹姆斯·邦德的东西……”。

你的朋友带着纯粹的惊讶和敬畏盯着你。

免责声明:上面的场景很可能不会发生。

但说真的,机器学习(ML)相关领域,如计算机视觉(CV)、数据科学和自然语言处理(NLP),在过去十年中变得相当流行和时尚。

这篇文章将向你展示学习计算机视觉的方法。所以你也可以加入酷俱乐部。

我将强调的方法是我个人用来获得 ML 和 CV 知识的方法。

  1. 获得硕士学位
  2. YouTube 视频
  3. 书籍
  4. 个人项目
  5. 网站
  6. 奖金

如果你熟悉列出的任何一种方法,可以直接跳到不熟悉的部分。

1.硕士学位

获得高级资格证书的价格每年都在上涨,但是在一个新兴领域获得高级学位证书的价值几乎是无价的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Honey Yanibel Minaya CruzUnsplash 上拍摄

我在 2019 年完成了计算机视觉,机器学习和机器人学的硕士学位。如果没有我课程中的机器人部分,我也能完成。然而,事实证明,在三维空间中计算机器人手臂运动学所涉及的数学可以转移到增强现实环境中物体运动的计算。这与我有关,因为我现在在一家专门从事增强现实的公司工作。

我的硕士学位使我能够理解用于物体检测的流行计算机视觉技术背后的理论,如 YOLORCNNs

更重要的是,我发展了一种学术意识和思维方式,这在我目前作为计算机视觉工程师的角色中被证明是有用的。在我的研究中,我阅读了大量关于机器学习和计算机视觉的研究论文。我仍然需要阅读研究论文,理解并运用最先进的方法来解决日常工作中常见的简历问题。

通过硕士学位学习计算机视觉是有用的,原因如下:

  • 专注和专注:花 2 -3 个小时写论文或复习考试提高了我的注意力,因为我只专注于一个特定的主题或目标(在截止日期前完成论文)
  • **学术理解的发展:**无论是在学习期间还是在与 ML 相关的职位上,你都不会停止阅读学术研究论文。
  • 求职时脱颖而出:在就业市场上,没有多少人拥有理学硕士或博士学位,因此获得列出的学位之一可以让你在求职时占上风。
  • 加深对计算机视觉的理解
  • 在我学习期间,我和最聪明的人们在一起,并且和他们中的大多数人保持着联系。我们讨论工作机会、经历、面试技巧,或者分享与 ML 相关的笑话。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习笑话

2.YouTube 视频

我意识到不是每个人都有时间或资金去攻读硕士学位,但是退而求其次,也可能是更便宜的选择是利用互联网。

YouTube 是一个很好的学习平台,我观看热门频道的 ML/CV 内容,以进一步加深我的理解,提高我的实践技能。

这里有几个 YouTube 频道的例子,可以帮助我学习计算机视觉。

3 蓝色 1 棕色

这个频道的内容是首屈一指的,我怎么赞美这个频道的创作者都不为过。

那些熟悉 3Blue1Brown 的人会同意我的说法,他成功地在 15-20 分钟的短视频中教授了大学讲师数小时的课程。

这个频道教会了我机器学习和神经网络的基础知识,并让数学变得简单。

在机器学习中,理解线性代数、微积分和偏微分等主题是必不可少的。研究神经网络时,理解神经网络的基本组件至关重要。

理解诸如反向传播、消失梯度和不同的神经网络结构等概念也很重要。

如果你想对神经网络中发生的过程有一个简单的解释,下面来自 3Blue1Brown 的播放列表是一个必须观看的节目。

斯坦福计算机视觉

在了解了 ML 和神经网络的基础知识之后,您可以深入斯坦福大学的一些学术会议,这些会议解释了一些常见的计算机视觉技术和算法。

这个播放列表为您提供了一步一步的技术学术知识,使图像分类,对象检测,强化学习,等等。

完成此播放列表将为您提供一些关于计算机视觉算法、技术和方法的一般知识,这些算法、技术和方法目前在自动驾驶汽车、面部识别应用等系统中使用。

请务必做笔记,并记住所介绍的关键术语和概念。

深蜥蜴

如果您对神经网络和一些机器学习算法背后的理论和数学有坚实的掌握,您可以继续进行一些实际项目,并使用公共机器学习库(PyTorch)和编程语言 Python 进行编码。

PyTorch 是一个机器学习框架,它为像你我这样的人提供了从我们的笔记本电脑上实现和启动机器学习解决方案和神经网络架构的工具。PyTorch 是大多数研究人员在实现机器学习解决方案时选择的框架。

Python 是一种现代编程语言,在各种与计算相关的学科中占有一席之地,如 web 开发、服务器开发、软件开发等。这种语言很流行,可以用来实现机器学习解决方案。

Deep Lizard 的视频播放列表会逐步带你了解神经网络实现的过程。你将学习到诸如神经网络训练的图形处理器的利用,数据结构(数组和张量);神经网络层;超参数等等。

有了你积累的所有知识,你也许可以开始一个 ML 项目,在这之后,有了获得入门级计算机视觉工作职位的基本知识。

3.书

文章的这一部分包含一些附属链接。

用 Scikit-Learn 动手机器学习,Keras&tensor flow

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Scikit-Learn、Keras 和 TensorFlow 进行机器实践学习

如果你应该购买一本书来为现实环境中的机器学习做准备,那么 Aurélien Géron 的《动手机器学习》是实用机器学习的圣杯。

大多数读者都会接触到这本书或它以前的版本。

这本书包括两部分。

第一部分介绍典型的机器学习概念和技术,如梯度下降,支持向量机,特征工程,等等。第一部分还介绍了 SciKit-Learn ,一个流行的机器学习库,以及一些常见的可视化和争论工具。

这本书的第二部分介绍了卷积和递归神经网络和各种神经架构等概念。书的第二部分介绍 TensorFlow 2 和 Keras。

TensorFlow 是一个流行的机器学习库,支持神经网络的实施,并提供了一套用于常见机器学习任务的工具,如可视化、部署和模型优化。

完成这本书将使你能够用行业标准的工具、框架和库解决常见的计算机视觉问题。

用 Python 进行深度学习

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用 Python 进行深度学习

Fran ois Chollet 的《Python 深度学习》也是类似于前面提到的那本书的两部分。

第一部分介绍了机器学习领域的基础知识。它专注于解释人工智能、深度学习和机器学习这些术语的基本含义。

本书的第一部分旨在建立机器学习实践者经常遇到的常见概念和主题的简要理论知识。本书的第一部分介绍了 KerasJupyter 笔记本NumPy 等等。

第二部分通过提供实用的练习和项目,用公开可用的数据集来实现,重点关注实用的深度学习。还详细介绍了 CNN、rnn(GRU 和 LSTM)和 gan。

从这本书里可以学到很多实用的技能,我建议把所有代码和完成的项目放在一个在线的仓库里,比如 GitHub,开始建立一个在线的存在,或者一个作品集。

机器学习——一种概率视角

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习——概率视角

不适合胆小的人。

这里我就实话实说了;每次我拿起这本书,我都要吹掉上面的灰尘。这本书很重要,但不如前面提到的书实用。

《机器学习:概率视角》是一本应该放在每个严肃的机器学习从业者的武器库中的书。这本书概括了机器学习的数学和理论方面,形成了基础和先进的 ML 技术的基础。

尽管这本书的篇幅和内容可能令人望而生畏,但我还是用它来巩固一般话题的知识,然后在公共领域谈论或写作这些话题。

这本书将在这十年中发挥作用,下一个十年,你越早开始理解它的内容,你就会成为一名更好的机器学习实践者。

4.个人项目

学习机器学习或计算机视觉的一种方法是简单地做。这条规则适用于许多领域。

通过承担和完成个人计算机视觉/ML 项目,我学到了更多。

我亲身经历的承担个人项目的好处如下:

  • 你熟悉了你在机器学习项目 中会遇到的 阶段。
  • 为在线作品集创建项目,向人工智能社区和未来的雇主展示你的技能。
  • 巩固你对用于学习的任何 MOOCs、书籍或课程中的概念和主题的理解。

我没有在线作品集,但我有一些项目,它们的代码库托管在 GitHub 上。

例如,我参与了一个项目,该项目涉及利用计算机视觉技术对四足动物进行运动分析。通过这个项目,我了解了姿势估计、迁移学习、对象检测(RCNN)、神经网络实现以及用 PyTorch 进行训练等等。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

个人项目:四足动物上的关键点检测

5.网站

机器学习和深度学习的流行库和框架(TensorFlow 和 PyTorch)提供了一些基本计算机视觉解决方案和常见任务实现的教程。

有关于人脸检测、姿势估计、图像分类、迁移学习等等的教程。

教程的目的不仅是向您介绍深度学习解决方案的实施,而且还可以提高您对数据预处理、神经网络实施、训练或机器学习项目管道中的其他领域,甚至模型部署的框架或库方法的熟悉程度。

[## 欢迎来到 PyTorch 教程— PyTorch 教程 1.4.0 文档

要了解如何使用 PyTorch,请从我们的入门教程开始。60 分钟的闪电战是最常见的开始…

pytorch.org](https://pytorch.org/tutorials/) [## 教程| TensorFlow 核心

完整的端到端示例,帮助 ML 初学者和专家了解如何使用 TensorFlow。尝试谷歌教程…

www.tensorflow.org](https://www.tensorflow.org/tutorials)

奖金(网站):中等

是的,信不信由你,Medium 教会了我很多关于计算机视觉的知识。媒体上有大量关于机器学习和计算机视觉的文章。媒体上丰富的信息足以让你阅读几天。

媒体上有机器学习相关的教程、讨论、采访和评论,来自聪明、好奇和令人兴奋的作者

在媒体上,我关注两件事。消费和创造。

强烈的

如果我提到我在 2020 年已经在 Medium 上阅读了超过 50 篇机器学习相关的文章,我并没有夸大其词。实际上,把这个数字改成 100。我读过顶级作家和出版物的文章,比如《走向数据科学的》和《T2 成为人类的

创造

通过在 Medium 上阅读其他作者的内容,我学会了如何向可能从未听说过这个话题的人传达机器学习概念。

我已经在 Medium 内部发展了一个小规模的存在,迄今为止已经写了 30 多篇文章,都与人工智能/机器学习有关。

在公共平台上撰写关于 ML/CV 概念的文章鼓励你以促进和培养深度理解的方式深入研究主题。

在其他教导和告知中,你必须首先知道。

我恳请读者选择一个与 ML/CV 相关的话题,并在 Medium 上写一写。请随意给我加标签或者给我发一个你写的文章的链接。

结论

如果你喜欢这篇文章和里面的内容,那么给我一个关注,因为我每周都会写类似的文章。

从这里去哪里?

你可以读到我在攻读计算机视觉硕士学位时遇到的困难。

[## 拿了一个机器学习的硕士学位,我(非常)没有准备

我从全职到人工智能硕士生过渡的探索。

towardsdatascience.com](/took-a-masters-in-machine-learning-and-i-was-very-unprepared-7aba95f044a8)

阅读我的一次失败的面试

[## (拒绝)来自我的第一次数据科学面试

拒绝是获得数据科学工作的整个过程的一部分。但它并不经常被提起。这是我的账户…

towardsdatascience.com](/rejected-from-my-first-data-science-interview-c9784dd65296)

或者看看我作为计算机视觉工程师的第一天是怎么过的。

[## 我作为计算机视觉工程师的第一天

剧透:我引起轰动

towardsdatascience.com](/my-first-day-as-a-computer-vision-engineer-8b59750c79a0)

Python 列表理解的 5 个错误用例

原文:https://towardsdatascience.com/5-wrong-use-cases-of-python-list-comprehensions-e8455fb75692?source=collection_archive---------38-----------------------

知道什么时候不使用列表理解

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由加里·本迪格Unsplash 上拍摄

列表理解无疑是 Python 最强大的特性。它们是 pythonic 式的,功能强大,并提供可读性。

但是这很容易为滥用它们打开方便之门。或者说是各种形式的虐待。这样做,你的代码只能是非 pythonic 化的,很难被对等体破译。

在下一节中,我们将看看使用 Python 列表理解的几种不正确的方法及其替换。

当你只是改变状态,而不是列表

许多程序员在开始使用 Python 时,在并不真正需要的地方开始使用列表理解。

例如,在下面的例子中,使用列表理解并不是最好的主意,因为我们没有对列表做任何事情。

vehicles = [ car, bike, truck ]
[ v.setLights(true) for v in vehicles ]names = [ "A", "B", "C" ]
[ print(i) for n in names ]

在这种情况下,最好使用经典的 for 循环,因为它可以防止创建不必要的列表。列表理解并不意味着指定命令或设置元素的状态。

当你只是在转换价值观的时候

你可能想转换一个字符串的字符或者简单地添加一串数字。在这两种情况下,选择列表理解并不意味着它也是 pythonic 式的。

让我们考虑下面的例子:

total = 0
listOne = [1,2,3]
[total := total + x for x in listOne]

虽然 Python 3.8 的赋值操作符:=允许我们使用列表理解对列表元素求和,但是当 Python 提供了内置的sum()函数时,为什么要重新发明一个轮子呢?上面的列表理解可以通过一段非常短的代码来完成:

sum(listOne)

类似地,当你只是将一个字符串拆分成字符(或者转换它们)时,使用列表理解是多余的,而且完全没有必要:

str = "Fred"
chars = [x for x in str]#use this instead:
chars = list(str)

当理解与庞大的逻辑嵌套在一起时

列表理解无论有多好,当它们嵌套在一起时都会变成一种痛苦。当逻辑冗长时,可读性问题只会进一步恶化。

Python 列表的理解最好是留给简洁的逻辑,以符合 python 代码。这意味着,如果需要的话,可以放弃嵌套列表理解,而使用嵌套循环。

下面的例子仅仅展示了嵌套循环是如何变得更容易理解,并且有时是长嵌套理解的很好的替代品。

list = [[1,2,3],[-1,-5,6]]flatten = [item
           for sublist in list
           for item in sublist
           if item > 0]#using loops
flatten1 = []for rows in list:
    for sublist in rows:
        if sublist > 0:
           flatten1.append(sublist)

当你在内存中加载整个列表时,尽管你并不需要它

列表理解可以让你很容易地创建列表,但是它们会一直占用内存。这使得它们非常低效,尤其是在处理大型数据集时。

考虑下面的例子,您很容易遇到内存不足的错误。

sum([i * i for i in range(1000)])

建议使用生成器表达式,因为它一次生成一个值:

sum(i* i for i in range(1000))

将列表存储在内存中的另一个不好的例子是,当您只根据特定条件查找单个元素时。下面的列表理解单句效率很低。

first = [x for x in list 
         if x.get("id")=="12"]

我们不仅可以用生成器表达式来代替它,还可以设置next函数,以便在第一个元素匹配给定条件时返回:

first = next((x for x in list if x.get("id")=="12"), None)

使用itertools函数和生成器表达式是一种有效的退出方式,而不是使用不支持breakcontinue的列表理解。

当你过度使用列表理解时

同样,您会惊讶地发现陷入列表理解并将其用于解压缩元组是多么容易。

下面的例子只是恢复了另一个不正确的用例,我们将元组值拆分成嵌套列表:

myList **=** [('A', 1), ('B', 2), ('C', 3)]result = [[ i for i, j in myList ],
       [ j for i, j in myList ]]

Python 已经为我们提供了一个特定的内置工具,可以让我们解压缩元组。只需使用解包操作符*来析构元组,并将其传递给zip函数来创建单独的列表。

result **=** list(zip(*****myList))# [['A', 'B', 'C'], [1, 2, 3]]

结论

Python 列表理解非常强大,但是它们很容易被过度使用,从而使代码变得非 python 化。

我希望以上不正确的方法能帮助你更好地判断什么时候不使用列表理解。

这一次到此为止。感谢阅读。

5 YouTubers 数据科学家和 ML 工程师应该订阅

原文:https://towardsdatascience.com/5-youtubers-data-scientists-and-ml-engineers-should-subscribe-to-e5bf5e2e9167?source=collection_archive---------4-----------------------

1 号莱克斯·弗里德曼

你是一名数据科学家还是一名 ML 从业者,正在寻找有效利用空闲时间的方法?

或许你已经厌倦了在 YouTube 上看没完没了的猫咪视频——现在还有人这么做吗?

不要再看猫咪视频了!

相反,你应该订阅我在本文中介绍的与数据科学和机器学习相关的 YouTube 频道。

了解如何有效地导航您的数据科学职业生涯,或者更好的是,在等待培训损失收敛时,扩展您对人类思维和意识起源的直觉。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上的坦克

1。莱克斯·弗里德曼

莱克斯·弗里德曼的 Youtube 频道可以说是迄今为止机器学习从业者最有见地的频道。

该频道上的视频是 Lex Fridman 本人与非凡的个人之间的简单对话,这些个人是计算、机器学习、深度学习、人工智能等领域的先驱或顶级研究人员。

我向数据科学家和机器学习工程师推荐这个频道的主要原因是,Lex Fridman 已经与机器学习和深度学习领域的著名先驱进行了交流。

大多数深度学习实践者都熟悉我将要列出的一些深度学习先驱,如果不是全部的话。

除了 Lex 频道的深度学习内容,我最喜欢的视频是与约沙·巴赫的精彩对话。这次谈话会让你惊叹于乔沙对围绕意识、人类思维和我们的宇宙的问题做出优雅回答的速度。

不要犹豫,找出为什么这个频道目前拥有约 4500 万的浏览量!

如果你已经是这个频道的订户,请在评论中链接你最喜欢的视频。

[## 莱克斯·弗里德曼

探索人工智能、深度学习、自动驾驶汽车等研究主题的视频。

www.youtube.com](https://www.youtube.com/c/lexfridman/featured)

2。肯吉

YouTube 上最有趣的数据科学人物之一,在数据科学领域有五年的经验。

大多数数据科学家可能已经对 Ken Jee 很熟悉了,也许你已经看过他的一个关于简历和投资组合的视频,或者你已经看过他的“从零开始的数据科学项目”视频系列。

我是肯·吉视频的订户,因为他采访了数据科学家和机器学习实践者。这些访谈记录了嘉宾在数据科学和相关领域的知识和经验。

我已经从这个频道的几位采访嘉宾那里获得了大量关于如何在人工智能领域内导航职业生涯的信息。

如果您是数据科学家,以下是您应该订阅该频道的一些原因:

  • 信息丰富的视频采访数据科学家已申请 FAANG 公司。
  • 对数据科学界知名人士、四次 Kaggle 特级大师 Abhishek Thakur 的深入采访。
  • 大多数数据科学从业者都会涉及到的大量内容。Ken 有关于如何有效学习数据科学的视频,处理冒名顶替综合症以及你应该参与哪些项目才能被雇佣。
  • 在你等待你的 ML 模型完成训练的时候,观看五分钟的短片。

[## 肯·吉

数据科学和体育分析是我的爱好。我叫 Ken Jee,一直在数据科学领域工作…

www.youtube.com](https://www.youtube.com/channel/UCiT9RITQ9PW6BhXK0y2jaeg)

3。扬尼克·基尔彻

Yannic Kilcher 的频道是 YouTube 上为数不多的几个频道之一,在那里你可以获得关于涵盖最先进的机器学习技术的研究论文的精彩解释。

下面是几个视频,展示了 Yannic 在解释研究论文时所采用的直观而直接的方法。

并不是所有的机器学习从业者都有硕士或博士的经历,这使得阅读和理解研究论文所需的开发技能成为可能。

大量数据科学家和 ML 工程师都是自学的,不具备有效分析研究论文所需的学术知识。

这就是为什么 Yannic channel 是我最喜欢的 5 个 YouTube 频道之一,我会推荐数据科学家和 ML 从业者获得传统和现代机器学习模型和技术的深入技术信息。

[## 扬尼克·基尔彻

我制作关于机器学习研究论文、编程以及人工智能社区和更广泛的问题的视频…

www.youtube.com](https://www.youtube.com/channel/UCZHmQk67mSJgfCCTn7xBfew)

4。乔丹·哈罗德

乔丹·哈罗德是麻省理工学院和哈佛大学的毕业生,他创作人工智能相关主题的视频内容。

在 Jordan 的频道上,你可以找到大量解释基于人工智能的技术直接应用于解决现实世界问题的视频。

乔丹频道上的大部分视频都很简洁,长度不到 10 分钟。然而,它们包含了如此多的相关和当前的信息,大多数机器学习实践者将从中受益。

Jordan 的视频从技术角度探索了具有高度兴趣价值的主题,例如人工智能如何用于预测新冠肺炎,或者人工智能解决方案中的种族偏见

[## 乔丹·哈罗德

探索我们每天与人工智能、算法和其他新技术互动的方式,为…

www.youtube.com](https://www.youtube.com/c/JordanHarrod/featured)

5。3 蓝色 1 棕色

这个列表中的最后一个 YouTube 频道可能是非 ML 从业者都会遇到的。

这个频道的内容是首屈一指的,我怎么称赞这个频道的创造者格兰特·桑德森都不为过。

对于那些对该频道背后的面孔和个性感到好奇的人,那么看看莱克斯·弗里德曼对格兰特的两次采访吧:第一轮第二轮

那些熟悉 3Blue1Brown 的人会同意我的说法,他设法在 15-20 分钟的短视频中教授大学讲师需要花费数小时的主题。

这个频道教我机器学习和神经网络的基础知识,让数学变得简单。

在机器学习中,理解线性代数、微积分和偏微分等主题是必不可少的。研究神经网络时,理解神经网络的基本组件至关重要。

理解一般的反向传播梯度下降神经网络等概念也是必不可少的。

[## 3 蓝色 1 棕色

格兰特·桑德森的《3Blue1Brown》是数学和娱乐的结合,这取决于你的喜好。目标是…

www.youtube.com](https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw)

结论

这些 YouTube 视频足够让你在 2020 年的最后几个月以及 2021 年的最初几个月里忙个不停。

本文中包含的 YouTube 频道目前正在频繁地发布新的视频内容。

你觉得还有其他数据科学/ML YouTube 应该上榜吗?然后我邀请你在评论区与其他读者分享。

我希望这篇文章对你有用。

要联系我或找到更多类似本文的内容,请执行以下操作:

  1. 订阅我的 邮件列表 获取每周简讯
  2. 跟我上
  3. 通过 LinkedIn 联系我

[## 机器学习可以在不到五分钟内检测到新冠肺炎!

旨在快速检测冠状病毒的研究进展的信息和收获。

towardsdatascience.com](/machine-learning-can-detect-covid-19-in-less-than-five-minutes-23bba57aeaa3) [## 我如何使用智能手表传感器来防止面部触摸

一个值得追求的想法?

towardsdatascience.com](/how-im-using-smartwatch-sensors-to-limit-covid-19-infection-51abe04f81f9)

25 个深度学习面试问题

原文:https://towardsdatascience.com/50-deep-learning-interview-questions-part-1-2-8bbc8a00ec61?source=collection_archive---------5-----------------------

深度学习的实践问题及解决方案

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

以下是 25 个关于深度学习的问题,可以帮助你测试你的知识,也是面试准备的一个很好的复习资源。

**1。**为什么有必要在神经网络中引入非线性?

:否则我们会有一个线性函数的合成,也是一个线性函数,给出一个线性模型。线性模型的参数数量少得多,因此其建模的复杂性有限。

**2。**描述处理神经网络中消失梯度问题的两种方法。

解决方案:

  • 使用 ReLU 激活代替乙状结肠。
  • 使用 Xavier 初始化。

3。在图像分类任务中,使用 CNN(卷积神经网络)而不是 DNN(密集神经网络)有什么优势?

解决方案:虽然两种模型都可以捕捉邻近像素之间的关系,但 CNN 具有以下特性:

  • 它是平移不变的——像素的确切位置与滤镜无关。
  • 它不太可能过度拟合——CNN 的典型参数数量比 DNN 少得多。
  • 让我们更好地理解模型——我们可以查看过滤器的权重,并可视化网络“学习”了什么。
  • 层次性——通过用简单模式描述复杂模式来学习模式。

**4。**描述在图像分类任务中可视化 CNN 特征的两种方法。

解决方案:

  • 输入遮挡-覆盖输入影像的一部分,查看哪一部分对分类的影响最大。例如,给定一个训练好的图像分类模型,给出下面的图像作为输入。例如,如果我们看到第三幅图像以 98%的概率被分类为狗,而第二幅图像只有 65%的准确度,这意味着第二幅图像中覆盖的部分更重要。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 激活最大化——想法是创建一个人工输入图像,最大化目标响应(梯度上升)。

**5。**尝试以下学习率:0.1,0.2,…,0.5 是优化学习率的好策略吗?

**解决方法:**不可以,建议尝试对数标度,优化学习速率。

**6。**假设您有一个具有 3 层和 ReLU 激活的神经网络。如果我们用相同的值初始化所有的权重会发生什么?如果我们只有一层(即线性/逻辑回归)会怎样?)

**解决方案:**如果我们将所有权重初始化为相同,我们将无法破坏对称性;即,所有梯度将被相同地更新,并且网络将不能学习。然而,在 1 层场景中,成本函数是凸的(线性/sigmoid ),因此权重将总是收敛到最优点,而不管初始值如何(收敛可能较慢)。

**7。**解释 Adam 优化器背后的理念。

解决方案: Adam,或称自适应动量,结合了两种思想来提高收敛速度:按参数更新以加快收敛速度,动量有助于避免陷入鞍点。

**8。**比较批量、小批量和随机梯度下降。

解决方案:批量指的是通过获取整个数据来估计数据,小批量指的是通过采样几个数据点来估计数据,而 SGD 指的是在每个时期更新一个数据点的梯度。这里要权衡的是梯度计算的精度和我们可以在内存中保存的批量大小。此外,通过在每个时期添加随机噪声,采用小批量而不是整个批量具有正则化效果。

**9。**什么是数据增强?举例说明。

**解决方案:**数据扩充是通过对原始数据进行操作来增加输入数据的技术。例如在图像中,可以:旋转图像,反射(翻转)图像,添加高斯模糊。

**10。**GANs 背后的理念是什么?

解: GANs,或者说生成性对抗网络,由两个网络(D,G)组成,其中 D 是“鉴别者”网络,G 是“生成性”网络。我们的目标是创造数据——例如,与真实图像没有区别的图像。假设我们想创造一个猫的反面例子。网络 G 将生成图像。网络 D 将根据它们是否是猫来对图像进行分类。G 的成本函数将被构造成试图“愚弄”D——总是将其输出分类为 cat。

**11。**使用 Batchnorm 有什么好处?

解决方案: Batchnorm 加速训练过程。它也(作为包含一些噪声的副产品)有一个正则化的效果。

12。W 什么是多任务学习?应该在什么时候使用?

**解决方案:**当我们有少量数据用于某项任务时,多任务处理是有用的,我们将受益于在另一项任务的大数据集上训练模型。模型的参数以“硬”方式(即相同的参数)或“软”方式(即成本函数的正则化/惩罚)共享。

13。什么是端到端学习?举几个它的优点。

**解决方案:**端到端学习通常是一种获得原始数据并直接输出期望结果的模型,没有中间任务或特征工程。它有几个优点,其中之一是:不需要手工制作特征,并且它通常导致较低的偏差。

**14。**如果我们使用 ReLU 激活,然后使用 sigmoid 作为最终层,会发生什么情况?

**解决方案:**由于 ReLU 总是输出一个非负的结果,网络将不断地为所有输入预测一个类别!

15。如何解决爆炸渐变问题?

**解决方案:**爆炸梯度问题的一个简单解决方案是梯度裁剪——当梯度的绝对值大于 M 时,将梯度取为 M,其中 M 是某个大数。

**16。**使用批量梯度下降时是否需要对训练数据进行洗牌?

**解决方案:**否,因为梯度是在每个历元使用整个训练数据计算的,所以混洗没有区别。

**17。**使用迷你批量梯度下降时,为什么打乱数据很重要?

**解决方案:**否则,假设我们训练一个 NN 分类器,并且有两个类——A 和 B,并且一个类的所有样本出现在另一个类之前。不对数据进行洗牌会使权重收敛到错误的值。

**18。**描述迁移学习的一些超参数。

**解决方案:**保留多少层,增加多少层,冻结多少层。

19 。测试集上是否使用了辍学?

解决方案:没有!只在火车布景里。辍学是一种在培训过程中应用的正规化技术。

20 。解释为什么神经网络中的漏失会起到正则化的作用。

解决方案:关于辍学为什么会起作用,有几种(相关的)解释。这可以被视为模型平均的一种形式——在每一步,我们“关闭”模型的一部分,并对我们得到的模型进行平均。还增加了噪点,自然有规整的效果。这也导致权重更加稀疏,并且实质上阻止了网络中神经元的协同适应。

**21。**举例说明多对一 RNN 架构的适用情况。

解决方案:举几个例子:情感分析,语音性别识别。

22 。什么时候不能用 BiLSTM?解释必须做出的假设。

解决方案:在任何双向模型中,我们都假设在给定的“时间”内可以访问序列的下一个元素。文本数据(即情感分析、翻译等)就是这种情况。),但时间序列数据并非如此。

23 。对/错:将 L2 正则化添加到 RNN 有助于解决渐变消失问题。

:假!添加 L2 正则化将使权重向零收缩,这实际上在某些情况下会使消失梯度变得更糟。

24 。假设训练误差/成本很高,并且验证成本/误差几乎等于它。这是什么意思?应该怎么做?

解决方案:这表示装配不足。可以添加更多的参数,增加模型的复杂性,或者降低正则化程度。

25 。描述 L2 正则化如何解释为一种权重衰减。

:假设我们的代价函数是 C(w),我们加上一个惩罚 c|w|2。当使用梯度下降时,迭代将看起来像

w = w-grad©(w)-2cw =(1–2c)w-grad©(w)

在这个等式中,权重乘以一个< 1 的因子。

53 Python 面试问答

原文:https://towardsdatascience.com/53-python-interview-questions-and-answers-91fa311eec3f?source=collection_archive---------0-----------------------

面向数据科学家和软件工程师的 Python 问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

布鲁克·卡吉尔Unsplash 上拍摄的照片

不久前,我开始担任“数据科学家”的新角色,实际上是“Python 工程师”。

如果我提前温习 Python 的线程生命周期而不是推荐系统,我会准备得更充分。

本着这种精神,以下是我的 python 面试/工作准备问答。大多数数据科学家都写了很多代码,所以这对科学家和工程师都适用。

无论你是在面试候选人,准备申请工作,还是只是在温习 Python,我认为这个列表都是非常宝贵的。

问题无序。我们开始吧。

1.列表和元组有什么区别?

在我参加的每一次 python /数据科学面试中,我都会被问到这个问题。对答案了如指掌。

  • 列表是可变的。它们可以在创建后进行修改。
  • 元组是不可变的。元组一旦创建,就不能更改
  • 列表是有顺序的。它们是有序的序列,通常属于同一类型的对象。Ie:按创建日期排序的所有用户名,["Seth", "Ema", "Eli"]
  • 元组有结构。每个索引可能存在不同的数据类型。Ie:内存中的一个数据库记录,(2, "Ema", "2020–04–16") # id, name, created_at

2.字符串插值是如何执行的?

在不导入Template类的情况下,有 3 种方法可以插入字符串。

name = 'Chris'# 1\. f strings
print(f'Hello {name}')# 2\. % operator
print('Hey %s %s' % (name, name))# 3\. format
print(
 "My name is {}".format((name))
)

3.“是”和“==”有什么区别?

在我 python 职业生涯的早期,我认为这些都是一样的…你好,臭虫。因此,根据记录,is检查身份,==检查平等。

我们将浏览一个示例。创建一些列表,并将它们分配给名称。注意b与下面的a指向同一个对象。

a = [1,2,3]
b = a
c = [1,2,3]

检查等式并注意它们都是相等的。

print(a == b)
print(a == c)
#=> True
#=> True

但是他们有相同的身份吗?没有。

print(a is b)
print(a is c)
#=> True
#=> False

我们可以通过打印他们的对象 id 来验证这一点。

print(id(a))
print(id(b))
print(id(c))
#=> 4369567560
#=> 4369567560
#=> 4369567624

cidab不同。

4.什么是室内设计师?

我在每次面试中都会被问到的另一个问题。这本身就值得一贴,但是如果你能写下自己的例子,你就已经准备好了。

装饰器允许通过将现有函数传递给装饰器来为现有函数添加功能,装饰器执行现有函数和附加代码。

我们将编写一个装饰器,在调用另一个函数时记录日志。

**编写装饰函数。**这需要一个函数func作为参数。它还定义了一个函数log_function_called,这个函数调用func()并执行一些代码print(f'{func} called.')。然后它返回它定义的函数

def logging(func):
  def log_function_called():
    print(f'{func} called.')
    func()
  return log_function_called

让我们编写最终将添加装饰器的其他函数(但现在还没有)。

def my_name():
  print('chris')def friends_name():
  print('naruto')my_name()
friends_name()
#=> chris
#=> naruto

现在将装饰器添加到两者中。

[@logging](http://twitter.com/logging)
def my_name():
 print('chris')[@logging](http://twitter.com/logging)
def friends_name():
 print('naruto')my_name()
friends_name()
#=> <function my_name at 0x10fca5a60> called.
#=> chris
#=> <function friends_name at 0x10fca5f28> called.
#=> naruto

看看我们现在如何通过在上面添加@logging来轻松地将日志添加到我们编写的任何函数中。

5.解释范围函数

Range 生成一个整数列表,有 3 种方法可以使用它。

该函数有 1 到 3 个参数。注意,我将每种用法都包装在列表理解中,这样我们就可以看到生成的值。

**range(stop)** : 生成从 0 到“停止”整数的整数。

[i for i in range(10)]
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

**range(start, stop)** : 生成从“开始”到“停止”的整数。

[i for i in range(2,10)]
#=> [2, 3, 4, 5, 6, 7, 8, 9]

**range(start, stop, step)** : 以“步”为间隔,从“开始”到“停止”生成整数。

[i for i in range(2,10,2)]
#=> [2, 4, 6, 8]

感谢塞尔格·博瑞姆丘克建议了一种更 pythonic 化的方式来做这件事!

list(range(2,10,2))
#=> [2, 4, 6, 8]

6.定义一个名为 car 的类,它有两个属性,“颜色”和“速度”。然后创建一个实例,返回速度。

class Car :
    def __init__(self, color, speed):
        self.color = color
        self.speed = speedcar = Car('red','100mph')
car.speed
#=> '100mph'

7.python 中的实例、静态和类方法有什么区别?

**实例方法:**接受self参数,并关联到类的一个特定实例。

**静态方法:**使用@staticmethod装饰器,与特定实例无关,并且是独立的(不要修改类或实例属性)

**类方法:**接受cls参数并可以修改类本身

我们将围绕一个虚构的CoffeeShop类来说明这种差异。

class CoffeeShop:
    specialty = 'espresso'

    def __init__(self, coffee_price):
        self.coffee_price = coffee_price

    # instance method
    def make_coffee(self):
        print(f'Making {self.specialty} for ${self.coffee_price}')

    # static method    
    [@staticmethod](http://twitter.com/staticmethod)
    def check_weather():
        print('Its sunny') # class method
    [@classmethod](http://twitter.com/classmethod)
    def change_specialty(cls, specialty):
        cls.specialty = specialty
        print(f'Specialty changed to {specialty}')

CoffeeShop类有一个属性specialty,默认设置为'espresso'CoffeeShop的每个实例都用属性coffee_price初始化。它也有 3 个方法,一个实例方法,一个静态方法和一个类方法。

让我们用5coffee_price初始化咖啡店的一个实例。然后调用实例方法make_coffee

coffee_shop = CoffeeShop('5')
coffee_shop.make_coffee()
#=> Making espresso for $5

现在调用静态方法。静态方法不能修改类或实例状态,所以它们通常用于实用函数,例如,将两个数相加。我们用我们的来查天气。Its sunny。太好了!

coffee_shop.check_weather()
#=> Its sunny

现在我们用类的方法修改咖啡店的特产然后make_coffee

coffee_shop.change_specialty('drip coffee')
#=> Specialty changed to drip coffeecoffee_shop.make_coffee()
#=> Making drip coffee for $5

注意make_coffee以前是怎么做espresso的,现在是怎么做drip coffee的!

8.「func」和「func()」有什么区别?

这个问题的目的是看你是否明白 python 中所有的函数也是对象。

def func():
    print('Im a function')

func
#=> function __main__.func>func()    
#=> Im a function

func是代表函数的对象,该函数可被赋给一个变量或传递给另一个函数。func()用括号调用函数并返回它输出的内容。

9.解释地图功能的工作原理

map返回一个映射对象(一个迭代器),它可以对序列中的每个元素应用一个函数而返回的值进行迭代。如果需要,地图对象也可以转换为列表。

def add_three(x):
    return x + 3li = [1,2,3][i for i in map(add_three, li)]
#=> [4, 5, 6]

上面,我给列表中的每个元素加了 3。

一位读者建议了一个更 pythonic 化的实现。感谢克里斯扬·伍斯特

def add_three(x):
    return x + 3li = [1,2,3]
list(map(add_three, li))
#=> [4, 5, 6]

此外,感谢迈克尔格雷姆肖特的更正!

10.解释 reduce 函数的工作原理

这可能会很棘手,直到你使用它几次。

reduce接受一个函数和一个序列,并对该序列进行迭代。在每次迭代中,当前元素和前一个元素的输出都被传递给函数。最后,返回一个值。

from functools import reducedef add_three(x,y):
    return x + yli = [1,2,3,5]reduce(add_three, li)
#=> 11

返回11,它是1+2+3+5的和。

11.解释过滤函数的工作原理

Filter 确实如其名。它过滤序列中的元素。

每个元素被传递给一个函数,如果该函数返回True,则该函数以输出序列返回,如果该函数返回False,则该元素被丢弃。

def add_three(x):
    if x % 2 == 0:
        return True        
    else:
        return Falseli = [1,2,3,4,5,6,7,8][i for i in filter(add_three, li)]
#=> [2, 4, 6, 8]

请注意所有不能被 2 整除的元素是如何被删除的。

12.python 是按引用调用还是按值调用?

如果你在谷歌上搜索这个问题并阅读了上面的几页,就要做好陷入语义陷阱的准备。

简而言之,所有的名字都是通过引用来调用的,但是一些内存位置保存对象,而另一些保存指向其他内存位置的指针。

name = 'object'

让我们看看这是如何处理字符串的。我们将实例化一个名称和对象,将其他名称指向它。然后删除名字。

x = 'some text'
y = x
x is y #=> Truedel x # this deletes the 'a' name but does nothing to the object in memoryz = y
y is z #=> True

我们看到的是,所有这些名字都指向内存中的同一个对象,它不受del x的影响。

这是另一个有趣的函数例子。

name = 'text'def add_chars(str1):
    print( id(str1) ) #=> 4353702856
    print( id(name) ) #=> 4353702856

    # new name, same object
    str2 = str1

    # creates a new name (with same name as the first) AND object
    str1 += 's' 
    print( id(str1) ) #=> 4387143328

    # still the original object
    print( id(str2) ) #=> 4353702856

add_chars(name)
print(name) #=>text

注意在函数内部的字符串中添加一个s是如何创建一个新名称和一个新对象的。即使新名称与现有名称具有相同的“名称”。

感谢迈克尔·p·雷利的指正!

13.如何反转一个列表?

请注意reverse()是如何在列表上被调用并对其进行变异的。它不会返回变异后的列表本身。

li = ['a','b','c']print(li)
li.reverse()
print(li)
#=> ['a', 'b', 'c']
#=> ['c', 'b', 'a']

14.字符串乘法是如何工作的?

我们来看看字符串‘cat’乘以 3 的结果。

'cat' * 3
#=> 'catcatcat'

该字符串自身连接了三次。

15.列表乘法是如何工作的?

让我们看看一个列表[1,2,3]乘以 2 的结果。

[1,2,3] * 2
#=> [1, 2, 3, 1, 2, 3]

输出包含重复两次的[1,2,3]的内容的列表。

16.一个班里的“自己”指的是什么?

Self 指的是类本身的实例。这就是我们如何给予方法访问和更新它们所属对象的能力。

下面,将 self 传递给__init__()使我们能够在初始化时设置实例的color

class Shirt:
    def __init__(self, color):
        self.color = color

s = Shirt('yellow')
s.color
#=> 'yellow'

17.如何在 python 中连接列表?

将两个列表相加会将它们连接起来。请注意,数组的工作方式不同。

a = [1,2]
b = [3,4,5]a + b
#=> [1, 2, 3, 4, 5]

18.浅拷贝和深拷贝有什么区别?

我们将在一个可变对象(列表)的上下文中讨论这个问题。对于不可变的对象,浅和深并不相关。

我们将经历 3 个场景。

**i)引用原始对象。**这个新名字li2指向内存中li1指向的相同位置。所以我们对li1所做的任何改变也会发生在li2上。

li1 = [['a'],['b'],['c']]
li2 = li1li1.append(['d'])
print(li2)
#=> [['a'], ['b'], ['c'], ['d']]

**ii)创建原始文件的浅拷贝。**我们可以用list()构造函数,或者更 pythonic 化的mylist.copy()(感谢 Chrisjan Wust !).

浅表副本创建一个新对象,但用对原始对象的引用填充它。所以向原始集合添加一个新对象li3,不会传播到li4,但是修改li3中的一个对象会传播到li4

li3 = [['a'],['b'],['c']]
li4 = list(li3)li3.append([4])
print(li4)
#=> [['a'], ['b'], ['c']]li3[0][0] = ['X']
print(li4)
#=> [[['X']], ['b'], ['c']]

**iii)创建深层副本。**这是通过copy.deepcopy()完成的。这两个对象现在完全独立,对其中一个对象的更改不会影响另一个对象。

import copyli5 = [['a'],['b'],['c']]
li6 = copy.deepcopy(li5)li5.append([4])
li5[0][0] = ['X']
print(li6)
#=> [['a'], ['b'], ['c']]

19.列表和数组有什么区别?

注意:Python 的标准库有一个数组对象,但这里我特指常用的 Numpy 数组。

  • 列表存在于 python 的标准库中。数组由 Numpy 定义。
  • 列表可以在每个索引处填充不同类型的数据。数组需要同质元素。
  • 列表算术在列表中添加或删除元素。每个线性代数上的数组函数的算术。
  • 阵列还使用更少的内存,并提供更多的功能。

我写了另一篇关于数组的综合文章。

20.如何连接两个数组?

记住,数组不是列表。数组来自 Numpy 和算术函数,如线性代数。

我们需要使用 Numpy 的 concatenate 函数来实现。

import numpy as npa = np.array([1,2,3])
b = np.array([4,5,6])np.concatenate((a,b))
#=> array([1, 2, 3, 4, 5, 6])

21.你喜欢 Python 的什么?

请注意,这是一个非常主观的问题,你需要根据角色的需求来修改你的回答。

Python 可读性很强,几乎所有事情都有 python 式的方法,这意味着这是一种清晰简洁的首选方法。

我将此与 Ruby 进行对比,在 Ruby 中,通常有许多方法来做某件事,但没有哪种方法更好的指导原则。

22.你最喜欢的 Python 库是什么?

亦主观,见问题 21。

当处理大量数据时,没有什么比 pandas 更有用了,它使处理和可视化数据变得轻而易举。

23.命名可变和不可变对象

不可变意味着状态在创建后不能修改。例如:int、float、bool、string 和 tuple。

可变意味着状态在创建后可以修改。例子有列表、字典和集合。

24.你如何将一个数字四舍五入到小数点后三位?

使用round(value, decimal_places)功能。

a = 5.12345
round(a,3)
#=> 5.123

25.你如何分割一个列表?

切片表示法有 3 个参数,list[start:stop:step],其中 step 是返回元素的间隔。

a = [0,1,2,3,4,5,6,7,8,9]print(a[:2])
#=> [0, 1]print(a[8:])
#=> [8, 9]print(a[2:8])
#=> [2, 3, 4, 5, 6, 7]print(a[2:8:2])
#=> [2, 4, 6]

26.什么是腌制?

Pickling 是 Python 中序列化和反序列化对象的常用方法。

在下面的例子中,我们序列化和反序列化一个字典列表。

import pickleobj = [
    {'id':1, 'name':'Stuffy'},
    {'id':2, 'name': 'Fluffy'}
]with open('file.p', 'wb') as f:
    pickle.dump(obj, f)with open('file.p', 'rb') as f:
    loaded_obj = pickle.load(f)print(loaded_obj)
#=> [{'id': 1, 'name': 'Stuffy'}, {'id': 2, 'name': 'Fluffy'}]

27.字典和 JSON 有什么区别?

Dict 是 python 数据类型,是一个索引但无序的键和值的集合。

JSON 只是一个遵循特定格式的字符串,用于传输数据。

28.你在 Python 中用过哪些 ORM?

ORMs(对象关系映射)将数据模型(通常在应用程序中)映射到数据库表,并简化数据库事务。

SQLAlchemy 通常用在 Flask 的上下文中,Django 有自己的 ORM。

29.any()和 all()是如何工作的?

Any 接受一个序列,如果序列中的任何元素为真,则返回真。

All 仅当序列中的所有元素都为真时返回真。

a = [False, False, False]
b = [True, False, False]
c = [True, True, True]print( any(a) )
print( any(b) )
print( any(c) )
#=> False
#=> True
#=> Trueprint( all(a) )
print( all(b) )
print( all(c) )
#=> False
#=> False
#=> True

30.字典或列表查找更快吗?

在列表中查找一个值需要 O(n)时间,因为需要遍历整个列表直到找到该值。

在字典中查找一个键需要 O(1)时间,因为它是一个散列表。

如果有很多值,这会造成很大的时间差,因此为了加快速度,通常建议使用字典。但是它们也有其他的限制,比如需要唯一的键。

31.模块和包的区别是什么?

模块是可以一起导入的文件(或文件集合)。

import sklearn

包是模块的目录。

from sklearn import cross_validation

所以包是模块,但不是所有的模块都是包。

32.Python 中如何对一个整数进行加减运算?

可以用+--=来增加和减少。

value = 5value += 1
print(value)
#=> 6value -= 1
value -= 1
print(value)
#=> 4

33.如何返回整数的二进制?

使用bin()功能。

bin(5)
#=> '0b101'

34.如何从列表中删除重复的元素?

这可以通过将列表转换成集合,然后再转换回列表来实现。

a = [1,1,1,2,3]
a = list(set(a))
print(a)
#=> [1, 2, 3]

注意,集合不一定保持列表的顺序。

35.如何检查列表中是否有值?

使用in

'a' in ['a','b','c']
#=> True'a' in [1,2,3]
#=> False

36.追加和扩展有什么区别?

append将一个值添加到一个列表,而extend将另一个列表中的值添加到一个列表。

a = [1,2,3]
b = [1,2,3]a.append(6)
print(a)
#=> [1, 2, 3, 6]b.extend([4,5])
print(b)
#=> [1, 2, 3, 4, 5]

37.如何取整数的绝对值?

这可以通过abs()功能完成。

abs(2)
#=> 2abs(-2)
#=> 2

38.如何将两个列表合并成一个元组列表?

您可以使用zip函数将列表组合成一个元组列表。这并不局限于只使用两个列表。也可以用 3 个或更多。

a = ['a','b','c']
b = [1,2,3][(k,v) for k,v in zip(a,b)]
#=> [('a', 1), ('b', 2), ('c', 3)]

39.你如何按字母顺序按关键字给字典排序?

您不能“排序”字典,因为字典没有顺序,但是您可以返回一个排序的元组列表,其中包含字典中的键和值。

d = {'c':3, 'd':4, 'b':2, 'a':1}sorted(d.items())
#=> [('a', 1), ('b', 2), ('c', 3), ('d', 4)]

40.Python 中一个类如何继承另一个类?

在下面的例子中,Audi继承自Car。随着这种继承而来的是父类的实例方法。

class Car():
    def drive(self):
        print('vroom')class Audi(Car):
    passaudi = Audi()
audi.drive()

41.如何从字符串中删除所有空格?

最简单的方法是用空格分割字符串,然后不用空格重新连接。

s = 'A string with     white space'''.join(s.split())
#=> 'Astringwithwhitespace'

2 读者推荐了一种更 Python 化的方式来处理这个问题,这种方式遵循了Explicit is better than Implicit的 Python 精神。它也更快,因为 python 不创建新的列表对象。感谢евгенийкрамаров和 Chrisjan Wust

s = 'A string with     white space'
s.replace(' ', '')
#=> 'Astringwithwhitespace'

42.为什么在对序列进行迭代时要使用 enumerate()。

enumerate()迭代序列时允许跟踪索引。这比定义和递增一个表示索引的整数更有技巧。

li = ['a','b','c','d','e']for idx,val in enumerate(li):
    print(idx, val)
#=> 0 a
#=> 1 b
#=> 2 c
#=> 3 d
#=> 4 e

43.传球、继续、突破有什么区别?

pass指无所事事。我们通常使用它,因为 Python 不允许在没有代码的情况下创建类、函数或 if 语句。

在下面的例子中,如果在i > 3中没有代码,将会抛出一个错误,所以我们使用pass

a = [1,2,3,4,5]for i in a:
    if i > 3:
        pass
    print(i)
#=> 1
#=> 2
#=> 3
#=> 4
#=> 5

continue继续执行下一个元素,并停止执行当前元素。所以对于i < 3处的值,永远不会达到print(i)

for i in a:
    if i < 3:
        continue
    print(i)
#=> 3
#=> 4
#=> 5

break中断循环,序列不再迭代。因此不打印从 3 开始的元素。

for i in a:
    if i == 3:
        break
    print(i)    
#=> 1
#=> 2

44.将下面的 for 循环转换成列表理解。

这个for循环。

a = [1,2,3,4,5]

a2 = []
for i in a:
     a2.append(i + 1)print(a2)
#=> [2, 3, 4, 5, 6]

变成了。

a3 = [i+1 for i in a]print(a3)
#=> [2, 3, 4, 5, 6]

列表理解通常被认为是更 pythonic 化的,因为它仍然是可读的。

45.举一个三元运算符的例子。

三元运算符是一行 if/else 语句。

语法看起来像a if condition else b

x = 5
y = 10'greater' if x > 6 else 'less'
#=> 'less''greater' if y > 6 else 'less'
#=> 'greater'

46.检查字符串是否只包含数字。

可以用isnumeric()

'123a'.isnumeric()
#=> False'123'.isnumeric()
#=> True

47.检查字符串是否只包含字母。

可以用isalpha()

'123a'.isalpha()
#=> False'a'.isalpha()
#=> True

48.检查字符串是否只包含数字和字母。

可以用isalnum()

'123abc...'.isalnum()
#=> False'123abc'.isalnum()
#=> True

49.从字典中返回一个键列表。

这可以通过将字典传递给 python 的list()构造函数list()来完成。

d = {'id':7, 'name':'Shiba', 'color':'brown', 'speed':'very slow'}list(d)
#=> ['id', 'name', 'color', 'speed']

50.如何区分字符串的大小写?

您可以使用upper()lower()字符串方法。

small_word = 'potatocake'
big_word = 'FISHCAKE'small_word.upper()
#=> 'POTATOCAKE'big_word.lower()
#=> 'fishcake'

51.remove,del,pop 有什么区别?

remove()删除第一个匹配值。

li = ['a','b','c','d']li.remove('b')
li
#=> ['a', 'c', 'd']

del按索引删除元素。

li = ['a','b','c','d']del li[0]
li
#=> ['b', 'c', 'd']

pop()通过索引移除元素并返回该元素。

li = ['a','b','c','d']li.pop(2)
#=> 'c'li
#=> ['a', 'b', 'd']

52.举一个字典理解的例子。

下面我们将创建一个字典,以字母表中的字母作为关键字,以字母表中的值作为索引。

# creating a list of letters
import string
list(string.ascii_lowercase)
alphabet = list(string.ascii_lowercase)# list comprehension
d = {val:idx for idx,val in enumerate(alphabet)} d
#=> {'a': 0,
#=>  'b': 1,
#=>  'c': 2,
#=> ...
#=>  'x': 23,
#=>  'y': 24,
#=>  'z': 25}

53.Python 中的异常处理是如何执行的?

Python 提供了 3 个词来处理异常,tryexceptfinally

语法看起来像这样。

try:
    # try to do this
except:
    # if try block fails then do this
finally:
    # always do this

在下面这个简单的例子中,try块失败了,因为我们不能将整数和字符串相加。except块设定val = 10,然后finally块打印complete

try:
    val = 1 + 'A'
except:
    val = 10
finally:
    print('complete')

print(val)
#=> complete
#=> 10

结论

你永远不知道面试中会出现什么问题,最好的准备方式是拥有丰富的代码编写经验。

也就是说,这个列表应该涵盖了数据科学家或初级/中级 python 开发人员角色在 python 方面被问到的几乎所有问题。

我希望这对你和我一样有帮助。

有没有我错过的很棒的问题?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值