在 Data Studio 中计算一个月的剩余天数
这并不像听起来那么简单!
Joshua Hoehne 在 Unsplash 上拍摄的照片
介绍
你有没有遇到过这样的情况,你创建一个数据工作室的报告,有很多障碍要通过?
上周我也遇到过类似的事情。我正在使用不同的数据源、计算字段、混合等进行仪表板自动化工作,突然我意识到我需要一个非常具体的指标。
那是什么?
我想计算到月底为止每天可用的平均预算。但是在 Data Studio 中,没有提供该月剩余天数的字段。作为一个纯 90 后的孩子,我从谷歌搜索开始。经过一些搜索和博客文章阅读,我意识到没有工作的解决方案,将涵盖我的需求。大多数解决方案建议创建一个谷歌表,然后计算一个月的剩余天数,然后将其与我的 Data Studio 仪表板连接,诸如此类。
不够好!正如我所说的,我正在为一个自动化任务工作。所以,我开始研究自己的解决方案。
它并不花哨,但很有效…
该过程
对于我自己的任务,我使用了 Google Ads 数据源。当然,您可以使用自己的数据源,但是您必须适当地调整字段,以便解决方案能够工作。
流程背后的想法:我需要哪些领域?
- 每月天的一个字段
- 一个带有当月剩余天数的字段
在整个过程中,我们将需要一些额外的修改,但主要的想法是创建这两个字段。
让我们看看实践中…
正如你可能已经知道的,谷歌数据工作室定制字段,不能在一个案例函数中结合维度和度量——真扫兴。因此,像下面这样的字段最终将不起作用:
CASE
WHEN Month = 'January' THEN 31
WHEN Month = 'February' THEN 28
...
END
诀窍是表现为两个场都是二维的。
字段 1: 一年中的月份
对于我的解决方案,我们希望将月维度从日期类型修改为文本类型。我不喜欢修改我的原始字段,所以我们将创建一个新字段,其中只包含月份维度。就像下面这样:
自定义字段:一年中的月份
Data Studio 会自动将您的字段识别为日期类型。
- 转到数据源以更改自定义字段的类型
- 单击“类型”列中的项目
- 选择文本选项
字段 2:每月的天数
现在我们有了一年中的月份字段,我们可以创建一个新字段来为每个月分配正确的天数:
自定义字段:每月的天数
⚠️In 为了在我的计算中调用我的“一年中的月份”字段,我创建了一个表来查看我的字段的格式。我建议您对自己的数据源也这样做。
字段 3: Num(每月的天数)
正如你可能已经注意到的,在我的计算中,我给每个月分配了一个数字**作为维度。**我们需要用一个新的自定义字段来解决这个问题…
自定义字段:Num(每月的天数)
⚠️When:你将“Num(每月的天数)”字段添加到一个可视或表格中,你必须使用 MAX ,作为你的聚合方法。
到目前为止,我们应该能够用您的月维度和我们创建的 Num(每个月的天数)创建一个数据表,并且能够看到每个月的正确天数(!idspnonenote)。!!不要忘记使用 MAX!!!).
字段 4:本月剩余天数
接下来是“本月剩余天数”。这当然是这篇文章的最终目的!
自定义字段:一个月的剩余天数
我们流程的最后一步,当您使用我们的“本月剩余天数”字段时,您应该定义符合您需求的日期范围。我喜欢使用“本月至今”,它不包括当天,但是您也可以使用“本月”来获得总天数。在下表中,您可以看到正在运行的字段:
实际日期:2021 年 1 月 17 日
万岁!!!🎆
最后的想法
我告诉过你,这不会是幻想…
Data Studio 是一个强大的工具,功能丰富,但有时,像这样的重要字段会丢失。有时候很容易计算,有时候却不容易。可能还有其他更好的方式,但我希望我为你节省了一些填写谷歌表单的时间。🤓
我叫 Alexandra Poulopoulou,是 Reprise Digital 的数据和分析主管。在我的职业生涯中,我参与了几个分析项目,以推动成功的商业决策。
如果你喜欢刚刚阅读的内容,请在 Medium 、 LinkedIn 或 Twitter 上关注我,因为还会有很多类似的活动。下次见…
用 Python 计算偏斜度(有例子)
在本教程中,我们将探索如何在 Python 中计算偏斜度
作者图片
目录:
- 介绍
- 什么是偏斜度?
- 如何计算偏斜度?
- Python 中如何计算偏斜度?
- 结论
介绍
偏斜是我们在日常生活的许多领域观察到的现象。例如,人们经常在网上搜索的是感兴趣的特定国家的工资分布。这里有一个例子:
在 Statista 找到更多统计数据
从上面的图表中,我们可以看到 2019 年加拿大的收入分布,平均收入大约在 40,000 美元到 50,000 美元之间。
我们还注意到,数据不是正态分布在平均值周围,因此存在某种类型的偏斜。
在上面的例子中,很明显有一些负偏斜,分布的左尾更粗。但是为什么会有歪斜呢?我们看到,分布的中位数将在 60,000 美元左右,因此它大于平均值;并且分布的模式将在$60,000 和$70,000 之间,因此产生了我们上面观察到的偏斜。
其中峰度衡量的是两个尾部中是否存在极值(或者只是尾部是重还是轻),偏斜度关注的是基于极值(或者只是尾部的对称性)来区分分布的尾部
为了继续学习本教程,我们需要以下 Python 库: scipy 。
如果您没有安装它,请打开“命令提示符”(在 Windows 上)并使用以下代码安装它:
pip install scipy
什么是偏斜度?
在统计学中,偏度是概率分布关于其平均值的不对称性的度量,有助于描述概率分布的形状。基本上,它衡量给定分布与正态分布(对称)的差异程度。
偏斜度可以取几个值:
- 正-当分布具有较厚的右尾且众数
- Negative — observed when the distribution has a thicker left tail and mode>中值>平均值时观察到。
- 零(或接近零)-当分布关于其均值对称且近似众数=中位数=均值时观察到。
注:上述定义是一般化的,值可以根据分布族的不同而有不同的符号。
如何计算偏斜度?
在大多数情况下,样本偏度的计算方法是 Fisher-Pearson 偏度系数(注意:还有更多计算偏度的方法:Bowley,Kelly’s measure,Momental)。
这种方法把偏斜度看作分布的第三个标准化矩。
听起来有点复杂?按照下面的步骤,对计算有一个完整的理解。
分布的第 k 阶矩可以计算为:
作者图片
如前所述,偏斜度是分布的三阶矩,可计算如下:
作者图片
其中:
作者图片
如果您想要校正统计偏差,那么您应该求解调整后的 Fisher-Pearson 标准化力矩系数,如下所示:
作者图片
举例:
上面是很多公式。为了使这一切成为一个更好理解的概念,让我们来看一个例子!
请考虑以下代表学生考试成绩的 10 个数字序列:
X=【55,78,65,98,97,60,67,65,83,65】
计算 x 的平均值,我们得到:x̄=73.3.
求解 m_3:
作者图片
作者图片
求解 m_2:
作者图片
作者图片
求解 G1:
作者图片
在本例中,Fisher-Pearson 偏斜系数等于 0.647511,表明数据中存在正偏斜。另一种检查方法是查看这些值的众数、中位数和平均值。这里我们有 mode
In addition, let’s calculate the adjusted Fisher-Pearson coefficient of skewness:
Image by Author
How to calculate Skewness in Python?
In this section we will go through an example of calculating skewness in Python.
First, let’s create a list of numbers like the one in the previous part:
To calculate the Fisher-Pearson correlation of skewness, we will need the scipy.stats.skew 函数:
我们应该得到:
0.6475112950060684
要在 Python 中计算调整后的偏斜度,请将 bias=False 作为参数传递给 skew() 函数:
我们应该得到:
0.7678539385891452
结论
在本文中,我们讨论了如何使用 scipy 库在 Python 中计算一组数字的偏斜度。
如果您有任何问题或对一些编辑有建议,请随时在下面留下评论,并查看更多我的统计文章。
原载于 2021 年 7 月 26 日 https://pyshark.comhttps://pyshark.com/skewness-in-python/。
为分类模型选择基线精度
选择一个简单的基线精度来证明您的分类模型在某个问题上有技巧
罗伯特·阿纳奇在 Unsplash 上的照片
当你评估一个新的机器学习模型,并最终得到一个准确度数字或其他指标时,你需要知道它是否有意义。特别是在不平衡的分类模型中,看起来你的模型并不比猜测好多少。什么样的精度才足以称你的模型有用?
这篇文章只是为了展示你的模型的简单的基线准确性,我发现这很有用。
问题是
我创建了一个选举模型,使用经济指标预测了美国所有 3200 多个县(民主党或共和党)的投票习惯。该模型的准确率为 86%。这听起来很棒,直到你意识到美国 84%的县都投票给共和党。这些县碰巧更小,更农村,所以有更多。像许多数据集一样,我有明显的阶级不平衡。
你可以简单地预测所有的县都是共和党的,准确率为 84%。我的模型真的仅仅比猜测每个县的共和党好一点点吗?
零速率分类器
我们刚刚描述的模型基线有一个名字。
ZeroR(或零比率)分类器总是分类到最大的类,换句话说,只是平凡地预测最频繁的类。对于一个两种结果的模型来说,只是随波逐流往往是正确的。
总是选择多数组(ZeroR 分类器)作为基线是有见地的,并且是任何分类模型都应该选择的。对于一个机器学习算法来说,要证明它在某个问题上有技巧,它必须达到比这个零值更好的精度。
对于高度不平衡的问题(如投票分类问题),一个比 ZeroR 稍高一点的模型精度可能是非常重要的。不管怎样,你的模型必须比 ZeroR 更好才能被认为对问题有用。
随机速率分类器(加权猜测)
现在我们将把我们的高中数学运用到工作中。我们可以使用的另一个基线策略是,如果我们猜测每个类的加权百分比,看看我们的准确度会是多少。该值将始终低于 ZeroR 值,因此它不应该是您的下限基线。相反,它可以用来解释和理解您的结果,即您的模型增加了多少价值。
随机比率分类器—在进行随机类别分配时应用类别分配的先验知识。
我们将针对几个分类问题研究这两种策略。
抛硬币
让我们先来看一个抛硬币模型。50%的结果是反面(0),50%的结果是正面(1)。
我们的基线策略在这里是如何工作的?:
- 零——猜测所有的头像会给我们 50%的准确率。
- 随机比率——我们凭直觉知道,猜测 0.50 的正面和 0.50 的反面也会给我们 50%的准确率。我们将有一半正面预测和一半反面预测是正确的。
猜测随机速率分类器的半头半尾在数学上是这样工作的:
Odds of Guessing Heads Correct: 0.50 * 0.50 = 0.25
Odds of Guessing Tails Correct: 0.50 * 0.50 = 0.25Baseline = 0.50**2 + 0.50**2 = 0.50
不平衡的结果
现在我们来看一个不是 50/50 的。假设结果是 75/25。我们现在将对猜测进行加权,这样我们可以在 75%的情况下预测大多数结果。这个随机速率猜测策略看起来像这样
Odds of Guessing Minority Correct: 0.25 * 0.25 = 0.0625
Odds of Guessing Majority Correct: 0.75 * 0.75 = 0.5625Baseline = 0.25**2 + 0.75**2 = 0.625
如果我们以这个速度猜测,我们的正确猜测率只有 62.5%。任何在这个基线上改进的机器学习模型都是增值的,但也必须高于零或 75%的阈值才能用作预测器。
我们的投票示例
那么我在本文开头描述的投票模型到底做得怎么样呢?它高于零基线,所以这个模型是有用的。如果我们猜测实际速率,我们还可以找出我们的基线,然后将其与我们的模型准确性进行比较。
Odds of Guessing Democratic Correct: 0.16 * 0.16 = 0.0256
Odds of Guessing Republican Correct: 0.84 * 0.84 = 0.7056Baseline = 0.16**2 + 0.84**2 = 0.73
所以用随机加权猜测,我们只能预测 73%的县。我们的实际准确率是 86%。这比加权猜测的理论值提高了 13%。这个看起来没什么前途的模型,无疑增加了重要的价值。它也在 ZeroR 基线之上,所以这个模型对这个问题很有用。
多类问题
你能为多类问题这样做吗?当然可以。
我最近做了一个 Twitter 情绪分类器,它将一条推文的情绪分为积极、消极或无情绪。这些班级在以下方面不平衡:
No emotion toward brand or product 0.593
Positive emotion 0.328
Negative emotion 0.080
使用我们的猜测策略的理论基线是:
0.593**2 + 0.328**2 + 0.080**2 = 0.465633
我们的实际准确率是 0.81,所以机器学习给我们的理论基线增加了 34%。这很重要。更重要的是,如果我们对每一个结果都预测了“无情绪”,我们的准确度也远高于 0.59 的零值。
要点和建议
- 你的模型必须比零规则(ZeroR)做得更好,才能在预测中有用。这是无法回避的。
- 您可以将您的模型与随机猜测的理论基线进行比较,并使用它来评估您的模型的有用性。
- 您可能会发现其他一些有用的基线(统一猜测、随机猜测和一个规则就是其中的几个)。
- 查看sk learn . dummy . dummy classifier,它为以下基线策略提供了自动化解决方案:、【分层】、【最频繁】、【先验】、【统一】、【恒定】。
- 当评估不平衡分类问题的准确性时,考虑查看 AUC。
- 在构建模型之前创建基线,并建立用于评估最终模型的规则。
此处展示的技术为您的模型性能提供了一个“现实检查”,对于广大观众来说是可以理解和解释的(我可以很容易地用非技术演示来解释这一点)。他们帮助我评估和理解我自己的模型,我希望你也能发现它们有用。
计算火灾探测的可靠“黄金时间”
将关于野火的空间信息转换成基于时间的信息。线性回归增加了可信度。
在 Alchera Inc .工作期间,我被分配到视觉异常检测技术产品部门工作,目前我们正在从事基于摄像头的烟雾和火灾检测。野火缓解空间中的典型对话领域是“黄金时间”,即从着火事件到需要检测它以防止它变成灾难之间的时间量。虽然有许多因素在起作用,但下面的文章是我试图对火灾探测的黄金时间进行适当的分类,以便根据部署位置为我们的火灾探测系统提供一个明确的基准。
在我开始之前,我想说清楚野火的灾难是什么。如果不对“灾难”一词进行定义,黄金时间的概念也会过于主观。我将“野火灾难”定义为一场超出消防员在“失控”之前将其扑灭的能力的火灾。那么,让我把‘失控’的意思说清楚。我建议,考虑控制火灾的实体,如果火灾蔓延范围/速度,经济损失,灭火花费的时间等。变得不可预测,不可计算,火势处于‘失控’状态。现在我准备好继续问题/解决方案分析了。
问题:关于防止野火失控的最晚可能时间,没有确定的“基于时间”的信息。
解决方案:利用既定的可防御空间面积、火势蔓延速度、风力条件和湿度数据,我们可以创建一个代理公式来计算给定位置的黄金时间。
可防御空间是“建筑物周围的自然和/或景观区域,经过维护和设计以降低火灾危险。在野火的情况下,该术语尤其用于荒地-城市界面(WUI)。”这个空间降低了火势从一个区域蔓延到另一个区域或一个结构的风险,并为消防队员提供了通道和一个更安全的区域来保卫受威胁的区域。这意味着,即使在森林中的随机区域发生火灾,只要它在可防御的空间内,消防员就可以阻止它进一步蔓延。
根据 CalFire 网页上的一篇文章,防御空间有两种类型的区域。1 区从建筑物延伸 30 英尺(如果发生野火,它将是起火点)。区域 2 从建筑物或着火点向外延伸 100 英尺。现在我们有了野火的空间数。
然后,韩国国立森林科学研究所(NIFOS)进行了一项实验。他们根据风速和土地坡度测试了火势蔓延的速度。以下是 NIFOS 实验的结果。
作者图片
地势越陡,火势蔓延越快。此外,大风会导致火势蔓延得更快。虽然需要更多的原始数据来获得更好的准确性,但为了制定一些通用的代理公式,我进行了多元线性回归。
(当然,它可以是取决于变量的二次函数;然而,为了简单起见,让我们假设它是线性关系)
作为线性回归的结果,X1(风速)的系数是 1.245625,X2(土地坡度)的系数是 0.170425,Y 截距是-2.58388;
为了计算可防御空间的黄金时间,我们用传播速度来划分空间范围。
作者图片
- 100 英尺= 30.48 米
- 30.48 米/传播速度(按米/分钟)=黄金时间(分钟)
因此,我们黄金时间计算的结果如下:
作者图片
作者图片
因为基本的线性回归公式由于数据相当缺乏而相当极端,所以我们可以在低风速和低坡度的情况下稍作调整以使数字合理。可以将 Y 截距设置为 0,这个数字看起来更有说服力,但与 NIFOS 数据相比有些保守(图片由作者提供)
从分析中可以看出,野火的黄金时间会因位置而异,只要我们知道位置的坡度并监控该区域的风速,就有可能为任何给定的位置创建实时黄金时间。例如,美国的加利福尼亚州是全球最大的野火危害区之一,从春季到秋季野火最为频繁。在此期间,加州洛杉矶的平均风速约为 3.2 米/秒。假设加利福尼亚的一个位置有 10°的坡度,基本线性模型(LM)给出 9.8 分钟的黄金时间,调整后的 LM 给出 7.7 分钟的黄金时间。
虽然这是一个合理的估计,如果不是粗略的话,但仍然有一个变量没有包括在内:湿度。有理由认为湿度会极大地影响火势的蔓延。理想情况下,上述分析还应包括上述线性回归中的湿度。不幸的是没有足够的原始数据。尽管如此,还是有必要看看湿度是否与火势蔓延呈负相关。
两篇著名的论文论述了这个问题。根据湿度和温度对火焰在滤纸上向下蔓延的影响(2000) 由铃木、Kushida 和 Dobashi 提出,绝对湿度和相对湿度都与火焰蔓延速率负相关。它说火焰传播速度随着湿度的增加而降低,当绝对湿度高于临界值时,火焰传播速度变为零。下面是一个图表。
铃木,Kushida,Dobashi (2000),湿度和温度对滤纸上向下火焰蔓延的影响,日本东京 113–8656()T4【https://pdf . semantic scholar . org/38 a2/0647392 C9 c 145 CFB 8 f 76173088 EC 79 f 38 c 7b . pdf
此外,相对湿度对波兰中部森林火灾的影响研究了湿度和野火点燃次数之间的关系,条件是与湿度相关的环境因素。表 3 显示,火灾爆发与相对湿度之间通常存在负相关关系。
konca-kdzierska,Pianko-Kluczyńska (2018 年),*相对湿度对波兰中部森林火灾的影响,*波兰波德莱娜 61,01–673(https://content . science do . com/download pdf/journals/FRP/79/3/article-p269 . XML)
要提供尽可能精确的计算,这一篇文章是不够的;我们需要用更多的原始数据进行另一个实验,将所有四个变量(三个自变量和一个因变量)考虑在内。然而,值得注意的是,本文提出的方法是可行的,并适用于实际计算。
不管怎样,我相信我们已经提出了最可靠的方法来计算野火探测的黄金时间。利用这一点,我们的目标是将这一计算引入我们的火灾探测工作,为我们的客户增加情景意识。Alchera Inc .目前正在加州各地的摄像机上部署基于机器视觉的火灾检测,在 2020 年已经捕捉到数百起早期野火点火,并在 2021 年继续这样做。
关于 Alchera: Alchera Inc .是一个人工智能专家团队,他们解决需要人工智能但受资源限制的问题。凭借世界级的速度和准确性,Alchera 将系统和硬件不可知的 AI 技术部署到影响社会的行业。
[参考]
[1]https://en . Wikipedia . org/wiki/Defensible _ space _(fire _ control)
[2]https://www . readyforwildfire . org/prepare-for-wild fire/get-ready/defensible-space/
[3] 2016.03.23.韩国보도자료国立森林科学研究所
[4]铃木,Kushida,Dobashi (2000),*湿度和温度对滤纸上向下火焰传播的影响,*日本东京 113-8656
[5]Konca-kdzierska,Pianko-Kluczyńska (2018),*相对湿度对波兰中部森林火灾的影响,*波兰波德莱娜 61,01–673
计算和设置阈值以优化逻辑回归性能
如何创建一个简单的类来优化精确度、召回率、f1 分数、准确度、TPR-FPR 或定制成本函数的阈值
背景
我已经了解了逻辑回归、混淆矩阵、ROC 曲线、阈值等。我参加过各种数据科学课程,但我从未完全理解它们,并希望更详细地探索它们。
此外,我还在网上看到了各种例子,说明如何在给定阈值的情况下重新计算真假分类,但这些例子没有提供我在现实世界中使用阈值所需的细节。
我怀疑可能有一种方法可以将阈值优化封装到一个简单的面向对象的类中,这样我就可以在将来轻松地使用它们,因此本文记录了我实现这些目标的学习之旅。
准备
让我们从导入我们将需要的库开始…
我们还需要一些数据来操作。我选取的数据是来自 ka ggle—https://www . ka ggle . com/c/credit-default-prediction-ai-big-data/overview的银行信用违约数据。
我对这些数据进行了一些清理,包括处理空值、转换分类特征和平衡数据以均匀地表示真假分类,这超出了本文的范围。下面导入的数据包括所有这些数据清理步骤…
作者图片
让我们通过将数据分为测试和培训来完成准备工作,这样我们就可以根据培训数据进行优化,稍后再回到测试数据上来…
((4754, 32), (1189, 32), (4754,), (1189,))
标杆管理
初步分析
好了,让我们对测试数据进行基本的LogisticRegression
拟合,然后查看结果…
array([0, 0, 0, ..., 1, 0, 0], dtype=int64)
混淆矩阵的可视化将有助于我们评估性能…
作者图片
银行数据被用来预测哪些客户会继续违反他们的信贷协议,哪些不会违约。
我们可以直接看到,一个基本的逻辑回归有 79%的准确性,预测了 352 个客户将违约,3395 个客户不会违约。
听起来很不错,对吧?好吧,如果我是接收这个算法的经理之一,我的第一个问题会是——“那 934 个假阴性呢?”。有近 1000 名客户没有被算法预测为违约,而是继续违约。
如果银行默认账户的平均成本是 10,000 英镑,我的数据科学团队刚刚让企业损失了 934 万英镑,对此我肯定不会满意!
这个简单的分析揭示了三个关键点-
accuracy
测量可能并不总是评估分类算法性能的最佳方式。- 分类算法的优化方式在很大程度上取决于企业想要实现的目标。
- 必须对算法进行适当的优化,以实现预期的业务成果。
进一步分析
更深入的挖掘将揭示我们基本算法性能的所有关键指标-
accuracy = 0.7881783761043332 precision = 0.8282352941176471
recall = 0.2737169517884914
f1 score = 0.4114552893045003
true positive rate (tpr) = 0.2737169517884914
false positive rate (fpr) = 0.02104959630911188
tpr-fpr = 0.2526673554793796
我通常也会看一下 ROC(受试者工作特性)曲线
作者图片
黑点代表最佳点的一种解释。
一种可用于计算 ROC 曲线上最佳点的方法是𝑇𝑃𝑅−𝐹𝑃𝑅,其中𝑇𝑃𝑅=的真阳性率和𝐹𝑃𝑅=的假阳性率。𝑇𝑃𝑅−𝐹𝑃𝑅达到最大值的点是最佳点。
该图显示,如果我们将逻辑回归的阈值设置为 0.31261,而不是默认值 0.5,那么我们将优化𝑇𝑃𝑅−𝐹𝑃𝑅.的逻辑回归算法
快速回顾一下阈值
如果所有这些关于阈值的讨论令人困惑,有许多在线文章将解释细节,但最简单的设想是这样的
我们数据的每一行将被分类为Default=True
或Default=False
。逻辑回归为每一行分配一个带来True
的概率,然后对每一行进行预测,其中该概率为> = 0.5,即 0.5 是默认阈值。
一旦我们对其工作原理有了更多的了解,我们就可以使用 0.5 的默认值来改进和优化我们预测算法的结果。
分析结论
根据这个快速分析,证据表明我们可以做得比接受默认阈值 0.5 更好,默认阈值是在作为sklearn.linear_model
库的一部分的LogisticRegression
算法中实现的。例如,我们已经知道,如果我们改变默认值为 0.31261,我们将优化𝑇𝑃𝑅−𝐹𝑃𝑅TPR−FPR.
然而,没有简单的方法来改变LogisticRegression
类中的阈值,通常数据科学家将手动完成这一点,并在多个项目中重复工作。
我们需要的是一个简单的类,每当我们想要优化阈值时,它就会为我们做这件事。
自动化阈值计算
这是我第一次尝试编写一个类来扩展LogisticRegression
类,以优化基于𝑇𝑃𝑅−𝐹𝑃𝑅TPR−FPR 计算的阈值。它由一个类定义、一个名为threshold_from_optimal_tpr_minus_fpr
的方法和一个predict
方法组成,后者覆盖了基类方法,使threshold
参数能够被传入…
有了这个新的实用程序类,我们现在可以轻松地将训练数据与它相匹配,要求该类告诉我们𝑇𝑃𝑅−𝐹𝑃𝑅TPR−FPR 的最佳阈值,然后使用该阈值返回一组新的预测…
(0.3126109044627986, 0.3383474055618039)
作者图片
嗯,这种优化确实改变了结果的形状,如混淆矩阵所示。假阴性和真阴性减少了,而假阳性和真阳性增加了。
这个发现让我问了一个问题——“还有什么其他的优化方法?”
精确和召回的快速回顾
评估分类算法结果的另一种方式是绘制混淆矩阵的精确度和召回率,而不是 FPR 和 TPR。
快速提醒一下,精确度和召回率的计算如下-
作者图片
即精度是混淆矩阵的右手列,精度是底行。
𝑇𝑃𝑅−𝐹𝑃𝑅通常用于挑选 ROC 曲线上的最佳点,而 F1 分数可以用于挑选精度-召回曲线上的最佳点。F1 分数的计算方法如下-
作者图片
F1 分数是精确度和召回率的调和平均值。我们使用调和平均值而不是简单平均值,因为它会惩罚极值。
我们默认算法的精确度和召回率的关系图如下所示-
作者图片
这里我们可以看到最佳(即最大)F1 分数是 0.5237148537347345,最佳精度和召回率分别是 0.41 和 0.72。从算法中产生这个结果的阈值是 0 . 32660 . 386383863686
自动化阈值计算需要 2
扩展LogisticRegression
类的第二次尝试增加了一种优化 F1 分数的新方法,以产生最佳精度和阈值-
现在,我们可以很容易地使用该类的新版本来告诉我优化 f1 分数所需的阈值,然后使用该值来微调算法,以获得最佳精度和召回率…
(0.3126109044627986, 0.5237148537347345)
作者图片
这个版本大大减少了假阴性,代表了最大可能的优化精度和召回。
现在想象一下,我把新模型带回给银行的管理团队,他们说“嗯,这是一个改进,但我们必须召回 90%的产品,这种模型才能有效”。
记住,回忆是𝑇𝑃/(𝑇𝑃+𝐹𝑁)而此刻这个模型有 922 / (364+922) = 71.7%。
我们需要向管理团队解释召回率和精确度是相互权衡的,因此如果模型被调优为 90%的召回率,精确度肯定会降低,但是如果这是可以接受的,如何实现呢?
自动化阈值计算需要 3
第三次尝试增加了两种新方法来计算给定特定召回(和精度)所需的阈值,现在可以使用这两种方法来实现管理团队要求的性能-
(0.19142214362243234, 0.35382262996941893)
作者图片
我们可以看到,管理团队要求的召回已经实现,因此精确度从 41.3%降到了 35.4%。
自动化阈值计算需要 4
在这一点上,我有点忘乎所以了,我想要一个可以实现自定义成本函数的优化版本。
让我们假设管理团队现在给我们以下新信息-
- 每一个真负值意味着我们可以向不会违约的客户销售 10,000 份额外的信贷产品。
- 每一次误报都会让我们损失 1000 英镑,因为我们本可以吸引这些客户,但我们却避开了他们。
- 因为我们未能干预并阻止这些客户违约,所以每一次假阴性都会让我们损失 1500 英镑。
- 每一个真正的积极有助于我们防止信贷违约,每一个都产生 20,000 英镑的新收入。
实现这一点的“成本函数”很容易构建
再做一点工作,我们可以修改我们的类,计算出优化这个成本函数所需的阈值,然后应用它-
…可以按如下方式使用-
(0.4324142856743824, -40033500)
新的混淆矩阵看起来像这样…
作者图片
…这是我们的自定义成本函数值与阈值的关系图…
作者图片
阈值计算自动化—最终版本
鉴于我已经意识到最佳精度的阈值可以使用与定制成本函数非常相似的方法来计算,我想我会将其添加到最终版本中。
毕竟,许多数据科学竞赛确实是基于准确性进行评估的,尽管我已经开始考虑这并不总是,事实上也不经常是分类算法有效性的最佳衡量标准。
也就是说,当我将使用训练数据计算的最佳准确性阈值插入到测试数据中时,它将预测的准确性提高了整整 1%,这在数据科学竞赛中可能会有所不同!
LogisticRegressionWithThreshold
类的最终版本增加了一个新方法来计算优化精度所需的阈值
(0.5654501621491699, 0.7968026924694994)
这是最佳(最高)精确度的混淆矩阵…
作者图片
…这是精度与阈值的关系图…
作者图片
结论
我们已经看到,有许多优化逻辑回归的方法,这些方法可以顺便应用于其他分类算法。这些优化包括为精确度、召回率、f1 分数、准确度、TPR-FPR 或定制成本函数的优化寻找和设置阈值。
我们还看到,所选择的优化严重依赖于期望的业务成果。
我们已经看到,sklearn.linear_model
中的LogisticRegression
类无法设置阈值来优化算法,但是我们可以使用本文中开发的LogististicRegressionWithThreshold
类来让我们即时访问所有必要的功能,以便根据期望的业务结果来调整基本算法。
完整的代码可以通过以下链接在 GitHub 上找到
感谢您的阅读!
如果你喜欢读这篇文章,为什么不看看我在 https://grahamharrison-86487.medium.com/的其他文章呢?
此外,我很乐意听到您对这篇文章、我的任何其他文章或任何与数据科学和数据分析相关的内容的看法。
如果你想联系我讨论这些话题,请在 LinkedIn 上找我—https://www.linkedin.com/in/grahamharrison1或者发邮件给我ghar rison @ Lincoln college . AC . uk。
用 OSM 数据计算建筑密度
介绍
OpenStreetMaps 是一个很好的空间数据源。大多数通用编程语言都有从 OSM 下载数据的包。
在本教程中,我将展示如何使用 R 的 osmdata 包下载建筑数据,执行密度分析,并使用 ggplot 绘制,以及交互使用 tmap。
这需要一些空间数据结构的知识。
获取数据
第一步需要使用 osmdata 从 OSM api 下载数据。首先,我需要为 OSM 设置一个边界框来搜索数据。接下来,我将下载用于制作 choropleth 地图的行政边界。最后,我将为定义的边界框下载建筑数据。
设置搜索区域
我将在土耳其的伊兹密尔市搜索数据。为了定义我的搜索,我将使用getbb
命令。该命令将位置名称作为字符串,并返回由 OSM 定义的边界框。也可以返回一个多边形的边界框,这很有用,因为我想搜索由行政边界定义的建筑物。
因为该函数返回一个矩阵,所以您可以使用自己的多边形来定义 OSM opq
查找(如下),但是确保数据的 CRS 是 EPSG:3857 是很重要的。
获取边界多边形
检索边界线
在这个项目中,我正在寻找伊兹密尔的街区边界。因为各国的行政级别界限并不统一,所以可能需要进行一些研究来确定需要什么样的行政级别。幸运的是,他有一个有用的工具,可以让你在交互式地图中找到 OSM 的边界。
地区名称旁边的数字表示 OSM 的行政级别。在我的例子中,我在 8 级寻找界限。我可以使用osmdata
请求特性传递这个信息,它是 OSM API 的包装器。
检索 OSM 边界线
(注意:OSM 有更多可用的地图功能,可以使用右键键:值对进行查询。)
该函数返回一个 osmdata 对象,这是一个sf
数据帧的列表。每个数据帧由不同的几何类型组成,这意味着返回的对象可能很大。为了得到正确的数据,你需要知道你在寻找哪种几何图形。
在这种情况下,我需要的形状是多多边形几何类型。OSM 查询最终会返回大型对象。为了保留一些空闲空间,我将删除多余的数据帧。我还会清理一些数据。
清理边界数据
现在我想检查一下我是否有正确的界限。
原始边界多边形的 OSM 边界线
看起来不错,但是它也返回了所有外围区域的边界,因为它们可能落在边界多边形线上。这是我以后可以处理的事情。
检索建筑
使用与上面相同的过程,查询 OSM 原始边界多边形:iz_bbox
内的所有建筑物。建筑物多边形对象将比我的边界对象大 100 倍,所以我将再次去掉多余的数据。这一次我将保持多边形 sf 对象。
然后我会画出结果。
在边界多边形上打印建筑多边形
返回的建筑物并不真正遵循任何多边形的边界,所以现在我将做一些空间修剪。
剪裁点数据
为了过滤掉所有的外围建筑,我需要将它们作为点来计算,这可以通过找到它们的质心来完成。我将使用建筑质心创建一个新的数据框。在此之前,我想计算所有建筑物的面积,这样数据就可以与新创建的数据框一起使用。从现在开始,我不再需要建筑多边形了。
我还需要创建一个多边形几何图形,以过滤外围建筑。我可以用原来的边界框iz_bbox
来做这件事。但是,因为这个对象是一个矩阵,我需要把它转换成一个 sf 对象。这可以通过使用sf_headers::sf_polygon
来完成。
红色的多边形是目标区域,我可以使用这个多边形来裁剪建筑数据
现在我有了一个可以过滤点的多边形。首先,我必须创建一个允许我过滤的数据框架。将st_join
连接变量设置为st_within
将给出一个列,指示一个点是否在多边形数据框内。列id
被创建,1 表示一个点落在多边形内。我将策划检查结果。
将质心构建为边界多边形内的点
它工作了,所以现在我将过滤正确的点,然后从iz_polys
数据帧创建一个新的数据帧,但是使用过滤的点。
使用更精细的数据框架,我可以对每个地区内所有建筑的总面积进行汇总和求和。我将创建一个最终的数据框,其中包含总建筑面积以及地区多边形的总面积。
现在我将使用tmap
创建一个漂亮的交互式地图。
互动图截图。看这里的实物:https://greggsaldutti . netlify . app/post/2021-05-05-calculating-building-density-in-r-with-osm-data/
结论
这里我们有一张建筑的面积密度图,以占总土地面积的百分比来表示。当你有很多数据要处理,或者需要以编程方式访问数据时,r 是一个很好的工具。其他程序,如 QGIS,可能对用户更友好,但是 R 给你更多的控制,也能制作漂亮的地图。
注意:这篇文章基于 Matt Herman 关于纽约树木的文章,以及这个使用 Python 的伟大开源 GIS 课程。
原载于 2021 年 5 月 5 日https://greggsaldutti . net lify . app。
在 BigQuery 中计算内部收益率(IRR)
在 BigQuery 中实现 Excel 的 IRR 函数的分步指南
内部收益率(IRR)是财务中经常出现的一种常见计算方法。在这篇博文中,我将展示如何在 BigQuery 中构建一个查询,该查询执行相当于 Excel 的 [IRR](https://support.microsoft.com/en-us/office/irr-function-64925eaa-9988-495b-b290-3ad0c163c1bc)
函数的计算。如果现金流存储在 BigQuery 表中,并且您希望在不将数据移动到 Excel 的情况下计算 IRR,或者如果您希望将 BigQuery 用作数据可视化和 BI 的来源,这将很有帮助。
1.背景:内部收益率(IRR)和净现值(NPV)
内部收益率(IRR)是投资产生的所有现金流的净现值等于零的收益率。它主要作为一个决策规则:一项投资的一系列现金流的内部收益率越高,超过资本成本的金额越大,该项投资就越有利可图。
从数学上讲,IRR 是求解以下方程的r
的值:
这与以下内容相同:
这里,t
是时间段(从 0 到N
),CF
是时间段t
的现金流,r
是收益率(IRR)。
上述方程没有解析解。换句话说,没有数学公式可以给我们内部收益率。解决这个问题的唯一方法是用数值方法,尝试r
的多个值,看看哪一个最接近满足这个方程。
对于r
的任何给定值,上述等式的左侧给出了净现值:
2。示例使用 Excel 的 IRR 函数计算 IRR
在本指南的其余部分,我们将使用下面的简单示例。让我们假设我们在文件irr.csv
中存储了以下现金流
PERIOD, CASHFLOW
0, -10000
1, 2000
2, 6000
3, 6000
我们可以用 Excel 的IRR
函数来计算内部收益率。 Excel 的文档对IRR
函数描述如下:
返回由数值中的数字表示的一系列现金流的内部收益率。这些现金流不必像年金一样均匀。然而,现金流必须定期发生,例如每月或每年。
在 Excel 中计算 IRR 相当简单:
我们的目标是在 BigQuery 中实现这一点。
3.现在净价值
a. 首先,让我们在 BigQuery 中计算上述现金流的净现值。我们可以使用 BigQuery 控制台轻松地将irr.csv
数据导入到 BigQuery 表中。在本指南中,生成的表被命名为tutorial.irr.cashflows
b. 一旦创建了表,我们就可以运行下面的查询,该查询返回一个包含每个现金流现值的附加列:
SELECT
period,
cashflow,
cashflow/POWER(1+0.16, period) AS present_value
FROM
`tutorial.irr.cashflows`
ORDER BY
period
BigQuery 输出以下查询结果:
c. 净现值就是现金流的现值之和。因此,我们可以使用 SUM aggregate 函数来获得现金流的净现值:
SELECT
SUM(cashflow/POWER(1+0.1614, period)) AS net_present_value
FROM
`tutorial.irr.cashflows`
BigQuery 输出以下查询结果:
净现值接近于零,这验证了我们从 Excel 得到的结果,即 16.14%是 IRR 的近似值。
4.内部收益率
答。现在我们知道了如何计算净现值,我们的目标是找到r
的一系列值的净现值,并选择最接近零的一个。为了生成r
的一系列值,我们将利用 BigQuery 的GENERATE_ARRAY
函数。下面是来自 BigQuery 的官方文档对GENERATE_ARRAY
函数的简要说明:
[GENERATE_ARRAY](https://cloud.google.com/bigquery/docs/reference/standard-sql/array_functions#generate_array)
根据起始值、结束值和步长值生成一个值数组。例如,以下查询生成一个数组,其中包含从 11 到 33 的所有奇数,包括 11 和 33:
SELECT GENERATE_ARRAY(11, 33, 2) AS odds;
+--------------------------------------------------+ | odds | +--------------------------------------------------+ | [11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33] | +--------------------------------------------------+
b 。为了说明我们将如何找到 IRR,让我们考虑一小组r
[0.14, 0.15, 0.16, 0.17, 0.18, 0.19]
的值作为 IRR 的猜测值。(我们稍后将考虑更大范围的值。现在,假设我们知道 IRR 在上述范围内。我们从前面的计算中知道,IRR 最接近 0.16。)以下查询为这些猜测值中的每一个生成净现值:
SELECT
guess,
SUM(cashflow/POWER(1+guess, period)) AS net_present_value
FROM
`tutorial.irr.cashflows`
CROSS JOIN
UNNEST(GENERATE_ARRAY(0.14,.19,0.01)) AS guess
GROUP BY
guess
我们可以看到,当猜测值等于 0.16 时,结果表中的净现值最接近于零。
我们的下一个任务是编写一条 SQL,给出净现值最接近于零的r
的值(即 IRR)。以下查询通过使用公用表表达式来实现这一点:
WITH
npv_table AS (
SELECT
guess,
SUM(cashflow/POWER(1+guess, period)) AS net_present_value
FROM
`tutorial.irr.cashflows`
CROSS JOIN
UNNEST(GENERATE_ARRAY(0.14,.19,.01)) AS guess
GROUP BY
guess)
SELECT
guess AS IRR
FROM
npv_table
WHERE
ABS(net_present_value) = (
SELECT
MIN(ABS(net_present_value))
FROM
npv_table)
BigQuery 输出以下查询结果:
d. 现在我们知道了如何计算 IRR,我们可以考虑使用下面的查询来计算GENERATE_ARRAY
函数中r
的更大范围的值:
WITH
npv_table AS (
SELECT
guess,
SUM(cashflow/POWER(1+guess, period)) AS net_present_value
FROM
`tutorial.irr.cashflows`
CROSS JOIN
UNNEST(GENERATE_ARRAY(0,2,.0001)) AS guess
GROUP BY
guess)
SELECT
ROUND(guess*100,2) AS IRR_percentage
FROM
npv_table
WHERE
ABS(net_present_value) = (
SELECT
MIN(ABS(net_present_value))
FROM
npv_table)
BigQuery 输出以下查询结果:
这与我们从 Excel 的 IRR 函数中得到的值完全相同。(在最终查询中,IRR 值已被格式化为小数点后两位的百分比。)
感谢阅读!请在评论中分享反馈。
使用 DAX 幂 BI 计算负数和正数的增长率百分比
简单但复杂的算术
计算百分比变化的常用方法(【A-B/| B |)在涉及负数的情况下不起作用,但我有一个更好的替代方法,可以让你的工作保持干净和敏捷。
用 A-B/ABS(B) 计算增长率似乎是大多数分析师的标准,我们经常忽略这样一个事实,即我们所依赖的简单公式并不是在所有情况下都是正确的。
我最近完成了一份报告,正在向团队展示结果,一名成员要求我延长报告的时间线,其中包括一些负增长期,我随意延长了过滤器,令我惊讶的是,结果显然是错误的。
我回到我的 DAX 公式,看看我是否将 absolute ABS() 应用于分母,是的!我做了,但我的结果仍然是错误的,这使我开始思考负数会如何影响我们的百分比增长率计算的输出。
为了更清楚起见,我读了几篇文章,这篇来自 Linkedin 上Ismael的帖子解释了相对增长率脱颖而出,阐明了我们在计算增长率时经常忽略的灰色区域。
做了一些谷歌搜索,我看到一些分析师使用不同的方法来解决这个问题,懒惰的方法通常涉及返回空白()或零,其中任何值小于零。另一种方法是创建一个回报 P 或 N(正或负),以掩盖我们亲爱的公式“A-B/ABS(B)”的低效率。
在阅读了这么多关于如何解决这个问题的文章后,Excel 超级用户论坛来帮忙了。来自论坛的超级用户(塔赫尔·艾哈迈德)建议考虑不同的场景,并使用 If 函数来解决问题。
下面是我最后的 DAX 查询,它最终处理了所有可能影响百分比增长计算的场景,并为任何使用 DAX 的人解决了这个问题
Net Value - Growth Rate MoM% =
VAR _PREV_MONTH =
CALCULATE ( [Net Value], DATEADD ( 'Calendar Table'[Date], -1, MONTH ) )VAR _CURR_MONTH =
CALCULATE ( [Net Value] )VAR _RESULT =
IF (
AND ( AND ( _CURR_MONTH < 0, _PREV_MONTH < 0 ), _CURR_MONTH < _PREV_MONTH ),
( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) * -1,
IF (
AND ( AND ( _CURR_MONTH < 0, _PREV_MONTH < 0 ), _CURR_MONTH > _PREV_MONTH ),
( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ),
IF (
AND ( _CURR_MONTH < 0, _PREV_MONTH < 0 ),
( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) * -1,
IF (
AND ( _CURR_MONTH > 0, _PREV_MONTH < 0 ),
( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) * -1,
IF (
_PREV_MONTH < _CURR_MONTH,
( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ),
IF (
_PREV_MONTH > _CURR_MONTH,
( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ),
ABS ( ( ( _CURR_MONTH - _PREV_MONTH ) / _PREV_MONTH ) )
)
)
)
)
)
)RETURN
_RESULT
以下是对计算增长率百分比时预期的不同情景的简单解释,所有这些都用上述 DAX 公式进行了完美的处理(简单的说明归功于 Taheer
- A>0,B>0,A
- A>0,B>0,A>B
- 一个<0, B> 0,|一个
- A <0, B> 0,|A|>B
- A>0,B <0, A
- A> 0,B<0, A>| B | 0
- A <0, B<0, |A|
- A<0, B<0, |A|> |B|
下一次,当您使用 DAX 在 Power BI 报告中计算增长率百分比时,请仔细考虑您的公式,并考虑利用上面的片段。
在 Linkedin 上关注我以了解我的故事
这个片段在 GitHub 上——叉出来!
计算数据科学项目的商业价值
性能度量不能告诉你你想知道的:一个项目实际上有多大价值
照片由 Unsplash 上的 israel palacio 拍摄
数据科学非常关注各种性能指标。数据科学家将花费几个月的时间来尝试改进项目的各种性能指标。问题是,不清楚所有这些努力是否真的有价值。如果你只看性能指标,就不可能知道你是否增加了你的模型所提供的价值。
绩效指标不知道你的预测有多大价值。举一个例子,F1 分数明确地对精确度和召回率赋予了同等的权重。在实践中,假阳性和假阴性通常有不同的业务成本。
您可以使用一百万种不同的指标来告诉您您的模型做得有多好。但是这些都没有告诉你利益相关者真正想知道的:这有什么商业价值?
金钱万能
什么是商业价值?归根结底,对于营利性企业来说,商业价值就是货币价值。
商业价值= $ $
这对数据科学家来说是个好消息:我们热爱数字。钱是量化的。
不幸的是,我们建造的东西和货币价值之间的联系并不总是简单明了的。
将数据科学项目与商业模型联系起来的最具体的方法之一是计算实现该模型对公司的底线意味着什么。这并不总是可能的,但它是一个有用的练习。通过查看我们可以计算显式值的情况,我们可以澄清联系不太清楚的领域。
计算模型商业价值的一个具体例子
让我们举一个简单的例子,我们正在为一个业务问题建立一个模型:在一个部件工厂检测制造缺陷。
我们知道,如果我们检测到一个有缺陷的部件,我们会扔掉它,导致生产成本的损失。更换有缺陷的部件的成本是 100 美元
如果我们未能检测到有缺陷的部件,我们会将部件运送给客户,然后必须更换他们的部件并支付新部件的运费。假设运输成本为 50 美元,加上替换小工具的 100 美元损失。
如果我们有一个预测缺陷部件的模型,我们就可以写出不同场景的成本:
真阳性:-100 美元用于关闭一个小工具
误报:-100 美元更换我们认为有缺陷的部件
真负值 : 0(我们认为“无缺陷”是比较成本的默认场景)
假阴性:-150 美元运送替换部件
此场景的成本矩阵
请注意,这相当于说假阳性的成本是 100 美元(假阳性和真阴性之间的差异)假阴性的成本是 50 美元(假阴性和真阳性之间的差异)。
现在,我们可以构建一个分类器,并为该分类器计算如果我们将该分类器用作筛选过程,缺陷的成本会是多少。评估模型的商业价值很简单——我们只需要在测试集上产生一个混淆矩阵。让我们举个例子:
然后,我们将每个结果的成本乘以该结果发生的次数比例:
(-1000.2) + (-1000.05) + (-150 * 0.05) + (0 * 0.8) = -32.50.
换句话说,平均来说,如果我们使用这种模式,由于缺陷,每个小部件我们将平均损失 32.50 美元。
我们可以将此与当前政策的成本进行比较。让我们假设目前没有缺陷筛选,所有的小部件都已发货。根据上面的混淆矩阵,25%的部件是有缺陷的。因此,要计算这项政策的成本,我们只需将 0.25 乘以运输缺陷产品的成本:
-150 * 0.25 = -37.50
这项政策的平均成本为每件 37.50 美元。因此,实施我们的模型来筛选小工具将为公司节省平均每个小工具 5 美元。
就是这样!我们已经计算了模型的商业价值。当然,在现实世界中,实施一项新政策可能会有成本,这些成本必须与实施该模型的计算收益进行比较。
不对称成本改变了最优决策阈值
有了明确定义的成本矩阵,我们就有机会微调我们的模型,以进一步降低成本。
默认情况下,大多数分类器使用 0.5 的概率决策阈值来确定标记积极或消极的内容,但对于不对称成本,这不一定是使用的最佳阈值。
例如,在这种情况下,假阴性的成本低于假阳性(假阳性为 100 美元,假阴性为 50 美元)。这将最优决策阈值推得更高;假阴性比假阳性成本低,所以我们应该更愿意接受假阴性。
下面是成本矩阵的成本曲线的简单模拟(请注意,成本曲线的最小值约为 0.7,因此这将是我们的最佳决策阈值):
不同概率阈值的成本曲线示例。成本已标准化,因此 1 是成本最高的方案。
因此,我们应该把任何预测概率在~0.7 以上的东西贴上有缺陷的标签,其他的都贴上没有缺陷的标签。
改变成本矩阵
认识到成本矩阵的改变不仅会改变模型的商业价值,还会改变最佳决策阈值,这一点很重要。
例如,假设公司里有人开发了一种新的有缺陷部件的测试。它很贵,所以我们不想在每个部件上都使用它,但是它明确地告诉我们一个部件是否有缺陷。如果这个测试花费 20 美元,我们的模型的成本矩阵会有很大的变化:
真阳性:-120 美元(100 美元的生产成本,另外 20 美元用于最终测试,以确保它是有缺陷的)
假阳性:-20 美元的最终测试费用,这将免除好的部件
真负值 : 0(我们再次考虑将“无缺陷”作为比较成本的默认场景)
假阴性:-150 美元运送替换部件
成本矩阵,如果我们有一个有缺陷的部件的决定性测试
因为假阳性的成本现在更低了,这就改变了收益曲线。我们现在应该更愿意出现假阳性,因为假阳性的成本没有假阳性高,而假阴性的成本仍然一样高:
随着成本矩阵的变化,成本曲线移动。成本已标准化,因此 1 是成本最高的方案。
使成本最小化的最优决策阈值已经转移到 0.3 左右。我们会将更多的部件标记为潜在缺陷,但这没关系,因为现在我们会将它们提交给进一步的测试,而不是扔掉它们。我们可以计算这个策略的总体成本,并将其与其他策略进行比较(例如,对每个小部件进行 20 美元的测试)。
在更模糊的情况下进行归纳
在现实世界中,我们很少遇到如此明确定义的问题。以这种方式定义一个业务问题就是我所说的数据科学的困难部分。
在现实世界中,成本并不为人所知,而且很少有直接的分类问题能够完全抓住业务问题的本质。然而,通过观察这些简化的案例,我们可以更清晰地处理更复杂的问题。认识到项目定义中的模糊或缺失是澄清问题并将其与带来最大商业价值的技术解决方案联系起来的第一步。
使用地理编码计算两个位置之间的距离
PYTHON。地理空间分析。位置数据。
如何使用 Python 计算两组地理编码之间的距离
塔玛斯·图兹-卡泰在 Unsplash 上的照片
介绍
你可能听说过著名的短语“位置,位置,位置”,例如人们想要强调位置对商业和房地产的中心地位。
然而,在数据分析和计算中,这个短语有点含糊不清。计算机理解“位置”概念的方式是通过我们所知的“地理编码”这些是经度和纬度,并且是特定于特定位置的。
注:对于那些想知道如何计算这些地理编码的人,我写了一篇关于这个的文章。
根据不同位置的地理编码,我们可以生成其他“特征”这个过程是地理空间特征工程的一个例子。
一个特别的特征是起点和目的地位置之间的距离。距离在许多机器学习问题中发挥着重要的作用,例如,客户和员工流失预测,客流量,以及在某些情况下,财富预测。
例如,某些研究表明,离兴趣点较远的员工和客户,比如一个分支机构或公司,流失的可能性更高。但是,仅使用地理编码,不可能生成此特征并因此在机器学习模型中使用它们。
但是,如何计算一组经度和纬度之间的位置呢?
一种方法是使用大圆距离公式。
大圆距离/哈弗线距离
大圆距离,有时称为正圆,或球面距离,是球面上两点之间的最短距离**。**
虽然不是一个完美的球体,地球表面上两点之间的距离因此可以近似为大圆距离。
假设我们有地理编码,公式如下:
作者配制的配方
作者配制的配方
请注意,在公式中,地理编码假定为弧度,而不是度。我们通常从网上或通过谷歌 API 等提供商获得的地理编码是分等级提供的。
PYTHON 代码
事不宜迟,下面是计算哈弗线距离的代码:
import numpy as npdef haversine_distance(lat1, lon1, lat2, lon2):
'''
Calculates the spherical distance between two sets of geocodes coming from an origin and a destination.
Parameters:
--------------
lat1: float
- latitude of the origin location in degrees
lon1: float
- longitude of the origin location in degrees
lat2: float
- latitude of the destination location in degrees
lon2: float
- longitude of the destination location in degrees
Returns:
--------------
Float distance in km.
'''
r = 6371 # radius of the Earth in Km
# Convert degrees to radians
phi1 = np.radians(lat1)
phi2 = np.radians(lat2)
delta_phi = np.radians(lat2 - lat1)
delta_lambda = np.radians(lon2 - lon1)
a = np.sin(delta_phi / 2)**2 + np.cos(phi1) * np.cos(phi2) * np.sin(delta_lambda / 2)**2
c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
d = r * c
return f'{d:.2f} KM'
让我们试试我们的功能:
作者图片
尝试从谷歌地图上查看实际距离,并验证这确实是一个很好的近似值。
结束语
大圆距离,或称哈弗线距离,是两个短距离位置之间的近似距离。
对于更长的距离,由于更多的道路障碍、堵塞和道路延长了整个路径,这种近似法就失效了。
为此,可以尝试使用 Google API 来计算两点之间的总距离。
参见我关于地理编码和访问 Google Maps API 的文章:
使用谷歌地图 API 生成地理编码
让我知道你的想法!
校准基于代理的细胞复制模型
解释现实世界细胞样本中的部分同步性
基于主体的模型提供了探索和解释世界的另一种方式。他们可以通过告知其行为的逻辑提供预测和解释力,特别是如果他们根据现实世界的数据进行校准。
在这篇论文中,研究人员构建了一个数学模型来预测细胞样本复制中发生的部分同步性。我很好奇,想看看我能否采取一种基于智能体的方法来解决这个问题,这是否也能让我解释这一现象。我将使用 HASH,一个基于代理的在线模拟平台来构建我的模型,并根据原始论文中使用的真实数据对其进行校准。
细胞复制
细胞在许多不同的阶段之间有规律地转换: G1 、 eS 和 S/G2/M 。它们只在这个周期结束时进行有丝分裂(复制),分裂成两个不同的细胞。由于这种加倍,细胞样品的生长呈指数增长,但仍然是离散的。因此,如果细胞样本是完全同步的(所有细胞处于周期的同一阶段,同时复制),绘制细胞数量随时间的变化曲线将不会产生平滑的曲线,而是离散的跳跃。
为了确保样品中的细胞生长是平滑的曲线,为生物实验室和分析准备了异步样品,细胞随机分布在不同的阶段。然而,实验数据显示,大多数样本的行为是部分同步的,而不是异步的。这是很重要的,因为研究和结果是基于平稳指数增长的假设。
让我们尝试创建一个模型来解释这种部分同步的行为。
模型
这个模型中的代理只需要一种行为:复制。这种行为将跟踪每个代理的细胞周期,并在达到适当的阶段时生成一个新的细胞。定义这种行为暴露了一条非常重要的信息。当细胞分裂时,产生的两个细胞都处于细胞周期的开始。他们已经同步。尽管我们的代理最初是在细胞周期的随机阶段产生的,但我们的细胞复制得越多,同步性就可能出现得越多。如果我们的模型与观察到的数据匹配得足够好,这可能是理解制备样本中部分同步性的关键。
我将通过在细胞周期的每个阶段初始化正确数量的代理来确保我的初始状态与数据一致。每种试剂都根据其当前的细胞周期阶段用不同的颜色标记,与原始论文中使用的颜色相匹配。有三个不同的图来解释我们系统的状态:总细胞的时间序列、按颜色计数的细胞的时间序列和 Q 的时间序列(基于每个周期中细胞数量计算的比率)。
你可以在这里找到型号。让我们看看我的第一个版本是什么样子的,与实际数据相比,我估计了每个周期的时间(模型是蓝色的,对比实验数据是橙色的):
总细胞生长(图片由作者提供)
各期细胞比例: Q(t) = R(t) / (Y(t) + G(t)) (图片作者提供)
总的形状看起来是正确的,细胞总数呈指数增长,Q 值也是振荡的,尽管离数据还很远。增长和振荡周期都太快了。让我们看看是否可以使用优化引擎使模型更接近数据。我们将尝试发现细胞周期中每个阶段长度的最佳值,并确定我们先前的关键观察是否是部分同步性的有效解释。
校准
通过检查数据,看起来我们的细胞周期应该是大约 70 步长。我将为细胞周期的长度选择一个数值范围*、G1* 、 eS 和 S/G2/M ,它们的总和大约在那里。我将提供它们作为优化引擎的潜在值
在 HASH 中定义优化实验(图片由作者提供)
我将创建一个定制代理来计算每个时间步的模型输出和实验数据之间的误差。该代理将使用简单的平方和来捕获错误,优化引擎将尝试减少该值。首先,让我们试着拟合第二张图中的曲线,该图根据细胞周期中的阶段对药剂进行计数。
总细胞生长—第一次校准尝试(图片由作者提供)
细胞分阶段生长—第一次校准尝试(图片由作者提供)
q 比率—第一次校准尝试(图片由作者提供)
在前两个图中拟合看起来很好,但是 Q 的第三个图看起来不太拟合。让我们将误差度量改为对应于 Q 中的误差。这意味着平方和计算将使用从模拟和数据集计算的 Q 比率。这是优化的结果:
总细胞生长—第二次校准尝试(图片由作者提供)
细胞分阶段生长—第二次校准尝试(图片由作者提供)
q 比率—第二次校准尝试(图片由作者提供)
q 现在有了一个更好的拟合,以其他两个图为代价。我将尝试合并这两个误差(按颜色的代理计数和 Q 比率),以便找到模型的最佳拟合。因为我从这些优化中获得了一些关于好的参数值的信息,所以我可以缩小实验定义的范围以提高其有效性。对于每个阶段的长度,我们将缩小到 5–10 之间的范围,而不是大约 20 个值的范围。
总细胞生长—第三次校准尝试(图片由作者提供)
细胞分阶段生长—第三次校准尝试(图片由作者提供)
q 比率—第三次校准尝试(图片由作者提供)
现在看来,我们已经找到了一组值,为第二个和第三个图提供了最佳的拟合平衡。每个阶段长度的最终值为:
- G1: 25 个时间步骤
- 埃斯:27 个时间步
- S/G2/M: 18 个时间步长
每个时间步长相当于 1/4 小时。
用基于主体的模型复制实验数据的能力提供了对导致系统以特定方式运行的机制的洞察。与黑盒方法不同,使用基于代理的模型使我们不仅可以预测细胞生长,还可以解释为什么它会部分同步发生。在这种情况下,我们可以假设,观察到的行为是因为细胞复制得越多,它们就越有可能与共享“母”细胞的其他细胞排成一行。
像这样的洞察力可以让研究人员、实验室技术人员和审查委员会对细胞样本的行为方式做出更好的假设,让他们在预期和实验结果之间做出更明智的比较。这只是一个例子;使用根据真实世界数据校准的基于主体的模型也可以改善我们在经济、政府和许多其他领域的假设。
呼唤属性图模式标准
重视人际关系。
属性图模式。图片作者。
我使用数据库作为图数据库已经有一段时间了,并且认真地研究了有向图的概念。我的观点是,有向图是看图的一种相当原始的方式。
上图是一个简单订单管理数据库的属性图模式。人们下订单,每个订单都包含一定数量的商品。订单、人员和物品是由边/关系连接的图论的图中的节点/顶点。有向图是指每个边/关系都有一个方向的图,如下所示:
有向图。图片作者。
微妙的区别在于,现在每条水平线(关系)都有一个指向一个方向的箭头。
我不觉得有向图特别有用。从本质上来说,关系是双向的。例如,对于每个由 人员下达的 订单,该人员 下达 订单。更不用说,在我们的数据库模式中,每个订单最多由一个人下。如果我们用箭头表示只能存在一个关系(作为该关系的实例),那么我们会将第二个图理解为每个订单只包含一个商品。显然,这不会是一个非常有用的数据库。****
对标准的呼唤
本文是对数据库行业标准的呼吁。如果我们要有属性图模式,让它们背后至少有一点逻辑和意义。
多对多关系。图片作者。
我的建议是,带有两个大箭头的边代表多对多关系。也就是说,在我们的模式中,一个项目可以有多个订单,一个订单可以包含多个项目。
我还建议:
- 如果关系包含一个大箭头和一个小箭头,则表明数据库中存在关系的反向读数;
- 带有大箭头和可选小箭头的关系表示该关系是多对一的。
多对一关系提案。图片作者。
例如,在我们的数据库中,许多订单可能由一个人下,而它的倒数…任何一个人都可以下许多订单。
为什么专门的图形供应商会锁定有向图?
在我对专用(本地)图形数据库所做的研究中,出现了简单的有向图概念,因为它反映了数据是如何存储在数据库的磁盘层的。也就是说,当数据库中的数据最终存储到永久介质中时,它的存储方式是焦点位于有向图的非箭头侧……相关的节点信息从该节点延伸到一个有效且复杂的一维数组中。
当数据被放入随机存取存储器时,一个更传统的图被开发出来,使得该图在概念上形成被称为无索引邻接的链接;更像是一个三维图形,因为随机存取存储器中的晶体管矩阵可以被认为是三维的。
数据科学是非常技术性的,但基本上,它归结为…如果你做你的研究,你会很容易地发现从业者抱怨图形数据库性能差,当图形数据库以这种方式而不是那种方式查询时,只有图形数据库供应商和专家告诉你,图形数据库的查询性能在很大程度上取决于你如何构造有向图。我甚至读到过这样的评论,有人抱怨说,为了达到他们所追求的查询性能,他们需要在混合中引入索引(放弃了无索引邻接所带来的好处的整个概念),数据库供应商的专家说了类似这样的话:“好吧,如果这真的是您想要做的查询类型,那么图形数据库可能不适合您”。即关系数据库将会是。
也就是说,这些都没有回答描绘关系的基数或它们的相互关系的问题。在我看来,将数据在磁盘级别存储的方式以及单个数据库如何工作融入到图形的概念中,并不是标准化属性图模式的任何方式。
为什么?
在我看来,答案很简单。世界正朝着多模型(关系和图形)数据库的方向发展,不管怎样,图形数据库供应商正在悄悄地向关系领域发展。
正在发生的情况是,专用图形数据库的营销材料几乎总是基于它们的索引而轻视关系数据库,只是转而告诉它们的数据库的用户“为了获得这种类型的查询所需的查询性能,你将需要一个索引”。
也就是说,图只是查看模式概念化的一种方式,如果我们无论如何都要在混合中加入索引的话,它也可以被看作是一个实体关系图。
也就是 所有的 要说…属性图模式最好像周围最好的实体关系图一样信息丰富,如果它们要让数据库专业人员相信的话,这些专业人员知道他们在谈论什么,并且希望概念模型在他们的意义上是清晰和信息丰富的。
我的业务是编写软件,将数据库概念化,就好像它已经是一个多模型数据库(关系或图形)。我之所以呼吁属性图模式的标准,是因为我发现简单的有向图太简单了。我觉得是时候让人们拥有概念模型了,它们尽可能地具有表现力,并且是数据库不可知的。当我创建一个属性图模式时,我更关心的是模型在概念上是否合理,而不是任何数据库的底层架构。在许多情况下,我可能甚至没有选择我想要使用的数据库。我当然不希望使用一个不能满足我的概念模型的数据库;我想使用那些 做 对概念模型表现良好的数据库。
让我们停止在图形数据库空间中遵从单个数据库供应商,并创建单个数据库供应商可以向往的标准。让我们抛弃旧的有向图的概念,转而使用同样表示基数的双向图。
感谢阅读。如果时间允许,我将写更多关于图数据库、关系数据库、多模型数据库和属性图模式的文章。
— — — — —结束— — — —
回调、布局和引导:如何在 Plotly Dash 中创建仪表板
数据科学家和分析师最重要的角色之一是以可理解的方式向利益相关者呈现数据和见解。创建仪表板是显示您在数据探索和机器学习建模中发现的东西的一种很好的方式。Plotly 提供了一个健壮的开源版本的库,用于构建仪表盘 Dash。此外,还有多个额外的开源库,使得在 Dash 中构建仪表板变得容易。本教程概述了使用 Dash 实现您的第一个多页面仪表板应用程序的一种方法。
Dash 是什么?
Dash 是一个框架,允许您创建高度可定制和交互式的数据可视化应用程序,这些应用程序仅使用 Python 在您的 web 浏览器中呈现。Dash 在 R 和 Julia 中也可用,但本教程将重点介绍 Python。Dash 中的仪表板构建在 Plotly、Flask 和 React 之上,能够部署到互联网上,并在移动设备上跨平台显示。本质上,Dash 能够创建 web 应用程序,而不直接使用 HTML 或 CSS。这里我们将重点介绍免费的开源版本,但是 Plotly 为 Dash 提供了一个企业版,用于管理企业仪表盘。
Dash 的关键要素
在我们深入细节之前,让我们回顾一下我们将在构建第一个多页 dash 应用程序时使用的一些关键想法:
- 布局&组件: 布局描述了您的仪表板的外观。这包括样式选择,如 CSS 脚本生成的字体和颜色,以及哪些组件将填充应用程序。
dash_core_components
和dash_html_components
库提供了 dash 应用程序的各种常用组件。HTML 组件是 HTML 标记的 python 版本,可以在 dash 应用程序中使用,允许您创建 div、显示文本、构建段落/标题等。你也可以像在 HTML 中一样给它们分配一个样式、一个类或者一个 id。核心组件是可以放在仪表板上的各种有用的元素,就像下拉菜单、图表、滑块、按钮等等。你可以在 Dash 的文档中找到许多额外的 Dash 组件库。 - 回调: 回调是 python 装饰器,控制你的 dash 应用的交互性。装饰器是一个包装另一个函数的函数,在它们装饰的函数之前和/或之后执行代码。在 Dash 中,回调装饰器使用该属性来查找用户对您的 dashboard 应用程序组件所做的更改,并执行您定义的任何相关更改。例如,您可以设置一个回调,从仪表板上的滑块组件获取信息,然后根据滑块的输入对图形进行更改。
- Bootstrap: 如果你已经熟悉 CSS,你可以通过编写自己的 CSS 脚本来设计你的 Dash 应用程序。但是,如果你不熟悉 CSS 或者不想花时间自己写,Bootstrap 是个不错的选择。Bootstrap 是一个流行的 CSS 框架,用于创建交互式的移动应用。faculty.ai 的
dash_bootstrap_components
库提供了 CSS 样式以及附加组件,如应用导航工具、可折叠内容、对话框等等。Bootstrap 使您能够创建包含组件的列和行,从而简化了内容的组织。这里有一个关于它如何操作的概要,查看文档了解如何将其翻译成 python。
开始使用您的仪表板
首先,您需要安装 Dash 和 Dash 引导组件(核心和 HTML 组件应该预装在 Dash 中)
$ pip install dash==1.19.0
$ pip install dash-bootstrap-components
安装 dash 后,您需要创建一个目录来保存构建应用程序的所有 python 脚本。注意,有多种方法来构造这个目录和其中的 python 文件,下面只是构造它的一种方法。我喜欢用这种方式组织它,因为我发现它有助于我保持代码的条理性。在这个结构中,您将有四个文件:
PyFile #1:应用程序
app.py
:这个脚本简短明了。它会创建您的 dash 应用程序,并将其连接到服务器。如果您选择使用 Bootstrap CSS 样式(或另一个预制的 CSS 样式表),您也可以在这里这样做。
PyFile #2:索引
这将是你进入仪表板的主要入口。这意味着当你想运行 dashboard 应用程序时,你可以在命令行中输入python index.py
。在这里,您还将定义在应用程序的哪些页面上显示哪些布局。app.layout
将是你的总体结构。在这个例子中,我有一个 location 组件,它将结构与 URL 联系起来,实例化一个水平导航栏,并将页面内容放在一个 HTML div 中。这种结构将在应用程序的所有页面上显示相同。下面的回调是一个特殊的回调,当你点击导航栏中的链接到一个新页面时,它将页面布局发送到结构中的page-content
HTML div。确保从layouts.py
中导入您想要显示的布局、组件和样式。
PyFile #3:布局
layouts.py
:这是你设计仪表盘应用的地方。你需要将每个布局、组件或样式设置为一个变量或存储在一个函数中,这样你就可以在index.py
和这个布局脚本的其他地方访问它。请记住,layouts.py
只是定义每个页面的布局和各种附加组件,如导航栏。我们将在后面讨论如何在 **callbacks.py**
中实现交互性。
在这个例子中,我已经导入了经典的 iris 数据集来生成两个 Plotly Express 图形进行显示。我还创建了一个导航栏、两种样式和两种布局。每个布局由一个 1 行 2 列的引导网格组成。在第一个布局中,左边的列有两个选项卡,将显示不同的图形。右边的列显示与用户在图上的点击相关联的文本。对于第二个布局,它展示了两个非常有利于交互性的 dash 核心组件:下拉菜单和单选按钮。除了显示选择的值之外,它们现在不做太多事情,但这是您可以发挥创造力并弄清楚如何使用选择的值与其他组件和图形进行交互的地方。
layouts.py
很可能是你最长的 py 剧本。
PyFile #4:回调
您想要创建的任何互动都应该放在这里。您会注意到上面的layouts.py
脚本中的许多元素都传递了一个id=
参数。这些 id 是callbacks.py
中的回调如何识别哪些组件监听用户输入,以及在哪里显示回调的输出。回调的结构如下:
@app.callback(
Output("component-id-to-output-to", "children"),
Input("component-id-to-listen-to", "valuesIn")
)
def callback_name(valuesIn):
#code for callback to execute
return output_to_children
每个回调都监听一个组件并从中获取值。这是Input()
的作品。然后使用这些值执行回调函数。一旦函数返回一个值或对象,它就被发送到Output()
。"children"
是每次回调的通用输出。子元素是组件的子元素。我们实际上已经用了很多孩子。在上面的脚本中,每次我们将组件嵌套在另一个组件中时,我们都添加了一个子组件。所以本质上,当children
在回调的输出中时,它告诉 Dash 将返回的内容放在 id 与输出中列出的 id 相匹配的组件中。例如,callbacks.py
中的第一个回调从 id 为tabs
的组件获取值active_tabs
,并将回调的输出返回给 id 为tab-content
的组件。返回的内容现在是tab-content
组件的子组件。
我在下面的脚本中设置了四个回调:
- 监听当前点击了哪个选项卡,并返回相关的图表
- 监听图表上的点击并返回与该点击相关联的文本
- 监听下拉菜单并以字符串形式返回选定的值
- 监听单选按钮并以字符串形式返回选定的值
大多数回调并不有趣,但是在开始构建更复杂的回调之前,理解简单的回调是有帮助的。
一旦你设置好了所有的四个文件,编辑它们到你的数据,来自 Plotly 的可视化,等等。此外,尝试改变结构/布局,并创建自己的回调。学习 Dash 的最好方法是尝试不同的布局和风格。当你想看看你的应用程序头输入python index.py
到你的命令行。它应该是这样的:
$ python index.pyDash is running on http://127.0.01:5000/* Serving Flask app "app" (lazy loading)* Environment: productionWARNING: This is a development server. Do not use it in a production deployment.Use a production WSGI server instead.* Debug mode: on
在任何网络浏览器中输入运行 Dash 的 URL,看看你创建了什么!如果调试模式是打开的,你应该能够更新你的脚本,你的应用程序将改变生活。您可以通过设置debug=False
来关闭index.py
中的调试模式。
Dash 是一个庞大、灵活、强大的库,需要学习的东西太多了,一开始可能会有点不知所措。但是这是一个很好的工具,一旦你投入进去,它就值得了。
在这里找到这个项目的 GitHub 库。
用 ctypes 模块从 Python 调用 C++代码
决策树实现示例
Python 在过去几年变得非常流行,因为它有一个很大的社区和很多可用的包,这些包非常容易使用,可以帮助你相对快速地完成工作。但是很多包不是用纯 Python 写的,因为作为一种解释语言,这意味着你不需要编译你的程序来执行指令,它非常慢。例如,一个名为 xgboost 的流行数据科学包主要是用 C++编写的,这是一种编译语言,因此执行起来很快。出于这个原因,如果我们能用这样一种语言编写计算量最大的操作,但从一种较慢但非常用户友好的编程语言(如 Python)调用它,那就太好了。好消息是我们可以做到,在本教程中,我们将看到如何使用 ctypes 模块。
先决条件:您需要安装 Python 3(ctypes 是一个内置库)和 Visual Studio buildtools 来编译 C++代码。
为了能够从 Python 中调用 C++代码,我们需要精确地定义我们将在语言之间传递的输入和输出数据类型,因为 C++需要在编译时知道所有的数据类型。在 Python 中,一切都是对象,包括像 int 、 float 等数据类型。虽然它们通常不对应于唯一的 C++类型,例如,Python 中的 int 是唯一的,而在 C++中,我们可以有 short、long、unsigned integers 等等,它们的不同之处在于它们可以存储多少位或符号。因此,当在语言之间转换时,我们需要指定确切的数据类型,以防止 Python 整数溢出/下溢 C++整数(即,传递的 Python int 的大小大于或小于某个 C++整数类型预期的大小)。所以,一旦我们定义了对应于 Python 对象的 C 类型,我们就差不多完成了,可以从 Python 中调用我们的 C++函数了!
履行
我们不打算在这里深入研究决策树算法——当前的 C++实现与 sklearn 模型非常相似,如果我们不使用样本权重,它应该会给我们相同的结果,正如我将在本教程末尾展示的那样。
因为 Python 和 C++都是基于 C 编程语言构建的,所以我们可以使用它来使两者进行交互——我们需要的是将我们希望 C 可以调用的函数封装到 extern “C” 命令中,如果我们在 Windows 平台上,则在它们之前添加 __declspec(dllexport) 。在下面的代码中,由于我们希望我们的 Python 代码能够与决策树类初始化器、 fit 和 predict_data 方法交互,我们定义了 3 个可从 Python 调用的函数(将它们包装在extern“C”)——new _ tree、fit_tree & predict。new_tree,在被调用时返回一个指向新初始化的决策树实例的指针,该实例具有已定义的 max_depth 和 min_size 参数, fit_tree 函数将初始化的决策树实例的指针、指向 2d 数组的双指针、行数、列数和布尔值作为参数,如果为真,将打印出拟合的树。传递行数和列数对于循环 C++数组指针至关重要,否则我们无法推断出它的维数。最后预测函数采用与 fit_tree 相同的参数,除了最后一个布尔值,并返回给定特征数组的预测值。
既然我们已经使相关函数可以从 Python 中调用,第二步就是构建 C++模块。为此,我们需要在命令行中运行 python setup.py build ,它将编译在 setup.py (见所附链接)文件中的 ext_modules 参数下定义的扩展模块,然后我们可以调用这些模块。
现在我们要用 Python 定义一个决策树类
在加载了构建好的 C++编译模块( decision_tree.pyd )并定义了决策树实例之后,我们调用了 fit 函数,在这个函数里面发生了 ctypes 的神奇之处!首先,我们需要确保我们有一个连续的数组,即数组存储在一个连续的内存块中,这样我们就可以在知道第一个元素的地址和元素数量的情况下遍历它。然后我们开始定义输入(argtypes) 和返回类型(restype) 。 new_tree 方法的输入类型非常简单,因为它只是 2 c_int (max_depth 和min _ size),而输出被设置为 c void 指针,这将允许我们获得指向 C++决策树实例的指针,并在稍后将其传递给 fit_tree 和 predict 方法。事实上,我们可以观察到最后两个方法的第一个参数将 a c_void_p 作为输入。Void 指针没有与之相关的数据类型,所以存储我们的决策树类对象很方便。对于 fit_tree 函数,我们需要定义一个指向 2d 数组的双指针——我们首先将连续的 numpy 数组转换成一个 c 类型数组 ( ct_ar ),然后将其转换成双指针。请注意,我们没有将 ct_arr 直接转换为双指针,这样做会在遍历数组时引发访问冲突错误。因此,我们首先将 2d 数组的每一行转换为一个指针,然后将其转换为一个双指针。基本上对预测功能也是如此。最后值得注意的是, fit_tree 方法不返回任何东西,而 predict 方法返回一个数组指针,我们需要为返回类型定义该指针来指示预期的输出长度,否则我们将无法返回正确的预测数。
结果
我们可以比较 C++决策树和 sklearn 的结果
Sklearn 决策树图和预测:
作者图片
C++决策树绘图和预测:
作者图片
你可以在 this GitHub 页面找到完整的代码,包括 C++决策树实现。
结论
在本教程中,我们已经看到了如何使用内置的 ctypes 模块从 python 中调用 C++代码。虽然这不是唯一的选择,实际上我们可以使用其他的库,比如 SWIG ,它实现起来非常快,但是在某些情况下可能会变得复杂。 CFFI 是另一种选择——不用手动定义 c 类型,你只需用 C 代码描述你的数据类型,然后 cffi 就会从中推断出它们。尽管如此,在切换到 cffi 之前,我相信理解使用 ctypes 库的逻辑是有用的。
带 Flask 和 OpenCV 的相机应用程序
使用 flask 构建一个相机应用程序,应用 Snapchat 一样的过滤器,点击照片和录制视频…
在这篇博文中,我们将使用 flask framework 构建一个相机应用程序,在其中我们可以点击图片,录制视频,应用灰度、负片和“仅面部”滤镜等滤镜,就像 Snapchat 上出现的那样。我使用了一个非常基本的前端设计,因为这个项目背后的主要动机是让自己熟悉 flask web-framework,还包括实时视频流。同样的功能也可以扩展,以增加更多的功能。
巴斯蒂安·里卡迪在 Unsplash 上拍摄的照片
演示:
作者 GIF
我们利用了像线程、HTTP 请求-响应、全局变量、错误处理和人脸检测这样的概念。让我们详细看看所有这些是如何发生的。
前端:
首先,前端是一个基本的 HTML 文件,带有接受输入的按钮和在后端预处理后显示输出帧的图像源标签。文件中的按钮将数据发送到服务器。该文件还显示了一些使用该应用程序的说明。该文件保存在项目目录的“templates”文件夹中。
作者截图
后端:
至于后端,它是一个完成所有魔术的 python 脚本。它保存在项目目录中。让我们分别看一下文件的各个部分,以便理解它的工作情况。
初始化:
在上面的代码中,我们导入了所有必要的模块。
Flask 是一个微型的 web 框架,它就像是前端和后端之间的桥梁。从 flask 中,我们导入’ Response 和’ request 模块来处理 HTTP 响应请求。 render_template 用于渲染之前显示的 HTML 文件。OpenCV 是用于执行所有计算机视觉任务的模块。线程模块用于产生新的线程。
然后,我们声明所有的全局变量,它们就像一个“拨动开关”来执行不同的任务,如捕捉图像、开始/停止记录和应用过滤器。将变量初始化为 0,将所有内容设置为 false。
在第 18 行,我们尝试创建一个名为“ shots 的文件夹,如果它不存在的话。这是保存所有捕获图像的地方。
第 24 行加载了一个预训练的人脸检测模型供将来使用,第 27 行创建了 Flask 应用程序的一个实例。第 30 行为内置摄像头创建了一个视频捕获对象。
功能:
记录功能用于开始记录,即将帧写入 avi 文件,同时将变量 rec 设置为真。它使用“ out ,这是后来初始化的视频编写器的对象。(注意:如果你觉得录制的视频快或慢,调整一下 time.sleep 的值)。
detect_face() '将相机帧作为输入,并返回一个裁剪出的帧,其中只包含在该帧中检测到的人脸。它使用之前加载的预训练人脸检测模型。(请访问 本网站 深入了解这是如何做到的)。
gen_frames 是一个重要的功能,在其中完成实际的帧捕捉(通过摄像机)和处理。它在一个无限的 while 循环中运行。第 4 行从相机对象中捕获帧。如果帧捕获成功,它将检查是否有任何过滤器开关为真。如果’*人脸’、‘负片’*或’灰度’为真,则分别对读取帧应用人脸滤镜、负片滤镜和灰度滤镜。
如果’ capture ‘变量被设置为 true,它被重置为 false(全局变量),当前帧以’ png ‘格式保存。如果’ rec ‘为真,帧被复制到’ rec_frame '全局变量,该变量在被触发时被保存到视频文件中。
第 25 行将帧编码到内存缓冲区,然后转换成字节数组。第 27 行产生了需要作为 HTTP 响应发送的格式的帧数据。
HTTP 路由:
这是前端与服务器通信的地方。通信通过 URL 路由发生在*‘GET*’和 POST 方法中。
@app。route(‘/’)'是 Flask 提供的一个 Python 装饰器,用于轻松地将 URL 分配给我们应用程序中的函数。Route '/‘是根 URL,输入根 URL 时调用’ index() '函数。 ‘index.html’ 文件从函数渲染到网页中。
在 html 文件中,Route ’ /video_feed '被设置为图像源。此函数返回由循环中的“ gen_frames() ”生成的帧的响应块。
路由’/请求’被分配给’任务()‘功能,该功能处理所有开关和视频记录。该路由既有’ POST '又有 'GET ‘方法,即接受信息,也发送信息。之前所有路线默认为’ GET '。
如果来自客户端的 HTTP 方法是’ POST ‘,那么’ request.form.get ‘接受来自用户按下的按钮的数据,并反转全局变量的先前状态,这些变量就像’ gen_frame 函数中的开关。例如,当用户按下’灰色’按钮时,灰色’全局变量被设置为真,从而在’ gen_frames '函数中将帧转换为灰度。当再次按下灰色按钮时,“灰色”设置为假,将画面恢复正常。
在运行 flask 应用程序的同时将帧记录到视频中是非常棘手的。最简单的解决方案是启动一个新的线程。
一个线程是一个独立的执行流。这意味着你的程序将同时发生两件事。一个线程共享数据段、代码段、文件等信息。与其对等线程,同时包含其自己的寄存器、堆栈、计数器等。
在我们的例子中,'record()【T21]‘函数有自己的 while 循环,所以这个循环在新线程中运行。首先,当’ rec ‘为真时,我们创建一个’ VideoWriter 对象。在第 37 行,我们初始化一个新线程,目标是’ record() ‘函数,第 38 行启动新线程,其中’ record()’ 函数正在运行。再次按下录制按钮时,【video writer】对象被释放,录制停止,将视频保存到根目录。
最后,如果来自客户端的 HTTP 方法是’ GET ‘,则呈现’ index.html '模板。
主要功能:
‘app.run()’ 用于启动默认地址**😗*http://127 . 0 . 0 . 1:5000/**的烧瓶 app。**您可以通过将“主机”和“端口”参数添加到函数“运行”来设置不同的主机和端口号。将主机设置为广播地址 0.0.0.0 将使应用程序在整个局域网(wifi 等)中可见。因此,如果移动设备连接到同一个 Wi-Fi,您就可以从移动设备访问该应用程序。这是一个很好的“间谍凸轮”。
结论:
要运行这个应用程序,你应该在你的电脑上安装 python、flask 和 OpenCV。要启动应用程序,请在命令提示符中移动到项目目录。键入并输入:
python camera_flask_app.py
现在,将http://127 . 0 . 0 . 1:5000/复制粘贴到你最喜欢的互联网浏览器中即可。
你可以添加更多像人工智能滤镜这样的功能来构建一个 Snapchat 式的应用程序。您还可以增强用户界面,使其更具交互性和丰富多彩。你可以在 我的 GitHub 账号 中获取这个项目的源代码。
谢谢大家!!
摄像机标定
相机几何和针孔模型
摄像机校准或摄像机切除估计给定照片的针孔摄像机模型的参数。通常,针孔摄像机参数用一个称为摄像机矩阵的 3 × 4 矩阵表示。我们用这些参数来估计一个物体的实际大小或者确定摄像机在世界上的位置。
怎么
在我们讨论摄像机校准之前,首先你需要了解针孔摄像机是如何工作的。
为什么我需要了解针孔摄像头?
因为这是任何相机工作的本质。针孔相机模型解释了世界上的一个点与图像平面(图像传感器)上的投影之间的关系。
我们如何将世界上的点投影到相机传感器中?
针孔型号
如果我们使用大开的相机传感器,我们最终会得到模糊的图像,因为成像传感器在传感器的同一位置收集来自物体上多个点的光线。
解决这个问题的方法是在成像传感器前面放一个有微小孔洞的障碍物。
该屏障仅允许有限数量的光线穿过该孔,并降低了图像的模糊性。
https://en.wikipedia.org/wiki/Depth_of_field
【示例】不同光圈大小的真实图像
https://en . Wikipedia . org/wiki/Depth _ of _ field # Effect _ of _ lens _ aperture
针孔摄像机模型中最重要的两个参数
- 焦距:针孔与像面之间的距离
它影响投影图像的尺寸。使用镜头时会影响相机对焦。
2.摄像机中心:针孔中心的坐标。
https://en.wikipedia.org/wiki/Pinhole_camera_model
针孔摄像机模型非常简单。知道了焦距和相机的中心,我们就可以用数学方法计算出物体反射的光线到达图像平面的位置。
焦距和相机中心是相机内参数,K 。( K 是表示固有矩阵的行业规范。)
内在参数
(又名,相机矩阵。)
固有参数,K 。
(C x,Cy) :以像素为单位的相机中心。
( fx , fy ):以像素为单位的焦距。
FX=F/px
fy=F/py
F :世界单位焦距(如毫米。)
像素倾斜
(P x ,P y ):以世界单位表示的像素大小。
s :倾斜系数,如果图像轴不垂直,则不为零。
s=FXtan(α)
坐标系转换(通过矩阵代数!)
我们为什么想要这个?
为了将世界帧中的点投影到摄像机图像平面!
做什么?
(如果说的是自动驾驶汽车)把自动驾驶汽车本土化!
光线(从物体反射)从世界通过相机光圈(针孔)传播到传感器表面。通过孔径投射到传感器表面上导致翻转的图像。为了避免翻转混淆,我们在摄像机中心前定义了一个虚像平面(黄色平面)。
图来自简化的摄像机模型投影
# World Coordinate System
**Oworld = [Xw, Yw, Zw]**# Camera Coordinate System
**Ocamera = [Xc, Yc, Zc]**# Pixel Coordinate System
**Oimage = [u,v]**
我们定义了一个 3 乘 3 的旋转矩阵 ( R )和一个 3 乘 1 的平移向量 ( t ),以便对世界坐标系和另一个坐标系之间的任何转换进行建模。
现在我们可以将投影问题(世界坐标→图像坐标)框架为
- 世界坐标 →摄像机坐标
- 相机坐标→ 图像坐标
**Oworld [Xw,Yw,Zw]** → **Oimage [u,v]**
怎么会?通过使用线性代数!
**1\. World coordinates** → Camera coordinates**Ocamera = [R|t] * Oworld**2\. Camera coordinates → **Image coordinate****Oimage = K * Ocamera** Remind me what **K** (camera intrinsic parameter) was?
内参数,K: f 为焦距,c 为相机中心,是相机特有的参数
步骤 1 和 2 都只是矩阵乘法。因此,它可以重写(组合)为:
**Oimage = P * Oworld = K[R|t] * Oworld****Let P = K[R|t]
P** as Projection
等等, K 是(3,3)矩阵。**【R | t】**为(3,4)。(|意味着你将矩阵 R 与向量 t 连接起来。) Oworld [Xw,Yw,Zw] 为(3,1)。
那就不能用 Oworld [Xw,Yw,Zw] (3,1) 乘以 K[R|t] (3,4) !
😎我们可以通过在 Oworld vector [Xw,Yw,Zw,1]的末尾添加一个来解决这个问题,称为齐次坐标(或投影坐标)。
如果想进一步把图像坐标转换成像素坐标:用 x 和 y 除以 z,得到图像平面上的齐次坐标。
**[x, y, z] -> [u, v, 1] = 1/z * [x, y, z]**
这就是了。这是核心。这个简单的投影原理将被用于每一个 3d 视觉感知算法,从物体检测到 3d 场景重建。
在现实生活中,会有更复杂的场景,比如非方形像素、摄像头访问倾斜、失真、非单位长宽比等。但是,他们只是改变了相机矩阵 K ,方程还是一样的。
需要注意一些事情:
a)旋转矩阵 ( R )和平移向量 ( t )被称为外部 参数,因为它们在摄像机的“外部”。
平移向量 t 可以解释为相机坐标中世界原点的位置,旋转矩阵 R 的列代表相机坐标中世界轴的方向。这可能有点难以理解,因为我们习惯于用世界坐标来思考。
b)通常,多个传感器(如摄像机、激光雷达、雷达等。)用于自动驾驶车辆中的感知。每个传感器都有自己的外部参数,用于定义从传感器框架到车辆框架的变换。
c) 图像坐标(虚像平面)**【u,v】**从虚像平面的左上角开始。这就是为什么我们将像素位置调整到图像坐标框架。
眼见为实
看一下功能project_ego_to_image
。它连续调用两个函数,首先是project_ego_to_cam
,然后是project_cam_to_image
,就像我们把世界坐标分解成两步转换成图像坐标一样:世界坐标 →相机坐标,然后相机坐标→ 图像坐标。
cart2hom
将笛卡尔坐标转换成齐次坐标。
上面的代码片段来自 argoverse-api 。
在下面的 jupyter 笔记本中,您可以看到手动计算(从世界到图像平面的点云投影)与 argoverse api 的结果相匹配。
一个数据科学家能代替一个 NBA 球探吗?最佳转会建议的 ML 应用程序开发
实践教程
使用 NBA API 创建自己的 ML 模型并预测最佳球员交易
“我有一个行动计划,但这个游戏是一个调整的游戏” |迈克·沙舍夫斯基
照片由 JC Gellidon 在 Unsplash 上拍摄
由于最近达到顶峰的希腊怪胎,我给了这个项目一个机会,这个项目我潜伏了几个月。那就 NBA 吧!
本文的主要内容是提出一个端到端的 ML 应用程序开发过程,其中包含了大量的监督和非监督算法,包括高斯混合模型(GMM) 、 K-Means 、主成分分析(PCA) 、 XGBoost 、随机森林和多项逻辑回归分类器。
概念
在成功聚集威士忌品种以促进供应商的销售后,数据公司接受了一个新项目:协助密尔沃基雄鹿队在 2020 年交易窗口期间做出最佳下一步行动。即预先接触得分后卫(SG)位置的候选球员,并购买表现最好的球员。对篮球知识的无知让我想到了一个棘手的选择:
请求 NBA API,从过去赛季的比赛中获取球员数据(例如,助攻失误率、助攻百分比等),以一种有意义的方式为总经理(GM)分类,并最终指导他应该在谁身上花费转会预算,怎么样?
为了更好地传达结果,我们做了几个假设:
#1:我们在 2020 赛季(10 月)结束。雄鹿通用为 SG 职位准备了 3 名候选人名单:朱·霍勒迪、丹尼·格伦、博格丹·博格达诺维奇。
#2:为了完成任务,我们必须从数据中发现任何可能导致雄鹿在各自主场进攻中提高表现的见解(最大助攻数、最小失误数等),同时保留其余的统计数据(即加权投篮命中率%等)。也就是说,我们不应该简单地建议总经理购买最好的传球手或得分手,因为这可能会损害其他有价值的数据。
作案手法
- 构建数据集;获取每个游戏的玩家统计数据(从现在开始“游戏”)。
- 执行**EDA;**对变量的利用建立直觉,得出最早的结论。
- 集群‘玩’通过K-Means&GMM;揭示潜在模式并确定最适合该案例的群集。
- 使用现在标记的数据集(clusters = labels),训练多个多类分类器,包括多项式 逻辑回归,随机森林 & XGBoost 。
- 对候选球员的最新‘比赛’(2020 赛季)进行预测,并据此对其进行基准测试。
- 通过构建&服务 API(在下一篇文章中分析),向最终用户提供**训练好的模型。
工作流程图(图片由作者提供)
您可以运行解释过的工作流程的笔记本或脚本文件(。py)为自动的。
1.资料组
该数据集分两步构建:(a)从这个 Kaggle 数据集开始,我们查询basketball.sqlite
以提取 2017-2020 赛季的GAME_IDs
,( b)我们向 NBA_api 发出请求以获取每场比赛的球员数据。
整个过程被打包在[dataset.py](https://github.com/makispl/ml-nba-transfer-suggestion-app/blob/main/src/dataset.py)
中,你可以选择运行它,或者使用已经准备好的数据集,放在“ data/raw 目录中。
我们使用 2017-2019 赛季的比赛来训练聚类和分类模型,并保留 2020 年的数据用于测试。以下是数据集的样本和对变量的充分的解释:
plays_df
数据集样本
在减杂的脉络中,我不深究 数据清理 和 预处理 程序——大家可以分别参考00 _ EDA . ipynb&preprocess . py。
2.电子设计自动化(Electronic Design Automation)
【00 _ EDA . ipynb中提供了一个完整的 EDA
当涉及到评估 SG 的性能时,我们必须根据真正重要的东西来建立直觉。在这种情况下,我们根据领域知识将特性从最不重要的到最重要的进行分类。这也会让你更容易做出最终决定。
*# classify features by domain importance
group_1 = [OF_RATING,AST_PCT,AST_TOV,TM_TOV_PCT,EFG_PCT,TS_PCT,POSS]
group_2 = [MIN, AST_RATIO, DREB_PCT]
group_3 = [OREB_PCT, REB_PCT, USG_PCT, PACE, PACE_PER40, PIE]
group_4 = [START_POSITION]
group_5 = [DEF_RATING]*
已解释-分类特征
简而言之,就零存在、重复样本或低方差而言,所有特征都是高质量的,而它们的边界是有意义的(没有不合理极值的可疑情况)。
特征直方图
然而,它们中的许多都包含了任一侧的异常值。这是意料之中的,因为我们处理的是真实的游戏,没有人(甚至是不同游戏中的同一玩家)能够总是在一个固定的性能“范围”内表现。
特征的须盒图
关于关键的一组group_1
特征,它们在左右倾斜之间几乎是平衡的。然而,占主导地位的因素是超出相关上限的异常值的大量存在。有许多球员经常表现出色,超出预期,这一事实符合我们最初的结论:
归纳#1 :我们必须深入研究
group_1
,不仅要保证各自特性的显著水平,而且不能损害(尽可能多的)其他特性。
考虑到这一点,我们启动了一种简单的方法,通过主特征(AST_PCT
)对数据集进行排序,取其较高的部分(第 95 百分位)并“水平地”(跨所有特征)评估剧本。
plays_df
描述性统计(人口)
plays_df
描述性统计(第 95 百分位)
结果令人失望。通过将人口与第 95 百分位的平均特征进行比较,我们看到随着AST_PCT
的最大化,许多剩余的特征变得更差,违反了假设 2。另外,我们也不愿意买一个助攻率很高但投篮表现很差的 SG(EFG_PCT
)!
因此,很容易想到,我们无法基于简单的探索技术完成构建最佳 SG 轮廓的任务。因此:
归纳#2 :我们必须在现有数据的基础上建立更好的直觉,并使用更先进的技术,有效地对其进行细分并捕捉潜在的模式,这可能会引导我们找到最佳的 SG 档案。
集群拿起火炬…
3.使聚集
k 均值
我们从流行的 K-Means 算法开始,但是首先实现 PCA,以便降低数据集的维数,同时保留大部分原始特征的方差[1]。
pca4clustering.py
PCA ~解释方差
我们选择一个 4 部分的解决方案,因为它解释了至少 80%的人口方差。接下来,我们通过使用肘形法并绘制 WCSS 线,找到最佳的簇数(k ):
locate _ 肘部. py
WCSS ~团簇图
最佳聚类数是 4,我们准备好拟合 K 均值。
kmeans.py
k-均值聚类
得到的聚类还不错,但是分别有许多cluster_2
和cluster_3
蓝绿色&蓝色的重叠点。为了寻求潜在的增强,我们将研究另一种聚类算法。这次不是基于距离,而是基于分布;高斯混合模型【2】。
戈-梅-莫三氏:男性假两性畸形综合征
一般来说,GMM 可以处理更多种类的形状,而不需要假设聚类是圆形的(像 K-Means 那样)。此外,作为一种概率算法,它为数据点分配概率,表示它们与特定聚类的关联有多强。然而,没有免费的午餐;GMM 可能会很快收敛到局部最小值,从而恶化结果。为了解决这个问题,我们可以用 K-Means 初始化它们,通过调整各自的类参数[3]。
为了挑选合适的聚类数,我们可以利用 Scikit 中的贝叶斯高斯混合模型类——了解哪些权重聚类,将错误的聚类拉平为零或接近零。
贝叶斯 _gm.py
*# returns
array([0.07, 0.19, 0.03, 0.14, 0.19, 0.09, 0.06, 0.18, 0.05, 0.01])*
显然,只有 4 个集群超过 0.01 阈值。
gmm.py
GMM 星团
就是这样!cluster_3
(蓝色)这次更好分离,而cluster_2
(青绿色)也更好包容。
聚类评估
为了增强聚类评估,我们引入了一个新的变量,它描述了被检查特征的净得分。对每组进行加权,以便更好地表达其对最终性能的影响,并计算它们的代数和。我将权重分配如下:
*NET_SCORE = 0.5*group_1 + 0.3*group_2 + 0.2*group_3 - 0.3*group_5# group_4 (START_POSITION) shouldn't be scored (categorical feature)
# being a center ‘5’ doesn't mean to be ‘more’ of something a guard ‘1’ stands for!# group_5 (DEF_RATING) is negative in nature
# it should be subtracted from the Net Score*
那么,让我们对集群进行评分和评估。
net_scoring.py
通用汽车集群得分由NET_SCORE
显然,cluster_3
的表现优于其他产品,其NET_SCORE
为 aprox。662.49,而cluster_1
紧随其后。但是,这里值得强调的是第 95 百分位和新引入的cluster_3
之间的量化比较:
**
NET_SCORE
第 95 百分位& cluster_3 的须盒图
通过注意 146.5 个NET_SCORE
单位的增加,可以清楚地看到cluster_3
在第 95 百分位段中占主导地位!因此:
归纳#3 :
Cluster_3
以一种真正平衡的方式概括了那些源自 SG 出色表现的“剧本”——group_1
特性达到了较高水平,而其余大部分保持了不错的平均水平。该分析考虑了比最初尝试更多的特性(参考文献 1)。EDA),它利用了一个主导者(AST_PCT
)。这证明了…归纳#4 :聚类促进了更全面的数据分离,这些数据来自更多组件的信号,沿着这些思路,我们设法揭示了顶级 SG 的预期性能的更清晰指示。
现在,我们能够操纵标记的(具有聚类)数据集,并开发一种方法来预测新样本(未标记的“播放”)所属的聚类。
4.分类器
【参考02 _ 分类【logres_rf_xgboost】。ipynb ]
我们的问题属于多类分类的范畴,要采取的第一步是选择一个验证策略来解决潜在的过度拟合。
*# check for the clusters' balance
0 27508
1 17886
3 11770
2 5729*
偏斜的数据集意味着必须选择一个分层 K 倍交叉验证,而不是随机验证。这将使标签的比率在每个折叠中保持不变,无论我们选择什么度量来评估,它都将给出相似的结果[4]。说到指标,F1 分数(精确度和召回率的调和平均值)看起来比准确度更合适,因为目标是倾斜的[5]。
创建 _ 折叠. py
接下来,我们标准化数据,以便训练我们的(基线)逻辑回归模型。请注意,这里首先要适合训练数据集,然后转换训练和测试数据。这对于避免数据泄露至关重要[6]!
基线 _ 模型. py
*# returns
Mean F1 Score = 0.9959940207018171*
特征重要性
如此惊人的准确性从一开始就令人生疑。在检查特征重要性的可用方法中(例如 MDI),我选择了置换特征重要性,它是模型不可知的,因此我们能够对所有模型使用任何结论【7】。
置换 _ 专长 _ 重要性. py
排列特征重要性为:(a)所有特征,(b)所有≦START_POSITION
,©所有≦START_POSITION
,MIN
START_POSITION
贡献的重要性极高(单独计算,得分 F1=0.865 )。如果我们检查相关的描述性统计,我们看到所有的group_1
特征在START_POSITION
为 0(即 NaN)时得到最低水平。
START_POSITION
描述性统计
这暴露了这些玩家没有开始游戏,所以他们很有可能比其他人玩的时间少,因此他们的统计数据更差!这同样适用于MIN
变量——它精确地表达了一名球员在球场上花费的时间。因此两者都会导致数据泄漏,我们忽略它们。除此之外,我们还区分了最重要的特征。
特征工程
此外,我们试图通过构建一个新的、数量更少的变量来减少特征的数量,这些变量捕获了原始信息的重要部分。我们再次将 PCA 置于聚光灯下,这一次尝试 9 和 7 组分。注意只使用剩余的标准化特征(≦START_POSITION
,MIN
)!
最终,我们产生了以下特征“桶”:
*all_feats = [all] - [START_POSITION,MIN]
sgnft_feats = [all_feats] - [OFF_RATING,AST_TOV,PACE,PACE_PER40,PIE]
pca_feats = [pca x 9]
pca_feats = [pca x 7]*
超参数优化
在考虑了特征选择之后,我们开始优化每个模型的超参数。 GridSearch 非常有效,尽管很耗时。该过程与所有模型相似——为了简单起见,我只给出 XGBoost 案例:
xgboost_grid_search.py
*# returns
Best score: 0.7152999106187636
Best parameters set:
colsample_bytree: 1.0
lambda: 0.1,
max_depth: 3,
n_estimators: 200*
模型
现在,我们在 model_dipatcher.py 中声明每个模型的最佳超参数,它将我们选择的模型分派到 train.py 中。后者总结了整个训练过程,使训练具有每个特性“桶”的调整模型变得更加容易。我们得到:
*## Logistic Regression ## used num_feats F1_weighted
========= | ========= | ==========
all_feats | 16 | 0.7144
sgnft_feats | 11 | 0.7152
pca_feats | 9 | 0.7111 # sweet-spot
pca_feats | 7 | 0.7076## Random Forest ## used num_feats F1_weighted
========= | ========= | ==========
all_feats | 16 | 0.7213
sgnft_feats | 11 | 0.7145
pca_feats | 9 | 0.7100
pca_feats | 7 | 0.7049## XGBoost ## used num_feats F1_weighted
========= | ========= | ==========
all_feats | 16 | 0.7238 #best
sgnft_feats | 11 | 0.7168
pca_feats | 9 | 0.7104
pca_feats | 7 | 0.7068*
注 :由于模型的随机性质或数值精度,您的结果可能会有所不同。
引入了经典的性能与简单性的权衡;我选择了具有 pca_feats (x9)的逻辑回归的潜力来进一步进行。
5.预言
现在,对于测试数据集的剧本,我们通过使用所选择的模型来预测它们的聚类。
预测. py
确认
为了进行验证,基本事实标签是必要的。然而,这不是我们的情况,因为测试数据集(test_proc.csv
)没有被标记。您可能想知道为什么我们不通过聚类来标记它,但这将引导我们执行完全相同的程序,交叉验证已经完成了 5 次—隔离一小部分数据并进行验证。
相反,我们将通过进行定性检查来进一步评估分类器。我们可以手动检查一部分数据的标签,以确保它们是好的,或者将预测值与训练聚类进行比较,并检查任何主要的描述性统计数据是否仍然有效。
通过NET_SCORE
预测集群得分
事实上,cluster_3
以 109.35 辆的NET_SCORE
成绩再次领先于其他厂商,同时在大多数关键特性(OFF_RATING
、AST_PCT
、AST_TOV
和POSS
)上保持最高水平。
交易
最后也是最有趣的部分涉及到决策。首先,我们对候选球员(朱·霍勒迪、丹尼·格伦、博格丹·博格达诺维奇)在 2020 年上半赛季的“发挥”进行预测,并用各自的聚类对他们进行标注。
然后我们检查它们在cluster_3
中的成员资格,根据各自的cluster_3_plays
/ total_plays
比率对它们进行排序。因此,我们运行predict.py
脚本并得到:**
**# Results
{
'**Jrue Holiday**': **0.86**,
'Bogdan Bogdanovic': 0.38,
'Danny Green': 0.06
}**
你猜怎么着?
密尔沃基雄鹿队关于朱·霍勒迪转会太阳队的推特
2020 年 11 月 24 日,雄鹿官方宣布朱·霍勒迪交易!你这样认为;一个脱离现实的验证…
结论
到目前为止,我们已经走了很长的路……从 Kaggle & NBA API 开始,我们建立了一个庞大的数据集,对它进行了聚类,并揭示了成为一名真正优秀的得分后卫所需要的深刻模式。然后,我们在带标签的数据集上训练各种分类模型,以相当高的精度预测新玩家条目可能注册的集群。通过这样做,我们成功地聚焦了密尔沃基雄鹿队的下一步行动。)拿着,去补 SG 的位置。
类似于 DJ vs 数据科学家的案例,几乎不可能武断地回答数据科学在球探领域的潜力。然而,时代的迹象再次表明了人工智能在体育产业决策领域实施的有利温床…
我把这个项目献给我的好朋友帕诺斯——一个狂热的篮球迷、天文爱好者和 IT 专家。
感谢您的阅读&祝您度过愉快的一周!如果有任何问题,欢迎在下面留言或通过 Twitter / LinkedIn 联系我。无论如何…
坐下来,克隆回购,开始下一步……行动🤝
参考文献
[1]https://machine learning mastery . com/dimensionally-reduction-for-machine-learning/
[2]https://www . analyticsvidhya . com/blog/2019/10/Gaussian-mixture-models-clustering/
[3]https://towards data science . com/Gaussian-mixture-models-vs-k-means-one-to-choose-62f 2736025 f 0
[4] A .塔库尔,《接近(几乎)任何机器学习问题,第一版(2020),isbn-10: 9390274435
[6]https://machine learning mastery . com/data-preparation-without data-leaving/
[7]https://sci kit-learn . org/stable/modules/permutation _ importance . html
高压锅可以冲全豆咖啡吗?
咖啡数据科学
这可能是个坏主意
我没花太多心思在这上面。我想预先警告所有可能想玩巨魔的人。我有很多咖啡实验,非常酷和有趣,还有一些是因为我看着像我的火锅一样的东西,问自己,“我想知道我是否可以用它来煮咖啡,但不需要研磨?”所以我就这么做了。
首先,它不工作,但我很高兴这样做。
所有图片由作者提供
我将 18 克咖啡放入装有 54 克水的杯子中。我以为会吸收一些水分。我把它放入装有水的球拍上的火锅或速溶锅里,然后我打了蒸汽。
我想水应该是热的,有压力,这两样东西加上流量就成了浓缩咖啡。那么没有流量呢?而不磨呢?
使用折射仪测量总溶解固体(TDS ),该数字用于确定提取到杯中的咖啡的百分比,并结合一杯咖啡的输出重量和咖啡的输入重量,称为提取率(EY)。
2 分钟后,我测量了一下,只有 1.52 TDS。所以我又戴了 15 分钟。
仍然只有 4.43 TDS,所以我又做了 15 分钟,以 5.29 TDS 结束。这很难令人满意。
支点!
所以我想,为什么不把这整个混合物扔进维生素 a 混合物里呢?因为如果你想变得古怪,那就试试吧!
好吧,也许这是个糟糕的主意,咖啡没有磨好。大概是因为是刀片研磨机,液体不够。
使用毛刺研磨机!
再次旋转!
所以我把它废弃了,我把它放进了我全新的零号位置!
开个玩笑!
我疯了,但不傻。我把它放进一个杯子里,用我的浸泡式搅拌机多加了一点水。
然后我需要过滤这种混合物,所以我把它倒进我信赖的 Kompresso。首先,我过滤掉所有的液体:
然后我加入了剩下的大块咖啡。
虽然颜色不吸引人,但我尝了第一半,尝起来像是未充分提取的酿造品。我还做了一些 TDS 测量来估算提取率。
从数字来看,咖啡没被充分提取。我想知道根据云量,TDS 测量是否关闭。
就像随机实验一样,有时它们不起作用。然而,我已经进入了发布我正在尝试的任何东西的模式,以防万一。
这个故事的寓意是,你应该在冲泡之前研磨咖啡豆,以防这还不明显。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。
我的进一步阅读:
在水中跌跌撞撞:浓缩咖啡水实验
克莉玛,嗯,它有什么用?
单个 app 能代替所有图像神经分类器 app 吗?一个有趣的夹子
Android 设备上零镜头学习的 OpenAI CLIP 模型部署。TL DR:app 在这里这里,随意试验一下吧!
通用分类器适用于概念概括(作者拍摄的应用程序截图)。灵感来自 unsplash (中)和 unsplash (右)的 Ed van duijn
什么是剪辑,为什么有趣?
今年 1 月,图像处理领域取得了一项重大突破——open ai 展示了一种新的神经网络生成器 Dall-E,它可以根据文本描述生成图像。尽管名为 OpenAI,但它并没有开源。然而,我对一个作为 Dall-E 训练和最佳生成范例选择的辅助神经网络非常感兴趣。与 Dall-E 相反,CLIP 是一个在 MIT 许可下发布的开源项目,因此人们可以在任何地方轻松使用它。这个神经网络可能不太适合演示,但它让我印象深刻。总的来说,这是一个两个模块的项目。第一个模块是一个非常有效的图像转换器神经网络。该深度神经网络使用最先进的注意力机制将图像编码到 512 维嵌入空间中。另一个部分是文本转换器,它将文本转换成向量,再转换成同样的 512 维空间。
零镜头学习的剪辑工作和 it 应用方案(图片来自剪辑 github
我没有找到任何关于训练过程的数据,但我认为这是对 cosface/arcface loss 的一些修改,对这两个模块采用了不同的训练机制。至于数据,尽管模型本身的大小相对较小,但训练这样的模型所需的数据是巨大的。因此,CLIP 在大量签名图像上进行训练,这些图像可能是在整个互联网或维基上解析的。然而,每个人都可以使用预训练剪辑。
为什么剪辑让我印象深刻?
由于它有效地将图像和文本转换到一个空间(CLIP 意味着对比语言-图像预训练),因此使用它可以容易地执行零镜头学习。如果我们生成类似“这是一张猫的照片”和“这是一张狗的照片”的文本,并将它们转换为矢量(对它们进行编码),我们可以检查任意转换的图像是更接近“猫”还是“狗”矢量。正如 OpenAI 博客文章中所示,这种分类方式甚至比针对特定分类任务在大数据集上预先训练的经典卷积神经网络更有效。我检查了这个事实,发现它对我尝试过的大多数任务都是正确的。在极少数任务中(例如,照片中的矿物名称),经典搜索结果显示稍好的结果。我在玩 CLIP 的过程中发现的第二个令人印象深刻的事实是预测的灵活性,我甚至发现 CLIP 的图像部分能够识别一些文本的照片(它在英语照片上工作得很好,其他语言感觉更差)。这种能力来自注意力机制,它允许更复杂的特征估计。几天前 OpenAI 发表了另一篇关于在剪辑的图像部分探索神经元激活的精彩帖子,显示相同的神经元在完全不同的图像中被激活,对应于相同的概念。例如,类似的神经元在蜘蛛的图像、蜘蛛侠的图画和文字“蜘蛛”的照片上被激活。
第三,CLIP 的图像转换器部分相对较轻。它甚至可以在 CPU 上实时工作。在 GPU 工作显示出非常高的帧率。另一方面,Textual transformer 没有这么快。
我已经测试过,发现 CLIP 图像转换器部分可以很容易地在 android 设备上运行,我决定创建一个应用程序,可以使用 CLIP 的转换器部分进行分类。
应用架构
我实现了图像转换器以及图像预处理部分,可以访问图像存储和 android 应用程序的设备摄像头。图像转向其 512 维嵌入。还有,我有几组对应不同概念的向量(在 pc 上预生成)。每个集合可以对应一个特定的主题(例如宠物品种、食物、国籍、年龄、名人等)
之后,我将该图像与集合中的每个向量进行比较(使用余弦相似度的 softmax ),并显示得分最高的前 5 个答案。为了扩展分类器的可能性,增加了用于生成新集合的模块。新分类器的类别列表可以从应用程序发送到服务器。服务器使用文本转换器部分将概念转换为向量,并将其返回给应用程序。用户获得了一个新的分类器!开发部署方案如下所示:
应用程序的流水线和架构(图片由作者提供)
Python 部分
我用过 python 的 Anaconda 发行版。让我们从虚拟环境的创建和调整开始
安装所有软件包后,让我们开始工作!在 jupyter 笔记本中导入所有必需的包:
比我载入模型
选择和编译可视转换器部件“aardvark.jpg”可以是任何图像:
然后我寻找一些与主题相关的列表(大部分来自 wiki ),并使用该功能从模板中创建句子:
该函数将模型保存为*。pt 文件,并为 android 的进一步使用创建 XML。该 XML 包含所有的类名。csv 列出了 4000 个最常用的英语名词
Java 部件(应用程序)
尽管 Kotlin 语言更容易用于 android 开发,但我更喜欢 Java,因为我在这方面有一些经验,而在 Kotlin 方面完全没有经验。
不幸的是,Java 代码太重,可读性差,所以我将只展示 2 个重要的部分
- 加载可视转换器和顶级模型(这里我还添加了传统训练的头部模块,用于在 X 射线上检测肺部肺炎,以显示额外的可扩展性):
2.然后我添加一个重要的客户端部分(服务器部分)。这是一个用于服务器请求并将响应(头模型)保存到 ExternalFilesDir 的模块。类和模型名称的 Dir 列表保存在这里:
请求的 URL 是基于要扩展的类和句子构建的。代码的另一部分以及接口部分在当前的出版物中没有显示。
Python Flask 服务器部分
我在其中一个网站上租了 VPS。关于系统——我已经在 Centos 7 下用 WSGI/Flask 启动了一个 apache 2.0 服务器(对我来说这是最难的部分,因为我以前从未使用过服务器部署,所以需要几天的 googling 和 StackOverflow 搜索)
Python 服务器部分类似于 cerate_xml 函数。唯一的区别是处理请求和发送回生成的模型文件。不幸的是,服务器的运行速度没有我希望的那么快。如果该应用程序将会流行,我应该将一些计算转移到 AWS Lambda:
app 修改方案(图片作者提供)
好玩的部分!测试!
该应用程序运行得非常好。首先,让我们重复一下 OpenAI 的惊人结果,它在一个由不同方式表示的概念上发现了相似的神经元激活:
通用分类器适用于概念概括(作者拍摄的应用程序截图)。作者打印的左侧图像。中央图片由艾德·范·杜伊因从 unsplash 拍摄。右图由hello ’ mnik从 unsplash 拍摄
通用名词分类器使用由模板“这是名词的图像”生成的 4000 个最常用的英语名词和句子
该应用程序明确“理解”所有这些概念都与蜘蛛有关。有趣的是,它可以识别文本,所以我决定在比利时艺术家雷内·玛格利特的作品上测试它,他的作品充满了文字和图像的互动:
雷内·玛格利特艺术品描述(autor 截图)
没什么特别有趣的。但有趣的是,当我试图用国籍或用鸡尾酒名或狗品种来描述这张图片时:
不同的分类器处理同一个图像示例(作者制作的截图)
这里肯定有法国的东西)。我还发现用鸡尾酒的名字来描述图像特别有趣:
有限选择的关联搜索示例(作者截图)图片来自 unsplash 的 HelloI’mNik
绿魔?真的吗?这里我真的被联想思维的那个变形金刚给打动了)。有人可能会说,这是一个又红又大、会飞、甚至类似昆虫的东西的图像。为了测试服务器部分,我创建了一个自定义分类器,通过图像来确定职业。我从一些英语教科书上找到了 30 种职业的清单,并把它们加了进去。模型已在服务器上成功生成并下载。不幸的是,这需要几分钟(
自定义模型创建图像模板和类的界面可以更改(作者截图)
让我们测试新的分类器:
用户创建的职业分类器工作的例子(作者制作的截图)。左图 iby westwindairservice 发自 unsplash 。右图来自Francisco venncio来自 unsplash
帕克先生是谁?
蜘蛛侠先生是谁?(作者截图,图片由hello ’ mnik来自 unsplash )
至于其他类型的分选机机头,它们可以按预期工作:
不同分类器工作的结果(作者截图),左图由
吉拉辛·约斯里来自 unsplash 右图由历史高清来自 unsplash
或者,正如 OpenAI 研究人员发现的那样,我们可以用它们来捕捉一些明显的关联:
中国风景描述(作者截图,landskape 作者 Alice Triquet 来自 unsplash )
但是另一方面,剪辑网络继承了关联,包括来自训练数据集的一些预先判断:
分类器的预判断存在于图像转换器中(作者制作的截图,图像来自高清的历史记录来自 unsplash )
应用程序部署到 Google Play
我已经将应用程序发送到 Play market,但它正在 1 周的检查过程中,所以一旦它通过,我会在这里添加一个链接。尽管如此,如果你不害怕,你可以在这里使用 alpha 版本 apk(广告尚未添加,所以我计划在 Google play 版本发布后关闭 alpha 应用的服务器部分)。更新:在 Play Market 上!
货币铸造
我将从 AdMob 添加几个横幅来获得一些钱)
问题
在描述的应用程序中有几个问题。首先,我发现由于应用程序启动时图像转换器加载到 RAM,几个设备出现了缓慢的(5s)冷启动。第二个问题是服务器对新分类器请求的响应缓慢。可以通过把计算搬到云端来解决(我考虑的是 AWS lambda 服务),但是现在我在纠结 AWS lambda 价格的估算和 app 的受欢迎程度。我可能应该限制每个用户对服务器的每日请求,或者向用户收取限制增强费,以弥补 AWS 的开支并提供更好的 UX(
未来的改进
我还在考虑增加一次拍摄模式(用于分类器创建的单张照片)。这种改进很容易在应用程序中实现。此外,我还尝试了很多 CLIP 和 BERT 的组合来生成图像的自然语言描述,并已经获得了一些有希望的结果。但是 BERT 肯定不能在手机上运行,甚至不能在我的 rtx3080 GPU 上运行,这种透视系统的快速原型化存在一些问题。
谢谢大家!
如果有新想法、提议或问题,请随时联系我!
有用的链接:
关于达尔-e:
https://openai.com/blog/dall-e/
关于剪辑:
剪辑 github:
https://github.com/openai/CLIP
关于 CLIp 和多模态中的神经元激活: