经济学家在数据科学中的价值
经济学家的技能组合产生了一种独特类型的数据科学家。— — — — —斯蒂芬·库克在 Unsplash 上拍摄的照片
作为一名数据科学家,我努力理解经济学带来的价值。现在我明白了数据科学远不只是知道如何编码,我已经能够识别像我这样的经济学家可以给数据科学和机器学习带来的价值。本文旨在帮助经济学家解释他们可以为机器学习角色带来的价值,并帮助数据科学领域的非经济学家了解经济学家可以带来什么。
如果你上过经济学课,你可能听说过经济学是这样定义的:
“关于财富的生产、消费和转移的知识分支。”
如果你没有,你可能会将经济学与“金融”、“GDP”和“股票市场”等标签联系在一起。然而,这个领域——也是我喜欢经济学的地方——远比这些术语所引导的要广泛得多。经济学涉及历史、地理、商业、政治、心理学、市场营销和许多其他学科。如果你想深入了解各种可能性,可以看看魔鬼经济学播客。分析通常包括考虑围绕结果和影响的约束和概率。
广度可能会让你相信经济学家认为他们无所不知(在某些情况下,你是对的);他们有解决任何问题的方法。我认为他们真正拥有的是一个解决问题的框架。该框架包括成本效益分析、成本和产出优化、影响研究、博弈论分析,以及贯穿其中的计量经济学。在整篇文章中,我将引用一个经典的预测房价的数据科学问题(它的一个变种也是经济学家可以解决的问题)。
我使用的“经济学家”一词泛指在经济学的某个方面完成了研究生学位(硕士或博士学位)的个人,或者已经正式成为经济学家的个人。我将在下面描述的许多技能在本科阶段还没有得到充分发展(根据我的个人经验)。
计量经济学
计量经济学是统计分析的一种形式,经济学家可以用它来推断某种行为对结果的边际效应。这里有一个例子:考虑我前面提到的我的房子的额外空间。在保持所有其他因素不变(如位置、面积等)的情况下,一个经济学家可以根据邻居、城市或更大地理区域的家庭数据来确定。),在你的房子上多建一个房间*(这是‘边际’部分)会让它的价值*增加‘X’美元(这是推论)。
你可能已经在想象这可能会有所帮助的情况。但是如果没有,这里有几个例子可以让齿轮转动起来:
- 如果一家公司有 1000 美元的广告资金,应该使用哪些广告渠道来最大化这些资金的价值?
- 保险公司可能会根据每位客户遭遇车祸的概率来确定费率。哪些因素对概率的增加贡献最大(以及到什么程度)?
兰迪·法特在 Unsplash 上的照片
计量经济学通常专注于这些对结果有贡献的边际效应,而机器学习方法通常专注于结果本身的预测(在我们最初的例子中,是房屋的成本)。计量经济学和机器学习都使用回归、决策树和其他算法等工具,但通过不同的镜头查看结果。因此,每个镜头都有其单独的用例,但它使经济学家比那些没有推理统计学背景的人更容易过渡到机器学习。
偏差评估
当我们讨论偏差时,我们谈论的是预测值和实际值之间的一些差异。在我们的房价例子中,偏差可能出现在以下情况:
您的数据集只包含非常大或非常小的房屋,但您希望预测任何房屋的价格
您没有在数据集中包括重要的变量,比如邮政编码(“location,location,location”,对吗?)
你将每一个可能的变量都放入你的模型中,希望它能解释数据集中任何重要的东西
经济学家,特别是在运行统计模型时,被训练来仔细考虑数据、理论和结果之间的潜在偏差。偏差可以在数据生命周期中的任何一点引入,并可能导致高估/低估的结果,甚至是完全误导的结果。偏见方面的正规训练给了经济学家两件事:
1)考虑当前研究/数据集/算法可能有问题的原因的经验,以及定量检测该偏差的工具,
2)培养健康的怀疑精神和质疑结果的能力,而不是只看表面价值
在分析过程的早期测试和识别偏差的能力使经济学家能够比在试错的情况下更快地选择和实施机器学习算法。对于一些类型的偏见的良好视觉表现,请查看本文。
商业应用
经济学与商业交织在一起。因此,尽管不是 MBA,但经济学家通常对企业的一般运作方式、他们为什么做出决策以及决策的类型有着合理的理解。毕竟,经济学是一门研究激励的学科(对企业和消费者都是如此)。当涉及到价格、成本、收入、利润优化和市场研究等主题时,尤其如此。因此,作为数据科学家的经济学家拥有在相关应用中特别有效的领域知识。对于从事与这些主题无关的应用的经济学家来说,他们有工具为模型的使用开发有效的商业案例。
在我们的房地产例子中,一位经济学家可能会说,“我们想创建一个预测房价的模型,这很好,但它能给我们的业务带来什么价值呢?了解房价是否会提高我们识别“好交易”的能力,增加我们的利润?它会吸引更多的顾客到我们的网站吗?还是用现在的评估方法降低成本?”经济学家对这些问题的认识允许他们与管理层就模型开发的价值进行更有教育意义的讨论,并保持对业务最重要的事情的关注。
外部性
经济学家被训练去考虑商业行为的后果。这些后果通常被称为“外部性”,在性质上可能是积极的,也可能是消极的。然而,在考虑机器学习模型的含义时,这种训练尤为关键。有一个著名的案例,塔吉特百货公司能够根据一个女人的购物历史预测她是否怀孕,甚至准确预测预产期。经济学家通常有兴趣了解向公众发布这样一个模型会对公司业务产生什么影响。我们知道其中一些影响,但随着人工智能这样的新技术的出现,工业界仍在努力确定人工智能的影响。虽然有些人可能在不考虑外部性的情况下实现模型,但经济学家的仔细考虑可能会带来显著的节约(在金钱和声誉方面)。
复杂系统的数学建模
约翰·巴克利普在 Unsplash 上的照片
经济学家经常面临用数学描述复杂系统如何工作的问题。这些系统可能试图回答关于商品的供给和需求的问题,甚至是为什么企业做出某些决定以及他们下一步可能做出什么决定。几乎在任何情况下,这些系统都在数学也必须考虑的约束下运行。通过对这些系统建模而发展起来的对数学的掌握,让经济学家对机器学习的数学有了一定程度的适应。他们习惯于接受一个抽象的概念,并创建一套规则来管理这个概念。这些技能可以直接转移到机器学习过程中的算法选择。
结论
虽然许多人在考虑机器学习和数据科学角色时,只关注数据科学的编码部分,但这可能是一种危险的做法。经济学家拥有一套独特的技能,允许他们以与数据科学家非常相似的方式应用统计数据,同时还能够评估偏差、外部性并理解算法背后的数学。此外,他们分析业务的经验提供了质疑和讨论模型相对于业务目标的价值的能力。
如果你对经济学和数据科学之间的联系有任何疑问,请在评论中留下,我会尽力解答!
使用 Google Colab 构建代码协作
了解更多关于 Google Colab 的信息
卢卡斯·布拉塞克在 Unsplash 上的照片
M 可能我们很多人都很熟悉谷歌可乐。如果你不知道的话,Colab 是一个完全在云中运行的免费 Jupyter 笔记本环境。最重要的是,这不需要设置,您创建的笔记本可以由您的团队成员同时编辑,就像您在 Google Docs 中编辑文档一样。Colab 支持流行的机器学习库,您可以轻松地将其加载到笔记本中。
其实我在 2018 年大学的时候就开始使用 Google colab 了,但是那时候即使是从 google drive 上访问数据还是很复杂的。最后,出于无奈,我决定使用一个规格低得多的计算机实验室。
但是当我在 2019 年底朋友推荐的时候尝试了一下。从那里,我意识到现在访问数据等。变得更容易了,我将与你分享我的知识。
为什么使用 Google Colab
Google Colaboratory 或 Colab 允许您在浏览器中编写和运行 Python,具有:
- **零配置需求,**使用 colab 的便利之处之一是,你不需要配置/安装系统,因为一切都已经由 Google 完成了。你只需要安装你需要的 python 库。
- **免费使用 GPU,**另一个好处是你有权限使用 GPU。所以你只需要有一个能打开浏览器,能上网的设备。
- 轻松分享,就像其他 Google 服务一样,你可以像使用 Google Docs 一样与他人分享你的工作成果。但是需要注意的是,根据我的经验,不能有一个以上的人同时在一台笔记本上编辑。
还有一点,如果当前 RAM 不够用,Google 会提供额外的 RAM。根据我当时的经验,我正在提取维基百科的数据,然后它因为 RAM 满而崩溃了。然后谷歌提出将 ram 从原来的 12 GB 增加到 25 GB。
在浏览器打开的情况下,Google Colab 运行笔记本的“最长寿命”限制为 12 小时,而“空闲”笔记本实例在 90 分钟后中断。此外,您最多可以同时运行两台笔记本电脑。
如果在实例仍在运行时关闭并打开记事本窗口,输出和单元变量仍将存在。但是如果笔记本实例已经被回收,那么您的输出和单元格变量就不再可用。
然而,如果每次使用 Google Colab 时都必须上传数据集或模型,Google Colab 可能会很烦人。也许你不介意文件大小足够小,但如果你上传的数据集或模型文件足够大加上你有限的互联网连接,这将是一个问题。在这里,我给出了处理这些问题的技巧。
使用 Google Drive
第一种方法是用 Google Drive 安装它。所以你将要使用或已经使用的数据都存储在 Google Drive 里。使用 Google Drive 安装 Google Colab 需要使用下面的代码,该代码将提示输入授权代码。
from google.colab import drive
drive.mount('/content/drive')
代码行将返回获取授权代码的链接。点击链接,你会得到授权码。然后将其复制到提示符下,并按回车键。
您的 Google Drive 中的所有文件和文件夹都可以从名为“My Drive”的文件夹中访问。
驱动安装
如果使用 zip,效率会更高,但因为它可以压缩较小的文件,所以如果文件包含图像集合,它也很有用。您可以使用 Colab 中的 unzip 命令来解压缩以’!'开头的文件(感叹号)。感叹号用于执行来自底层操作系统的命令。
!unzip /path/to/file.zip
如果你要做长时间的训练,强烈建议使用一个检查点,保存在 google drive 上。
使用 Git
如果因为存储驱动器已满而无法使用 Google Drive。也可以使用 git 作为存储。比如你可以使用 Github 。Github 的限制是每个存储库 100 GB,每个文件 100 MB。相比之下,Google Drive 的免费版本只能提供 15GB 的存储空间。
要克隆 git remote,通常可以使用 git 命令,在开头添加感叹号。例如:
!git clone https://github.com/keras-team/keras.git
如果想推送到 git remote,有几个配置是必须要做的。
首先,是初始化 git 存储库。
!git init
然后,设置全局电子邮件和用户名。
!git config — global user.email “You@Your.com”
!git config — global user.name “Username”
添加文件
!git add .
提交
!git commit -m "first commit"
这是最重要的一行,当我们添加 git 远程源时,我们必须传递我们的 Github 凭证。
!git remote add origin https://<username>:<password>github@github.com/<username>/reponame.git
最后,用力。
!git push -u origin master
使用 wget
Google Colab 机器是建立在基于 Debian 的 Linux 上的,因此通过网络下载数据最简单的方法是 wget。您可以将文件上传到某个地方,然后您可以从 cell code notebook 下载并使用这个 shell 命令:wget。
例如,如果你想检索维基百科的数据。您可以使用以下命令将它直接下载到您的 Google colab。
!wget https://dumps.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles-multistream-index.txt.bz2
如果你想更完整地了解如何在 Google Colab 中处理文件,你可以访问下面的链接。
[## 如何在 Google Colab 中处理文件:你需要知道的一切- neptune.ai
谷歌合作实验室是一个免费的 Jupyter 笔记本环境,运行在谷歌的云服务器上,让用户…
bit.ly](https://bit.ly/37vKYN1)
在 PySpark 上实现 DBSCAN
一种基于三角形不等式的高效距离计算和聚类合并算法
DBSCAN 是一种众所周知的聚类算法,它经受住了时间的考验。虽然算法没有包含在 Spark MLLib 中。有几个实现( 1 、 2 、 3 )虽然都是在 scala 中。在 PySpark 中的实现使用 rdd 与其自身的笛卡儿积,这导致 O(n)复杂度,并且在滤波器之前可能需要 O(n)内存。
ptsFullNeighborRDD=rdd.cartesian(rdd) .filter(lambda (pt1,pt2): dist(pt1,pt2)<eps) .map(lambda (pt1,pt2):(pt1,[pt2])) .reduceByKey(lambda pts1,pts2: pts1+pts2) .filter(lambda (pt, pts): len(pts)>=minPts)source: [https://github.com/htleeab/DBSCAN-pyspark/blob/master/DBSCAN.py](https://github.com/htleeab/DBSCAN-pyspark/blob/master/DBSCAN.py)
关于 DBSCAN 算法复杂性的快速入门:
https://en.wikipedia.org/wiki/DBSCAN#Complexity
DBSCAN 可能多次访问数据库的每个点(例如,作为不同聚类的候选)。然而,出于实际考虑,时间复杂度主要由 regionQuery 调用的数量决定。DBSCAN 对每个点只执行一个这样的查询,并且如果使用在 O(log n )中执行邻域查询的索引结构,则获得 O( n log n )的总体平均运行时间复杂度(如果以有意义的方式选择参数ε,即平均只返回 O(log n )个点)。在不使用加速索引结构的情况下,或者在退化数据上(例如,距离小于ε的所有点),最坏情况运行时间复杂度保持为 O( n )。大小为( n - n )/2 的距离矩阵可以被具体化以避免距离重新计算,但是这需要 O( n )存储器,而基于非矩阵的 DBSCAN 实现只需要 O( n )存储器。
在本文中,我们将探讨如何通过减少距离计算的次数,在不使用 O(n)运算的情况下,在 PySpark 中高效地实现 DBSCAN。我们将实现一个基于三角形不等式的索引/分区结构来实现这一点。
三角形不等式
让我们用来刷新三角形不等式。如果三角形有三个顶点 a 、 b 和 *c、*以及给定的距离度量 d. 那么
d ( a,b)≤d*(a,c ) + d ( c,b )*
d ( a,c)≤d(a,b ) + d ( b,c )**
d ( b,c)≤d(b,a ) + d ( a,c )**
在 DBSCAN 中有一个参数ε,用来寻找点与点之间的联系。现在,让我们用这个参数来看看能否利用三角形不等式来减少运算次数。
**假设有四个点 x 、 y、z、c、
引理 1 :如果 d ( x,c ) ≥ ( k +1)ε和 d ( y,c ) < k ε那么 d ( x,y
根据三角形不等式,
d ( x,c ) ≤ d ( x,y ) + d ( y,c )
d ( x,c )- d ( y,c )≤ d ( x,y )
d ( x,c )- d ( y,c)>(k+1)ε-kε>ε
所以 d ( x,y ) > ε
**引理 2 :如果 d ( x,c ) ≤ l ε和 d ( z,c)>(l+1)ε则 d ( x
根据三角形不等式,
d ( z,c ) ≤ d ( x,z ) + d ( x,c )
d ( z,c )- d ( x,c )≤ d ( x,z
d ( z,c )- d ( x,c)>(l+1)ε-lε
d ( z,c )- d ( x,c ) > ε
所以 d ( x,z ) > ε
从上面我们可以推断出,如果我们计算所有的点到 c 的距离,那么我们可以使用上面的标准过滤点 y 和 z 。我们可以计算从 c 到同心环(中心为 c )中分割点的距离。
重叠同心环形隔板
隔板的宽度应该是多少?
从以上引理可以看出,如果
(m+1)ε≥d(x,c ) ≥ m ε那么我们就可以过滤出点 y 和 z 如果 d ( y,c ) < ( m -1)ε和 d**
由此我们可以推导出,对于(m+1)ε≥d(x,c ) ≥ m ε为真的任意一点,我们可以有一个宽度为( m +3)ε的分块,从( m -1)ε开始,到( m+ 2)ε结束**
图 1:隔板的宽度应该是多少?
**这是它看起来的样子。二维空间被分成ε欧氏距离的分位数。绿色环表示分区。 x 1 在距离c(m-1)ε—(m+2)ε隔板的中心)的( m +1/2)ε距离处。 x 2 和 x 3 位于 m ε和( m +1)ε距离 c. 很明显对于 x 1、 x 2 和 x 3 所有相关点(在圆内
如果我们创建互斥分区并计算该分区内各点之间的距离,这将是不完整的。比如 x 4 和 x 5 的范围圈会重叠两个分区。因此需要重叠分区。一种策略是将分区移动ε。尽管在这种情况下,如果分区宽度是 3ε,那么一个点可能出现在三个不同的分区中。相反,分区是以 2ε宽度创建的,并按ε移动它们。在这种情况下,一个点可能只出现在两个分区中。
****
图 2:具有ε重叠的 2ε宽度分区
上面两张图片展示了这种分区方案的工作原理。两个分区的组合允许对从 m ε到( m+ 1)ε的所有点进行ε半径的范围查询。第一个分区覆盖从 m ε到( m+ 1/2)ε ( x 2 被覆盖但 x 3 未被覆盖)的所有点,第二个分区覆盖( m+ 1/2)ε到( m+ 1)ε ( x 3 被覆盖但 3)
分区可视化
让我们看看这些分区在一些生成的数据上是什么样子的。
图 3:数据点
上述数据和图像由以下代码生成:
图 4:从数据中生成的几个分区
上述数据分区由以下代码生成:
partition_index 标识每个分区。如前所述,根据从 c (枢轴)到ε的距离,每个数据点被放入两个分区。距离方法一次处理一个点。在 PySpark 中,flatMap 方法用于将每个点映射到元组数组(out)中。
合并分区
在生成可视化之前,合并分区内的所有数据点。它们还需要合并,以便在 PySpark 上进一步处理 DBSCAN。
reduceByKey 方法用于将分区数据合并为一个。单词分区的使用可能会与 PySpark 分区混淆,但这是两件不同的事情。虽然 partitionBy 方法也可以用来协调这一点。
在 reduceByKey ,之后,我们将得到 rdd 的每一行,如图 4 所示。正如你所看到的,有一个重叠,所以点将在两行 rdd 中,这是故意的。
距离计算
上面的代码计算每个分区内的距离。该方法的输出是一个元组列表。每个元组都有一个点的 id 和它在ε距离内的邻居集。我们知道,该点会出现在两个分区中,因此我们需要组合给定点的集合,以便在整个数据中获得其所有在ε距离内的邻居。 reduceByKey 用于通过对集合进行并集运算来合并集合。
**reduceByKey(lambda x, y: x.union(y))**
到目前为止,组合代码如下所示:
核心和边界点标记
一旦我们在一个点的ε距离内有了邻居,我们就可以确定它是核心点还是边界点。
核心点:ε距离内至少有个 min_pts**
边界点:ε距离内有少于个 min_pts ,但其中一个是核心点。**
为了识别核心点和边界点,首先,我们将它们分配给一个集群。对于作为核心点的每个点,我们创建一个与其 id 相同的聚类标签(假设 id 是唯一的)。我们为每个核心点及其邻居创建一个元组,其形式为( id ,[( cluster_label , is_core_point )])。这种情况下的所有邻居都将被标记为基点。让我们举一个例子
***min_pts* = 3
Input: (3, set(4,6,2))
Output: [(3, [(3, True)]), (4, [(3, False)]), (6, [(3, False)]), (2, [(3, False)])]**
输入是一个元组,其中 3 是点的 id,而(4,6,2)是它在ε距离内的邻居。
可以看出,所有点都被分配了聚类标签 3。当 3 被指定为真时是核心点并且所有其他点被认为是基点并且被指定为假时是核心点。
对于 4、6 和 2,我们可能有类似的输入元组,它们可能被指定为核心点,也可能不被指定为核心点。想法是最终组合一个点的所有聚类标签,并且如果至少一个对的赋值是 _ 核心 _ 点是真,那么它是核心点,否则它是边界点。
我们使用 reduceByKey 方法将一个点的所有( cluster_label , is_core_point )元组组合起来,然后在组合该点的所有聚类标签时调查它是否是核心点。如果它是一个边界点,那么我们将只为它留下一个集群标签。
上述方法用于组合一个点的所有聚类标签。同样,如果它是边界点,那么我们只返回第一个聚类标签。
到目前为止,PySpark 中的代码如下所示:
连接的核心和边界点
对于每个点,我们都有聚类标签。如果一个点有多个聚类标签,则意味着这些聚类是相连的。那些相连的聚类是我们需要求解 DBSCAN 的最终聚类。我们通过创建一个图来解决这个问题,如果顶点被分配到同一点,则图中的顶点作为聚类标签,而边位于聚类标签之间。
在上面的代码中,combine_cluster_rdd 是行的集合,其中每一行都是一个元组( point , cluster_labels )。每个聚类标签是顶点,点的聚类标签的组合是边。该图的连通分量给出了每个聚类标签和一个连通的聚类之间的映射。我们可以将它应用到点上以得到最终的聚类。
上面是最终方法的样子,它返回一个 Spark 数据帧,带有点 id、集群组件标签和一个布尔指示符(如果是核心点的话)。
比较
现在,我将结果与 DBSCAN 的 sklearn 实现进行比较。
make_blobs 方法在三个输入中心周围创建斑点。使用 sklearn 和我的实现在ε=0.3 和 min_pts =10 的情况下运行 DBSCAN 得到以下结果。
****
左:sklearn vs 右:基于 pyspark 的实现(ε=0.3 且 min_pts =10)
核心点是较大的圆圈,而边界点是较小的圆圈。噪声点被涂成黑色,这在两种实现中是相同的。突出的一点是边界点被分配了不同的集群,这说明了 DBSCAN 的不确定性。我的另一篇帖子也谈到了这一点。
在这篇文章中,我想讨论一些关于 DBSCAN 算法的见解。通常,当我看一个算法时,我…
medium.com](https://medium.com/@salilkjain/some-notes-on-dbscan-algorithm-61a2e9acce29)
左:sklearn vs 右:基于 pyspark 的实现(ε=0.2 且 min_pts =10)
对于ε=0.2,我们得到分配给相同聚类的边界点。下面是环中数据的一些代码和结果。
操作次数
对于 n=750,DBSCAN 的简单实现所需的距离运算的数量将是 n(n-1)/2,即 280875。当我们基于ε创建分区时,ε越小,所需的距离运算次数就越少。在这种情况下,总共需要 149716 次(ε= 0.2)和 217624 次(ε=0.3)运算。
环比数据
左:sklearn vs 右:基于 pyspark 的实现(ε=0.3 并且 min_pts =5)
左:sklearn vs 右:基于 pyspark 的实现(ε=1 且 min_pts =5)
结论
基于ε值的 pyspark 实现是高效的,其步骤如下:
- 分区数据:用ε移动的 2ε宽的重叠环进行分区。
- 合并分区数据:这样我们就可以在一条记录中获得所有分区数据。
- 距离计算:计算同一分区内的距离
- 点标注:基于相邻点、标注核心和边界点的数量。
- 连接的簇:使用 Graphframe 连接簇标签以评估最终的 DBSCAN 标签。
与现有实现的比较显示了该算法和该帖子的实现的准确性。
是否高效?
在具有驱动程序和工作节点的本地机器上,实现比 sklearn 慢。可能有几个原因需要调查:
- 对于少量数据,sklearn 可能要快得多,但对于大数据来说是这样吗?
- Graphframe 需要相当长的时间来执行,想知道是否可以在驱动程序上使用其他图形库来执行连接组件分析?
履行
完整的 PySpark 实施可在以下网址找到:
在 py spark-salil Jain/py spark _ DBSCAN 上“高效”实现 DBS can
github.com](https://github.com/SalilJain/pyspark_dbscan)**
一种高效的朴素贝叶斯语言检测模型
一个简单的 Python 语言检测模型
比利亚纳·约万诺维奇摄于皮克斯拜
语言检测(或识别)是自然语言处理的一个迷人的分支。它的目标是创建一个模型,能够检测一个文本是用哪种语言写的。
数据科学家通常采用神经网络模型来实现这一目标。在本文中,我展示了如何使用朴素贝叶斯模型在 Python 中创建一个简单的语言检测模型。
问题是
我们要面对的问题是创建一个模型,一旦有了文本,它就能检测出它的语言。文本可以是一个句子、一个单词、一个更复杂的文本等等。例如,输出变量可以是语言代码(如英语的“en”)。
一个好主意是建立一个模型来检测文本的语言,即使该文本包含该模型在训练阶段没有看到的单词。我们想要一个模型,它能够以一种使语言能够正确检测的方式来概括语言的底层结构。
让我们看看如何创建这样一个模型。
数据
我要训练这个模型检测三种语言:意大利语、英语和德语。对于意大利语,我将使用我的一个简短的恐怖故事的文本来训练模型, L’isola del male 。对于英语,我将使用这个故事的英文翻译,邪恶之岛。对于德语,我将使用的文本也就是查拉图斯特拉在这里找到的弗里德里希·尼采:http://www.nietzschesource.org/#eKGWB/Za-I。我将把这些文档分割成句子,最终的句子数据集将被分割成训练集和测试集。
使用字符二元模型进行矢量化
所以,我们在讨论一个三值类的分类问题,即:it,en,de。这是目标变量。
现在,我们来谈谈特点。我要使用的特性是 char bigrams,它是一个句子中两个连续字符的集合。例如,考虑“行星”这个词。在这种情况下,字符二元组是“pl”,“la”,“an”,“ne”,“et”。
为什么我们应该使用 char 二元模型?因为这样会降维。拉丁字母表由 26 个字母组成。加上这 10 个数字和一些其他特殊的字符或符号,我们得到大约 50 个不同的符号。我们可以拥有的字符二元模型的最大数量是 50*50 = 2500。
如果我们使用经典的单词驱动的矢量化,我们将拥有更高的维度,因为每种语言可能有数十万个单词,我们可能需要将它们全部矢量化,创建一个包含数千个特征的向量,并遭受维度的诅咒。使用 char 二元模型,我们最多可以得到 2500 个组件,它们可以在所有使用拉丁字母的语言中共享。这非常令人印象深刻,因为我们可以使用这个语料库作为使用这种字母表的每种语言的通用特征集。此外,我们没有绑定到预定义的单词语料库,因此我们的模型甚至可以处理从未被训练过的单词,只要它们是由原始训练语料库的字符二元组构成的。
在我们的特殊例子中,三个文档的完整词汇由 7062 个不同的单词组成。如果我们使用 chars char 二元模型,我们得到 842 个特征。我们已经将问题的维度减少了近 90%!
所以,这些就是特色。对于每个句子,我们计算字符二元模型,并计算特定二元模型在句子中出现的次数。这个数字将填充表示句子的相应向量分量。
模型
我要用的模型是多项式朴素贝叶斯。这是一个非常简单的模型,一般来说,当谈到自然语言处理时,朴素贝叶斯非常强大。它几乎没有超参数,所以我们可以专注于预处理阶段,这是最关键的。
根据 scikit-learn 文档,多项式朴素贝叶斯可以将计数向量作为输入特征,这正是我们需要的。
代码
让我们导入一些库:
我们将要使用的语料库由 3 个文本文件组成。我们必须清理文本,将其矢量化,然后我们可以训练模型。
数据预处理和矢量化
首先,我们必须清理我们的文本,以便把它分成单句。让我们编写一个函数,它获取一个文本文件,删除双空格、引号和无用的标点符号,返回一个句子列表。
每个文档都存储在单独的 txt 文件中。我们可以加载三个文档的句子,创建一个包含所有句子的数组,另一个包含与每个句子相关的语言。
完整的语料库规模为 4195 个句子。下面是一个例子:
语料库的一个例子。图片由作者提供。
如你所见,每个句子都与其语言相关联。
语言在语料库中的分布相当均匀,所以不存在不平衡的类别。
语料库中语言的分布。图片由作者提供。
现在,我们可以将数据集分为训练集和测试集,并开始处理模型。
首先,我们必须调用 sklearn 的 CountVectorizer 对象,以便为每个 char 二元模型创建它在每个句子中出现的次数。然后,我们可以创建管道,将我们的数据矢量化,并将其提供给模型,这是一个多项式朴素贝叶斯。
现在,我们可以拟合管道,并在测试集上计算预测:
我们终于可以看看混淆矩阵了:
挺斜的。分类误差似乎很低。
让我们看看分类报告:
如你所见,我们达到了 97%的整体准确率。如果我们考虑到我们只处理三个文档和一个少于 5000 条记录的数据集,这是非常令人印象深刻的。
让我们强调模型
现在,让我们强调一下我们的模型。
下面是三种不同语言的一组句子。“评论”栏是我的一个评论,解释了这个句子的一些特征,包括它的真实语言。“检测到的语言”列是模型预测的语言的 ISO 代码。
正如我们所看到的,即使对于混合语言的句子,该模型也相当不错。仍然存在一些错误(例如,“超参数”被错误地检测为意大利语),但是结果看起来健壮且不错。
甚至在意大利文和英文文本中都出现的单词“Harrier”也被正确地认为是一个英文单词。
一个简单的 API
我已经将模型嵌入到 pickle 文件中,并使用 Flask 创建了一个简单的 API,将其部署在 Heroku 上。这是一个用于测试目的的开发 API。我善意地鼓励你尝试一下,并给我你的反馈。
终点是:https://gianlucamalato.herokuapp.com/text/language/detect/
请求必须是带有“text”键的 JSON 文档,其值是要处理的文本。该方法是 POST。
响应是一个 JSON 文档,包含“文本”字段中的原始文本和“语言”字段中检测到的语言代码。
下面是一个如何调用我的 API 的例子:
我创建了另一个 GET 方法来显示模型修改日期和支持的语言:
结论
在本文中,我展示了如何使用朴素贝叶斯创建一个简单的语言检测模型。像往常一样,模型的功能依赖于输入特性,使用 char 二元模型似乎是个好主意。
如果你喜欢这个模型,请使用我的 API 强调它,并给我你的反馈。
一种安装和加载 R 包的有效方法
照片由克劳迪奥·施瓦茨拍摄
什么是 R 包,如何使用?
与其他程序一样,r 默认只提供基本功能。因此,您经常需要安装一些“扩展”来执行您想要的分析。这些扩展是由 R 用户开发和发布的函数和数据集的集合,称为包。它们通过添加新的功能来扩展现有的 base R 功能。r 是开源的,所以每个人都可以编写代码并将其发布为一个包,每个人都可以安装一个包并开始使用包中内置的函数或数据集,所有这些都是免费的。
为了使用一个包,需要通过运行install.packages("name_of_package")
将它安装在你的计算机上(不要忘记在包的名字周围加上""
,否则,R 会寻找以那个名字保存的对象!).安装软件包后,您必须加载软件包,只有在加载后,您才能使用它包含的所有函数和数据集。要加载一个包,运行library(name_of_package)
(这一次包名两边的""
是可选的,但是如果你愿意,仍然可以使用)。
安装和加载 R 包的低效方法
根据你使用 R 的时间长短,你可能会使用有限数量的软件包,或者相反,使用大量的软件包。随着你使用越来越多的软件包,你很快就会开始有(太多)多行代码来安装和加载它们。
下面是我博士论文中的代码预览,展示了当我开始研究 R 时,R 包的安装和加载是什么样子的(为了缩短代码,只显示了一小部分):
# Installation of required packages
install.packages("tidyverse")
install.packages("ggplot2")
install.packages("readxl")
install.packages("dplyr")
install.packages("tidyr")
install.packages("ggfortify")
install.packages("DT")
install.packages("reshape2")
install.packages("knitr")
install.packages("lubridate")# Load packages
library("tidyverse")
library("ggplot2")
library("readxl")
library("dplyr")
library("tidyr")
library("ggfortify")
library("DT")
library("reshape2")
library("knitr")
library("lubridate")
你可以猜到,随着我需要越来越多的分析包,代码变得越来越长。此外,我倾向于重新安装所有的软件包,因为我在 4 台不同的计算机上工作,我不记得哪个软件包已经安装在哪个机器上了。每次打开我的脚本或 R Markdown 文档时重新安装所有的包都是浪费时间。
更有效的方法
后来有一天,我的一个同事跟我分享了他的一些代码。我很高兴他这样做了,因为他向我介绍了一种更有效的安装和加载 R 包的方法。他允许我分享这个技巧,所以下面是我现在用来执行安装和加载 R 包任务的代码:
# Package names
packages <- c("ggplot2", "readxl", "dplyr", "tidyr", "ggfortify", "DT", "reshape2", "knitr", "lubridate", "pwr", "psy", "car", "doBy", "imputeMissings", "RcmdrMisc", "questionr", "vcd", "multcomp", "KappaGUI", "rcompanion", "FactoMineR", "factoextra", "corrplot", "ltm", "goeveg", "corrplot", "FSA", "MASS", "scales", "nlme", "psych", "ordinal", "lmtest", "ggpubr", "dslabs", "stringr", "assist", "ggstatsplot", "forcats", "styler", "remedy", "snakecaser", "addinslist", "esquisse", "here", "summarytools", "magrittr", "tidyverse", "funModeling", "pander", "cluster", "abind")# Install packages not yet installed
installed_packages <- packages %in% rownames(installed.packages())
if (any(installed_packages == FALSE)) {
install.packages(packages[!installed_packages])
}# Packages loading
invisible(lapply(packages, library, character.only = TRUE))
这段安装和加载 R 包的代码在几个方面更有效:
- 函数
install.packages()
接受一个向量作为参数,所以过去每个包的一行代码现在变成了包含所有包的一行代码 - 在代码的第二部分,它检查一个包是否已经安装,然后只安装缺少的包
- 关于包的加载(代码的最后一部分),使用
lapply()
函数一次性调用所有包的library()
函数,这使得代码更加简洁。 - 加载包时的输出很少有用。
invisible()
功能删除该输出。
从那天起,每当我需要使用一个新的包时,我简单地把它添加到代码顶部的向量packages
,它位于我的脚本和 R Markdown 文档的顶部。无论我在哪台计算机上工作,运行整个代码都将只安装缺失的包并加载所有的包。这大大减少了安装和加载我的 R 包的运行时间。
最有效的方法
{pacman}
包装
这篇文章发表后,有读者通知我关于{pacman}
包的事情。在阅读了文档并亲自试用之后,我了解到{pacman}
中的函数p_load()
会检查是否安装了某个包,如果没有,它会尝试安装该包,然后加载它。它还可以同时应用于多个包,所有这一切都以一种非常简洁的方式进行:
install.packages("pacman")pacman::p_load(ggplot2, tidyr, dplyr)
在曲柄上找到更多关于此包装的信息。
{librarian}
包装
与{pacman}
一样,{librarian}
包中的shelf()
函数自动安装、更新和加载尚未安装在单个函数中的 R 包。该功能接受来自 CRAN、GitHub 和 Bioconductor 的软件包(仅当安装了 Bioconductor 的Biobase
软件包时)。该函数还接受多个包条目,以逗号分隔的未加引号的名称列表的形式提供(因此包名周围没有""
)。
最后但同样重要的是,{librarian}
包允许在每个 R 会话开始时自动加载包(感谢lib_startup()
函数),并通过关键字或正则表达式在 CRAN 上搜索新包(感谢browse_cran()
函数)。
下面是一个如何安装缺失的包并用shelf()
函数加载它们的例子:
# From CRAN:
install.packages("librarian")librarian::shelf(ggplot2, DesiQuintans/desiderata, pander)
对于 CRAN 包,提供不带""
的普通包名,对于 GitHub 包,提供用/
分隔的用户名和包名(即desiderata
包所示的UserName/RepoName
)。
在 CRAN 上找到更多关于这个包的信息。
感谢阅读。我希望这篇文章能帮助你以更有效的方式安装和加载 R 包。
和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。
特别感谢 Danilo 和 James 告诉我关于 *{pacman}*
和 *{librarian}*
包的信息。
相关文章:
- 我的数据符合正态分布吗?关于最广泛使用的分布以及如何检验 R 中的正态性的注释
- R 中的 Fisher 精确检验:小样本的独立性检验
- R 中独立性的卡方检验
- 如何在简历中创建简历时间线
原载于 2020 年 1 月 31 日https://statsandr.com。
阿姆斯特丹 Airbnb 数据集:一个端到端的项目
一个数据科学组合项目就像为你的驾驶执照实践考试而学习,你不是在学习驾驶,而是在学习如何通过考试。
准备作品集时,重要的是要有涵盖不同领域、技术并能讲述一个故事的项目。
Chait Goli 在 pexels.com 拍摄的照片
在本文中,我的主要目标是展示我将如何做一个数据科学组合项目,该项目涵盖可视化、数据预处理、建模和最终考虑以及生产建议。
给定一系列预测因素,我使用阿姆斯特丹 Airbnb 数据集预测一套公寓的价格。
简介:
数据集一旦导入 Python,就会使用[pandas_profiling](https://github.com/pandas-profiling/pandas-profiling)
进行分析,这是一个非常有用的工具,它扩展了 pandas 中的df.info()
功能。
报告的第一部分
如报告中所述,数据集包含 14 个变量,10 个是数字变量,2 个是分类变量(建模时,我们可能需要为这些变量获取虚拟变量)。
此外,根据报告变量host_listings_count
和calculated_host_listings_count
与 0.94 的皮尔逊分数高度相关,因此我们将放弃前者以避免多重共线性问题。
我们可以看到我们的目标变量price
不是一个数字,让我们看看最长的一个,以便了解是否有任何格式需要在转换前删除:
max(df[‘price’].values, key = len)>>> '$1,305.00'
首先,我们可以看到我们的目标变量有 2 个不同的字符需要去掉,即符号$
和识别千位的逗号。让我们用df.apply()
来摆脱它们。
df[‘price’] = df[‘price’].apply(lambda x: x.replace(‘$’, ‘’))
df[‘price’] = df[‘price’].apply(lambda x: x.replace(‘,’, ‘’))df[‘price’] = pd.to_numeric(df[‘price’])
数据可视化:
数据集有两列,包含公寓所在位置的坐标信息,此外还有我们的目标变量。因此,我们可以创建一个热图,以更好地了解公寓的位置以及价格如何受到位置的影响
为了实现这一点,我们将使用[gmaps](https://pypi.org/project/gmaps/)
,一个使用谷歌地图创建交互式地图的 python 包。
使用 GMaps 的热图示例
你可以使用免费版本,没有 API 密钥,但是,你会得到带有难看的“仅供开发”水印的地图,如果你想消除这些水印,你可以注册(通过添加信用卡)到谷歌云平台,并申请免费积分。点击此处了解更多信息。
请小心使用 API 键,尤其是如果你想在线共享你的项目。(在把笔记本推给 GitHub 之前,我禁用了我的键🙃)
您可以在 Jupyter 笔记本上安装gmaps
,首先通过终端ipywidgets
扩展启用:
$ jupyter nbextension enable — py — sys-prefix widgetsnbextension
然后:
$ pip install gmaps
最后,用以下代码加载扩展:
$ jupyter nbextension enable — py — sys-prefix gmaps
用gmaps
创建热图很简单,我们指定一个Map
对象,然后传递带有坐标和权重的数据帧。
fig = gmaps.Map(layout={‘width’: ‘1000px’, ‘height’: ‘500px’, ‘padding’: ‘10px’})fig.add_layer(gmaps.heatmap_layer(df[[‘latitude’, ‘longitude’]],
weights=df[‘price’]))fig
名词(noun 的缩写)如果你安装了 gmaps,并做了所有正确的事情,但地图没有显示,只需重新启动 jupyter 笔记本,它将(很可能)工作!
地图显示,市中心的位置更贵,而郊区更便宜(这种模式可能不仅仅存在于阿姆斯特丹)。另外,市中心似乎也有自己的格局。
为了捕捉一些地理模式,我们需要应用一些特征工程,一个很好的方法是找到一个兴趣点(POI)列表,并计算每个观察值和 POI 之间的距离。
如果我们知道一个特定的地点离我们认为很贵的地方很近,很可能整个周边地区都会很贵。
为了计算以千米为单位的距离,我使用了一个函数来检索哈弗线距离,也就是球体上两点之间的距离。
这种度量有其利弊:它提供了一种计算两点之间距离的简单方法,但它没有考虑建筑物、湖泊、河流、边界等障碍。
为了得到一个兴趣点的列表,我在谷歌上搜索,我搜索了每个兴趣点的地理坐标。
结果如下:
现在可以定义一个函数来计算一个房屋到每个 POI 的距离:
from math import radians, cos, sin, asin, sqrtdef haversine(lon1, lat1, lon2, lat2):
“””
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
“””
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 — lon1
dlat = lat2 — lat1
a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
c = 2 * asin(sqrt(a))
km = 6367 * c
return km
现在,我们可以迭代数据集的每一行,对于每一行,我们迭代我们的 POI 数据帧,并计算每个 POI 的距离(我说了太多次“每个”或“POI”了吗?)
现在让我们用 poi 再次绘制我们的地图,我们可以通过迭代poi
数据帧的每一行并使用列表理解创建一个元组来做到这一点:
fig.add_layer(gmaps.symbol_layer([tuple(x) for x in poi.to_numpy()]
, fill_color=’green’, stroke_color=’green’))
fig
从可视化中可以看出,Willemspark 附近的公寓比周围地区少得多,此外,大多数 poi 都位于“昂贵”区域,尤其是 Dam Square 区域周围。
建模:
现在让我们开始建模部分,我们将通过对分类变量room_type
进行编码并将其分为训练和测试来准备数据集
df = pd.get_dummies(df)X = df.drop([‘price’], axis=1)
y = df[‘price’]from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=1)
数据集在训练和测试之间分成 80–20%。
基线模型📏:
使用的第一个模型将用作基线,因为我们需要一个基准来评估其他模型的性能并比较结果。
它包括一个经典的线性回归,使用r2
和MAE
指标上的GridSearchCV
类进行交叉验证评估。
让我们来适应它:
from sklearn.linear_model import LinearRegressionlin_reg = LinearRegression()lin_reg.fit(X_train, y_train)
y_pred = lin_reg.predict(X_test)
现在,我们可以通过创建虚拟数据帧来存储每个模型的结果,从而计算 r2 和 MAE 误差:
from sklearn import metricsr2 = metrics.r2_score(y_test, y_pred)
mae = metrics.mean_absolute_error(y_test, y_pred)scores = pd.DataFrame({‘Baseline (regression)’ : [r2, mae]}, index=[‘R2’, ‘MAE’])scores
mae
告诉我们,我们的预测平均相差 40 美元,而 R2 告诉我们,我们的数据相当稀疏。
以图形方式评估回归结果的一个有趣的图是测试集和预测值相对于我们的测试集的差异:
理想情况下,我们希望看到我们的结果越稀疏越好,以 45°穿过图
这些值越接近 0 越好,因为 delta y_test — y_pred
应该是理想的是 0。
支持向量机模型📈:
根据 sklearn 地图选择了下一个模型,它由一个支持向量机组成。然而,由于使用参数并不总是容易,而且可能需要特定的知识GridSearchCV
将会有所帮助:
if 'svr_gridsearch_cv.pkl' in os.listdir():
svr_grid_search = joblib.load('svr_gridsearch_cv.pkl')
else:
from sklearn.svm import SVRsvr = SVR()param_grid = [
{'C': [1, 10, 100, 1000], 'kernel': ['linear']},
{'C': [1, 10, 100, 1000], 'gamma': [0.01, 0.001, 0.0001], 'kernel': ['rbf']}]svr_grid_search = GridSearchCV(svr, param_grid=param_grid,
n_jobs=-1,
scoring=['r2', 'neg_mean_squared_error'],
refit='neg_mean_squared_error', verbose=100)svr_grid_search.fit(X_train, y_train)joblib.dump(svr_grid_search.best_estimator_, 'svr_gridsearch_cv.pkl')
请注意,这项任务可能需要 40 多分钟,这就是为什么在拟合之前,我会检查模型是否已经存在,如果存在,我会加载它。
然后,我们将再次根据来自GridSearchCV
的最佳参数来预测和计算我们的指标
使用支持向量机,我们已经从我们的基本模型进行了改进。
与我们的基准模型相比,mae
平均降低了近 4 美元。
让我们也为这个模型绘制预测值与误差增量的关系图:
与前一个相比,预测不那么稀疏,这解释了 R2 的小幅增长。
梯度推进树模型🌲:
我们将测试的第三个模型是基于随机梯度下降的,我将使用 LightGBM ,这是微软的一个库,在行业中广泛使用,是赢得 Kaggle 竞赛最常用的库之一。
if 'gbm_gridsearch_cv.pkl' in os.listdir():
gbm_grid_search = joblib.load('gbm_gridsearch_cv.pkl')
else:
from lightgbm import LGBMRegressorgbm = LGBMRegressor()param_grid = {
'learning_rate': [0.01, 0.1, 1],
'n_estimators': [50, 100, 150],
'boosting_type': ['gbdt', 'dart'],
'num_leaves': [15, 31, 50]}gbm_grid_search = GridSearchCV(gbm, param_grid=param_grid,
n_jobs=-1,
scoring=['r2', 'neg_mean_squared_error'],
refit='neg_mean_squared_error', verbose=100)gbm_grid_search.fit(X_train, y_train)joblib.dump(gbm_grid_search.best_estimator_, 'gbm_gridsearch_cv.pkl')
模型训练相当快,结果一点也不差:
到目前为止,表现最好的模型是 GBM,它将 R2 提高了约 6%,而mae
略差。
很多差值似乎是负数,这意味着预测值经常高估真实值。
神经网络🧠:
在考虑如何进一步改进我们的回归变量时,我首先想到的显然是神经网络!所以我决定实现一个简单的方法:
def build_model():
model = keras.Sequential([
tf.keras.layers.Dense(64, activation=’relu’, input_shape=(25,)),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(128, activation=’relu’),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(1)
])optimizer = tf.keras.optimizers.RMSprop(0.001)model.compile(loss=’mean_squared_error’,
optimizer=optimizer,
metrics=[‘mae’, r2_keras])
return model
然而,在玩了一会儿并运行了 100 个纪元后,结果并不特别令人惊讶:
结果基本上是 GBM 和 SVR 之间的平均值,并且绘制误差给出了与之前非常相似的图。
那么哪个才是最好的模式呢?
尽管已经有了模型性能的度量标准,但是为了给出哪个模型被认为是最佳的最终评估,有必要添加其他评估度量标准,例如实现模型所需的资源和训练模型所需的时间。
考虑第二个模型 SVR:它表现异常,实现了最好的 MAE,但是实现网格搜索的训练时间花费了 40 多分钟,这意味着每次想要检查或更改某个东西都至少要花费 40 分钟。
第三个模型(梯度推进树),花了几秒钟来拟合,结果相当好,实际上达到了整体最好的结果。
考虑到最后一个模型,神经网络,它也没有花太多时间来训练,几分钟,但是,结果并没有从根本上优于以前的模型,实际上,它的表现或多或少是相同的,可能是因为我没有选择正确的超参数,可能是因为数据量,可能是因为其他多种原因,但是,它并没有从根本上优于以前的模型。
此外,这是一个不太容易解释的模型,这意味着我们很难解释预测是如何决定的,而例如,对于线性回归,我们可以拥有所有数据,如截距和系数:
coefficients = pd.concat([pd.DataFrame(X.columns, columns=['variable']),
pd.DataFrame(np.transpose(lin_reg.coef_), columns ['coefficients'])], axis = 1)coefficients
我们基线模型的系数
总结一下:
考虑到前面提到的注意事项,并指出妥协通常是一个很好的近似,我们可以得出结论,根据我们的指标,最佳模型是梯度推进树(LightGBM),它在一眨眼的时间内训练完毕,结果是其他候选模型中最好的。
此外,选择机器学习模型提供了一个优势:决策树是一个可解释的模型,可以分解它,并找到它为什么以及如何计算特定的结果,而不是另一个,在树回归器上调用以下方法,可以查看树的图表:
import lightgbmlightgbm.create_tree_digraph(gbm_grid_search.best_estimator_)
XAI 或可解释的人工智能是现代数据科学的一个非常重要的方面,它专注于如何实现特定的预测,而不是将模型视为黑盒。
引用波恩大学的一篇论文:
获得科学成果的先决条件是领域知识,这是获得可解释性以及增强科学一致性所必需的。
[*] Ribana Roscher,Bastian Bohn,Marco F. Duarte 和 Jochen Garcke,科学见解和发现的可解释机器学习 (2019)。
**I have a newsletter 📩.**Every week I’ll send you a brief findings of articles, links, tutorials, and cool things that caught my attention. If tis sounds cool to you subscribe.*That means* ***a lot*** *for me.*
[## 米尔斯形式
编辑描述
无情-创造者-2481.ck.page](https://relentless-creator-2481.ck.page/68d9def351)
一个端到端的时序数据科学项目,将提升您的投资组合
数据科学组合项目就像学习驾照实践考试,你不是在学习驾驶,而是在学习如何通过考试
照片由 Pixabay 拍摄
在本指南中,我想向您展示如何根据现实生活中的零售数据进行收入时间序列预测,为了完成这些任务,我将使用一个非常常见的库:Prophet,由脸书的科学家开发。
为什么是先知?
根据先知 GitHub 页面:
“为具有线性或非线性增长的多重季节性时间序列数据生成高质量预测的工具”
而且,Prophet 被集成到了 AWS 生态系统中,成为时间序列分析最常用的库之一。
来源:脸书的 Github
数据
本教程中使用的数据来自一家零售公司,由于数据来源的业务性质,它具有很强的季节性。数据框已经被匿名化,它包含两列:交易的datetime
和交易的金额。
交易出现在一天的不同时间,为了减少噪音,每天对数据进行重新采样,汇总总收入。
此外,时间戳列已被转换为与 CET 时区相匹配,这样做的主要原因是能够以可理解的格式保存数据,使我们以及最终我们的客户更容易理解。以下是用于实现此目的的函数:
交易是在 2018 年 6 月至 2019 年 10 月期间收集的,它包含 11284 条销售记录。
但是让我们更深入地了解一下 Prophet:根据脸书 Prophet 的文档,要放入 Prophet 的数据必须具有非常严格的格式:一个名为ds
的列表示时间点,另一个名为y
的列表示目标。
使用以下代码片段很容易实现这一点:
在这一步,数据可能看起来准备好用于拟合模型,但是在绘制数据之后,必须进行一个非常重要的考虑:
(自己阐述)
数据似乎包含了一些看起来奇怪的值,非常极端的值,这些值会改变平均值:这是什么?
这些观察值被称为异常值,异常值是与其他观察值显著不同的数据点,可能是由于测量中的一些误差造成的。
在数据科学中,必须正确对待异常值,因为它们会严重误导分析和/或降低模型的质量。
剔除异常值的一个很好且非常常用的策略是四分位间距(IQR)规则,通过查看低于 Q1-1.5 IQR 或高于 Q3+ 1.5 * IQR 的观测值,可以找到异常值。这可以用下面的语法在 pandas 中实现:
为了更好地理解发生了什么,方框图会很有帮助:
在剔除异常值之前:显然有大量的异常值,这些是从顶部最大值中掉出的观察值。(自己阐述)
剔除离群值后。(自己阐述)
此时,可以查看“干净”的数据集:
(自己阐述)
在构建机器(和深度)学习模型时,我们希望有一些指标来了解模型的表现,因此第一个拟合的模型是基线模型;该模型由 Prophet 提供的最基本的装配工组成,将用作衡量其他模型之间改进的基线。
该模型被拟合并用于预测 60 天的窗口,并在第 12 天和第 60 天对其性能进行评估,以更好地了解短期和长期预测。
本教程选择的评估模型的度量标准是 MAE:平均绝对误差是一种用于测量预测中误差的平均大小的工具,它不考虑误差的方向,并且实际值和预测值之间的所有差异都具有相同的权重。
MAE 是这类任务的一个非常常见的指标,为了更深入的解释,我想提到这个帖子。
通过绘制预测图可以看出,该模型以一种非常笨拙的方式捕捉了数据的趋势。
(自己阐述)
但是让我们检查一下 MAE:
(自己阐述)
第一个模型从第 12 天的 MAE 约为 240 开始,这意味着第 1 天的平均误差为 240 欧元(我们目标值的货币),而与 60 天的预测相比,误差达到 450 欧元。
在这一点上,有可能更进一步,建立第二个模型,最终(并且有希望)能够胜过第一个模型;滚动 prophet 文档可以看到 prophet 有一个让用户按国家指定假日的方法。
假期是零售数据的一个非常好的预测指标,例如,想想圣诞节有多近,人们就会传统地争相寻找最完美的礼物。
第二个模型显示了一些改进,但是,该模型用拟合线上的一些奇怪尖峰来拟合数据:
(自己阐述)
(自己阐述)
从图中可以看出,该模型从大约 230 的 MAE 开始,而在大约第 60 天达到 360-370。因此,从短期来看,它往往是一个更好的模型,而从长期来看,它的表现略好于基线。
深入到 Prophet 文档中可以看到,通过指定周期的持续时间及其傅立叶阶,可以将自定义季节性添加到我们的模型中。
在尝试不同的自定义季节性时,我注意到数据每两个月就有一个增长趋势,这就是为什么我决定添加两个月的季节性成分:
该模型不断更好地拟合数据,捕捉越来越多的季节性成分,这导致短期内的小幅度改善,而从长期来看,这种策略似乎并不奏效,从长期来看,最好的模型仍然是第二种。
(自己阐述)
(自己阐述)
但是怎样才能将长期误差降到最低呢?
已经看到添加两个月的季节性项有助于捕捉一些趋势,这可能表明一个好的策略是添加更多的季节性项。它工作,但是…
但是…要小心!添加大量季节性成分可能会导致强烈的过度拟合,这可以通过减少傅立叶项来部分避免,这不需要太深入,就可以使季节性“侵入性更小”。
分别每一个月、两个月和三个月用三个自定义季节性来拟合最后一个模型,从长远来看会导致误差的显著减少,同时拟合线会稍微好一些:
(自己阐述)
结论
从这个小指南中,可以推断出一个特定的模型在一个特定的时间范围内表现更好,而在另一个时间范围内可能表现很差。
通常模型是在试错框架下训练的,换句话说:需要多次尝试才能获得可观的结果。这并不意味着只是随机尝试一切,而是更好地理解数据。
在本例中,数据来自时尚零售,时尚零售产品周期短,t 恤(几乎)仅在夏季销售,套头衫仅在冬季销售,这就是为什么添加了不同的定制季节性术语。
拟合时间序列模型可能是一项相当棘手的任务,部署阶段甚至可能更棘手,例如,考虑将模型部署到客户端:每次客户端希望获得一些预测时,模型都需要再次拟合,如果模型托管在一些云提供商上,您可以按需付费,费用可能会快速增长。
**I have a newsletter 📩.**Every week I’ll send you a brief findings of articles, links, tutorials, and cool things that caught my attention. If tis sounds cool to you subscribe.*That means* ***a lot*** *for me.*
[## 5-bullet 数据科学与技术📡
编辑描述
无情-创造者-2481.ck.page](https://relentless-creator-2481.ck.page/68d9def351)
使用 Python 获取股票数据的更简单的指南
Jason Briscoe 在 Unsplash 上的照片
跟着走,在这里访问代码。
我刚刚在我的电子邮件简讯中看到了这篇文章。所以我想用 Python 做一个更简单的获取股票数据的版本。只有我的版本不需要在您的计算机上安装 Python。它完全是使用 Google Colab 运行的。
对于那些不熟悉 Google Colab 的人来说,这是一个免费的基于云的在线 Jupyter 笔记本环境。它使编程变得非常容易,无需在本地机器上安装任何东西。它还能够远程利用 GPU,非常适合热爱编程但没有资源这样做的人。
在文章中,他们提到使用一个名为yfinance
的库。我将使用pandas_datareader
。我们不需要在 Google Colab 中安装它,因为它已经是内置的了。因此,我们只需要做一些进口。我们从代码开始:
from pandas_datareader import data as web
因为我们会处理很多日期,所以另一个方便的库是datetime
。让我们继续导入它。
import datetime
为了简单起见,我还将使用与文章相同的股票代码,即 SPDR 标准普尔 500 ETF 信托。翻译成股票代号形式的间谍。所以我们把它设为一个名为stock
的变量。
stock = 'MSFT'
在下一段代码中,我获取了这段代码运行前一年的数据。
start_date = (datetime.datetime.now() - datetime.timedelta(days=365)).strftime("%m-%d-%Y")
我现在将start_date
插入 DataReader。我将从雅虎获取数据。然后我将输出到一个数据帧中。
df = web.DataReader(stock, data_source='yahoo', start=start_date)
我们现在可以导入matplotlib
,如果我们想可视化它,让它看起来更好。
import matplotlib.pyplot as plt
现在绘图就像取其中一列一样简单。现在让我们用数据框中的 close 列来做这件事。
plt.plot(df['Close'])
就是这么简单,不需要安装,就可以使用了!请随意分享这篇文章和代码!Google Colab 让它变得简单快捷。
也可以随意查看我的其他文章。我还有使用 Python 的技术分析,以及如何使用 Python 连接 Robinhood。
我最近发现了今年内的期权交易。这是一次有趣的经历,我学到了一些新东西…
towardsdatascience.com](/options-trading-technical-analysis-using-python-f403ec2985b4) [## 使用 Python 获取罗宾汉数据
让我们自动化一些股票,可以用来建造一个交易机器人。
towardsdatascience.com](/using-python-to-get-robinhood-data-2c95c6e4edc8)
过度拟合的一个例子及如何避免
一个简单的例子展示了过度拟合和交叉验证的重要性
对于试图训练监督模型的数据科学家来说,过度拟合是一个巨大的敌人。这将极大地影响性能,其结果在生产环境中可能非常危险。
但是什么是过度拟合呢?在这篇文章中,我解释了如何识别和避免它。
什么是过度拟合?
当您的模型从训练数据中学到了太多东西,并且不能概括底层信息时,就会发生过度拟合。当这种情况发生时,模型能够非常准确地描述训练数据,但是在没有对其进行训练的每个数据集上都失去了精度。这是完全不好的,因为我们希望我们的模型在它从未见过的数据上相当好。
为什么会这样?
在机器学习中,简单是关键。我们希望概括从训练数据集中获得的信息,因此我们可以肯定地说,如果我们使用复杂的模型,我们会有过度拟合的风险。
复杂的模型可能会从训练数据中过度学习,并且会认为使训练数据偏离基础动态的随机误差实际上值得学习。这正是模型停止概括并开始过度拟合的时候。
复杂性通常用模型在学习过程中使用的参数数量来衡量。比如线性回归中的参数个数,神经网络中的神经元个数等等。
因此,参数的数量越少,简单性越高,并且合理地,过度拟合的风险越低。
过度拟合的例子
让我们借助一些 Python 代码来做一个简单的例子。
我将按照公式创建一组 20 个点:
每个点将增加一个平均值为 0、标准偏差为 0.05 的正态分布误差。在现实生活的数据科学中,数据总是由于随机误差而偏离“真实”模型。
一旦我们创建了这个数据集,我们将拟合一个越来越高次的多项式模型,看看在训练集和测试集中会发生什么。在现实生活中,我们不知道数据集内部的真实模型,所以我们必须尝试不同的模型,看看哪一个更适合。
我们将前 12 个点作为训练集,后 8 个点作为测试集。
首先,让我们导入一些有用的库:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
现在让我们创建样本点:
np.random.seed(0)
x = np.arange(-1,1,0.1)
y = -x**2 + np.random.normal(0,0.05,len(x))plt.scatter(x,y)
plt.xlabel("x")
plt.ylabel("y")
plt.show()
正如你所看到的,实际上有一点噪音,就像现实生活中的试衣一样。
现在,让我们将这个数据集分成训练和测试两部分。
X_train = x[0:12]
y_train = y[0:12]
X_test = x[12:]
y_test = y[12:]
我们现在可以定义一个简单的函数,在给定训练集和多项式次数的情况下,返回一个函数,该函数表示最适合训练数据的多项式的数学表达式。
def polynomial_fit(degree = 1):
return np.poly1d(np.polyfit(X_train,y_train,degree))
现在让我们定义另一个绘制数据集和特定次数的最佳拟合多项式的函数。
def plot_polyfit(degree = 1):
p = polynomial_fit(degree) plt.scatter(X_train,y_train,label="Training set")
plt.scatter(X_test,y_test,label="Test set") curve_x = np.arange(min(x),max(x),0.01)
plt.plot(curve_x,p(curve_x),label="Polynomial of degree
{}".format(degree)) plt.xlim((-1,1))
plt.ylim((-1,np.max(y)+0.1))
plt.legend() plt.plot()
现在,让我们看看 1 次多项式会发生什么
plot_polyfit(1)
如您所见,1 次多项式比测试数据更适合训练数据,尽管它可能更适合。我们可以说这个模型没有从训练中正确地学习,所以它不好。
让我们看看在相反的情况下会发生什么,这是一个非常高次的多项式。
这是 7 次多项式的情况。
现在,多项式更好地拟合了训练点,但它对测试点完全错误。
更高的学位似乎让我们更接近过度拟合训练数据和测试数据的低准确性。请记住,多项式的次数越高,学习过程中涉及的参数数量就越多,因此高次多项式是比低次多项式更复杂的模型。
现在让我们清楚地看到过度拟合。我们有 12 个训练点,很容易证明过拟合可以用 11 次多项式来创建。叫做拉格朗日多项式。
现在很清楚会发生什么。多项式完全符合训练数据,但在测试集上失去了精度。它甚至没有接近测试点。
因此,多项式的次数越高,对训练数据的插值精度越高,对测试数据的性能越低。
关键词是“插值”。我们实际上不想插值我们的数据,因为这样做会让我们拟合误差,就像它们是有用的数据一样。我们不想从错误中学习,我们想知道错误中的模式。这就是为什么完美的拟合会在遵循相同的训练数据动态的看不见的数据上做出非常糟糕的模型。
如何避免过度拟合
怎样才能找到多项式的正确次数?交叉验证来了。因为我们希望我们的模型在看不见的数据上表现良好,所以我们可以测量我们的多项式相对于测试数据的均方根误差,并选择最小化该测量的程度。
使用这个简单的代码,我们遍历所有的学位,并计算训练集和测试集的 RMSE。
results = []
for i in range(1,len(X_train)-1):
p = polynomial_fit(i)
rmse_training = np.sqrt(mean_squared_error(y_train,p(X_train)))
rmse_test = np.sqrt(mean_squared_error(y_test,p(X_test))) results.append({'degree':i,
'rmse_training':rmse_training,'rmse_test':rmse_test})plt.scatter([x['degree'] for x in results],[x['rmse_training'] for x in results],label="RMSE on training")
plt.scatter([x['degree'] for x in results],[x['rmse_test'] for x in results],label="RMSE on test")plt.yscale("log")
plt.xlabel("Polynomial degree")
plt.ylabel("RMSE")
plt.legend()
plt.show()
让我们在下面的图中看到结果:
正如你所看到的,如果我们选择一个 2 次多项式,我们得到了测试集 RMSE 的较低值,这是我们的数据被采样的模型。
我们现在可以看看这样一个模型,并发现它实际上非常擅长描述训练和测试数据。
因此,如果我们想概括产生我们数据的潜在现象,我们必须在一个没有经过训练的数据集上交叉验证我们的模型。只有这样,我们才能对过度拟合更加安全。
结论
在这个简单的例子中,我们看到了过度拟合是如何影响模型性能的,以及如果我们对交叉验证不够重视,它会有多危险。虽然在避免过度拟合(如装袋)时,有一些非常有用的训练技术,但我们总是需要仔细检查我们的模型,以确保它得到了正确的训练。
评估推荐系统的详尽方法列表
如何使用不同的评价指标来评价推荐系统?
来源 bixabay ,作者 wokandapix
想象一下,我们已经建立了一个基于项目的推荐系统,根据用户的评分历史向他们推荐电影。现在,我们想评估我们的模型将如何表现。它真的擅长向用户推荐他们会喜欢的电影吗?它能帮助用户从我们系统中的大量电影中找到令人兴奋的新电影吗?这有助于改善我们的业务吗?要回答所有这些问题(以及许多其他问题),我们必须评估我们的模型。下面我提供了许多不同的技术来评估推荐系统。
首先,我将讨论基于数学的评估方法。这有助于我们从数以亿计的算法中减少可供选择的算法。
之后,我将讨论更多与业务相关的指标,以帮助选择最适合我们业务的技术。
最后,我将讨论几个现实生活中的场景,以帮助我们进一步理解现实生活中的推荐问题以及它如何随领域而变化。
基于精度和误差的方法
平均绝对误差
平均绝对误差是推荐者预测的值和用户给出的实际值之间的差的平均值。我所说的价值是指用户给出的评分。因此,我们首先通过减去每个用户的预测评级和实际评级来计算误差,然后我们取所有误差的平均值来计算 MAE。
让我们用一个电子表格中的例子来看看这一点。假设我们计算了电影《玩具总动员》的推荐分数,并希望评估我们的模型预测分数的准确性。下图显示了如何做到这一点。
Muffaddal 对电影分级的 MAE 计算
MAE 显示预测分数与实际分数相差多少。我们取绝对值(顾名思义)是为了取消负号,因为我们对正负分数不感兴趣,我们只想知道真实值和预测值之间的差异。
零 MAE 意味着预测值和实际值之间没有差异,模型预测准确。因此,MAE 越小越好。在我们的例子中,MAE 是 1.5,接近于零,表明我们的模型能够准确预测任何给定用户的电影评级。
下面是它是如何用数学形式表示的:
MAE 方程,来源维基
均方误差
均方误差类似于平均绝对误差,唯一不同的是,我们不是用误差的绝对值来抵消负号,而是对其求平方。
MAE 有助于惩罚结果,因此即使很小的差异也会导致很大的差异。这也表明,如果 MSE 接近于零,这意味着推荐系统确实做得很好,因为否则,MSE 不会这么小。
MSE 方程,来源维基
你能看出 MAE 和 MSE 的唯一区别吗?
MSE 还具有其他特性,尤其是在梯度下降的情况下。我不会在这篇文章中详述,但是你可以看看李因的文章来进一步探索 MSE。
均方根误差(RMSE)
MSE 有助于否定负号,但它放大了由于不同等级而无法与实际等级值进行比较的误差。在我们的电子表格中,MAE 是 1.6,但 MSE 是 4。
Muffaddal 对电影分级的 MSE 计算
我们可以很容易地理解和比较 MAE 与评级,模型预测的总体差异为 1.6,但我们不能说 4 也是如此,因为我们知道它与用户评级不在同一尺度上。这就是 RMSE 派上用场的地方。
在 RMSE,我们用 MSE 的平方根来标准化 MSE 的规模问题。这使我们的平均结果正常化,其等级与评级等级相同。
RMSE 方程,来源维基
你一定会问梅和 RMSE 有什么不同。有!。RMSE 重建了误差项,而梅没有。梅一视同仁地对待离群值和非离群值,而 RMSE 则不然。此外,RMSE 几乎总是比梅更伟大。Tumas Rackaitis 在他的 MAE vs RMSE 的文章中详细解释了这一点。
**你注意到了吗?**在我们的例子中,RMSE 也大于平均平均寿命,即分别为 2 和 1.6。
电影评分 MAE vs MSE vs RMSE,Muffaddal
决策支持方法
决策支持度量有助于了解推荐器在帮助用户通过选择好的项目和避免坏的项目来做出更好的决策方面有多大用处。两个最常用的指标是精确度和召回率。
精确
精度是相关的选定项目的数量。因此,假设我们的推荐系统选择 3 个项目推荐给用户,其中 2 个是相关的,那么精度将是 66%。
精确插图,来源 researchgate
精确是指在假设有比你想要的更多的有用项目的情况下,为用户检索最好的项目。
回忆
召回是被选择的相关项目的数量。因此,假设有 6 个相关项目,推荐器从中选择 2 个相关项目,那么召回率将是 33%。
回忆插图,来源研究门户
召回是为了不遗漏有用的物品。
精确度和召回率通常被用来理解推荐系统的性能。你可以查看 Giorgos Papachristoudis 的文章来进一步了解他们的细节。
受试者工作特征曲线
假设我们决定使用我们的基于项目的协同过滤模型向用户推荐 20 个项目。20 个项目列表可以有一半项目被正确预测,而另一半被错误预测。或者它可以有 90%的项目被正确预测,而只有 10%被错误预测。此外,改变推荐项目的数量将改变我们列表中正确和错误的项目数量。
如何确定推荐项目数的最佳阈值,才能得到最大的相关项目和最小的不相关项目?ROC 曲线可以帮助我们回答这个问题。
ROC 曲线有助于确定可以获得最佳结果的阈值。这是它的图形外观
ROC 曲线,来源 youtube
ROC 是正确预测项目(TPR)和错误预测项目(FPR)之间的曲线。如果目标是调整推荐器以识别其性能的最佳点,它会提供见解。你可以观看这个视频来更多的了解 ROC。
基于排名的方法
到目前为止,我们接触的方法允许我们理解从推荐系统获得的结果的整体性能。但他们没有提供这些物品是如何订购的信息。一个模型可以有一个好的 RMSE 分数,但是如果它推荐的前三项与用户不相关,那么这个推荐就没有多大用处。如果用户必须向下滚动来搜索相关的项目,那么推荐的首要目的是什么?即使没有推荐,用户也可以滚动来寻找他们喜欢的项目。
基于排名的评估方法帮助我们理解建议的项目如何根据它们对于用户的相关性来排序。他们帮助我们衡量项目的质量排名。
nDCG
nDCG 有三个部分。首先是“CG ”,代表累积收益。它处理这样一个事实:最相关的条目比有些相关的条目更有用,有些相关的条目比不相关的条目更有用。它根据项目的相关性对项目求和,因此称之为累积。假设我们被要求根据项目的相关性进行评分,如下所示
最相关分数=> 2
稍微相关分数= > 1
最不相关分数= > 0
如果我们将这些分数相加,我们将获得给定项目的累积收益。
CG 方程,来源 wiki
由 Muffaddal 计算 5 项的累积增益
但是 CG 并没有说明物品在列表中的位置。因此,改变物品的位置不会改变重心。这就是 nDCG 的第二部分发挥作用的地方,即“D”。
贴现累积收益,简称 DCG,惩罚列表中较低的项目。出现在列表末尾的相关项目是不良推荐系统的结果,因此该项目应该被扣除以指示模型的不良性能。为此,我们将项目的相关性分数除以其在列表中排名的对数。
DCG 方程,来源维基
5 个项目的贴现累计收益计算,由 Muffaddal
DCG 有助于排名,但假设我们正在比较推荐者的不同列表。每个列表的 DCG 将根据推荐者放置项目的位置而不同。当最相关的项目被放在推荐者的 20 个项目列表的第 10 个位置时,DCG 将会是什么,而当稍微相关的项目被排在第 11 个项目列表的第 10 个位置时,DCG 将会是什么。为了使 nDCG 的这个“n”正常化,第三部分开始发挥作用。
nDCG 将不同数量的项目列表的 DCG 值标准化。为此,我们根据相关性对项目列表进行排序,并计算该列表的 DCG。这将是完美的 DCG 分数,因为项目是按其相关性分数排序的。我们将所有列表的所有 DCG 分数除以这个完美 DCG,得到该列表的归一化分数。
nDCG 方程,来源维基
5 个项目的 n-贴现累计收益计算,由 Muffaddal
平均倒数排名
平均倒数排名(Mean reciprocal Rank),简称 MRR,关注的是哪里是推荐列表中的第一个相关项目。第一相关项目位于第三位置的列表的 MRR 将大于第一相关项目位于第四位置的列表。
MRR 取相关项位置的倒数并求和。如果相关项目位于项目列表上的位置 2 和 3,MRR 将为( 1/2+1/3)。
MMR 计算,通过 Muffaddal
这也表明,项目在排名中越高,惩罚越高,并且随着项目在列表中的下降,其惩罚降低。所以 58 号的相关物品无关紧要。
平均精度
Precision 有助于了解模型的整体性能,但不能说明项目的排序是否正确。简而言之,平均精度 AP 有助于衡量推荐模型中所选项目的排名质量。
它只计算推荐的相关项目的精度。
平均精度由 Muffaddal
假设我们的模型推荐 8 个项目,如上所述,其中 4 个是正确的,4 个是不正确的。我们取第一个相关项并计算它的精度,在我们的例子中是第一项,因此,它的精度是 1/1。接下来,计算第二个相关项目(项目 3)的精度。它的精度将是 2/3。因为从第 1 项到当前项,总共 3 项中有两项预测正确。我们将对所有相关项目进行同样的处理。最后,取精度列表的平均值来计算平均精度。
该模型的总体精度为 0.5,而平均精度为 0.427。较低的 AP 表示质量排名。
前 4 项相关时的平均精度是多少?与整体精度相比,其表现如何?
斯皮尔曼等级相关评估
Spearman rank correlation 计算模型如何对项目进行排序,以及它们应该如何排序的分数。让我们用一个例子来理解这一点
斯皮尔曼等级相关性的模型等级示例,作者 Muffaddal
假设我们的模型按照上图所示的顺序对项目(A 到 E)进行排序。然后,我们列出推荐项目的排名
Spearman 等级相关性计算,由 Muffaddal
上图中的“推荐者排名”列列出了项目相对于实际项目的排名。因此,“E”实际上排在第 5 位,所以我们将 add 5 存储在项目 E 的“推荐者排名”列中。我们对所有其他项目也是如此。
接下来,我们计算推荐者排名和实际排名之间的差异
Spearman 等级相关性计算,由 Muffaddal
现在,我们使用差值计算 Spearman 等级相关性,如下所示
穆法达尔的斯皮尔曼等级相关方程
Spearman 等级相关值,由 Muffaddal
Spearman 等级相关范围在 1 和-1 之间,带负号表示项目按相反方向排列。
您可以查看下面的文章,进一步探索 Spearman 等级相关性。
本指南将告诉你什么时候应该使用 Spearman 的等级-顺序相关性来分析你的数据,什么假设…
statistics.laerd.com](https://statistics.laerd.com/statistical-guides/spearmans-rank-order-correlation-statistical-guide.php)
其他方法
我们使用了不同的指标来评估推荐系统模型在预测、决策和搜集能力方面的性能。但是它们并不能帮助我们评估问题,比如模型建议的项目总数。或者如果模型推荐不寻常的东西,或者它只推荐与用户的过去历史相似的项目。让我们在本节中讨论这些方法。
新闻报道
覆盖率有助于衡量推荐者能够从总项目库中推荐的项目数量。假设我们有 1000 种产品,模型覆盖了不同用户的 800 种产品,那么这意味着我们推荐器的覆盖率是 80%,这还不错。覆盖范围可以进一步细分为项目类型。模型能够建议的填充项与非填充项的百分比。如果目标是向用户建议最大数量的项目,那么覆盖率可以是评估推荐器模型的非常有用的工具。
流行
某些项目主导用户偏好是正常的。这些是受欢迎的项目。同样正常的是,推荐者也大多推荐受欢迎的商品。这也不是一件坏事。如果我们希望我们的模型推荐受欢迎的商品,或者我们希望推荐者推荐不受欢迎的商品,这取决于我们。受欢迎程度有助于我们评估这一点。能够理解我们的推荐者建议了多少这样的项目可以帮助我们决定我们是否应该继续使用这个模型。
新奇
在某些领域,比如音乐推荐,如果模型向用户推荐相似的项目是可以的。但是即使这样,一次又一次地建议相似的项目也会导致糟糕的用户体验,因为用户可能想要探索新的和不同的东西。新奇有助于理解模型的这种行为。我们的推荐模型有能力推荐出人意料的商品吗?。当你在收银台向用户推荐商品时,这种新奇感可能没有用,因为用户会对他们购买的类似商品更感兴趣。但是,一个用户仍在探索网站的地方,建议一些完全新的和不同的东西可能是有用的,新鲜感有助于衡量这一点。
多样性
类似于新奇,根据领域和我们要推荐的项目,了解我们模型的多样性也是有用的。衡量我们的模型的建议的多样性是非常有用的。因为高度多样化意味着我们的用户将总是有不同的和多样化的东西来观看和消费。因此,对于我们总是想展示新东西的领域,多样性是我们追求的标准。
时间评估
人们的口味随着时间而变化。当你看一部电影时,你可能会给它打 10 分,但两三年后,你的评分可能会下降到 8 分或 6 分。这可能是因为你的品味变了,或者你变得成熟了,或者你现在和你给电影打 10 颗星的时候完全不一样了。有很多因素可以改变你对某样东西的喜好。考虑项目的时间效应也可以帮助我们建立和评估模型。网飞竞赛的获胜者在他们的模型中也有时间因素。考虑用户给出的每一个评分,而只考虑用户最近给出的评分,会对我们的模型预测用户在那个时间点可能喜欢什么的能力产生重大影响。在评估推荐系统的性能时,我们也应该考虑这个因素。
业务指标
除了衡量推荐系统的预测能力之外,衡量模型如何实现业务目标也非常重要,甚至更重要。任何模型,无论它有多复杂,都可以帮助支持业务,对吗?。最终目标应该是度量为之构建模型的业务度量。如果这种模式是为了增加收入,如果整合推荐系统后收入增加,那么这就是一个适合你的企业的推荐系统。如果模型的目标是改善应用内的体验,如果你看到每日活跃用户增加,那么你的模型的表现正是它被建立的原因。改善电子邮件活动,提高留存率,增加应用内参与度,如果一个模型能够实现它的构建,那么它就是一个好的推荐系统,否则你应该重新构建并重新评估它。
情景练习
无论我们选择什么方法来测试我们的推荐系统,几乎总是取决于我们试图解决的问题。我们需要深入理解我们正在为之构建模型的领域。以下是一些示例场景,帮助您理解评估模型的方法如何随着我们要解决的问题而变化。
请注意,下面讨论的问题可能有不止一个解决方案。我不会去详细说明,我会让你发现。
1-一家电子商务公司向您寻求帮助,希望建立一个模型,在他们的结账页面上推荐两件商品。他们的分析系统拥有大约 30%的用户购买历史和 10%的商品评级历史。你会用什么方法解决这类问题?RMSE,精密,MRR,nDCG 或任何其他方法?
2-一家在线音乐公司希望你建立一个模型,可以向用户推荐他们从未听过的新歌。他们还希望你显示系统推荐的每首歌曲的预测得分。该公司希望增加用户在网站上的平均时间。
3-你的任务是为一家医疗咨询公司建立一个模型,该模型可以根据用户面临的症状和问题向用户推荐最佳顾问。请记住,任何咨询师一次只能招待一个病人,所以向所有人推荐最好的服务是行不通的。此外,你不能向任何病人建议任何顾问。背景和地点也需要考虑。
4- ABC 健身房希望在他们的健身房播放可以激励里面的人的音乐。健身房对男性和女性开放,全天开放。健身房的老板告诉你,他们的客户群由不同背景的人组成。任务是推荐歌曲,考虑顾客的性别、背景、一天中的时间来播放可以激励他们的音乐,并取悦大多数人。
您将使用什么评估方法来测试模型的性能,以克服企业主面临的问题?
**提示:**要解决上述问题,你需要对该领域有很强的理解,并需要考虑业务的各个方面,以决定采用什么方法。
我强烈推荐查看 这个推荐人评估课程 如果你有兴趣学习和解决许多这样的现实生活中的问题。导师们不仅更深入地讨论了评估方法,还解释了许多业务场景以及如何应对它们。
结论
我们提到了一些评估推荐系统性能的方法。我们从讨论基于精度的方法开始,例如 MSE 和 RMSE。然后,我们研究了基于决策的技术,如精确度、召回率和 ROC 曲线。我们还讨论了如何使用 MRR、nDCG 和 AP 等排名方法来评估我们的模型如何对项目进行排名。除了数学方法,我们还涉及了其他方法,如覆盖面,新颖性,多样性和基于时间的方法。最后,我们看到了如何根据我们为之创建模型的业务目标来评估模型
但是不管你使用什么方法,永远记住它始于对我们要解决的领域和问题的深刻理解。有用的评估总是取决于问正确的问题。
相似读取
本指南将详细介绍基于项目的推荐系统的工作原理以及如何在实际工作中实现它…
towardsdatascience.com](/comprehensive-guide-on-item-based-recommendation-systems-d67e40e2b75d)
一种最大化精度的实验分配机制
最优分层随机分配
https://pix abay . com/photos/vaccine-chemist-注射器-秒表-4892059/
丹·万鲁宁
为什么这很重要
随机实验是因果推断的黄金标准:如果你想得到一个治疗效果的无偏(你的估计方法的平均值是真实值)估计,随机实验是最好的方法。
但是实验是昂贵的,你收集的数据越多,花费就越大。使用这篇文章中的方法,你可以提高你的实验精度,这样你就可以用更少的数据和更少的成本来测量效果。
如果你对实验感兴趣,我建议你也看看我的其他帖子
方法的高级概要
这篇文章概述了一种在随机实验中实现最佳分层的方法。
该战略如下:
- 使用实验前协变量,建立一个模型来预测你感兴趣的结果。
- 根据上一步中训练的模型的预测结果,对您的实验单位(您分配治疗的人群级别:此处区域)进行排序。
- 将治疗随机分配给预测结果最高的两个单元之一,以及预测结果第三和第四高的两个单元之一,依此类推,直到将治疗分配给预测结果最低的两个单元之一。
- 然后,为了测量治疗对结果的影响,回归结果~ b0 + b1 治疗+ b[2:N/2+1]对 _ 指标。最后一步中治疗指标的系数是治疗对结果的影响。
参见论文第 18 页
直观地说,这是分层随机分配,其中每一层是一对实验单元,它们对感兴趣的结果具有非常相似的预测值。
这个职位的其余部分将通过
- 用玩具数据将事物具体化的示例实验
- 最简单的分配和效果评估策略
- 最优策略
- 为什么协变量不如最优策略有效
示例实验
假设我们拥有一家专门从事狗旅行的公司。
https://pix abay . com/photos/dog-mountain-mombarone-clouds-190056/
我们想衡量一个电视广告对我们收入的影响。电视广告可以分布到不同的地理区域。为了衡量电视广告的影响,我们可以衡量(I)播放电视广告的地区和(ii)没有播放电视广告的地区之间的收入差异。
让我们建立一个玩具数据集来说明这个例子。
该数据集的关键要素是:
- 收入与协变量相关:人口。这种关系是非线性的。
- 如果该地区接受治疗,试验期的收入平均会高出 1%。这就是我们试图测量的效果。
散点图显示了这些元素:
我们还将创建一个助手函数,将实际观察到的收入添加到我们的数据中。
接下来,让我们转向一个简单的回归,可以衡量这种治疗效果。
测量效果
回归
为了衡量收入的相对变化,我们可以使用以下回归方法:
如果该区域接受了治疗,则为 1,否则为 0。
那么,β₁可以解释为治疗对收入的比例影响:如果一个单位接受治疗,收入将增加
100(1-e^β₁)% ≈ 100β₁%
这是我们对β₁的预期范围的一个很好的近似值(在我们的玩具数据中接近 1%)。
简单随机分配
作为第一个原则,我们需要随机分配。否则,我们可能会得到一个有偏差的测量。例如,如果我们决定将广告发送到前期收入最高的所有地区,那么当我们运行上述回归时,我们可能会看到非常大的治疗效果,因为我们将前期收入较大的效果归因于治疗。但是如果我们随机处理,就不会存在这样的混淆变量。
我们在这个实验中测量效果的最简单的方法是随机分配一半的地理位置来获取广告,然后运行前一部分的回归。
我们发现一个估计并不像我们希望的那样接近实际效果水平:当它是 1%的效果时,我们测量的是 2.2%的效果。
我们如何改变我们的分配机制来更精确地测量这 1%的影响?
最优分层分配
这篇文章旨在解决的关键问题是:我们如何分配哪些地区应该得到广告(治疗)以获得我们需要的数据来尽可能精确地估计广告的影响。答案是:分层分配,不同的阶层有相似的结果值。
让我们为流程的每一步创建函数。
- 预测结果,将具有相似预测结果的地理位置(单位)对分配给阶层(随机分配治疗的群体)
- 在层内随机分配治疗
- 衡量效果
预测结果和划分区域
首先,让我们制作一个使用模型来预测结果的函数。然后,将具有相似预测结果的区域(单元)对分配给相同的层。
层内随机分配
接下来,在每个层中,它将随机分配一半的单元进行治疗。
测量效果
最后,一个衡量效果的函数。在这里,我们可以运行一个回归,每个层都有虚拟模型,但是这相当于使用“plm”的层固定效应。
把它放在一起
让我们用这种最优分配方法重新衡量一下效果。我们将使用简单的回归来预测前期收入:
然后,我们将使用这个模型和我们创建的函数来测量效果。
现在,结果更接近我们期望测量的 1%!标准误差*比简单方法小一个数量级。
就是这个方法!简单,但功能强大!
https://pix abay . com/photos/flash-雷雨-超级细胞-2568381/
*请注意,我们使用回归分析得出的默认错误,因为它们显示了本文的关键点,但考虑到我们的不确定性来自赋值,随机化推断可能是一个更好的主意。参见这篇文章,看看如何做随机化推断。
这篇文章的剩余部分深入探讨了细节。
- 我们不能用协变量来完成同样的事情吗?
- 这种方法为什么有效?
协变量
让我们使用简单随机分配的数据,看看我们是否可以用协变量完成同样的事情:
所有这些结果仍然比优化分配差:如上所述,它们不太精确,点估计离真实值更远。为什么?
为什么优化分层分配是最好的
如果我们满足普通最小二乘法的一些标准假设(我们的结果和协变量之间的关系是线性的,单位之间不相互影响,治疗和影响结果的其他协变量之间没有相关性,homoskedastity—请参见我的 stats stackexchange 帖子了解关键假设和含义)治疗系数的 OLS 估计方差为:
分母中的总和是处理中的总样本变异。这可以通过将一半区域分配给治疗来最大化(并且它越高,我们的系数估计器越精确)。我们在所有的例子中都这样做了。
( 1 − R − t r e a t e d ) (1-R _ {-treated }) (1−R−treated) term 是除了治疗之外,不能被我们的模型的所有元素解释的治疗中的变化的百分比(如果你将治疗的回归作为所有其他协变量的函数,它是 1 减去 R)。这表明,如果你增加许多与治疗高度相关的特征,你的精确度就会降低。在我们的例子中,处理在所有情况下都是随机的,所以我们希望该项可以忽略不计(其他协变量不应该解释随机处理,所以 ( 1 − R − t r e a t e d ) (1-R _ {-treated }) (1−R−treated)应该接近 1)。
分子是回归的误差方差:如果我们的模型有更强的解释力,精度就会提高。这是我们的例子之间的关键区别。
- 在回归中只有处理项的随机分配表现最差,因为它不能解释模型中只有处理的大量变化。
- 有协变量的模型做得更好,因为它们可以解释模型中人口和/或前期收入的更多结果变化。
- 具有最优分配和固定效果(与地层指标相同)的模型效果最佳。这是因为考虑到人口和收入之间的非线性关系,预测前期结果的模型在预测后期结果方面做得最好。我们可以添加更灵活的协变量函数来解释这种关系,但预测结果的模型可能会做得更好(特别是如果我们使用更灵活的模型,如随机森林)。
有协变量的模型被认为更差的另一个原因是因为回归产生方差加权平均处理效果:见本文第 477 页。当我们使用纯随机分配(非优化分层)时,我们仍然可能将相对更多的控制或处理区域分配给不同水平的协变量。在最终测量中,处理和对照水平更均衡的协变量水平(各约 50%)将被赋予更大的权重。优化的方法避免了这一点,因为它确保我们将总是在每一对中分配一半的治疗和一半的控制,这样所有的协变量空间将大致相等地计数。
题外话:倾向得分
你不应该使用倾向分数来创造随机的阶层。上面我们预测了感兴趣的结果,而倾向评分使用过去的数据预测治疗。使用倾向分数来匹配最终会在您的数据中产生更多的不平衡和更不可靠的结果。详情见此视频:
如果你对实验感兴趣,我推荐你也看看我之前的帖子:所有数据科学家都应该知道的实用实验基础。
对可解释人工智能的内容、原因和方式的解释(XAI)
以下是我在 2019 年 11 月多伦多机器学习峰会上的一次演讲的书面摘要。
现代人工智能系统越来越有能力解决现实世界的问题。然而,一些人工智能系统的黑箱性质,给出没有理由的结果,阻碍了人工智能的大规模采用。根据普华永道的年度调查,绝大多数(82%)的首席执行官同意,基于人工智能的决策要被信任,它们必须是可解释的。随着人工智能成为我们现代世界越来越不可或缺的一部分,我们需要理解它为什么以及如何做出预测和决策。
这些为什么和如何的问题是人工智能领域的主题。像人工智能本身一样,XAI 不是一个新的研究领域,人工智能理论和应用的最新进展给解释它的努力带来了新的紧迫性。我在 TMLS 19 上的演讲基于我之前发表的一系列博客文章。该系列探索了 XAI 领域的各个方面,包括它是什么,为什么它很重要,以及如何实现它。
在这里,我不是重复本系列的内容,而是对本系列的五个部分进行概述,并推荐感兴趣的读者进行详细的讨论。
可解释人工智能的原因
这一部分概述了 XAI 研究的一些最重要的驱动因素,如建立信任、法规遵从性、检测偏差、人工智能模型泛化和调试。
该交代什么艾
这一部分从现有定义、解释用户角色和给定应用的重要性、可能的权衡以及超出人工智能社区的解释研究等方面深入探讨了解释人工智能模型的真正含义。
如何解释人工智能:预建模可解释性
可解释性在人工智能发展的三个主要阶段有不同的含义,即建模阶段之前、期间和之后。这一部分着眼于在建模阶段之前实现可解释性。这包括审查一套方法,以便更好地理解和记录用于建模的数据集。
如何解释人工智能:可解释的建模
人工智能模型可以以可解释性和典型的预测性能为目标来开发。这一部分回顾了实现可解释建模的几种方法,包括采用固有可解释模型、混合模型、联合预测和解释,以及通过正则化和架构调整的可解释性。
如何解释人工智能:后建模可解释性
绝大多数 XAI 文学作品都专注于从预先开发的模型中提取解释,以便更好地理解它。这一部分提出了一种新的后建模可解释方法论的分类。这种分类法然后被用作回顾相关文献工作的基础结构。
XAI 在 H2O.ai
我有幸在 H2O.ai 担任面向客户的数据科学家,h 2 o . ai 是 AI 和 ML 领域的开源领导者。我用了一部分时间来概述 H2O.ai 的企业自动机器学习平台,即无人驾驶 AI ,特别是它的机器学习可解释性 (MLI)能力。
XAI 的未来
我以三个预测陈述了我对 XAI 前景的看法,以此结束了我的演讲。首先,我预计我们将会看到更多来自人工智能社区之外的解释研究的知识注入。其次,我讨论了 XAI 最佳实践在未来的出现。最后但并非最不重要的一点是,我主张未来在设计的可解释性方面做更多的工作,而不是目前占主导地位的后可解释性范式。
在 19 年的 TMLS 上做了一个关于 XAI 是什么、为什么和如何的演讲,座无虚席
对可解释人工智能的内容、原因和方式的解释(XAI)
活动讲座
巴哈多·卡莱吉| TMLS2019
来自多伦多机器学习峰会的演讲:【https://torontomachinelearning.com/
关于演讲者
Bahador Khaleghi 是 H2O.ai 的客户数据科学家和解决方案工程师。他在过去 13 年中积累了独特的技术背景,涉及广泛的学科,包括机器学习、统计信息融合和信号处理。Bahador 在滑铁卢大学获得 CPAMI 博士学位。在过去的六年中,他积极参与了 R&D 工业项目的各个领域,包括远程信息处理、移动医疗、预测性维护和客户分析。作为 Element AI 可解释性团队的(前任)技术负责人,他目前专注于开发新的方法,以增强 AI 解决方案的透明度、可信任度和可访问性。"
关于谈话
“现代人工智能系统越来越有能力解决现实世界的问题。然而,一些人工智能系统的黑箱性质,没有理由地给出结果,正在阻碍人工智能的大规模采用。根据普华永道的一项年度调查,绝大多数(82%)的首席执行官同意,要让基于人工智能的决策可信,它们必须是可解释的。随着人工智能成为我们现代世界越来越不可或缺的一部分,我们需要理解它为什么以及如何做出预测和决策。这些关于为什么和如何的问题是可解释人工智能或 XAI 领域的主题。像人工智能本身一样,XAI 不是一个新的研究领域,人工智能理论和应用的最新进展给解释它的努力带来了新的紧迫性。在这次演讲中,我们将介绍 XAI 的技术概况。演讲将涵盖 XAI 的三个关键问题:“这是什么?”,“为什么重要?”,以及“如何才能实现?“.“XAI 是什么”部分深入探讨了从现有定义、解释用户角色和给定应用的重要性、可能的权衡以及超出人工智能社区的解释研究等方面解释人工智能模型的真正意义。在 XAI 的“为什么”部分,我们探索了 XAI 研究的一些最重要的驱动因素,如建立信任、法规遵从性、检测偏差、人工智能模型泛化和调试。最后,在“如何 XAI”部分,我们讨论了如何在人工智能解决方案开发的建模阶段之前、之中和之后应用可解释性原则。特别是,我们引入了一种新的后模型解释方法的分类,然后我们利用它来探索大量的 XAI 文学作品。”
数据库管理初探
理解大数据
平衡安全性、信息完整性和 UX
图片来自凯文·Ku(ikukevk ),获得知识共享许可
原子性、一致性、隔离性和持久性
数据库管理有许多细微差别,这些差别决定了高效数据库和非结构化数据存储库之间的区别。索引的主要目的之一是减少在数据库环境中查找所需信息所需的步骤。在给出的一个例子中,一个数据库管理器优化了索引搜索,能够将一个查询的步骤数从 300,000 减少到 30(文泽尔,2020)。这种巨大的改进只是索引在提高大型数据库查询效率方面的一个例子。
索引有用的另一个原因是它使查询结果更加准确。在索引已经被充分定义并且子组树已经被适当地阐明的情况下,在该上下文中的查询将比没有被适当索引的数据库中的相同查询产生更准确的搜索结果。在使用一副牌的例子中,通过创建两个级别的子组来定义不同的类别,使用索引将查找特定牌所需的翻牌次数从 26 次减少到 9 次(文泽尔,2020)。
B+树是细分数据库以建立索引类别的标准方法(文泽尔,2020)。在建立操作节点结构,然后有索引的数据由页面,B+树使得有可能大大减少与数据库查询相关的时间和精力(文泽尔,2020)。
虽然数据库索引使查询更有效,但在 B+树应该索引多深的问题上存在收益递减点。在大多数数据库中,管理员或经理不会索引每个列和表,因为这将导致在定义索引上花费过多的时间。数据库管理员通常会尝试找到最佳的分析级别,以优化查询速度,而不会花费太多时间来定义数据库中的级别。每个数据库都是独一无二的,因为数据的使用将特定于用户的上下文。这将导致需要确保被访问的每个数据库都是专门为用户及其期望的需求而索引的,而不是任意地将每个数据库索引到每个列、表和单元格。
网络数据库管理系统
关于操作数据库管理系统,网络有许多优点和缺点。由于 HTML 是一种无状态协议,它在没有先前请求的记忆的情况下运行,以处理分配给内存的有限资源(Begg,2014)。这给 DBMS 协议如何操作的一般需求带来了障碍。此外,Web 的动态特性使得 DBMS 比在内部网或局域网中运行的 DBMS 更容易受到恶意行为者的攻击。虽然网络的动态特性可能是一种风险,但它也使用户比独家接入点更容易访问数据库。
使用 Web 操作 DBMS 的另一个好处是轻量级协议防止了硬件使用中不必要的膨胀。Web 编程的性质导致 DBMS 协议必须绕过 Web 的限制,因此副产品是对用户来说更灵活的产品,而不增加硬件需求。Web DBMS 的另一个好处是语言之间的互操作性。将 HTML 与多种其他语言结合使用来创建 DBMS 的情况并不少见。这种互操作性在网络的限制下创造了更多的动态能力。
网络数据库管理系统的一个缺点是互联网的可靠性(Begg,2014)。如果数据库管理系统只能通过网络访问,而互联网连接断开,则数据库管理系统不起作用。随着智能手机的普及,互联网接入变得越来越普遍,过度依赖网络数据库管理系统对大多数企业来说可能是一个太危险的风险。
虽然在现代,企业完全在封闭的网络上运营是不现实的,但明确划分非军事区和军事化区,使敏感数据不会不必要地进入 Web DBMS,这将是有益的。由于 Web DBMS 可用于不太敏感的数据,因此企业有理由将 Web DBMS 用于低级别操作以减少开销,同时仍然建立封闭的网络来保护敏感数据。这种组合获得了两种方法的优点,同时又不忽略任何一种方法的优点或缺点。
在某些特定的情况下,可扩展标记语言(XML)比超文本标记语言(HTML)对构建的功能更有用。在用户需要对象持久性的情况下,由对象产生的或为对象产生的数据存储在对象中,XML 可能是用户的更好语言。此外,用户的需求将决定是否使用 XML 作为本地 XML 数据库(NXD),或者是否有一个关系数据库管理系统(RDBMS)用于创建一个层来存储数据版本,以便在修改时不会被破坏(Westphal,1999)。
虽然这种差别看起来微不足道,但在利用 RDBMS 和 NXD 方法之间存在着显著的功能差异。在使用 NXD 方法时,应用层 UI 中表示的数据与 XML 数据层中的数据相同。这种方法与 RDBMS 的不同之处在于,至少有一种其他语言用于修改和表示 XML 数据库中的数据。RDBMS 可以使用多种语言来处理 XML 数据库,因为开发人员可能会选择使用多种语言来实现项目所需的功能。虽然 XML 足以显示数据并实现表示数据的基本功能,但 RDBMS 在执行复杂的事务或分析数据时会更有效,而这在 XML 层中是无法实现的。
使用每种方法的利弊将严格取决于用户的功能需求和开发人员为了用户的利益利用每种方法的不同方面的能力。NXD 方法将为用户提供更简化的数据访问,并且很可能使用更少的计算资源来访问数据库。另一方面,在用户需要更多的功能分析或数据点之间的事务关系而不必破坏或修改数据库中的数据的情况下,RDBMS 方法将是有益的。NXD 不适合分析或事务,RBDMS 在对象持久化方面也不太有效,所以这是开发人员必须权衡用户需求的地方。
商业智能
阐明商业智能(BI)、数据挖掘、数据仓库和在线分析处理(OLAP)之间的区别以及这些实践的重叠之处是很有用的。虽然 BI 包括利用这些实践的不同方面来生成运营的整体视图,但采矿和仓储是基础架构的基本方面,必须存在才能生成有用的 OLAP 报告。此外,这三个要素必须同时存在,以便为决策支持系统(DSS)提供准确的数据。
为了理解这三个要素是如何协同工作的,理解它们正在解决的问题将是有益的。员工遍布全球的企业级组织必须在不同分支机构之间拥有一致的数据存储库,以减少冗余工作,并需要这种类型的数据完整性来保持日常运营。除了对数据完整性的这种需求,分支机构之间的连接性作为一种必要性,成为潜在安全漏洞的主要风险(周,2019)。由于这些看似矛盾的需求,有必要划分组织内的数据流和分析,以使数据管理更易于访问,同时保护组织流内的敏感数据(周,2019)。
在这种情况下,组织内寻求分析客户或产品数据的人的需求将不同于寻求分析员工之间的数据流以提高效率的经理的需求(Begg,2014)。在建立统一的 BI 接口时,许多组织可能需要独立访问 OLAP、数据仓库和 DDS 应用层,以便在企业范围内运行。正是在这种理解的背景下,可能严重依赖数据仓库的人力资源部门的需求将在功能上不同于市场营销部门,市场营销部门可能需要更多的 OLAP 或数据挖掘访问,而不是对数据仓库本身的访问。
此外,决策支持系统需要对所有这些要素进行高级访问,以便为决策者提供做出明智决策所需的适当信息。虽然可以在不参考数据仓库的情况下做出关于 OLAP 数据的决策,但是对运营的潜在影响使得有必要访问所有相关信息,以确保减轻所有可避免的风险。
模式和无模式数据库
NoSQL 的讨论本质上解决了关系数据库和无模式数据库之间的差异。虽然存储和分析数据的两种方法各有其用武之地,但是在无模式数据库比关系数据库更合适的情况下,提供一个环境还是很有用的。
阐明无模式数据库优点的一种方法是查看关系数据库的缺点,以确定无模式方法是否提供了一些更好的功能。关系数据库方法最广为人知的缺点之一是,当数据在内存状态和数据库状态之间移动时,需要经历格式更改(Fowler,2012)。当有时间开发一个模式并在状态之间移动数据以正确分析它时,这种方法很有用,但是在数据移动很快并且需要更频繁地根据其他数据集进行分析的情况下,这种方法就不合适了。虽然无模式数据库对于金融服务来说可能不是最好的方法,但是这种方法在有重叠开发团队的环境中可能更有益,在这种环境中,无模式数据库采用 scrum 方法。
在一个 NoSQL 部署的上下文中,这意味着在一个开发项目中多个部门使用,与数据的交互需要通过一个单层应用程序来防止数据不一致。此外,处理数据库的管理员有必要阐明操作协议,以便冗余数据不会造成不一致或破坏数据完整性。这成为无模式数据库的最大弱点之一,因为如果从多个应用程序接口访问数据库,数据完整性会很快被破坏(Fowler,2012)。正是由于多个应用程序接口容易导致冲突,开发人员有时会选择使用单个 web 服务接口作为 NoSQL 数据库和多个应用程序之间的中间层。这种方法为用户提供了 NoSQL 数据库的灵活性,减少了由于不兼容的应用程序层而导致数据损坏的可能性。
当将分布式数据库管理系统与集中式数据库管理系统进行比较时,使用分布式数据库有一些明显的好处和缺点。描述 DDBMS 局限性的一个框架是 CAP 定理,它指出在一致性、可用性和分区容差这三种状态之外;DDBMS 一次只能有三个状态中的两个(Sadat,2018)。
分区容差是部署在野外的数据库的一个不可或缺的方面,因为它表明故障节点不会影响数据库网络中的任何其他分区(Sadat,2018)。在具有牺牲可用性的高分区容差的系统中,通过代理,数据库将更加一致,因为单个节点将具有减少的容量,以使节点受到外部参与者的危害(Sadat,2018)。
集中式与分散式并发控制
虽然集中式数据库有其优势,但分布式数据库的优势之一是与集中式数据中心相比接近 100%的正常运行时间,集中式数据中心经常不得不中断访问以完成系统更新(Sadat,2018)。此外,分散式系统比集中式系统更容易横向扩展,这使得用户更容易获得更强大的处理能力,而不会增加进入的财务障碍。
另一方面,用户可能需要一个高度可用且抗分区的分布式数据库。在这种情况下,并发输入可能会导致冲突或混乱的输出,这并不代表记录条目的时间一致性,但记录将对用户高度可用(Sadat,2018)。
考虑到 CAP 定理,分布式数据库方法可能更适合协作工作沙箱这样的应用程序。这可能以电子表格或公告板的形式出现。这些允许输入、输出和分布式访问记录的信息交换类型为许多不同类型的团队提供了在这种类型的数字空间中协作的机会。相比之下,其他类型的全球交易需要更加集中,如财务记录。财务记录可能会跟踪世界各地多方之间的交易,但需要以一种使集中式 DBMS 成为更合适的方法的方式来维护和监控数据库。
对比在乐观并发数据库和保守并发数据库上执行嵌套事务的不同之处,可以发现在每种情况下都有不同的优点和缺点。为了理解优点和缺点,将不同类型的并发控制之间的细微差别放在上下文中是很重要的。在乐观并发控制场景中,事务将被假设为不会破坏数据库的完整性,并且即使有多个事务同时发生,也将被序列化(Block,2018)。这与保守的并发控制方法形成对比,后者为每个事务打上时间戳,以确保数据序列化时不会发生冲突。
在处理大量事务时,乐观方法会快得多,在单个嵌套事务的情况下,更新最终数据库会比保守的并发方法更快。另一方面,保守并发方法可能会产生更准确的数据吞吐量,而不会导致数据库需要频繁地回滚到以前的状态。虽然这种方法会产生更准确的数据库,但对于需要为大量用户存储不断变化的数据的数据库来说,这种方法并不理想。
虽然乐观并发方法更适合于高频率和高容量的事务场景,但是假设传入的数据不会导致数据库状态的冲突,这使得它更容易受到垃圾邮件攻击,在垃圾邮件攻击中,数据库的功能受到恶意尝试的阻碍,恶意尝试使数据库回滚其状态,使其陷入永久的回滚循环中。人们可能会查看所存储数据的上下文,以确定采用哪种方法可能更合适。例如,使用保守的并发方法来更新处理金融交易的数据库可能更合适。对数据库使用乐观并发方法的应用程序层的一个例子可能是社交媒体网站评论中的数据。这种类型的方法在数据库需要相当频繁地更新的环境中是有用的,其中多个条目在一个层中同时发生,不允许用户创建可能触发回滚的危险状态改变。
两阶段提交(2PC)协议和三阶段提交(3PC)协议是在数据库中提交和验证事务的两种不同方法。2PC 旨在建立一种准备分布式数据库以更新新事务信息的方法(Atif,2009)。然而,最初的方法有一个设计缺陷,导致系统范围的资源冻结,这就是所谓的阻塞(Atif,2009)。在 2PC 方法中,如果一个节点发生故障或一个事务受到损害,使得参与节点处于不确定状态,那么参与节点将锁定它们的资源,直到从协调节点接收到下一个消息(Atif,2009)。
2PC 的另一个问题是状态不一致的问题,如果在一个节点处于预提交阶段并失败时发生回滚,可能会出现这种问题(Atif,2009)。这一点上的失败会导致系统显示提交和中止命令,从而产生不一致的全局状态(Atif,2009)。
引入 3PC 是为了通过建立一种称为预提交的新状态来解决这些问题(Atif,2009)。预提交状态的引入增加了另一层一致性,这样,在进入提交写阶段之前,分布式数据库都同意预提交就绪。相对于 2PC,3PC 提供了更多终止交易的机会。由于 2PC 只允许提交或中止,所以实际上只有一次机会可以主动终止事务,而不会导致节点故障,从而创建系统范围的回滚。另一方面,3PC 将给出在预提交状态下终止事务的机会,使得网络不会移动以提交事务。
即使在提交前状态过去之后,理论上仍有机会通过引起系统范围的回滚来终止事务。虽然系统范围的回滚并不是最佳的,但是下一个完全断电的情况会带来确切的场景。在 2PC 中,如果没有活动的提交,那么电源故障可能不会导致问题。但是,断电前队列中的任何类型的中止或提交命令都可能导致启动时的阻塞问题,并且传输中的数据可能会永远丢失。理论上,3PC 预提交状态应该使其在断电的情况下更能抵抗阻塞问题,如果断电之前有任何节点处于预提交状态,则所有节点都可能回滚。
骨料建模
聚合模型是一种有用的模型,其中聚合被视为单个数据捕获单元。定义聚合点的所有数据都被视为键值,随后被视为键值对(Fowler,2012)。代表客户及其所有订单的聚合就是一个例子(Fowler,2012)。通过固有的数据聚类,聚合的关系建立了要引用的数据点。当试图在存在于两个单独的聚合中的数据之间建立连接时,这种排序会出现问题。聚合模型对于检查聚合中的数据非常有用,但是当需要检查更高级别的关系时,就需要对该模型进行修改。
列族聚合建立了一组称为“列族”的列,然后通过行标识符分解列,为每一行提供一个特定的数据值(Fowler,2012)。键值数据库允许用户在一个键下存储数据。相比之下,文档数据库为用户提供了在数据库中存储文档的能力,而没有结构上的限制(Fowler,2012)。
聚合模型提供了一种存储元数据的方法,以定义 riak 或键值存储中的聚合之间的关系(Fowler,2012)。这种更高级的元数据定义能力使得面向聚合的数据库能够保持聚合的原子性,而不会限制用户在单独的聚合之间建立关系。
总的方法有优点也有缺点。最重要的好处之一是能够存储大量紧密相关的数据。如前所述,将一个客户的所有订单保存在一个聚合中,同时将不同的客户分成不同的聚合,这将对商家有利。此外,riak 选项将使商家能够通过元数据层在聚合之间分析客户的购买或偏好。另一方面,与明确专用于关系分析的关系数据库相比,这种类型的方法可能会降低聚合之间的及时关系分析的能力。
机器学习
有监督的和无监督的机器学习在数据分析的环境中都有它们的位置。有监督的 ML 最适合于期望的结果具有一组研究主题已知的度量的情况(Lieber 等人,2013)。例如,如果一个人希望预测天气模式或交通模式等事件的可能性。假设一个研究人员拥有 ML 程序可以分析模式的预先存在的数据。在这种情况下,该算法可以进行预测分析,提供最准确的数据来创建预测。
无监督最大似然法最适合于没有已知模式可供观察的情况。ML 算法将发现可能存在的任何重要的非随机数据。像可视化、聚类、离群点检测或降维这样的无监督 ML 方法通常被用作数据挖掘复杂数据集的第一线分析。这种类型的 ML 更适合于用户行为分析,以寻找涌现模式或在数据湖中寻找相同类型的涌现模式。
在分析这些 ML 方法时,每种策略都有简单明了的应用,其中一种策略比另一种策略更有优势。与无监督 ML 相关的一个问题是算法可能膨胀,并在资源上产生不平衡的负载。如果一个无监督的 ML 算法没有以某种方式被限制,它可能会使资源过载,从而停止查询或使系统完全崩溃。相反,受监督的最大似然算法能够发现受其限制参数阻碍的数据。
在每种方法的这两个显著缺点之间,有可能利用监督和非监督串联来使监督 ML 更健壮,同时控制非监督 ML 对资源的利用。此外,ML 云服务的可用性使得利用无监督和有监督的 ML 更加合理。云服务使组织能够使用这些 ML 平台,而无需扩展基础设施,特别是为了这个目的。除非一个组织正在开发一个需要板载 ML 的应用,否则云 ML 平台可能是许多组织最可行的选择。
在平衡安全性和可用性时,保护系统和增加用户体验难度之间有一条细微的界限。跨越这条线并使用户体验更加困难的一个问题是,用户通常通过绕过迟钝的安全措施来应对这种情况。最终,如果用户觉得安全性太不方便并绕过他们,那么安全团队会无意中降低用户的安全性,因为目标是使系统以最安全的方式可用。如果可用性受到阻碍,那么无论平台在理论上有多安全,安全措施都是一个问题。
参考资料:
Atif,M. (2009 年 10 月)。两阶段提交和三阶段提交协议的分析和验证。2009 年新兴技术国际会议(第 326-331 页)。IEEE。
Begg,T.C. C. (2014)。数据库系统:设计、实施和管理的实用方法。[科罗拉多技术大学(CTU)]。从https://coloradotech.vitalsource.com/#/books/9781323135761/取回
Block,S. (2018 年 6 月 10 日)。保守并发与乐观并发控制。检索自https://Shannon block . org/conservative-concurrency-control-vs-optimistic-concurrency-control/
埃兹尔切尔文,p .,奥尔德威什,a .,,范范莫塞尔,A. (2018,6 月)。使用区块链的非阻塞两阶段提交(第 36-41 页)。第一届分布式系统加密货币和区块链研讨会会议录。从 https://doi-org.proxy.cecybrary.com/10.1145/3211933.3211940取回
P.J.S. M .福勒(2012 年)。 NoSQL 蒸馏:多语言持久性新兴世界简要指南。[科罗拉多技术大学(CTU)]。从 https://coloradotech.vitalsource.com/#/books/9781323137376/取回
利伯,丹尼尔&斯托尔佩,马可&康拉德,贝内迪克特&德乌斯,约亨&莫里克,卡塔琳娜。(2013).基于监督和非监督机器学习的互联制造过程质量预测。普罗塞迪亚·CIRP。7.193–198.10.1016/j.procir
赖默,M. (1983 年 10 月)。用预测乐观并发控制解决幻影问题。在 VLDB(第 83 卷,第 81-88 页)。
萨达特,S. (2018,4 月 24 日)。CAP 定理和分布式数据库管理系统。中等。检索自https://towards data science . com/cap-theory-and-distributed-database-management-systems-5c2be 977950 e
Shannonblock3,A. (2018 年 7 月 07 日)。持久性机制的比较(XML、RDBMS、NXD)。2020 年 10 月 8 日,从https://shannonblock.biz/?p=62检索
英国文泽尔(2020 年)。数据库索引解释。从 https://www.essentialsql.com/what-is-a-database-index/取回
韦斯特法尔河(1999 年 9 月 8 日)。使用 XML 实现对象持久性。检索于 2020 年 10 月 8 日,来自https://www.xml.com/pub/a/1999/09/serialization/index.html
卓,中国水电能源股份有限公司(2019)。OLAP 开发平台的探讨。 DEStech 计算机科学与工程汇刊,(aicae)。
Python 中的一个可扩展进化算法实例
学习如何用不到 50 行代码从头开始编写一个简单的进化算法,供您的项目使用。包括两个例子!
Johannes Plenio 在 Unsplash 上拍摄的照片
E 进化算法是解决计算问题的特殊方法,比如最优化问题。它们通常会在合理的时间内产生非常好的结果,而无需我们在特定问题的属性上花太多心思。通常,我们只需要调整一些参数,然后让一个相当通用的框架运行,给我们带来一个解决方案。在本文中,您将看到如何用 Python 实现这样一个通用框架。
这在处理极其困难的问题时尤其有趣,比如 NP-complete 的问题。这些都是现实生活中的相关问题,许多公司每天都必须解决这些问题,而我们却不知道任何有效的算法。其中一个问题是旅行推销员问题 (TSP)的优化版本,其表述如下:
一个推销员想在 n 个城市销售他的商品。他从城市 1 开始,按照某种顺序访问其他 n-1 个城市中的每一个,恰好一次,然后再次返回城市 1。为了缩短旅行距离,游览城市的最佳顺序是什么?
我们稍后将再次讨论这个问题,作为应用我们的进化算法的一个重要例子。但在此之前,让我们看看什么是进化算法,以及如何将它们应用到一个简单的例子中。
如果你只是想看代码,访问我的 GitHub 页面!;)
一个有趣的例子:MarI/O
进化算法的一个有趣的应用是由 Seth Bling 基于“简洁”的论文构建的 MarI/O。一个复杂的神经网络架构是使用进化算法从零开始构建的,以玩经典的超级马里奥世界。怀旧开始了。
进化算法
我们现在将看到如何开发一种进化算法来解决一个简单的函数最大化问题,即我们想要找到一个输入 x ,它最大化给定函数 f 的输出。例如,对于 f(x,y)=-(x +y ) ,唯一的解将是 (x,y)=(0,0) 。
该算法可以很容易地适用于解决 TSP 和其他问题。但是首先,让我们看看进化算法实际上是什么。
动机
进化算法被设计成类似于自然界中发现的进化。其中,这三个概念是进化的核心:
- 有一群个体。
- 个体可以繁殖和死亡。任何这些事情的发生都是由其适应度决定的。适应度越高,个体的属性(DNA)在群体中停留的时间就越长,要么是个体本身,要么是其后代。
- 个体可以变异,也就是稍微改变他们的属性。
我们可以使用这些概念来创建一个元算法,,即一个在内部使用其他算法的算法,我们还没有指定*、*来解决我们的问题。别担心,我们会立刻让它充满生机。
元算法
- 随机生成初始个体群体。
- 评估群体中每个个体的适合度。
- 你想重复多少次就重复多少次:
a)选择健康指数好的个体进行繁殖。
b)让他们产生后代。使这些后代变异。评估群体中每个个体的适合度。
f)让适应值不好的个体去死。 - 挑选适应度最高的个体作为解。
等等,这个挺笼统的吧?有许多事情必须详细说明。
有哪些个体?
第一种群有多少个个体,它们是如何产生的?
哪个体能分?多少父母生育多少后代?具体是怎样的?
如何变异?有多少人死亡?多长时间重复一次?
现在让我们用最大化一个函数的问题来说明我们如何具体实现一个元算法。
一个简单的开始例子
让我们以区间[0,4]上的函数*f(x)=-x(x-1)(x-2)(x-3)(x-4)*为例。我们希望找到一些值来最大化这个函数。一个潜在的问题可能是 1.4 左右的局部最大值,这是我们不想看到的!
x 最大 f 约为3.6,最大值也约为 3.6。
让我们看看能否用进化算法重现这一点。所以,让我们开始回答所有未解决的问题。
有哪些个体?
个体是总是 潜在解决问题的年代。
在我们的例子中,在 0 和 4 之间,因为我们只考虑这个区间上的函数。这个很简单,对吧?不会比这更难了,我保证。
第一种群中有多少个体,它们是如何产生的?
个体的数量是一个超参数,你要补上。如果您不知道解决方案是什么,请尽可能随机地选择初始群体。
在我们的例子中,我们使用 10 个随机个体,随机含义为在 0 和 4 之间均匀抽取的数字,如何?
我希望使用均匀随机元素是一个好的选择,因为我们可以很好地覆盖整个解空间。例如,如果我们使用平均值为 1.4 的正态分布,也许我们会将我们的解决方案推至 1.4 左右的错误局部最大值。
我已经从个人 0.596,1.067,1.184,1.431,1.641,
1.792,2.068,2.495,3.169,3.785 开始。
哪个健身分?
这个我们也要编一个。我们的解决方案应该具有最高的适应性分数。
我们想最大化我们的函数 f ,所以我们可以只使用我们的函数 f 本身。
最右边的个体具有大约 3.1 的最高健康分数。一些个体具有大约 1 的健康分数,三个个体甚至具有负的健康分数。
多少父母生育多少后代?具体是怎样的?
这个我们也要编一个。所有的一切。
在我们的例子中,我们总是可以用两个个体产生一个后代。我们也可以让他们生产更多,但让我们从这里开始。所以,如果我们有两个个体**(也叫父母),他们的后代可能就是他们的平均值。例如,1.1 和 3.5 的后代可能是 2.3。总的来说,让我们产生三个孩子,总共使用六个不同的父母(即每个父母只有一个伴侣)。**
再说一遍,这些都是我武断决定的事情。你也可以使用其他策略来完成这一步!每个后代使用一个或三个父母,使父母得到五个孩子,并循环播放。
具有最高适合度的六个个体是数字 1.792、1.184、3.169、1.641、1.431 和 3.785(按照适合度的递增顺序)。现在,让我们假设这个列表中的两个邻居得到了后代:
- 1.792 与 1.184: 1.488
- 3.169 与 1.641: 2.405
- 1.431 与 3.785: 2.608
生命的奇迹!
如何变异?
从概率上改变后代。这是一个很好的方法,可以在不同的地方探索更多可能的解决方案,不要确定性地走错路。
在我们的例子中,我们可以只给每个后代加上高斯噪声**。也许零的平均值和 0.25 的**标准差是可以的。另外,请记住:****
个人必须是潜在的解决方案!所以,变异不能把孩子推出可行区间[0,4]。如果发生这种情况,请将孩子设置到距离间隔最近的边缘。
突变后,橙色点有所移动。
有多少人死亡?
你喜欢多少就有多少。也许在不同阶段保持相同的人口规模是好的,因为否则人口规模可能会爆炸或者每个人都会在某个时刻死亡。
因为我们现在有 13 个个体,让他们中的 3 个死去,我们最终又有了 10 个。让我们挑选出适应度最差的,分别是老个体 0.596 和 2.495 以及新创建个体 2.121 。😔
生命的循环。
多久重复一次?
你喜欢多久就多久。只是有时检查,直到你看到解决方案不再变得更好。
也许让我们修正 50 个纪元,看看会发生什么。在我们的人工进化一路成功后,我们可以检查所有的个体,选择得分最高的一个作为我们问题的解决方案。
直到第 50 纪元的进化看起来是这样的:
我们可以看到算法成功了!但看起来是千钧一发。直到纪元 25,人口聚集在大约 x = 1.4 的另一个局部最大值周围。幸运的是,我们有一个远在 4 点的个体,从第 25 纪元开始,它成功地将种群拉向右边。
当查看每个时期人口中最佳个体的健康分数时,我们也可以在时期 25 左右看到这种转变。
它在公元 25 年左右暴涨。
讨论
好了,我们已经看到了算法是如何工作的,而且我们最终甚至得到了正确的答案(或者至少是一个非常好的近似值)!其中有一点运气,但这将永远是一样的。我们可能会更不幸,我们的初始人口可能会在当地最大值 1.4 左右开始。那么个人就不太可能逃出这个区域,就像这个例子:
失败的尝试。该算法只找到错误的局部最大值。
仍然可能是这样的情况,一个突变把一个个体推向右边,反过来又把更多的个体拉向右边。但这是极不可能的,因为变异在任何方向上推动个体最多 0.75,概率> 99%,因为标准差是 0.25。
那么,用更极端的突变好吗?好吧,如果我们夸大的话,个体只是跳得到处都是或者聚集在两个角落 x = 0 和 x = 4。因此,我们必须小心选择这里的参数。
从理论的角度来看,你可以把进化算法看作是一种高度随机化的算法。初始种群是随机的,个体通过或多或少复杂的操作产生后代,后代利用随机性变异,所有这一切重复数百、数千、数百万次。
因此,很难分析这些算法,并对它们的成功概率或结果质量给出任何理论界限。对于非常简单的算法来说,这是可能的,例如用于最大化极其简单的函数的 (1 + 1)进化算法【1】,或者用于解决简化的多目标背包问题的算法【2】,,但是像这样的例子很少见到。
但是,如果运行不起作用,就用相同或其他参数再试一次。
用 Python 实现
在这里,我将与你分享我的实现。我试图使它通用和抽象,所以你可以很容易地使用它来达到你的目的。
如果你以前从未使用过 ABBasClasses,不要担心。类Individual
只是告诉你应该为代表你个人的对象使用哪个接口。你的个体需要一个值(有效载荷,潜在的解决方案),你必须实现一个随机的初始化,一个变异,和一个配对函数。
然后泳池和进化课会处理剩下的事情。我还实现了函数最大化示例,向您展示这可能是什么样子。我在这里使用了更多的参数,但是如果您将所有的下限替换为 0,上限替换为 4,rate 替换为 0.25,dim 替换为 1,alpha = 0.5,那么您最终将再次使用我们的示例。
您可以像这样使用这些类:
你走吧!
到目前为止,我们已经在一个小玩具问题上获得了一些信心,但现在是时候再次回到困难的 TSP 问题上了。
旅行推销员问题
TSP 是关于寻找经过 n 个城市的最短往返旅程。以这些为例:
地图上的十个城市。
TSP 的解决方案如下所示:
最短的往返行程,访问所有城市。
一些简单的事实
有许多算法可以解决这个问题。它们的范围从穷举搜索(尝试所有方法)到更复杂的算法。然而,所有这些方法都很慢,而且如果 P≠NP,我们永远也不能指望出现任何快速算法。
如果你能等几天,详尽的搜索将让你解决多达 15 个城市的问题。其他方法,如赫尔德-卡普算法让你乐观地解决多达 50 个城市的问题。
如果你不再需要最好的解决方案,1976 年的克里斯托菲德斯算法会在很短的时间内给你一个解决方案也就是说被证明比最短的往返时间最多多 50%。****
T 想想为什么这是一个令人敬畏的结果:我们甚至不知道最短的往返长度,但我们仍然可以说,这个算法的往返长度比这个未知的解长不到 50%!
但是现在,让我们给你你所期待的:一个求解 TSP 的进化算法!
求解旅行商问题的进化算法
这一次,我们从 20 个城市开始。这个量仍然足够低,可以用 Held-Karp 算法来解决它,所以我们甚至可以检查我们最后是否得到了最佳解!这是地图:
地图上的二十个城市。让我们不要费事去尝试对这个进行彻底的搜索。也许这些城市甚至不存在了,直到我们得到最短的往返。
现在,我们必须再次回答所有的问题。让我们首先回答更简单的“数字问题”(如果事情不顺利,我们可以轻松调整的超参数):
- 多少个纪元? 1000
- 有多少个起始个体? 100
- 多少家长? 60 (两个产生一个后代,像以前一样)
- 有几个后代? 30
- 有多少人濒临死亡? 30
令人兴奋的问题是处理我们现在必须定义的类TSP
的实现。有哪些个体?随机初始化是如何工作的?削皮?变异?健身分数是多少?
初始人口
先说一个基础的:这里的个体有哪些?普罗提普:不是城市。再次重申:
个人总是问题的潜在解决方案。
在 TSP 的情况下,我们搜索一个短的往返行程。“短”是指往返行程中每两个城市之间的欧几里德距离之和。我们可以将这样一个往返行程表示为一系列 n 的数字,例如(0,3,1)读作“从城市 0 开始,然后到城市 3,从那里到城市 1,然后回到城市 0。”。所以,我们的个体是一列数字,包含从 0 到 n -1 的每个数字恰好一次,即{0,1,2,…,n-1} 上的排列。
在整个过程中,我们必须保持这种属性。将不能代表问题可行解决方案的个体留在群体中是没有意义的,因为它阻塞了群体,我们甚至可能在最后选择它,给我们一个无效的解决方案。
以及如何初始化它们?好吧,只是从 0 到 n -1 随机排列数字。这应该够了。
**def _random_init(self, init_params):
return np.random.choice(
a=range(init_params['n_cities']),
size=init_params['n_cities'],
replace=False
)**
让我们继续变异程序。
变化
那么,我们如何以简单的方式改变往返行程呢?假设我们往返五个城市,例如(3,1,4,2,0)。一个简单的方法是随机交换两个元素。我们的例子可能会变成(0,1,4,2,3)或(3,4,1,2,0)。我们还可以多次交换,并从中得出一个超参数rate
,与之前函数最大化示例中的标准差相当。
**def mutate(self, mutate_params):
for _ in range(mutate_params['rate']):
i, j = np.random.choice(
a=range(len(self.value)),
size=2,
replace=False)
self.value[i], self.value[j] = self.value[j], self.value[i]**
很明显,这种变异保留了个体是排列的性质,即可行解。
这里最有意思的大概就是pair
函数了。
配对
让我们假设我们有以下想要用作父母的个体:
方法如下:将第二个个体的右半部分复制到第一个个体的右半部分。
第一个个体的右半部分被替换。4 代替旧的 5,2 代替 3,3 代替 1。
我们现在想使用改变后的第一个个体作为后代,但是这样做是行不通的,因为现在有重复的数字。因此,必须首先修复被改变的第一个人的左半部分。我们可以这样做:
插入右半部分的 4 踢出了之前在那里的 5。所以,让我们用这个 5 代替左半部分的 4,因为它现在不见了。对 2 做同样的事情,把 3 踢出去,得到如下结果:
但是还有下一个问题:我们现在有两次 3 号了。但是我们可以多次重复这个过程,直到我们再次得到一个可行的个体。3 是问题所在。它最初踢出了 1。所以把左半部分的 3 换成 1,瞧:后代就是(0,5,1,4,2,3) 。
履行
总的来说,我们的TSP
类看起来像这样:
在这里,我还引入了另一个超参数α,它决定在哪里分割个体。对于我的例子,我使用 alpha=0.5。
健身得分
由于我们想最小化往返长度,我们可以只使用减去往返长度作为适应性分数。
实验
让我们用 20 个城市解决 TSP!我使用了下面的代码:我定义了一个适应度函数、一个计算往返距离的函数和一个计算距离矩阵(两个城市之间的成对距离)的函数。
对我来说,适应度函数是这样的:
以下是每个时代最优秀的人:
解决方案的演变。在公元 400 年之后,一切都没有改变。
我们从公元 400 年获得的解决方案甚至是我们能为这 20 个城市获得的最佳解决方案!我用卡尔·埃克洛特的赫尔德-卡普算法实现检查了这一点。
更多城市!
最后一幕,让我们尝试一些真正困难的事情。不仅仅是 10 或 20 个城市,而是 100 个,这对于任何精确的算法来说都太多了。
********
从一个非常混乱到一个干净的多,时间短的往返。
我不能告诉你这是不是最快的往返,但对我来说,这绝对是一个不错的选择!
结论
在本文中,我们通过两个例子看到了进化算法是如何工作的:最大化一个函数和解决旅行推销员问题。进化算法通常用于解决我们不知道确切答案的难题。这些算法可以非常快,并产生准确的结果。实现起来很容易,你不必是你的问题所在领域的专家,例如,你不必阅读过去 20 年 TSP 研究的论文来编写一个性能良好的算法。
可悲的是,很难获得任何理论上的结果,因为进化算法经常与许多以复杂方式相互作用的随机性一起工作。因此,我们无法知道给定的解决方案是好是坏,我们只能检查它对于我们的用例是否足够好。在 100 个城市的例子中,如果我们的目标是以 150,000 或更少的长度旅行到每个城市,算法已经给了我们一个完美的答案。
参考
[1] S. Droste,T. Jansen 和 I. Wegener,,【1+1】进化算法的分析(2002),理论计算机科学,第 276 卷,第 1-2 期,2002 年 4 月 6 日,第 51-81 页
[2] M. Laumanns,L. Thiele 和 E. Zitzler,对简化的多目标背包问题的进化算法的运行时间分析 (2004),自然计算 3,37–51
[3] K. Stanley,R. Miikkulainen, 通过扩充拓扑结构进化神经网络【2002】进化计算 10(2) 2002,s . 99–127**
我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!
作为最后一点,如果你
- 想支持我多写点机器学习和
- 无论如何,计划获得一个中等订阅,
为什么不做 通过这个环节 ?这将对我帮助很大!😊
说白了,给你的价格不变,但大约一半的订阅费直接归我。
非常感谢,如果你考虑支持我的话!
有问题就在LinkedIn上写我!
An extensible, interactive visualization framework to measure gender bias in the news
How we successfully integrated Dash (by Plotly) into our NLP and linguistics research to study women’s portrayal in mainstream Canadian news
How balanced is our representation of gender in the news? (Image credits: Tumisu via Pixabay)
Background
Over the last several months, I’ve been working at the Discourse Processing Lab at Simon Fraser University (under the leadership of Dr. Maite Taboada), where we’ve been actively developing and extending the Gender Gap Tracker, an automated Natural Language Processing (NLP) system that measures men and women’s voices on seven major Canadian news outlets in real time. The Gender Gap Tracker is a collaboration between Informed Opinions, a non-profit dedicated to amplifying women’s voices in the media and Simon Fraser University, through the Discourse Processing Lab and the Big Data Initiative.
At a high level, we perform the following steps on a daily basis to generate statistics that allow us to quantify the number of men and women quoted in the news:
- Scrape the text and metadata of news articles from the daily web content of seven Canadian English-language news outlets.
- Process each article’s text using a variety of NLP techniques (syntactic parsing, named entity recognition, quote extraction) and gender services in order to identify quoted people and their genders.
- Compute and store individual/aggregated statistics that measure the number of quoted people (i.e., sources) from either gender.
Disclaimer: We acknowledge that gender is non-binary, and that there are different social, cultural, and linguistic conceptualizations of gender. For this project, we rely on name lookups from internal/external gender services in order to classify people mentioned and quoted as female, male, or other.
In addition to our daily pipeline, we also run a monthly topic modelling pipeline that performs large-scale discovery of topics using Latent Dirichlet Allocation (LDA), on each month’s English news articles. On average, we process 20,000–30,000 articles’ worth of text per month to generate 15 topics (i.e., keyword distributions) for that month, that are then labelled by a human based on real-world knowledge of the month’s events.
All our NLP utilities (including the upstream tools that perform named entity recognition and quote extraction to extract gender statistics) are developed using Python and spaCy. Topic modelling, for reasons involving the sheer size of data being handled, is done using PySpark’s scalable implementation of LDA.
Although we do showcase our primary gender statistics (i.e., the proportion of female/male sources quoted by each outlet) on a live, interactive tracker website (hosted by Informed Opinions), we quickly realized the value of building our own custom dashboard for research and exploration purposes. The aim of our research dashboard (hosted here, on Simon Fraser University’s servers) is to provide data scientists and software developers at the Discourse Processing Lab with the means to easily extend the existing data analysis framework, and to help answer new research questions that may arise in the future.
We chose the Dash framework (by Plotly) to build our own custom interactive applications within a multi-page dashboard, all in Python. In this article, I’ll highlight some of our results, design decisions, and why Dash is a great framework for tasks related to data science research and exploration.
Multi-page research dashboard built using Dash: https://gendergaptracker.research.sfu.ca/
A brief overview of the existing apps
This section highlights a range of interactive tools implemented in the dashboard. Each high-level function is separated into its own application, accessible by clicking the respective button on the home page.
Text analyzer
This app takes in a user’s input text, typically from a news article or blog post, and runs an NLP algorithm on the backend server to extract the text’s quoted sources and people mentioned. The detected names are passed through our internal cache and gender service scripts to assign each name a gender (any one of ‘female’, ‘male’ or ‘unknown’). A doughnut chart showing the proportion of sources from each gender is displayed, along with the detected names and the quotes in the article/blog post.
Text analyzer dashboard for the Gender Gap Tracker
Because journalists employ a wide range of styles in naming the persons they quote, a naive system that simply looks for quotation marks in the text is nowhere near sufficient. The dependency-based parse tree of a text block, obtained using spaCy, plays a key role in our quote extraction system, locating the beginning and end of quotations using a sentence’s syntactic structure. We first identify key verbs that are commonly used in quotation (defined using a custom, hand-curated verb list), and then locate the objects of each verb, i.e., clauses that are dependent on the verb, based on the parse tree. This allows us to find speakers of quotes regardless of the sentence structure and the presence of quotation marks.
In addition, a coreference resolution algorithm (powered by neuralcoref) is used to link pronoun mentions (‘he’ or ‘she’) to a prior named entity of the type ‘PERSON’. This allows us to capture quotes that do not directly name the speaker. The example snippet shown below highlights the range of quotes detected by our system.
Prime Minister Justin Trudeau said Saturday that Canada will contribute $300 million towards the international effort to battle COVID-19.
“None of us have been spared from the effects of COVID-19 and none of us can beat it alone.”
Canada will contribute $180 million to address the immediate humanitarian and development impacts of the pandemic, he said.
“We are happy to see Minister Gould pushing for more investment because more is desperately needed,” said Stuart Hickox, the Canadian director of the One Campaign.
Example of the various kinds of quotes and speakers detected by the text analyzer app
Try out your own custom news snippets on the text analyzer app to get the gender breakdown of the people quoted/mentioned!
Topic model explorer
In this app, we showcase a new way to visualize the relationship between the topics covered in a news corpus and the gender of those quoted. Our primary goal through this app is to analyze whether female or male sources are more likely to be associated with specific topics in the news. As described earlier, we perform large-scale topic discovery on each month’s data using an LDA algorithm implemented in Spark. The topic keywords discovered for that month, along with other relevant metadata, are written to a MongoDB database (which also hosts all the raw text data from the news articles). These keywords are then inspected by a human, at the start of each month, and labelled manually based on knowledge of the month’s events.
Because we store the topic distribution (as predicted by LDA) on a per-document basis, we can average these values based on the outlet that published the article. We plot the topic names, as labelled by a human, and these mean ‘topic intensities’ by outlet on a heat map, as shown below for the month of August 2019. The darker the colour, the more strongly that topic was covered, on average, by that outlet in that particular month.
To study the relationship between topics and the gender of those quoted in articles pertaining to that topic, we first divide our article set for a given month into two subsets — those that quote a majority of female sources (i.e., at least one more female source quoted than male sources), and those that quote a majority of male sources. We then perform a similar averaging of topic intensities (i.e., the topic weights per article obtained from LDA) for each outlet. The results are once again plotted as a heat map, this time with a divergent colour scale from red to blue.
Average topic intensity and topic gender prominence for August 2019, in the topic model dashboard app
The topic intensity plot (green) for August 2019 clearly shows that ‘Sports’ was a major topic that month, as were ‘Crime and police investigations’ and ‘Business and consumer products’. ‘U.S. politics’ was covered particularly extensively by Huffington Post Canada, in comparison to the other outlets. What is more interesting, however, is that in the second heat map, the ‘Sports’ and ‘Healthcare & medical services’ topics exhibit a strong female prominence, which is a term we use to describe topics that are strongly associated with women being quoted the majority of the time on average for that topic. The darker the red colour, the stronger the female prominence for a given topic and a given outlet. Conversely, the darker the blue colour, the stronger the male prominence for that topic.
A deeper analysis on the ‘Sports’ topic for August 2019 showed that this was the period in the aftermath of the US women’s soccer team winning the FIFA 2019 women’s world cup. In addition, Canadian tennis player Bianca Andreescu had a dominant performance in the U.S. Open (which she later went on to win in September). As a result of numerous female players and coaches being quoted over the course of August 2019, the sports topic, which would normally be dominated by the quotes of male players and coaches, showed a strong female prominence in this particular month. Unsurprisingly, the ‘U.S. politics’ and Canadian ‘Federal politics’ topics exhibit strong male prominence, due to the sheer number of male politicians in both the U.S. and Canada being regularly quoted in articles pertaining to politics.
Overall, we obtained some very interesting findings from the topic model app, which can be explored in more detail for all months dating back to October 2018.
Top-quoted sources app
In this app, the quoted persons (male or female) from each article for are collected from our MongoDB database (after having been calculated independently by the NLP modules that run on a daily basis), and then aggregated to retrieve the number of quotes per person for any given month. These lists of top-quoted men and women are plotted as lollipops, the top 15 of which are shown below for the month of May 2020. Each dot represents the man/woman’s quote count, and the length of the line connecting them represents the disparity in counts between either gender.
Top 15 quoted men and women in May 2020 as per the top-quoted sources app
It is very interesting that 10 of the top 15 quoted women in May 2020 are either medical officers or healthcare experts, as opposed to just 1 of the top 15 quoted men being from the healthcare domain. Due to the COVID-19 pandemic, many expert women (provincial/regional medical officers and physicians) holding prominent positions in various regions of Canada were brought to the forefront in the news. In fact, our data shows that Bonnie Henry, the Chief Provincial Health Officer of British Columbia, was the most quoted woman all through March-July 2020. The top-quoted men during the same period overwhelmingly tended to be politicians, both Canadian and American, presumably due to over-representation of men in this domain.
Another interesting aspect of the lollipop plot shown above is its distribution — not only are men always quoted much more frequently than women, but also, the top-quoted people (both men and women) tend to be quoted far more often than people in the middle or bottom. This points to the Pareto principle, i.e., that a large proportion of resources is held by a small percentage of the population, also known as the 80/20 rule. While it is certainly possible that some people (especially politicians) get preferential treatment by the media because they already have a voice, recent evidence from the COVID-19 pandemic suggests that having more women in positions of power can increase the likelihood of journalists quoting them and improve gender parity overall.
Similar trends and patterns can be explored in detail using the top-quoted sources app, for all months dating back to October 2018.
Monthly trends app
This app visualizes a monthly time series of the number of quotes for a given person (male or female). Because of the size of our data (500,000+ articles with thousands of unique male/female sources over two years, and counting), we only display the names of prominent, public-facing men/women that appear in a month’s top 50 quoted people. The trends are displayed using a line chart, as shown below.
Comparing four prominent women in Federal/provincial healthcare positions using the monthly trends app
Exposing the number of quotes as a time series allows us to study interesting phenomena pertaining to individuals, such as “the rise of Bonnie Henry”. In the early months of the COVID-19 pandemic (March-April 2020), a sharp increase was observed in the quote count for Bonnie Henry, the Chief Provincial Health Officer of British Columbia. Interestingly, her quote count is significantly higher than that of her federal counterparts (Theresa Tam, the Chief Public Health Officer of Canada and Patty Hajdu, the Federal Minister of Health), as well as that of Christine Elliott, Minister of Health for Ontario, a province with a much higher population than British Columbia. We think this could be due to two factors: 1) British Columbia was a success story in the early days of the COVID-19 pandemic, leading to Bonnie Henry being talked about (and hence quoted) more frequently, and 2) both Ontario and Ottawa had multiple prominent public-facing women for journalists to quote, reducing each woman’s overall share.
Seeing whether the monthly trends app can help predict future outcomes, for example, the dominant players in elections, is a very interesting prospect, and we are keen to explore this further.
A look under the hood
In this section, I’ll explain some of the technical details involved in building the dashboard, including some ideological and design decisions.
Why Dash?
In a research-focused environment such as ours, front-end web development skills (and knowledge of the associated JavaScript tools) are not easily available. Python is the natural choice of language for all aspects of this project, because of its massive, robust NLP and data science ecosystem. However, the Python visualization ecosystem is immensely complex, and it can quickly become overwhelming to decide between the multitude of options for the specific tasks at hand. There exist a number of great libraries for building dashboards and interactive visualizations in Python, such as Panel, Bokeh, Streamlit, and Dash.
Panel is a novel, high-level dashboarding solution for Python that allows users to create interactive web apps and connect user-defined widgets to plots, images, tables or text. Unlike many other approaches, Panel attempts to be plotting library and environment-agnostic, i.e., it is designed to support nearly all Python plotting libraries, and work just as well in a Jupyter notebook or on a standalone web server. The key defining feature of Panel is that it allows users to separate their science/engineering/business logic from their GUI implementation, without getting tied to any particular GUI or web frameworks. Developed under the support of Anaconda Inc., Panel is an ambitious project that provides users the flexibility to move expensive computations and data processing between the server side and the client side, depending on the application’s requirements and the size of the data. The Panel documentation contains a rich and detailed explanation of its features in comparison with other Python dashboarding frameworks.
Streamlit is a light-weight, minimalistic framework to build dashboards in Python. The main focus of Streamlit is to provide users with the ability to rapidly prototype their UI designs using as few lines of code as possible. All the heavy lifting typically required to deploy a web application, such as defining the backend server and its routes, handling HTTP requests, etc., are abstracted away from the user. A certain degree of customizability is traded off for ease of use and rapid setup, making it ideal for early-stage interactive exploration of data and modelling results.
Bokeh, also developed with the support of Anaconda Inc., is a visualization library that provides lower-level primitives for charts and widgets that can be used to power other higher-level charting libraries (such as Panel, or chartify). In Bokeh, high-level “model objects” (representing plots, axes, or other attributes related to plotting) are created in Python (or any other language), converted to JSON, and then consumed by a JavaScript client library, BokehJS. This decoupled architecture allows Bokeh to extend to other languages than Python, provide the backend code that runs the server, and ultimately power the UI event in the front-end (browser) via JavaScript.
Dash is a powerful, highly customizable library for building dashboards in Python. It is written on top of Flask, Plotly.js and React.js, allowing for fluid, reactive web applications that scale well to multiple client sessions. In terms of its architecture and functionality, Dash is most similar to Bokeh, in that it allows users to define higher-level plot objects in Python (using an underlying Flask web server), whose underlying attributes are then consumed by a JavaScript library (Plotly.js) that fires events on the client side. Unlike Streamlit and Panel, Dash does require users to have some knowledge of the underlying HTML and CSS details, greatly increasing users’ ability to customize the UI to their needs. Although Dash’s web server can support other Python visualization libraries (such as Altair, Seaborn or matplotlib), it is still somewhat opinionated, with users encouraged to stick to the Plotly graph API for the most part, because this API has been tried and tested in production.
Key features of each dashboarding solution in Python
As can be seen in the above figure, Dash provides the ideal combination of all our primary requirements. To start with, Dash uses a web server built on top of Flask (unlike the other three frameworks, which use Tornado), and is deployed just like traditional Flask servers using WSGI. Because we already had other dashboards and backend APIs based on Flask, it made more sense to build our new system with some level of compatibility. Dash is designed to store a session’s state on aper-userbasis, within the client (i.e., the browser). This is apt in terms of scalability for our use case, because we need a system where many simultaneous client sessions are able to view results from the database without necessarily using up server resources.
We opt to work around any potential computational bottlenecks on the server side by designing our apps such that they never request huge amounts of data from the server at any one time. Any NLP computations (e.g., in our text analyzer app) only request highly specific data (such as gender values for a given name) and run in near real-time, so the server is unlikely to be bogged down due to compute-heavy requests by many simultaneous client sessions. To avoid repeating expensive calculations for each user, a number of options are available for caching intermediate results (on the client side) that can be reused within the session. Most importantly, Dash offers a great deal of freedom in terms of page design and layout— it allows the developer to directly modify the underlying HTML and CSS attributes, providing much greater flexibility in customizing the dashboard’s appearance.
Multi-page structure
The dashboard is deployed using a multi-page layout, to make it more extensible as time goes on. A simple, responsive HTML layout based on this CSS template is used to allow for flexible rearrangement of components based on the user device’s display resolution. Each app’s layout and source code is self-contained, in its own Python file, and within a clearly defined zone outside the sidebar as shown below. An arbitrary number of independent apps can be added using this structure.
Extensible, multi-page layout for the dashboard (designed using CSS, as per this file)
Modularity and code readability
A Dash app can be conceptualized as being made of three main blocks of code. The first of these is the application layout, which contains the structure of the web page, including all the interactive widgets and core components (dropdowns, text inputs, etc.) required by the user to modify an app’s state. All code is written in Python, using Dash’s wrappers around Plotly’s graph objects and generic HTML.
The next block defines the callbacks for the app, which are functions (defined using Python’s decorator syntax) that allow users to observe, modify and update the properties of any component in the UI. Because all Dash code is written in Python, it integrates very well with pandas, allowing specific results to be returned on the fly based on user input. In this example, a dropdown’s selected value is passed as an input argument to a callback, which executes asynchronously to filter the contents of a preloaded pandas DataFrame, returning just the required data. This data is output as a Plotly figure
object and rendered as a line chart on the browser.
The third block contains user-defined, custom functions, primarily written to make the callbacks and the application layout more readable. For example, if we were performing a slightly more complicated action along with filtering the DataFrame, that portion of code could be factored out into a separate function, making the callback much more readable. The example below is the same as the one above, except that the filtering steps are factored out to an external function, greatly improving readability in complex cases.
Using this 3-block structure, arbitrarily complex apps can be designed to perform data manipulation and NLP tasks on the fly.
Intermediate data storage
One common problem that arises when performing NLP tasks is that of expensive bottleneck computations that can increase an app’s response time. For example, in the text analyzer app described earlier, we are required to perform named entity recognition, coreference resolution and gender prediction on a potentially large list of names, all in real time, based on arbitrary text input by the user. This is further complicated by the fact that multiple components in the app — the doughnut charts and multiple data tables — all need to access the same intermediate data.
Rather than perform the same (potentially expensive) calculation multiple times for each callback, we apply Dash’s inbuilt mechanisms to share state between callbacks. The simplest way to do this is to store expensive-to-compute intermediate data as in-memory JSON, that can be accessed by every subsequent callback without wasteful recomputation. An example is shown below.
In the snippet shown above, a user first inputs a condition (e.g., a date filter), for which we read specific data from a MongoDB database using the pymongo library. Then, we perform some expensive calculation on this data (using the function expensive_calc
) within the first callback. The data computed from this callback is stored as JSON and kept in memory on the client side, where it can then be accessed for free by the second callback. It is trivial to then transform the JSON data blob into a pandas DataFrame, following which it can be output to a Plotly figure
object and rendered as a chart on the client side.
Conclusions
In building each application for the Gender Gap Tracker research dashboard, design decisions were taken to minimize the amount of data being transferred between the server and the client. Because our primary data storage layer is in MongoDB, all data must be passed around as JSON. Due to the immense size of the data in this project (500,000+ news articles from over a two year period, and counting), we only work with aggregated quantities (precomputed through intermediate operations on these JSON objects) in all our visual components. All charts (heat maps, lollipop plots and line charts) display precomputed values that either sum up or average the individual values over a specified time period. This is mainly done to maintain reasonable response times and to provide a fluid run time experience.
The Gender Gap Tracker is the result of many months’ work by a team of eight at Simon Fraser University, whose findings draw from various fields, including big data, computer science, social science, media and linguistics. We are excited to present more nuanced results of this interdisciplinary work for consumption by the broader public, and are always open to feedback!
Acknowledgements
We thank Alexandra Wilson at Simon Fraser University, who provided invaluable guidance on the design, layout and colour styles for the dashboard. We’re also grateful to to Alexandre Lopes at SFU Research Computing, who built and maintains the database and server infrastructure for the Gender Gap Tracker.
Resources
The research dashboard for the Gender Gap Tracker and our most recent results can be explored in detail here:
[## Measuring gender bias in media
Dashboard showcasing results from our study on gender bias in the media
gendergaptracker.research.sfu.ca](https://gendergaptracker.research.sfu.ca/)
The code for the dashboard and the NLP functionality described in this article is available on the project’s GitHub repo, shown below.
[## sfu-discourse-lab/GenderGapTracker
This page contains code for dashboard apps that we are building internally in the discourse processing lab, pertaining…
github.com](https://github.com/sfu-discourse-lab/GenderGapTracker/tree/master/dashboard_for_research)