TowardsDataScience 博客中文翻译 2021(七百四十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

为什么选择 Python 或 R 进行数据分析并不重要

原文:https://towardsdatascience.com/why-it-does-matter-to-choose-python-or-r-for-data-analysis-c251ba2aa6c8?source=collection_archive---------9-----------------------

比较实践指南

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

哈维尔·阿莱格·巴罗斯在 Unsplash 上的照片

Python 和 R 是数据科学生态系统中的主流编程语言。两者都提供了各种库来执行有效的数据争论和分析。

有抱负的数据科学家或分析师面临的最常见问题之一是选择哪种编程语言来学习数据科学。

有许多文章从不同的角度比较了 Python 和 R。这篇文章也是一个对比。然而,重点或目标不是宣布一个优于另一个。

我在本文中想要展示的是强调 Python 和 R 库都能够进行有效的数据争论和分析。我将介绍几个使用 Python 和 r 完成相同操作的例子。

我们将使用的库是 Python 的 Pandas 和 r 的“data.table”和“stringr”。我们将使用 Kaggle 上的网飞数据集来做示例。我们从导入库和读取数据集开始。

# Pandas
import pandas as pd
netflix = pd.read_csv("/content/netflix_titles.csv") # data.table
library(data.table)
netflix <- fread("Downloads/netflix_titles.csv")

该数据集包含 7787 种图书的详细信息。以下是功能列表(即列)。

['show_id', 'type', 'title', 'director', 'cast', 'country', 'date_added', 'release_year', 'rating', 'duration', 'listed_in', 'description']

标题可以是电影或电视节目。我们先来看看每个类别的标题数量。在 Pandas 中,我们可以使用 groupby 或 value_counts 函数。

netflix['type'].value_counts()
Movie      5377 
TV Show    2410 netflix.groupby('type').agg(number_of_titles = ('show_id','count')) number_of_titles
type    
Movie                5377
TV Show              2410

在 data.table 中,我们可以按如下方式完成这项任务:

netflix[, .(number_of_titles = .N), by=type] type number_of_titles
1: TV Show             2410
2:   Movie             5377

by 参数的作用类似于 Pandas 的 groupby 函数。N 计算每个类别中的行数。

我们可能想计算网飞电影的平均长度。持续时间列的当前格式不适于计算。它包含数量和单位:

netflix.duration[:5] # Pandas
0    4 Seasons 
1       93 min 
2       78 min 
3       80 min 
4      123 min

我们将创建两个新列,分别包括持续时间数量和单位。

# Pandas
netflix['duration_qty']=netflix.duration.str.split(" ").str.get(0).astype('int')netflix['duration_unit']=netflix.duration.str.split(" ").str.get(1)# stringr and data.table
netflix[, duration_qty := as.numeric(str_split_fixed(netflix$duration, " ", 2)[,1])]netflix[, duration_unit := str_split_fixed(netflix$duration, " ", 2)[,2]]

我们所做的基本相同,但语法不同。我们在空格字符处拆分 duration 列,然后使用第一部分作为数量,第二部分作为单位。

数量部分需要转换为数字数据类型。在熊猫中,我们使用 astype 函数。同样的操作可以用 r 中的“as.numeric”函数来完成。

让我们看看派生列和原始列。

# data.table
head(netflix[, c("duration", "duration_qty", "duration_unit")]) 

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

(图片由作者提供)

我们现在可以用分钟来计算电影的平均长度。

# Pandas
netflix[netflix['type'] == 'Movie']['duration_qty'].mean()
99.30798# data.table
netflix[type == "Movie", mean(duration_qty)]
99.30798

电影平均时长 100 分钟左右。我认为电影长度在不同的国家变化很大。我想看看平均电影长度排名前五的国家。

# data.table
netflix[type == 'Movie', .(avg_length = mean(duration_qty)), by='country'][order(avg_length, decreasing = TRUE)][1:5]# Pandas
netflix[netflix['type'] == 'Movie'].groupby('country')\
.agg(avg_length = ('duration_qty', 'mean'))\
.sort_values(by='avg_length', ascending=False)[:5]

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

(图片由作者提供)

我们来详细说明一下语法。我们按国家对行进行分组,并在国家列中计算每个组的平均电影长度。然后我们将计算出的平均值按降序排序,选择前 5 名。

最大的 5 个值大约是 200 分钟,比 99 分钟的总平均值大得多。上面截图中显示的前 5 个值可能是极端情况。他们可能包含很少的电影,所以我们不能真正谈论一个平均值。

确认我们的怀疑的一种方法是,也添加每个类别中的电影数量,或者过滤电影数量超过一定数量的类别。

# Pandas
netflix[netflix['type'] == 'Movie'].groupby('country')\
.agg(avg_length = ('duration_qty', 'mean'), 
     qty = ('duration_qty', 'count'))\
.query('qty > 10').sort_values(by='avg_length', ascending=False)[:5] # data.table
netflix[type == 'Movie', .(avg_length = mean(duration_qty), .N), by='country'][N > 10][order(avg_length, decreasing = TRUE)][1:5]

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

(图片由作者提供)

我们添加了一个列来显示每一列中的电影数量。然后,在对值进行排序之前,我们根据该列过滤行。

最长的电影在巴基斯坦、印度和韩国。

结论

我们已经做了一些展示数据争论和分析的典型案例的例子。这里的要点是 Python 和 R 库都提供了完成这些任务的高效方法。

无论你选择哪种编程语言来学习数据科学,你都不会有问题。一旦你用其中一种学习或练习,习惯另一种就相对容易了。大多数任务的逻辑和实现方式非常相似。

感谢您的阅读。如果您有任何反馈,请告诉我。

为什么 Julia 代码如此难以正确记录

原文:https://towardsdatascience.com/why-julia-code-is-so-hard-to-document-properly-abccec3a42a?source=collection_archive---------33-----------------------

Julia 包没有被很好地记录的真正原因。

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

(src =https://pixabay.com/images/id-1149962/

介绍

虽然大多数数据科学家最喜欢使用的语言可能是 Python,或者不太可能是 R,但我最喜欢的编程语言是 Julia。Julia 语言是一种相当年轻的、实时(JIT)编译的编程语言,它的范例围绕着通用编程概念多重分派。他们不仅使用这种泛型,而且在语言的任何地方都使用它,结果非常惊人。如果你想阅读我写的关于 Julia 和该语言中的 genius multiple dispatch 用法的整篇文章,你可以在这里查看这篇文章:

几天前,我写了一篇关于我认为 Julia 作为编程语言所面临的问题的文章。正如一些人可能预料的那样,这些问题中第一个也是最重要的一个是,朱莉娅需要一个更好的生态系统来合作。最后一点是,该语言的开发者没有明确表达该语言在行业中的定位,尽管他们明确说明了该语言的发展方向。然而,这种事情背后是否有更多的隐含意义——我真的不能说,因为我不是他们团队的成员。无论如何,在这两个问题之间是我想集中讨论的一整篇文章:

文档。

另外,如果你对那篇文章感兴趣,你可以在这里单独阅读:

成因

在上面提到的文章中,我讨论了在我看来,Julia 的文档的问题是如何根源于 Documenter.jl 的。软件工程师是懒惰的,当涉及到软件工程文档时更是如此。完成开发一个包的整个任务可能会非常有压力。在软件包开发完成后,然后对其进行严格的测试,制作一些文件,选择一个许可——最后是一个发布版本……但是随后意识到您仍然必须担心文档。

幸运的是,Documenter.jl 可以用来自动化这个过程。此外,Julia Hub 网站会自动生成一致的软件包文档。不用说,这是一个非常棒的方法,但是,这是不是太简单了?让我们也记住,你必须做的是用 Julia 编写软件文档,只需调用一个 autodoc 宏。也就是说,许多主流软件包选择在文档管理器文件中编写完整的描述,这是一件好事。

也就是说,我认为这也使得文档变得如此简单,以至于很容易浏览一遍。不用说,当一个人唯一可以处理的东西是文档字符串时,这可能是有问题的,文档字符串可能很少包含示例或复杂的类型描述。不用说,在 HTML 文档中拥有比简单的自动生成的文档字符串更好的文档当然是最佳的。那个人说,做后者太容易了,我认为这已经损坏了文档。

另一件损害 Julia 文档的事情是,许多用户甚至不知道如何记录他们的软件。这是为什么呢?因为信不信由你,

文档管理器. jl,并且文档化 Julia 通常很少被文档化。

对我来说,这真是个可笑的讽刺。想象一下。

我无法记录我的包,因为我需要用来记录包的包的文档不完整然而,事实并非如此,只是没有很多全面的关于 Julia 的文章解释如何做到这一切——这肯定会令人沮丧!有些 Julia 程序员甚至不知道 Documenter.jl 的存在!

最大的原因

当我写上一篇文章的时候,我甚至没有想到 Julia software 经常没有文档记录或者文档记录很差的最大原因。直到后来,我从另一位 Julia 程序员和 fan 那里得到回复,谈到他们也遇到了许多文档方面的问题。事实上,他们写道,我是他们关于朱莉娅的最大信息来源——这也是我写朱莉娅的目的,就是不断地教授这门语言。话虽如此,我觉得自己很有成就,但也思考了为什么那些甚至没有 Documenter.jl 这样的工具的语言往往有更好的文档。我甚至研究了 C、Ruby、JavaScript、F#、Vala 等语言的其他包。

通过所有这些研究,我得出的结论是,朱莉娅很少被记录下来,而且也很难被记录下来,这是有一个非常坚实的原因的。原因深植于编程语言中,存在于编程范例本身:

多重派遣。

等等,所以多重派遣是问题所在!?虽然本文中讨论的问题都不是决定性的问题,但是很容易理解为什么多重分派会对工程师记录 Julia 代码的能力产生重大影响。

为什么多重派遣?

为了理解为什么多重分派对于文档来说是一个问题,让我们首先考虑 Julia 中多重分派的一个例子。考虑以下两种类型:

tru = "true"
fls = 0

这里我们有 fls,false,它是一个表示布尔值的整数。在上面声明的,我们有 tru,true,另一个布尔值,但是这个包含在一个字符串中。这两者需要以不同的方式处理。我们可以通过简单地将 bool 类型转换为整数 0 来处理整数。然而,如果我们试图对我们的字符串这样做,我们将得到一个方法错误。在我们进入字符串之前,让我们为这个整数写一个函数:

turn_bool(x::Int64) = Bool(x)

虽然这是一个相当简单的例子,但现在让我们来做字符串。需要使用 parse()方法将字符串解析为其各自的数据类型 bool:

turn_bool(x::String) = parse(Bool, x)

现在让我们考虑为这些函数编写一个文档字符串。

"""Turns an integer between 0:1 to a boolean type."""turn_bool(x::Int64) = Bool(x)"""Turns a string, true, false, or 1, 0, into a boolean type."""turn_bool(x::String) = parse(Bool, x)

每当我们使用。()语法,我们将按预期的顺序得到这两个,这是完美的!

?(turn_bool)

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

(图片由作者提供)

然而,当只有一个版本的函数是 doc-string 的,或者更常见的是,doc-string 不提供输入参数时,问题就来了。这是有问题的,因为它使得确定什么函数将对特定类型起作用变得不可能。例如,如果您研究索引 DataFrames.jl 数据帧,您最终会遇到一个使用 filter()方法的示例—这就是应该如何做的。如果你要调用 filter()方法。(),你会看到这个函数在 Base 和 DataFrames.jl 中的每一次使用都是完全没有记录的!!!从而展示了这些基本函数在整个语言中使用的根本缺陷——用户觉得没有必要记录它们的用法!

结论

我真的很高兴有一个关于朱利安软件文档的小对话。就个人而言,我必须承认我在记录我的软件方面也不是最好的。然而,我的主要软件包,车床和 OddFrames,有两个大的稳定版本即将在这里发布——这两个版本都将有很好的文档记录,并且易于理解,我可以保证!非常感谢您的阅读。我认为这些问题是可以解决的,社区只需要认同这个问题,并尝试从整体上改善它。希望作为朱利安,我们能走到一起,给这种语言它应得的包和各自的文档。祝你在 Medium 度过美好的时光!

为什么 Julia 是迭代开发的绝佳语言

原文:https://towardsdatascience.com/why-julia-is-an-awesome-language-for-iterative-development-67cea5f93c3e?source=collection_archive---------32-----------------------

意见

扔掉旧的大开发解决方案,因为这个更好

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

https://pixabay.com/images/id-516559/

介绍

TJulia 编程语言是一种相当新的语言,它已经在软件工程和科学计算社区掀起了一场风暴。这有很多不同的原因,因为 Julia 编程语言是可用的最快的语言之一,当然也是如此高水平的最快语言。这种语言编码像一种脚本语言,语法非常类似于 Python 或 MATLAB 的语法,同时还保持令人难以置信的速度。这是古老的格言“像 Python 一样行走,像 c 一样运行”的地方。然而,尽管 Julia 是一种编译速度相当快的语言,但这肯定不是该语言唯一的吸引力。

该语言使用多重分派作为范例。这可以用编程创造出一些你在其他地方根本找不到的非常显著的结果。多调度往往被当作语言的主干,在语言的多个方面展现着自己的美丽。多重分派极大地影响了 Julia 编程语言的一个方面是在整个 Julian 生态系统中扩展模块的能力。这很酷,因为它创建了您可以添加的包,并且您已经知道一些方法,而无需查看文档。

多重派遣—概述

为了理解多重分派如何促进一些非常棒的迭代开发,我们首先需要理解多重分派到底是什么。多重分派是 Julia 编程语言的核心,没有多重分派的 Julia 根本就不是 Julia。这个概念允许我们接受多种类型,并通过相同的函数调用传递它们。这些函数调用可以限制在一个类型的父类的任何部分,这意味着该函数的多个版本可以仅使用一个类型来调度。如果你想进一步了解我为什么如此喜欢多重分派,我最近写了一篇文章,你可能会感兴趣:

虽然在我看来,多重分派是一种很好的编程方式,而且比使用其他编程概念生成的代码结构更自然,但我认为它在 Julia 语言中真正与众不同的地方是它几乎可以在任何地方使用。通常在编程中,我们在正常的全局范围之外编写两种不同类型的东西:

  • 构造器
  • 功能

这两者如何协同工作通常由我们正在使用的语言的范例决定。在 Julia 中,这两件事都遵循完全相同的编程概念,即多重分派。这使得 Julia 成为一种非常独特的语言,因为我们既有创建类型的 dispatch,也有创建方法的 dispatch。考虑下面的例子:

mutable struct CoolKid
    cool_status::Int64
    function CoolKid(height::Int64, weight::Int64, n_friends::Int64)
        cool_status = height - weight * -n_friends
        new(cool_status)
    end
end

上面的构造函数使用 dispatch 来创建 CoolKid 类型。获取 CoolKid 类型的第一种方法是直接调用外部构造函数。外部构造函数是中间没有函数的部分。如果我们使用一个整数作为参数来调用这个函数,我们将直接得到一个 CoolKid(integer)返回。

然而,如果我们用三个都是整数的参数调用这个构造函数,我们仍然会得到相同的一致的返回,但是我们会运行函数中提供的算法。为了方便起见,使用了 new()方法。我认为这是 Julian 编程的一个非常酷的方面,因为典型的全功能编程语言不能有类型的初始化函数,使用这种形式的分派,我们可以选择最终用户是否调用这个初始化函数。

积木

那么是什么让 Julia 和它的多重分派概念对迭代开发如此重要呢?多分派范例有许多优点,但是我认为有一点被严重忽视了,那就是方法的扩展。使用多重分派,语言内部的任何方法都可以扩展到新类型。这包括来自 Julia 的基本模块的方法,以及来自 Julia 的整个生态系统中的其他模块的方法。

考虑到这一点,我们很快意识到 Julia 的生态系统可以非常有效地迭代开发。向已经存在的代码中添加内容可以像向这些方法分派新类型一样简单。考虑下面的例子,其中我分派加法运算符来处理一个字典和一对。

import Base: +
+(d::Dict, p::Pair) = push!(d, pair)

这只是一行代码,通过这一行代码,二进制加法运算符对字典和 pair 类型变得非常有用。当然,这也可以从我们自己的模块和环境中有效地用于我们自己的类型,我可能在一篇文章中详细介绍了如何做到这一点,您可以在这里查看:

这篇文章实际上是我最近写的最喜欢的文章之一,因为它真正展示了 Julia 编程语言的伟大之处。

现在,使用我们的一行分派和一行显式导入,我们实际上对这种方法有了一个全新的用途,这种方法通常对这种类型基本上是无用的:

d = Dict(:A => [5, 10, 15], :B => [10, 15, 20])
d + :C => [25, 30, 35]

结论

Julia 编程语言非常适合做很多不可思议的事情。这些概念中有很多可能更符合科学,但是我认为大多数人都同意多分派范例对软件工程来说是一个巨大的优势。它的一种应用方式是在迭代开发中。这是因为 Julia 中的大多数东西都可以建立在一个方法之上,例如 Base.push 或 Base.filter,它贯穿于整个语言,用于从多个模块中分派多种类型——我认为这非常巧妙!非常感谢您阅读我的文章,我希望它至少对展示在 Julia 中编写自己的代码并与他人的代码一起工作有所帮助。

为什么 Jupyter 笔记本没有那么差!

原文:https://towardsdatascience.com/why-jupyter-notebooks-arent-all-that-bad-d75e90d02c3a?source=collection_archive---------25-----------------------

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

图片由作者提供。由 Vectors MarketFreepikFlaticon 制作的图标。

入门

以及如何给它们增压。

在过去的几年里,我注意到越来越多的人不喜欢 Jupyter 笔记本,很多人说你应该从 Jupyter 转向 scripts(这里是这里是,这里是这里是,这里是这里是,这里是这里是等等)。).

事实上,使用 Jupyter 笔记本有一些缺点,但这并不意味着你应该忽略它的优势,它可以帮助你成为一名更高效的数据科学家!

Jupyter 笔记本可以补充您的工作流程

与大多数工具一样,这是一个将工具用于其预期目的的问题。当然,有一些简单的方法可以让 Jupyter 笔记本在生产中使用,但它的真正潜力在不同的领域大放异彩。

我认为你不应该将切换到脚本,而是使用 Jupyter 笔记本,一个与脚本一起使用的工具。

使用 Jupyter 笔记本和脚本可以产生协同效应

在这篇文章中,我将通过几个原因来解释为什么 Jupyter 笔记本电脑没有一些人想象的那么糟糕。在这里,我将重点介绍它的优势、用例以及在您的技术堆栈中的潜在作用。

1.它们非常适合探险

Jupyter 笔记本是一个神奇的探险工具。它允许您快速,最重要的是,交互式地浏览您的数据,创建一些可视化,并计算结果都一气呵成。

熊猫概况 这样的工具可以帮助你增加 Jupyter 笔记本作为探索工具的实用性,因为它可以快速创建数据中可以发现的内容的概览。

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

熊猫-侧写示例。图片由作者提供。

由于它的交互性,您可以继续深入研究数据,并创建自己的可视化效果来补充个人资料。

为 Jupyter 创造了大量的探索工具,如 【小平面】【D-Tale】bq plot。对我来说,这证明了 Jupyter 对于探索的用途。

2.它们可以用于开发代码

我听到的关于 Jupyter 的一个主要担忧是它鼓励了糟糕的编码实践。事实上,如果您不小心,Jupyter 笔记本可能会导致污染全局名称空间,难以控制源代码,并且如果您不以线性方式运行笔记本,还会出现可再现性问题。

如果使用不当,这些都是主要问题。然而,这仅仅意味着您在使用 Jupyter 笔记本时应该更加小心,并了解如何改进您的工作流程。

为了改进工作流程并防止这些问题,有一件事通常可以解决大多数问题:打包您的代码

在适当的地方以线性方式使用函数和类

如果你把你的代码打包在一个中。py 文件或者甚至是一个 pip 可安装包,你就可以把这些代码加载到你的 Jupyter 笔记本上并继续开发。

%load_ext autoreload  # Load the extension
%autoreload 2  # Autoreload all modules

允许你在执行代码前重新加载模块。把它放在你的笔记本的开头,每次你执行一个单元,所有载入的函数和类都会更新。

而且,随着 Jupyter Lab ,笔记本越来越类似于合适的 ide。

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

Jupyter 实验室示例。图片由作者提供。

您甚至可以使用扩展来增强您的 Jupyter 环境,如 nbdevnbdimenbviewernbstripout****,这些扩展允许更多的可再现性和更丰富的功能。

3.它们是完美的交流工具

对我来说,Jupyter 笔记本非常适合用于交流目的,如教程、演示和解释算法。用户可以使用它来隐藏代码,显示可视化,嵌入视频,交互式演示结果,等等!

例如,每当我创建一个包时,我都会确保包含一套 Jupyter 笔记本,其中包含几个关于如何使用该包的教程。这使得同事之间共享笔记本变得容易,特别是如果你已经花时间使它成为一个很好理解的文档。

您可以使用诸如https://github.com/bqplot/bqplotipyleaflet 等扩展来提高 Jupyter 笔记本的可视化能力。这些工具在扩展绘图功能方面非常出色。

我个人是VoilaFastpages 的忠实粉丝。瞧,你可以用交互式小工具渲染 Jupyter 笔记本的实时版本。Fastpages 是一个支持 Jupyter Notebook 的博客平台,可以用作文档。

4.他们的准入门槛很低

Jupyter 笔记本的准入门槛极低。它们的交互性与简单易用的界面相结合,使用户可以快速开始编程。它们使探索和可视化您的数据变得轻而易举。

这对于那些主要不是程序员,但确实需要额外执行一些分析的人,例如不同领域的科学家,特别有帮助。

正如所料,有一堆扩展可以进一步降低这个障碍!

Jupyterhub 开始,这个工具可以创建单用户 Jupyter 笔记本服务器的多个实例。在实践中,您可以向一班学生提供笔记本电脑服务器。我自己在学习期间也用过它,并且用得很开心!

与学术环境保持一致,nbgradier可以让老师轻松分配和评分 Jupyter 笔记本。

5.插件/扩展/工具可以增压 Jupyter

从上面的段落中你可能已经注意到,有大量的扩展可以改进你的 Jupyter 笔记本工作流程。

这些扩展让您可以弥补 Jupyter 笔记本的任何缺点,并将其转化为优势!

下面,我将列出我之前提到的扩展的概述,但我也会添加一些我认为可能对您有很大好处的扩展。

内核是执行笔记本中代码的计算引擎。可用的有很多,比如【R】Scalac++,甚至 GO 内核都可以在 Jupyter 内使用。

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

可能的 Jupyter 内核。图片由作者提供。

还可以使用https://github.com/nteract/hydrogenVscode-jupyter分别在 Atom 和 vs code 中运行 Jupyter 笔记本。

小部件和可视化

使用小部件和可视化扩展可以轻松快速地可视化和浏览您的数据。pandas-profilingD-Tale是创建数据概览的绝佳工具,而ipywidgetsipyvolume使进一步扩展这些功能成为可能。

有很多这样的扩展可以创造更好的视觉体验。几个值得注意的扩展是interactQgridLuxmpld3

发展

对于开发来说,像paper millnbdevNBD ime这样的工具允许更多的再现性和更丰富的特性。它们包括在 Jupyter 笔记本中开发包的可能性,甚至在必要时应用单元测试。

尽管 Jupyter 笔记本并不是用来创建产品级代码的,但这些扩展肯定能帮助用户实现这一点。

出版

我们可以发布类似Voilafast pages这样的扩展名的 Jupyter 笔记本来渲染 live 版本。这使得我们可以交流研究结果,同时允许同事们进行实验。

我们甚至可以更进一步,将 Jupyter 笔记本转换成更适合您的使用案例的格式。以 nbconvert 为例,它将 Jupyter 笔记本转换成 pdf,HTML,甚至 LaTeX!

类似的扩展还有jupytextjupyter-book ,它们允许有趣的选项来发布或转换您的 jupyter 笔记本。

感谢您的阅读!

Jupyter 笔记本不仅仅是他们做得不好的事情。通过专注于他们做得好的事情,你肯定可以提高你的工作流程!

如果你和我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我,或者在 Twitter 上关注我。

为什么在递归神经网络中“学会遗忘”

原文:https://towardsdatascience.com/why-learn-to-forget-in-recurrent-neural-networks-ddf89df3f0ab?source=collection_archive---------45-----------------------

用一个简单的例子来说明

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

照片由妮可·罗德里格兹Unsplash 拍摄

考虑下面的二进制分类问题。输入是任意长度的二进制序列。当且仅当输入中出现 1 但不是最近才出现 1 时,我们希望输出为 1。具体来说,最后的 n 位必须为 0。

我们也可以把这个问题写成语言识别问题。对于 n = 4,描述为正则表达式的语言是(0 or 1)*10000*

以下是案例 n = 3 的一些标记实例。

000 → 0, 101 → 0, 0100100000 → 1, 1000 → 1

为什么会出现这个看似奇怪的问题?它需要记住(I)1 出现在输入中,以及(ii)不是最近。正如我们将很快看到的,这个例子有助于解释为什么简单的递归神经网络是不够的,以及注入一个学习遗忘的机制如何有所帮助。

简单递归神经网络

让我们从一个基本的递归神经网络(RNN)开始。 x ( t )是在输入中的时间 t 到达的位,0 或 1。这个 RNN 保持一种状态 h ( t ),试图记住它是否在过去某个时候看到了 1。经过适当的转换后,输出将从该状态中读出。

更正式地说,我们有

*h*(*t*) = tanh(*a***h*(*t*-1) + *b***x*(*t*) + *c*)
*y*(*t*) = sigmoid(*d***h*(*t*))

接下来,我们考虑以下(输入序列输出序列)对,假设 n = 3。

x 10000000
y 00011111

讨论这对 RNN 的行为和学习,将有助于像通常所做的那样及时展开网络。

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

简单的 RNN 在时间中展开

把这想象成一个有阶段的管道。状态从左向右移动,并在过程中由某一阶段的输入进行修改。

让我们更详细地了解一下阶段内部发生的情况。考虑第三阶段。它输入状态 h 2 和下一个输入符号 x 3。 h 2 可以被认为是从 x 1 和 x 2 导出的用于预测 y 3 的特征。该框首先从这两个输入计算下一个状态 h 3。 h 3 然后被结转到下一阶段。 h 3 也决定了工作台的输出 y 3。

考虑当看到输入 1000 时会发生什么。y 4 是 1,因为 y ^4 小于 1(总是这样),所以有一些误差。遵循通过时间反向传播的学习策略,我们将通过时间使误差波动回到更新各种参数所需的程度。

考虑参数 b 。它有 4 个实例,分别连接到 x 1 到 x 4。附加到 x 2 到 x 4 的实例不会改变,因为 x 2 到 x 4 都是 0。所以这些 b 实例对 y^没有任何影响。当进行这种改变使 y^ 4 更接近 1 时,连接到 x1 的 b 的实例增加。

随着我们继续看到 x 5、 x 6、 x 7、 x 8,以及它们对应的目标 y 5、 y 6、 y 7、 y 8,同样的学习行为也会发生。 b 会一直增加。(尽管如此,因为我们需要更早地反向传播误差,以到达 x 1。)

现在想象一下 x 9 是 1。 y 9 必须为 0。然而,^9 很大。这是因为参数 b 已经得知 x i = 1 预测 y j = 1 对于j=Ib 无法强制要求 x i = 1 后面必须只跟 0,编号至少为 3。

简而言之,这个 RNN 无法捕捉到 x i = 1 的联合交互作用,并且它后面的所有位都是 0,编号至少为 3,以预测 y j。还要注意,这不是一个长期影响。 n 只有 3。因此,这个例子中 RNN 的弱点不能用时间反向传播时误差梯度的消失来解释[2]。这里还发生了别的事情。

一个学会遗忘的 RNN

现在考虑这个版本

z(*t*)    = sigmoid(*a***x*(*t*) + *b*)
*h*new(*t*) = tanh(*c***x*(*t*) +*d*)
*h*(*t*)    = (1-*z*(*t*))**h*(*t*-1) + *z*(*t*)**h*new(*t*)
*y*(*t*)    = sigmoid(*e***h*(*t*))

我们不是凭空想象出来的。它是流行的门控递归神经网络 GRU 中的一个关键方程。我们从[1]中对它的描述中得到这个方程。

这个 RNN 有一个显式的遗忘机制!它是 z ( t ),一个介于 0 和 1 之间的值,表示遗忘的程度。当 z ( t )趋近于 1 时,状态 h ( t -1)被完全遗忘。

h ( t -1)被完全遗忘的时候, h ( t )应该是什么?我们将它封装在一个表示“新状态”的显式函数 h new( t )中。 h new( t )仅来自当前输入。这是有道理的,因为如果要忘记 h ( t -1),我们面前只有新的输入 x ( t )。

更一般的是,下一个状态 h ( t )是前一个状态 h ( t -1)和一个新状态 h new( t )的混合,由 z ( t )调制。

这个 RNN 有能力在这个问题上做得更好吗?我们将通过开出一个可行的解决方案来肯定地回答这个问题。随附的解释将揭示各种神经元在使该解决方案工作中所扮演的角色。

考虑 x ( t )为 1。 y ( t )必须为零。所以我们要将 y ^( t 向 0 驱动。我们可以通过将 e 设置为一个足够大的负数(比如-1)并迫使 h ( t )接近 1 来实现这一点。获得期望的 h ( t )的一种方法是强制 z ( t )接近 1,并将 c 设置为足够大的正数,并将 d 设置为足够大的正数,使得 c + d 足够大。我们可以通过将 a 设置为足够大的正数,将 b 设置为足够大的正数,使得 a + b 足够大,从而强制 z ( t )接近 1。

这个处方的作用就好像

If *x*(*t*) is 1
   Set *h*new(*t*) to close to 1.
   Reset *h*(*t*) to *h*new(*t*)
   Drive *y*^(*t*) towards 0 by setting *e* sufficiently negative

由于 y ( t )依赖于 x 的最近过去值,因此 x ( t )为 0 的情况更复杂。让我们以下面的设定来解释一下:

Time … *t*    *t*+1     *t*+2      *t*+3
*x*    … 1     0       0        0
*y*    … 0     0       0        1
*h*new … 1 D=tanh(*d*)   D        D
*z*    … 1     ½       ½        ½
*h*    … 1  ½(1+D) ½(*h*(*t*+1)+D) ½(*h*(*t*+2)+D)*h*^   … >>0  >>0      >>0     <<0y^   … → 0  → 0      → 0     → 1

这里有很多!所以让我们一行一行地走一遍。

我们正在查看顺序处理输入 x = …1000 的最后 4 位时的情况。对应的目标是 y = …0001。我们假设 RNN 的参数已经以某种方式被选择得恰到好处(或被学习),如下所示。(当然,这些必须与我们在 x (t)为 1 时使用的设置一致。)简而言之,我们描述的是固定网络在这种情况下的行为。

现在看 h new。当 x ( t )为 1 时,我们已经讨论过 h new( t )应该趋近于 1。当 x ( t )为 0 时, h new( t )等于 tanh(CX(t)+d)= tanh(d)。我们称之为 d。

接下来看 z 。当 x ( t )为 1 时,我们已经讨论过 z ( t )应该趋近于 1。当 x ( t )为 0 时,既然要记住过去,我们就把 z ( t )设为近似值。为此,我们只需将 b 设置为 0。这可以在不忘记当 x ( t )为 1 时工作的 z ( t )的情况下实现。

对于剩余的行,让我们从最后一行开始,一步一步来。在 y ^行中,给定 y 目标,我们描述我们想要什么。假设我们已经把 e 固定在一个足够大的负数上,这就给出了我们想要的状态。我们称他们为^.

因此,现在剩下的就是展示如何制造出与^.相匹配的产品首先让我们放大这两行,同时也将 h 转换成更方便的形式

h  … 1        ½ + ½D        ¼ + ¼D + ½D          ⅛ + ⅛ D + ¼ D + ½ D
h^ … >> 0     >> 0          >> 0                 << 0

可以看出,选择 d 使得-⅓ < D < -1/7 will meet the desiderata. It’s easy to find d 使得 tanh( d )在这个范围内。

案例 x ( t ) = 0 的处方可以总结为

If *x*(*t*) is 0
   Set *h*new(*t*) to be slightly negative.
   Set *h*(*t*) as average of *h*(*t*-1) and *h*new(*t*)

所以只要看到 1 后面的 0, h ( t )就一直下降。如果看到足够多的 0, h ( t )变为负值。

总结

在这篇文章中,我们讨论了有和没有显式“遗忘”机制的递归神经网络。我们在一个简单描述的预测问题的背景下讨论了这个问题,而更简单的 RNN 无法解决这个问题。具有“忘记”机制的 RNN 能够解决这个问题。

这篇文章将对那些想了解简单 RNNs 如何工作,带有遗忘机制的增强版本如何工作(特别是 GRU),以及后者如何改进前者的读者有用。

延伸阅读

  1. https://colah.github.io/posts/2015-08-Understanding-LSTMs/
  2. https://www . superdata science . com/blogs/recurrent-neural-networks-rnn-the-vanishing-gradient-problem

为什么最小二乘这么特别?

原文:https://towardsdatascience.com/why-least-squares-regression-whats-with-the-l1-norm-criterion-51e8b7f905eb?source=collection_archive---------27-----------------------

为什么没人谈‘绝对损失’?

在这个故事中,我们将解决为什么我们通常更喜欢最小化偏移的平方而不是它们的绝对值的问题,至于简短的回答,这主要是因为它更容易**,它更稳定**,它更强大**。******

回想一下,对于 OLS(普通最小二乘法),我们寻求最小化

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

问题是,为什么我们不把

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

先说我们简答的第一点。最小化前者更容易。特别是,最小化涉及平方偏移的成本函数的系数向量θ是通过一个封闭形式的表达式找到的,这也是我最近一篇文章的主题(你可以在这里查看)。)相反,对于最小化涉及绝对偏移的成本函数的系数,没有“封闭形式”。我们能做的最好的事情也许是达成一个迭代方案,它能帮助我们最终在数值上收敛到属于最佳拟合超平面的系数。

**最小化前一个成本函数更容易的事实源于这样一个事实,即 y = f (x) 有一个很好的导数,即 y’ = 2f(x)。f '(x)y’ = |f(x)|f '(x) /f(x) 那是因为 y = |f(x)|。对于后者,绝对值在微分后保持不变,这使得求和表达式等于零(尤其是涉及求和的情况下)变得非常重要。

吉菲的扎克·加利费安纳基斯反应

我们简短回答的第二点是稳定。两个成本函数都承诺存在一个系数向量θ,该向量在全局上最小化从超平面到数据集的偏移。这是两个函数都是凸的直接结果(有自己的证明)。

问题在于,涉及绝对失调的成本函数可能有点过了,因为它实际上可以提供无限数量的不同系数向量θ,所有这些向量都可以最小化成本函数。同时,对于 OLS 方法,总是有一个唯一的系数向量θ使成本函数最小化(除非数据集非常小,在这种情况下两个问题都简化为插值)。)这两个事实是从 L1 范数的
非严格凸性和 L2 范数的严格凸性中推导出来的,两者也都有自己的证明。

如果你想看到与我们的论点一致的东西,考虑为一些随机数据集绘制两个成本函数(你可以考虑拟合类似于 y=ax 的东西来使它变得简单),然后根据你的数据集,你可能会看到类似这样的东西。

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

L1 vs L2 损失-作者图片。

最小值明显不同,对于平方损耗,最小值是一个唯一点,而对于 L1 损耗,最小值是无穷多个点。

我们简短回答中的最后一点是关于 L2 损失的回归比 L1 损失的回归在统计上更有说服力。让我们首先强调这样一个事实,即在某种意义上,两种选择都可能是真正最优的,特别是,如果我们假设误差(偏移)遵循正态分布,那么最小化 L2 损失与寻找最大似然估计 ( )相一致,这主要用于统计推断。)另一方面,如果我们假设误差遵循拉普拉斯分布,那么最小化 L1 损失与找到最大似然估计相符。当然,这两个事实都有自己的证明。

下图显示了两种分布的曲线图(在 2D)。红色和蓝色分别对应正态和拉普拉斯分布。

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

正态分布与拉普拉斯分布-作者图片。

现在的问题是,我们应该相信误差服从哪个分布,即使是近似的。答案是,这通常是正态分布,因为我们通常认为误差是独立的(不以任何方式相互影响),这使得它们随着数据集的增长而接近正态分布,这要归功于中心极限定理。事实上,你可能只听说过正态分布,因为它在现实生活中出现的频率更高。

原来如此?使用 L1 标准是没有意义的?答案肯定是没有。事实上,使用 L1 范数准则进行回归是一件真实的事情,也可以按需使用。如果你不知道,它通常也被称为最小绝对偏差(缩写为 LAD)。在一种情况下,LAD 似乎优于 OLS,特别是当数据集包含许多异常或异常值时,因为 OLS 会在尽量减少损失的同时大肆渲染这些异常或异常值,因为对它们的偏移量求平方会产生很大一部分误差,结果是一个位于实际数据集和异常值之间的超平面,如果你没有理解我在这里试图说的话,请仔细观察****

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

小伙子对 OLS-GIF 和作者的项目。

此处的数据集包括左侧表格中的 8 个点,黄线(yₐ)is 归因于 LAD,白线归因于 OLS。数据集不包含任何异常值,这两条线似乎是合理的。当然除了我们每次计算时,LAD 的意见略有不同(迭代格式每次从不同的初始点开始,LAD 不保证有唯一的极小值)。

现在,如果我们把点(9,6)换成(9,50)会发生什么

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

小伙子对 OLS-GIF 和作者的项目。

对于 LAD 线来说没什么大不了的,同时 OLS 很容易被诱惑牺牲整个数据集,只为了离群值,这证实了 LAD 比 OLS 更健壮的事实。

如果您想自己尝试一下,请访问:

**[## 最小绝对偏差

mathemati.herokuapp.com](http://mathemati.herokuapp.com/LeastAbsoluteErrors)**

希望这有助于你理解为什么我们通常选择 OLS,下次再见。

参考资料:

[1]:吉菲。https://giphy.com/gifs/reaction-BmmfETghGOPrW扎克·加利费安纳基斯反应

[2]:维基百科。最大似然估计 https://en.wikipedia.org/wiki/Maximum_likelihood_estimationT4

[3]:维基百科,最小一乘偏差https://en.wikipedia.org/wiki/Least_absolute_deviations

[4]:维基百科,正态分布https://en.wikipedia.org/wiki/Normal_distribution

为什么数据越少越好

原文:https://towardsdatascience.com/why-less-is-more-when-it-comes-to-data-8b90619fdeaf?source=collection_archive---------43-----------------------

意见

大数据可能是一种趋势,但更多并不一定更好

*“少即是多”,*自称英国人。德国人说,“在德国首都时代”。

说到数据的有用性,我们应该记住这些说法。在不断发展的数据驱动型经济中,这些对于成功甚至生存都至关重要。

对许多组织来说,有效利用数据是一项艰巨的任务。多年来,IT 结构已经发展成为一个复杂的系统集合。几乎不支持流程。更不用说满足信息需求了。这是许多组织无法为算法和决策提供可靠数据的重要原因。

数据管理方案旨在解决这一问题。尽管有时结果令人失望。这些项目往往归结为事后的修复,因此有可能成为一次性的**。创建和维护高质量的数据需要更多的工作,而不仅仅是修补。当基础不正确时,就像装满一个满是洞的桶。**

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

佩德罗·达·席尔瓦Unsplash 上的照片

尽管在数据管理方面取得成功很难,但在这方面还有另一个经常被忽视的因素:超过 80%的组织信息是以非结构化形式存储的。这些海量的数据堆积起来,并且还在不断增长。

这是洞察的重要来源,但对所有这些数据的控制仍然非常有限。这些数据中的大部分事实上——简单地说——是垃圾。挑战在于清除垃圾,只保留相关的数据。因为少实际上就是多。

商业领袖不能不接受这一挑战。首先,因为托管、维护和备份这些数据的成本过高,而且只会继续增长。另一个因素是因为法律法规(合规)需要删除旧数据。但到目前为止,最重要的论点是,被污染的非结构化数据会导致糟糕的决策。****

想象一下根据错误的简历雇佣某人。然后不小心给那个新员工发了一份永久合同而不是临时合同。在数据驱动的经济中,这是不可接受的。

好消息是什么?

有一个解决方案可以以可控和负责任的方式清理旧数据。利用现代技术—索引和分类技术— 删除冗余、过时和琐碎的(ROT)并识别有价值的数据。这些见解作为元数据添加进来,在曾经庞大的、难以管理的数据堆中创建结构。这些年来,我开发并测试了一个 5 级数据保留漏斗,它提供了一个行之有效的方法。在漏斗的每一层中,多一点的 ROT 数据被移除。

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

照片由安东Unsplash 上拍摄

应对囤积心理

组织害怕丢失有价值的数据并不罕见。克服这个问题的一个好方法是在有限的时间内以隐藏的形式存储数据。最终用户可以在宽限期内请求特定数据。如果出于适当的业务原因需要,他们可以使用这些信息。记录原因并用于丰富数据保留策略。通过数据保留漏斗的各个步骤使数据可用是很重要的,以确保数据被正确地添加了元数据。在漏斗的末端,只剩下有价值的数据。

坏消息呢?

这是艰苦的工作。毫无疑问,结构化数据清理方法有助于组织改善非结构化数据的管理,从而做出更好的决策。但是,解决这个问题的数据专家才是最重要的。清理比特和万亿字节是一项艰苦而乏味的工作。没有多少人喜欢做数码清洁女工。但是总得有人去做。我认为见证它对新机会的贡献是非常有益的。这是兑现一句流行的荷兰谚语的承诺的绝佳方式:“Opgeruimd statat netjes”

脚注

1 元数据是关于数据的数据,它提供关于特定数据对象内容的信息。例如作者、创建日期或文档类别(如简历或合同)。

为什么线性回归是你所需要的

原文:https://towardsdatascience.com/why-linear-regression-is-all-you-need-afb1304f8f8e?source=collection_archive---------11-----------------------

理解它,进入深度学习将变得不那么困难(仍然是困难,但更少)

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

图一。从地面真相到使用深度学习的预测。图片由作者提供。

这篇短文是为那些开始学习线性回归,并且正在进入深度学习领域的初学者写的。但是我不会在本文中深入讨论这些话题。

我的意图只是给出一个概念,为什么线性回归可以促进进入更深水域的路径。我以前写过线性回归。这里可以看,这里可以看

“哦,线性回归真的是机器学习吗?!…"

这是我的想法。

我听到人们开玩笑(或半开玩笑)说线性回归不是机器学习。我懂了。如果你决定进入这个领域来建造你的自动驾驶汽车或机器人来清理你的房子,就像电影中一样,线性回归可能会令人失望。

但是相信我,线性回归对于获得其他更复杂主题的直觉是必不可少的。而理解逻辑回归就更好了。不要因为它的简单(相对而言)而失去动力。继续学习。

权重、偏见、乐观主义者——无处不在!

这条线的公式也一样!y-hat =重量*x +偏差

我开始研究神经网络和深度学习,我很庆幸我先学会了线性回归。了解基础知识真的很有帮助。

  • 权重(线的斜率)
  • 偏差(直线的 y 截距)
  • 一个优化器预测某个值,与实际数据(地面真实值)进行比较,并计算误差(预测值与实际数据之间的距离)。然后,算法调整权重和偏差以最小化误差。

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

图二。各种线的旋转表示。图片由作者提供。

所有这些概念也是深度学习的一部分。同样的事情也发生在神经网络中。

简而言之,一个问题需要深度学习,因为直线可能无法覆盖,或者更好地说,很好地代表数据。一条直线不能符合下面右边的例子。

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

图 3。线性和非线性表示。图片由作者提供。

但核心逻辑是一样的。在神经网络中,简单地说,每个节点代表一条线。它们组合起来形成表示数据点所需的线。

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

图 4。从地面真相到使用深度学习的预测。图片由作者提供。

最后的想法

我读过关于节点、隐藏层、权重和偏差的内容,但我并不清楚所有这些东西是什么或做什么。得益于学习线性回归,我有了更清晰的认识。

神经网络还有更多的东西,它们的内部工作可能会变得非常复杂。

有没有尝试过跟随语言翻译器(encoder-decoder/seq2seq)或者 word2vec 算法的实现?试一试,你就知道了。

我的目标是在深度学习主题上覆盖更多内容。不同的激活功能,RNNs 到 LSTM 和 GRUs 到 seq2seq 到 seq2seq 的演变,注意变压器。用于图像识别的卷积网络等等。

暂时就这样。感谢阅读。

为什么负载测试对于将您的 ML 应用程序投入生产至关重要

原文:https://towardsdatascience.com/why-load-testing-is-essential-to-take-your-ml-app-to-production-faab0df1c4e1?source=collection_archive---------25-----------------------

行业笔记

使用 Locust 对 Flask ML 应用程序进行负载测试

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

图片来自 Unsplash

随着我继续在数据科学、人工智能、人工智能的世界里航行,无论你想叫它什么,我继续发现越来越多的术语,这些术语最初是我害怕涉足的。正如我在之前的一篇文章中提到的,我来自一个非技术背景的人,经常把关键的软件术语,比如“测试”藏在心底。在获得了更多构建由 ML 驱动的应用程序的经验后,我明白了一种特殊形式的测试的必要性,这种测试被称为 【负载测试】 ,也被称为性能测试。负载测试是一种模拟或测试应用程序预期流量的方式。在 Flask 服务器上抛出一个端点并期望它保持运行是很容易的,但是在现实中,顺序测试一个端点并不能显示关于端点性能的真实情况。这就是为什么我们将使用一个名为Locust的开源 Python 工具来模拟我们的端点的多个并发用户**,看看它如何保持明智的性能。这种类型的测试对于理解您可能需要对您的项目/软件进行的优化所带来的变化以及关于成本节约以正确利用您正在使用的服务器是至关重要的。**

在本文中,我们将构建一个基本的 ML powered Flask 应用程序,但我们不会太关注这些步骤,因为它主要是测试我们用应用程序创建的端点。

目录

  1. 构建烧瓶应用程序和 ML 模型
  2. 创建蝗虫脚本
  3. 模拟用户
  4. 整个代码和结论

构建烧瓶应用程序和 ML 模型

在我们开始负载测试之前,我们必须创建我们的模型,并在一个简单的 Flask 应用程序上进行推理。对于我们的模型,我们将使用一个回归数据集,使用随机森林模型来预测汽油消耗量。下面的代码有助于将我们的模型训练和部署成一种 Flask 可以加载和处理的推断格式。

模型结构

现在我们已经建立了模型,我们可以使用 Flask 服务器来使这个模型可用于推理。

Flask 服务器

我们的模型现在可以在我们的服务器上的/预测路径下进行推理。为了确保我们的端点正常工作,我们创建了另一个文件,并使用请求库来测试推断。在这种情况下,使用另一个工具如 Postman 也是可行的。

测试 API

要测试这个脚本,请确保您的 flask 服务器已经安装了 flask,运行并执行 API 测试脚本来查看模型结果。

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

API 测试结果(作者截图)

现在,我们已经有了为推理加载的模型的 API,并且我们准备好开始用 Locust 进行负载测试。如果您想了解更多关于在 Flask 上部署 ML 模型的知识,请查看这篇很棒的文章,它专门围绕这个主题。

创建蝗虫脚本

如前所述,Locust 帮助模拟同时拥有许多用户,您可以在您的 locustfile.py 中定义一个任务来执行这个模拟。任务是 locust 中的关键特性,每次我们开始负载测试时,都会为用户创建一个我们创建的类的实例,它们执行 Python 脚本中定义的任务。

导入和设置

首先,我们从 Locust 导入必要的模块,然后创建一个类,该类将包含我们用于模拟的主要功能。继承 HttpUser 使用户能够处理我们想要加载测试的 HTTP 请求**,比如我们例子中的端点。**

在我们班里

在执行任何 Locust 任务之前调用 On_Start,当用户停止执行任务时调用 On_Stop。现在我们创建一个任务,将模拟数据发布到我们的 API。

发布模拟数据进行模拟

我们现在已经准备好测试我们的简单的 Locust 脚本,为了学习更多关于 Locust 的知识并开始使用您自己的脚本,请查看他们的文档这里

模拟用户

随着我们所有的资源准备就绪,我们现在终于可以看到蝗虫在行动,并查看它提供的一些指标。确保您的 flask 服务器已经启动,要运行我们的 locust 文件,只需在终端中键入 locust 。如果您的 locust 脚本没有命名为 locustfile.py,确保使用 locust -f filename.py 指向它。

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

作者截图

您应该到达如下屏幕,对于主机,您通常应该输入您正在使用的实际 IP。点击开始,你会看到蝗虫在行动。

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

作者截图

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

RPS(作者截图)

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

响应时间(作者截图)

在您的终端中单击 stop 之后,您应该会看到一些通用的统计数据,您也可以将其下载为 csv 文件,以运行进一步的分析或可视化。

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

综合统计(作者截图)

我们看到,Locust 跟踪各种指标,如请求/秒**、平均吞吐量响应时间,以及端到端延迟百分点。在浏览文档时,您可以使用更高级的 Locust 功能,下载这些统计数据来运行您自己的函数或服务,以确定您的应用程序的限制,或者当您接近某个延迟或吞吐量阈值时,您不希望越过该阈值。**

整个代码和结论

**https://github.com/RamVegiraju/Locust-ML

要访问该应用程序的完整代码,请查看上面的链接。Locust 是一种非常干净的方法,可以帮助您以高效而简单的方式对应用程序进行负载测试。关于负载/性能测试,还有许多其他的软件或方法,但是我只想强调负载测试在将你的应用提升到生产水平时的普遍重要性。从节约成本优化您的资源,负载测试对于了解您的端点实际上如何应对您在实时场景中预期的流量至关重要。

我希望这篇文章是对蝗虫和负载测试的一个很好的介绍。请随时在 LinkedIn 上与我联系,或者在 Medium 上关注我,了解我更多的写作内容。分享任何想法或反馈,谢谢阅读!**

为什么 Matplotlib 不能安装在 Visual Studio 代码中

原文:https://towardsdatascience.com/why-matplotlib-cant-be-installed-in-visual-studio-code-cb1261c822ad?source=collection_archive---------4-----------------------

因为有了 MVC++构建工具

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

作者制作的图片

我们知道“Matplotlib 是一个用于在 Python 中创建静态、动画和交互式可视化的综合库”。如果允许安装 Anaconda,通常使用 Matplotlib 没有问题。但是最近 Anaconda 为商业用户更新了服务条款。详细信息解释如下:

“为了应对过去几年商业用户对 Python 和 Anaconda 的使用和采用的急剧增加,我们更新了我们的服务条款。展望未来,我们要求依赖我们的包装&分销工作到商业用户购买我们的商业产品之一。”—https://www . anaconda . com/blog/anaconda-commercial-edition-FAQ

如果公司还没有准备好为 Anaconda 付费,一些工程师可能会转向 VS Code。

在 python 可以在 VSC 正常运行之前,有一些设置会困扰用户。大部分都是要求你安装库的错误,像“导入错误:没有名为 numpy 的模块”,可以通过“pip”或“pip3”或“python pip”或“python3 -m pip”等命令解决。来解决。

但是今天,我想把重点放在 Matplotlib 问题上,这个问题可能不能仅仅通过 pip 命令来解决。

万一:

  1. 你有一个视窗系统
  2. 您的电脑上没有安装 Anaconda
  3. Python 扩展已在 VSC 安装
  4. 解释器(在 VSC 的左下角)选择正确
  5. 没有安装 visual studio 构建工具(你可能也不知道为什么你需要它,直到问题发生,一个工程师(比如机械工程师)写 python 代码。

现在我们来举个例子。

尝试测试以下 py 文件:standardplot.py:

import numpy as np
import matplotlib.pyplot as pltx = np.linspace(0, 20, 100)  # Create a list of evenly-spaced numbers over the rangeplt.plot(x, np.sin(x))       # Plot the sine of each x pointplt.show()                   # Display the plot

你是否得到了下图的美丽身材:

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

还是你得到了错误?像下面:

Import Error: No module named numpy

谷歌一下,解决方案可能是:

pip install numpy
or 
pip3 install numpy
or
python3 -m pip install numpy
or
python3 -m pip install numpy

类似的问题如“没有 sklean 的模块”可以用类似的解决方案来解决。

再次运行它,现在 NumPy,没有问题,但是可能会有一个错误,如:

ERROR: Command errored out with exit status 1:
...... error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": [https://visualstudio.microsoft.com/visual-cpp-build-tools/](https://visualstudio.microsoft.com/visual-cpp-build-tools/)

这是因为您的计算机上没有安装 Microsoft C++Build Tools。为了在 Microsoft for Python 中运行 matplotlib 或类似的交互式界面,需要构建工具,而不仅仅是 Microsoft C++可再发行版。

如何:

单击链接,它会将您带到下面的窗口:

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

下载构建工具,运行。exe 文件,在安装过程中使用如下的 C++编译工具。一定要选择正确的物品。

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

图片来自这个网站

这需要一点时间,在这个过程中喝水或走动。😃

如果构建工具安装正确,现在以正常方式安装 Matplotlib。

运行 py 文件,你会得到如上的美丽图形。

外卖:

  1. 我写这个故事是因为当我搜索解决方案时,大多数人提到安装它,但很少有人提到这个案例。是的,这可能是一种罕见的情况(想想 Anaconda 无法安装…),但当它发生时,可能需要您花时间来解决它。希望这能让你想起这个案子。
  2. Microsoft Visual C++ build tool 是在 VSC 用 python 运行 Matplotlib 的先决条件的可能原因,我在下面找到了一个解释,但如果我错了,请随时纠正我。

Windows Python 需要通过 SDK 安装 Visual C++库来构建代码,比如通过setuptools.extension.Extensionnumpy.distutils.core.Extension。例如,使用 Python 在 Windows 中构建[f2py](https://www.scivision.dev/tags/f2py)模块需要安装如上所述的 Visual C++ SDK。在 Linux 和 Mac 上,C++库随编译器一起安装。-https://www . scivision . dev/python-windows-visual-c-14-required/

谢谢你的时间。希望有助于解决你在 VSC 的 Matplotlib 问题。

为什么 ML 应该从一开始就写成管道

原文:https://towardsdatascience.com/why-ml-should-be-written-as-pipelines-from-the-get-go-b2d95003f998?source=collection_archive---------14-----------------------

MLOps

通过迭代、可复制的管道消除技术债务

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

照片由EJ·斯特拉特Unsplash 上拍摄

今天,机器学习为世界上最有价值的 1%的组织(FB、ALPH、AMZ 等)提供动力。然而,99%的企业努力生产 ML,即使拥有超特定数据集和卓越的数据科学部门。

更深入地研究 ML 如何在组织中传播会更深入地揭示这个问题。下图显示了机器学习的典型设置的公认简化表示:

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

图 1:为什么很难复制 ML 模型

上述过程有三个阶段:

实验和概念验证:

  • 技术 : Jupyter 笔记本、Python 脚本、实验跟踪工具、数据探索工具
  • 角色:数据科学家
  • 描述:快速科学的实验定义了这个阶段。该团队希望尽快增加他们对数据和机器学习目标的理解。

转换:

  • 技术 : ETL 流水线工具,如 Airflow
  • 角色:数据工程师
  • 描述:将最终实验转化为自动化的、可重复的过程是本规范的目的。有时这在下一阶段之前开始,有时在下一阶段之后,但本质是相同的——从数据科学家那里获取代码,并尝试将它们放入某种形式的自动化框架中。

生产和维护:

  • 技术 : Flask/FastAPI,Kubernetes,Docker, CortexSeldon
  • 角色 : ML 工程师/运营
  • 描述:这是从模型部署开始的阶段,跨越监控、再培训和维护。这一阶段的核心重点是保持模型健康,并在任何规模下提供服务,同时考虑漂移。

每个阶段都需要不同的技能、工具和组织。所以,一个组织一路走来能碰到的坑坑洼洼也是理所当然的。不可避免的是,下游重要的东西在早期阶段没有被考虑。例如,如果培训与部署策略相分离,那么这在生产场景中就永远不会有好的表现——导致不一致、无声的失败以及最终失败的模型部署。

解决方案

查看上面图 1 中的多阶段过程,简单地减少所涉及的步骤并因此消除它们之间存在的摩擦似乎是显而易见的。然而,考虑到每个步骤的不同需求和技能,这说起来容易做起来难。数据科学家没有被训练或装备来勤奋地关心生产概念,如再现性——他们被训练来迭代和实验。他们并不真正关心代码质量,考虑到速度和开销之间的权衡,在早期过分努力地执行这些标准可能不符合公司的最佳利益。

因此,我们需要的是一个框架的实现,它是灵活的,但是从一开始就执行生产标准。实现这一点的一种非常自然的方式是通过某种形式的管道框架,该框架公开了一种在受控环境中运行 ML 实验的自动化、标准化的方式。ML 本质上是一个过程,可以分解为单独的具体步骤(如预处理、训练、评估等),因此管道是一个很好的解决方案。至关重要的是,通过在早期阶段标准化这些管道的开发,组织可以通过多种工具和步骤减少 ML 模型的破坏/重建周期,并加快从研究到部署的速度。

如果一个组织能够激励他们的数据科学家购买这样一个框架,,那么他们就已经赢得了生产化之战的一半。然而,真正的问题在于细节——如何在一个足够健壮的框架中为数据科学家提供他们进行实验所需的灵活性,以便一直应用到生产中?

寻找正确抽象的练习

从一开始就有了在管道中写作的动机,公平地说,我给出了关于如何实现这一点的框架的更具体的例子。然而,在我看来,目前的工具领域被分割成了许多框架,这些框架要么是为 ML 人员设计的 ML 工具,要么是为 Ops 人员设计的 Ops 工具,并没有真正满足我在上一节提到的所有要求。缺少的是一个面向 ML 人员的 Ops(读取管道)工具,带有适合数据科学家的高阶抽象。

为了理解这一点的重要性,我们可以看看 web 开发是如何从基于 PHP/JQuery 的原始脚本(web 开发的 Jupyter 笔记本)和 LAMP 堆栈发展到今天强大的基于 React/Angular/Vue 的现代 web 开发堆栈的。看看这些现代框架,它们的成功是由提供更高阶的抽象决定的,这些抽象更容易被更多的受众消费和消化。它们没有改变底层 web 技术工作的基本原理。他们只是以一种更容易被更多的观众理解和接受的方式改变了它的用途。具体来说,通过将组件作为一等公民提供,这些框架引入了一种分解、利用和重新共享为现代网络提供动力的 HTML 和 Javascript 的新机制。然而,ML(Ops)并没有相应的动作来找出正确的抽象顺序,以达到类似的效果。

为了展示我上面更抽象的想法的一个更具体的例子,我将使用 ZenML ,一个开源的 MLOps 框架来创建迭代的、可复制的管道。

声明:我是 ZenML 的核心维护者之一。

ZenML 是一个为 ML 寻找正确抽象层的练习。在这里,我们将管道视为一等公民。这意味着数据科学家直接接触框架中的管道,但与来自 ETL 空间的数据管道的方式不同( PrefectAirflow 等)。管道被视为实验— 意味着它们可以被直接比较和分析。只有到了转向生产化的时候,它们才能转换成经典的数据管道。

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

图 2: ZenML 用熟悉的语言抽象管道来增加模型部署的所有权。

管道中有步骤,这些步骤是用数据科学家熟悉的 ML 语言抽象出来的。例如有TokenizerStepTrainerStepEvaluatorStep等等。比将脚本插入某种形式的 orchestrator 包装器更容易理解的范例。

每个管道运行都会跟踪元数据和参数,并且可以与其他运行进行比较。每个管道的数据在流经时都会自动进行版本控制和跟踪。每次运行都链接到 git 提交,并编译成一个易于阅读的 YAML 文件,该文件可以选择性地编译成其他 DSL,例如 Airflow 或 Kubeflow 管道。这对于满足价值链中的数据工程师和 ML 工程师等其他利益相关者是必要的。

此外,为各个步骤公开的接口大多是以一种易于以幂等方式扩展的方式设置的,因此也是一种分布式方式。因此,当数据科学家处理更大的数据集时,他们可以使用不同的处理后端(如数据流/火花)进行横向扩展。

总而言之,ZenML 试图达到以下场景:

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

图 3: ZenML 统一了 ML 过程。

当然,ZenML 并不是实现上述目标的唯一机制——许多公司构建了自己的抽象框架来解决他们的特定需求。通常这些都是建立在我上面提到的一些其他工具之上的。不管如何实现,目标应该是明确的:让数据科学家尽可能接近生产并尽可能减少摩擦,激励他们在部署后增加对模型的所有权。

这是一个双赢的局面,对于任何一个将 ML 作为业务增长核心驱动力的组织来说都是一个巨大的胜利。

插头

如果你喜欢这里的想法,我们很乐意听到你对 ZenML 的反馈。这是开源,我们正在寻找早期采用者和贡献者!如果您发现这是适合您/您的数据科学家的抽象顺序,那么也请通过我们的 Slack 告诉我们,期待您的回复!

为什么大多数 A/B 测试效率不高

原文:https://towardsdatascience.com/why-most-a-b-tests-are-not-efficient-11b289414191?source=collection_archive---------19-----------------------

行业笔记

揭开纯粹探索的神秘面纱(第 0 部分)

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

A/B 测试有许多应用领域,例如药物测试。(图片由 Unsplash 上拍摄)

几十年来,A/B 测试一直是统计学的支柱,成为整个受控随机测试体系的基石,这是最神圣的科学确证技术。鉴于这个网站上关于这个主题的文章太多了,我认为没有必要让读者相信 A/B 测试的重要性,或者就此而言,参考这种技术似乎找到了自己的方式的不断扩展的应用领域列表。然而,A/B 测试的一个重要方面
却很少受到关注,这篇文章的目的就是填补这个空白。

快速总结 A/B 测试。

目前执行的基本程序本身非常简单。
以网站优化为例。一家公司希望推出其网站的新版本,希望新版本能比旧版本更好地影响用户注册该公司的服务。用户被分成两组,控制组(A 组)和测试组(B 组),分别展示新旧版本。每个用户,无论注册与否,都被假定提供一些关于他们所看到的网页版本质量的嘈杂反馈。通过两个概率密度(或质量函数,视情况而定)fA 和 fB,用平均值 A 和 b 对这种有噪声的反馈进行建模。然后,每组中的注册百分比指示哪个版本是优选的。从统计学上来说,这可以归结为使用噪声样本来测试以下哪个假设是正确的

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

(图片作者)

也可以通过用τ代替上面不等式中的 0 来测试所选的容差τ > 0。如下图所示,行业中最常用的方法包括

  • 利用经典统计学预先求出用户的数量 nA 和 nB(我从现在开始用通称“样本”代替“用户”),
  • 进行测试,以及
  • 做决定。

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

进行 A/B 测试的传统方式。(图片由作者提供)

听起来不错,不是吗?嗯,不完全是。虽然这个过程在科学上是正确的,但这不是本文的重点。如标题所示,其目的是通过向读者介绍更现代、更复杂的测试假设的方法来帮助提高 A/B 测试的效率。

什么意义上的高效?考虑测试消耗的样本数,即 N = (nA + nB)项。这个数字称为样本大小,由几个因素决定,如噪声方差和设计者认为可接受的【I 型,II 型】误差范围。请注意,在上面的过程中,所有与采样相关的决定都是在实验开始之前做出的*。具体来说,没有利用输入数据提供的越来越清晰来帮助决策的概念。即使使用了可能的最佳样本量估计,我现在也将论证为什么在许多情况下,可以证明这是次优的。自然,另一种选择是让数据本身决定取多少样本。换句话说,把 A/B 测试转到在线。*

顺序统计

允许基于输入数据做出决策的数学方法,因此,其样本大小不是预先固定的,被称为序列统计学。取而代之的是,对输入的数据进行逐个样本的分析,当收集到“足够”的证据支持某个假设时,预定义的停止规则会停止进一步的数据收集。因此,通常的网页优化 A/B 测试的顺序版本对进入的用户流起作用,并且包括

  • 一个采样规则将一个进入的用户分配到控制组或测试组(这里是网页版本),
  • 一个停止规则,以及
  • 基于可用证据接受/拒绝 H0 的决策规则

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

顺序测试可以提供高达 4 倍的速度!(图片由作者提供)

说明性示例

在进一步讨论之前,让我们先用一个简单的例子来证明顺序测试的优越性。对于给定水平的 I 型和 II 型错误,最有效的序贯检验之一是亚伯拉罕·瓦尔德的序贯概率比检验 (SPRT)。与我们的网页示例保持一致,这个测试如下进行。

为简单起见,假设 A < µB and that we know fA and fB up to a permutation, i.e., we are only trying to find which of the two webpages generates sign up samples from fA and which from fB: Let f0 = fA ⊗ fB
代表对照网页并不比测试网页更好的情况,f1 = fB ⊗ fA,相反的情况。预先选择两个阈值 L0 和 L1 (0 < L0 < 1 < L1 ),并使用以下

1.采样规则:

  • 进入的用户流被分成成对的流,并且每对中的用户被随机分配到两个网页中的一个。
  • 第 n 对的反应被记录为样本二元组

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

(图片作者)

  • 定义 Zn = Xn — Yn,设 g0,g1 分别是 Zn 在 f0 和 f1 下的分布。

2.停止规则:

直到时间 n 的累积似然比,由下式给出

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

(图片作者)

并与阈值进行比较。如果任一λn < L0 or λn > L1,测试停止。否则,对 n + 1 对重复测试。

3.决策规则:

如果λn < L0 accept H0 and if λn > L1 拒绝 H0。

当 fA N(A;σ)和 fB≡N(B;σ),这在许多自然应用中是正确的,可以表明 SPRT 的平均样本量约为(2σ )/( A- B)。另一方面,普通的 A/B 测试需要大约(8σ )/( A- B)个样本。因此,顺序程序代表着效率提高了 4 倍!

上面的例子虽然很能说明问题,但并不完全符合实际情况,因为一般来说,平均值 A 和 B 是未知的。在文献中,这个例子是一个更一般的(序列)统计结构的特例,称为双臂土匪。具体来说,它属于一类被称为“最佳手臂识别”的问题,或称纯探索。这篇文章的目的是激起读者的兴趣,在本系列的后续部分,我们将更详细地讨论
当前背景下的多股武装匪徒。

从多臂强盗(MAB)的角度进行 A/B 测试有几个优点。

  • 纯探索的 MAB 算法不需要手段的知识。
  • 如果需要同时测试多个(3 个或更多)假设,该怎么办?在我们的例子中,公司可能想在几个网页版本中找到最好的。MAB 算法可以轻松处理这种
    情况。
  • 正如我们将要看到的,纯探索分析对样本量有非常严格的限制,因此,可以显著地提高这种检验的效率。

结束语

我希望我已经说服了读者需要更详细地理解最佳 Arm 标识。在本系列的下一部分,我们将设计并分析一个非常简单的纯探索算法(不,是不是汤普森采样)。我们将一点一点地检查这个算法的样本大小的表达式,并看到它包含了与自然现象相关的重要因素,这些自然现象是随机过程理论的核心。

值得注意的是,在过去的三十年里,纯探索领域的许多研究都受到了这些因素的影响。因此,对它们的含义以及它们是否可以避免的讨论将构成本系列的结论部分。

(注:参考资料将在第 2 部分末尾提供。)

为什么多重共线性不是机器学习中的问题

原文:https://towardsdatascience.com/why-multicollinearity-isnt-an-issue-in-machine-learning-5c9aa2f1a83a?source=collection_archive---------12-----------------------

多重共线性的处理取决于分析的目的。学会区分模型解释和预测将影响数据准备步骤。

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

由作者编辑的 Unsplash 上的 Austin Chan 照片

H 阿文在哥本哈根商学院教了三年统计学,我已经非常习惯于解释多元线性回归的模型假设(如果你需要重述的话,)。简单线性回归和多元线性回归在假设上的唯一区别是多重共线性的问题。

我教我的学生如何检查这个假设,如何处理它,但是突然一个教授告诉我忽略它。本文将概述他的回答,并通知您何时注意多重共线性的可能性。

什么是多重共线性?

当特征之间高度相关时,我们通常说存在多重共线性或相互关联的问题。有多种方法可以检测多重共线性。一种方法是使用如下所示的相关矩阵:

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

作者图片

该矩阵清楚地显示了花瓣长度(cm)和花瓣宽度(cm)之间的高度相关性。发现多重共线性的另一种方法是计算方差膨胀因子(VIF ),经验法则是 VIF 不应高于 10:

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

作者图片

我们显然发现了数据集中的多重共线性,但是我们应该处理它吗?看情况!

模型解释

向学生介绍统计学目标通常是模型解释。换句话说,目标是了解当自变量(也称为特征)之一发生变化时,目标变量(也称为因变量)的影响或变化。例如,我们有下面的等式(为了简单起见,忽略误差分量):

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

我们可以通过假设我们正在计算一所房子的价格来使它更加相关,我假设这取决于房间的数量、平方、基底面积和楼层的数量:

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

通过计算参数估计值(β系数),我们可以了解房价和独立变量之间的关系。假设正方形的数量独立于其他变量,增加将意味着房子的价格将增加β2。

假设我们有由房间数和楼层数之间的强相关性引起的多重共线性,不调整或处理多重共线性将导致错误的参数估计,并破坏要素的统计显著性。在这种情况下,我将不得不移除一个独立变量,以便获得更可靠的估计值(为了更直观地展示效果,请单击此处)。

多重共线性的一个典型示例是某个要素的所有名义类别都包含在回归模型中。通过排除一个类,我可以用它作为解释参数估计的基线,同时避免多重共线性。

模型预测法

当数据准备的目标是预测而不是解释时,我们会发现自己处于另一种情况。这一点在考特纳(2005)的《应用线性统计模型一书中有所概述:

事实上,一些或所有的预测变量之间是相互关联的,这通常不会抑制我们获得良好拟合的能力,也不会影响对新观察结果的平均反应或预测的推断。

要了解为什么会出现这种情况,让我们假设有以下数据集:

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

作者图片

两个独立变量 X1 和 X2 完全相关。这通常意味着不可靠的参数估计,但是让我们从给定的数据着手,并拟合一个多元线性回归模型。第一个等式可能如下:

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

该方程完全符合数据,但另一个很好的拟合将是下面的(尝试插入表格中的数字并自己查看):

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

第一个等式表示 X2 对目标变量有很大影响,而第二个等式则讲述了一个完全不同的故事。这意味着,只要我们不开始解释参数估计,我们就可以很容易地拥有完全符合数据的模型,甚至可以用它们进行预测。

换句话说,在为以预测为目标的机器学习上下文准备数据集时,您不必删除任何列。

文章中图表的代码:

我希望你像我喜欢写这篇文章一样喜欢它。如果你理解我的代码有任何困难,请留下评论。数据科学社区给了我很多,所以我总是乐于回馈。

请随时在 Linkedin 上与我联系,并在 Medium 上关注我以接收更多文章。

为什么多重分派是我最喜欢的编程方式

原文:https://towardsdatascience.com/why-multiple-dispatch-is-my-favorite-way-to-program-786bf78f4878?source=collection_archive---------10-----------------------

多种调度的优势概述,以及我为什么这么喜欢它。

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

(https://unsplash.com/photos/cvBBO4PzWPg

简介—一些历史

Julia 语言是一项令人难以置信的技术壮举,自 2008 年以来一直在进行中,并在过去几年中真正取得了进展。这种语言以其独特的范式和编程风格令人兴奋、面向科学,并且使用起来很有趣。要理解 Julia 编程语言,您需要理解多重分派。

多重分派是一个基于参数多态性的通用编程概念。一般来说,多态性有趣的地方在于,它通常是声明式和函数式编程的一种品质,但是这种品质本身似乎在其他编程范例中有更好的描述。多重分派是 Julia 编程语言的支柱,但这肯定不是编程概念的起源。多重分派的编程概念实际上最早是在 48 年前的 1973 年提出的!第一个实现是用一种叫做 ML 的小语言实现的,这种语言是由爱丁堡大学的 Robert Milner 和其他同事发明的。

这种语言与我们今天使用的许多高级编程和脚本语言非常相似。ML 和许多更具声明性的现代语言之间的最大区别是 ML 也是一种非常命令式的语言,当你考虑到这种语言也是函数式的时,这似乎有点奇怪。从 70 年代中期开始,许多语言实际上都遵循这种语调,我认为这是一个有趣的观察。我们总是称赞 C++真正发明了泛型的概念,但是在 70 年代出现了如此多的多范例语言,以至于几乎不可能跟踪它们。

什么是多重派遣?

多重分派是一个编程概念,它允许程序员多次编写一个函数来处理不同的类型。许多程序员倾向于远离函数式编程范式,因为它具有全局范围。这是可以理解的,让一切全球化,尤其是像 Julia 这样的出口,可能会很成问题。这主要是因为命名。实际上,很久以前我写过一篇关于 Julia 语言中的名称空间的文章,在那里我讨论了为什么一个类似于 C++的名称空间的实现可以减轻这个问题。我认为这是一个有趣的阅读,如果你想看看你可以在这里:

这个问题在函数中尤其普遍。这是因为 Julia 不是一种面向对象的语言,因此没有一个真正的类作用域,我们可以使用它来使函数私有,以便处理特定的类型,我们只是编写方法来将我们的类型放入全局作用域中。这意味着很多时候我们可能有名字完全不同的方法,却做着完全相同的事情。当然,在朱丽亚身上完全不是这样,之所以不是这样,是因为多次派遣。

多重分派是一种我们可以将函数调用作为类型属性来应用的方式。换句话说,我们可以一次又一次地重新定义同一个函数,但只是计划不同的类型通过它,以便从本质上重新创建方法来处理新的类型。考虑下面的例子。

x = [1, 2, 3, 4, 5]
y = 5
function add_5(x)
    x + 5end

上面的函数给作为 x 传递的参数加了 5,对于这个例子,我们只能通过这个函数传递 y。如果我们试图通过这个函数传递 x,我们会很快意识到没有匹配+(Array,Int64)的方法。这当然是因为我们没有办法把一个整数加到数组中。我们也不想草率地用另一个名字写另一个函数,就像这样:

function add_5_array(x)
     [x += 5 for x in array]
end

那太荒谬了。幸运的是,多重分派正是为了解决这个问题而产生的。使用 dispatch,我们可以将一个类型转换为这两个函数的参数,当该类型通过函数传递时,只有该特定类型的函数才会运行。

function add_5(x::Array)
     [x += 5 for x in array]
endfunction add_5(x::Int64)
    x + 5end

现在我们可以毫无顾虑地让 x 和 y 通过这里。

朱莉娅的现代调度

multiple 的 Julian 实现类似于典型的 multiple dispatch,但是使用了类固醇。我们不仅获得了能够在一行中非常快速地调用多个分派的额外好处,就像我们在用 Python 编写 lambda 表达式一样,我们还可以选择以两种方式交替编写函数。此外,朱莉娅有更多的锦囊妙计,使多重调度更好。

给 Julia 的调度增加美感的第一件事是创建子类型的能力。在 Julia 中,大多数类型都属于一种叫做超类型层次结构的东西。超类型层次结构只允许我们跨具有相似类型的方法创建继承,并且可以由这些函数以相同的方式处理。例如,假设我们有一个可以接受无理数、整数或浮点数的函数。我们可以通过简单地从我们的函数中分派实类型来限制这将到达树的哪一部分。

add5(x::Real) = x + 5

我们也可以在这个函数的使用中包括复杂类型,取而代之的是沿着树向上并调用所有的数字:

add5(x::Number) = x + 5

这意味着我们不仅可以分派我们的类型,还可以让其他类型继承我们分派给抽象类型的那些函数。如果你想了解更多关于我刚刚提到的数字层级的知识,我有一整篇文章,你可以在这里阅读:

Julia 令人敬畏的内部构造函数为 dispatch 增添了美感。内部构造函数允许您创建多个输入来实现相同的输出。这些基本上是初始化函数,可以接受任意数量的参数,然后从提供的参数中构造应用它们的类型。真正酷的是,dispatch 会注意是否有人在调用内部或外部构造函数,所以您仍然可以使用普通参数创建类型,但您也可以使用新参数创建它。考虑下面的例子:

mutable struct broken_array
    dim1
    dim2
end

这里我们有一个新的类型叫做 broken_array。为了从两元素数组中构造这种类型,我们需要填充 dim1 和 dim2 数据值。我们当然可以这样做:

array = [5, 2]
broken = broken_array(array[1], array[2])

然而,这对于终端用户来说有些不方便。我们可以用内部构造函数来解决这个问题,就像这样:

mutable struct broken_array
    dim1::Int64
    dim2::Int64 function broken_array(x::Array)
        new(x[1], x[2]) end
end

我们之前执行的旧调用仍然会被调度来通过调用外部构造函数直接创建类型,但是现在我们有了扩展的功能,可以像这样用我们的数组调用内部构造函数。

broken = broken_array(array)

很酷,对吧?

另一个很棒的事情是,它还使得语言中的所有类型和方法都具有难以置信的可扩展性。我们可以从任何包中取出任何类型或任何方法,直接导入,并扩展它做我们想做的任何事情。类型的内部构造函数甚至也不需要在构造函数中,所以我们可以真正利用和编写函数来创建其他包中已经存在的类型,并在任何地方使用它们。此外,我们甚至可以用自己的类型扩展其他方法。一个非常酷的结果是,Julia 中的所有包经常使用相同的一组基方法,而你可能习惯于使用完全不同的类型。

结论

在我工作和涉足的所有编程语言中,Julia 很容易成为我最喜欢的编程语言。这是多次调度的直接结果。Julia 语言中的多重分派概念不仅允许一些非常激进和富于表现力的编程,而且允许对该语言中使用的任何方法或类型进行扩展。不用说,这是一个非常强大的概念。此外,这也是科学编程的一个好方法,因为方法调用和函数定义经常看起来就像在论文中一样。非常感谢您阅读我的文章,并希望它可能会使您倾向于检查出美妙的礼物是多派遣!

我的认知科学学位如何为数据科学和机器学习奠定了坚实的基础

原文:https://towardsdatascience.com/why-my-cognitive-science-degree-was-a-great-foundation-for-data-science-and-machine-learning-f5838b527d40?source=collection_archive---------14-----------------------

数据科学中的个人故事

从认知科学背景进入机器学习和数据科学领域令人生畏——但最终提供了一个有益的基础。

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

Bret Kavanaugh 拍摄的 Unsplash 图像

我进入了数据科学和机器学习的领域,其中隐藏着许多不确定性和不安全性。我有无尽的好奇和兴奋——天真而乐观。但是萦绕在我脑海深处的是一种不安全感,*我不是来自任何传统背景,*例如,计算机科学、统计学或商业。相反,我毕业时获得了认知科学学士学位。然而,随着时间的推移和我经验的增长,一个想法开始慢慢解开——也许,我的背景提供了比我最初预期的更坚实的基础。

首先,什么是认知科学?

每当有人问起我的专业,我往往会背诵:

“认知科学是神经科学、人工智能、计算机科学、哲学、心理学、语言学和人类学的交叉领域.”

这并不能解释太多,通常会得到缓慢的点头和不确定的*“…好的。”*

因此,我想花一点时间来表达我所学到的东西,以及为什么我会对它提供给我的框架心存感激。

心灵的神秘

我怀着强烈的愿望开始了我的研究,想了解心灵;发现的最有力途径之一是通过认知失败的案例。

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

照片由 E ngin AkyurtUnsplash 上拍摄

我了解到有些人不能识别面孔。其他人通过颜色来看声音。有些人在看到痛苦的人时会感到痛苦。其他人强烈渴望截肢,因为他们认为这是一个入侵的实体。有些人醒来时会不由自主地被自己的手掐住脖子。最重要的是,我已经意识到每种疾病都伴随着一种生物损伤。这些生物损伤有治疗方法。

在我们对这些疾病的存在有所了解之前,我们会把任何偏离常态的人归类为“疯子”。例如,那些患有面孔失认症的人可能在识别他们的孩子或同事方面有困难。这意味着如果他们走过一个他们认识但不认识的人身边,却没有和他们打招呼,他们可能会显得很粗鲁。

或者一些患有身体完整性认同障碍的人想要截肢,因为他们觉得这是一种阻碍。因此,旁观者会认为他们“疯了”,而不是考虑造成这种情况的潜在身体缺陷。

那么什么是认知科学,为什么它是跨学科的?

然而,精神障碍只是我研究的一个方面。我的专业,简而言之就是围绕*【理解认知】。换句话说,这种神秘的能力我们必须去思考、推理和获取知识。*

在这门学科中,我获得了一种新的自我意识,以及思考人类经历所包含的东西的途径。在认知科学领域之前,我们使用严格的内省和心理学,或者严格的神经科学和生物学来研究这个主题。

但是认知科学提出,为了理解大脑的复杂性,我们不能依赖一个单一的学科来获得所有的答案。我们需要理解思维的内部状态以及大脑的解剖结构——但这还不够。我们需要了解社会、文化、语言、现代技术以及其他一切可能有助于发展我们思考能力的事物。

更准确地说,我的研究使我能够深入研究意识、梦、记忆、注意力、存在、神经系统、社会、文化、药物对大脑的影响、开发略微模拟大脑神经网络的计算机系统的过程,以及不断发展的技术的其他方面。

那么数据科学和机器学习在哪里呢?

我在下面列出了我看到的认知科学世界和数据科学/机器学习世界碰撞的几种方式。

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

国家癌症研究所拍摄的 Unsplash 照片

  1. **神经网络和神经科学:**神经网络的灵感来源于人脑的神经回路。在 了解这种生物现象的数学表示之前,研究神经元、连通性以及信息如何向前传播 是很有见地的。尽管深度学习领域引入了新奇的术语,但这些数学模型所启发的潜在生物过程要复杂得多;网络架构是简化的数学表示。此外,深度学习架构中的许多变体也是受生物副本的组件或模仿人类认知的想法的启发。有了更复杂的生物学灵感的基础后,概念化这些模型和概念就容易多了。
  2. **人机交互和数据可视化/讲故事:**理解思维的一个关键部分是理解人类如何捕捉和保留信息。在认知科学中,我们研究记忆和注意力的基本过程。我们研究注意力是如何被捕捉的,人们可能会关注什么,以及我们如何自然地将视觉线索分组以理解一个总体故事。此外,我们调查了不同文化之间的认知差异,以及生活方式和传统如何影响我们的思维方式。这一背景使我能够批判性地思考可视化。谁是观众,这些颜色对这个群体来说代表什么?我的视觉化能把观众的注意力引向我想要传达的东西吗?是否有太多的杂乱会分散我的听众快速直观地理解信息的注意力?人类一次能理解多少信息?
  3. **统计分析:**任何科学努力都会带来统计分析。科学研究数据检查、概率评估和预测分析。从我完成的统计学课程中,我对我遇到的每一条新信息或统计数据都抱着健康的怀疑态度。我喜欢问这样的问题:“谁是研究的对象?取样是如何进行的?实验设计符合最初的问题吗?实验设计是否让我们有信心做出更广泛的结论?我们能利用这些信息做些什么,这符合道德吗?”这种怀疑同样适用于机器学习问题。重要的是要采取一种方法和全面的方法,特别是如果我们的模型的部署具有社会影响。
  4. 计算社会科学和网络分析:认知科学中有一个探索分布式认知的框架,根据维基百科,“指的是一个认知资源在中被社会共享以扩展个体认知资源的过程”。目标是分析认知是如何在个体范围之外产生的,包括探索个体之间的相互作用。我的计算社会科学课相当直接地翻译成了网络分析。我的班级通过模拟和建模调查了社会互动和行为互动。为了分析连接度,我们应用了网络分析技术。这些技术在数据科学领域中无处不在。
  5. **神经信号处理与一般时间序列分析:**神经信号处理的目标是对神经信号进行分解,以提取大脑如何表征和传递信息的信息。由于这些神经信号具有时间成分,我们可以将它们表示为时间序列数据。因此,我能够将该课程中使用的相同技术应用于其他时间序列数据集。

虽然我只阐述了我的认知科学和机器学习研究之间的 5 个联系,但这个列表并没有结束。其他一些共享主题包括微积分、线性代数、A/B 测试、数据伦理等。慢慢地发现我以前的学习并没有让我处于劣势,这让我感到很温暖;相反,它提供了一个坚实的基础框架。

冒名顶替综合症

我带着一种强烈的冒名顶替综合症的感觉开始了向数据科学和机器学习的过渡。尽管我不确定,但我从未对研究心灵感到后悔。对思维的研究让我产生了一种愿望,那就是为那些遭受神经损伤或与精神健康问题作斗争的人服务。与此同时,对数据科学和机器学习的研究激发了人们利用我们所拥有的计算能力来为社区服务的热情。

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

卢卡斯·法夫尔拍摄的 Unsplash 照片

最后,值得注意的是,虽然冒名顶替综合症可能会让人麻痹,但在许多情况下,它促使我更快、更有意识地学习。我开始害怕这些话题会从我的头上飞过,却发现我的背景出人意料地让我有了直观的联系。现在我有了一个“缩小”的镜头,不是来自“传统背景”的恐惧和不确定性被纯粹的感激所取代。

建议

如果任何读到这篇文章的人也感受到来自非传统背景的不确定性,要知道你并不孤单。许多数据科学家和机器学习实践者并没有传统背景。请记住,这项研究涉及到我们可以应用于任何领域的工具,您的道路将使您能够建立独特的联系,帮助您巩固新概念。

最后,不要让冒名顶替综合症的感觉压倒你。相反,让它为你提供必要的动力和意图,以跟上数据科学和机器学习不断变化的格局。

为什么我 90%准确率的模型不工作

原文:https://towardsdatascience.com/why-my-model-with-90-accuracy-doesnt-work-685817a2b0e?source=collection_archive---------9-----------------------

不平衡数据集的模型性能度量

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

阿菲夫·库苏马在 Unsplash 上拍摄的照片

当您处理客户流失(当客户在一定时间内停止使用公司的产品)预测等营销问题时,原始数据集通常是不平衡的,这意味着类别本质上是不平衡的。基本上,这意味着你的客户流失的百分比可能比那些没有流失的要低得多。在本例中,二进制分类问题可能有 80–20%的分裂,只有 20%的客户停止与该公司的合作,80%的客户继续购买。

问题是,这 20%可能对企业的底线非常重要。

想想看,一家礼品公司有 100,000 名客户,平均每人价值 50 美元。这些客户给了你 500 万美元,但是如果有 20%的人不再购买该公司的产品,你就损失了 100 万美元!在几年的时间里,即使是最大的电子商务公司或实体店,这一数字也会增加。因此,公司营销部门的一个主要目标是预测客户何时会流失,并实施某种干预措施来防止这种情况发生。

用于流失预测的机器学习

现在,如果你的公司有一个好的数据科学/数据分析团队,你可能会很幸运。有了一个好的客户流失预测模型,你可以在客户放弃你的业务之前进行干预,并有可能让他们回到他们的忠诚状态。现在,我们进入下一个问题——当我们使用二元分类模型时,不平衡的类往往会使事情变得有点混乱。主要是,许多分析师转向的核心性能指标是准确性,但准确性只能告诉你这么多…

什么是准确性?

在另一篇关于走向数据科学的文章中, Koo Ping Shung 评论了不同的性能指标来评估你的 ML 模型。在本文中,我们将回顾其中的一些选项,以及为什么它们可能比准确性更适合不平衡的数据。

准确度 =正确预测总数/预测总数

直觉上,准确性是有意义的——你想知道你有多少预测是正确的。不幸的是,有了不平衡的数据,事情就没那么简单了。让我们看一个例子…

您有来自营销部门的去年客户流失数据,总共有 100,000 名客户和 20,000 名流失客户。现在,如果我们预测所有 100,000 个都不会流失,这意味着我们有 80,000/100,000 个正确(80%的准确率)。在这个例子中,您实际上没有识别出任何问题案例。如果你更进一步,你的数据更加不平衡(90-10 分裂),如果你预测每个人都不会流失,你的模型实际上会有 90%的准确率,尽管没有识别出一个问题案例。

最终,准确率为 90%的模型可能无法工作。

那么,我们该如何解决这个问题呢?

正如前面提到的文章中所讨论的,还有模型性能的其他度量。出于我们的目的,我们将回顾三种这样的措施:

  • 精确
  • 回忆
  • 子一代

精度

精度=真阳性/(真阳性+假阳性)

这可能看起来不像精确度那么清晰,但是本质上,精确度告诉你离你的目标有多近。也就是说,如果你预测正确,你会得到更多的“分数”,但是如果你错误地分类,你也会失去一些分数。因此,如果我们要抓住所有 20,000 名流失的客户,这是 20,000 个真正的阳性,但如果我们还包括另外 20,000 名没有真正流失的客户,我们的精确度就会下降,如下所示。

无误报:20,000/(20,000+0)= 100%

误报率:20,000/(20,000+20,000)= 50%

当您有一个不平衡的数据集,并且您想要防止误报(或者在 stats 中称为类型 1 错误)时,Precision 就很方便了。例如,如果你正在诊断癌症并实施有风险的治疗,你要确保你只治疗那些病人。如果你对大部分没有真正生病的人使用这种治疗(假阳性),你可能会有一些非常负面的影响。

回忆

回忆=真阳性/(真阳性+假阴性)

如果使用精确度来防止假阳性,那么召回是防止假阴性(也称为“遗漏”或 2 型错误)的等效措施。看同类型的例子,如果我们正确地分类我们所有的搅拌,我们不会错过任何一个,我们将有完美的回忆,如下所示:

无漏报:20,000/(20,000+0)= 100%

现在,如果我们错过了 5,000 个目标案例,我们的召回率就会下降,包括分子和分母,如下所示:

有假阴性:15000/(15000+5000)= 75%

如果你的班级不平衡,回忆是一个很好的选择,最重要的是你找到所有的问题案例。在前面的客户流失预测示例中,假设分析的目标是找出谁最有可能流失,并向这些客户发送非侵入性消息,提醒他们再次购买。

如果出现误报的唯一风险是发出一些额外的通知,那么召回可能是一个很好的性能指标选择。你可能不在乎把 500 张明信片寄给那些不太可能流失的人,从而浪费了它们——你在乎的是你抓住了所有真正的正面案例。(您识别了每一次点击)。

F1 得分

F1 分数可能是最不直观的性能指标,但它可能是解决您的问题的正确方法。

F1= 2 X(精度*召回)/(精度+召回)

基本上,F1 分数是精确度和召回率的组合,它允许您在确定模型性能时权衡您的误报和漏报。

如果你想更好地理解你计算中的原始数字,维基百科在分解数学方面做得很好。

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

来源:https://en.wikipedia.org/wiki/F-score

如果您识别了 20,000 个目标案例中的 15,000 个,但是您也错误地识别了 5,000 个(并且遗漏了 5,000 个),您的 F1 分数将如下所示:

f1:15000/(15000+. 5(5000+5000))=75%

F1 分数的顶点是精确度和召回指标的调和平均值

后续步骤

现在我们已经看了一个如何分析不平衡数据集的例子,很明显,准确性可能并不总是最好的衡量标准。底线是,你可以有一个准确率为 90%的模型,但召回率或精确度为 0%。如果您在 python 中运行逻辑回归,您可能需要考虑一些选项来处理这些类型的问题:

  • SMOTE —这个包允许你过采样或欠采样来平衡你的类
  • 加权逻辑回归 —通过选择每个类别的权重(或简单地选择根据类别分布平衡权重),您可以设置 TP、FP 和 FN 的重要性级别,从而对结果进行更多控制。

摘要

不平衡的分类问题可能很难处理,即使使用 R 和 python 作为机器学习算法。然而,本文的目标是防止您基于不完整的数据分析而犯逻辑错误。关键要点如下:

  • 准确性并不总是最好的
  • 定义你的商业目标
  • 查看用于平衡数据的包

我希望你喜欢这篇文章,如果你有任何问题,请随时联系我们!

为什么神经网络有激活功能

原文:https://towardsdatascience.com/why-neural-networks-have-activation-functions-9732e5405d4e?source=collection_archive---------25-----------------------

入门

它们是强制性的。

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

作者图片

有一次面试,有人问我“为什么神经网络有激活功能?”那一刻,我坚信没有激活功能的神经网络只是线性模型,因为我在某本书上读到过,但我不确定为什么是这样。不过我自信地回应道,“因为一个没有任何非线性激活函数的神经网络只是一个线性模型。”面试官回答,“嗯,有意思,我不确定这是不是真的,我想知道的是‘它们让计算梯度变得更容易’。”这立刻成了我新宠的面试问题。

会后,我翻遍了我的书,试图找出我是在哪里第一次了解到这个事实的。我是在伊恩·古德菲勒、约舒亚·本吉奥和亚伦·库维尔的《深度学习》 中找到它的。第 168 页,关于前馈神经网络的主题[1]:

f⁽ ⁾应该计算什么函数?到目前为止,线性模型为我们提供了很好的服务,让 f⁽ ⁾成为线性模型也很有吸引力。不幸的是,如果 f⁽ ⁾是线性的,那么前馈网络作为一个整体将保持其输入的线性函数。暂时忽略截距项,假设 f⁽ ⁾ ( x ) = Wᵀx,f⁽ ⁾ (h) = hᵀw.,那么 f(x) = xᵀWw.我们可以把这个函数表示为 f(x) = xᵀw’,其中 w’ = Ww。

随着近年来对人工智能和机器学习的兴趣激增,我觉得以几种替代形式写一篇文章来说明这一事实似乎是有价值的。我希望其中的一种表示能引起你的共鸣,在这篇文章中,我将提供大量的视觉效果和代码片段供你自己观察和使用。为本文编写的所有代码都是开源的,可以在我的 GitHub 上获得。如果在本文中出现的代码片段的上下文不清楚,请参考本文的伙伴 GitHub repo 以获得完整的上下文。

在我们讨论神经网络之前

我认为,首先概念化一个具有数百万参数的巨大神经网络如何可能是一个线性模型,如果我们没有向它添加任何非线性激活函数,这有点势不可挡,所以在我们开始将我们的讨论与神经网络联系起来之前,让我们谈谈单变量模型。假设我有一个单变量模型,其中我将一个输入( x )乘以某个数量( n )的系数( β ),并添加相同数量( n) 的偏差(偏差):

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

相乘后:

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

上述内容可以重新表述如下:

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

从这里,我们可以将公式的各个部分分配给变量:

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

然后最后替换为:

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

最终,尽管我们做了所有的乘法和加法,我们只剩下一个线性模型。这是有意义的,因为 β偏置都是简单的常数。一个代表一串随机实数的乘积,一个代表一串随机实数的乘积之和。因此,如果我们选择用实际值替换等式中的 β(s)偏差,我们会发现自己留下了一个非常熟悉的公式,其中我们将变量 x 乘以某个斜率 β ,然后添加一些截距偏差。为了用一些代码形象化这个事实,我们将首先编写一个随机模型类:

这个类从我们的原始公式中初始化 β(s)、bias(es)和 n 。当被调用时,这个模型执行上面详述的相同过程来计算 f(x) 。最后,我们需要一个单变量线性回归,代表我们的最终方程:

从这里,我们可以初始化一个随机模型,并拟合我们的 OLS 回归。

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

完整的脚本,点击这里。作者图片

正如你所看到的,由这种方法生成的每个随机模型都可以用一个简单的单变量 OLS 来表示。我选择强调这个过程,因为迭代地将一个输入乘以一个系数,然后添加一个偏差项,这与神经网络的前向传播步骤中发生的过程没有太大的不同。也许现在感觉,如果没有任何非线性激活函数的神经网络仅仅是一个线性模型,这应该是正确的,但是在我们接受这种直觉作为事实之前,让我们说明一个平凡的小神经网络。

一个玩具神经网络

假设我们有一个简单的神经网络,它有两个输入,一个具有两个节点的隐藏层(具有线性激活函数),和一个输出。

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

为了便于阅读,对权重和偏差进行了标注。作者图片

从这里我们可以得出结论:

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

我们应该已经注意到,这些方程都是一个简单的线性模型。接下来,我们可以为等式的各个部分分配新的变量(在这个例子中,我选择替换,以使我们接下来的每一步更具可读性,我们可以轻松地避开这种替换):

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

因此:

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

从这里开始,让我们将 h₁ 代入一个等式,然后乘以:

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

现在让我们用 h₂ 和我们的 c 等式做同样的事情:

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

从这里开始,让我们将 ac 代入我们的方程 y :

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

分组相似术语:

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

将新变量分配到等式的各个部分:

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

最后,将这些代入我们的公式:

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

我们又一次只剩下一个线性模型。事实上,如果我们选择增加神经网络的大小和深度,不管有多剧烈,我们都可以执行相同的简化,并最终从中导出一个线性模型。

正如我们之前所做的,让我们编写一些代码来测试这个发现,方法是生成非平凡大小的神经网络,并对它们的输入和输出进行线性回归拟合。首先,创建随机前馈神经网络的函数:

我正在覆盖默认的偏差初始化“零”,以确保偏差对输出有影响,因为我们不会改变任何初始化的权重

接下来,让我们使用随机神经网络生成一些输入和输出,我们可以使用它们来训练线性回归(这次我们将使用 scikit-learn 的线性回归实现,而不是扩展我们的实现以包括多个输入和输出):

运行完整脚本会返回:

$ python3 ff_example.pyr2 score: 0.999999999999102
mse: 1.7702930123167377e-14

在这一点上,我们可以非常肯定伊恩·古德费勒、约舒阿·本吉奥和亚伦·库维尔是正确的(我的意思是,通常可以非常安全地假设这些人是正确的)。然而,你们中的一些人可能会想,“到目前为止,我们只做了简单的前馈神经网络,那么具有卷积层或递归层的神经网络呢?”好了,现在我们有了一个比较神经网络和线性函数的框架,我们可以简单地修改我们的函数来测试其他层类型:

$ python3 cnn_example.pyr2 score: 0.9999999999793131
mse: 7.416074040925858e-16
$ python3 rnn_example.pyr2 score: 0.9999999999749045
mse: 5.490464324395404e-08

如你所见,如果你所有的激活函数都是线性的,那么递归层、卷积层、甚至池层都不会产生任何非线性。

异或线性与异或非线性

作为最后一个例子,我觉得这是最快速地说明具有所有线性激活函数的神经网络和具有非线性激活函数的神经网络之间的差异,让我们检查不同的神经网络如何在 XOr 上执行。

异或运算

XOr 读作“异或”是一个著名的逻辑连接词。[2]

逻辑上称为“异或”或“异或”的连接词。如果两个条件中恰好有一个(但不是两个)为真,则产生 true。—https://mathworld.wolfram.com/XOR.html

我们将关注二进制异或方程。二进制异或有如下真值表:

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

作者图片

模型

在本练习中,我们唯一要参数化的是激活函数,关于架构的其他一切都将保持一致:

我们的神经网络,可视化后,看起来像这样:

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

作者图片

线性模型

基于我们现在所知道的,我们如何期望完全线性激活的神经网络运行?

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

完整的脚本,点击这里。作者图片

正如预期的那样,我们的神经网络具有所有线性激活函数,其表现与线性回归模型完全一样。

非线性模型

现在,如果我们改变隐藏层的激活函数为 sigmoid 而不是线性的呢?

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

完整的脚本,点击这里。作者图片

通过简单地将隐单元的激活函数改变为非线性 sigmoid 方程,神经网络可以适当地解决 XOr 问题。这是相同的神经网络,但是使用 ReLU(校正线性单元)激活:

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

完整的脚本,点击这里。图片作者

结论

对于神经网络来说,没有所谓的“最重要”组件,然而,激活函数为第一个获得该头衔提供了有力的论据。在本文中,我们了解到,没有任何非线性激活函数的前馈神经网络(无论是包含递归层、卷积层还是池层)都只是线性模型。我们通过数学符号、实验和大量的可视化展示了这一事实。

参考

[1] I .古德费勒,y .本吉奥和 a .库维尔,深度学习 (2016),https://www.deeplearningbook.org/

[2] 杰蒙德松,罗杰魏斯泰因,埃里克 W. “异或”来自 数学世界——一个 Wolfram 网络资源。https://mathworld.wolfram.com/XOR.html

为什么非营利组织应该关注合成数据

原文:https://towardsdatascience.com/why-nonprofits-should-care-about-synthetic-data-ab1d327908dc?source=collection_archive---------15-----------------------

合成数据如何帮助非营利组织改善其业务运营及其对服务对象的影响

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

版权所有 2021 Gretel.ai

TL;速度三角形定位法(dead reckoning)

我是 Gretel 公司的机器学习研究员,这是一家为开发者开发隐私工程工具的公司。11 月,我参加了一个小组,讨论为什么合成数据对非营利组织很重要,以及他们如何使用它。用例是无止境的,跨越医疗保健、教育、经济发展等行业。很多创新取决于正在成熟的技术创新以及这些创新如何解决非营利组织的各种痛点。非常感谢 DataKind 邀请 Gretel 在 NetHope 峰会上与 Medic 谈论这些问题。

介绍

合成数据被认为是最重要、最激动人心的新兴技术创新之一。它将使营利性公司能够共享数据,特别是在使用有差异的私人合成数据时,因为它消除了隐私相关许可问题的摩擦,并允许在预生产管道中进行更快速的技术开发。此外,合成数据可用于支持太小或数据集严重失衡的数据集。这将帮助组织建立更复杂的机器学习能力,这些能力通常非常渴求数据。然而,这些好处不仅有助于营利性部门,也能极大地影响公共部门。

我很高兴受到 DataKind 的邀请,在 NetHope 峰会上与 Medic 一起在一个关于合成数据的小组上发言。这是一个完美的机会来展示合成数据的力量,以及为什么非营利组织也开始思考它是重要的。营利性组织经历的每一个痛点都会被非营利性组织放大。以下是三个主要挑战以及合成数据如何应对这些挑战:

(1)保护数据隐私

许多非营利组织和非政府组织与弱势群体打交道,在这些群体中,隐私风险更高。这些人口面临着技术滥用,如监控系统累犯算法政府福利系统。非营利组织明白,这种滥用可能发生在他们服务的人群身上,因此必须对他们收集的任何数据加以保护。

有区别的私人合成数据是非营利组织可以减轻这种风险的一种方式,释放了一些以前被认为风险太大的创新和实践,例如合作打击人口贩运(在我们的小组讨论中,一名观众分享了一个用例!).尽管这不一定能防止模型开发中数据的不完美使用,但它确实能保护弱势群体的信息不被泄露和用于其他邪恶目的。

(2)收集和利用有限的数据集

但是,即使我们能够共享数据来改进分析、洞察和模型构建,公共部门也不从事收集数据的工作。致力于加强公民社区纽带的研究团体公民社会法律家庭委员会(Law Family Commission on Civil Society)于 2021 年 10 月发布了一份报告,描述了公共部门如何因糟糕的数据做法而落后于私营部门,例如使用 pdf 等“不可读格式”来存储数据。

收集数据既费钱又辛苦,做对更是难上加难。定义收集的信息的粒度、节奏和类型本身就是一项全职工作。很少有非营利组织有预算或员工带宽来致力于强大的内部数据收集和管理系统。不可避免的是,更接近非营利组织核心使命的其他活动几乎总是优先于这些困难的任务,尤其是当投资回报难以计算的时候。

这就是合成数据大放异彩的地方。如果一个非营利组织已经收集了足够的数据(数量未知,但少于一次完整的数据收集),那么他们可能能够训练一个合成模型来增加一个相对较小的样本。因为如果有足够的真实数据来源,那么即使只有一点点也可以转化为无限量的合成数据!随着数据集的扩大,非营利组织对其战略计划和每个计划的绩效有了更全面的了解,他们可以做出更明智的选择,将稀缺资源分配到哪里,从而最大限度地提高效益。

我在会上讨论的一个真实世界的例子是与 Microcred 合作建立的模型 DataKind。这种模式本可以帮助 Microcred 在贷款方面做出更好的决策,因此它变得更加高效和包容。然而,Microcred 只收集获得贷款的人的数据。因此,该模型只能用于那些获得贷款的人,而不能用于那些被拒绝的人。这限制了该模式的效力和影响。收集这些被拒贷款的数据需要几个月甚至几年时间。但如果 Microcred 在未来利用合成数据,他们将能够在更短的时间跨度内收集数据,并在更好的隐私保证下构建其数据集的其余部分。

(3)共享数据

隐私保护数据带来的最大好处之一是能够安全地共享数据集。将孤立的私人信息转化为团队可以合作的匿名工件可以引发新的讨论和发现,从而为所服务的弱势群体带来更好的结果。

英国的一些公务员已经开始倡导使用合成数据来改善政府对数据的使用。例如,在最近由几个公共机构主办的公务员竞赛期间提出的 200 多个想法中,合成数据被评为最佳之一,作为一种工具,它可以在公共部门中用于,除其他外,“通过工作和养老金部、英国税务海关总署以及英国签证和移民局之间更丰富的数据交换,提高对福利和税务欺诈的检测。”通过赋予公共部门团体与数据合作的权力,可以发现新的见解,弥合差距,并为所服务的人群建立更好的系统。

结论

非营利部门对任何健康社会的运作都至关重要。它有助于确保贫困的弱势群体得到照顾,并改善全世界数百万人的生活质量。为了继续向个人提供这些基本服务,并在更大范围内成为一股向善的力量,非营利组织必须有效地利用数据。通过使用像格雷特这样的合成数据工具,他们可以打破隐私瓶颈,开启以前似乎难以置信的创新。

现在的关键是确保各地的非营利组织都知道这些高效、廉价(在某些情况下甚至免费)的工具已经可以为他们所用。我希望你能和我一起传播这个好消息!

你可以免费开始合成数据。

为什么不使用 Thompson 采样进行最佳 Arm 识别。

原文:https://towardsdatascience.com/why-not-to-use-thompson-sampling-for-best-arm-identification-8ed458428126?source=collection_archive---------27-----------------------

思想和理论

如何使用多臂 bandit 分配方法在最少次数的试验中找到最佳臂?

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

内森·杜姆劳Unsplash 上拍摄的照片

在本帖中,我们展示了当目标是识别最佳手臂时,为什么不应该使用汤普森采样。特别是,我们将比较 Thompson 抽样和最近引入的名为 Top-two Thompson 抽样的分配方法,并展示它们的使用案例。在我们的实验中,前两名汤普森需要少 35%的试验来确定最佳手臂。Thompson 抽样是近年来越来越流行的多臂土匪问题中的一种分配方法。多臂 bandit 方法以一种平衡的方式顺序做出决策,探索可能提高未来性能的新信息,并利用已知信息最大化性能。这通常被称为勘探开发权衡。在多武器强盗问题中,我们的目标是最小化累积遗憾,这是最优武器的平均奖励和所玩武器的奖励之间的差异。最常用的方法之一是汤普森抽样(有时也称为贝叶斯土匪)。Thompson sampling 从获得的奖励中构建一个概率模型,并从中抽取样本来选择一只手臂进行游戏。Thompson 抽样在工业中被广泛使用,因为就最小化累积遗憾而言,它是分配臂的最佳方法之一[1]。

从业者有时使用多臂土匪的方法来确定最好的手臂。在这种情况下,Thompson 采样在有限的时间范围内运行(即勘探阶段),并从那时开始发挥最佳作用(即开采阶段)。开发阶段的这种性能保证被称为简单后悔。简单的遗憾可以解释为在探索阶段结束后一定要打出最好的手臂。Russo 最近的一篇文章[2]表明,Thompson 抽样是一种远非最佳的分配方法,无法决定开采期的最佳策略。在这篇博客中,我们讨论了 Top-two Thompson 采样,并提供了一个 Python 代码示例来复制和比较最佳 arm 识别情况下的方法。

前两名汤普森抽样。

Thompson 抽样是多臂土匪问题的一种流行的分配方法。这个博客主要关注伯努利分布案例。在伯努利分布中,奖励只能有两种可能的结果,1 和 0。更多关于汤普森取样的信息,请阅读这篇精彩的文章。

当奖励具有伯努利分布时,Thompson sampling 从贝塔分布中取样,并播放具有最高返回值的手臂。在实验开始时,所有的分布都很宽,并且在所玩的武器之间存在相对均匀的分配。随着实验中试验次数的增加,概率分布变得更窄,汤普森抽样将更频繁地使用更高概率的奖励。因此,勘探减少,开采增加。在识别最佳臂的情况下,这种行为远非最佳。

Top-two Thompson 采样是对标准 Thompson 采样的简单修改,增加了一个重采样步骤[2]。与 Thompson 抽样相似,在每个试验中,从所有的组中提取一个样本。与 Thompson 采样相反,不是使用具有最高样本奖励的手臂,而是在最高和第二高返回值之间抛硬币。这种抛硬币的方式可以防止只玩样本奖励最高的牌。这导致更多地探索第二个表现最好的武器,而不是发挥最好的武器。硬币翻转的量可以通过超参数β来改变,但通常是。这意味着最好的和第二好的手臂被打的概率相等。

汤普森抽样实现。

我们将首先创建一个名为 ThompsonSampling 的类,在 ThompsonSampling 中的参数标准(如成功次数( a )和失败次数( b )旁边,我们添加了参数 top_arms 。该参数允许在标准 Thompson 抽样和 Top-two Thompson 抽样之间变化。

import numpy as np
import pandas as pd
from datetime import datetimeclass ThompsonSampling():
    """Class to implement a Thompson sampling policy 
    for a multi-armed bandit problem.

    Args:
        a (list): The alpha parameter of a Beta 
        distribution. For multiple arms, this will be a list of
        float values.
        b(list): The beta parameter of a Beta 
        distribution. For multiple arms, this will be a list of
        float values.
        top (int): Either 1 to use a standard Thompson sampling
        or 2 to use Top-two Thompson.
    """

    def __init__(self, a, b, top_arms=1):
        self.top_arms = top_arms

        # Beta parameters
        self.a = a
        self.b = b
        return

    def initialise(self, num_arms):
        """Initialises the arms.

        Args:
            num_arms (positive int): The number of arms.
        """
        self.num_arms = num_arms

        # Use Uniform distribution as prior for all the arms
        self.a = [1 for arm in range(self.num_arms)]
        self.b = [1 for arm in range(self.num_arms)]
        return

    def select_arm(self, random_seed):
        """Selects an arm for each round.

        Args:
            random_seed (int): The seed for random number generator.

        Returns:
            An integer corresponding to the index of the selected 
            arm.
        """
        # Select each arm at least once
        arms = []
        for i in range(self.num_arms):
            if self.a[i] == self.b[i] == 1:
                arms.append(i)
        if arms:
            np.random.seed(seed=random_seed)
            return np.random.choice(arms)

        # Perform random draw for all arms based on their parameters
        np.random.seed(seed=random_seed)
        all_draws = np.random.beta(self.a, self.b, 
                                   size=(1, self.num_arms))
        all_draws = np.concatenate(all_draws, axis=0)

        # Return index of arm with the highest reward for Thompson
        # Return index of any top-two arm for top-two Thompson 
        np.random.seed(random_seed)
        return np.random.choice(all_draws.argsort()[::-1]
                                [:self.top_arms])

    def update(self, chosen_arm, reward):
        """Updates the parameters of the chosen arm.

        Args:
            chosen_arm (int): The index of the selected arm. 
            reward (int): The reward obtained. Either 0 or 1.
        """
        # a is based on total counts of successes of an arm
        self.a[chosen_arm] = self.a[chosen_arm] + reward

        # b is based on total counts of failures of an arm
        self.b[chosen_arm] = self.b[chosen_arm] + (1 - reward)

        return

为了比较,我们还创建了类 *BalancedPolicy。*这个职业完全随机选择一只手臂。我们用这个类来比较 Thompson 和前两名 Thompson 的均衡分配。平衡分配与传统 A/B 测试一样,随机分配一个臂。该类需要成功次数( a )和失败次数( b )来更新 arm,以便我们可以执行最佳 arm 识别。

class BalancedPolicy():
    """Class to implement a Balanced policy 
    for a multi-armed bandit problem.
    It selects an arm completely at random.

    Args:
        a (list): The alpha parameter of a Beta 
        distribution. For multiple arms, this will be a list of
        float values.
        b(list): The beta parameter of a Beta 
        distribution. For multiple arms, this will be a list of
        float values.
    """

    def __init__(self, a, b):
        self.arms = []

        # Beta parameters
        self.a = a
        self.b = b
        return

    def initialise(self, num_arms):
        """Initialises the arms.

        Args:
            num_arms (positive int): The number of arms.
        """
        self.arms = [arm for arm in range(num_arms)]
        self.num_arms = num_arms # Use Uniform distribution as prior for all the arms
        self.a = [1 for arm in range(self.num_arms)]
        self.b = [1 for arm in range(self.num_arms)]
        return

    def select_arm(self, random_seed):
        """Selects an arm for each round.

        Args:
            random_seed (int): The seed for random number generator.

        Returns:
            An integer corresponding to the index of the selected 
            arm.
        """
        # Select each arm at least once
        arms = []
        for i in range(self.num_arms):
            if self.a[i] == self.b[i] == 1:
                arms.append(i)
        if arms:
            np.random.seed(seed=random_seed)
            return np.random.choice(arms)

        # Perform random selection of arms
        np.random.seed(seed=random_seed)
        return np.random.choice(self.arms)

    def update(self, chosen_arm, reward):
        """Updates the parameters of the chosen arm.

        Args:
            chosen_arm (int): The index of the selected arm. 
            reward (int): The reward obtained. Either 0 or 1.
        """
        # a is based on total counts of successes of an arm
        self.a[chosen_arm] = self.a[chosen_arm] + reward

        # b is based on total counts of failures of an arm
        self.b[chosen_arm] = self.b[chosen_arm] + (1 - reward)

        return

为了模拟使用每种分配方法选择手臂的结果(奖励),我们实现了一个 BernoulliArm 类,其中奖励只能有两种可能的结果,1 和 0,这取决于每只手臂的预期奖励。

class BernoulliArm():
    """Class to simulate a Bernoulli arm.

    Args:
        p (float): The probability of success.
    """
    def __init__(self, p):
        self.p = p

    def get_reward(self, random_seed):
        """Obtains a reward based on Bernoulli.

        Args:
            random_seed (int): The seed for random number generator.

        Returns:
            1 for success, 0 otherwise.
        """
        np.random.seed(seed=random_seed)
        if np.random.random() > self.p:
            return 0.0
        else:
            return 1.0

由于目标是识别最佳手臂,我们需要计算找到最佳手臂的概率。在这样做的时候,我们利用了一个模拟,其中我们从带有参数的 beta 分布中抽取成功次数( a )和失败次数( b ) N 次。

def calculate_bayesian_probability(num_arms, N, random_seed, a, b):
    """
     Calculated the bayesian probabilities by performing 
     sampling N trials according to the provided inputs.

    Args:
        num_arms (int): The number of variations to sample from.
        N: The number of sampling trials.
        random_seed: The seed for random number generator.
        a (list): The alpha parameter of a Beta 
        distribution. For multiple arms, this will be a list of
        float values.
        b(list): The beta parameter of a Beta 
        distribution. For multiple arms, this will be a list of
        float values.

    Returns:
        Ordered list of floating values indicating the success 
        rate of each arm in the sampling procedure.
        Success rate is the number of times that the sampling 
        returned the maximum value divided by the total number 
        of trials.
    """
    np.random.seed(seed=random_seed)
    sim = np.random.beta(a, b, size=(N, num_arms))
    sim_counts = sim.argmax(axis=1)
    unique_elements, counts_elements = np.unique(sim_counts, 
                                                 return_counts=True)
    unique_elements = list(unique_elements)
    counts_elements = list(counts_elements) for arm in range(num_arms):
        if arm not in unique_elements:
            counts_elements.insert(arm, 0) return counts_elements / sum(counts_elements)

为了将前两个 Thompson 采样与标准 Thompson 采样和平衡策略进行比较,我们进行了模拟。在这些模拟中,我们对每个策略进行分配 num_sims 次,以消除随机性。在仿真中,我们计算了(1)识别最佳 arm 的贝叶斯概率,以比较最佳 arm 识别的分配方法。(2)累积遗憾:打出的手臂和打出最好的手臂之间的奖励差异。(3)选择最佳手臂的比率,因此所有分配方法使用定义为最佳(即成功概率最高)的手臂的频率。

def simulate(policy, arms, best_arm, num_sims, trials, N):
    """Simulates a multi-armed bandit process.

    Args:
        policy: The policy class.
        arms (list): A list of arm classes. 
        The leght of the list equals the number of arms.
        best_arm (int): The index of arm with the highest reward.
        num_sims (int): The number os simulations.
        trials (int): The numbe of trials in each simulation.
        N: The number of sampling trials to calculate the 
        bayesian probabilities.
        balanced (bool): If True, a uniform distribution is used 
        to calculate the bayesian probabilites, if False, then a 
        beta distribution.

    Returns:
        A dataframe with information such as the select arm, 
        reward and regret per simulation per trial.
    """
    # Initialise a dataframe to store the results of the simulations
    columns = ['num_sims', 
               'trials', 
               'chosen_arms', 
               'rewards', 
               'rewards_best_arm', 
               'prob_best_arm']
    for a in range (len(arms)):
        columns.append('prob_arm_{}'.format(a))
    for a in range (len(arms)):
        columns.append('alpha_arm_{}'.format(a))
    for a in range (len(arms)):
        columns.append('beta_arm_{}'.format(a))
    results = pd.DataFrame(index=range(0,num_sims*trials),
                           columns=columns, dtype='float') for sim in range(num_sims):
        sim = sim + 1
        policy.initialise(len(arms))        
        for t in range(trials):
            t = t + 1
            index = (sim - 1) * trials + (t - 1)
            # Selection of best arm
            chosen_arm = policy.select_arm(random_seed=index)
            # Obtain reward information from the chosen arm
            reward = arms[chosen_arm].get_reward(random_seed=index)
            bayesian_probabilities = \
                calculate_bayesian_probability(num_arms=len(arms),
                                               N=N,
                                               random_seed=index,
                                               a=policy.a,
                                               b=policy.b)
            # Obtain reward information from the best arm 
            # to calculate regret later
            reward_best_arm = \
                arms[best_arm].get_reward(random_seed=index)
            results.loc[index] = \
                [*[sim, t, chosen_arm, reward, reward_best_arm, 
                   bayesian_probabilities[best_arm]],
                 *bayesian_probabilities, *policy.a, *policy.b]
            policy.update(chosen_arm, reward) # Calculate the cumulative reward
    results['cumulative_rewards'] = \
        results.groupby('num_sims')['rewards'].cumsum()
    results['cumulative_rewards_best_arm'] = \
        results.groupby('num_sims')['rewards_best_arm'].cumsum()

    # Calculate the average reward
    results['average_rewards'] = \
        (results['cumulative_rewards'] / results['trials'])

    # Calculate the regret
    results['regrets'] = \
        results['rewards_best_arm'] - results['rewards']
    results['cumulative_regrets'] = \
        results['cumulative_rewards_best_arm'] - \
        results['cumulative_rewards'] # Calculate the rate of choosing the best arm
    results['is_best_arm'] = \
        (results['chosen_arms'] == best_arm).astype(int)
    results['is_best_arm_count'] = \
        results.groupby('num_sims')['is_best_arm'].cumsum()
    results['rate_of_choosing_best_arm'] = \
        (results['is_best_arm_count'] / results['trials'])

    return results

为了展示 Thompson 与 Top-two Thompson 采样的不同用例,我们创建了一个具有五个分支的模拟,每个分支的预期回报为*【0.1,0.2,0.3,0.4,0.5】。我们做出 1500 个分配决策(即试验*)并运行模拟 500 次以创建稳健的结果(即 num_sims )。

在这个模拟中,arm 4 是最好的 arm。均衡策略随机分配臂,因此最佳臂的分配率约为 20%。假定超参数β设置为,前两个 Thompson 采样将接近 50%的最佳臂选择率。最后,Thompson 抽样将逐渐提高在接近 100%的试验次数中选择最佳臂的比率。

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

在最佳 arm 识别方面,Top-Two Thompson 在识别最佳 arm 方面优于其他分配方法。例如,在 200 次试验后,识别最佳手臂的贝叶斯概率约为 77%。相比之下,汤普森抽样有 73%的概率识别最佳手臂。就最佳武器识别而言,武器的均衡分配低于汤普森和排名前两位的汤普森抽样。为了达到识别最佳手臂的 95%贝叶斯概率,前两名汤普森平均需要 689 次试验,而汤普森平均需要 1073 次试验。在 1500 次试验后,汤普森和平衡分配都有 96%的概率识别最佳臂,而前两个汤普森在识别最佳臂时达到 99.6%的贝叶斯概率。

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

对贝叶斯概率的深入研究解释了为什么汤普森采样在最佳臂识别上表现不佳。例如,在 100 次尝试后,Thompson 对第 4 手牌的概率密度相对较高,但对第 1-3 手牌的概率密度相对较低,因为他不经常使用这些手牌。换句话说,Thompson sampling 播放 1-3 号手臂的频率不足以区分 4 号手臂。相比之下,平衡策略对于 arm 0 具有相对较高的概率密度,尽管这对于最佳 arm 识别来说是不必要的,因为 arm 0 和 arm 4 之间的概率分布已经彼此可区分。

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

在累积后悔方面,汤普森抽样的累积后悔最低。累积遗憾是在所有回合中使用的武器和使用最佳武器之间的奖励差异。正如预期的那样,Thompson 采样优于排名前两位的 Thompson 采样,因为排名前两位的采样选择最佳臂的频率较低。武器的平衡分配导致最高的累积遗憾,因为随着时间的推移,它不会开始玩性能最差的武器。

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

何时使用哪种策略?

在这篇博客中,我们证明了在最佳 arm 识别中,Top-two Thompson 采样优于 Thompson 采样和平衡分配。因此,在寻找最佳臂的情况下,数据科学家应该使用像 Top-two Thompson 采样这样的方法。这样做时,数据科学家应该监控最佳 arm 的贝叶斯概率,并将其用作自适应停止规则,以最小化勘探阶段的成本。如果业务涉众不打算停止实验(即连续测试),则应使用 Thompson 抽样,因为它会导致更低的累积遗憾。本博客提供了 Python 示例代码来实现和比较这两种方法,以便数据科学家可以向他们的业务利益相关者演示这些分配方法的用例。通过使用面向对象的方法,读者能够很容易地为他们在日常工作中遇到的用例修改代码。

参考文献。

[1] Russo,d .,Van Roy,b .,Kazerouni,a .,Osband,I .和 Wen,z .(2017 年)。汤普森采样教程。arXiv 预印本 arXiv:1707.02038。

[2] Russo,d .,“最佳武器识别的简单贝叶斯算法”运筹学 68,6(2020):1625–1647。

以正确的方式轻松提升您基于数字的分析

原文:https://towardsdatascience.com/why-numba-sometime-way-slower-than-numpy-15d077390287?source=collection_archive---------5-----------------------

理解并使用 Numba——Numpy 的掺杂版本

我最近遇到了[Numba](https://numba.pydata.org/),这是一个针对 python 的开源实时(JIT)编译器,可以将 python 和Numpy函数的子集翻译成优化的机器代码。原则上,带有低级虚拟机(LLVM)编译的 JIT 会使 python 代码更快,如 numba 官方网站所示。当我尝试我的例子时,起初看起来并不那么明显。

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

函数的 Numba 版本比 Numpy 版本长得多,为什么

如图所示,我得到的**N**umba运行时间比 **Numpy**长 600 倍**!我可能做错了什么?**

在进行详细的诊断之前,让我们后退一步,回顾一些核心概念,以便更好地理解Numba是如何工作的,并希望能更好地使用它。如果您熟悉这些概念,请直接进入诊断部分。

Python,字节码和 PVM?

Python 作为一种高级编程语言,需要被翻译成本机语言,以便硬件(例如 CPU)能够理解并执行这些指令。

对于像 C 或 Haskell 这样的语言,翻译是直接从人类可读语言到本地二进制可执行指令。这是在代码执行之前完成的,因此通常被称为提前(AOT)。其他语言,如 JavaScript,在运行时被一条一条地翻译。

预编译代码的运行速度比解释后的代码快几个数量级,但是需要权衡平台特定性(特定于编译代码的硬件)和预编译的义务,因此是非交互式的。

Python,像 Java 一样,使用这两种翻译策略的混合:高级代码被编译成一种中间语言,称为Bytecode,它是进程虚拟机可以理解的,它包含所有必要的例程来将Bytecode转换成 CPU 可以理解的指令。在 Python 中,进程虚拟机被称为Python virtual Machine (PVM)

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

不同实现中的 Python 编译—图片由作者提供

与纯解释语言相比,这种策略有助于 Python 的可移植性和更快的速度。然而,由于解释高度复杂的CPython Bytecode需要时间,所以PVM上的运行时间Bytecode与本机代码的运行时间相比仍然很慢。出于这个原因,新的 python 实现通过优化Bytecode来提高运行速度,以直接在Java virtual Machine (JVM)上运行,就像对于Jython一样,或者甚至在[Pypy](https://www.pypy.org/)中使用JIT编译器更有效。JIT-compiler基于低级虚拟机(LLVM)是Numba背后的主要引擎,这通常会使其比Numpy功能更有效。

那么 Python 中的 JIT 是什么呢?

实时(JIT)编译器是运行时解释器的一个特性。而不是像在CPython解释器中那样,每次调用一个方法就解释字节码。JIT 将分析代码以找到将被多次执行的hot-spot,例如循环中的指令,并将该部分编译成本机语言。这允许在需要时动态编译代码;与bytecode解释相比,减少编译整个代码的开销,同时显著提高速度,因为常用指令现在是底层机器的本地指令。JIT 编译器还提供了其他优化,比如更有效的垃圾收集。

Numba 如何工作?

简单地说,一个 python 函数可以简单地通过使用装饰器"@jit"转换成Numba函数。当编译这个函数时,Numba会查看它的Bytecode来找到操作符,同时也拆箱函数的参数来找出变量的类型。这两个信息帮助Numba知道代码需要哪些操作数以及它将修改哪些数据类型。然后沿着分析管道向下,创建函数的中间代表(IR)。之后,它在后端将此处理给后端低级虚拟机LLVM,以进行低级优化并使用JIT生成机器码。一旦生成了机器码,它就可以被缓存并执行。缓存允许我们下次需要运行相同的函数时跳过重新编译。如需更多详细信息,请查看此技术说明。

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

Numba 的工作模式——作者提供的图片——改编自 Stan Seibert (Numba 的合著者)

对 Numba 明显迟钝的诊断

  1. 研究案例的设定

有了所有这些先决知识,我们现在准备诊断我们的Numba代码的缓慢性能。

首先让我们安装Numba : pip install numba

我们的测试功能如下。

def calc_numpy(x, y, n):
    res = np.zeros(len(x))
    for i in range(n):
        for j in range(n):
            res += np.add(i*x, j*y)
    return res

**@jit(nopython=True, cache=True)**
def calc_numba(x, y, n):
    res = np.zeros(len(x))
    for i in range(n):
        for j in range(n):
            res += np.add(i*x, j*y)
    return res

正如你可能注意到的,在这个测试函数中,有两个循环被引入,因为Numba文件表明loop是其中一种情况,这时JIT的好处将会很明显。除了装饰器"@jit"之外,calc_numbacalc_numpy几乎相同。我们将使用大小为nobsn的循环来检查每个函数在模拟数据上的运行时间。

args = parse_args()
nobs = args.nobs
n = args.n
x = np.random.randn(nobs)
y = np.random.randn(nobs)res_numpy = calc_numpy(x, y, n)
res_numba = calc_numba(x, y, n)

这产生了

check res_numpy == res_numba: True
run time Numpy / Numba [ms]: 1.34 / 839.37
  1. Numba 开销

很明显,在这种情况下,Numba版本比Numpy版本长得多。由于代码完全相同,唯一的解释就是NumbaJIT编译底层函数时增加了开销。如果是这样的话,如果我们再次调用Numba函数(在同一个会话中),我们应该会看到改进。

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

Numba 函数在编译后速度更快——Numpy 运行时不是不变的

如图,第一次调用后,Numba版本的函数比Numpy版本快。同时,如果我们再次调用Numpy版本,它需要相似的运行时间。这很好的展示了Numba中编译的效果。

问题是:我们想用Numba来加速我们的计算,然而,如果编译时间那么长,那么运行一个函数的总时间会不会比 cannonical Numpy函数的时间太长了?

Numba 哪里可以发光?

1。交互式 Jupyter 笔记本

作为构建您的 Jupiter 笔记本的一种常见方式,一些函数可以在顶部单元格上定义和编译。然后,这些函数可以在后面的单元格中多次使用。在这种情况下,编译时间的损失可以通过以后使用时的时间增益来补偿。

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

作者在 Jupyter 笔记本中重用快速编译的数字函数

2.缓存功能

现在,如果您没有使用交互式方法,如Jupyter Notebook,而是在editor中运行Python或直接从terminal运行。我们如何从一个函数的编译版本中获益?事实上,这是装饰器jit中的选项cached的直接结果。

@jit(nopython=True, **cache=True**)
def calc_numba(x, y, n):
    res = np.zeros(len(x))
    for i in range(n):
        for j in range(n):
            res += np.add(i*x, j*y)
    return res

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

Numba 中的缓存选项允许避免重新编译

如图所示,当我们第二次重新运行相同的脚本时,测试函数的第一次运行所用的时间比第一次少得多。这是因为它利用了缓存的版本。还要注意,即使使用了缓存,函数的第一次调用仍然比随后的调用花费更多的时间,这是因为检查和加载缓存函数的时间。

事实上,如果我们现在签入 python 脚本的同一个文件夹,我们会看到一个包含缓存函数的__pycache__文件夹。

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

当使用’ cache '选项时,编译的函数将被缓存到 pycache

3.循环次数

你可能会注意到,在上面讨论的例子中,我故意改变了循环数n。实际上,NumbaNumpy版本之间运行时间的增加取决于循环的数量。让我们试着比较一下测试函数中大量循环的运行时间。

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

Numba 在高循环数时表现出色

更普遍的是,在我们的函数中,循环的次数非常多,编译一个内部函数的成本,比如 np。add(x, y)将在很大程度上由每次循环迭代重新解释bytecode的时间增益来重新补偿。

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

在高循环数(nobs=1000)下,“Numba”运行时间低于“numpy ”-图片由作者提供

4.大数据

与循环次数类似,您可能也会注意到数据大小的影响,在本例中是由nobs调制的。我们可以测试将输入向量的大小从x, y增加到100000

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

Numba 也因大量输入数据而大放异彩

对于较大的输入数据,Numba版本的函数必须比Numpy版本快,即使考虑到编译时间。

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

对于大输入(nloop=100),运行时间“Numba”低于“Numpy 图片由作者提供

事实上,NumpyNumba运行时间的比率将取决于数据大小和循环次数,或者更一般的函数性质(要编译)。下面是这两个参数的Numpy/Numba运行时比率的一个例子。

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

比率 Numpy/Numba 运行时间与循环次数和输入数据大小的函数关系—图片由作者提供

最终注释

我发现Numba是优化计算时间的一个很好的解决方案,使用jit decorator 对代码的改动很小。包中还有更多令人兴奋的东西有待发现:并行化、矢量化、GPU 加速等,这些超出了本文的范围。好奇的读者可以从 Numba 网站找到更多有用的信息。

通过这个简单的模拟问题,我希望讨论一些我觉得有趣的NumbaJIT-compiler背后的工作原理,希望这些信息对其他人有用。像往常一样,如果你有任何意见和建议,请不要犹豫让我知道。

参考

[1] 编译语言 vs 解释语言
【2】JIT vs 非 JIT 的比较
【3】Numba 架构
【4】pypypy 字节码

为什么开源软件击败了 MLOps 的专有软件

原文:https://towardsdatascience.com/why-open-source-beats-proprietary-software-for-mlops-b30e52f70f5b?source=collection_archive---------34-----------------------

为了灵活性和控制力,拥有自己的 ML 管道是很重要的

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

来源:作者

机器学习团队可以使用 Knime 或 SageMaker 等专有平台,或者使用开源工具构建自己的平台。公司通常将专有平台标榜为更强大、更高效、更易于使用。但实际上,它们通常比开源替代方案更复杂,功能更弱。

我们从纯粹的开源基础上构建自己的 MLOps 架构。这就是为什么你的平台的所有权是重要的。

开源质量更高

人们有时会怀疑免费工具,但是开源软件通常比付费软件质量更高。像谷歌和微软这样的大公司严重依赖开源软件,并经常让他们最好的工程师从事这些项目。

开源项目也受益于比闭源项目更多的关注。如果开发人员发现了一个 bug,他们可以贡献一个对所有人都有益的补丁。

最后,开源软件通常不上市,这意味着激励更好,因为质量是决定成功的关键因素。相比之下,商业项目的成功更多地取决于营销、合作和品牌。这意味着公司经常被激励在这些领域花费比工程更多的时间和精力。

因此,当谈到开源软件时,“你得到你所支付的”是一个真正的用词不当。

开源带来了可转移的技能,这使得招聘变得更加容易

工程师们想要学习开源工具,因为他们也可以在其他公司使用这些知识。没有人希望被困在目前的工作中,因为他们花了十年时间学习一些内部平台的细节。

培训你的团队使用对其他公司有价值的工具,比如 TensorFlow 和 Kubernetes,可能会让一些人紧张,但这确实是吸引顶级工程人才的唯一可持续方式。

你的团队也可以通过其他方式受益于这些可转移的技能:如果你和其他人使用相同的工具,找到专家顾问甚至简单的社区来源的帮助要容易得多。

开源解决方案更加模块化

“包罗万象”是企业平台试图脱颖而出的一个关键方式。他们不是只构建一个培训平台,或只构建一个部署工具,而是将自己推销为“一体化”解决方案或“您的团队将需要的最后一个工具”。

但是事事都做到最好是不现实的。这些解决方案的整体性使得更换单个组件变得更加困难。如果您的团队想要使用最好的模型注册中心,通常他们不能将它插入到他们现有的平台中。

相比之下,开源软件通常更加精细,并且非常注重与其他平台的集成。这意味着开源解决方案更像是在玩乐高:如果它的一部分给你带来了麻烦,你可以简单地把它拆下来换一个。

专有平台存在隐性成本

专有平台被鼓励不断向现有客户出售升级和新功能。在许多情况下,这意味着他们不坦率地承认自己的局限性。

在销售过程中,他们可能会让你相信一个低级或中级的计划非常适合你的需求。只有在购买之后,你才意识到他们已经战略性地删除了关键功能,或者添加了旨在削弱你工作流程的特定限制,直到你为下一次升级付费。

这些平台还可以在几乎没有通知的情况下提高价格,所以你的团队要么匆忙重写一切,要么支付比你预算更多的费用。

什么时候使用专有平台有意义?

如果您的团队没有太多的工程专业知识,特别是在开发运维以及创建和管理基础设施方面,那么设置和维护开源解决方案可能会很有挑战性。

开源工具往往是“由开发人员为开发人员”构建的,因此在某些情况下,像营销这样的非技术团队也可能更喜欢专有平台。

最后,如果您正在处理小型内部项目或概念验证应用程序,通常很少需要基础架构。如果人们不把你的解决方案作为产品来使用,一个现成的工具,比如快速可视化,通常就足够了。

您的团队在采用开源 MLOps 时需要帮助吗?

我们是一家机器学习机构,喜欢帮助研究团队建立开源 MLOps 基础设施。如果您想讨论 MLOps 工具,请随时联系我们

为什么运筹学很棒——简介

原文:https://towardsdatascience.com/why-operations-research-is-awesome-an-introduction-7a0b9e62b405?source=collection_archive---------1-----------------------

数学是宇宙的语言,根据定义,它是逻辑的。但是做数学不仅仅是逻辑——它是一个利用数学给我们的工具的高度创造性的过程。在运筹学中,你可以用数学工具创造性地解决一些令人兴奋的问题!

运筹学(OR)是一个应用数学领域,其中数学工具和运算符不是用于进一步研究数学,而是通过设计创新的解决方法来分析和解决 OR 领域内的问题。

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

图一。美国宇航局在 Unsplash 拍摄的照片

理解运筹学的动机

未来的决策将尽可能接近完全自动化(想想“托尼·斯塔克”级别的自动化)。研究和促进这种转变的一个研究领域是 OR。其核心是一个应用数学领域,将高级分析方法集成到决策支持/决策中。

随着问题和决策环境变得越来越复杂,推进强调人机界面的研究以避免误解是至关重要的。未来的一个经典恐怖例子是,如果决策者寻求最大化客户幸福,那么(人工智能)系统会将这一点转化为将每个人置于类似于“黑客帝国”中的多巴胺昏迷状态(我们可能已经进入,也可能没有进入)…).

但是,我们今天还面临着更多的实际问题。例如包裹递送的路线安排,其中路线的总距离应该最小化,同时仍然使递送的包裹的数量最大化。在极端情况下,这两个目标要么不让司机递送任何包裹,要么不让他们有任何空闲时间,但在这两者之间也有许多次优实例。这些问题只是冰山一角,杰克。因此,未来的决策者能够恰当地整合他们的偏好以避免这些情况是至关重要的——而运筹学恰恰研究了这一点!

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

图 2:无限长手套说明了或者(当然!),因为 OR 带来的工具包将会抹去未来问题的一半。照片由晨酿破浪

我还是研究生的时候偶然发现了数学和经济学,这两个方向都有可能研究;要么还是金融工程。相比较而言,后者处理金融、交易和风险/投资方面的决策,而运筹学更广泛地处理工业和商业领域的决策。虽然,一些术语将金融工程作为一个更专业的子类别放到了当时更广泛的 OR 领域。

什么是运筹学?

一般来说,或涉及获得一些现实世界目标函数的极值;最大值(利润、性能、效用或收益),最小值(损失、风险、距离或成本)。它结合了数学建模、优化和统计分析的技术,同时强调了人机界面。然而,回答这个问题的一个困难是,科学术语中有很多重叠——有时术语变得非常流行,影响了术语的前景。例如,人工智能和大数据等模糊而宽泛的术语的流行,这两个术语对营销都很有用,但对研究的讨论毫无帮助。因此,我试图用 ORs 相关的字段、子字段和图 3 中解决的问题来说明它。

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

图 3:运筹学相关学科和问题的整体说明。注意,我很大程度上受限于 2D 的表述,因为除了这里显示的,学科之间还有许多其他的联系。例如概率论和统计学是机器学习的固有部分。Alex El kjr Vasegaard 的插图。

运筹学起源于 17 世纪,当时博弈论方法和期望值被用来解决问题。现代版的 OR 起源于第二次世界大战期间,当时很明显,军方需要解决战争中出现的一些重要的后勤和供应链问题。

当时,它被定义为“一种为行政部门提供有关其控制下的业务决策的定量基础的科学方法”,并被创造为“运营分析”(仍在丹麦),或“定量管理”。

运筹学的未来?

OR 的一个吸引人的特点是知识、技能和工具在各个行业的适用性。如今,OR 在大多数企业和行业中以或多或少的专业化版本应用,从农业、能源交易、生产和销售到航天工业、资产定价、军事行动和需求预测,无所不包。最显著的用例可能是:

  • 供应链管理
  • 物流和库存管理
  • 路由和寻路问题
  • 预测性维护
  • 调度和分配问题
  • 评估问题(多标准决策)
  • 系统工程
  • 预测

工具的共同点是以下四项技能,使您能够:

  • 利用数学优化方法,如线性规划、动态规划、随机规划等。
  • 开发求解算法。通常需要近乎实时的解决方案。也就是说,最优解不是必须的。人们“只是”想要一个足够好的解决方案。对于具有高复杂性的大问题(例如,NP-Hard 问题),诸如专家启发的启发式算法或生物启发的遗传算法、蚁群优化、甚至神经网络或决策树启发的梯度推进方法的解决算法。这取决于问题的框架,以及它是基于模型还是基于数据的解决方法。
  • 进行广泛的模拟,以调查衍生解决方案的稳健性和灵活性。或者通过蒙特卡罗模拟、灵敏度分析等。
  • 对问题进行广泛的分析,例如确定网络中的关键路径。为了举例说明正确分析的重要性,在网络分析中,更具体地说,在交通网络中,已经观察到通过移除道路,可以增加交通流量。这是布赖斯悖论,它也被发现欺骗其他系统,如电网,生物学和团队运动策略。因此,正确分析自己的解决方案至关重要。

我希望这是非正式的,让你知道什么是运筹学——我的家人、朋友和其他研究领域的同事一直在问我这个问题,所以我希望这澄清了你的兴趣。

为什么组织需要数据驱动

原文:https://towardsdatascience.com/why-organizations-need-to-be-data-driven-98ade3ca53a?source=collection_archive---------6-----------------------

这个新职位面向不同领域、服务产品或垂直行业的企业家和大、中、小型企业主。通读之后,您将理解数据驱动意味着什么,以及为什么组织需要数据驱动。

介绍

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

作者图片

W 为什么数据是必要的?为什么组织应该寻求数据驱动?数据驱动的文化有什么好处?组织如何成为数据驱动型组织?这些以及更多的相关问题是我在会议、研讨会和知识分享活动中听到企业主、高管和员工提出的。

思考了上面提到的一些问题后,写作的灵感自然而然地来了,我决定用最好的方式来分享我的想法。如果您希望了解数据驱动意味着什么,以及为什么数据对每个企业都至关重要,那么您来对地方了。

我把这篇文章分成了两个独立的系列。在这第一个版本中,我将帮助您理解数据驱动的含义,以及为什么数据对每个组织都至关重要。随后,我将发表另一篇文章,讨论成为数据驱动的一些挑战,以及组织应该如何真正应对这些挑战。

关于“为什么组织需要被驱动”的整个出版物是企业主、企业家、公司企业以及任何想要了解数据对组织的重要性以及如何成为数据驱动的人的必读之作。

数据驱动到底是什么意思?

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

作者图片

术语“数据驱动”意味着一个实体倾向于根据数据而不是直觉、个人意见、一般观察或纯粹的希望来做出战术和战略决策。换句话说,数据驱动也意味着一个实体拥有做出决策所需的数据,从而产生出色的结果。

B ecoming 数据驱动不仅仅是安装合适的应用程序和工具、雇用专门的数据专业人员团队、承诺进行重大的数据基础设施投资或运行一次性数据扫盲计划— 它更多的是让数据和分析成为您的业务战略、组织文化、流程以及所有层级的基础部分。

数据驱动型组织不仅认识到收集原始数据的重要性,而且明白他们不应该仅仅使用原始数据来制定业务决策。相反,他们收集、分析并从数据中获得洞察力,以解决业务问题、发现新的增长机会并提高盈利能力。本质上,数据驱动型组织将数据用于多种用例,如分析客户调查反馈和人口统计数据、观察客户行为、购买模式等。这类企业已经建立了一种渗透到整个组织的数据文化,而不仅仅是在某些职能部门或管理层。

根据我作为一名数据科学家的经验,我相信每个组织都会产生数据,并且可以成为数据驱动的组织,无论他们的业务规模、领域和服务提供如何(,只要他们采用正确的策略并正确地做事)。如果你不相信你的组织正在产生数据,一个好的开始是检查和思考你的业务的每个方面,你的客户类型,他们在不同的社交媒体平台上对你的评论,等等。我打赌你最终会发现可能的数据源和有价值的信息,你可以开始提取,汇总和分析,以推动你的业务向前发展。

我相信你现在明白“数据驱动是什么意思了。如果您仍然不明白,请花一分钟时间再次阅读前面的段落,然后继续阅读下面的部分,您将了解为什么数据对企业至关重要,以及如果不使用您的企业每天产生(或可能产生)的数据,您会错过什么。

为什么数据对每个企业都很重要

数据是每个组织最有价值的资产之一。这是一座金矿,也是一种极具战略意义的无价资源,有可能改变世界,改善我们的生活方式,发展业务,并实现更便宜、更快、更好的业务流程。

与传统公司不同,数据驱动的企业不会线性增长,我认为谷歌和亚马逊这样的大公司总是保持指数增长的原因之一是因为他们的商业模式从根本上讲是围绕数据构建的:

在你被令人震惊的数字冲昏头脑之前,你需要始终记住的一件关键事情是,数据“就像未开发的黄金”在其原始形式下可能不会提供很多信息或立即有所帮助。为了充分利用您的数据,您需要收集适当的数据,并将其转换为可重用的形式。也就是说,以下是每个组织都应该开始有效使用其业务数据的一些重要原因。

了解客户行为,改善品牌客户体验

我们生活在一个产品和/或服务数不胜数的世界里,你的现有/潜在客户有几个选择来投资。此外,产品供应商之间的竞争从未如此紧张。

提高品牌认知度并与你的业务相关的一个非常战略性的方法是了解你的客户对你的评价以及他们对你的品牌的看法。但是,如果没有数据,即使知道谁是你的客户,他们是否喜欢你的产品和服务,或者你的营销策略/活动是否有效,也变得相当具有挑战性。相比之下,你可以通过开展客户调查、阅读关于你的品牌的社交媒体评论/在线评论来轻松实现所有这些

一旦从客户那里收集到数据,您就可以分析这些数据点,以了解他们的痛点、他们对您的业务的看法、他们希望您提供什么产品或服务、您的组织需要改进什么,以及更重要的是,他们选择您而不是竞争对手的意愿。最终,从客户反馈中产生的见解将有利于客户关怀、交叉销售和追加销售服务,和/或产品创新。在大多数情况下,我认为商业利润与数据驱动、以客户为中心的战略性业务流程和决策密切相关。

例如,etflix 收集并分析客户数据,以了解哪种电影和节目受欢迎。之后,该公司利用获得的见解购买类似的脚本,假设订户也会根据他们以前的偏好喜欢新的脚本。该公司使用这种数据驱动的战略,在 2020 年疫情高峰期将其商业价值增加了超过500 亿美元。亚马逊还利用浏览历史、客户购买和偏好等消费者数据来推动其产品推荐引擎。这种数据驱动的战略产生了大约 35%的公司收入

做出更好、更明智的业务决策

决策是每个企业的一个重要方面,通常涉及几个企业高管、股东和企业主无法承受的数百万美元损失。有了正确的数据供您支配,您的组织将不必根据直觉、最佳猜测、*错误假设、轶事判断、*或不确定的消耗做出重大业务决策,即使在危机或压力时期。然而,您的业务数据将提供您做出明智的计算决策或了解绩效所需的事实、趋势、统计数字和见解。

我相信,一般组织中的每个部门都会产生(或能够产生)有价值的数据,这些数据可用于制定业务战略、推动增长和盈利。例如:

  • 企业高管需要数据来了解其市场中更重要的趋势,如制造、运输或客户价格敏感度的变化。
  • 产品团队需要数据来了解产品发布后最终用户的感受。
  • 销售团队需要销售业绩数据来了解和区分畅销产品和难卖产品。
  • 营销部门需要市场细分数据来识别更愿意从他们那里购买的客户,并加快销售结束过程。
  • 人力资源部门需要人员数据来更好地管理人才,并建立更有效的全球远程团队。
  • 不胜枚举。

通过不断地收集、监控和分析业务数据,组织可以更好地做出更明智的执行决策,并开发出影响底线的成功想法,从而实现更多增长或更有效的战略。从本质上说,数据驱动的决策能让你更好地有效管理风险,提高品牌成功的几率。

衡量业务绩效并了解员工参与度

除了帮助您了解客户行为、提高品牌认知度和做出更好的业务决策之外,分析业务数据还使您能够衡量业务绩效、建立更可靠的长期假设和充满活力的员工队伍。您可以深入业务数据,了解您是否达到了最重要的业务指标。例如,如今大多数职业球队都雇佣了一个数据分析师和收集者团队,利用数据来帮助支持和提高 球员在 赛场上的表现。

通过分析业务绩效数据,您还可以了解过去行之有效和行之无效的策略、带来最大回报的业务决策和/或政策、可以优化的业务运营和成本,以及业务的其他驱动因素。最终,您的组织可以利用所有的见解来重新制定战略、降低成本、改进您的服务、产品或您如何培养和吸引潜在客户。对于假设验证,一些企业考虑随机实验,如 A/B 测试,以测试业务决策的几种变化,分析并找出产生更好结果的替代方案或方法。

任何组织都如此执着于“客户为王”的信条,以至于他们只优先考虑让他们的客户保持独特和满意。这很容易理解,因为顾客是企业命运的核心。然而,我唯一的建议是,你永远不要忽视你的员工,因为他们和你的品牌一样重要:

  • 你的员工乐意和你一起工作吗?
  • 他们如何适应新的工作方法
  • 他们是否拥有高效工作所需的所有工具?
  • 他们是乐于在家工作还是苦苦挣扎?
  • 你的员工还和队友保持良好的工作关系吗?

事实是,虽然这些问题看起来非常简单,有些直接,但只有正确的数据才能提供答案,帮助您确定您的员工在工作场所是否面临影响他们的动力、快乐、士气或生产力的特定挑战/限制。

“当你的员工快乐时,他们更有可能建立更好的关系,让你的客户快乐—我相信你对这句名言很熟悉,对吧?嗯,更快乐的员工队伍与您的组织提供更好的客户满意度和品牌增长的能力密切相关。通过收集和分析正确的员工数据,并将他们的体验放在与客户体验相同的基座上,你会变得更加积极主动,并更好地克服员工的不愉快或脱离— ,不幸的是,这是企业界最顽固的问题之一。

结论

毫无疑问,数据是任何企业的核心。随着大数据的大规模增长以及好数据提供的可能性,它在业务各个方面的重要性与日俱增。我认为,在未来十年,组织定位自己、超越竞争、推动创新计划并取得市场领先地位的最佳方式之一是创新和创造性地使用数据。当然,为了实现这一目标,组织还需要培养一种支持数据驱动决策的文化。

在我的下一篇文章(即即将发布的本出版物的第二部分)中,我将讨论阻碍组织成为数据驱动的一些因素,以及组织如何克服这些挑战以成为真正的数据驱动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值