TowardsDataScience 博客中文翻译 2019(三百七十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

你的工具箱中的一个新工具,KL Divergence at Work

原文:https://towardsdatascience.com/part-2-a-new-tool-to-your-toolkit-kl-divergence-736c134baa3d?source=collection_archive---------10-----------------------

最后,将 KL 散度应用于真实数据集

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

在我的上一篇中,我们对交叉熵KL 散度有了一个直观的了解,也通过实例计算了它们的值。如果你错过了,请在进入最后一集之前再看一遍

在本帖中,我们将应用这些概念,并在真实的数据集中检查结果。此外,它将为我们提供良好的直觉,告诉我们如何在建模各种日常机器学习问题时使用这些概念。那么,我们开始吧。

1.分析数据集

数据集包括两个潜在特征‘f1’和‘F2’以及数据点所属的类,即正类或负类。

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

Dataset

数据集可视化

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

Visualizing the Data with a scatterplot

Code used for Visualisation

因此,我们的数据点有两个潜在特征,“f1”和“f2”。数据点属于’+‘类(红色)和’-'类(蓝色)。

2.定义目的

我们的目的是为数据集的正负类定义一个理想的分布。到目前为止,我们还不知道它会是什么样子,它的概率密度函数会是怎样的,但是我们可以定义一些好的性质。

理想分布的性质

  1. 正类的分布应该使得任何数据点属于正类的概率应该是 1,而负类的概率应该是 0。
  2. 负类的分布应该使得任何数据点属于正类的概率应该是 0,负类的概率应该是 1。

3.如何估计上述理想分布

现在好戏开始了。如何估计理想分布。这是一个开放式的问题,可以尝试许多技术。但是对于这个博客的帖子,我将保持事情简单,不会偏离原始主题太多,将 KL 散度应用于日常的机器学习问题。

高斯/正态分布救援

估计分布的一种方法是使用高斯分布。我们将尝试为正类拟合一个高斯,为负类拟合另一个高斯。有可用的软件包可以为我们找到这些拟合的高斯函数的适当参数。但是,如果你有兴趣了解它是如何做到的,那么你可以在这里阅读更多关于它的。一种叫做期望最大化的算法被用于此。也许,我会在另一篇博文中写下它。让我们使用 python 中可用的 GaussianMixture 包来拟合发行版。

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

PDF of a multivariate Gaussian Distribution

Fitting the Distribution and visualizing the results

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

Fitted Gaussians for the positive and negative class

从视觉上看,在完成分配的任务时,分配看起来很好。一个高斯模型适合正类,另一个适合负类。接下来,我们将计算每个数据点属于正负类分布的概率。

4.寻找每个数据点的概率(可选)

在这一部分中,我们将看到,一旦完成了正类和负类的多元高斯拟合,如何计算每个数据点的最终概率。这将是一个数学密集型和可选的。它可以作为黑箱,得到最终的概率。但是万一,你有兴趣了解背后的数学,你可以按照章节 else 跳到下一个。

对于任何数据点’ x ',属于分布概率由下式给出

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

使用上面的公式,我们可以找到可能性,

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

Probability of datapoint given + distribution

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

Probability of datapoint given - distribution

接下来,我们可以找到类概率或先验,

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

Probability of + distribution

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

Probability of - distribution

其中 n 是数据点的总数。

一旦我们有了可能性和先验,最后一步就是找到后验,即数据点的概率。我们可以用贝叶斯定理来计算。

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

Probability of datapoint belonging to the + distribution

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

Probability of datapoint belonging to the - distribution

我们可以利用上面的后验,求出每个数据点属于+ve 或-ve 分布的概率。

5.评估拟合优度

现在,一旦我们拟合了分布,并且计算了每个数据点属于正负分布的概率。我们可以看到这个拟合的分布与我们的理想分布有多大的不同。

我们如何检查呢?当然,使用我们最喜欢的度量标准, KL 散度(kull back–lei bler 散度)。

只是重申,KL 散度只是拟合分布和实际分布之间的差异,即交叉熵和熵之间的差异。还可以看出这两种分布有多大差异。

计算 KL 散度

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

KL Divergence

其中 H(p,q)是交叉熵,H§是系统的熵,其中 pᵢ 是第事件的实际概率,q 是第 I 个事件的估计概率。

重申我们理想分布的性质

  1. 正类的分布应该使得任何数据点属于正类的概率应该是 1,而负类的概率应该是 0。
  2. 负类的分布应该使得任何数据点属于正类的概率应该是 0,负类的概率应该是 1。

pᵢ 是来自理想分布特性的事件的实际概率。q 是事件的估计概率,使用拟合/估计分布计算。我们用这些概率来寻找 KL 散度。

Calculating the probabilities and KL Divergence

KL 散度出来是 5.74 ,这表示拟合的分布非常接近理想值。但是我们能做得更好吗?

6.努力接近理想的分布

每类一条高斯曲线可能不足以模拟整个分布。我们可以拟合高斯混合分布,看看结果。有多少高斯人?直到我们的 KL 散度接近 0,即理想分布和拟合分布之间没有差异或差异最小。让我们试试那个。

Try fitting more than one Gaussian per Class

结果

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

KL Divergence on increasing the number of Gaussians per Class

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

1 Gaussian per Class, KL Divergence = 5.74

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

2 Gaussian per Class, KL Divergence = 3.18

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

3 Gaussian per Class, KL Divergence = 1.81

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

4 Gaussian per Class, KL Divergence = 0.77

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

5 Gaussian per Class, KL Divergence = 0.20

外卖食品

每类四个高斯分布就足够了,并且非常接近地模拟了 KL 散度几乎为 0 的理想分布。下面的情节也清楚地表明了这一点。

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

4 Gaussian per Class, KL Divergence approaches 0

7.结论

我们选择了一个包含两个不同类的数据集。我们想找到这两个类的基本分布。所以,我们首先定义了什么是好的,有理想分布的性质,并且能够非常接近地模拟理想分布。这样,我们总是可以尝试找到数据的基本分布,并使用 KL 散度来查看拟合度。希望它为这个主题带来了所需的清晰度,并为其在日常机器学习工作中的应用带来了新的视野。

我的 Youtube 频道获取更多内容:

[## 阿布舍克·蒙戈利

嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…

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

写一篇清晰易懂的好文章需要很多努力。我会继续努力做好我的工作。在 关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。任务的完整代码可以从这里获得。

8.参考

  1. https://en.wikipedia.org/wiki/Probability_density_function
  2. https://en.wikipedia.org/wiki/Entropy
  3. 【https://en.wikipedia.org/wiki/Cross_entropy
  4. https://en . Wikipedia . org/wiki/kull back % E2 % 80% 93 lei bler _ divergence
  5. https://scikit-learn.org/stable/modules/mixture.html
  6. https://towards data science . com/part-I-a-new-tool-to-your-toolkit-KL-divergence-5b 887 b5 b420 e
  7. https://towards data science . com/demystifying-entropy-f2c 3221 e 2550
  8. https://towards data science . com/demystifying-cross-entropy-e 80 e 3 ad 54 a 8
  9. http://www . ai shack . in/tutorials/expect-maximization-Gaussian-mixture-model-mixtures/
  10. https://en . Wikipedia . org/wiki/Expectation % E2 % 80% 93 最大化 _ 算法
  11. https://brilliant.org/wiki/gaussian-mixture-model/
  12. https://en.wikipedia.org/wiki/Bayes%27_theorem
  13. https://en . Wikipedia . org/wiki/kull back % E2 % 80% 93 lei bler _ divergence

第 2 部分——自动化和人工智能能打破商业智能应用的障碍吗?

原文:https://towardsdatascience.com/part-2-could-automation-and-ai-break-the-bi-adoption-barrier-6bb9a5933423?source=collection_archive---------26-----------------------

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

探索人工智能及其对 BI 采用的影响的系列文章的第 2 部分。

第一部分可以在这里找到。

正如我们在本系列的第 1 部分中所看到的,如果 77%的企业“绝对没有”或“可能没有”充分利用分析,并且分析平台的采用率只有糟糕的 32%,那么就需要采取一些重大措施。拥有机器学习和人工智能的增强分析时代能够解决这个采用问题吗?为了找到答案,我们需要了解我们迄今为止是如何在业务分析方面取得进展的。我们需要了解每个分析时代的优势和缺陷,才能知道增强分析是否真的是答案。

我们如何进入增强分析时代,商业智能简史

1985 年至 2005 年:引领潮流

我们第一次看到仪表板和业务记分卡的概念。但是,要实现这一点,需要昂贵的工具,而且使用和配置极其复杂。由于复杂性和不灵活性,见解需要数周才能挖掘出来,只能由 IT 专家提供。这意味着数据和见解在很大程度上也是不可访问的,因此很少有人能够获得用于业务决策的数据。只有大型企业才有能力聘请数据分析师。但正如我们所知,这个时代是使用仪表盘的商业报告的诞生。

2005–2015 年:自助服务分析

到了 2005 年中期,“自助服务”成了流行语。自助服务分析供应商催生了能够独立于 IT 运营的超级用户和数据分析师。BI 供应商使分析师能够使用不太复杂的流程和更简单的用户界面来准备、发现和可视化数据。然而,那个时期的弱点是分析的分散化,这意味着缺乏治理。很少的治理意味着对分析的来源或获取见解的过程没有监督,当多人从相同的数据中产生不同的结果时,这导致了不信任。由于缺乏这些制衡,用户不会采用,部分原因是缺乏信任。尽管 BI 比以往任何时候都更容易获得,但采用率却达到了一个稳定的水平。这个时代大部分商家还在经营。

2016 年—现在:增强分析

最近,我们看到了新一轮的分析浪潮,它承诺为所有人提供自动化和即时洞察力。这种趋势已经像滚雪球一样,包括自然语言搜索查询、机器学习生成的分析和自动数据发现。在接下来的 12 个月内,我们将看到几乎所有分析供应商在其平台中使用机器学习和自然语言界面推出自动化。尽管在以企业一直希望的速度提供数据洞察方面,这将是一个巨大的飞跃,但它也带来了自己的问题——透明度。正在使用的算法和底层计算是什么?我能信任它所依赖的引擎吗?如果洞察和数据发现背后的自动化是一个黑匣子,那么对数字的信任将保持非常低的水平,让人想起无人监管的自助服务时代。这可能会成为分析师而非商业用户的一个问题,商业用户已经毫无疑问地依赖于生活中许多领域的算法,从谷歌搜索结果到脸书的时间线提要。对于企业用户来说,甚至无需与分析工具交互就能交付的自动化见解,可能远远超过他们对算法的任何担忧。

我们如何转向这一波增强分析

三个市场趋势正在推动下一波分析浪潮:数据量增加、种类更多、数据速度更快——这是人们通常创造的三个 v。随着物联网(IoT)的加入,这些问题变得尤为明显,物联网正在收集和生成大量的指标。几乎没有一天不添加新的 web 数据源、API 或客户 360 视图的另一部分,以带来更大的多样性。数据传输的速度是惊人的。要看到它的实际效果,你只需要暂停网上购物,转到社交媒体上,你刚刚考虑购买的商品就会出现在广告中。有了数据的三个 v,我们现在有能力提出更多的问题和更具体的问题,以找到优化业务所需的答案。随着数据的激增,我们可以将问题从“发生了什么?”到“为什么会发生?”但是“为什么”仍然是大海捞针,而且大海捞针还在不断增加。数据的数量、种类和速度可能是发现数据价值的促进因素,也可能是障碍,因为数据分析仍然由手动数据发现驱动,这需要数据分析师的技能。

BI 采用的四大阻碍因素

在第 3 部分中,我们将了解阻碍 BI 和分析采用的四个潜在因素,从而揭示分析自动化如何解决这一问题。

第二部分:机器学习、人工智能和自动化如何打破 BI 采用壁垒 最初发布于 2019 年 4 月 16 日yellowfinbi.com

为您的机器或深度学习项目提供更多不常见的数据清理器

原文:https://towardsdatascience.com/part-2-more-uncommon-data-cleaners-for-your-machine-or-deep-learning-project-b30f862b2d81?source=collection_archive---------17-----------------------

帕索项目

我将介绍类型和格式转换数据清理器。

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

几乎所有的 paso ,包括这里讨论的所有函数,都要求 paso 数据清理步骤(如删除空值和 NA 值)已经完成。

这些数据清理器在以下文章中有详细介绍:

[## 用于真实世界机器或深度学习项目的不寻常的数据清理器

介绍

towardsdatascience.com](/uncommon-data-cleaners-for-your-real-world-machine-or-deep-learning-project-f926d8ecb258)

背景故事

在我们以前的项目中,我们发现自己大部分时间都在用非常相似或略有不同的数据清理器清理数据。

在第一个项目中,我们在数据清理开发上花费了大量时间。以至于在第二个项目开始时,项目管理将数据清理分为三类:相同、差异小于 33%和差异大于 33%。

这些类别定义了两个重要原因:

  • 作为一个团队,随着数据清理器需求的确定,我们能够消除大量的“重新编码车轮”,并向我们的数据清理器包添加超过 33%的不同类别。
  • 我们的开发时间估计变得更加精确。

两年半之后,我们开始了第八个项目,并且发现,到目前为止,不到十分之一的数据清理器属于第三类,即花费开发人员更多时间的类别。更重要的是,我们从开发到生产的时间是前两个项目的一半。我们现在可以将大部分时间花在寻找足够好的机器学习(有时是深度学习)解决方案上。

您的体验可能会有所不同,因为我目前的领域是用于资产配置、平衡和风险的固定收益金融数据。(好吧,是的,一些我在这里不会提到或使用的其他晦涩的东西。)

现在你可能会问我为什么要讲这个故事。因为随着我们沿着这条路走下去,我从一个机器学习科学家进化成了一个软件架构师和软件工程师。

我现在负责修复一个生产服务,并完成最初的架构设计工作和代码开发。我喜欢从开发到生产。有时我会写下并分享我们的一些成就。

我真诚地希望你能使用我们的一些工作。这里使用的函数的所有代码都可以在https://github.com/bcottman/paso/toutil.py找到。

故事已经够多了。你能做什么?给我看看!

使用不同组合的清洗策略(管道)是 paso 的一个重要目标。

讨论将分为以下几个主要部分:

  • 首先,我们创建可以改变的数据集。
  • 接下来,通过对创建的数据集进行操作来演示每个清理器。
  • 然后我们展示了一个与管道很好地混合的调用功能:链接掉 pandas DataFrame 实例。这是我们熟悉的 R 开发模式。我们发现编码 paso 链比编码 sklearn 管道要容易得多。我们甚至认为链式管道比传统管道更容易检查和理解。
  • 最后,我们总结一下 paso 的数据清理器,以及我们对未来文章和 paso 版本的计划。

本课的代码在这里这里文件中给出。获得整个 paso 包的最好方法是 git 克隆base。pip将不起作用,因为此包中有您需要的基于文本的文件(描述)。

目标实用程序:目标数据框架

paso.pre.toutil.toDataFrame(X: pd.DataFrame,
    columns: List = None, 
    inplace: bool = True, 
    verbose: bool = True) 
    -> pd.DataFrame:

Parameters:
    X: DataFrame
        Attempt to convert python datatype argument into 
        pandas dataframe.

    columns:     
        The column names to  be used for new DataFrame. 
        If a number of column names given is less than a number 
        of column names needed, then they will be generared 
        as c_0...c_(n-1), where n is the number of missing
        column names.

    verbose: default: True) Logging is on.

    Returns: DataFrame

该功能基于willmcginnis's convert_input()

paso 是一个包,其中所有的功能和方法都需要一个数据框架。

由于 paso 函数和方法只消耗 pandas 数据帧,我们需要一个函数来转换各种 python 数据类型,同时还提供 paso 的基本服务。这个功能就是paso.to_util.toDataFrame

此函数是" paso 规则的例外。第一个参数是 DataFrame "规则,因为它将一维或二维列表、元组、csr_matrix、numpy 数组或 1d pandas 系列转换为 pandas DataFrame。

你也有paso.to_util.isDataFrame(X) -> bool来检查对象是否是一个pandas.DataFrame

如果不需要 paso 的服务,比如日志记录和缓存,可以使用方法pandas.DataFrame。我建议你不要这样做,但是你可以选择这样做。

一个好的做法是在管道的开始制作类型为DataFrame的数据集。由 paso 函数所做的更改将被保存在 DataFrame 实例的状态中(inplace=True)。在您的实验运行的整个管道中,就地将会发生,以最大化完成速度和最小化内存使用。

如果您需要引用原始数据帧,那么您可以执行类似以下操作:

<dataset_name>_original = <dataset_name>.copy()

但是,系统会警告您,保留原件会消耗一些电脑内存。

由您决定是否保留原始数据集的副本。

几乎总是从本地文件或通过 URL 寻址的非本地文件输入原件,因此,您可能不需要在计算机内存中保留副本。

您可以通过以下方式查看任何对象的大小(以字节为单位):

from sys import getsizeof
getsizeof(pd.DataFrame())=> 24

这表明空数据帧的大小为 24 字节。

创建一个我们可以使用的数据集

现在,我们创建一个人工数据集df_of_ints,一个由int组成的数组

from paso.base import raise_PasoError  
from paso.pre.toutil import toDataFrame
arr = np.ndarray(shape=(1000000,6), dtype=int, order='F')
df_of_ints = toDataFrame(arr)

日志输出[=>]:

2019-12-12 13:29:08.164 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with 
column names: Index(['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')

toDataFrame(arr, columns=['a','b']) 可以为新的 DataFrame 指定前两个列名。

df_of_ints = toDataFrame(arr, columns=['a','b'])
df_of_ints.shape

日志输出[=>]:

2019-12-12 13:29:22.981 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with 
column names: Index(['a', 'b', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')

输出[=>]:

(1000000, 6)

请注意,前两个列名是如何给出的,toDataFrame检测到这一点,并创建了所需的接下来的四个列名。

这次我们调用toDataFrame,同时保持 paso 注销。只有在调用的函数范围内,日志记录才会被关闭。

df_of_ints = toDataFrame(arr, columns=['X','yyyyyy'],verbose=False)
df_of_ints.columns

输出[=>]:

Index(['X', 'yyyyyy', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')

to _ util:to 类别

paso.pre.toutil.toCategory(
    X: pd.DataFrame,
    bool_: bool = True,
    int_: bool = True,
    object_: str = True,
    inplace: bool = True,
    verbose: bool = True,
) -> pd.DataFrame:

Parameters:
    X: dataFrame

    bool_: default: True - convert to category type.

    int_: default: True - convert to category type.

    object_: default: True - convert to category type.

    inplace: default:
        True - change DataFrame arg "in-place"
        False:  return new resulting DataFrame

    verbose: default: True - Logging is on.

Returns: resulting DataFrame

该函数将一个 pandas DataFrame 实例的任何布尔值、对象值或整数值转换为类别类型值。

例外情况是连续(浮点或日期时间)值,它返回未转换的值。

如果要将连续或日期时间类型转换为类别,则在 paso toCategory 之前使用 ContinuoustoCategory 或 DatetimetoComponents。

注: paso 数据清理步骤(如删除空值和 NA 值)已在此步骤之前完成。

datetime特征应在此步骤之前调用toDatetimeComponents(),以便datetime组件(类型为int)转换为category

该步骤的行为不是将datetime转换为category

from paso.base import raise_PasoError  
from paso.pre.toutil import toCategory
df_cat = toCategory(df_of_ints,inplace=False)

日志输出[=>]:

2019-12-12 13:36:58.748 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : X
2019-12-12 13:36:58.768 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : yyyyyy
2019-12-12 13:36:58.786 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_2
2019-12-12 13:36:58.802 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_3
2019-12-12 13:36:58.814 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_4
2019-12-12 13:36:58.824 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_5

看起来df_of_ints没变,这就是我们在本例中想要的,inplace=False

df_of_ints.dtypes

输出[=>]:

X         int64
yyyyyy    int64
c_2       int64
c_3       int64
c_4       int64
c_5       int64
dtype: object

现在看来,df_of_ints的所有值都是从类型int转换为类型category并带有 inplace=True

df_of_ints.toCategory(inplace=True)
df_of_ints.dtypes

日志输出[=>]:

2019-12-12 09:39:37.193 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : X
2019-12-12 09:39:37.214 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : yyyyyy
2019-12-12 09:39:37.233 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_2
2019-12-12 09:39:37.251 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_3
2019-12-12 09:39:37.269 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_4
2019-12-12 09:39:37.282 | INFO     | paso.pre.toutil:toCategory:197 - toCategory integer feature converted : c_5

输出[=>]:

X         category
yyyyyy    category
c_2       category
c_3       category
c_4       category
c_5       category
dtype: object

链接

我猜有些读者(不是你)对df_of_ints.toCategory(inplace=True)有点困扰。如果是这样的话,你会更加为此烦恼:

toDataFrame(arr, columns=['a','b']).toCategory(verbose=False).dtypes

日志输出[=>]:

2019-12-12 09:39:37.359 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with column names: Index(['a', 'b', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')

输出[=>]:

a      category
b      category
c_2    category
c_3    category
c_4    category
c_5    category
dtype: object

如果您对这种大惊小怪不感到困扰甚至困惑,那是因为您知道 DataFrame 可以是一个python类实例,并且您在一个类实例上调用方法。你甚至可以方法。也就是说,你可以一个接一个地调用方法。

在这种情况下,我链接了toDataFrame输出的 DataFame 实例的两个方法.toCategory().dtypes

pasoCleaners类和toutils函数的所有方法都要求第一个参数是 DataFrame 实例。Dataframe 作为第一个参数,通过使用基于包 pandas-flavor 的重构装饰器,使它们成为 DataFrame 的方法。

链接可以使它非常容易理解,因为操作是从左到右调用的。这和你阅读(英语和许多其他语言)的方式是一样的。

有些人更喜欢链而不是使用 sklearn 的管道。你会注意到我们的链接在语法上与 sklearn 的管道链接略有不同。

我们的链接非常接近R的外观。从现在开始,我们将使用这两种调用方法。

to_util: toContinuousCategory

def toContinuousCategory(
        X: pd.DataFrame,
        features:List=[],
        drop: bool = True,
        inplace: bool = True,
        verbose: bool = True,
        integer: bool = True,
        floaty: bool = True,
        quantile: bool = True,
        nbin: int = 10,
    ) -> pd.DataFrame:

    Parameters:
        X:pd.DataFramedrop: default:True
            do not keep original features.integer: default:True
            set integer=False if not continuous and not to 
            transform into category.floaty: default:True
            set floaty=False if not continuous and not to 
            transform into category.quantile: default: True
            use quantile bin.
            Quantile is similar to v/(maxy-miny), works on any scale.
            False, use fixed-width bin. miny,maxy arguments are ignored.nbin:int (default: 10)Returns: DataFrameRaises:
        TypeError('"ContinuoustoCategory:inplace: requires boolean type.")

util:today time components

paso.pre.toutil.toDatetimeComponents(
    X: pd.DataFrame,
    drop: bool = True,
    components: list = [],
    prefix: bool = True,
    inplace: bool = True,
    verbose: bool = True) -> pd.DataFrame:

Parameters:

    X: DataFrame

    drop: default: True
        If True then the datetime feature/column will be removed.

    components:: default: []
        list of column(feature) names for which datetime components
        are created.

    prefix: default: True
        If True then the feature will be the prefix of the 
        created datetime component features. The postfix will be
       _<component> to create the new feature column
        <feature>_<component>.

        if False only first _PREFIX_LENGTH_ characters of feature
        string will be used to create the new feature
        name/column<featurename[0:_PREFIX_LENGTH_]>_<component>.

    components:list default:
        ['Year', 'Month', 'Week', 'Day','Dayofweek'
        , 'Dayofyear','Elapsed','Is_month_end'
        , 'Is_month_start', 'Is_quarter_end'
        , 'Is_quarter_start', 'Is_year_end', 'Is_year_start']

        or set components to one or component names in a list
        Must be components names from default list.

    inplace: default: True
        True: change DataFrame arg in-place"

        False: return new resulting dataframe

    verbose: default: True Logging is on.

Returns:DataFrame
        toDatetimeComponents transformed into datetime
        feature components.

为什么要将一个日期时间分解成单位成分?这导致了一种高级的编码策略,在论文分类变量的实体嵌入中有详细的讨论

[## 理解实体嵌入及其应用

最近,在被指派研究一个预测问题后,我读了很多关于实体嵌入的文章。

towardsdatascience.com](/understanding-entity-embeddings-and-its-application-69e37ae1501d)

以下条款指出:

"Categorical variables are known to hide and mask lots of interesting information in a data set and many times they might even be the most important variables in a model. A good data scientist should be capable of handling such variables effectively and efficiently. If you are a smart data scientist, you’d hunt down the categorical variables in the data set, and dig out as much information as you can."

出于多种原因,所有这些都会产生更好的预测能力,您可以将一个datetime分解成int个组件。您可以更进一步,将datetime int组件转换成分类类型的组件。

你可能已经明白这是怎么回事了。如果我有一些非分类特征,比如一列datetimes,我将需要一个函数把日期时间转换成分类特征。

我将在下一篇文章中介绍如何使用分类特征作为嵌入向量。

您可以通过datetimeComponents查看哪些日期时间组件可用。我们的版本基于 fast.ai 包中的一个函数。

from paso.pre.toutil import datetimeComponents
datetimeComponents()

输出[=>]:

['Year',
 'Month',
 'Week',
 'Day',
 'Dayofweek',
 'Dayofyear',
 'Elapsed',
 'Is_month_end',
 'Is_month_start',
 'Is_quarter_end',
 'Is_quarter_start',
 'Is_year_end',
 'Is_year_start']

我首先创建一个 DataFrame 实例来展示toDatetimeComponents的功能。

from datetime import datetime, timedeltarc = 94598; cc = 1; acc =13
darr = np.arange(datetime(1751,7,1),
                 datetime(2010,7,1),
                 timedelta(days=1)).reshape(rc,cc)
from paso.pre.toutil import toDatetimeComponents
toDataFrame(darr,columns = []).toDatetimeComponents(inplace=False).head(2)

日志输出[=>]:

2019-12-12 09:39:37.601 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with column names: Index(['c_0'], dtype='object')
2019-12-12 09:39:37.609 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Year
2019-12-12 09:39:37.614 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Month
2019-12-12 09:39:37.621 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Week
2019-12-12 09:39:37.627 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Day
2019-12-12 09:39:37.633 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Dayofweek
2019-12-12 09:39:37.640 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Dayofyear
2019-12-12 09:39:37.794 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Elapsed
2019-12-12 09:39:37.800 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Is_month_end
2019-12-12 09:39:37.805 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Is_month_start
2019-12-12 09:39:37.812 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Is_quarter_end
2019-12-12 09:39:37.816 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Is_quarter_start
2019-12-12 09:39:37.822 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Is_year_end
2019-12-12 09:39:37.828 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: c_0_Is_year_start
2019-12-12 09:39:37.837 | INFO     | paso.pre.toutil:toDatetimeComponents:351 - datetime feature dropped: c_0

输出[=>]:

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

Resulting DataFrame from toDatetimeComponents

在这种情况下,datetimeComponents将每个日期时间值转换成十三个int组件。然后它将这些int类型转换成category类型。

如果 X[[dt_features]]不是日期时间类型(如object类型),那么不会试图将 X[[dt_features]]强制转换为datetime类型。

最好将原始数据字段作为datetime而不是object读取/输入。您可以使用以下方法将 dataframe 列转换为 datetime:

X[feature] = pd.datetime(X[feature])

我们可以进行自动转换,但是我们发现对于一些较大的数据集(> 1 亿行),转换速度太慢。使用数据帧列作为datetime而不是object来启动管道要快得多。

toutil: toContinuousCategory

paso.pre.toutil.toContinuousCategory(
    oX: pd.DataFrame,
    features: list = [],
    drop: bool = True,
    int_: bool = True,
    float_: bool = True,
    quantile: bool = True,
    nbin: int = 10,
    inplace: bool = True,
    verbose: bool = True,
) -> pd.DataFrame:*Parameters:
    X: dataset

Keywords:

    features:  default: []
        The column  names to  be transform from continuous
        to category.

    drop: default: True)
        If True then the datetime feature/column will be removed.

    int_: Default: True
        set integer=False if not continuous and not to 
        transform into category.

    float_: Default: True
        set floaty=False if not continuous and not to transform
        into category.* *quantile: Default: True use quantile bin.
        quantile is simular to v/(maxy-miny), works on any scale.
        False, use fixed-width bin. miny,maxy arguments are ignored.

    nbin: default: 10
        Alternately ``nbins`` can be integer for number of bins.
        Or it can be array of quantiles, e.g. [0, .25, .5, .75, 1.]
        or array of fixed-width bin boundaries i.e. [0., 4., 10., 100].

    verbose: Default True
        True: output
        False: silent

    inplace: Default: True
        True: replace 1st argument with resulting dataframe
        False:  (boolean)change unplace the dataframe X

Returns: pd.DataFrame

Raises:
        TypeError('" requires boolean type.")*

toContinuousCategory将任何连续的浮点数,或 pandas DataFrame 的整数值分组到 bin 中,转换为类别值。

宁滨,也称为量化,用于将连续的数字特征(np.number类型)转换为category类型。

每个容器代表一系列连续的数值。

宁滨数据的具体策略有固定宽度(quantile=False)和自适应宁滨(quantile = True)。

无论输入数据集的类型如何,它都将作为DataFrame返回。如果要设置功能名称,在此功能之前调用toDataFrame

固定宽度的宁滨只对基于树的模型的数据集有效,没有缩放,例如 random forest、xgboost、lightgbm、catboost 等。非树基模型,如线性、对数、、神经网络等。,不会正确工作,因为它们依赖于值的大小。

线性宁滨的统计问题。

宁滨增加 I 型和 II 型误差;(简单的证明是,随着箱数趋近于无穷大,那么信息损失趋近于零)。此外,改变容器数量将改变容器分布形状,除非分布均匀平坦

分位数宁滨与单一数据集一起使用。

如果你有一个训练和测试数据集,基于百分位数(分位数)将连续特征转换成类别特征是错误的。分位数基于数据集,除非每个数据集的分布形状相同,否则分位数会有所不同。在极限中,只有两个箱,然后几乎没有关系可以建模。我们主要是在做 t 检验。

如果特征之间存在非线性甚至非单调关系

如果你需要线性宁滨,而不是分位数,使用quantile=False

如果你想要分位数——宁滨。

尽管有上述警告,您的用例可能需要分位数宁滨。
在这种情况下,将分位数宁滨应用于合并的训练和测试数据集,然后再将它们分开。

基于分位数的宁滨是用于自适应宁滨的一个相当好的策略。分位数是将要素的连续值分布划分为离散的连续箱或区间的特定值或分界点。因此,q-分位数将数值属性划分为 q 个相等(百分比-宽度)的分区。

这些箱变成分类特征。你可能想这样做的年龄,体重,温度,工资,价格等特征…

分位数的众所周知的例子包括 2 分位数,中位数,将数据分布分为两个相等(百分比宽度)的二进制数,4 分位数,标准四分位数,四个相等的二进制数(百分比宽度)和 10 分位数,十分位数,十个相等宽度(百分比宽度)的二进制数。

您应该注意到,新要素是由分位数宁滨附加 q 产生的,而新要素是由固定宽度宁滨附加 w 产生的

将连续浮动功能转换为类别并删除原始列:

from paso.pre.toutil import toContinuousCategory
nc = 6
nr = 1000000
delta = 0.1
farr = np.arange(0,(nr*delta*nc),delta, dtype=float).reshape(nr,nc)
toDataFrame(farr).toContinuousCategory(drop=True).head(n=2)

日志输出[=>]:

2019-12-12 15:27:27.638 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with 
column names: Index(['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')
2019-12-12 15:27:28.204 | INFO     | paso.pre.toutil:toContinuousCategory:533 - toContinuousCategory features:: Index(['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')

输出[=>]:

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

将连续浮动要素转换为固定宽度的类别箱,并保留原始列。

toDataFrame(farr).toContinuousCategory(quantile=False,nbin=3,drop=False)\
.head(n=2)

日志输出[=>]

2019-12-12 09:39:38.578 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with column names: Index(['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')
2019-12-12 09:39:38.896 | INFO     | paso.pre.toutil:toContinuousCategory:533 - toContinuousCategory features:: Index(['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')

输出[=>]:

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

DataFrame resulting in quantile binning

toutil: toColumnNamesFixedLen

def toColumnNamesFixedLen(
    oX: pd.DataFrame,
    column_length: int = 1,
    col_separator: str = "_",
    inplace: bool = True,
    verbose: bool = True,
) -> pd.DataFrame:

    Parameters:
    X: dataset

Keywords:

    column_length:  Default: 3
        Character length for which to truncate all columns.
        The column separator value and number for duplicate
        column name does not contribute. Therefore, if all
        columns are truncated to 10 characters, the first
        distinct column will be 10 characters and the
        remaining will be 12 characters (assuming a column
        separator of one character).

    col_separator: Default: "_"
        The separator to append plus incremental Int 
        to create unique column names. Care should be 
        taken in choosing non-default col_separator 
        so as to create legal pandas column name.

    verbose: Default: True
        True: output
        False: silent

    inplace: Default: True
        True: replace 1st argument with resulting dataframe
        False:  (boolean)change unplace the dataframe X

Returns: A pandas DataFrame with truncated column lengths.

将列名截断到特定长度。如果列长度较短,则列长度保持不变。

toColumnNamesFixedLen会将所有列截断到给定的长度,并附加给定的分隔符和重复列的索引,第一个不同的列名除外。

toDataFrame([[1,2,3,4]],columns=[
 “long_name”,
 “another_long_name”,
 “another_longer_name”,
 “data”,
]).toColumnNamesFixedLen(column_length=5)

日志输出[=>]:

2019-12-12 09:39:39.051 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with column names: Index(['long_name', 'another_long_name', 'another_longer_name', 'data'], dtype='object')
2019-12-12 09:39:39.052 | INFO     | paso.pre.toutil:toColumnNamesFixedLen:669 - toColumnNamesFixedLen features:: ['lo', 'an', 'an=1', 'da']

输出[=>]:

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

Resulting DataFrame from toColumnNamesFixedLen

函数式编程——用链接创建可读管道

在这一节。我将展示 python 中的函数式编程风格。这种风格也被称为链式,使用 R 的人应该非常熟悉。

我将创建一个数据框架,这样我们就可以显示我们的一些清洁链(管道)。

arr = np.ndarray(shape=(1000000,6), dtype=int, order='F')
dataset = toDataFrame(arr)
dataset['date'] = pd.to_datetime('11/30/1956')

日志输出[=>]

2019-12-12 09:46:58.614 | INFO     | paso.pre.toutil:toDataFrame:112 - toDataFrame  with column names: Index(['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5'], dtype='object')
dataset.toDatetimeComponents(inplace=False)\
.toColumnNamesFixedLen(column_length=12)\
.toContinuousCategory(quantile=False,nbin=10,drop=False)\
.head(n=3)

日志输出[=>]

2019-12-12 10:18:49.817 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Year
2019-12-12 10:18:49.861 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Month
2019-12-12 10:18:49.920 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Week
2019-12-12 10:18:49.962 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Day
2019-12-12 10:18:50.013 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Dayofweek
2019-12-12 10:18:50.060 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Dayofyear
2019-12-12 10:18:50.092 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Elapsed
2019-12-12 10:18:50.139 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Is_month_end
2019-12-12 10:18:50.182 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Is_month_start
2019-12-12 10:18:50.236 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Is_quarter_end
2019-12-12 10:18:50.280 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Is_quarter_start
2019-12-12 10:18:50.327 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Is_year_end
2019-12-12 10:18:50.368 | INFO     | paso.pre.toutil:toDatetimeComponents:346 - datetime feature component added: date_Is_year_start
2019-12-12 10:18:50.477 | INFO     | paso.pre.toutil:toDatetimeComponents:351 - datetime feature dropped: date
2019-12-12 10:18:50.478 | INFO     | paso.pre.toutil:toColumnNamesFixedLen:669 - toColumnNamesFixedLen features:: ['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5', 'date_Year', 'date_Month', 'date_Week', 'date_Day', 'date_Dayofwe', 'date_Dayofye', 'date_Elapsed', 'date_Is_mont', 'date_Is_mont_1', 'date_Is_quar', 'date_Is_quar_1', 'date_Is_year', 'date_Is_year_1']
2019-12-12 10:18:51.112 | INFO     | paso.pre.toutil:toContinuousCategory:533 - toContinuousCategory features:: Index(['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5', 'date_Year', 'date_Month',
       'date_Week', 'date_Day', 'date_Dayofwe', 'date_Dayofye', 'date_Elapsed',
       'date_Is_mont', 'date_Is_mont_1', 'date_Is_quar', 'date_Is_quar_1',
       'date_Is_year', 'date_Is_year_1'],
      dtype='object')

输出[=>]

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

Resulting DataFrame from chaining

摘要

从 Python 3.6 (PEP 484)开始,引入了类型提示。类型提示(注意:不是强类型检查)使得用下游工具对 Python 代码进行静态类型检查成为可能。

使用类型提示,toutil函数调用签名被总结如下:

# 1
paso.pre.toutil.toDataFrame(
        X: pd.DataFrame,
        columns: List = None, 
        inplace: bool = True, 
        verbose: bool = True) -> pd.DataFrame:
#2
paso.pre.toutil.toCategory(
    X: pd.DataFrame,
    bool_: bool = True,
    int_: bool = True,
    object_: str = True,
    inplace: bool = True,
    verbose: bool = True) -> pd.DataFrame:
#3
paso.pre.toutil.toContinuousCategory(
    oX: pd.DataFrame,
    features: list = [],
    drop: bool = True,
    int_: bool = True,
    float_: bool = True,
    quantile: bool = True,
    nbin: int = 10,
    inplace: bool = True,
    verbose: bool = True,
) -> pd.DataFrame:

#4
 paso.pre.toutil.toDatetimeComponents(
    oX: pd.DataFrame,
    drop: bool = True,
    components: list = [],
    prefix: bool = True,
    inplace: bool = True,
    verbose: bool = True) -> pd.DataFrame:

#5
paso.pre.toutil.def toColumnNamesFixedLen(
    X: pd.DataFrame,
    column_length: int = 1,
    col_separator: str = "_",
    inplace: bool = True,
    verbose: bool = True) -> pd.DataFrame:

本文的代码在这里给出在这里给出在这里给出

关于帕索的其他文章有:

** [## paso 为您的 Python 项目提供日志记录和参数服务

paso 为您的 Python 项目提供日志记录和参数服务

paso 为您的 Python Projectmedium.com 提供日志记录和参数服务](https://medium.com/@dr.bruce.cottman/pasos-offering-of-logging-and-parameter-services-for-your-python-project-c3ae2fd6869a) [## 第 1 部分:平衡和扩充结构化数据

数据扩充很重要,因为它从我们当前现有的数据集生成(准确地)人工数据。的…

medium.com](https://medium.com/@dr.bruce.cottman/part-1-balancing-and-augmenting-structured-data-4ade0df38662) [## 用于真实世界机器或深度学习项目的不寻常的数据清理器

介绍

towardsdatascience.com](/uncommon-data-cleaners-for-your-real-world-machine-or-deep-learning-project-f926d8ecb258)

未来,我们将通过以下文章更深入地介绍 paso :

  • 链接整个机器学习管道。
  • 第 2 部分:平衡和扩充结构化数据的更多(更好)方法。
  • 第 1 部分:分类特征的不同编码方法。
  • 第 2 部分:分类特征的深度学习编码。

如果你有一个服务或功能,或者看到一个 bug,那么就把这个 paso 项目留给一个注释。**

你的工具箱中的一个新工具,KL 散度介绍

原文:https://towardsdatascience.com/part-i-a-new-tool-to-your-toolkit-kl-divergence-5b887b5b420e?source=collection_archive---------14-----------------------

以有趣且非常直观的方式揭开熵、交叉熵和 KL 散度的神秘面纱

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

Image Source

作为一名数据科学从业者,您在工作中多久使用一次 KL 散度的概念?你对交叉熵、或 KL 散度这些概念有多少清晰和把握?一点点,只是理论上的或者看过一次就忘了的类型。

不管是什么,都没关系。你一定在网上看过一些关于这个话题的文章,甚至我也看过,但是它太理论化和无聊了,以至于我们会随着时间而忘记。但是,等等,如果我提出一个完全不同的观点,这个观点使我很好地理解了这个概念,并使它成为我武器库中的一个强有力的武器。相信我,一旦你完成了这些,你就会知道如何在每个小的分类、聚类或其他日常机器学习问题中利用这些概念。

这篇文章之后会有另一篇文章。在这一部分,我们将从了解熵开始,然后是交叉熵,最后是 KL 散度。然后,我们将使用学到的概念,并将它们应用到一个数据集中,这将在下一篇文章中使事情变得非常清楚。我会尽我最大的努力让事情简单和直观,但请随时跳转到参考资料部分,并研究更多的主题。让我们开始旅程吧。

你也可以找到我在 Youtube 上的相同主题的视频。

My Youtube video on the same topic

1.理解熵

互联网上说熵是信息增益的数量。让我简单明了地说,熵就是与事件相关的无序、不确定性、惊奇或不可预测性的数量。这是什么意思?

举个例子,看到我预测的今天的天气,

  1. 明天下雨的可能性为 50%。
  2. 明天有 75%的可能性会下雨。

哪个案例给了我们更多的信息增益或知识?

当说到 50-50 的机会时,它意味着更多的不确定性,任何事情都有可能发生,因此有更多的随机性。而在第二种情况下,75%的下雨几率意味着下雨的可能性更大,随机性更小,或者获得新信息。因此,第一种情况比第二种情况具有更高的熵。

让我们再举一个例子,抛硬币的可能结果是什么,给定

  1. 头部和尾部概率相等的无偏硬币,0.5
  2. 正面概率为 0.75 的有偏硬币

和以前一样,在第一种情况下,有 50–50 的机会正面或反面。这意味着更多的不确定性,任何事情都有可能发生,因此有更多的随机性。而在第二种情况下,75%的正面机会意味着硬币的结果更有可能是正面,随机性更小,或新信息增益。因此,第一种情况比第二种情况具有更高的熵。

计算熵

系统“H§”的熵计算如下:

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

The entropy of the system

其中 pᵢ 是第 I 个事件的概率。

让我们计算上面例子的熵,并表明无偏硬币比有偏硬币具有更高的熵。

情况一:头部和尾部概率相等的无偏硬币的熵,0.5

=-0.5 * log(0.5)-0.5 * log(0.5)= 1.0

案例二:正面概率为 0.75 的有偏硬币的熵

=-0.75 * log(0.75)-0.25 * log(0.25)= 0.81

2.理解交叉熵

按照我的说法,交叉熵是拟合度,即预测分布与实际分布的接近程度。让我简化一下,

假设我们得到了一枚正面概率为 0.75 的有偏硬币。我们没有意识到硬币的偏见,所以

案例一:我们投掷硬币 100 次,得到 70 个正面和 30 个反面。我们的估计是硬币有偏差,正面概率为 0.70。

案例二:我们投掷硬币 100 次,得到 72 个正面和 28 个反面。我们的估计是硬币有偏差,正面概率为 0.72。

我们更接近情况 II 中的实际分布,因此情况 II 中的交叉熵比情况 I 中的更低。如果碰巧我们能够无任何误差地模拟真实分布,则交叉熵将与熵相同。因此,交叉熵总是大于或等于熵。

计算交叉熵

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

The Cross-Entropy of the system

其中 pᵢ 是第事件的实际概率,q 是第 I 个事件的估计概率。所用对数以 2 为底。

让我们计算上述示例的交叉熵,并显示情况 II 比情况 I 具有更低的交叉熵,因为它更接近实际分布。

情况一:发现硬币有偏差,头部概率为 0.70。

=-0.75 * log(0.70)-0.25 * log(0.30)= 0.820

情况二:发现硬币有偏差,正面概率为 0.72。

=-0.75 * log(0.72)-0.25 * log(0.28)= 0.814

显然,情况 II 的交叉熵小于情况 I,因为它更接近实际分布。

如果估计是,硬币偏向正面的概率是 0.75,

=-0.75 * log(0.75)-0.25 * log(0.25)= 0.811(最小,这里交叉熵与熵相同)

3.了解 KL 差异

KL 散度只是拟合分布和实际分布之间的差异,即交叉熵和熵之间的差异。还可以查看这两种分布有多大差异。

计算 KL 散度

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

KL Divergence

让我们举一个同样的例子,我们得到了一个偏向硬币,正面的概率是 0.75。我们没有意识到硬币的偏见,所以

案例一:我们掷硬币一百次,得到 70 个正面和 30 个反面。我们的估计是硬币有偏差,正面概率为 0.70。

KL = 0.75 * log(0.75/0.70)+0.25 * log(0.25/0.30)= 0.0088

案例二:我们投掷硬币一百次,得到 72 个正面和 28 个反面。我们的估计是硬币有偏差,正面概率为 0.72。

KL-散度= 0.75 * log(0.75/0.72)+0.25 * log(0.25/0.28)= 0.0032

显然,第二种情况下的距离比第一种情况下的距离小,因为第二种分布更接近实际分布。

如果估计是,硬币偏向正面的概率是 0.75,

KL-Divergence= 0.75 * log(0.75/0.75)+0.25 * log(0.25/0.25)= 0(熵与交叉熵相同),所以两个分布没有区别。

4.结论

这是第一篇让我们彻底理解熵、交叉熵和 KL-散度的文章。我们也通过直观的方式和通过计算理解了这些术语,并通过例子看到了它们的价值。我希望这澄清了这个话题,给了它一个不同于传统互联网上的观点。在下一篇文章中,我打算在真实的数据集中使用这些概念。它将为每个人提供如何在每个小的分类、聚类或其他日常机器学习问题中利用这些学习到的概念的想法/直觉。不要错过它伙计们,记住我的话,它只会变得更好。

我的 Youtube 频道更多内容:

[## 阿布舍克·蒙戈利

嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…

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

写一篇清晰易懂的好文章需要很多努力。我会继续努力做好我的工作。在 关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。

5.参考

  1. https://en.wikipedia.org/wiki/Entropy
  2. https://en.wikipedia.org/wiki/Cross_entropy
  3. https://en . Wikipedia . org/wiki/kull back % E2 % 80% 93 lei bler _ divergence
  4. https://towards data science . com/demystifying-entropy-f2c 3221 e 2550
  5. https://towards data science . com/demystifying-cross-entropy-e 80 e 3 ad 54 a 8
  6. https://towards data science . com/demystifying-KL-divergence-7 ebe 4317 ee 68

选择机器学习模型

原文:https://towardsdatascience.com/part-i-choosing-a-machine-learning-model-9821eecdc4ce?source=collection_archive---------11-----------------------

挑选完美的机器学习模型的部分艺术,部分科学。

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

外面闪亮模型的数量可能是压倒性的,这意味着很多时候人们依靠他们最信任的几个,并用它们来解决所有新问题。这可能导致次优结果。

今天,我们将学习如何快速有效地缩小可用模型的范围,找到最有可能解决您的问题类型的模型。我们还将看到如何使用权重和偏差来跟踪模型的表现,并对它们进行比较。

你可以在这里找到伴随代码。

我们将涵盖的内容

  • 竞争数据科学与现实世界中的模型选择
  • 模特们的盛大集会
  • 比较模型

我们开始吧!

与指环王不同,在机器学习中,没有一个戒指(模型)可以统治所有的戒指。不同类别的模型擅长对不同类型数据集的底层模式进行建模。例如,决策树适用于数据形状复杂的情况:

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

而线性模型最适合数据集可线性分离的情况:

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

在我们开始之前,让我们稍微深入一下现实世界中的模型选择与竞争数据科学之间的差异。

竞争数据科学与现实世界中的模型选择

正如 William Vorhies 在他的博客文章中所说,“Kaggle 竞赛就像数据科学的方程式赛车。赢家在小数点后第四位击败竞争对手,就像 f1 赛车一样,我们中没有多少人会把他们误认为日常车手。投入的时间和有时极端的技术不适合数据科学生产环境。”

Kaggle 模型确实像赛车,它们不是为日常使用而制造的。现实世界的量产车型更像雷克萨斯——可靠但不浮华。

Kaggle 竞赛和真实世界针对非常不同的事情进行优化,其中一些关键差异是:

问题定义

现实世界允许您定义您的问题,并选择封装您的模型成功的度量标准。这允许你优化一个更复杂的效用函数,而不仅仅是一个单一的指标,其中 Kaggle 竞争只带有一个预定义的指标,并且不允许你有效地定义问题。

韵律学

在现实世界中,我们关心推理和训练速度、资源和部署约束以及其他性能指标,而在 Kaggle 竞赛中,我们唯一关心的是一个评估指标。想象一下,我们有一个精度为 0.98 的模型,它非常耗费资源和时间,而另一个精度为 0.95 的模型速度更快,计算量更少。在现实世界中,对于许多领域,我们可能更喜欢 0.95 的精度模型,因为我们可能更关心推理的时间。在 Kaggle 比赛中,无论训练模型需要多长时间,或者需要多少 GPU,精度越高总是越好。

可解释性

类似地,在现实世界中,我们喜欢更简单的模型,更容易向利益相关者解释,而在 Kaggle 中,我们不关注模型的复杂性。模型可解释性很重要,因为它允许我们采取具体的行动来解决潜在的问题。例如,在现实世界中,查看我们的模型并能够看到特征(例如街道上的坑洼)和问题(例如街道上发生车祸的可能性)之间的相关性,比将预测精度提高 0.005%更有帮助。

数据质量

最后,在 Kaggle 比赛中,我们的数据集被收集并为我们争论。任何研究过数据科学的人都知道,现实生活中几乎不会出现这种情况。但是能够收集和组织我们的数据也让我们对数据科学过程有了更多的控制。

激励

所有这些激励我们花费大量的时间来调整我们的超参数,以从我们的模型中提取最后的性能下降,有时,复杂的特征工程方法。虽然 Kaggle 竞赛是学习数据科学和特征工程的一种极好的方式,但它们并没有解决现实世界中的问题,如模型可解释性、问题定义或部署约束。

模特们的盛大集会

是时候开始选模特了!

当选择我们的初始模型集进行测试时,我们需要注意一些事情:

选择一组不同的初始模型

不同类别的模型擅长对数据中不同种类的底层模式进行建模。因此,一个好的第一步是快速测试几个不同类别的模型,以了解哪些模型能够最有效地捕捉数据集的底层结构!在我们的问题类型(回归、分类、聚类)领域中,我们希望尝试基于树、基于实例和基于内核的混合模型。从每个班级中挑选一个模型进行测试。我们将在下面的“要尝试的模型”一节中详细讨论不同的模型类型。

为每个模型尝试一些不同的参数

虽然我们不想花太多时间寻找超参数的最佳集合,但我们确实想尝试一些不同的超参数组合,以使每个模型类都有机会表现良好。

挑选最强有力的竞争者

我们可以使用这个阶段中表现最好的模型来给我们直觉,让我们知道我们想要进一步深入哪个类别的模型。您的权重和偏好仪表板将引导您找到最适合您的问题的模型类别。

深入研究最佳性能模型类中的模型。

接下来,我们选择更多属于我们上面列出的最佳表现类别的模型!例如,如果线性回归似乎效果最好,那么尝试套索或岭回归也是一个好主意。

更详细地探索超参数空间。

在这个阶段,我鼓励你花一些时间调整候选模型的超参数。(本系列的下一篇文章将深入探讨为模型选择最佳超参数的直觉。)在这一阶段结束时,您应该拥有所有最强模型的最佳执行版本。

做出最终选择——ka ggle

从不同的模型中挑选最终提交的作品。理想情况下,我们希望从多个类别的模型中选择最佳模型。这是因为如果你只从一类模型中进行选择,而恰好是错误的,那么你提交的所有模型都将表现不佳。Kaggle 竞赛通常允许你选择一个以上的参赛作品进行最终提交。我建议从不同的类中选择你最强的模型所做的预测,以在你的提交中建立一些冗余。

**排行榜不是你的朋友,你的交叉验证分数才是。**最重要的是要记住,公共排行榜不是你的朋友。仅仅根据你的公开排行榜分数来挑选你的模型将会导致训练数据集过拟合。当私人排行榜在比赛结束后公布时,有时你可能会看到你的排名下降很多。您可以在训练模型时使用交叉验证来避免这个小陷阱。然后选择交叉验证分数最高的模型,而不是排行榜分数最高的模型。通过这样做,您可以根据多个验证集来衡量模型的性能,而不仅仅是公共排行榜使用的一个测试数据子集,从而应对过度拟合。

做出最终选择——真实世界

**资源限制。**不同的模型占用不同类型的资源,了解您是将模型部署在带有小型硬盘和处理器的物联网/移动设备上,还是部署在云中,对于选择正确的模型至关重要。

**训练时间 vs 预测时间 vs 准确率。**了解您正在优化的指标对于选择正确的模型也至关重要。例如,自动驾驶汽车需要极快的预测时间,而欺诈检测系统需要快速更新其模型,以跟上最新的网络钓鱼攻击。对于医疗诊断等其他情况,我们关心的是准确性(或 ROC 曲线下的面积),而不是训练次数。

**复杂性与可解释性的权衡。**更复杂的模型可以使用数量级更多的特征来训练和预测,这需要更多的计算,但如果训练正确,可以捕捉数据集中真正有趣的模式。这也使得它们令人费解,难以解释。知道向利益相关者简单解释模型与在放弃可解释性的同时捕捉一些真正有趣的趋势是多么重要,是选择模型的关键。

**伸缩性。**了解您的模型需要扩展的速度和规模可以帮助您适当地缩小选择范围。

训练数据的大小。对于非常大的数据集或具有许多特征的数据集,神经网络或增强树可能是一个很好的选择。而较小的数据集可能更适合使用逻辑回归、朴素贝叶斯或 KNNs。

**参数数量。**具有大量参数的模型为您提供了很大的灵活性,以获得真正出色的性能。然而,可能会有这样的情况,你没有所需的时间,例如,从头开始训练神经网络的参数。在这种情况下,开箱即用的模型将是最佳选择!

比较模型

权重和偏差让您用一行代码跟踪和比较模型的性能。

一旦你选择了你想尝试的模型,训练它们,然后简单地添加*wandb . log({ ’ score ':cv _ score })*来记录你的模型状态。一旦你完成训练,你可以在一个简单的仪表板上比较你的模型表现!

你可以在这里找到有效完成这项工作的代码。我鼓励你分叉这个内核并摆弄代码!

就是这样,现在您拥有了为您的问题选择正确模型所需的所有工具!

模型选择可能会非常复杂,但我希望这篇指南能给你一些启发,并给你一个挑选模型的好框架。

在第二部分,机器学习模型的旋风式旅行中,我们将更深入地研究 ML 模型,何时应该使用它们!

如果您有任何问题或反馈,请随时 发微博给我

词性-单词标记

原文:https://towardsdatascience.com/part-of-speech-word-tagger-c533e8ed1f51?source=collection_archive---------16-----------------------

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

将单词分类到它们的词性并相应地标记它们的过程被称为词性标注词性标注,或简称为标注

请查看 GITHUB repo 的代码和其他酷项目

词类又称为词类词类

词性解释了一个词在句子中的用法。有八种主要的词类——名词、代词、形容词、动词、副词、介词、连词和感叹词。

用于特定任务的标签集合被称为标签集

词性标注器,或称词性标注器,处理一系列单词,并给每个单词附加词性标签。

让我们首先运行下面的 coed,看看我们到底在谈论什么。

下面是输出。这是我们正在谈论的 POS 标签列表。

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

现在让我们试着输入我们自己的句子,看看 NLTK 库如何给每个单词添加 PosTag。

注意:为了得到词性,我们必须对我们的句子进行分词。

在下面的输出中,我们可以看到 POS 标签是如何被分配给每个单词的。

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

注意:如果你得到错误,那么你可以不注释第二行,这样就可以下载 averaged_perceptron_tagger。

下一个问题是这些位置是从哪里映射来的???
它们来源于语料库或统称为语料库。

语料库是用于语言研究和编写词典的书面语和/或口语的集合。

当我们提供输入时,在语料库中搜索这些单词以获得标记的位置。
NLTK 中包含的几个语料库已经标记了它们的词性
**事实:**文本到语音转换系统通常执行词性标记

如果语料库也被分割成句子,它将有一个 tagged_sents()方法,该方法将标记的单词分割成句子,而不是作为一个大列表呈现。

注意,词性标签已经转换成大写,自从 布朗语料库 出版以来,这已经成为标准做法。

因为我们对 POS 标记很熟悉,所以让我们看看如何使用它们,以及打电话后有什么好处。

在 Jupyter 笔记本中运行下面的例子。

在下面的例子中,我们可以看到在提供了“v”即“动词”标记后,我们得到了不同的输出。

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

如果没有 POS 标签,它会认为你输入的所有东西都是名词。所以这里它认为你在传递名词“爱”(比如“甜蜜的爱”)

春分???

我们用它来检测句子中的实体。

看看下面的图片。

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

较小的方框显示单词级标记和词性标注,而大方框显示更高级别的组块

组块工作在词性标注之上,它使用词性标注作为输入,并提供组块作为输出。
简单来说,这是一种标记的推广,其中一个连续的单词序列被分配一个标记
这也被称为浅层解析。由此产生的一组单词被称为“组块”
在浅层解析中,根和叶之间最多有一层,而深层解析包括不止一层。
浅层解析也叫轻解析或分块。

要创建块树,请在 Jupyter 笔记本中输入以下代码。

下面应该是代码和一个新的窗口将会打开,块树将会显示。

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

到目前为止,我们已经讨论了词性标注和组块。我们将在未来的帖子和实现中使用上述所有概念。

如果你发现文章有什么改进,请提出意见。

粒子滤波器:非线性和非高斯世界的英雄

原文:https://towardsdatascience.com/particle-filter-a-hero-in-the-world-of-non-linearity-and-non-gaussian-6d8947f4a3dc?source=collection_archive---------2-----------------------

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

粒子滤波技术在非线性、非高斯系统中的优越性决定了其广泛的应用范围。此外,粒子滤波器的多模态处理能力也是其被广泛应用的原因之一。在国际上,粒子滤波已经应用于各个领域。

  • 在经济学领域,它被用于经济数据的预测。粒子滤波技术在非线性和非高斯系统中的优越性决定了它的广泛应用。此外,粒子滤波器的多模态处理能力也是其被广泛应用的原因之一。在国际上,粒子滤波已经应用于各个领域。数字无处不在,当它们被收集和记录时,我们称之为数据。机器学习是从数据中学习数学模型的科学。这样的模型,一旦从数据中学习
  • 在军事领域,它已被应用于雷达跟踪空中目标、空对空、空对地被动跟踪
  • 在交通控制领域,它被应用于汽车或人的视频监控。
  • 在视觉分析领域,使用粒子滤波器开发了一种新的模式识别模型,用于分割和跟踪视频序列中的嘴唇轮廓
  • 它也用于机器人的全球定位。

传统分析方法无法解决的问题现在正通过粒子模拟得到解决。

在动态系统的模型选择、故障检测和诊断中,出现了基于粒子的假设检验、粒子多模型、粒子似然比检测等方法。

在参数估计方面,通常将静态参数作为扩展状态向量的一部分,但由于参数是静态的,粒子会很快退化成一个样本。为了避免退化,常用的方法是人为地增加静态参数的动态噪声。

核平滑法,以及 Doucet 等人提出的点估计法,避免了对参数的直接采样,直接在粒子框架下使用最大似然估计(ML)和最大期望值(EM)算法对未知参数进行估计。

揭开神秘粒子滤波的神秘面纱

粒子滤波器(PF: Particle Filter)的思想基于蒙特卡罗方法,该方法使用粒子集来表示概率,可用于任何形式的状态空间模型。核心思想是通过从后验概率中提取随机状态粒子来表达其分布。它是一种序贯重要性抽样方法(序贯重要性抽样)。

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

The breakdown of the concept

简单来说,粒子滤波方法是指通过寻找一组在状态空间中传播的随机样本来近似概率密度函数,并用样本均值代替积分运算,从而得到状态最小方差分布的过程。

这里的样本指的是粒子,当样本数 N→∞时,可以近似任何形式的概率密度分布。

虽然算法中的概率分布只是真实分布的一种近似,但由于其非参数特性,可以摆脱求解非线性滤波问题时随机量必须满足高斯分布的约束,可以表达比高斯模型更广的分布。

它还具有更强的建模变参数非线性特性的能力。因此,粒子滤波能够准确表达基于观测和控制量的后验概率分布,可用于解决 SLAM 问题。

粒子滤波的发展

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

马尔可夫链蒙特卡罗改进策略

马尔可夫链蒙特卡罗(MCMC)方法通过构造具有良好收敛性的马尔可夫链从目标分布中产生样本。在 SIS 的每次迭代中,结合 MCMC 将粒子移动到不同的位置以避免退化,马尔可夫链可以将粒子推向更接近概率密度函数 (PDF)。使样本分布更加合理。

无味粒子滤波(UPF)

无迹卡尔曼滤波器(UKF)是由 Julier 等人提出的。EKF(扩展卡尔曼滤波器)使用一阶泰勒展开来逼近非线性项,并使用高斯分布来逼近状态分布。UKF 类似于 EKF,具有近似状态分布的高斯分布,但是没有线性化,仅使用了一些称为适马点的样本。

这些点通过非线性模型后,得到的均值和方差可以精确到非线性展开泰勒的二阶项,使得非线性滤波更加精确。Merwe 等人提出使用 UKF 来生成 PF 的重要性分布,称为无迹粒子滤波(UPF)。UKF 产生的重要性分布大于真实状态 PDF 的重叠,估计精度更高。

数据科学和机器人学中的粒子滤波

粒子滤波器现在广泛应用于金融市场模型的估计,特别是随机波动模型。

粒子滤波方法是递归贝叶斯滤波,当模型是非线性的并且噪声不是高斯的时,它提供了一种方便和有吸引力的方法来近似后验分布。

这些技术提供了许多问题的一般解决方案,其中线性化和高斯近似是难以处理的或者会产生太低的性能。非高斯噪声假设和对状态变量的约束的结合也可以以自然的方式进行。此外,粒子滤波方法非常灵活,易于实现,可并行化,并适用于非常普遍的设置。

基于粒子滤波器的机器人定位

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

An Indoor robot navigating its way inside a office

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

The lost robot on a map with the approximation of its location

粒子滤波器解决了应用机器人学中的许多问题。假设我们可能有想要追踪的移动物体。也许这些物体是战斗机和导弹,或者也许我们正在跟踪在田野里打板球的人。这其实并不重要。让我们考虑一下三维机器人问题的特点:

  • 多模态:我们想同时跟踪零个、一个或多个物体
  • 遮挡:一个对象可以隐藏另一个对象,导致多个对象的一次测量。
  • 非线性行为:飞机受到风的冲击,球以抛物线运动,人们相互碰撞。
  • 非线性测量:雷达给我们一个物体的距离。将其转换为(x,y,z)坐标需要平方根,这是非线性的。
  • **非高斯噪声:**当物体在背景上移动时,计算机视觉会将部分背景误认为是物体。
  • **连续:**物体的位置和速度(即状态空间)可以随时间平滑变化。
  • 多变量:我们想要跟踪几个属性,比如位置、速度、转弯率等。
  • 未知流程模型:我们可能不知道系统的流程模型

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

The initial assumption of the localized pose is noisy as we can see the points spread across the grid (map). As the robot moves further the particles converge which explains the convergence of the particles.

各种机器人表示,在仓库中导航的室内机器人可以使用粒子过滤器根据测距传感器的输入来定位自己,例如 2D 激光扫描仪或用于自动驾驶汽车的粒子过滤器可以用于融合传感器输入并识别道路上的车道标志。无人驾驶飞机可以使用粒子过滤器来优化光流。

强化学习算法和粒子滤波器

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

Reinforcement learning, in the context of artificial intelligence, is a type of dynamic programming that learns and perfects an algorithm using a system of reward and punishment.

基于粒子滤波器的强化学习(RL)算法在计算上是廉价的,且具有非常低的内存占用。包括基于粒子滤波器的直接全局策略搜索的 RL 算法将在由所选策略参数化定义的策略空间中执行搜索。

粒子过滤器可以是 RL 算法的核心概念,可以通过创建粒子来指导探索和开发,每个粒子代表一个整体策略。由于粒子滤波器执行全局搜索的能力,所得到的 RL 算法应该能够在策略空间中直接进行全局搜索,这是对传统的基于局部搜索的策略 RL 的显著改进。

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

这增加了价值,因为它继承了粒子过滤器的许多优点,其中包括:

  • 它实现起来非常简单,可以很容易地在嵌入式系统中实现在线学习
  • 它可以通过更改σ参数的值,根据可用资源(时间和 CPU 方面)使用自适应计算
  • 它可以将 RL 探索的努力集中在策略空间的最重要部分,
  • 通过改变初始噪声水平和衰减因子λ,它可以根据精度和时间的要求表现出自适应的收敛速度

粒子滤波的危害

虽然粒子滤波算法可以作为解决 SLAM 问题的有效手段,但是该算法仍然存在一些问题。主要问题是需要大量样本来近似逼近系统的后验概率密度。机器人面临的环境越复杂,描述后验概率分布需要的样本就越多,算法就越复杂。

因此,能够有效减少样本数量的自适应采样策略是算法的重点。此外,重新采样阶段会导致样本有效性和多样性的丧失,从而导致样本耗尽。如何保持粒子的有效性和多样性,克服样本的枯竭也是重采样算法的重点。

在强化学习中,粒子滤波作为全局搜索方法的一员,一般需要更多的尝试才能收敛,因为搜索的范围是最大可能的——整个策略空间。

粒子滤波器没有严格的收敛性证明。理论上,我们用全局搜索方法交换了“局部收敛的证明”,该方法没有全局收敛的证明,但至少保证不会陷入局部最优。

定位粒子滤波

原文:https://towardsdatascience.com/particle-filter-on-localisation-9e0802282aaf?source=collection_archive---------16-----------------------

粒子滤波器在自动驾驶汽车上的应用概述

在之前的帖子中,我们谈到了卡尔曼滤波器在帮助自动驾驶汽车定位方面的作用。课程在这里介绍了另一种叫做粒子过滤器的定位方法,这很有趣,我认为它可以以某种方式被塞进一篇文章中,所以我将简要介绍粒子过滤器的概念并实现它。

直觉

顾名思义,粒子过滤器构建了许多粒子来代表我们对汽车位置的猜测。考虑一个场景,一辆自动驾驶汽车在一个有 4 个主要地标的世界中行驶:

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

汽车上的传感器能够粗略计算汽车和四个地标之间的距离,同时我们初始化大量粒子,每个粒子代表汽车潜在位置的猜测。基于来自实际汽车的测量和来自虚拟汽车(粒子)的测量,我们应该能够生成每个粒子是实际汽车的后验概率,并且随着汽车继续移动,不相关的粒子将被逐渐过滤掉。

所以一般来说,粒子过滤器包括 4 个步骤:

  1. 生成一组粒子
  2. 测量每个粒子成为实际汽车(机器人)的概率
  3. 基于概率权重的重采样
  4. 重复移动到接近方向

让我们一步一步来。

产生粒子

除了粒子是我们对汽车实际位置的猜测,它应该具有实际汽车的所有功能。

这里的代码指的是课程。首先在这个 2D 世界中,一辆汽车被定义为 3 个基本元素(x, y, orientation),所以在 init 函数中,它随机初始化这 3 个元素,这里的噪声是每个动作的不确定性。其次在setset_noise功能中我们可以直接设置位置、方向和噪声。第三,汽车应该能够sensemove,而sense测量与每个地标的距离,move在汽车采取行动后返回新的状态。

现在让我们首先生成一辆真实的汽车:

[x=27.984 y=67.990 orient=4.0437]  # the real location of the car

然后生成随机猜测的粒子:

上面的代码生成了 1000 个粒子,每个粒子都有随机初始化,但噪声固定(0.05, 0.05, 5.0)

[[x=89.958 y=44.058 orient=0.5153],
 [x=67.425 y=71.905 orient=3.0930],
 [x=11.044 y=60.100 orient=2.3018],
 [x=21.359 y=43.892 orient=4.0847],
 [x=6.6223 y=41.454 orient=0.8310]]

通过打印出初始化,我们可以看到每个粒子可以有非常不同的位置和方向。

测量概率

现在让我们让汽车行驶,获得每个粒子概率的想法是,通过使用来自实际汽车的测量值,并给出每个粒子的测量值,我们应该能够计算每个粒子成为实际汽车的可能性。让我们看下面的例子:

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

假设我们将仅基于地标 2 的距离测量来测量图中粒子的概率。粒子的距离为 3,噪声为 1,也就是说测量服从高斯分布 N(3, 1),**表示粒子可以用距离 4.2、3.2、5.1、1.2、…,以不同的概率测量自身。**现在问题来了,给定我们的汽车测量值dist = 5,这个粒子也测量距离 5 的自身的概率是多少?答案是计算 5 给定分布的概率 N(3, 1)

所以在robot类中,我们需要增加两个函数:

我们可以通过以下方式来衡量每个概率:

我们的 1000 个粒子每个都将采取与实际汽车相同的移动,之后,每个粒子将通过rob.measurement_prob(Z)计算其概率给定测量Z

**经过概率计算,靠近实际位置的粒子概率较高,远离实际位置的粒子概率较低。**所以下一步要明确,对粒子进行采样,保留大概率的粒子。

重采样

现在每个粒子都被标注了不同的概率,我们希望保留高概率的粒子,在我们的下一轮迭代中使用它们。这样做的方法是基于概率权重进行重新采样。

这是一种相当原始的基于权重的采样方式,我并不完全理解。我猜np.random.choice也可以做到同样的效果,但是请记住,我们需要基于当前的概率权重重新采样一个相同大小的粒子列表。

找到方向

我们已经谈了很多关于距离和位置的问题。但是,即使我们能够得到最接近我们的汽车的位置的粒子,我们如何能够确定它的方向呢?

**事实上,我们可以通过汽车行驶到地标的距离来暗示方向。**考虑以下场景:

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

假设我们有两个粒子,粒子 1 和粒子 2,它们同样接近真实的汽车。然而,粒子 2 朝着我们汽车的同一个方向运动,而粒子 1 则相反。显然,随着时间的推移(更多轮次的迭代),粒子 1 的概率将显著降低并最终被过滤掉,而粒子 2 更有可能存活下来。

所以定位方位的方法就是让车多做动作,走的更远。最后,我们需要将代码放入一个循环中:

最终,只有位置和方向最接近的粒子才能存活下来(完整实现此处)。

参考:

  1. 【https://classroom.udacity.com/courses/cs373

在 React 组件(父组件、子组件、兄弟组件)之间传递数据

原文:https://towardsdatascience.com/passing-data-between-react-components-parent-children-siblings-a64f89e24ecf?source=collection_archive---------1-----------------------

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

React 是由 T2·脸书创建的一个 JavaScript 库。React 中的数据处理可能有点棘手,但并没有看上去那么复杂。我目前在 React 中编译了三种数据处理方法

  1. 从父母到孩子使用道具
  2. 使用回调从子进程到父进程
  3. 兄弟姐妹之间:
    (一)结合以上两种方法
    (二)使用 Redux
    (三)使用 React 的上下文 API

这个博客主要包含了这些概念的实现的汇编,这对于任何试图一目了然地掌握事物的初学者来说肯定是有益的。

从父母到孩子使用道具

让我们考虑这样的目录结构,即父组件在应用程序中呈现子组件。

App
└── Parent
    ├── Child1
    └── Child2

这是 React 中最简单的数据流方向,也是最基本的方向。

class Parent extends React.Component {state = { data : "Hello World" } 
render() {

        return (
            <div>
                 <Child1/>            //no data to send             
                 <Child2 dataFromParent = {this.state.data} />
            </div>
        ); }
}
//It is no compulsion to use the data to send as a state, simple vars or const variables could also be used to send data from Parent to Child.

只需使用 this.props.dataFromParent(只是一个用于发送 props 的变量)来访问从父节点发送到子节点的数据。

class Child2 extends React.Component {
render() {

        return (
            <div>
                The data from parent is:{this.props.dataFromParent}
            </div>
        );
    }
}

使用回调从子进程到父进程

让我们假设我需要从 Child1 向 Parent 发送一条消息——“嗨,Popsie,最近怎么样?”。为此,我需要遵循一系列步骤。

第一步: 定义一个回调函数,该函数接受一个我们认为是从 Parent.js 中的 child 访问的参数
第二步: 同样,将定义好的回调函数作为道具发送给 Child1.js

class Parent extends React.Component {state = { message: "" }callbackFunction = (childData) => { this.setState({message: childData})},render() {
        return (
            <div>
                 <Child1 parentCallback = {this.callbackFunction}/>
                 <p> {this.state.message} </p>
            </div>
        );}
}

第三步: 在 Child1.js 中使用 this . props . callback(data to parent)发送数据

class Child1 extends React.Component{sendData = () => {
         this.props.parentCallback("Hey Popsie, How’s it going?");
    },render() { 
//you can call function sendData whenever you'd like to send data from child component to Parent component.
    }
};

兄弟姐妹之间

当我还是初学者时,我很难决定选择哪种方法在兄弟姐妹之间共享数据,我知道有三种方法在兄弟姐妹之间共享数据,它们都有自己的优缺点。
方法一: 将以上两种共享数据的方法结合起来。然而,这种方法不适用于复杂的目录结构,因为人们将不得不编写大量代码来在彼此相距甚远的组件之间发送数据。然后,数据将不得不通过每个中间层被推和拉。

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

方法 2: 使用一个全局存储来维护所有子组件的状态,这些子组件需要从存储中交互和消费所需的数据— Redux

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

方法 3: 使用 React 的 Context API 关于 React 为什么升级到 Context API 以及哪一个在哪些方面更好,已经有大量的文章和博客,这两篇文章将有助于理解这一切:

[## React 上下文 API——Redux 的替代品?

将使用 Redux 进行状态管理的 React 应用程序转换为使用 React 的新上下文 API

blog.bitsrc.io](https://blog.bitsrc.io/react-context-api-a-replacement-for-redux-6e20790492b3) [## 你可能不需要 Redux

人们往往在需要之前就选择 Redux。“如果没有它,我们的应用无法扩展怎么办?”后来,开发商皱眉…

medium.com](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367)

我使用过这种方法,并且已经稍微倾向于在 Redux 上使用这种方法。

Context API 的主要优势在于它将开发者从钻柱中解救出来。(Prop-drilling 指的是将变量传递给子组件的技术。主要思想是函数式编程,将参数传递给下一个函数,依此类推)

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

Image source: Google

考虑目录结构,我们需要在 Child1 和 Child2 之间传递数据。[ Child1 必须发送消息—“SSup 兄弟??"to Child2 ]
我们使用上下文 API 通过以下方法实现这一点:

App
├── Child1
└── Child2

步骤 1: 为两个孩子创建一个提供者组件。这个提供者维护状态(组件和一些用于操作状态的回调所使用的数据)并返回一个 contextObject。提供商 JSX 组件)

第二步: 将状态和回调函数作为道具传递给 Provider 组件内部的所有子组件。

export const MContext = React.createContext();  //exporting context objectclass MyProvider extends Component {state = {message: ""}render() { return ( <MContext.Provider value={ {   state: this.state, setMessage: (value) => this.setState({ message: value })}}> {this.props.children}   //this indicates that the global store is accessible to all the child tags with MyProvider as Parent </MContext.Provider>) }}

提供者是其子代的老板(所有状态和操作这些状态的回调函数的全局存储)。需要任何东西的人必须首先联系提供者才能访问对象。

(a)要通过 Child1 设置或操作消息,它必须访问提供者并设置提供者的状态。

(b)要按 Child2 查看/访问数据,它必须访问 Provider 以获取状态。

第三步: 使用 MyProvider 组件作为两个子组件——child 1、child 2——的父组件。

class App extends React.Component {render() {
        return (
            <div>
                 <MyProvider> <div className="App"> <Child1/> <Child2/> </div> </MyProvider> </div>
        );
}
}

**第四步:**以同样的方式实现想要的结果,但是这一次,使用 ContextObject。消费者如下所述:
两个孩子——孩子 1 和孩子 2 都是提供者的消费者。从今以后,它们在消费者标签中访问提供者。

import MContext
class Child1 extends React.Component {render() { return ( <div> <Mcontext.Consumer> {(context) => ( <button onClick={()=>{context.setMessage("New Arrival")}}>Send</button> )} </Mcontext.Consumer> </div> ) }}

现在 Child2 是如何接收数据的?
简单来说,就是使用消费者标签访问提供商。

import MContext
class Child2 extends React.Component {render() { return ( <div> <Mcontext.Consumer> {(context) => ( <p>{context.state.message}}</p>)} </Mcontext.Consumer> </div> )}}

我希望这为 React 中不同组件之间的数据传递提供了清晰的实现细节。
推荐:

[## 在 React 中使用上下文

我有机会在 React Conf 2018 上谈论 React 中使用上下文的新方法。这篇博文是一篇文字…

medium.com](https://medium.com/@wisecobbler/using-context-in-react-56a8e7da5431)

通过艾将纳粹浩劫的故事传递给年轻一代

原文:https://towardsdatascience.com/passing-shoah-stories-onto-younger-generations-thanks-to-ai-69594b1fc237?source=collection_archive---------21-----------------------

数据科学如何支持大屠杀幸存者证词的传播?

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

JEWISH ARMY, TEXT OF DIKA JEFROYKIN

我的祖父朱尔斯·迪卡·杰弗罗金从来没有谈起过他在二战期间的岁月。我们只知道他是法国抵抗组织的一员。然而,我们不知道他在抵抗运动中做了什么,也不知道他参与的程度。

我一直想知道在战争年代我的家庭发生了什么,我不断地研究我的家族史。在某个时候,我放弃了,并停止了寻找,认为我再也找不到比他的一些朋友在乔治·洛因格的书*“Les réresistences juives pendant l ’ occupation”*中发表的十行传记更多的东西了。

然后,上个月,我第一次去波兰进行了一次“寻根”之旅。这非常有力,提醒了我传承历史的重要性,尤其是在如今纳粹浩劫幸存者越来越少的时候。

“为了死者和生者,我们必须作证。”, 埃利·威塞尔

我一直有一种感觉,我需要发现我的家族历史,并为下一代做一个“目击者的目击者”。

所以参观完之后,我又开始寻找。一次偶然的机会,我在网上发现,在华盛顿 DC 的美国大屠杀纪念馆保存的一份文件中提到了我祖父的名字。我让他们寄给我,两天前我收到了。我惊奇地发现,这是我祖父关于他在法国抵抗运动中的作用的证词!他的故事的 26 页法文 PDF 草稿。

什么能帮助我?

我想清理这段文字,让每个人都更容易阅读,以传播和保存他的记忆,并能够出版它,以帮助下一代获得关于纳粹浩劫历史的洞察力和知识。我们生活在一个有趣的时代,随着人口的减少,越来越少的年轻人有机会听到幸存者的声音,但可以让年轻人接触幸存者的技术却在不断发展。

作为一名数据科学家,我一直试图利用我的技能做好事,我坚信人工智能可以成为社会变革的伟大工具。使用人工智能来帮助我分享我祖父的故事显然是下一步。

PDF 转换为文本文档

为了能够纠正错误和他的手写笔记,我需要一个文本文档。我使用了基于深度学习的文本识别:基于 LSTM谷歌的 OCR 引擎宇宙魔方

为了重现下面的代码,你需要 pip 安装所有导入的包。此外,你需要安装宇宙魔方。

词频

除此之外,我使用了一些 NLP 技术、方法、技术、算法来进行总结。下面是一些用 nltkgensim 提取摘要的例子。

**# Most frequent words** ['Juifs', 'Joint', "l'AJ", "l'Agence", 'Juive', "l'argent", 'jeunes', 'fait', 'France', 'fonds', '11', 'accord', 'Jefroykin', 'fallait', 'faire']*# '11' is an OCR mistake for 'Il'***# In English, powered by Google Translate** ['Jews', 'Joint', 'AJ', 'Agency', 'Jewish', 'money', 'young', 'made', 'France', 'funds', '11','agreement','Jefroykin','must','do']

所有文本中出现频率最高的词会直接给你主题。我们可以看到作者的名字’ Jefroykin ‘,他合作过的两个组织’ Joint ‘为 American Joint 和’ L’AJ '为 Jewish Army ,他的组织。

摘录摘要

今天,人们的注意力持续时间很短,特别是在消费新闻和其他信息时,所以摘要是参与的关键部分。这就是为什么我使用一些 NLP 技术、方法、技术和算法来自动总结较长的文档。这里有一些用 nltkgensim 摘录的例子。

**# NLTK 2 Sentence Summary:** Il y a donc eu un accord confidentiel entre la Direction  européenne du Joint située à Lisbonne, et Dika Jefroykin, représentant du Joint et France, #'autorisant à récolter de     l'argent -remboursable après la guerre —  Le but du Passage en Espagne de Jefroykin était triple, D'abord, diriger un convoi "cobaye" après une longue interruption des passages. Deuxièmement, rétablir une liaison entre le Joint au Portugal sa représentation en Espagne et l'AJ en France, Troisièmement, assurer un accord avec l'Agence Juive pour que les jeunes qui souhaitaient rejoindre la Brigade Juive en Palestine puissent être assurés de pouvoir le faire,**# Gensim Summary:** Il y a donc eu un accord confidentiel entre la Direction  européenne du Joint située à Lisbonne, et Dika Jefroykin, représentant du Joint et France, #'autorisant à récolter de     l'argent -remboursable après la guerre —  Le but du Passage en Espagne de Jefroykin était triple, D'abord, diriger un convoi "cobaye" après une longue interruption des passages.

翻译

然后,我将这些摘要翻译成英文,让更多的人能够看到文本,这要感谢谷歌云翻译 API

**# NLTK summary translated** There was therefore a confidential agreement between the European Directorate of the Joint located in Lisbon, and Dika Jefroykin, representative of the Joint and France, # authorizing to collect money-refundable after the war - The purpose of the Passage in Spain of Jefroykin was triple, First, to lead a convoy "guinea pig" after a long interruption of passages. Secondly, to re-establish a liaison between the Joint in Portugal its representation in Spain and the AJ in France, Third, to ensure an agreement with the Jewish Agency so that young people who wished to join the Jewish Brigade in Palestine can be assured of being able to do so ,**# Gensim summary translated** There was therefore a confidential agreement between the European Directorate of the Joint located in Lisbon, and Dika Jefroykin, representative of the Joint and France, # authorizing to collect money-refundable after the war - The purpose of the Passage in Spain of Jefroykin was triple, First, to lead a convoy "guinea pig" after a long interruption of passages.

这两个摘要都为我们提供了第一页的含义,即使一句话的摘要似乎已经足够好了。使用这些技术帮助我完成了一个文本文档,并理解了证词的关键部分。

AI 为好

就像互联网和社交媒体一样,多年前,人工智能也应该被用来继续教育的重要工作——纳粹浩劫和其他过去的种族灭绝,以及今天仍在世界各地发生的暴行。

忘记过去的人注定要重复过去。”,温斯顿·丘吉尔。

此外,是时候将人工智能引入慈善和人类组织了。高科技工作者应该支持它,并为社会公益贡献他们的知识。我管理着一个名为 Data For Good Israel 的组织,我们正试图利用人工智能的巨大力量来做到这一点。让我们传播这个消息吧!

PS:如果你对见证感兴趣,我可以和你分享,给我发消息就好。

我要感谢来自 Zencity 的同事和朋友,他们在这个项目中发挥了重要作用:Inbal Naveh Safir、Traci Siegel、Ori Cohen 和 Yoav Talmi。

Samuel JefroykinZencity.io 的一名数据科学家,他试图积极影响城市的生活质量。他还共同创立了 Data For Good Israel,一个致力于利用数据的力量解决社会问题的社区。

通过可怕的数据科学课后作业:2021 年更新

原文:https://towardsdatascience.com/passing-the-dreaded-data-science-take-home-assignment-8ae5d55f256b?source=collection_archive---------6-----------------------

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

“这只需要你 3 到 5 个小时的时间。”

“作为我们流程的一部分,接下来是简单的标准化带回家作业”

“应该不到 3 个小时(我们真的是这个意思)。”

这些原话你见过多少次了?希望在你的数据科学面试过程中不会太多。但是,如果你是许多正在找工作的数据科学家中的一员,你可能会发现自己正在做一个数据科学带回家的作业,它是一个压缩文件,里面有一个长达 10 页的需求 pdf。

招聘人员承诺,你的任务有一个复杂的评分过程,不会超过几个小时。但是突然到了凌晨 2:30,三天后,15 个小时的编码疲劳开始了,你甚至没有想过尝试一下 GAM 模型,看看它是否能让你的模型的 F1 分数提高 3%。

是的,数据科学带回家的作业应该被取缔,禁止,至少可能在你工作的时候得到补偿,在你被干掉之前,这些工作可能真的会碰到招聘经理的垃圾邮件过滤器。是的,我表面上写了我在 T11 之前有多恨他们。但不幸的是,似乎不知何故,他们会留在这里。

有兴趣聘请一名数据科学家和机器学习工程师吗?不知道如何建立标准化的数据科学挑战?

阅读更多关于我们如何帮助公司构建定制的数据科学招聘解决方案的信息

我甚至没有说这只是未经证实的初级候选人的过程的一部分。上个月在几乎每一次我与 采访询问 客户的反馈会议中,他们提到了一次采访,在那次采访中,他们收到了一份带回家的作业,花了他们十几个小时才完成,结果得到的只是一封迅速拒绝的电子邮件。为什么这种事情还在继续发生?为什么公司浪费应聘者的时间,却没有任何反馈?

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

事实是,对于许多没有标准化面试流程的公司来说,这个流程就像是一个过滤器。开发技术面试问题需要数据科学团队的知识历史,而与软件工程师相比,这是不存在的。

所以如果你必须,不得不,并且没有其他选择的话,做一个带回家的作业。这里有几个步骤,以确保更顺利的过程。

想练习一系列数据科学带回家的挑战吗?退房 面试查询 为你下次带回家做准备。

提前询问期望和未来反馈

你至少应该从招聘人员或招聘经理那里了解三件事:

  1. 如果有机会的话,除了做带回家的作业,是否还有其他选择。
  2. 你会得到对你工作的反馈,而不是一封标准化的拒绝邮件。
  3. 你了解你将被评分的标准和程度。

首先,仔细检查公司是否会给你提供技术筛选,而不是带回家的作业。如果替代方案意味着让候选人退出面试过程,许多公司都会这么做。数据科学现在炙手可热,我的许多朋友告诉我,他们选择上一个雇主是因为他们在没有带回家的情况下,面试过程进行得更快。

不过,这里还有一个检查,这家初创公司是否会向资深候选人提供技术筛选,然后只允许你为同一职位选择数据科学带回家的挑战?他们真的不应该,因为那是违法的。

第二,如果你提前征求反馈,但没有得到回应,或者不明白你将被评分的标准,我会重新考虑面试过程。为什么要经历自由工作的混乱,而没有至少一些反馈,也不知道别人会如何评价你?这就像是没有任何期望地去参加 SAT 考试

我知道很难去反对正在面试你或将要面试你的人或公司。但是要明白这是一种互利的关系。你们两个人都在这个过程中,他们面试你是因为他们想看到你成功,而不是他们希望你做些无脑的工作。

需要一个邮件模板来复制要求两个条件?这里有一个模板,欢迎你使用。

你好,招聘人员姓名,

谢谢你送来带回家的作业。我很高兴可以开始使用它,并且一定会在 X 天内将它和我完成的解决方案一起发送回来。

另外,我想知道是否可以给我一套关于作业评分的通用指南。我肯定要确保我专注并展示了带回家的正确技能,而不是不小心掉进兔子洞。

最后,如果在我提交了带回家的作业后,我能得到一些反馈,我会非常感激,不管我是否会继续面试。了解我做错了什么,或者我在技术成长方面做得好的地方,这真的意义重大。

谢谢!

提问并陈述假设

数据科学的课后作业是一场冗长的单边面试。在一个典型的现场面试中,如果你的面试官是一个好人,你可以问一些关于提示的问题,他们会给出深思熟虑的回答。在数据科学带回家挑战中,你应该做同样的事情。

在接到带回家的任务后,试着立即列出一份你必须发给招聘人员/招聘经理的问题清单。即使你的问题得到了答案或者没有得到答案,也要确保在你的作业中陈述你的假设。我这么说是什么意思?

如果您决定仅使用简单的插补模型来填充缺失值,而不是使用高级技术,该怎么办?陈述一下。写在评论里吧。做一些事情,让他们明白你在这项任务上花费的时间有限。

如果您最终使用 XGboost 而不是 Tensorflow,因为您意识到您可以更快地迭代,即使它在性能上可能不太强大,会怎么样?陈述一下。在你的简历中告诉招聘经理。他们需要理解你为什么选择你所做的模型。

写下你认为需要让你的评分者知道的一切。招聘经理忘记了编写代码和构建模型需要多长时间。他们是经理。他们不写代码。

放入建模基线

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

让我们假设数据科学的家庭作业更多的是建模挑战,而不是分析师挑战。系统会提示您从数据集创建模型。您直觉地知道,您必须清理、训练和验证数据集之外的模型,但是您能够并且实际上应该做多少呢?

这里有一个大概需要你至少三个小时的清单。

  • 数据清理
  • 最小特征选择
  • 估算缺失值
  • 创建分类管道
  • 尝试使用几个 sci-kit 学习分类器进行训练
  • 使用网格搜索调整超参数

嘣。现在,您的实现将达到他们期望的一般最低基线。根据你在功能选择上工作的时间长短,可能会多加或减两到三个小时。

同样,如果你不希望付出额外的努力,并希望评分者理解这一点,那么就把它写进去。让他们知道。

让你的代码可读

没有什么比看着杂乱的代码更让数据科学招聘经理拒绝你的了。在你完成所有的数据清理和模型构建之后,记得重构你的代码。将你的任务分成不同的功能。不要让混乱的代码排在 main()函数的下面。试着换个角度看问题,或者问朋友他们是否能理解。

对于数据科学家来说,这是一个很好的代码组织和可读性指南。这是关于以一种容易理解的方式组织你的项目。我偶然发现了这个,但它完全有道理。 Cookiecutter 数据科学框架允许数据科学项目的标准化流程。直接取自他们的网站:

  • 更轻松地与您合作进行分析
  • 从你对过程和领域的分析中学习
  • 对分析得出的结论充满信心

我会注意到,用完整的格式来组织你的项目肯定会花费你几个小时以上的时间。但话说回来,当你决定做带回家的作业时,你已经明白了成本。

编写测试和注释

我有没有提到把你脑子里的一切都记录到纸上?这包括写评论和测试你的代码,如果它适用的话。可读性和代码的效率一样重要,如果你在每个函数上都写了很好的注释块,这将有助于传达你的代码应该如何运行,以及你为什么要这样重构它。遵循一般的 Python 惯例来确保你是可靠的。

用 500 字以下总结你的思维过程!

还记得高中英语的时候,所有的论文都是由引言、内容,然后是结论组成,结论重复了引言。做到这一点,但在 500 字以内。在一天结束时,最有可能的情况是,看你带回家作业的人会花总共五分钟的时间来理解它,然后继续浏览 Reddit。你要让他们尽可能容易地理解你的数据科学带回家的作业是有史以来最好的带回家的作业。

感谢阅读!

我是如何通过谷歌云专业数据工程师认证考试的

原文:https://towardsdatascience.com/passing-the-google-cloud-professional-data-engineer-certification-87da9908b333?source=collection_archive---------0-----------------------

没有推荐的 3 年实践经验

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

Google hoodie: on. Game face: on. Photo from the video version of this article on YouTube.

注: 本文献给 2019 年 3 月 29 日前的谷歌云专业数据工程师认证考试。在这个日期之后,有一些更新。我已经将这些包含在 临时演员 部分

所以你想买一件和我在封面照片里的一样的新帽衫?

或者你一直在考虑获得谷歌云专业数据工程师认证,你想知道如何去做。

在过去的几个月里,我一直在使用谷歌云参加课程,为专业数据工程师考试做准备。然后我就拿了。我通过了。几周后,我的连帽衫到了。证书来得更快。

这篇文章将列出一些你可能想知道的事情,以及我获得谷歌云专业数据工程师认证的步骤。

你为什么想做谷歌云专业数据工程师认证?

数据无处不在。人们需要知道如何建立能够处理和利用数据的系统。谷歌云提供了构建这些系统的基础设施。

你可能已经掌握了使用谷歌云的技能,但你如何向未来的雇主或客户展示这一点呢?两种方式。通过项目组合或认证。

一份证书对未来的客户和雇主说,“嘿,我有技能,我已经努力获得认证。”

谷歌的一句话总结了这一点。

展示您在谷歌云平台上设计和构建数据处理系统以及创建机器学习模型的熟练程度。

如果你还不具备这些技能,浏览认证的学习材料意味着你将学习如何在 Google Cloud 上构建世界一流的数据处理系统。

谁会想做谷歌云专业数据工程师认证?

你已经看过数据了。云在增长。它会一直留在这里。如果你还没有看到这些数字,请相信云正在增长。

如果你已经是一名数据科学家、数据工程师、数据分析师、机器学习工程师或正在寻找数据领域的职业转变,谷歌云专业数据工程师认证适合你。

能够使用云技术正成为任何一种以数据为中心的角色的要求。

做一个好的数据工程师/数据科学家/机器学习工程师需要证书吗?

号码

没有证书,你仍然可以使用谷歌云来处理数据解决方案。

证书只是现有技能的一种验证方法。

这要花多少钱?

参加认证考试需要 200 美元。如果你失败了,你将不得不再次支付重考费用。

准备课程和使用平台本身都有相关的成本。

平台成本是你使用谷歌云服务的费用。如果你是一个狂热的用户,你会很清楚这些。如果没有,并且您只是浏览了本文中的培训材料,您可以创建一个新的 Google Cloud 帐户,并在 Google 注册时提供的 300 美元积分内完成所有这些内容。

我们马上会谈到课程成本。

认证持续多长时间?

两年。之后,你需要再次参加考试。

由于 Google Cloud 每天都在发展,证书的要求很可能已经改变了(当我开始写这篇文章时,我发现情况就是这样)。

考试需要准备什么?

谷歌推荐 3 年以上的行业经验和 1 年以上使用 GCP 设计和管理解决方案的专业水平认证。

这两样我都没有。

更像是 6 个月一次。

为了补充这一点,我利用了在线培训资源的组合。

我学了什么课程?

如果你和我一样,没有推荐的要求,你可能想看看下面的一些课程来提升自己的技能。

以下课程是我用来准备认证的。它们是按照完成的顺序排列的。

我列出了通过认证考试的成本、时间表和帮助。

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

Some of the incredible online learning resources I used to upskill myself for the exam. In order, A Cloud Guru, Linux Academy, Coursera.

谷歌云平台上的数据工程 Cousera 上的专业化

费用: $49 美元每月(7 天免费试用后)
**时间:**1-2 个月,每周 10+小时
有用性: 8/10

Coursera 上的谷歌云平台数据工程是与谷歌云合作完成的。

它分为五个子课程,每个子课程每周花费大约 10 个小时的学习时间。

如果你不熟悉谷歌云上的数据处理,这种专业化就像是 0 对 1。您将使用名为 QwikLabs 的迭代平台完成一系列实践练习。在此之前,将由谷歌云从业者就如何使用不同的服务,如谷歌 BigQuery,Cloud Dataproc,Dataflow 和 Bigtable 进行讲座。

云专家介绍谷歌云平台

**费用:**免费
**时间:**1 周,4-6 小时
有用性: 4/10

不要把有用性分数低当成这门课没用。远非如此。它得分较低的唯一原因是它没有专注于专业数据工程师认证(这可以从标题中收集到)。

在完成 Coursera 专业化认证后,我将此作为复习,因为我只在少数专业用例中使用过谷歌云。

如果你来自另一家云服务提供商,或者以前从未使用过谷歌云,你可能想参加这个课程。这是对谷歌云平台整体的一个很好的介绍。

Linux Academy 谷歌认证专业数据工程师

费用: $49 美元每月(7 天免费试用后)
**时间:**1-4 周,每周 4 小时以上
有用性: 10/10

完成考试后,回想我上过的课程,Linux Academy Google 认证专业数据工程师是最有帮助的。

这些视频,以及数据档案电子书(课程附带的一个很棒的免费学习资源)和练习考试使这门课程成为我用过的最好的学习资源之一。

考试结束后,我甚至在一些笔记中向团队推荐了它。

Slack Notes
考试中的一些内容是 Linux Academy 或云专家或 Google Cloud Practice 考试中没有的(预期)
1 个问题,其中包含数据点的图表以及对它们进行聚类所需的等式(例如 cos(X)或 X +Y )
了解数据流、Dataproc、数据存储、Bigtable、BigQuery、 Pub/Sub 以及如何使用它们是必须的
。考试中的两个案例研究与练习中的案例研究完全相同,尽管我在考试中根本没有阅读这些研究(问题提供了足够的洞察力)
了解一些基本的 SQL 查询语法非常有帮助,尤其是对于 BigQuery 问题
。Linux Academy 和 GCP 提供的练习考试与考试中的问题风格非常相似。 我会多次这样做,并使用它们来找出你的弱点
一点押韵来帮助 data proc:“data proc鳄鱼和 Hadoop 大象计划点燃一把火,煮一个蜂巢”(data proc 处理 Hadoop,Spark, 蜂巢和猪)
数据流是流动的光束(数据流处理阿帕奇光束)
“全世界的每个人都能联想到一把制作精良** 洗过的扳手。” (Cloud Spanner 是一个完全为云设计的数据库,它符合 ACID 标准,全球可用)
。很容易知道关系和非关系数据库选项的名称(例如 MongoDB、Cassandra)
。IAM 角色对于每个服务略有不同,但了解如何将用户与设计工作流区分开来是有帮助的(例如数据流工作者角色可以设计工作流,但看不到数据)**

这对现在来说可能足够了。每次考试的里程可能会有所不同。Linux 学院的课程将提供 80%的知识。

谷歌云 1 分钟视频

****费用:**免费
**时间:1–2 小时
有用性: 5/10

这些都是在云专家论坛上推荐的。其中许多与专业数据工程师认证无关,但我挑选了一些我认可的。

在学习一门课程时,有些服务可能看起来很复杂,所以在一分钟内听到对某项服务的描述是很好的。

备考云专业数据工程师考试

**费用: $49 认证或免费(无认证)
**时间表:**1-2 周,每周 6 小时以上
**有用性:不适用

我在考试前一天发现了这个资源。由于时间限制,我没有这样做,因此缺乏有用性评级。

然而,在浏览课程概述页面后,它看起来像是一个很好的资源,可以将你在 Google Cloud 上学习的所有关于数据工程的东西汇集在一起,并突出任何弱点。

我把这个课程作为资源发给了我的一个准备认证的同事。

谷歌数据工程备忘单作者特立独行的林

****费用:**免费
**时间线:**不适用
**有用性:不适用

这是我在考试后偶然发现的另一个资源。我看了一下,它既全面又简洁。另外,它是免费的。这可以用来在练习考试之间或者甚至在认证之后提醒你自己。

获得李圣杰的谷歌云认证

****费用:**每门课程 39 美元(共 3 门课程 49 美元)
**时间表:**自定进度
**有用性:不适用

Sam 是一名大数据工程师和 web 开发人员,他将自己的 Google Cloud 知识融入到课程中。有三种不同的课程,包括专业云架构师专业数据工程师助理云工程师。这是您需要的所有谷歌云认证的一站式商店。

课后我做了什么?

在接近完成课程后,我提前一周预约了考试。

有一个截止日期是复习你所学内容的一个巨大动力。

我多次通过 Linux Academy 和 Google Cloud 的模拟考试,直到我每次都能以 95%以上的准确率完成它们。

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

Passing the Linux Academy practice exam with over 90% for the first time.

每个平台的测验都是相似的,但我发现复习我经常出错的答案,并写下为什么出错,有助于修复我的弱点。

我参加的考试使用了在 Google Cloud 上为两个案例研究设计数据处理系统作为主题(这是从 2019 年 3 月 29 日开始更改的)。从头到尾都是多项选择。

我花了大约两个小时。比我参加的任何模拟考试都要难 20%。

我怎么强调模拟考试的价值都不为过。

如果再来一次,我会改变什么?

多练习考试。更实用的知识。

当然,你总是可以做更多的准备。

建议要求列出了使用 GCP 3 年以上的时间。但是我没有这个,所以我必须处理我所拥有的。

临时演员

考试更新于 3 月 29 日。本文中的材料仍将为您提供一个良好的基础,但是,注意一些变化是很重要的。

谷歌云专业数据工程师考试的不同部分(版本 1 )

1.设计数据处理系统
2。建立和维护数据结构和数据库
3。分析数据和实现机器学习
4。为分析和优化建立业务流程模型
5。确保可靠性
6。可视化数据和倡导政策
7。安全性和合规性设计

谷歌云专业数据工程师考试的不同部分(版本 2 )

1.设计数据处理系统。建立和运行数据处理系统
3。操作化机器学习模型(大部分变化都发生在这里)
【新增】**
4。确保解决方案质量**

版本 2 将版本 1 的第 1、2、4 和 6 部分合并为 1 和 2。它还将第 1 版的第 5 节和第 7 节合并为第 4 节。第二版的第三部分已经扩展到包括谷歌云的所有新的机器学习功能。

因为这些变化是最近才发生的,所以许多培训材料还没有机会更新。

然而,浏览本文中的材料应该足以涵盖您所需内容的 70%。我会将它与你自己对以下内容的一些研究结合起来(这些在考试的第二版中有介绍)。

正如你所看到的,考试的最新更新非常关注谷歌云的 ML 功能。

更新 29/04/2019: 来自 Linux 学院课程导师马修·乌拉森(Matthew Ulasien)的一段话。

仅供参考,我们计划更新 Linux Academy 上的数据工程师课程,以反映五月中/下旬开始的新目标。

*****更新 2019 年 1 月 6 日:*Linux Academy 课程导师马修·乌拉森的又一条消息。

我们现在正处于计划阶段。我估计要花一个月的时间来完全更新它。

考试后

当你完成考试时,你只会得到及格或不及格的结果。建议是至少要达到 70%,这就是为什么我在模拟考试中至少要达到 90%。

一旦你通过了测试,你将会收到一封电子邮件,里面有一个兑换码和你的官方谷歌云专业数据工程师证书。恭喜你!

你可以在一个专门的谷歌云专业数据工程师商店使用兑换代码,那里有很多赠品。有 t 恤,背包,帽衫(这些到了库存可能会有变化)。我选择了帽衫。

现在你已经通过了认证,你可以(正式地)展示你的技能,然后继续做你最擅长的事情,建筑。

两年后再见,重新认证。

PS 如果你有任何问题,或者想要澄清什么,你可以在 TwitterLinkedIn 上找到我。在 YouTube 上也有这篇文章的视频版本。

PPS 非常感谢所有在上述课程中出色的讲师,以及 Max Kelsen 为学习和准备考试提供的资源和时间。

纵向生存数据的患者治疗时间表

原文:https://towardsdatascience.com/patient-treatment-timelines-for-longitudinal-survival-data-81c65f5f3fba?source=collection_archive---------24-----------------------

我是一所研究型大学的生物统计学家,我经常发现自己在处理纵向生存数据。与任何数据分析一样,我需要检查我的数据的质量,然后再决定采用哪种统计方法。

这篇文章包含了一些可重复的例子,展示了我如何更喜欢直观地探索包含纵向暴露或协变量的生存数据。我为每个病人创建了一个“治疗时间表”,最终产品看起来像这样:

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

每条线代表一名患者,每个方块代表特定点的测量值。我发现这些图表有助于寻找随访时间、治疗和遗漏的模式或差异。它们还允许我在为我的分析进行不同的数据操作时验证我的编码是正确的。

对于下面的例子,我生成纵向生存数据集。我跳过了我是如何制作这些数据的,因为这不是这篇文章的重点,但是如果你对数据生成有疑问,请告诉我。总的来说,我试图从生存数据分析的角度出发,你已经计算了每个人的事件发生时间。

为了制作这些图表,我的第一步是加载包tidyverse,因为我使用了来自dplyrtidyrforcatsggplot2的函数。

library(tidyverse)

下面是数据生成代码。如果你对我是如何制作的感兴趣,你可以查看评论,但如果不是,我建议你复制并粘贴到你的 **R** 控制台来尝试绘图代码。

set.seed(7)
# The data sets I make these visualizations for are typically 100-500 patients in size, but for space purposes I'll set my n to only 50.
n <- 50dat <-
  tibble(.rows = n) %>% # empty data frame / tibble with n rows
         mutate(pt_id = factor(row_number()), # patient ids are 1-n
         pt_trt_prob = runif(n,0,1), # randomly generate a treatment probability for each patient so we can see patterns
         months_followup = round(runif(n, 0, 20)), # randomly generate length of time in the study
         death = rbinom(n, 1, .5)) %>% # death randomly occurs at any time point. Obviously an unrealistic assumption. :)
  group_by(pt_id) %>% # group by patient so we can do more data manipulation
  complete(months_followup = full_seq(0:max(months_followup), 1)) %>% # add in all the months patients are in the study
  fill(pt_trt_prob, .direction = "up") %>% # fill in the treatment probability I made earlier so I can use this to add treatment for every time point
  ungroup() %>% # no longer need patients grouped 
  mutate(trt = factor(rbinom(row_number(), 1, pt_trt_prob^2)), # fill in treatment for everyone based on their treatment probability
  death = replace_na(death, 0)) %>% # also fill in death 
  select(pt_id, months_followup, trt, death) # remove leftover columns from data generation

我们来看数据。它是“长”格式的,在我的(假)研究中,每个患者的 ID 都是重复的。在每个月,我们都知道他们是否在接受治疗,以及他们是否在那个时间点死亡。第一个例子没有任何遗漏。

knitr::kable(head(dat))

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

我们现在可以用一种非常基本的方式来绘制我们的数据。我们真的只需要在aes thetics 中指定x-轴是时间,y-轴是主题 id,col or 应该对应治疗,我们的线应该按照主题*group* 连接在一起。别忘了最后一个!然后我们可以说我们希望geom_line为每个主题制作一个基本时间轴,时间轴上的点应该是正方形(geom_point映射函数中的shape = 15)。

瞧啊!一个可爱的病人治疗时间表。

dat %>% ggplot(aes(x = months_followup, y = pt_id, group = pt_id, col = trt)) + geom_line() + geom_point(shape = 15)

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

好吧,不是那个可爱。但是那一点点代码真的是剧情的核心!如果你想添加死亡(或任何其他事件)的标记,并根据随访时间的长度重新排列,只需要一点额外的数据操作和一行额外的ggplot2代码。

dat %>%
 group_by(pt_id) %>% # make a new column with all patients last follow up visit
  mutate(last_month_followup = max(months_followup), # new variable for month that patients died, if they died 
  month_death = case_when(death == 1 ~ last_month_followup, TRUE ~ NA_real_)) %>% # reorder pt id by last month of follow up (highest to lowest)
# without fct_rev, chart is arranged in opposite direction (lowest to highest) 
  ungroup() %>%
  mutate(pt_id = fct_rev(fct_reorder(pt_id, last_month_followup))) %>%
  ggplot(aes(x = months_followup, y = pt_id, group = pt_id, col = trt)) +
  geom_line() +
  geom_point(shape = 15) + # add in a new mapping layer of points that correspond to death 
  geom_point(aes(x = month_death, y = pt_id), col = "black", shape = 4)## Warning: Removed 515 rows containing missing values (geom_point).

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

不要担心删除缺失值的警告—这是因为我们的month_death最多有NA个月,所以geom_point不知道在哪里放一个‘x’标记。

最后,让我们努力让情节看起来更好一点:

dat %>%
 group_by(pt_id) %>%
 mutate(last_month_followup = max(months_followup), month_death = case_when(death == 1 ~ last_month_followup, TRUE ~ NA_real_)) %>% 
 ungroup() %>% 
 mutate(pt_id = fct_rev(fct_reorder(pt_id, last_month_followup)), # make the treatment variable labels nicer
        trt = factor(trt, levels=0:1, labels=c("No","Yes"))) %>%
 ggplot(aes(x = months_followup, y = pt_id, group = pt_id, col = trt)) +
 geom_line() +
 geom_point(shape = 15) +
 geom_point(aes(x = month_death, y = pt_id), col = "black", shape = 4) +
 theme_bw() + 
 labs(x = "Months of Follow-Up", y = "Patient ID", col = "Treatment", title = "Patient Treatment Timeline", subtitle = "x indicates month of patient death") +
 # edit legend box and make patient ids small
 theme(axis.text.y = element_text(size=6), legend.position = c(.6, .9), legend.direction = "horizontal", legend.background = element_rect(linetype="solid", colour ="black")) + 
# remove extra space around timeline
 scale_x_continuous(expand=c(0.01,0.01)) + # set the color of the lines and points
 scale_color_manual(values=c("dodgerblue","firebrick1"))## Warning: Removed 515 rows containing missing values (geom_point).

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

我从来没有制作过这些情节中的一个用于出版,所以我不介意字幕包含图例信息。如果您希望图例中有month_death标记,您可以更改:

geom_point(aes(x = month_death, y = pt_id), col = "black", shape = 4)

收件人:

geom_point(aes(x = month_death, y = pt_id, shape = month_death), col = "black")

我们可以按照同样的步骤,为一个连续变量制作时间线。

同样,这是数据生成代码,因此您可以自己绘制这些图:

dat_cc <-
 tibble(.rows = n) %>%
 mutate(pt_id = row_number(),
        months_followup = round(runif(n, 0, 12)), # random months of follow up
        pt_cov_mean = runif(n, 80, 150), # random mean of a patient's covariate measures
        death = rbinom(n, 1, 0.5)) %>% # random death
 group_by(pt_id) %>%
 complete(months_followup = full_seq(0:max(months_followup), 1)) %>%
 fill(pt_cov_mean, death, .direction = "up") %>% 
 mutate(last_month_followup = max(months_followup),
        death_date = case_when(death == 1 ~ last_month_followup,
                               TRUE ~ NA_real_)) %>%
 ungroup() %>%
 mutate(cov = rnorm(row_number(),
        pt_cov_mean, 10)) # everyone's covariates are close to their original mean (use to see patterns later)

这一次,我在我的模拟协变量测量中纳入了患者水平的遗漏,以显示我们如何使用这些图来查看遗漏的潜在模式。

dat_cc_samp <-
 dat_cc %>%
 mutate(idx = row_number()) %>%
 sample_frac(.4, weight = pt_cov_mean^3) %>%
 # sample 40% of data, with weights for the sample determined by the patient's mean covariate. This would mean patients with a higher mean covariate measure are more likely to have missing data.
 pull(idx)dat_cc_miss <-
 dat_cc %>%
 mutate(cov = case_when(row_number() %in% dat_cc_samp ~ NA_real_,
                        TRUE ~ cov)) %>%
 select(pt_id, months_followup, cov, death)

再次查看我们将使用的数据:

knitr::kable(head(dat_cc_miss))

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

我们可以绘制数据,并用灰色的时间线点和线来观察这种缺失:

dat_cc_miss %>%
 group_by(pt_id) %>%
 mutate(last_month_followup = max(months_followup),
        month_death = case_when(death == 1 ~ last_month_followup,
                                TRUE ~ NA_real_)) %>%
 ungroup() %>%
 mutate(pt_id = fct_rev(fct_reorder(factor(pt_id), last_month_followup))) %>%
 ggplot(aes(x = months_followup, y = pt_id, group = pt_id, col = cov)) +
 geom_line() +
 geom_point(shape = 15) +
 geom_point(aes(x = month_death, y = pt_id), shape=4, col="black") + theme_bw() +
 labs(x = "Months of Follow-Up", y = "Patient ID", col = "Covariate", title = "Patient Timelines: Continuous Covariate", subtitle = "x indicates month of patient death, gray indicates missing covariate") +
 theme(axis.text.y = element_text(size=6), legend.position = c(.7, .9), legend.direction = "horizontal", legend.background = element_rect(linetype="solid", colour ="black")) +
 scale_x_continuous(expand=c(0.01,0.01)) +
 scale_color_gradient(low="dodgerblue", high="firebrick1", na.value = "lightgray", breaks=c(90, 120, 150, 180))## Warning: Removed 143 rows containing missing values (geom_point).

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

或者,我们可以通过创建一个包含sum(!is.na(cov))的新列,并根据该列重新排列我们的pt_id,根据我们对每个患者的cov变量的测量数量重新排列我们的时间线。

dat_cc_miss %>%
 group_by(pt_id) %>%
 mutate(last_month_followup = max(months_followup), # a column containing how many measures we have for each patient
        n_measures = sum(!is.na(cov))) %>%
 ungroup() %>%
 mutate(pt_id = fct_rev(fct_reorder(factor(pt_id), n_measures)), # reorder IDs by number of measures we have for each patient
        month_death = case_when(death == 1 ~ last_month_followup,
                                TRUE ~ NA_real_)) %>%
 ggplot(aes(x = months_followup, y = pt_id, group = pt_id, col = cov)) +
 geom_line() +
 geom_point(shape = 15) +
 geom_point(aes(x = month_death, y = pt_id), shape=4, col="black") +
 theme_bw() +
 labs(x = "Months of Follow-Up", y = "Patient ID", col = "Covariate", title = "Patient Timelines: Continuous Covariate", subtitle = "x indicates month of patient death, gray indicates missing covariate") +
 theme(axis.text.y = element_text(size=6),
       legend.position = c(.7, .9),
       legend.direction = "horizontal",
       legend.background = element_rect(linetype="solid", colour ="black")) +
 scale_x_continuous(expand=c(0.01,0.01)) +
 scale_color_gradient(low="dodgerblue",high="firebrick1",na.value = "lightgray", breaks=c(90, 120, 150, 180))## Warning: Removed 143 rows containing missing values (geom_point).

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

从该图中我们可以看出,缺失测量值较多的患者具有较高的协变量测量值。如果我们按照非缺失测量值的比例重新排列患者,这一点会变得更加清楚。

dat_cc_miss %>%
 group_by(pt_id) %>%
 mutate(last_month_followup = max(months_followup), # the proportion is the total number of measures divided by the total months of followup
        prop_measures = sum(!is.na(cov))/last_month_followup) %>%
 ungroup() %>%
 # reorder IDs by proportion of measures we have for each patient
 mutate(pt_id = fct_rev(fct_reorder(factor(pt_id), prop_measures)),
        month_death = case_when(death == 1 ~ last_month_followup,
                                TRUE ~ NA_real_)) %>%
 ggplot(aes(x = months_followup, y = pt_id, group = pt_id, col = cov)) +
 geom_line() +
 geom_point(shape = 15) +
 geom_point(aes(x = month_death, y = pt_id), shape=4, col="black") +
 theme_bw() +
 labs(x = "Months of Follow-Up", y = "Patient ID", col = "Covariate", title = "Patient Timelines: Continuous Covariate", subtitle = "x indicates month of patient death, gray indicates missing covariate") +
 theme(axis.text.y = element_text(size=6), # move legend to the side by removing legend location
       legend.background = element_rect(linetype="solid", colour ="black")) +
 scale_x_continuous(expand=c(0.01,0.01)) +
 scale_color_gradient(low="dodgerblue",high="firebrick1",na.value = "lightgray", breaks=c(90, 120, 150, 180))## Warning: Removed 143 rows containing missing values (geom_point).

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

如果这是我的真实数据,我会和我的研究合作者一起跟进,以获得更多关于遗漏机制的信息。

如果您对数据集有任何问题或建议,请告诉我。快乐治疗时间表绘制!

原载于 2019 年 11 月 29 日【https://www.khstats.com】

犯罪模式

原文:https://towardsdatascience.com/patterns-in-crime-90efacb25923?source=collection_archive---------12-----------------------

对过去三年警察数据的分析

犯罪是许多人每天都担心的事情。无论是确保出门时锁好门,还是避开不安定的社区,或是安装安全警报,预防犯罪占据了我们生活的重要部分。尽管事实上在过去的 25 年里,英国的犯罪率几乎一直在下降。

在这篇文章中,我将调查由英国警方提供的公开数据集,以揭示任何有趣或令人惊讶的模式、趋势或异常现象。

这里使用的数据可以从 data.police.uk 网站上公开获得,包含了从 2016 年 10 月到 2019 年 9 月英格兰 43 个地理警察部队中的超过 1900 万报告的 个人犯罪和反社会行为、威尔士& NI(加上两支特种部队:英国交通警察和司法部)的信息。这包括关于地点、日期、犯罪类型和最新调查状况的信息。和我的文章一样,分析和可视化是用 r。

罪恶的循环

可视化这些数据的最简单方法是查看一段时间内犯罪的绝对数量:

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

Graph showing the number of reported crimes each month across all police forces in the UK from October 2016 to September 2019.

  • 显而易见,这里存在某种季节性趋势,犯罪数量在冬季月份下降,在年中上升到最高点-最高值出现在 2018 年 7 月(全英国报告的犯罪数量为 621,005 起)。

为了更清楚地显示这种循环模式,我们可以将每年的图表叠加起来,跨日历月显示。所有 45 支部队每个日历月报告的犯罪总数见下图。

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

The total number of reported crimes by calendar month and year from Oct 2016 to Sep 2019.

  • 犯罪水平的这种季节性趋势是一个有据可查的现象,自 19 世纪以来一直是犯罪学家研究和辩论的来源。然而,对于为什么会出现这种情况,仍然没有一致的意见,因为季节性的确切特征取决于你所研究的犯罪、地点和时间段。在这里,季节性遵循日历,夏季报告的犯罪数量更多,但情况并非总是如此。
  • 这种模式没有单一的原因,简单的解释如天气已经被证明是错误的。然而,温度/天气很可能是环境和社会影响之间复杂相互作用的一部分,从而导致这种季节性。

导致这种模式的一些因素包括:

  • 事实上,在夏季的几个月里,会有更多的人出国(这意味着入室盗窃更有可能/可行)。
  • 一个潜在的循环:高犯罪率导致警察“镇压”——导致犯罪减少——随后资源撤出——导致更高的犯罪率,等等。
  • 还有证据表明,高于平均温度会增加人类攻击性的可能性。

各种违法行为

上面的这些图表掩盖了不同类型犯罪之间的差异。在英国,每起已报告的犯罪都被归为 14 类中的一类,如“入室盗窃”、“毒品”或“暴力和性犯罪”。类别和解释的完整列表在的中。

下图显示了各类犯罪数量随时间的变化情况。

请注意,为了使图表更容易阅读,我将犯罪数量最少的六个类别(“毒品”、“其他犯罪”、“抢劫”、“持有武器”、“盗窃他人财物”和“盗窃自行车”)合并为一个“其他”类别。这不能与“其他盗窃”相混淆,其他盗窃包括员工盗窃、勒索和不付款就走。

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

Number of reported crimes over time, by type of crime. From Oct 2016 to Sep 2019.

  • 两种最常见的犯罪类型是“反社会行为”和“暴力和性犯罪”。
  • 2016 年 10 月以来,ASB 不断下跌,VSO 不断增加。
  • ASB 似乎非常接近前面描述的季节性趋势。这是有道理的,因为它往往涉及到人们在外面(13 种 ASB 中只有 2 种与近邻有关,即大多数只能通过离开房子来犯下),所以可能会随着温度的变化而发生很大变化。这也可以从本质上与 ASB 非常相似的“公共秩序”罪中看出。
  • 另一方面,VSO 完全不遵循周期性模式。VSO 可以(而且经常)在家庭或室内进行,所以温度不会有太大的影响。

当地违法行为

所提供的数据还提供了所报告犯罪的地理细节,包括 LSOA(“低层超级输出区”)。出于统计报告的目的,英国在地理上被划分为 34,000 多个地方自治市。它们大小不一,较大的区域在农村地区,较小的集水区在城市中心。下面你可以看到这些在英格兰和威尔士是如何划分的。

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

Map of the 34,700 Lower Layer Super Output Areas (LSOAs) in England & Wales as of 2016.

你可以在一些地方看到,LSOAs 是如此之小,以至于它看起来是一个深色的块。这无意中导致了人口密度的热图——因为在人口密集的地区,人口密度往往更小。

我们可以通过在图中包含 LSOA 的人口密度来验证这一点。下图显示了每个 LSOA 的人口密度(每平方公里的人口数),颜色越深,人口越密集。

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

Map showing the population density of LSOAs across England and Wales. Darker colours indicate a higher population density, measured as the number of people per square kilometre. The log value of population per sq. km. is used for readability.

在这里,我们可以看到英格兰和威尔士的大城市的位置,以及该国人口最稀少的地区。

在我们的警方数据中,98%的犯罪都与 LSOA 相关联,因此我现在可以将人口和犯罪的数据集结合起来,以可视化每个 LSOA 的人均犯罪水平。生成的地图如下所示。

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

Map showing the average number of crimes per person per month in the three years leading up to September 2019.

很明显,这张地图并不像我们希望的那样有用。有少量的地方自治市的犯罪率极高,而且这些地方都位于全国的城市中心(这些地方也很小,所以很难在地图上找到)。

要了解这种差异有多大,请考虑以下情况:

  • 在 LSOA,人均每月犯罪数量的中位数0.006 起犯罪
  • 90%的 LSOAs 的人均月犯罪率低于 0.0155 起**。**
  • 最大值比中值 高 82 倍 ,比 90%的 LSOAs 高 34 倍 。这是在伦敦威斯敏斯特市中心,平均每人每月 0.532 起犯罪。

英格兰和威尔士犯罪率最高的 10 个地方行政区位于伦敦、曼彻斯特、伯明翰、纽卡斯尔、加的夫和格洛斯特,这些都是英国最大的城市(格洛斯特和加的夫除外)。

城市遭受更高的犯罪率也许不足为奇——这是有据可查的事实——但这将是另一篇博文的主题。我使用的数据包含了每起已报告犯罪的大致坐标,因此可以在英国一些最大的城市中绘制一些有趣的地图。

时髦的重罪

为了将本文的所有主题联系在一起,最后要看的是调查全国范围内最常见的 型犯罪是否存在差异,以及是否有任何可见的模式。

再看下面一张 LSOAs 的地图,每张地图都根据 14 种犯罪中哪一种最常见来着色。

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

Map showing the most commonly reported crime for each LSOA in the three years leading up to September 2019.

正如本文前面所讨论的,两种最广泛的犯罪类型(“反社会行为”和“暴力和性犯罪”)远比其他类型更常见,这反映在上面的地图中,它们淹没了其他类型的比较。

为了更深入地挖掘,我们可以从分析中移除这些类型的犯罪,并检查剩余的数据。

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

Map showing the most common type of reported crime (excluding ‘Anti-social behaviour’ and ‘Violence and sexual offences crimes’) in the three years leading up to September 2019.

这里可以得出一些更有趣的结论:

  • 如果你将这张地图与之前的人口密度地图进行比较,你会发现人口密度与车辆失窃之间有很强的相关性——城镇中的汽车比农村地区更容易被盗。
  • 离开市中心稍微远一点,在建筑密集区的郊区,T2 的入室盗窃似乎很常见。在伦敦周围,中部和西北部的城市都能看到。
  • 这与非常偏远的地区形成了鲜明的对比,在那里刑事破坏公共秩序犯罪似乎是最常见的犯罪。
  • 地图上为数不多的几个彩色点之一显示了威尔士的毒品犯罪报告。这与威尔士目前正在打击的毒品流行率的上升相对应,特别是在加的夫和南海岸。
  • 在东南海岸地图右下方的多佛可以看到另一种颜色的下降。这是通过汽车或火车从英国到欧洲其他地方的门户。拥有武器的高犯罪率清楚地表明有人试图通过欧洲向该国走私武器。

感谢阅读

如果你喜欢,那么请分享这个,关注并给数据片一个关注,以保持最新的文章!

正如我提到的,将会有一篇后续文章,在那里我将可视化城市中的犯罪,并回答一些问题,如:犯罪在住宅区、工业区还是零售园区更常见?还有警察局的存在对当地的犯罪有影响吗?我还将调查对犯罪的调查有多成功,比较不同地点、犯罪类型和一年中不同时间的定罪率。如果你有任何其他的建议或细节需要我分析,请不要犹豫,在下面评论或发电子邮件给 editor@data-slice.co.uk。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值