TowardsDataScience-博客中文翻译-2021-八十二-

TowardsDataScience 博客中文翻译 2021(八十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

水中的绊脚石:浓缩咖啡水实验

原文:https://towardsdatascience.com/stumbling-in-water-espresso-water-experiment-6e3e78b03b5e?source=collection_archive---------53-----------------------

咖啡数据科学

在酿造用水中的第一组实验

酿造水食谱的想法当然不是新的,也不是没有至少一些关于人们喜欢的食谱的文件。目前还没有一个合适的食谱对比,我也不打算在短期内填补这个空白。然而,随着詹姆斯·霍夫曼的世界咖啡品尝会,我有机会看到 T2 的第三波水。

第三波水生产不同的矿物质配方与蒸馏水混合,詹姆斯发出了一种类型,以帮助每个人在咖啡品尝期间拥有相同的水配方。考虑到人们在世界各地使用各种水源,这一点非常重要。

后来,我想开始看看酿造水,所以我用我剩下的一加仑水开始了一些配对拍摄。综上所述,我在六个配对镜头中发现了一个负面效应。我知道这只是一个小样本,我写这些不是作为一些结论性的陈述,而是初步的结果。我停止收集数据,因为我更感兴趣的是什么可以提高我的投篮,我只是没有看到一个很大的改进前进的道路。我

很有可能第三波水的经典配置不适合浓缩咖啡,或者我的水已经很好了。我仍然愿意尝试其他的酿造水,但同时我又进行了其他的实验,希望能回到过去。

所有图片由作者提供

基线水设置

为了比较,我用的是水龙头的过滤水,所以水是来自加州的圣克拉拉县。然后,在将水倒入我的 Kim Express 之前,我会使用 Brita 过滤器。我在家里的 Kim Express 上没有遇到我在工作中遇到的水垢问题,可能是 Brita 过滤器的问题。

镜头性能指标

我将这些定义放在这里,因为在这一节之后,我将使用这些指标评估不同数量的纸质过滤器。

我使用了两个指标来评估镜头之间的差异:最终得分咖啡萃取

最终得分是 7 个指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)记分卡的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难,会影响最终得分。

使用折射仪测量总溶解固体(TDS ),该数字用于确定提取到杯中的咖啡的百分比,并结合一杯咖啡的输出重量和咖啡的输入重量,称为提取率(EY)。

数据

我用我的金快车在两次烧烤中收集了六对照片。一般来说,我的镜头有 1.5 的输出输入比,而且大部分都在提取的高端。这些镜头都是用纸过滤器在中间断奏篡改过的镜头。

对于味道得分(最终得分),第三波仅在很大程度上好于一次,而它差了 3 倍。对于提取率(EY),第三波仅与过滤水一样好或更差。

在研究 TDS 与 EY 时,我没有看到任何第三波明显模式,除了被过滤水所表现出来。

我还查看了时间指标,TCF 和总时间。TCF 是覆盖过滤器的时间,我发现这是何时结束预输注的良好指标(3*TCF 似乎是结束预输注的最佳时间)。总时间包括预输注时间和输注时间,并且每对预输注时间是恒定的。

第三波拍摄运行较慢,我不知道为什么。奇怪的是,尽管花的时间更长,他们提取的却更少。

出于数据的目的,最好记住 6 个配对样本只是一个探索性研究。它没有统计学意义。如果有什么不同的话,这个小研究建议我应该同时尝试几个 brew 食谱,以缩小需要更深入研究的食谱范围。

我肯定有一个制作浓缩咖啡的最佳配方,但不是这个。我也确信有比我的过滤水更好的配方,我会继续寻找。

如果你愿意,请在 TwitterYouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以在关注我。

我的进一步阅读:

使用模式识别比较咖啡

咖啡数据回顾:等级和口味

按地区、工艺、等级和价格分类的咖啡

家庭烘焙咖啡的经济效益

咖啡豆脱气

解构咖啡:分割烘焙、研磨和分层以获得更好的浓缩咖啡

浓缩咖啡的预浸:更好的浓缩咖啡的视觉提示

咖啡的形状

搅拌还是旋转:更好的浓缩咖啡体验

香辣浓缩咖啡:热磨,冷捣以获得更好的咖啡

断续浓缩咖啡:提升浓缩咖啡

用纸质过滤器改进浓缩咖啡

浓缩咖啡中咖啡溶解度的初步研究

断奏捣固:不用筛子改进浓缩咖啡

浓缩咖啡模拟:计算机模型的第一步

更好的浓缩咖啡压力脉动

咖啡数据表

使用散景和 svg 惊艳表格

原文:https://towardsdatascience.com/stunning-tables-using-bokeh-and-svg-e612a6f1c541?source=collection_archive---------8-----------------------

清晰简洁的数据展示

作者插图

你是否曾经处理过复杂的数据,却在简洁的可视化方面惨败?当然,这是我每天遇到的最大挑战之一,我也看到我的许多同事在展示数据时很吃力。

在这篇文章中,我想给你一个简短的例子,说明如何使用 Bokeh DataTable 小部件及其内置的 HTMLTemplateFormatter 将表格数据与预览可视化相结合。

简单散景数据表

我们将开始创建一个简单的散景数据表,它有六列,其中五列包含某个主题的结果。

没有任何格式的简单散景表格

您可能会意识到,即使只有三个结果,也很难识别结果模式。我们可以尝试的第一件事是添加单元格格式(例如字体颜色或背景颜色)。

颜色单元格格式

下面是根据值有条件地更改背景颜色的一些代码(灵感来自https://stack overflow . com/questions/42740477/bokeh-datatable-with-conditionally-colored-cells/42742954 # 42742954):

应用值相关的 HTMLTemplateFormatter 后的表

这看起来好多了,但是让我们试着让它看起来更简洁。

使用 unicodes 汇总数据

为此,我们将创建一个新的 pandas 列,包含表示结果 1 到 5 的 html 代码,并使用“■”(■)字符来表示每个结果。

创建 HTML 摘要列后的表

这看起来很棒,而且不用把眼睛从一列移到另一列,也很容易识别结果模式。

使用 svg 的复杂结果模式

最后,让我们将数据变得更复杂(15 个结果列),并绘制一些自定义 svg 来汇总数据。

使用 HTML 和 svg 的 3x5 结果可视化表

以 3x5 模式总结的 15 个结果。这比遍历 15 个单独的结果列要容易得多。

通过 svg 多段线预览 PCR 曲线

您可以进一步自定义散景数据表,创建小型 svg 图。让我们假设我们的结果是新型冠状病毒和其他病原体的 PCR 结果。得到一个小小的 PCR 曲线预览不是很好吗?这是如何实现的。

使用 HTML 和 svg 的 3x5 结果可视化和 PCR 曲线预览表

定制表格数据的可视化是一个很好的工具,可以用一种简单明了的方式呈现数据。散景数据表小部件是一个伟大的工具,让您可以自由定制。非常感谢散景团队。

Styleformer:将非正式文本转换为正式文本,反之亦然

原文:https://towardsdatascience.com/styleformer-convert-casual-text-to-formal-text-and-vice-versa-9cdc52abeaf5?source=collection_archive---------31-----------------------

如何利用强大的 T5 Transformer 模型改变文本的形式

作者图片

Styleformer 是一个全新的 Python 库,允许你使用一个强大的名为 T5 的 Transformer 模型来改变文本的样式。本教程重点介绍它将非正式文本转换为正式文本的能力,反之亦然。改变文本的形式有许多应用。例如,您可能希望增加工作邮件的正式程度——只需运行几行代码的 Styleformer。

装置

您可以使用以下命令直接从 GitHub 下载 Styleformer。

pip install git+https://github.com/PrithivirajDamodaran/Styleformer.git

从休闲到正式

现在,让我们导入一个名为 Styleformer 的类,我们将使用它来加载模型。

from styleformer import Styleformer

让我们加载将非正式文本转换为正式文本的模型。这个模型的样式 ID 是 0,所以在实例化 Syleformer 对象时,我们将把它的“style”参数设置为 0。

styleformer_c_t_f = Styleformer(style=0)

从这里我们可以通过调用 styleformer_c_t_f.transfer()立即开始转换文本。我们将提供希望转换的文本作为第一个也是唯一的位置输入。然后,如果我们想使用 CPU,我们将把“推论 _ 开”参数设置为 0,如果我们想使用 GPU,则将参数设置为 1。

text_1 = "Yo, I love coding in Python. "result_1 = styleformer_c_t_f.transfer(text_1, inference_on=1) print(result_1)

输出:我喜欢用 Python 编码。

这是另一个例子。

text_2 = "I'm going to go buy some stuff like apples at the store "result_2 = styleformer_c_t_f.transfer(text_2, inference_on=1) print(result_2)

结果:我要去商店买一些东西,比如苹果。

不算太差!现在,让我们讨论相反的情况——将正式文本转换成非正式文本。

正式到休闲

让我们加载模型,将正式文本转换为非正式文本。此型号的样式 ID 为“1”。

styleformer_f_t_1 = Styleformer(style=1)

我们现在可以像以前一样调用“transfer()”方法。

text_3 = "Let's discuss our plans for this evening"
result_3 = styleformer_f_t_c.transfer(text_3, inference_on=1) 
print(result_3)

结果:让我们谈谈今晚我们要做什么

多个句子

虽然文档中没有说明,但我相信这个包一次只能用于一个句子。在查看了源代码之后,我注意到启用了“early_stopping ”,这意味着当到达“句子结束”标记时,模型停止生成文本。此外,内部设置设置每次迭代最多 32 个标记,其中标记通常是单词或符号。下面是如何使用名为 TextBlob 的 Python 包按句子分解输入的快速概述。

PiPI 上有 TextBlob,我们可以用一个简单的 pip 命令安装它。

pip install textblob

现在,让我们导入一个名为 TextBlob 的类,我们将使用它来按句子分解字符串。

from textblob import TextBlob

让我们通过向 TextBlob 类提供一个字符串来创建一个 TextBlob 对象。注意这个字符串是如何包含多个句子的。我们将按句子分解文本,然后通过使用 syleformer_c_t_f 对象将文本从随意转换为正式。

text_4 = "Hey man, what's up? We should hang out and watch the Olympics. Then maybe go grab some food" blob = TextBlob(text_4)

TextBlob 构建在名为 NLTK 的 Python 框架之上。有时我们需要在用 TextBlob 执行操作之前从 NLTK 安装资源。因为 NLTK 是 TextBlob 的依赖项,所以我们不需要安装它。让我们从 NLTK 下载一个名为‘punkt’的标记器。

import nltk 
nltk.download('punkt')

我们现在有了开始逐句标记字符串所需的一切。

result_4_list = [] 
for sent in blob.sentences: 
    temp_result = styleformer_c_t_f.transfer(sent.string) 
    result_4_list.append(temp_result) result_4 = " ".join(result_4_list) 
print(result_4)

输出:你好,你在做什么?我建议我们花时间在一起看奥运会。之后,也许去吃点东西。

带快乐变压器的造型器

你可能想用一个更成熟的包,像拥抱脸的变形金刚库或者我自己的快乐变形金刚包来运行这个模型。与 Styleformer 不同,这两个包都可以在 PyPI 上获得,并允许您修改文本生成设置。

您可能希望修改文本生成设置有几个原因。例如,默认情况下,Styleformer 包每次推理最多生成 32 个标记,其中标记通常是单词或符号,没有办法调整这一点。此外,通过修改设置,您可以更改不太可能被选中的单词的比率,这允许您改变文本的“创造性”。

下面是一个 GitHub 要点,演示了如何将 Styleformer 模型与 Happy Transformer 一起使用。也许我会写一篇关于如何将 Styleformer 与 Happy Transformer 一起使用的完整文章,但是现在,下面的要点对大多数人来说应该足够了。

您还可以查看这篇文章,这篇文章深入解释了如何将 Happy Transformer 用于 Styleformer 作者创建的类似模型。这种模型被称为“文法形成器”,用于纠正输入文本的语法。

结论

希望你学到了很多!我期待着阅读这个模型的未来应用。在给你的老板发邮件之前,一定要使用 Styleformer,让每个人都开心!

资源

订阅我的 YouTube 频道,了解 Styleformer 上即将发布的内容。

本教程中使用的代码

原载于 2021 年 8 月 2 日https://www . vennify . ai

如何设计熊猫图和图表的样式

原文:https://towardsdatascience.com/styling-pandas-plots-and-charts-9b4721e9e597?source=collection_archive---------18-----------------------

用现成的样式表定制你的熊猫图——或者设计你自己的

mathplotlib 样式—作者图片

网站、出版物和新闻来源都有自己的风格。看看英国广播公司(BBC)或《纽约时报》(NewYork Times)发布的金融数据。或者内特·西尔弗的 538 网站上的投票数据。它们每个都有清晰一致的外观。

我们将看看如何用我们的熊猫图表和情节实现类似的东西。首先,通过使用我们可用的内置样式,然后看看如何创建我们自己的定制。

默认样式呈现如下图所示的折线图。这是一个干净的图像,但如果你喜欢不同的东西,还有几个内置的风格。

默认样式—按作者分类的图像

要获得 Mathplotlib 中所有可用样式的列表,请使用以下命令。

plt.style.available

您将得到如下所示的列表(注意,不同版本的 mathplotlib 可能有不同的样式,这些样式包含在我的 matplotlib 3.3.4 系统中)

['Solarize_Light2',
 '_classic_test_patch',
 'bmh',
 'classic',
 'dark_background',
 'fast',
 'fivethirtyeight',
 'ggplot',
 'grayscale',
 'seaborn',
 'seaborn-bright',
 'seaborn-colorblind',
 'seaborn-dark',
 'seaborn-dark-palette',
 'seaborn-darkgrid',
 'seaborn-deep',
 'seaborn-muted',
 'seaborn-notebook',
 'seaborn-paper',
 'seaborn-pastel',
 'seaborn-poster',
 'seaborn-talk',
 'seaborn-ticks',
 'seaborn-white',
 'seaborn-whitegrid',
 'tableau-colorblind10']

在开始绘图之前,您可以通过执行这样的代码来更改特定的样式。

matplotlib.style.use('ggplot')

这将选择 ggplot 样式,它会给你一个类似下图的图形。

一个 ggplot 样式的图表—作者图片

已经为绘图包 Seaborn 创建了许多样式,但是您可以将它们用于任何基于 mathplotlib 的绘图库。

其他样式是对其他绘图系统或网站的模拟。 ggplot 样式基于 R 语言中常用的 ggplot2 库。

在本文的最后,我附上了一个图片列表,展示了上面列表中的所有风格。

这里有一些代码,您可以尝试不同的风格。

import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np# Change 'default' to the style that you want to try out
matplotlib.style.use('default')df = pd.DataFrame(np.random.rand(100, 2), columns=['x', 'y'])
df.plot.scatter(x='x', y='y')

该代码只生成两列随机数据,并绘制一个散点图。下面是我把默认改成 dark_background 得到的结果。

深色 _ 背景样式—按作者分类的图像

这是 Solarize_Light2:

Solarize_Light2 样式-作者提供的图像

这就是我们如何改变到一个内置的风格,其中一个可能适合你的目的。或者你想更冒险一点。

更改单个属性

Matplotlib 图形的属性存储在名为 rcParams 的字典中。您可以通过在该字典中设置值来更改单个属性。因此,如果您想将字体大小从默认值 10 更改为更小的值,您可以这样做:

matplotlib.rcParams['font.size'] = 8

您所做的任何后续绘图的字体大小现在将为 8。

只需打印出来,就可以很容易地找到所有的 rcParams。

print(matplotlib.rcParams)

它们数量惊人,其中一些的目的并不明显,但这里有几个目的相当明确:

 'font.family': ['sans-serif'],
          'font.size': 10.0,
          'font.style': 'normal',
          'font.weight': 'normal',
          'lines.color': 'C0',
          'lines.linestyle': '-',
          'lines.linewidth': 1.5,
          'scatter.marker': 'o',
          'text.color': 'black',

下面是一个简短的程序,说明如何使用这些参数。我们将绘制一个散点图,如上图所示,但改变了一些参数。

matplotlib.rcParams['scatter.marker'] = '*'
matplotlib.rcParams['figure.facecolor'] = 'yellow'
matplotlib.rcParams['axes.facecolor'] = 'lightblue'
matplotlib.rcParams['font.family'] = 'serif'
matplotlib.rcParams['font.size'] = 8
matplotlib.rcParams['font.weight'] = 'bold'
matplotlib.rcParams['text.color'] = 'red'df.plot.scatter(x='x', y='y', title='Scatter graph')
plt.show()

这是结果:

一种颇为可疑的定制风格——作者图片

您可以在生成的图表中看到每个参数的变化—这些参数的含义相当清楚。(顺便说一下,我并不是建议你采用这种特殊的配色方案!)

创建自己的样式表

你不必在你写的每个程序中都指定你想要的参数。您可以创建自己的样式表,并使用它来代替内置的样式表。

您所要做的就是创建一个文本文件,其中的 rcParams 按照您想要的方式进行设置,然后以类似于内置样式表的方式将它用作样式表,例如:

matplotlib.style.use('path-to-my-style-sheet')

当然,您不必指定所有的 rcParams,只需指定您想要更改的那些即可。

因此,如您所见,Matplotlib rcParams 允许您为熊猫图创建自己独特的、可重用的样式。

当然,这里的例子非常简单,但是您可以通过查看它们的源代码来探索如何在内置样式中使用这些参数。

样式库

你可以在 Matplotlib Github 库的 Stylelib 文件夹中找到所有不同风格的代码。试着看看经典风格——这演示了设置几乎所有可能的参数,但你也应该看看其他一些。

最后,下面是与每个内置主题相关的图像。

一如既往,感谢阅读,我希望你发现这是有用的。如果你想知道我什么时候发表其他文章,请考虑订阅我的免费、不定期的简讯这里

内置主题

下面的三幅图像是在 matplotlib 版本 3.3.4 中使用内置主题渲染的相同图形。

内置样式的图像—按作者分类的图像

使用 Python 风格化和自动化您的 Excel 文件

原文:https://towardsdatascience.com/stylize-and-automate-your-excel-files-with-python-cab49b57b25a?source=collection_archive---------1-----------------------

Python + Excel

如何利用 Python 创建风格化的 Excel 报表使用 xlwings,初学者入门 Python 的一种方式。

Unsplash的照片

介绍

当您第一次踏上 Python 领域的旅程时,没有默认的网关可供选择。这种语言的典型应用范围从数据科学到机器学习到人工智能,以及其他许多流行词汇。虽然这些都是可以快速实现 Python 的很好的领域,但是对于大多数公司的绝大多数员工来说,它们并没有一个用例。金融服务以及其他行业仍然使用并严重依赖 Excel 进行基本的数据操作。考虑到 Python 多年来与这些复杂的主题建立的联系,任何以这种方式工作的人可能都不会考虑将 Python 作为一个潜在的解决方案。

我接触 Python 是因为需要最大限度地减少我在手工 Microsoft Excel 工作上投入的时间。重复性任务的自动化可以节省大量的工作时间,让您专注于手头更复杂的问题。VBA 似乎是加快这一工作流程的理想解决方案。

我花了几个月时间才学会并掌握了 VBA。但是,即使达到了这一能力点,仍然感觉有一个严格定义和限制这种方法的效率和效果的不灵活的上限。就在那时,我将注意力转向了 Python,没过多久,很明显 Python 就是我所需要的。

如果您发现自己每天都在使用 Excel,正在研究这些任务的自动化,并且现在正在尝试学习 VBA,这篇文章可能会改变您的行动方针。

为什么要用 Python 而不是 VBA Excel?

Python 包含大量内置于标准库中的强大包。此外,您还可以利用易于安装的第三方模块。与 VBA 相比,这些技术的结合可以显著减少所需的代码量以及执行代码所需的时间。一个简单的例子是证明这一点的最好方式。

您可以很容易地比较如何使用 VBA、Python 和 Pandas 来计算数据集中一列的每个唯一值。以下两种方法都是初学者可以实现的。

VBA

这段代码利用了 Excel 的=COUNTIF()函数并将结果粘贴到一个新的工作簿中。

Sub Macro()Workbooks("Book1").Activate
    Workbooks("Book1").Sheets("fruit_and_veg_sales").Activate
    Columns("B:B").Select
    Selection.Copy
    Workbooks.Add
    ActiveSheet.Paste
    Application.CutCopyMode = False
    ActiveSheet.Range("$A:$A").RemoveDuplicates Columns:=1,  Header:=xlNoRange("B1") = "Count"
    Range("B2").Formula = "=COUNTIF([Book1]fruit_and_veg_sales!$B:$B,A2)"
    Range("B2").Copy
    Range("B2:B" & ActiveSheet.UsedRange.Rows.Count).PasteSpecial xlPasteAll
    Calculate
    Range("B2:B" & ActiveSheet.UsedRange.Rows.Count).Copy
    Range("B2:B" & ActiveSheet.UsedRange.Rows.Count).PasteSpecial xlPasteValues
    Application.CutCopyMode = False

End Sub

Python

在 Python 中使用熊猫是你所需要的。(它还将这些值作为额外的好处进行排序)

按作者分类的图像|唯一值计数输出:Python(左)、Excel(右)

利用 Python 中已经可用的包并将最终数据输出到 Excel 可以加快整个自动化过程,同时保持数据的所有常规用户的输出一致。这里节省的时间不仅是通过编写更少的代码行,而且是通过编写更容易理解的代码。

这可以为您和您代码的未来用户节省大量时间。

你现在可以看到,Python 对于初学者来说是一门更容易掌握的语言。对于那些仍然不愿冒险尝试的人来说,能够与 Excel 集成,使用自己熟悉的界面,是让自己轻松学习 Python 的最佳方式。

在您迈出 Python 和 Excel 的第一小步后,不久您就会大步迈向将该语言用于 SQL 数据库、从网站抓取数据和创建仪表板。所有这些都可以通过 Python 模块轻松实现。

开始学习 Python 是学习这些额外技能的一个很好的开端!

xlwings

现在,我们如何开始创建这个报告呢?

提示 xlwings…

xlwings 是一个开源 Python 库,允许使用 Python 代码轻松操作和自动化 Excel。xlwings 能够利用 Python 的科学包(NumPy、Pandas、SciPy、scikit-learn 等。),用 Python 代替 VBA 编写工具,用 Python 创建用户自定义函数在 Excel 中使用。您甚至可以创建仪表板来在线访问您的 Excel 数据!总之,xlwings 能够显著提升您当前的 Excel 工具包和工作流程!

如果您首选的 Python 安装方法是 Anaconda,那么从 2020 年 11 月的发行版开始,xlwings 0.20.8 已经内置在 Anaconda 的预安装包中。这意味着如果您通过 Anaconda 安装 Python,您将自动能够导入和使用 xlwings。

如果你还没有预装的话pip install xlwings会带你去那里。

xlwings 在基于 Excel 的工作自动化和报告创建方面对我非常有用。能够使用 Python 并与 Excel 交互使我能够将时间集中在学习更复杂的编码主题上,同时将 Excel 推向更次要的角色。

将数据格式化成可展示的报告

我创建了一个 csv 格式的水果和蔬菜销售测试数据集,用于本教程。

可以从 Github 下载数据:链接

创建报告的步骤!

  1. 进口熊猫和 xlwings。在本教程中,我们将重点关注 xlwings。Pandas 将仅用于将我们的数据快速导入 Python。
import pandas as pd
Import xlwings as xw

2.我们现在使用 Pandas 将 csv 文件作为数据帧导入。

df = pd.read_csv(r”path_to_csv/fruit_and_veg_sales.csv”)

提示:您也可以通过运行下面的代码行直接从 Github 读取 csv 文件df = pd.read_csv(r"https://raw.githubusercontent.com/Nishan-Pradhan/xlwings_report/master/fruit_and_veg_sales.csv")

现在我们有了 Python 中的数据,您可以自由地进行任何操作或进一步的计算。出于本教程的目的,我们将保持数据原样。

3.初始化 Excel 工作簿。

wb = xw.Book()

这里我们将我们的工作簿命名为wb,并使用 xlwings Book()来初始化我们的 Excel 工作簿。

4.接下来,我们将工作表引用设置为变量,并更改工作表的名称。

sht = wb.sheets["Sheet1"]
sht.name = "fruit_and_veg_sales"

这里,我们将对 Excel Sheet1 的引用设置为sht,并将 Sheet1 重命名为 fruit_and_veg_sales。

5.我们现在有了 Python 中的水果和蔬菜销售数据框架,并有了一个打开的 Excel 工作簿,其中有一个名为“fruit_and_veg_sales”的工作表。下一步是将我们的数据从 Python 导出并导入 Excel。我们通过调用:

sht.range("A1").options(index=False).value = df

如果你了解 VBA,你应该能认出熟悉的语法sht.range("A1")。这里,为了将我们的 DataFrame df放入我们的 Excel 文档,我们指定了放置数据的位置(在本例中是单元格“A1”)。

.options(index=False)避免复制不需要的索引。如果您需要数据帧的索引,您可以删除这部分行,因为默认情况下这是True ,即sht.range("A1").value = df

不要忘记包含 .value,如果不指定,你会得到一个类似于SyntaxError: can't assign a function to a call的语法错误。.value告诉 xlwings 您正在讨论 Excel 单元格中的值,而不是我们稍后将触及的任何其他属性。

6.现在,您应该看到一个 Excel 文件,其中包含完全无格式的数据。

作者图片|插入数据的 Excel 工作表

7.我们已经将数据从 Python 导入 Excel。现在我们将开始格式化!

在 Excel 中设置数据格式时,首先要做的是选择要设置格式的数据。为了在 xlwings 中做到这一点,我们将创建一个与工作表中的范围相关的变量。

all_data_range = sht.range("A1").expand('table')

这里使用sht.range("A1").expand('table')我们基本上是从单元格 A1 开始,然后按 CTRL + SHIFT + ↓(向下箭头)然后 CTRL + SHIFT + →(向右箭头)来选择我们的数据(窗口)。这将选择范围 A1:I1001,该范围引用被保存到名为all_data_range的变量中。

要检查 Python 中的变量引用了哪个范围,请运行print(all_data_range.address)

按作者分类的图片| range.address 示例

8.设置好范围参考变量后,我们现在可以开始设计我们的报告了。我们将从数据的行高和列高开始。

all_data_range.row_height = 22.5
all_data_range.column_width = 12

22.5 和 12 指的是 Excel 的尺寸,根据微软文档,这是“默认字体的字符”。

9.接下来,我们将改变单元格的背景颜色。为此,我们将在元组中使用 RGB 颜色。

all_data_range.color = (208,206,206)

这将把我们产品系列的背景颜色变成浅灰色。

10.要编辑我们的文本,所需的函数略有不同。我们将使用 xlwings 来调用微软的 Excel api。这将几乎等同于使用 VBA。

all_data_range.api.Font.Name = 'Arial'
all_data_range.api.Font.Size = 8all_data_range.api.HorizontalAlignment = xw.constants.HAlign.xlHAlignCenterall_data_range.api.VerticalAlignment = xw.constants.HAlign.xlHAlignCenterall_data_range.api.WrapText = True

这里,我们将数据的字体更改为 Arial,将字体大小设置为 8,使我们的文本中心水平和垂直对齐,最后,打开 Wrap Text 以查看单元格中的所有文本。

11.为了让我们的表格看起来更有吸引力,我们将添加一些颜色并格式化我们的标题。

header_range = sht.range("A1").expand('right')
header_range.color = (112,173,71)
header_range.api.Font.Color = 0xFFFFFF
header_range.api.Font.Bold = True
header_range.api.Font.Size = 9

这个块像我们以前做的那样选择一个范围。这一选择的主要区别是我们使用.expand('right')只控制+ SHFT + →(右箭头)。这允许我们从单元格 A1 开始,选择“I1 ”,这只是我们在 Excel 中的标题列。

这里的另一个不同是,我们选择将字体颜色改为白色。为此,我们用十六进制代码0xFFFFFF指定了颜色。

作者图片|半格式化文档

12.我们现在将格式化我们的交易 ID 号列。我想把这个涂成浅绿色。我们可以使用前面提到的 RGB 方法来实现这一点。这次我们将从单元格 A2 中选择expand('down')

id_column_range = sht.range("A2").expand('down')
id_column_range.color=(198,224,180)

13.下一步将只改变我们的数据的边框颜色(不是标题列或交易 ID#列)。微软的 api 在处理边框时有点笨拙,但是他们的文档已经足够了。

概括地说,上、下、左、右边界分别用数字 7、8、9、10 表示。

data_ex_headers_range = sht.range("A2").expand('table')for border_id in range(7,13):
    data_ex_headers_range.api.Borders(border_id).Weight = 2
    data_ex_headers_range.api.Borders(border_id).Color = 0xFFFFFF

14.最后一步是保存我们的报告。调用wb.save(),指定你想要保存的路径和想要的文件名。记得以文件类型结束文件名。在这种情况下,我们选择.xlsx来保留所有的格式。

wb.save(r"path_to_folder\fruit_and_veg_report.xlsx")

奖金!

作为一个额外的补充,我们也将改变标签颜色为绿色。

sht.api.Tab.Color = 0x70AD47

GIF by Author |使用 xlwings 格式化的 Excel 表格

结论

在几行简单的代码中,我们成功地为最终用户创建了一个格式简洁、可展示的 Excel 文档。本教程应该给你足够的 xlwings 构建块,让你得到创意,做出自己的美观的报告!尝试插入空白行,改变字体大小,背景颜色,边框粗细和边框颜色,使您的报告看起来更好!

这仅仅是使用 Python 和 xlwings 所能实现的开始!

本教程中使用的代码可以从 Github 这里获得

如果你被卡住了,查看 xlwings 文档这里

如果你还有任何问题,请在下面的评论区留言。

如果你想在这篇文章中学到的编码技巧的基础上再接再厉:

注:本文仅代表个人观点和经验。

Neo4j 图形数据科学库中的子图过滤

原文:https://towardsdatascience.com/subgraph-filtering-in-neo4j-graph-data-science-library-f0676d8d6134?source=collection_archive---------6-----------------------

自从我在 Neo4j 图形数据科学库 (GDS)中写了一篇关于新特性的文章已经有一段时间了。对于那些从未听说过 GDS 库的人来说,它有 50 多种图形算法,从社区检测到节点嵌入算法等等。在这篇博文中,我将展示子图过滤,这是该库的新特性之一。为了快速概括 GDS 图书馆的工作方式,让我们看看下图:

投影图模型。经许可添加图片 https://neo4j . com/docs/graph-data-science/current/common-usage/

Neo4j 图形数据科学库使用图形加载器组件来投影内存中的图形。内存中的项目图形与 Neo4j 数据库中存储的图形是分开的。然后,GDS 库使用内存中的图形投影(针对拓扑和属性查找操作进行了优化)来执行图形算法。您可以使用本机Cypher projections 来投影内存中的图形。此外,子图过滤允许您基于现有的投影图创建新的投影内存图。例如,您可以投影一个图,确定该网络中弱连接的组件,然后使用子图过滤来创建一个新的投影图,该图只包含网络中最大的组件。这使您的图形数据科学工作流程更加顺畅,您不必将中间结果存储回数据库,然后使用 Graph Loader 来投影新的内存图形。

图形模型

在这篇博文中,我们将使用我在之前的博文中创建的哈利波特网络数据集。它由《哈利·波特与魔法石》中人物之间的互动组成。

图形模式。图片由作者提供。

图表模式相对简单。它由角色和他们的互动组成。我们知道人物的名字,以及他们第一次出现在书中的时间(firstSeen)。交互关系保存关于两个角色交互的次数(权重)和他们第一次交互的时间(第一次看到)的信息。如果你想继续这篇文章中的练习,我建议你使用 Neo4j 沙盒并选择一个空白项目

选择一个空白项目。图片由作者提供。

Neo4j 沙箱提供免费的 Neo4j 数据库云实例,预装 APOC 和 GDS 库。然而,如果你想要 Neo4j 数据库的本地设置,我有的另一篇博文,在那里我描述了如何开始使用 Neo4j 桌面。

要导入 HP 交互网络,您需要执行以下两个 Cypher 查询。

导入字符:

LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/HP/character_first_seen.csv" as row
MERGE (c:Character{name:row.name})
SET c.firstSeen = toInteger(row.value)

导入交互:

LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/HP/HP_rels.csv" as row
MATCH (s:Character{name:row.source})
MATCH (t:Character{name:row.target})
MERGE (s)-[i:INTERACTS]->(t)
SET i.weight = toInteger(row.weight),
    i.firstSeen = toInteger(row.first_seen)

导入数据集后,可以使用以下查询检查样本子图:

MATCH p=(:Character)-[:INTERACTS]->(:Character)
RETURN p LIMIT 25

您应该会在 Neo4j 浏览器中看到类似的可视化效果:

哈利波特网络的样本子图。图片由作者提供。

子图过滤

如前所述,这篇博文的目的是展示子图过滤的威力。我们不会深入研究具体的算法以及它们是如何工作的。我们将从使用本机投影来投影内存中的图形开始。

CALL gds.graph.create('interactions',
  'Character',
  {INTERACTS : {orientation:'UNDIRECTED'}},
  {nodeProperties:['firstSeen'], 
   relationshipProperties: ['firstSeen', 'weight']})

我们在“交互”名称下投影了一个内存中的图形。投影的图形包括所有角色节点及其第一次看到的属性。我们还定义了我们希望将交互关系投影为无向的,并且包括 firstSeen 和 weight 属性。

现在我们已经有了投影的命名图,我们可以继续在它上面执行任何图算法。这里,我选择运行弱连通分量算法(WCC)。WCC 算法用于识别网络中断开的部分,也称为组件。

CALL gds.wcc.stats('interactions')
YIELD componentCount, componentDistribution

结果

WCC 结果。图片由作者提供。

当您只对结果的高级概述感兴趣,并且不希望将结果存储回 Neo4j 或投影图时,您可以使用算法的 stats 模式。我们可以观察到我们的网络中有四个组件,最大的有 110 个成员。现在,我们将从子图过滤开始。子图过滤过程的语法如下:

CALL gds.beta.graph.subgraph(
  graphName: String, -> name of the new projected graph
  fromGraphName: String, -> name of the existing projected graph
  nodeFilter: String, -> predicate used to filter nodes
  relationshipFilter: String -> predicate used to filter relationships
)

您可以使用 nodeFilter 参数根据节点属性或标签过滤节点。类似地,您可以使用 relationshipFilter 参数根据它们的属性和类型来过滤关系。在我们的惠普网络中只有一个节点标签和关系类型,因此我们将只关注按属性过滤。

首先,我们将使用子图过滤来创建一个新的投影内存图,该图只保存权重属性大于 1 的关系。

CALL gds.beta.graph.create.subgraph(
  'wgt1', // name of the new projected graph
  'interactions', // name of the existing projected graph
  '*', // node predicate filter
  'r.weight > 1' // relationship predicate filter
)

通配符操作符*用于定义我们不想应用任何过滤。在这种情况下,我们只过滤了关系,但保留了所有节点。谓词语法类似于 Cypher query。关系实体总是用r标识,节点实体用变量n标识。

我们可以继续对使用子图过滤创建的新内存图运行 WCC 算法。由于缺乏更好的命名法,它以wgt1的名字出现。

CALL gds.wcc.mutate('wgt1', {mutateProperty:'wcc'})
YIELD componentCount, componentDistribution

结果

WCC 算法的结果。图片由作者提供。

过滤后的投影图有 43 个分量。这是合理的,因为我们忽略了所有具有等于或小于 1 的权重属性的关系,但是保留了所有节点。我们已经使用算法的 mutate 模式将结果写回到投影的内存图形中。

假设我们现在只想在图的最大部分上运行特征向量中心性。首先,我们需要识别最大组件的 ID。WCC 算法的结果存储在投影的内存图中,所以我们需要使用gds.graph.streamNodeProperties过程来访问 WCC 结果并识别最大的组件。

CALL gds.graph.streamNodeProperties('wgt1', ['wcc']) 
YIELD propertyValue
RETURN propertyValue as component, count(*) as componentSize
ORDER BY componentSize DESC 
LIMIT 5

结果

正如我们之前看到的,最大的组件有 78 个成员,其 id 为 0。我们可以使用子图过滤特性来创建一个新的投影内存图,它只包含最大组件中的节点。

CALL gds.beta.graph.create.subgraph(
  'largest_community', 
  'wgt1',
  'n.wcc = 0', 
  '*'
)

现在,我们可以通过只对最大分量运行特征向量中心性来完成我们的任务。

CALL gds.eigenvector.stream('largest_community')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name as character, score
ORDER BY score DESC
LIMIT 5

结果

在哈利波特的世界里,哈利波特很有可能永远独占鳌头。我们已经完成了两个子图过滤步骤,所以你可能会弄不清现在投影的是什么版本的网络。GDS 图书馆提供了一个gds.graph.export特性,允许您在同一个 Neo4j 服务器中将投影图导出为一个单独的数据库实例。

CALL gds.graph.export('largest_community', { dbName: 'lc1' });

在 Neo4j 浏览器中访问新的数据库实例之前,您需要运行以下命令:

CREATE DATABASE lc1;

现在您可以在数据库下拉菜单中选择lc1数据库并检查其内容。

数据库下拉菜单。图片由作者提供。

我不知道为什么,但是沙盒实例不能很好地处理图形导出,而本地桌面版本则可以。目前,您不能将字符串属性导出到单独的数据库中。然而,我通过小道消息得知,很快就会支持投影内存图中的字符串属性。

在最后一个例子中,我将展示如何使用逻辑运算符组合多个节点和关系谓词。首先,我们将在交互网络上运行度中心性,并使用 mutate 模式将结果存储到投影图中。

CALL gds.degree.mutate('interactions',
  {mutateProperty:'degree'})

现在我们可以通过使用多个节点和关系谓词来过滤子图:

CALL gds.beta.graph.create.subgraph(
  'first_half', // new projected graph
  'interactions', // existing projected graph
  'n.firstSeen < 35583 AND n.degree > 2', // node predicates
  'r.weight > 5' // relationship predicates
)

在节点谓词中,我们选择了度数值大于 2 且第一次看到的属性小于 35583 的节点。对于关系谓词,我只选择了权重大于 5 的关系。我们可以在新过滤的内存子图上运行任何图形算法:

CALL gds.eigenvector.stream('first_half')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name as character, score
ORDER BY score
DESC LIMIT 5

结果

最后,当您完成图形分析后,可以使用下面的 Cypher 查询删除所有投影的内存中图形:

CALL gds.graph.list() YIELD graphName
CALL gds.graph.drop(graphName)
YIELD database
RETURN 'dropped ' + graphName

结论

子图过滤是对 GDS 库的一个很好的补充,允许更平滑的工作流程。您可以使用子图过滤来过滤现有的内存图,而不必将 algoritm 结果存储回 Neo4j 并使用 Native 或 Cypher 投影来创建新的内存图。在 Neo4j 沙盒上试试吧,让我知道效果如何!

和往常一样,代码可以在 GitHub 上获得。

向 Kaggle 竞赛提交离线内核指南

原文:https://towardsdatascience.com/submitting-model-predictions-to-kaggle-competition-ccb64b17132e?source=collection_archive---------18-----------------------

插图照片由亚历克斯·安德鲁斯派克斯拍摄

这篇文章展示了如何为需要离线环境的竞赛提交创建一个简单的 Kaggle 内核

之前的帖子中,我们谈到了对超参数搜索的需求,我们已经运行了 walked throw Grid.ai,这简化了云中的微调。我们甚至可以在线监控我们的训练,并最终根据我们的选择终止一些默认配置。

现在我们有了最好的模型,是时候提交我们的结果了。这个挑战和其他几个挑战限制了对测试数据的访问,这意味着真正的测试数据集只提供给没有任何外部连接的独立预测运行。

将我们的模型提交给 Kaggle 竞赛

在这个挑战中,要求用户准备一个笔记本,该笔记本读取一个包含测试图像的文件夹,并将其预测保存到一个特定的submission.csv文件中。您可以在提供一些测试图像时调试流程,并且可以在交互式会话中使用内核。在执行最终评估时,虚拟测试文件夹被真实测试文件夹替换。

也就是说,用户通常有两个选择——准备一个内核:
a)进行完整的训练,然后对测试图像进行预测;
b)使用保存的检查点并仅执行预测。

用 a)场景进行多次迭代是困难的,尤其是因为 Kaggle 内核运行时是有限的。b)选项允许我们将繁重的计算工作外包给任何其他平台,然后带着经过训练的模型甚至模型集合回来。

为模型和包创建私有 Kaggle 数据集

对于测试数据泄漏,这些评估内核需要离线运行,这意味着我们必须在 Kaggle 工作空间中包含所有需要的包和检查点。

内核必须离线,因此我们需要添加一个带有模型的私有数据集。

为此,我们创建了私有存储(Kaggle 称之为 dataset,即使您几乎可以在那里拥有任何东西),在那里我们上传所需的包(所有需要的 python 包都不包括在默认的 Kaggle 内核中)和我们训练的模型——check point。

创建的数据集的快照,包括包和模型。

要安装所有软件包,您可以调用:

! pip install /kaggle/input/my-storage-name/*.whl

管理更大的依赖关系树

Kaggle 内核有丰富的标准机器学习库,大多数都包含在基本配置中。但是,很可能你的任务需要一些其他的库,只是不同的版本。在这种情况下,尝试安装一个顶级依赖项(您直接使用的包)是非常烦人的,因为缺少较低的依赖项,您需要下载、更新私有数据存储并再次运行安装。假设我们有可以安装的包,并且我们已经在标准requirements.txt中列出了我们所有的依赖项,那么这个问题可以通过一种巧妙的方式来解决。

  1. 在本地创建自己的包python setup.py bdist_wheel
  2. 本地下载依赖项
    pip download -r requirements.txt -d package_freeze
  3. [可选]您可以移除一些您知道包含在 Kaggle 中的标准重包,例如torchtensorflow
  4. 将所有源包重命名为 Kaggle 对所有档案文件进行递归提取,从而产生中断包
    import glob, os, shutil
    pkgs = glob.glob("package_freeze/*.tar.gz")
    [shutil.move(p, p.replace(".tar.gz", ".xyz")) for p **in** pkgs]
  5. 将此文件夹上传到带有先前创建的自己的包kaggle_plantpatho的数据集 other
  6. 在 Kaggle 内核中,重新命名软件包,并通过将依赖项指向我们在 Kaggle 上的文件夹来安装我们的软件包
! cp -r /kaggle/input/plant-pathology/package_freeze package_freeze

import glob, os, shutil
# finad all packages
pkgs = glob.glob("package_freeze/*.xyz")
# rename them back to correct name format
[shutil.move(p, p.replace(".xyz", ".tar.gz")) for p **in** pkgs]

! pip install -q kaggle_plantpatho --no-index \
    --find-link /kaggle/working/package_freeze

准备简单的预测笔记本。

预测内核很简单,你可以在这里检查它。两个主要步骤(除了从存储器安装所有需要的包)如下:
1)加载保存的检查点,
2)对测试图像执行预测,
3)将它们保存到标准 CSV 文件。

检查点加载由本机 PyTorch 方法执行,并由我们的 Lightning 模型用load_state_dict解析。对于加载,我们建议坚持使用 CPU,以避免任何最终的副作用。

ckpt = torch.load(
    '/kaggle/input/plant-pathology-model-zoo/epoch=4-step=119.ckpt',
    map_location=torch.device('cpu')
)
# this can be any model as we caal load from checkpoint jsut after
model = MultiPlantPathology("resnet18")
model.load_state_dict(ckpt['state_dict'])

值得一提的是,我们的PlantPathologyDM还实现了探索测试文件夹来收集其中的所有图像。与解析训练数据集相反,我们返回与图像名称配对的图像数据,而不是标签(反正是未知的)。该预测对来自test_dataloader的所有图像进行迭代。并保存测试标签。最后,导出所有配对的图像名称和标签。

对所有测试图像运行预测

就是这样,现在制作这个内核和提交内核,看看你在排行榜上的得分如何!祝你好运!

使用基本型号 ResNet50 提交我们的首个多标签,挑战快照。

上一篇文章介绍了如何准备提交内核,适合在完全隔离的环境中运行。跟着我学我吧!

https://devblog.pytorchlightning.ai/practical-tips-to-rank-on-kaggle-image-challenges-with-lightning-242e2e533429

敬请关注,并跟随我了解更多!

https://devblog.pytorchlightning.ai/best-practices-to-rank-on-kaggle-competition-with-pytorch-lightning-and-grid-ai-spot-instances-54aa5248aa8e

关于作者

Jirka boro vec已经在几家不同的 IT 公司从事机器学习和数据科学工作好几年了。特别是,他喜欢探索有趣的世界问题,并用最先进的技术解决它们。此外,他还开发了几个开源 python 包,并积极参与了其他知名项目。在 Grid.ai 工作,担任研究工程师,是pytorchlightning . ai的主要撰稿人。

使用 Slurm 向高性能集群提交您的 MATLAB 作业

原文:https://towardsdatascience.com/submitting-your-matlab-jobs-using-slurm-to-high-performance-clusters-48fa696d37d3?source=collection_archive---------18-----------------------

关于使用 SLURM 向高性能集群提交作业的教程

作者使用 MATLAB 脚本创建的图像

在我的上一篇文章中,我写了使用 PBS 作业调度器向高性能集群(HPC)提交作业以满足我们的计算需求。但是,并非所有 HPC 都支持 PBS 作业。最近,我所在的机构还决定为其新安装的集群使用另一种叫做 Slurm 的作业调度器。

https://medium.com/swlh/how-to-submit-r-code-jobs-using-pbs-to-high-performance-clusters-ed82d0a578c7

从它的文档来看,Slurm 是一个开源的、容错的、可伸缩的集群管理和作业调度器 Linux 集群。作为一个集群工作负载管理器,Slurm 有三个关键功能:

  1. 它在一段时间内将对资源的访问分配给用户,以便他们可以执行他们的计算任务。
  2. 它提供了一个框架来启动、执行和监控一组已分配节点上的工作(通常是并行作业)。
  3. 它通过管理挂起工作的队列来仲裁资源的争用。

在本文中,我将演示如何向支持 Slurm 作业调度器的 HPC 节点提交 MATLAB 作业。

你一定想知道为什么 MATLAB 毕竟不是开源的。对此有大量的理由。首先,与大多数 python 包不同,MATLAB 支持真正的并行性——除了那些实际上用 C++实现并且只提供 python 级别的包装器的包。MATLAB 对分布式计算有很好的支持,底层实现确实是用 C++实现的,速度非常快。此外,MATLAB 提供现成的算法来支持控制工程、数字信号处理、机器人等 python 社区仍然落后的领域中的应用程序。如果您是大型组织(如大学)的一部分,那么您的组织可能拥有 MATLAB 的机构许可。

为工作提交编写 Slurm 脚本

Slurm 提交脚本有两个部分:(1)资源请求(2)作业执行

脚本的第一部分指定了节点数量、最大 CPU 时间、最大 RAM 量、是否需要 GPU 等。作业将请求运行计算任务。

脚本的第二部分指定加载哪些模块、加载哪些数据文件以及运行哪些程序或代码。

一个工作实例

我给出了一个工作示例,我想利用 MATLAB 提供的分布式计算工具箱并行计算一些东西。为此,我可以使用parfor代替传统的信号内核for。由于我想运行这段代码的 HPC 系统有 94 个内核,我将指定创建 94 个工作线程,这样就可以创建 94 个并行作业。

让我们开始吧,首先,在/home/u100/username目录下创建一个名为minimal_parfor.m的新文件:

L = linspace(0.000001, 200, 800000);
index = 1:length(L);formatOut = 'yyyy_mm_dd_HH_MM_SS_FFF';
dt = datestr(now,formatOut);datafolder  = "/home/u100/username";
outputfile = datafolder + "/"+"SIN_" + dt + ".csv";
if ~isfile(outputfile)
        fprintf("SIN Output file doesn't exist .. creating\n");
        fileID = fopen(outputfile,'w');
        fprintf(fileID,'L,Sin(L)\n');
        fclose(fileID);
else
        fprintf("SIN Output file exists .. not creating\n");
end**parpool(94);**
**parfor** ii = index S = sin(L(ii)); fileID = fopen(outputfile,'a');
    fprintf(fileID,'%.10f,%.10f\n', ...
        L(ii),S);
    fclose(fileID);end

正如我们所看到的,我使用parpool请求 94 个工人。此外,我正在并行计算一个数字的 sin 值,并将它们保存在一个文件中。我更喜欢将数据保存在文件中而不是存储在变量中的方法,因为我可以在执行仍在运行时查看文件。parfor随机选择指定的 94 个索引,运行 94 个并行作业。因此,我不会发现索引被顺序写入文件。但是,我总是可以在以后对它们进行排序。

第二步,我在/home/u100/username目录下创建一个 SLURM 文件,并将其命名为minimal.slurm:

#!/bin/bash# --------------------------------------------------------------
### PART 1: Requests resources to run your job.
# --------------------------------------------------------------
### Optional. Set the job name
#SBATCH --job-name=minimal_parfor### Optional. Set the output filename.
### SLURM reads %x as the job name and %j as the job ID
#SBATCH --output=%x-%j.out
#SBATCH --error=%x-%j.err### REQUIRED. Specify the PI group for this job
#SBATCH --account=manager### Optional. Request email when job begins and ends### Specify high priority jobs
#SBATCH --qos=user_qos_manager# SBATCH --mail-type=ALL### Optional. Specify email address to use for notification
# SBATCH --[mail-user=user@email.edu](mailto:mail-user=rahulbhadani@email.arizona.edu)### REQUIRED. Set the partition for your job.
#SBATCH --partition=standard### REQUIRED. Set the number of cores that will be used for this job.
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=94### REQUIRED. Set the memory required for this job.
#SBATCH --mem=450gb### REQUIRED. Specify the time required for this job, hhh:mm:ss
#SBATCH --time=200:00:00# --------------------------------------------------------------
### PART 2: Executes bash commands to run your job
# --------------------------------------------------------------### SLURM Inherits your environment. cd $SLURM_SUBMIT_DIR not needed
pwd; hostname; dateecho "CPUs per task: $SLURM_CPUS_PER_TASK"
### Load required modules/libraries if needed
module load matlab/r2020b### This was recommended by MATLAb through technical support
ulimit -u 63536 cd $PWD
matlab -nodisplay -nosplash -softwareopengl < /home/u100/username/mininal_parfor.m > /home/u100/username/out_mininal.txt
date
~

minimal.slurm是一个 bash 脚本,它指定了在 HPC 中请求的资源以及如何执行 MATLAB 作业。我使用命令SBATCH — cpus-per-task=94指定了 94 个 CPU,这样当 MATLAB 通过 parpool 请求 94 个工作线程时,它就可以使用了。此外,我请求 450 GB 的 RAM,当我的作业开始运行时它将是可用的。

要将作业提交给 HPC,请键入

sbatch minimal.slurm

要获取已提交作业的状态,您可以键入:

sacct

或者

squeue | grep username

一旦工作开始、完成或由于任何原因终止,我希望在我的 slurm 文件中的指定电子邮件地址上收到一封电子邮件。

我希望这篇文章对使用 SLURM 提交工作的人有所帮助,他们希望使用 MATLAB 的并行计算工具箱

有关 MATLAB 分布式计算工具箱的更多详细信息,请查看

参考文献

  1. https://slurm.schedmd.com/quickstart.html
  2. https://www . mathworks . com/help/parallel-computing/par pool . html

注意:本文绝不是对 MATLAB 或 Mathworks 的任何产品的邀约。作者与 Mathworks 或相关实体没有任何关系。

用群体平均值替代缺失数据:为什么要谨慎

原文:https://towardsdatascience.com/substituting-missing-data-with-the-group-average-why-its-good-to-be-cautious-d64bead7a029?source=collection_archive---------19-----------------------

分类平均法可能比 LOCF 法或整体平均法更好,但这种方法有一些弱点,会影响你的结论。

休伊·费恩·泰

和格雷格·佩奇一起

约瑟芬·加塞在 Unsplash 上的照片

网球巨星安德烈·阿加西已经习惯了炎热的天气。他在拉斯维加斯长大,那里的夏季平均气温高达 39 至 41 摄氏度(102 至 105 华氏度)。

因此,当一个适应了亚热带沙漠气候的人把澳大利亚墨尔本枯萎的夏天描述成一个“巨大的窑”时,这意味着一些事情。

在 2020 年澳大利亚网球公开赛期间,有一些惩罚的日子。例如,1 月 31 日,气温高达 42.9 摄氏度(109 华氏度)。但是,如果气象局的历史记录中没有这个值,并且没有其他方法可以找到,你就不会知道这一点。如果该年 2 月 7 日和其他 72 天的数据丢失,您将面临更多的问题。

虽然这是一个极不可能的场景,但是有几种方法可以用来对那些丢失的值进行最可能的猜测。

在之前的一篇文章 中,我介绍了另外两种插补方法:最后一次观察结转(LOCF)法,以及用整体数据集均值替换。在这里,我将演示另一种方法:用特定的组平均值来估算缺失值。

与使用整个数据集的平均值相比,使用特定组的平均值进行插补是一种更精确的方法。就像侦探在试图解决一个谜时会整合可用的线索一样,数据分析师可以使用组平均值来对替代 NAs 的可能价值做出更合理的估计。

例如,假设我们有大学学生的记录,这些记录的属性中包括“身高”和“性别”。还假设一些身高值缺失,而所有的性别值都是已知的。如果我们用每个性别类别的平均值估算缺失的身高值(男性 175 cm,女性 163 cm),我们更有可能接近“真实”值,而不是用“一刀切”的方法估算整个数据集的平均值。

当然,范畴手段的运用还远远不够完善。正如上面描述的高度插补方法会遗漏异常值一样,使用这种方法计算每日高温也无法预测像 2020 年 1 月 31 日这样破坏图表的日子。但是通过用月平均值代替 NAs 特别是在一个气候季节性变化的地方——与年平均值相比,我们的替代值更有可能反映现实。

为了实现这一点,我使用 R 的 tidyverse 提供的 dplyr 包按月对数据进行分组。接下来,我用 mutate()函数将 impute_monthlymean 列添加到数据集。然后,我给出了 R 指令,说明在这个函数中要做什么,如下所示:

这种策略比用总体均值进行估计更准确。考虑一下:在整个数据集中,月平均插补值与观察值相差 0.59。与用全年平均温度代替所有缺失数据的生硬方法相比,这是 27.6% (.813-.589)/.813 的改进。

虽然基于类别的插补在上述三种方法中效果最好,但它并不总是理想的。例如,在某些情况下,研究人员旨在建立变量之间的相关性。简单地用该类别的平均值输入缺失值会改变相关分数,从而改变关于变量之间关系的结论。

此外,均值插补会扭曲该变量内的数值分布。即使使用类别平均值,它也会影响变量的标准差,以及从普通最小二乘回归等数学模型中得出的推论。同样,获得的见解也会有偏差,尤其是在原始数据集包含大量 NAs 的情况下。无论如何,对 NAs 进行任何形式的插补的研究者都应该清楚地说明这一点,以便所有的读者都能理解做了什么,为什么做,以及如何做。

医疗保健行业的许多研究人员避免均值估算,因为它可能对推断统计产生负面的“多米诺骨牌效应”(康,2013)。换句话说,在流程的某一步用平均值替换 NAs 的决定会影响后续步骤的结论。

因此,虽然缺失值会降低数据集的统计能力,从而导致令人头疼的问题,但在深入分析和建模之前,需要对缺失数据的处理进行深入思考。根据您分析的目的和数据的性质,默认使用简单的解决方案(如均值插补)可能会带来各种问题。

参考:

Kang,Hyun(2013 年 5 月 24 日)。‘缺失数据的预防和处理’https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3668100/。韩国麻醉学杂志。

数据来源:澳大利亚气象局

数独求解器:使用纸浆的线性规划方法

原文:https://towardsdatascience.com/sudoku-solver-linear-programming-approach-using-pulp-c520cec2f8e8?source=collection_archive---------14-----------------------

用线性规划解决数独难题的完整指南(带代码!)

亚历山大·沙托夫在 Unsplash 上拍摄的照片。

数独是一种流行的日本益智游戏,它基于数字的逻辑排列。它不需要任何特殊的数学技能或计算。让我们来看一个来自维基百科的例子:

来源:维基百科

它是一个 9x9 的格子拼图(81 个方块)。在游戏开始时,一些方格中充满了数字,而大多数方格是空的。数独的目标是用数字填充那些空白的方块,这样每一行、每一列和 3×3 部分都包含 1 到 9 之间的数字。玩家需要使用逻辑来填充缺失的数字并完成网格,以便满足所有的约束和规则。在以下情况下,移动是不正确的:

  • 任何行都包含一个以上从 1 到 9 的相同数字。
  • 任何列都包含多个从 1 到 9 的相同数字。
  • 任何 3×3 网格都包含不止一个从 1 到 9 的相同数字。

上一篇文章中,我已经使用一个递归函数创建了一个数独解算器,类似于使用一个 81 级嵌套for循环。然而,解决难数独问题是非常低效的,因为它包含的起始数字比简单或中等数字要少得多。如果只有很少的起始数字,数独问题将会有大量的可行解,而不是只有一个。因此,如果我们使用蛮力方法来解决它,它增加了搜索空间并因此增加了计算成本。

在本文中,我将展示如何使用线性编程方法,这是一种创建数独求解器的更有效的方法。在此之前,让我分享一个小背景。

什么是线性规划?

线性规划是数学优化的一个分支。它是一种在给定一些约束条件的情况下寻找问题最优解的方法。线性规划由以下部分组成:

  • 我们希望最大化或最小化的线性目标函数
  • xₙx₁,…的一组 n 个变量,用于控制目标函数
  • 由线性不等式或等式表示的一组约束

因此,如果一个问题能够用一组线性不等式约束的线性目标函数来表达,那么线性规划就是寻找最佳最优解的一个强有力的工具。

数独求解器(线性规划方法)

我正在使用一个名为 PuLP 的 Python 包来解决 LP 问题。现在,让我们为数独游戏定义 LP 的 3 个主要组成部分。

制定目标函数

与典型的线性规划问题不同,数独没有比另一个解决方案更好的解决方案。在数独游戏中,我们不是真的试图最小化或最大化任何东西,而是试图找到满足一组约束的变量的值。因此,目标函数的最小化或最大化并不重要,目标函数可以是任何值。在本文中,我将使用零作为目标函数。

确定一组决策变量

即使我们可以确保行或列或 3x3 网格中所有值的总和等于(1+2+3+4+5+6+7+8+9 = 45),它仍然可以产生满足 45°约束的许多其他解决方案,但是在行或列或 3x3 网格中仍然有多于 1 个相同的数字,即(1+1+1+5+6+7+7+8+9 = 45)。因此,我们不能简单地为 81 个正方形中的每一个创建一个值在 1 到 9 之间的变量。

相反,我们必须创建一个 9 = 729 的(值、行和列)单个二进制(0–1)问题变量的组合。二进制变量指示正方形中的值或数字的存在是真还是假。例如,二进制值为 1 的变量(5,4,6)意味着值 5 出现在位于第 4 行第 6 列的方块中。类似地,如果二进制值为 0,则意味着那里没有值 5。

确定一组约束条件

1.任何方块中只能有一个数字。根据我上面提到的决策变量的定义,很明显,对于每个方块,9 个值中只能有 1 个为真(1),其他 8 个必须为假(0)。

2.任何一行的方块中的值必须是 1 到 9
3 中的每一个。任何列中正方形内的值必须是 1 到 9
4 中的每一个。3x3 网格中的值必须是 1 到 9 中的每一个

5.起始数独数字必须在最终解决方案中的相同位置,因为这些数字是不可改变的

数独求解器解决方案

现在让我们结合以上的一切,解决数独难题。

代码的输出。图片由作者提供。

我们可以使用线性规划方法来解决一个问题,只要该问题可以用受一组不等式约束约束的的 n 个变量的线性目标函数来表示。LP 还可以用于其他有趣的优化应用,如成本最小化、运输、工作分配、健康饮食规划等。

推荐阅读

https://betterprogramming.pub/sudoku-solver-a-brute-force-approach-using-python-ee180b071346

参考

[1]“数独——维基百科。”【在线】。可用:https://en.wikipedia.org/wiki/Sudoku

[2]“一个被公式化为 LP-PuLP 1 . 4 . 6 文档的数独问题。”【在线】。可用:https://www . coin-or . org/PuLP/case studies/a _ sudoku _ problem . html

关于如何在聊天机器人中构建意图并收集有用反馈的建议

原文:https://towardsdatascience.com/suggestions-on-how-to-structure-intents-in-chatbots-and-gather-useful-feedbacks-f72f7e552090?source=collection_archive---------11-----------------------

万花筒Unsplash 上拍摄的照片

行业笔记,聊天机器人设计

如何管理日益复杂的聊天机器人项目

我最近合作了几个涉及聊天机器人的项目,并有机会与行业专家讨论了这类项目中经常遇到的主要困难。虽然建立对话助手变得越来越容易,但随着聊天机器人的发展,由于没有适当的意图架构,看起来有一些问题系统地出现了。

恶意架构的一些症状是:

  • 聊天机器人经常混淆两种意图,而这两种意图恰好有相似的训练短语。
  • 聊天机器人似乎并不符合一些用户所说的正确意图,尽管它已经实现了,而且从大量收集的对话数据中提取更好的训练短语很麻烦。
  • 即使匹配了正确的意图,聊天机器人也无法解决用户的问题,用户给出了负面反馈,并且不清楚如何改进服务。

在这篇文章中,我提出了一种设计意图的方法,目的是避免这些不好的症状。

聊天机器人输入:自由文本和多项选择答案

我将主要处理聊天机器人,其输入可能是自由文本或语音(因此涉及到意图分类),以及多种选择。在聊天机器人中接受自由文本或语音有两个主要优点:

  • 用户可以说出他/她想要什么,并得到适当的回答,而不必浏览一系列的多项选择问题。这意味着在对话开始时,有一个非常高的分支因子,也就是说,从对话的单个步骤中可以选择大量可能的对话路径。这是只有多项选择的聊天机器人无法实现的,因为多项选择的列表太长,无法容纳一个单一的响应,从而导致更深入的对话路径。然而,随着分支因子的增加,聊天机器人给出错误答案的概率也增加,因为有更多的意图可供选择。
  • 我们可以看到用户真正想要的是什么,因为他/她可以自由地写或说。这意味着我们得到的数据可以分析,以便随着时间的推移改进聊天机器人,而不需要人工代理。

然而,与自由文本相比,多选输入也有重要的优势:

  • 虽然聊天机器人可能没有完全理解用户想要什么,但它可以以多选答案的形式提出似乎合理的替代方案。提出更多可能的解决方案比只提出一个好得多,但是是错误的。
  • 如果用户的反馈来自多项选择答案,就更容易理解。

好消息是,我们可以在同一个聊天机器人中使用两种输入模式,在正确的场合使用最好的一种。让我们看一个新的聊天机器人的例子。唯一的意图是 welcome 意图和 Fallback 意图,Welcome 意图包含聊天机器人在对话开始时向用户显示的欢迎消息,Fallback 意图在用户请求时没有其他意图匹配时匹配。

带有欢迎和回退意向的意向图表示例。图片由作者提供。

如何管理具有相似培训短语的意图

假设我们实现了续订意向,它用回答“要续订您的订阅,请这样做[…]”来回答类似“我如何续订我的订阅?”。我们可以区分以下内容的意图:

  • 系统意图:每个聊天机器人都有的共同意图,比如欢迎和后退意图。
  • 响应意图:其响应应该解决用户请求的意图。

带有回应意向的意向图表示例。图片由作者提供。

后来,我们发现有两种不同的续订过程:一种是在订阅尚未过期的情况下,另一种是在订阅已经过期的情况下。天真的解决方案是创造第二个意图,并尽可能地区分这两个意图的训练短语。我们创建了续订过期订阅意向,该意向以“要续订您的订阅,请执行此操作[…]”来回答类似于“我如何续订我的过期订阅”的问题。然后,我们更新了“续订未过期的订阅”意向,用“要续订您的订阅,请这样做[…]”来回答类似于“我如何续订尚未过期的订阅”的问题。

意向图表示例,包含具有相似培训短语的多个回应意向。图片由作者提供。

乍一看,这可能还不错。但是用户真的在他们的问题中指明他们的订阅是否已经过期了吗?用户想要的是更新他们的订阅,并且正确的过程取决于其他因素的事实并不意味着用户的意图不同。更好的管理方法是创建一个意图,其目的是消除用户的订阅是否过期的歧义,并导致正确的响应。让我们称这个新的意向更新订阅过期,它询问用户“您的订阅过期了吗?”。然后,我们应该将之前创建的响应意图的所有训练短语移到这个新的意图中。

这个新意图不是响应意图,因为它的响应不应该直接解决用户的请求。我们可以将其归类为消歧意图,其目的是从相似选项的短列表中找到正确的答案。由于它的目标与多项选择输入的优点非常相似,我们可以使它为用户提供多项选择答案,如“是的,我的订阅到期了”“不,我的订阅没有到期”

带有歧义消除意图的示例意图图表。图片由作者提供。

太好了!现在,用户不会再因为意图相似的训练短语而得到错误的答案,代价是多了一个必要的对话步骤。此外,如果系统已经知道用户的订阅是否过期,则可以自动消除歧义。一旦我们给聊天机器人添加了更多的意图,它的意图架构将会是这样的。

具有多种歧义和回应意图的示例意图图表。图片由作者提供。

可以链接多个歧义消除意图,以及多个响应意图。注意,通过多个歧义消除意图的对话流总是分叉成几个可能的路径。对于多个顺序响应意图来说,这并不总是正确的,因为它们可以在多个步骤中解决用户问题或者收集必要的用户数据。

我们已经看到了如何用具有歧义消除意图的相似训练短语来解决意图问题。现在让我们看看如何通过适当的反馈收集程序来改进意图分类。

如何构建反馈收集以改进意图分类

我们的聊天机器人可能仍然无法提供良好的客户支持,因为训练短语的意图没有充分涵盖用户可能提出的请求的范围。这种问题主要出现在我们有高分支因子的那部分会话流中,也就是在会话开始之后。

在对话开始时突出强调高分支因素的意图图表示例。图片由作者提供。

随着时间的推移,我们可以构建用户反馈的集合来解决这类问题,而且不费吹灰之力。让我们考虑这个更简单的场景,其中在对话开始时可用的意图是续订到期、密码恢复和回退。

带有歧义消除和回应意图的意图图表示例。图片由作者提供。

当续订订阅中的一个意图过期并且密码恢复匹配时,聊天机器人应该提供相应的答案,然后询问用户是否是这个意思。例如,如果用户说“我如何更新我的订阅”,意向更新订阅的响应应该是类似于“您要更新您的订阅吗?如果是,请选择最能描述您的情况的选项",并选择由、【不,我不是这个意思】组成的多项选择答案。如果用户选择前两个选项中的一个,我们可以推断出意图分类是成功的,并且连同用户的文本一起保存肯定的隐式反馈,这导致更新订阅是过期意图的匹配。如果用户选择第三个选项,聊天机器人应该触发一个新的意图来管理这些误解(或回退意图),并保存一个负面的隐式反馈,以及用户以前的文本。通过以这种方式保存积极和消极的反馈,您将有一个按反馈意图和类型划分的有组织的反馈集合,其中您只能分析导致反馈的对话步骤,而不是整个对话。这将为任何分析反馈以改进意图分类的人节省大量时间和麻烦。

让我们看另一个例子。如果用户写“我如何才能恢复我的密码”,聊天机器人应该匹配意图密码恢复并回答“要恢复你的密码,这样做[…]我解决了你的问题吗?”可能的选择“是”(正反馈)和“不,我是说别的”(负反馈)。

导致正面反馈的用户句子是已经被验证的潜在的新训练短语。请记住,向一个意图添加太多的训练短语可能会提高其性能,但会降低其可维护性,因为检查 100 个句子比检查 30 个句子要慢。我建议考虑这两个方面的折衷:尽量保持不超过 40 个训练短语,同时充分覆盖具有不同训练短语的用户可能提出的请求的范围。

由于这种类型的反馈的目标是通过提供新的和更好的训练短语来改进意图分类,我们将称之为意图分类反馈

带有意向分类反馈的意向图表示例。图片由作者提供。

意图分类错误并不是唯一可以使用反馈来解决的错误,让我们来看看为什么。

如何组织反馈收集以改善意向反应

对于某些用户来说,提供有意图的响应可能不足以解决他们的问题,即使对于写意图答案的人来说这看起来很奇怪,因为他们试图尽可能清楚。这与产品可用性测试的情况类似:开发产品的人有时间开发一个概念模型,使之易于在其中执行任何操作,并努力与第一次看到产品的用户产生共鸣。这种情况也发生在那些需要写下聊天机器人将给出的答案的人身上:他们非常了解这项服务,以至于他们第一眼就能写出完整的答案,但新用户却无法确定自己的方向。

那么,我们如何收集关于聊天机器人回答质量的反馈并加以改进呢?同样,通过以适当的方式组织反馈。让我们回到之前的例子。

带有意向分类反馈的意向图表示例。图片由作者提供。

检查消歧意图的响应的质量没有什么意义,因为它们有简短的答案,并且是以问题的形式。我们将关注响应意图。

如果用户问“我如何才能恢复我的密码”,聊天机器人应该匹配密码恢复意图并回答“要恢复你的密码,这样做[…]我解决你的问题了吗?”有三种可能的选择:【不,我无法用你的指令恢复我的密码】【不,我是说别的】。第一个回答既是一个积极的意图分类反馈,也是对回应文本质量的积极反馈。第二个答案是对回答质量的负面反馈,第三个答案是负面意图分类反馈。我们可以将响应反馈定义为与响应意图相关的答案质量反馈。

带有意向分类反馈和回应反馈的意向图表示例。图片由作者提供。

如果可能的话,负面的反应反馈应该总是导致移交给人类代理。然后必须对他们的对话进行分析,以了解为什么意向回应不够好。

带有反馈收集的最终建议意向架构

总的来说,这就是我建议你的意图架构的样子。

带有多种歧义和回应意图的示例意图图表,带有意图分类反馈和回应反馈。图片由作者提供。

概括一下:

自由文本输入更适合于限制用户请求的合理正确响应的数量,并收集关于用户所提问题的数据。

多项选择输入更适合从候选答案列表中找到正确答案并收集反馈。

响应意图应该用响应直接解决用户的请求。他们可以分多个步骤完成,尤其是当他们需要向用户询问数据时。

消歧意图的目标是从相似选项的候选列表中找到正确的响应,这可以是响应意图或其他消歧意图。它们提供多项选择答案,并用相似的训练短语解决意图问题。

欢迎意图建议用户用自由文本说出他/她的请求。意图分类的目标是将用户的请求缩小到响应意图或消除歧义意图。

意图分类反馈的目标是通过收集提供新训练短语的有组织的简明反馈来改进意图分类。它们是在意图分类完成后立即收集的,包括歧义消除和回应意图。

响应反馈的目标是通过收集有组织的、简洁的反馈来改善与响应意图相关的响应,这些反馈提供了关于用户问题的新观点。它们是在响应意图匹配后立即收集的。

额外提示

以下是一些在大多数聊天机器人项目中似乎有益的一般建议。这并不是一个完整的列表,因为它可以填充另一整篇文章。

用聊天机器人无法管理 100%的联系人是完全正常的

有些交互太复杂,计算机无法处理,或者太少,不值得教它去做。在这些情况下,请交给人工代理。聊天机器人可以极大地提高效率,即使它只是处理对话的第一个、机械的部分。旨在让聊天机器人管理 70%的重复和简单的联系,而让人工代理管理剩余的 30%的复杂和罕见的联系(百分比可能因行业而异)。

不要让聊天机器人重复自己

用户讨厌多次得到相同的回答,这让对话看起来没有进展。在你的意图图中尽可能避免循环,对同一意图实施不同的回应,以避免重复完全相同的句子。

解决愤怒的用户

如果你有了解用户情绪的技术(例如,对文本的情感分析),使用它,并对愤怒的用户说类似“对不起,我不明白,你想和真人说话吗?”**

如果你开始一个新的聊天机器人项目:从小项目开始,测试,监控,调整,迭代

从实现不超过 15 个响应意图开始,执行用户测试,并投入使用。集中精力管理几个接触的理由,但是很好。然后,在您的仪表板上监控意向分类反馈和响应反馈,查看对最高量意向无效的用户查询(即,在您拥有最高 ROI 的地方工作),并改进您的聊天机器人。通过数据驱动的决策来改进聊天机器人,不要只依靠你的直觉。

结论

像任何潜在规模和复杂性增长的项目一样,chatbot 项目中良好的意图架构对于保持其可维护性、清晰地监控其性能以及随着时间的推移系统地改进它是至关重要的。尽管我认为一个好的聊天机器人架构的概念模型即使在较小的项目中也可以省去很多麻烦,但是可以把这个指南看作是管理聊天机器人成长过程中出现的复杂性的辅助工具。

NLPlanet 标志。

LinkedInTwitter脸书 ,以及丨t丨e丨l丨e丨g丨r丨a丨m丨s丨上关注应用自然语言处理的最新故事并加入 NLPlanet 社区。**

总和(A+B)与总和(A)+总和(B)

原文:https://towardsdatascience.com/sum-a-b-vs-sum-a-sum-b-31fb094b786?source=collection_archive---------24-----------------------

粉碎 SQL Bug!

照片由егоркамелев通过 Unsplash 拍摄

我需要你把去年的销售额加到今年的销售额上,然后把总数给我。—你工作的地方有很多人

从这篇文章的标题来看,这两个公式略有不同。这些相似的结构甚至可能在您工作的地方的 SQL 查询中很常见。让我们来看看这两者的区别,以及如何在未来避免一个微小的错误和大量的时间/信誉损失。

桌子

让我们看一下我们的小表,它有“sales_ly”和“sales_ty”列。在该数据中,商店 5 在今年开业,因此去年没有销售额:

作者照片

让我们来看看使用上面显示的每种技术对这些值求和时的结果:

作者照片

我们可以看到,' sales_ly' = 400 而' sales_ty' = 500。检查检查。等一下,伙计!求和成单个值时,一个过程显示 800?!?这是什么原始巫术?

这和一个很久以前的朋友有关,他叫秩序行动。让我们想象一下正在发生的事情:

作者照片

我们的 SUM(A + B)过程用蓝色突出显示。我们可以看到,这个过程的第一步是右边“总计”栏中显示的内部 A + B。嗯,第 5 行总计有一个空值!这是因为像'+'和'-'这样的操作数不能处理空值。所以,100 + Null = Null。

现在,我们看看橙色的 SUM(A) + SUM(B)朋友。这个过程从垂直方向开始,先对 A 求和,然后对 B 求和,然后水平移动,得出正确答案!

解决方案 1:总和(A) +总和(B)

你可能已经注意到了我们的粉色惊喜嘉宾…

在这种情况下,使用 ISNULL()函数也很有帮助。这将把空值替换为 0,然后使用“+”操作数将 0 与 100 相加。

方案二:ISNULL( )

第三种解决方案,包括潜在缺陷

说“用 0 替换所有的空值”是很容易的。这肯定会解决空值的问题,并且总和仍然有效。如果你使用平均值之类的东西,这可能会产生另一个错误。去年没有开业的第 5 家店将被包括在分母中,同时为分子贡献一个大鹅蛋。书呆子在桌子上!

正如在之前的一篇文章中提到的,使用这个问题,你应该像看一场 80 年代的游戏秀一样阅读它,观众齐声尖叫:“什么……会……打破这个吗?!?,在提出已知问题的解决方案时非常有用。

暂定解决方案 3:用 0 替换表格中的所有空值

快速查看代码差异

让我们快速看一下执行聚合的代码:

作者照片

最后的想法

我关注的一个共同趋势似乎是,在数据世界中有很多工具和技术。找出什么有效,为什么有效。想想什么会打破它。不要认为相同的方法或工具在不同的应用中会产生相同的结果。可用数据取决于用例。

直到下一次,继续学习。

如何用 Python 汇总音视频文件

原文:https://towardsdatascience.com/summarize-audio-video-files-assemblyai-c9126918870c?source=collection_archive---------20-----------------------

了解如何使用 AssemblyAI API 的自动章节功能摘要音频文件

凯利·西克玛在 Unsplash 上的照片

介绍

文本摘要是指在自然语言处理(NLP)环境中应用的一组技术,能够以保留关键信息的方式缩短原始文本转录。

在需要更容易、更快地使用大量数据的情况下,文本摘要非常有用。此外,这种应用可以应用于我们需要处理音频文件的环境中。这意味着第一步将是在文本摘要之前执行语音到文本的转换,然后使用该输出作为将执行摘要任务的服务的输入。

在今天的文章中,我们将探讨如何使用直观且易于使用的 API 来总结音频和视频文件。

用一个简单的 API 总结音频文件

我们将使用 AssemblyAI API Auto Chapters 特性执行音频摘要,该特性为之前使用语音到文本 API 转录的音频文件提供随时间的摘要

在本教程中,作为音频文件,我们将使用拜登在 2021 年 4 月 28 日向美国国会发表的演讲。

你需要做的第一件事(尤其是如果你打算按照这个教程做的话)是从 AssemblyAI 网站(免费)获得你的 API 密匙

导入请求库并定义请求头—来源:作者

现在,我们需要做的第二件事是将我们的音频文件上传到 AssemblyAI 的托管服务,这反过来会给我们一个链接,我们将使用它来进行后续的请求,以便执行实际的转录和总结。

将我们的音频文件上传到 AssemblyAI 的 API 托管服务,以便取回 URL——来源:作者

上面的调用返回上传 url,它实际上是我们上传的音频文件的宿主。现在我们已经完成了,我们可以继续获取音频文件的转录以及由 AssemblyAI API 算法生成的摘要章节。

使用 AssemblyAI API 执行语音转文本和摘要—来源:作者

在上面的调用中,请注意,我们必须将auto_chapters设置为True,以便指示 API 对转录的文本执行汇总。

解读回应

先前 API 调用的响应如下所示:

包含转录文本以及输入音频文件的提取章节(摘要)的输出—来源:作者

在返回的输出中,可以在text键中找到全文转录,而在chapters键中可以找到 AssemblyAI 生成的摘要章节。对于每一个提取的章节,响应还将包括开始和结束时间戳以及summary,后者实质上包括总结特定时间帧的音频的几个句子以及headline

完整代码

完整的代码,用于本教程,以上传一个音频文件到汇编 AI API,执行语音到文本和总结可以在下面找到。

我们教程的完整代码—来源:作者

最后的想法

在今天的简短指南中,我们讨论了如何使用名为自动章节的 AssemblyAI API 特性对音频或视频文件执行摘要。作为本教程的一部分,我们只讨论了他们的 API 所提供的一小部分特性,所以如果你想看他们提供的完整列表,请确保查看他们的官方文档。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。

https://gmyrianthous.medium.com/membership

你可能也喜欢

使用机器学习对长文本文档进行摘要

原文:https://towardsdatascience.com/summarize-long-text-documents-using-machine-learning-d49aaf5fc99a?source=collection_archive---------16-----------------------

厌倦了阅读长文本文档,使用开源 python 库对它们进行总结

图片由 SCY 来自 Pixabay

文本摘要是为长文本文档创建简短、准确和流畅摘要的过程。它是从文本文档中提取最重要信息的过程。文本摘要的目的是创建大型语料库的摘要,该摘要具有描述整个语料库的要点。

文本摘要的需要?

互联网上产生了大量的文本数据,如社交媒体文章、新闻文章等。手动创建摘要是耗时的,因此出现了对自动文本摘要的需求。自动摘要工具不仅速度快得多,而且比人类更不容易出错。

文本摘要在许多方面都有助于总结文本数据。文本摘要的一些用途包括:

  • 减少长文档的阅读时间
  • 在研究文档时,摘要使选择过程更容易。
  • 文本摘要对于问答系统是有用的。

使用文本摘要系统使得商业摘要服务能够增加要处理的文本文档的数量。一些新闻门户网站,如 Google News、Inshorts 等,为他们的读者提供长新闻文章的简短摘要。

使用 Sumy 的文本摘要:

Sumy 是一个开源的 Python 库,用于从 HTML 页面和文本文件中提取摘要。该软件包还包含一个文本摘要的评估框架。Sumy 为文本摘要提供了几种算法和方法,其中一些是:

  • 卢恩:启发式方法
  • 潜在语义分析(LSA)
  • 埃德蒙森启发式方法
  • LexRank
  • 文本排名

还有很多。访问 Sumy 文档页面了解更多关于 Sumy 提供的文本摘要算法。

在这篇文章中,我们将讨论和实现一些流行的文本摘要算法 Luhn,LexRank,LSA。

安装:

Sumy 是一个开源 Python 库,可以使用 PyPl 安装:

**pip install sumy**

要从字符串变量或文件中读取文本文档,我们可以使用 Sumy 包中的**PlainTextParser**

从文本字符串变量“document”中读取文本文档:

**parser = PlaintextParser.from_string(document, Tokenizer("english"))**

从位置为“file”的文本文件中读取文本文档:

**parser = PlaintextParser.from_file(file, Tokenizer("english"))**

在 Sumy 文本解析器中读取文本文档后,我们可以使用几种算法或方法对给定的文本文档进行摘要。

LexRank 摘要生成器:

LexRank 算法是一种无监督的摘要方法,它受到 PageRank 算法的启发。LexRank 使用一个 IDF 修改的余弦相似性分数来提高文档摘要的 Pagerank 分数。它基于基于图的句子中心性评分对文本进行摘要。

如果一个句子与文本语料库中的其他句子非常相似,则该句子被认为非常重要。这样的句子可以推荐给用户。

使用 Sumy 实现 LexRank:

可以使用从 Sumy 包中调用的对象来实现 LexRank summarizer。创建一个对象**LexRankSummarizer**后,传递文本文档和行数以返回摘要。

使用 Sumy 的 LSA 汇总器:

潜在语义分析(LSA)基于词频技术和奇异值分解来概括文本。LSA 是一种无监督的自然语言处理技术,而 LSA 的目标是根据主题或潜在特征来创建文本数据的表示。

LSA 包括两个步骤:

  • 以生成文档术语矩阵(或数字向量)。
  • 对文档术语矩阵进行奇异值分解。奇异值分解通过用潜在特征对原始数据集进行编码来降低其维数。

对于 LSA,这些潜在特征代表原始数据中的主题。

(图片由作者提供),LSA 的台阶

结果:

文本摘要器用于创建长文本文档的简短摘要。输入的长文本文档取自机器学习的维基百科页面。

(图片由作者提供),输入摘要文本

使用 LexRank 算法的文本摘要的输出:

(图片由作者提供),使用 LexRank 算法生成的摘要

使用 LSA 算法的文本摘要的输出:

(图片由作者提供),摘要使用 LSA 算法生成

结论:

在本文中,我们讨论了如何使用开源 python 包 Sumy 总结长文本文档。Sumy 提供了诸如 LexRank、Luhn、LSA、TextRank、SumBasic 等各种算法来对文本文档进行摘要。Sumy 可以从字符串变量和磁盘上的文件中总结文本。

您还可以阅读 Text-summary,这是另一个用于总结文本文档的开源 python 库。

参考资料:

[1] Sumy 文档(2019 年 5 月 19 日):https://pypi.org/project/sumy/

感谢您的阅读

总结熊猫数据的更好方法。

原文:https://towardsdatascience.com/summarize-pandas-data-frames-b9770567f940?source=collection_archive---------19-----------------------

Skimpy 使得在笔记本和终端上汇总数据集变得非常容易。

总结一组数据—照片由 LukasPexels 拍摄

Describe 是我在任何新数据集上尝试的第一个函数。但是我现在找到了一个更好的。

我把它换成了 Skimpy。这是一个小的 python 包,显示了数据集的一些扩展摘要结果。您也可以在终端窗口上运行它,而无需输入 Python shell。

您可以使用以下命令从 PyPI 安装它。

pip install skimpy

为什么这么少?

在之前的帖子中,我分享了三个 Python 探索性数据分析工具。有了它们,您可以在瞬间生成关于数据集的更完整的报告。

但是如果你需要更简单的切割呢?

如果我必须从数据集开始,我几乎会一直运行df.describe()。它给你一个重要数字的漂亮的表格视图。

熊猫描述功能结果—作者截图

但是为了更仔细地研究数据集,我必须创建直方图和其他一些摘要。

这就是 Skimpy 帮助我们的地方。只需一个命令,它就可以生成更多关于数据集的矩阵和直方图。

from skimpy import skim
skim(df)

摘要结果来自 skippy—作者截图。

上面的总结以一种视觉组织的方式包含了更多的信息。

每一节总结了相同类型的变量。数字变量也包括直方图。我发现关于日期时间变量的首末日期和频率的细节很方便。

你不需要 Python 环境来运行 Skimpy。

你不必每次都进入 Python 回复或 Jupyter 笔记本来使用 skimpy。您可以对数据集使用 Skimpy CLI 进行总结。

$ skimpy iris.csv

在终端上运行上述命令将在窗口中打印相同的结果并返回。

这样,Skimpy 是一种生成任何数据集的快速摘要的便捷方式,甚至无需编写任何代码。

最终想法

Skimpy 是 Python 生态系统中的一个新工具,可以帮助我们更轻松地处理数据。然而,它已经通过生成扩展的汇总结果解决了一个奇妙的问题。

你可以从他们的 GitHub 页面了解更多。您也可以为改进该工具做出贡献。

朋友,感谢你的阅读!看来你和我有许多共同的兴趣。我很乐意在LinkedInTwitter和 Medium* 上与您联系*

还不是中等会员?请使用此链接 成为会员 因为,不需要你额外付费,我为你引荐赚取一小笔佣金。

用熊猫交叉表汇总数据

原文:https://towardsdatascience.com/summarizing-data-with-pandas-crosstab-efc8b9abecf?source=collection_archive---------14-----------------------

有效使用 Pandas 交叉表进行数据汇总的 7 个实用技巧

照片由印尼 UXUnsplash 上拍摄

汇总数据最直接的效果是获取大量的数据,并将其缩减为几个可以查看的关键汇总值,通常在表格或图表中。

来源于数据科学导论[1]

数据汇总是以易于理解和信息丰富的方式呈现生成数据的汇总的过程。Pandas 提供了几个汇总数据的选项:groupbypivot_tablecrosstab

我们之前已经介绍了熊猫[pivot_table()](/a-practical-introduction-to-pandas-pivot-table-function-3e1002dcd4eb)[groupby()](https://bindichen.medium.com/all-pandas-groupby-you-should-know-for-grouping-data-and-performing-operations-2a8ec1327b5),本文将探讨熊猫crosstab()以及如何使用它进行数据分析。这篇文章的结构如下:

  1. 最简单的交叉表
  2. 显示多行和多列
  3. 显示带边距的合计
  4. 使用 normalize 获取发生的百分比
  5. 指定值并执行聚合
  6. 处理缺失值
  7. Seaborn 热图的可视化

请查看笔记本获取源代码。更多教程可从 Github Repo 获得。

为了进行演示,我们将处理咖啡销售数据。让我们导入一些库并加载数据来开始:

import pandas as pd**def load_data():
    return pd.read_csv('coffee_sales.csv', parse_dates=['order_date'])**df = load_data()
df.head()

咖啡销售数据集(图片由作者提供)

1.最简单的交叉表

创建交叉表时,需要指定行的内容以及如何拆分列。默认情况下,它会计算每个组合中的观察次数。在我们的例子中,让我们使用region作为我们的行索引,并用product_category分割列。

pd.crosstab(**df['region']**, **df['product_category']**)

简单的交叉表示例(图片由作者提供)

在某些情况下,出于显示目的,您可能更喜欢自定义标签。为此,我们可以包含特定的rownamescolnames:

pd.crosstab(
    df['region'], 
    df['product_category'], 
    **rownames=['US Region'],** 
    **colnames=['Product Category']**
)

带有自定义名称的简单交叉表示例(图片由作者提供)

2.显示多行和多列

交叉表最有用的特性之一是可以传入多个索引和列,它为我们完成所有的分组工作。例如,如果我们想要查看数据是如何按市场分布的,我们可以通过将市场列包含在一个列表中来包含它:

pd.crosstab(
    df['region'], 
    **[df['product_category'], df['market']]**
)

多列交叉表示例(作者图片)

类似地,我们可以指定一个自定义标签用于显示目的。rownamescolnames都接受一个标签列表,每个标签对应一行和一列。

pd.crosstab(
    df['region'], 
    [df['product_category'], df['market']],
    rownames=['US Region'], 
    colnames=**['Product Category', 'Market']**
)

多重交叉表示例(作者图片)

3.显示行/列小计

交叉表中另一种常见的显示方式是显示每行和每列的小计。我们可以通过设置margins=True参数来添加它们:

pd.crosstab(df['region'], df['product_category'], **margins = True**)

带有分类汇总的交叉表示例(作者图片)

默认情况下,分类汇总显示有标签“全部”。我们可以使用margins_name参数指定一个自定义标签:

pd.crosstab(
    df['region'], df['product_category'], 
    margins = True, 
    **margins_name = 'Subtotals'**
)

带小计的简单交叉表(作者图片)

4.使用 normalize 获取发生的百分比

数据分析中的一个常见任务是了解发生的百分比。这可以通过将normalize参数设置为True来实现:

pd.crosstab(df['region'], df['product_category'], **normalize = True**)

带规格化的简单交叉表(作者图片)

如果我们希望结果用百分号(%)格式化,我们可以如下调用style.format('{:.2%}'):

pd.crosstab(
    df['region'], 
    df['product_category'], 
    normalize = True
)**.style.format('{:.2%}')**

带规格化的简单交叉表(作者图片)

此外,当marginsTrue时,该计算适用于小计:

pd.crosstab(
    df['region'], 
    df['product_category'], 
    **margins = True, 
    normalize = True**
).style.format('{:.2%}')

带规格化的交叉表(作者图片)

normalize参数接受另外两个值'index''columns':

  • 如果给定了'index',它将对每行进行归一化。
  • 如果给定了'columns',它将对每一列进行归一化。
pd.crosstab(
    df['region'], 
    df['product_category'], 
    margins = True, 
    **normalize = 'columns'**
).style.format('{:.2%}')

normalize=columns 的交叉表(按作者分类的图片)

pd.crosstab(
    df['region'], 
    df['product_category'], 
    margins = True, 
    **normalize = 'index'**
).style.format('{:.2%}')

normalize=index 的交叉表(作者图片)

5.指定值并执行聚合

默认情况下,crosstab对所有数字列执行count聚合函数,并返回结果。要显式指定我们关心的列并执行聚合,可以使用valuesaggfunc参数。

pd.crosstab(
    df['region'], 
    df['product_category'], 
    **values = df['cost'],**
    **aggfunc = 'mean'**
)

带聚集的交叉表(按作者分类的图片)

通过指定values = df['cost']aggfunc = 'mean',我们告诉熊猫将mean函数应用于所有数据组合的成本。

默认情况下,结果将保留 6 位小数。为了舍入结果,我们可以调用round():

pd.crosstab(
    df['region'], 
    df['product_category'], 
    values = df['cost'],
    aggfunc = 'mean'
)**.round(2)**

带聚集的交叉表(按作者分类的图片)

6.处理缺失值

您可能会注意到前面输出中的一个NaN值。我们之所以有这种产品,是因为在南方没有茶叶销售。

不像privot_table有内置的fill_value参数来替换任何丢失的值,crosstab不支持它。我们必须使用其他方法来处理缺失值,例如:

pd.crosstab(
    df['region'], 
    df['product_category'], 
    values = df['cost'],
    aggfunc = 'mean',
).**fillna(0)**

然而,如果crosstab输出包含条目都是NaN的行或列,我们可以使用参数drop_na=True来删除它们。

7.Seaborn 热图的可视化

老实说,我是看了 熊猫交叉表解说 文章[2]才知道这些的。有时候,一个图表胜过一千个单词,这是一个非常方便的功能,可以直观地总结交叉表的输出。我们需要做的只是将交叉表输出传递给 seaborn 热图:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as snsplt.figure(figsize=(8, 6))
sns.heatmap(
 **pd.crosstab(
        df['region'], 
        [df['product_category'], df['market']],
        rownames=['US Region'], 
        colnames=['Product Category', 'Market'],
        values = df['cost'],
        aggfunc = 'mean'
    ),** 
    annot = True
)
plt.show()

结论

在本文中,我们已经讨论了 7 个关于用 Pandas crosstab()方法汇总数据的用例。这是一个非常有用的工具,也是探索性数据分析中最受欢迎的数据汇总方法之一。

读完这篇文章后,你应该能够将它纳入你自己的数据分析。我希望你喜欢这篇文章,并学到一些新的有用的东西。

感谢阅读。请查看笔记本获取源代码,如果您对机器学习的实用方面感兴趣,请继续关注。更多教程可从 Github Repo 获得。

参考

将来自多个机器学习模型的洞察/预测汇总成客户、潜在客户或其他实体的完整视图

原文:https://towardsdatascience.com/summarizing-insights-predictions-from-multiple-machine-learning-models-into-a-complete-view-of-a-45a473783f8f?source=collection_archive---------53-----------------------

利用多种见解提出现实世界的建议

作者图片

https://github.com/shadgriffin/profile_of_1

介绍

数据科学的核心是理解实体。什么是实体?嗯,一个实体是你试图理解的“东西”。例如,实体可以是商店、客户、机器或员工。数据科学让我们能够洞察一个实体在做什么或想什么。

大多数实体都很复杂。他们有多种倾向,是典型的移动目标。假设你是一名在电信公司工作的数据科学家,消费者是你的实体。电信消费者可以做很多事情。他们可以取消、增加、减少或维持他们的支出。他们可以购买产品 x,取消产品 y,或者,他们可以取消产品 x 和 y,但增加产品 z。

或者想象你是一个在线零售商。当一位顾客进入您的门户网站搜索一件新毛衣时,您应该推荐什么颜色?你还应该提供一件夹克、一条裤子、一双鞋或一顶帽子吗?

当你深入研究一个实体的行为和倾向,检查他们能做的所有事情时,事情变得令人毛骨悚然。本文处理将这些倾向组合成最有可能与实体相关的消息。这些都不是新的。我做这种事情已经有二十多年了,从来不会声称是我发明的。

随着我学习一些技巧,我想你会发现这样做可能会变得很棘手。这是因为你经常试图管理多个目标。最佳解决方案总是取决于问题的背景和你希望达到的目标。

据我所知,大多数现实世界的解决方案比这些例子更复杂,但它们使用相似的逻辑,并在核心上面临相似的问题。

此外,我正在处理这个用例中的倾向模型输出。您可以很容易地将它改编为一个协会类型的模型输出。基本过程是一样的。

用例

在本文中,我将探索一家向小型企业销售广告的公司。小企业包括餐馆、油漆承包商和律师。在这个例子中,数据 100%是假的。我创造了它,它属于我。虽然是假的,但我觉得它准确地反映了我过去经历过的几个“真实世界”的例子。用例应该给你一种方式,你可以结合关于一个实体的多种见解。它并不意味着全面或包含您遇到的所有情况。它旨在提供一个框架,说明如何解决您将面临的具体问题。

我们的用例有三种类型的广告(产品),可以提供给小企业客户群。第一种是直邮。第二个是黄页。第三是线上/互联网。

直邮:通过邮政服务发送给消费者(家庭)的传统印刷广告。

黄页:传统平面广告。每年发行一次的企业名录。

在线/互联网:包括所有数字广告,如付费搜索、横幅广告和优先搜索位置。

在我们的第一个例子中,我们将假设我们的目标是为每个小企业客户提供一种产品。如果您通过账单插页或账单信息提供优惠,您可能会看到这一点。

对于账单插页或计费消息,空间有限。通常,只有向客户提供一个报价的空间。数据科学家必须决定向每个客户提供哪种产品。

其他情况下,你只限于一个报价是与互联网横幅广告或电子邮件广告。

在所有这些情况下,与最终客户的互动是最少的。你需要快速简洁地表达观点。

在我们的第二个例子中,我们将看一个场景,其中多个报价被扩展到一个小企业客户。这在有直销渠道的地方很常见。直销渠道意味着人们通过电话或亲自拜访客户。

在本例中,我们创建了小型企业客户的完整视图,快速总结了客户可能购买的产品。这给了每个销售人员一个如何接近每个客户的指南。第二个例子强调了与小型企业客户进行广泛互动,并且有更多时间来探索小型企业客户的需求的情况。

获取设置

第一步是导入 python 库。

import types
import pandas as pd
from botocore.client import Config
import ibm_boto3
import numpy as np
import numpy.dual as dualimport types
import pandas as pd
from botocore.client import Config
import ibm_boto3def __iter__(self): return 0

从 GitHub 导入数据。

!rm leads_for_humans.csv
!wget [https://raw.githubusercontent.com/shadgriffin/profile_of_1/main/leads_for_humans.csv](https://raw.githubusercontent.com/shadgriffin/profile_of_1/main/leads_for_humans.csv)df_datax = pd.read_csv("leads_for_humans.csv", sep=",", header=0)

探索数据。

df_datax.head()

以下是我们数据集中字段的描述。

cust_id:客户的唯一标识符。在这种情况下,客户是一个小企业实体。

yp_probability:这来自于一个机器学习/预测模型。表示客户购买黄页广告的可能性。

predicted_yp_revenue:这来自于一个机器学习/预测模型。表明客户购买黄页广告的可能收入。

internet_probability:这来自于一个机器学习/预测模型。表明客户购买互联网广告的可能性。

predicted_internet_rev:这来自于一个机器学习/预测模型。表明客户购买互联网广告的收入。

dm_probability:这来自于一个机器学习/预测模型。表明客户购买直邮广告的可能性。

predicted_dm_rev:这来自于一个机器学习/预测模型。表明客户购买直邮广告的收入。

credit_flag:表示客户是否有信用问题,是否有拖欠风险。

给每位顾客分配一种产品。

在我们的第一个场景中,我们希望将产品与客户相匹配。每位顾客只能接受一次优惠。有许多不同的方法可以为每位顾客找到最好的产品。这里有几个例子。

技巧一——赢家通吃

赢家通吃的方法是最简单化的。我们的数据包含每个小企业客户购买每个产品的概率。最显而易见的解决方案是给每位顾客分配他们最有可能购买的产品。

创建一个名为“LEAD_PRODUCT”的新字段,其中包含每个客户最有可能购买的产品,基于他们的概率得分。

df1=df_datax.copy()df1["BEST"] = df1[["yp_probability", "internet_probability","dm_probability"]].max(axis=1)df1['LEAD_PRODUCT']=np.where((df1.yp_probability==df1.BEST),'YP',
                                      (np.where((df1.internet_probability==df1.BEST),'INTERNET',
                                                (np.where((df1.dm_probability==df1.BEST),'DM','DOODOO')))))

按产品统计优惠数量。

df_sum = pd.DataFrame(df1.groupby(['LEAD_PRODUCT'])['BEST'].agg(['mean','count', 'std']))
df_sum['pct']=(df_sum['count'])/df_sum['count'].sum()df_sum

从上表中,我们可以看到,根据我们的“赢家通吃”方法,将有 4 个直邮优惠、2,216 个互联网优惠和 2,643 个黄页优惠。

呃?这有点麻烦,是吧?5000 个优惠中,只有 4 个是直邮?这通常是行不通的。

实际上,这完全说得通。如果您查看上表中的“平均”一栏,购买 DM 的平均概率大大低于其他产品。

原来,直邮是一个新的战略产品,该组织只是在最近几年才开始销售媒体。因为这是新产品,很少有人购买。因为历史上很少有人购买,所以从机器学习模型购买的概率会很低。

这是一个普遍的问题。如果你是一个在线零售商,有一件新的花哨的毛衣,没有办法使用机器模型来预测购买概率,因为没有新产品的销售数据。对在线零售商来说,问题变成了,当你不知道谁最有可能购买时,你如何向顾客展示新产品?显然,有几种方法可以做到这一点。下面是一个适用于这个用例的方法。

现在,回到我们当前的用例。我们如何保持真实的购买概率,同时增加直邮优惠的数量?

技巧二——赢家通吃

在我们的第二个场景中,我们将使用相同的数据。然而,这一次,我们将设置一个限制,即至少有 15%的小企业前景获得直邮优惠。

有几种方法可以做到这一点。在下面的代码中,我以下面的方式实现了 15%的限制。

  1. 向 15%最有可能购买直邮广告的潜在客户提供直邮广告。
  2. 对于剩余的 85%的潜在客户,分配可能性最高的报价(互联网或黄页)。
df3=df_datax.copy()

对数据进行排序,让最有可能购买直邮的客户排在最后。这将确保那些分配了直邮优惠的人最有可能购买直邮,即使他们更有可能购买 YP 或互联网广告。

df3=df3.sort_values(by=['dm_probability'])

运用“赢家通吃”的方法。

df3["BEST"] = df3[["yp_probability", "internet_probability","dm_probability"]].max(axis=1)df3['LEAD_PRODUCTX']=np.where((df3.yp_probability==df3.BEST),'YELLOW_PAGES',
                              (np.where((df3.internet_probability==df3.BEST),'INTERNET',
                                        (np.where((df3.dm_probability==df3.BEST),'DM','DOODOO')))))

为了简单起见,限制字段的数量。

df3=df3[['yp_probability','internet_probability', 'dm_probability', 'LEAD_PRODUCTX']]

将 LEAD_PRODUCT 字段转换成三个不同的虚拟变量。我们将使用这些新字段来计算累计和。

df_dv = pd.get_dummies(df3['LEAD_PRODUCTX'])
df_dv = pd.get_dummies(df3['LEAD_PRODUCTX'])
df3= pd.concat([df3, df_dv], axis=1)

统计数据框中的记录总数。

total_n=df3['DM'].count()

计算每次报价的累计记录百分比。

df3['dm_cuml']=pd.DataFrame((df3.DM.cumsum())/total_n)
df3['internet_cuml']=pd.DataFrame((df3.INTERNET.cumsum())/total_n)
df3['yp_cuml']=pd.DataFrame((df3.YELLOW_PAGES.cumsum())/total_n)

如果黄页和互联网/在线报价的累计数量少于总数的 85%,使用“赢家通吃”方法,否则提供直邮。

df3["BEST"] = df3[["yp_probability", "internet_probability","dm_probability"]].max(axis=1)df3['LEAD_PRODUCT'] = np.where((df3.yp_cuml+df3.internet_cuml<0.85), df3.LEAD_PRODUCTX, 'DM')
df3=df3[['yp_probability','internet_probability', 'dm_probability', 'LEAD_PRODUCT','BEST']]df_sum = pd.DataFrame(df3.groupby(['LEAD_PRODUCT'])['BEST'].agg(['mean','count', 'std','sum']))
df_sum['total']=df_sum['count'].sum()
df_sum['pct']=df_sum['count']/df_sum['total']
df_sum

现在,15%的企业客户将获得直邮优惠。其他人将获得互联网或黄页报价。

技巧三—将每个概率标准化,这样每个概率都在一个共同的尺度上进行测量(平均值为 0.5,标准偏差为 0.01)

这项技术将在一个共同的尺度上标准化三个产品概率(平均值为 0.5,标准偏差为 0.01)。在我们将三个预测标准化后,我们将使用标准化的值来分配产品报价。

df2=df_datax.copy()

计算每个指标的平均值和标准偏差。

df2['YP_STD']=df2['yp_probability'].std()
df2['YP_MEAN']=df2['yp_probability'].mean()
df2['DM_STD']=df2['dm_probability'].std()
df2['DM_MEAN']=df2['dm_probability'].mean()
df2['INTERNET_STD']=df2['internet_probability'].std()
df2['INTERNET_MEAN']=df2['internet_probability'].mean()

使用平均值和标准差来标准化指标。

df2['S_yp_probability']=(50+(df2['yp_probability']-df2['YP_MEAN'])*(10/df2['YP_STD']))/100
df2['S_dm_probability']=(50+(df2['dm_probability']-df2['DM_MEAN'])*(10/df2['DM_STD']))/100
df2['S_internet_probability']=(50+(df2['internet_probability']-df2['INTERNET_MEAN'])*(10/df2['INTERNET_STD']))/100

对标准化变量应用“赢家通吃”方法。

df2["BEST"] = df2[["S_yp_probability", "S_internet_probability","S_dm_probability"]].max(axis=1)
df2['LEAD_PRODUCT']=np.where((df2.S_yp_probability==df2.BEST),'YELLOW PAGES',
                                      (np.where((df2.S_internet_probability==df2.BEST),'INTERNET',
                                                (np.where((df2.S_dm_probability==df2.BEST),'DM','DOODOO')))))df_sum = pd.DataFrame(df2.groupby(['LEAD_PRODUCT'])['BEST'].agg(['mean','count', 'std','sum']))df_sum['pct']=(df_sum['count'])/df_sum['count'].sum()df_sum

请注意,在我们将变量标准化后,收到直邮优惠的小型企业客户数量大幅增加。这是有充分理由的。如果你深入研究这些数据,你会发现直邮的客户群与互联网广告和黄页的客户群有很大的不同。换句话说,最有可能购买直邮的客户通常不同于那些很有可能购买互联网和黄页的客户。

技巧四——将预期产品收入和购买可能性结合起来。

使用预测收入为每个小型企业客户分配产品可能是一个好主意。在这个技巧中,我们用预期收入来衡量每个购买的可能性。
在这个例子中,我们只是简单地用预期收入乘以购买概率的乘积。

预期收入' * '购买概率'

还有很多其他方法可以将两者结合起来;什么是最好的取决于您的业务问题的背景。

df4=df_datax.copy()

将预测收入乘以购买概率。

df4['wgt_yp']=df4['yp_probability']*df4['predicted_yp_revenue']
df4['wgt_internet']=df4['internet_probability']*df4['predicted_internet_rev']
df4['wgt_dm']=df4['dm_probability']*df4['predicted_dm_rev']

对新变量使用“赢家通吃”方法并检查结果。

df4["BEST"] = df4[["wgt_yp", "wgt_internet","wgt_dm"]].max(axis=1)df4['LEAD_PRODUCT']=np.where((df4.wgt_yp==df4.BEST),'YELLOW_PAGES',
                                      (np.where((df4.wgt_internet==df4.BEST),'INTERNET',
                                                (np.where((df4.wgt_dm==df4.BEST),'DM','DOODOO')))))df_sum = pd.DataFrame(df4.groupby(['LEAD_PRODUCT'])['BEST'].agg(['median','count']))
df_sum['pct']=(df_sum['count'])/df_sum['count'].sum()
df_sum

使用购买概率和收入预测来总结每个小型企业客户。

在前面的示例中,我们的目标是只选择一种产品提供给每个小型企业客户。正如我前面提到的,当您与最终客户的互动很少时,这通常很有用。在第二个例子中,我将总结机器学习模型输出,并呈现一个客户的完整视图。就像我之前说的,有很多方法可以做到这一点。我将只强调两个。没有“正确”的答案。最佳答案取决于您业务问题的背景。希望这能给你一些启发。

技巧五—将潜在客户总结为金星和银星客户

df5=df_datax

创建一个非常小的随机数。在我们创建十分位数之前,我们会将它添加到我们的加权值中。这是为了确保我们十分之一的边缘是干净的。

df5['wookie'] = (np.random.randint(0, 1000, df5.shape[0]))/100000000000000000

将预测收入乘以购买概率。

df5['wgt_yp']=(df5['yp_probability']*df5['predicted_yp_revenue'])+df5['wookie']
df5['wgt_internet']=(df5['internet_probability']*df5['predicted_internet_rev'])+df5['wookie']
df5['wgt_dm']=(df5['dm_probability']*df5['predicted_dm_rev'])+df5['wookie']

创建最高权重值在十分位数 100,最低权重值在十分位数 10 的十分位数。

df5['internet_decile'] = pd.to_numeric(pd.qcut(df5['wgt_internet'], 10, labels=False))df5['dm_decile'] = pd.to_numeric(pd.qcut(df5['wgt_dm'], 10, labels=False))
df5['yp_decile'] = pd.to_numeric(pd.qcut(df5['wgt_yp'], 10, labels=False))
df5['yp_decile']=(df5['yp_decile']+1)*10
df5['dm_decile']=(df5['dm_decile']+1)*10
df5['internet_decile']=(df5['internet_decile']+1)*10

简化数据框,仅保留您需要的记录。

df_one=df5[['cust_id','internet_decile','dm_decile','yp_decile']].copy()

现在我们将十分位数归纳为三个不同的组。

第一组是“金星”这个群体是你的产品的 A+++客户。如果有人获得了网络广告的金星,他们很可能会购买,我们需要花费资源让小企业客户介绍和销售产品。转化的几率很高。

第二组是“银星”这个群体包含第二层潜在客户。购买该产品的可能性很大,但不是非常大。

第三组是“NO_STAR”这个群体购买该产品的可能性很小。

请注意,我将“GOLD_STAR”归类为前十分之一,“SILVER_STAR”归类为接下来的三十分之一。“NO_STAR”是最后六个十分位数。如何将数据分组,分组数量取决于您的业务问题以及您联系每个小型企业客户所需的资源量。例如,如果你只有足够的销售人员去接触 5%的潜在客户,这种细分就没有什么意义。

df_one['internet']=np.where((df_one.internet_decile>90),'GOLD STAR', 
                         np.where(((df_one.internet_decile<=90) & (df_one.internet_decile>=70)),'SILVER STAR', 
                                  np.where(((df_one.internet_decile<=60)),'NO STAR', 'POOPY')))df_one['yp']=np.where((df_one.yp_decile>90),'GOLD STAR', 
                         np.where(((df_one.yp_decile<=90) & (df_one.yp_decile>=70)),'SILVER STAR', 
                                  np.where(((df_one.yp_decile<=60)),'NO STAR', 'POOPY')))df_one['dm']=np.where((df_one.dm_decile>90),'GOLD STAR', 
                         np.where(((df_one.dm_decile<=90) & (df_one.dm_decile>=70)),'SILVER STAR', 
                                  np.where(((df_one.dm_decile<=60)),'NO STAR', 'POOPY')))df_one.head()

汇总以查看每个类别中的客户数量。

df_sum = pd.DataFrame(df_one.groupby(['internet'])['yp_decile'].agg(['median','count']))
df_sum['pct']=(df_sum['count'])/df_sum['count'].sum()
df_sum

简化数据集。

df_one=df_one[['cust_id','yp','dm', 'internet']]

现在,让我们看一些记录,看看该档案如何推荐您应该向每个小型企业客户提供什么。

sample=df_one[df_one['cust_id']==516211000001]
sample

这是一个 A++++++的前景。他们很有可能购买所有三种广告产品。我们应该优先考虑这一前景。在这个小型企业客户身上使用许多资源是有意义的。也许我们带他们出去吃饭。也许我们可以将客户分配给我们最好的销售代表。这个潜在客户非常好。

sample=df_one[df_one['cust_id']==516211000042]
sample

这种前景并不乐观。花费大量资源来转化这种前景是没有意义的,因为他们购买任何产品的概率都很低。

sample=df_one[df_one['cust_id']==516211000010]
sample

这种前景应该通过互联网广告和黄页来实现。考虑到购买的可能性很小,花费资源销售直邮毫无意义。

技巧六—将潜在客户概括为金星和银星客户,同时覆盖其他业务特征。

有时,除了机器学习模型之外,加入关于潜在客户的信息也是有意义的。信用风险通常是一个需要考虑的重要因素。如果一个小企业前景有不良信用,你可能想确保你得到你的钱。如果这是不可能的,你可能应该跳过他们,把你的资源卖给其他人。

在下面的代码中,我给每个潜在客户分配了一个“星级”类别,但是如果一个潜在客户有信用标志,我将他们归类为“无信用”

df_one=df5.copy()df_one['internet']=np.where((df_one.internet_decile>90 ) & (df_one.credit_flag==0),'GOLD STAR', 
                         np.where(((df_one.internet_decile<=90) & (df_one.internet_decile>=70) & (df_one.credit_flag==0)),'SILVER STAR', 
                                  np.where(((df_one.internet_decile<=60) & (df_one.credit_flag==0)),'NO STAR', 'NO CREDIT')))df_one['dm']=np.where((df_one.dm_decile>90 ) & (df_one.credit_flag==0),'GOLD STAR', 
                         np.where(((df_one.dm_decile<=90) & (df_one.dm_decile>=70) & (df_one.credit_flag==0)),'SILVER STAR', 
                                  np.where(((df_one.dm_decile<=60) & (df_one.credit_flag==0)),'NO STAR', 'NO CREDIT')))df_one['yp']=np.where((df_one.yp_decile>90 ) & (df_one.credit_flag==0),'GOLD STAR', 
                         np.where(((df_one.yp_decile<=90) & (df_one.yp_decile>=70) & (df_one.credit_flag==0)),'SILVER STAR', 
                                  np.where(((df_one.yp_decile<=60) & (df_one.credit_flag==0)),'NO STAR', 'NO CREDIT')))

344 个前景有不良信用,应该避免。

df_sum = pd.DataFrame(df_one.groupby(['yp'])['internet_probability'].agg(['median','count']))
df_sum['pct']=(df_sum['count'])/df_sum['count'].sum()
df_sum

最后,让我们从上面看一下我们的一个客户。以前,这种前景是有希望的。然而,当你考虑信用因素时,你可能应该远离。

df_one=df_one[[‘cust_id’,’yp’,’dm’, ‘internet’]]sample=df_one[df_one[‘cust_id’]==516211000010]
sample

这个例子处理向小企业客户销售广告,但是基本思想也适用于其他情况。

比方说,你试图在一个电子商务网站(一个推荐引擎)上为消费者匹配产品。产品的数量可能会更多,所以您可能希望向消费者展示多种产品。基本思路是一样的。你会选择顶级 X 产品而不是顶级产品。

结论

正如我上面提到的。这绝不意味着是针对特定实体总结机器学习模型这一主题的全面解决方案。相反,我只是想给你一些关于什么是可能的想法。特定问题的最佳解决方案总是取决于上下文。

我希望这有所帮助。

用自然语言处理技术概括医学文献

原文:https://towardsdatascience.com/summarizing-medical-documents-with-nlp-85b14e4d9411?source=collection_archive---------10-----------------------

图片由 funforyou7 来自 Vecteezy

如果你想建立自动总结长文本的工具,自然语言处理肯定是一条可行之路。然而,由于许多原因,医疗文件可能很难处理。这里有一些关于如何应用文档摘要而不犯任何错误的考虑。

什么是文档摘要?

文本摘要是一项自然语言处理(NLP)任务,我们试图从文本输入(如书籍、文章、新闻)开始创建摘要。

当来源是一个文档时(在我们的例子中是一个临床文档,像出院信和护理报告),我们称之为文档摘要

根据输出类型,文档摘要可以是:

  • 提取:摘要是从输入的文本中提取的。输出通常是原文中最重要的句子的连接。
  • 摘要:摘要由生成。这意味着我们使用原始文本来学习内部表征,然后我们使用这样的表征来生成新的文本。输出是,而不是输入句子的组合/串联。
  • 混合:在识别出一个提取中间状态后产生一个抽象概要或者他们可以根据文本的细节选择使用哪种方法(例如:指针模型)。

摘录总结示例。通过保留输入中信息最丰富的句子,原始文档被压缩成一个单句文档。(图片由作者提供)

临床文档摘要的问题

尽管 NLP 有很大的承诺,但并非所有闪光的东西都是金子。当处理生物医学文本时,问题总是迫在眉睫。

在这种情况下,问题就出在我们试图传达的类型的信息上,这种信息可以是难以置信的精确和具体。在临床文件中,词汇选择很重要数字和单位很重要,解释和改写的余地很小。

这对抽象的摘要模型来说是个坏消息。到今天为止,你的超级骗子 GPT 怪物,经过数万亿次的训练,将无法重新表述"心电图显示向心 LVH,EF 为 62%。出院用药:诺和灵 70/30,每日两次 15 单位“不要弄乱了。
不幸的是,这里没有诠释和创造的空间。

然而,我们必须考虑到并不是每一篇生物医学文章都是临床文档。散漫的、写得好的医学论文传达不同种类的信息,可以讲述不同的故事,更适合文本生成。然而,生物医学文本是复杂的,抽象模型有时仍然会犯事实错误。但在恢复摘要时犯事实错误的影响比打包解雇信要轻松得多。

获得事实上正确的生成摘要的一个重要的方法——但仍然相对未被探索——涉及混合模型。指针生成器网络 ( 参见 et al .,2017 )尤其似乎能够产生更流畅的摘要,同时解决了再现事实细节不准确的缺点( Dang et al .,2019 )。这是通过将提取约束(即指针)添加到抽象过程中来实现的:一些不能弄乱的单词是从源文本中复制的,其余的是生成的。

图片来自 Vecteezy

总结方法和实现

今天我们有很多有前途的摘要算法。然而,评估哪一个是最好的是一个长镜头。首先,对于使用哪些指标来评估这些系统还没有明确的共识(我希望在下一篇博文中回到这个问题上)。此外,最好的摘要技术是高度依赖于你感兴趣的领域和文本类型

鉴于上面讨论的前提,这里我们将实现两种不同的临床文档摘要策略,即可靠快速提取

这两种方法都是无监督的:我们不依赖于将每个文档与人工生成的摘要相关联的标记数据集,因为它们创建起来很昂贵,并且需要领域专家的贡献。我也不知道有任何公开可用的临床报告评估数据集(如果有,请在评论中告诉我!).

我们将使用的输入数据取自 mtsamples.comhttps://www.mtsamples.com/,这是一个庞大的匿名转录医疗报告集合,可以免费获得。

我们将使用一封心脏评估信,但是您可以随意探索该集合并尝试使用其他文档。

传统方法:基于频率的句子评分

这是最简单、最直接的方法。这里,我们使用信息论为输入的每个句子分配一个基于相对频率的分数。一个句子的高值意味着它的内容可能是信息性的。
SpaCy 的帮助下,我们可以用几行代码实现这一点,SpaCy 是一个非常棒的库,旨在快速流畅地实现标准的 NLP 管道。

初始化

这里我们使用 SpaCy NLP 管道来处理英语,这非常方便,因为它返回一个 Doc 对象,该对象包含已经标记化和预处理的文本,被分成单词和句子。

首先,我们遍历 doc 对象中的标记化文本,用每个唯一的单词(没有停用词,没有标点符号)及其出现的相对频率创建一个字典。

词频计算

我们已经提到了摘要是如何基于句子评分的。因此,我们需要找到一种方法,给每个句子一个重要性分数,这样我们就可以在摘要中包含最重要的句子。为了给每个句子打分,我们对每个句子中的 相对词频求和,然后我们创建一个字典,将句子和它们的分数配对。

相对频率总和的问题在于它对短句不利。这是一件坏事吗?嗯,看情况。
确实存在这样的情况,即在一个繁琐的句子中找到有用信息的概率要高于较短的句子。然而,事实可能并非如此:虽然临床记录中的病历部分可能会很冗长,但药物处方或诊断通常会被浓缩成由几个词组成的短句。为了解决这种潜在的不希望的长度偏差,我们可以通过将相对频率和除以每个句子中的字数来归一化

句子评分

最终摘要heapq 模块中的 nlargest 函数生成,该函数高效地返回得分最高的 k 个句子

汇总生成

我们检查的文件是一封关于一名患者的,该患者有治疗控制的高血压、临界糖尿病和肥胖症的病史。
输出摘要如下所示:

  • NON _ REL:“他否认有任何冠心病的症状,但他可能有某种程度的冠状动脉粥样硬化,功能测试可能影响下壁[S1]。他有冠心病家族史,但否认有任何心绞痛或不耐努力的症状[S2]。我担心这位先生可能患有糖尿病和代谢综合征,包括躯干肥胖、高血压、可能的胰岛素抵抗、一定程度的空腹高血糖以及轻微的甘油三酯升高[S3]。总之,我们有一位 67 岁的男性患者,他有冠心病的危险因素[S4]。他进行了踏车心脏复律,仅进行到第 2 阶段,当患者达到预测最大心率的 90%时,监督医生终止了该试验[S5]。”**
  • REL:“众所周知,他的母亲患有冠心病[S1]。心脏检查正常[S2]。静脉压正常[S3]。这个病人对阿司匹林[S4]过敏。肾功能正常[S5]。”**

正如我们所料,的第一个输出显示了冗长且内容丰富的句子,而第二个输出则简洁得多。第二个总结也倾向于更多地关注病人的进展,忽略了医生担心的重要信息。

考虑到这一点,我们可以说摘要#1 在质量上优于这种类型的笔记。

尽管这个玩具示例很简单,但是这些模型现在仍然非常流行,并且经过一些改进,输出摘要的质量可能已经很高了。例如,学术文献中一种非常常见的方法( Widyassar 等人,2019 )不是依赖内部频率(只对长文本有效),而是使用 TF-IDF 计算整个临床样本集合上的词频。当文档显示可用于获得关于内容的额外信息的循环结构时,还可以设计额外的加权方案,如位置惩罚 ( Sarker 等人,2020 )。

图片由 Reno Devissandy 提供,来自 Vecteezy

现代方法:基于变压器的总结

可以根据不同的标准选择句子。第二种方法不是使用术语频率,而是围绕着 BERT ( Delvin 等人,2018 ),这是Transformer(vas Wani 等人,2017 )家族最受欢迎的模型之一。

讨论 BERT 的细节超出了这里的范围。我们只需要知道这一大堆注意力驱动的编码器是迄今为止学习上下文嵌入最有效和最流行的技术之一。

这种方法背后的主要思想是通过对预训练深度学习模型的输出嵌入进行聚类来执行提取摘要,如 Miller,2019 中所述。这项工作旨在创建讲座摘要,利用文本嵌入的 BERT 模型和 K-means 聚类来识别靠近质心的句子以进行摘要选择。

此处可用的汇总器管道遵循以下 4 个步骤:

  1. 传入的文本经过预处理,并标记为干净的句子。
  2. 将标记化的句子输入到 BERT 模型以获得句子嵌入。BERT 产生 N×W×E 个嵌入,其中 W 等于标记化的单词。为了得到句子级的嵌入,嵌入可以被平均或最大化以产生一个 N×E 矩阵。
  3. 使用 K-means 对句子嵌入进行聚类。
  4. 通过挑选更接近其质心的句子来选择候选摘要句子。因此,聚类的数量 K 定义了概要的输出句子的数量。

结果如下:

“感谢您推荐样本患者先生进行心脏评估【S1】。这是一名 67 岁的肥胖男性,有治疗控制的高血压、临界糖尿病和肥胖史[S2]。体检显示一名中年男子体重 283 磅,身高 5 英尺 11 英寸[S3]。
我担心这位先生可能患有糖尿病和代谢综合征
,这位先生患有躯干肥胖、高血压、可能存在胰岛素抵抗和一定程度的空腹高血糖,以及轻微的甘油三酯升高【S4】。鉴于没有症状,目前需要进行药物治疗,并对危险因素进行非常积极的调整[S5]。在没有症状的情况下,我目前没有发现进行任何进一步检查的迹象,如冠状动脉造影[S6]。”

这份总结几乎包含了我们需要的一切。第一句解释了临床记录的目的(心脏评估)。然后,下面的[S2] [S3]句子揭示了病人情况的细节(年龄、病史、医疗条件等。),而最新的句子围绕着医生的担忧(即为什么他需要心脏评估,在[S4]中解释)和他的适应症/意图([S5]和[S6])。

图片由 imajin noasking 来自 Vecteezy

结论

在本文中,我们探讨了两种不同的策略来解决总结临床文档的问题。在这种情况下,文档摘要可能会很棘手,原因有很多:医生的词汇选择、简洁的信息密集型句子加上冗长的句子、缩写、拼写错误等。
在这种情况下,应不惜一切代价避免事实错误。这也是我们从一开始就放弃抽象概括的主要原因。

但是,有一个重要的工具我们没有在这里讨论。一个在未来几年可能变得非常有用的工具,它可以克服像临床领域这样的棘手领域中的文档摘要的局限性:知识库。在最近 30 年里,科学家们付出了非凡的努力,将生物医学概念和关系映射到复杂的本体,实现了医学知识的共享和形式化。因此,用特定领域的本体信息增强现代摘要技术可能是克服当前在报告准确事实信息方面的限制的关键。

我希望尽快找到时间,在一篇新文章中讨论总结评估策略指针生成器网络。与此同时,请在评论区留下你的想法,如果你觉得这有帮助,请分享!如果你喜欢我的工作,现在你也可以给我买瓶啤酒!🍺

*https://www.linkedin.com/in/tbuonocore/ *

张量流中具有循环学习率的超收敛性

原文:https://towardsdatascience.com/super-convergence-with-cyclical-learning-rates-in-tensorflow-c1932b858252?source=collection_archive---------15-----------------------

使用循环学习速率表的超收敛是深度学习中最有用的技术之一,但经常被忽略。它允许网络架构、损失函数工程、数据扩充实验和训练生产就绪模型的快速原型制作,在数量级上减少训练时间和时期。

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

这篇文章和附带的代码表明,可以在几分钟内根据初始化的权重(即,未预训练或转移)训练深度神经网络模型以完成复杂任务,例如超分辨率。

以这种方式训练的技术来自几年前的研究。2015 年,Leslie Smith 发表了一篇题为训练神经网络的循环学习率的论文,概述了通过循环达到非常高的学习率来更快(用更少的时期)训练深度神经网络模型的方法。可悲的是,大多数深度学习实践者都没有注意到这一点。

这种技术是如此有效,以至于在不使用预训练模型的情况下,从初始化开始大约 4 分钟内,可以在低至 16 个时期内训练现有技术的超分辨率模型。取得了如下令人印象深刻的结果。

对来自 DIV2K 验证集的图像的裁剪执行的示例超分辨率

从 IDN 深度神经网络架构生成图像,该架构基于通过信息提取网络的快速准确的单幅图像超分辨率论文,其模型仅在 DIV2K 训练集中的 800 幅图像的训练集上训练了 16 个时期。这不是使用迁移学习训练的模型。

用于培训的学习率在 7e-3 和 7e-4 之间循环,最后一个周期在 7e-5 和 7e-6 之间。

7e-3 比传统上用于训练这些深度神经网络的学习速率高得多,后者通常可能是 2e-4,然后分段衰减。

12 个时期后的 2 倍超分辨率,左低分辨率,右高分辨率。来自 DIV2K 数据集的图像。

12 个时期后的 2 倍超分辨率,左低分辨率,右高分辨率。来自 DIV2K 数据集的图像。

12 个时期后的 2 倍超分辨率,左低分辨率,右高分辨率。来自 DIV2K 数据集的图像。

12 个时期后的 2x 超分辨率,来自 DIV2K 数据集的低分辨率左图像和改进的右图像。

12 个时期后的 2 倍超分辨率,左低分辨率,右高分辨率。图片来自 DIV2K 数据集

训练时间确实取决于硬件,这项研究是使用 NVidia 3080RTX 进行的,4 分钟的训练时间数字。

学习率高,训练不稳定

通常,高学习率会导致不稳定的训练,并导致模型偏离且无法被训练。小的学习率可能永远不会收敛,或者可能卡在次优模型上。因此,中等的学习速率被选择并用于许多时期,例如 10,000 个时期并不少见。步进式学习率并不少见,在训练过程中有几个降低学习率的步骤,如分段常数衰减学习率计划。

利用循环学习率时间表,高学习率仅维持很短的时间,并且有助于避免训练变得不稳定、爆发梯度和模型发散。即使是短时间的较高学习率也允许在相对较短的时期内训练和找到接近最优的模型。

实验

还有其他因素,如具有可以快速训练的深度神经网络架构,找到并使用最佳初始化。使用超级收敛可以让您轻松快速地找到并测试这些。

研究中多少实验都不会有结果,能够在更短的时间内进行越来越多不同的实验对研究人员来说是无价的。

如果你在云基础设施上进行培训,那么更快的培训和更少的能源使用可以节省成本,当云数据中心占世界能源使用的 1%以上时,这不是一件坏事。

张量流和 PyTorch

杰瑞米·霍华德在他的 Fastai 图书馆和课程中使用 PyTorch 向一些从业者和学生推广了循环学习率计划,特别是使用迁移学习和重新训练修改的现有(预训练)模型。在与 PyTorch 一起在 TensorFlow 中实现深度学习后,我发现令人惊讶的是,在 TensorFlow 2 中没有找到太多超级收敛的证据,也没有太多实际例子,因此有了写这篇文章的灵感,并希望能帮助其他人。

深度神经网络架构

通过使用循环学习率计划来实现超级收敛,可以快速试验测试更多架构,改变它们并调整它们的超参数。

损失函数

工程有效损失函数可能很复杂,尤其是在我的文章中概述的混合和加权值,能够在几分钟内评估调整,而不是几小时或几天,可以提高生产率,并允许实验更加多样化和更加详细。

数据扩充

数据扩充是另一个非常有效的工具,许多深度学习实践者没有充分利用它。使用循环学习速率表来实现超级收敛允许快速测试不同的数据增强,以查看每种增强技术的有效性,并调整增强的超参数。例如,为随机亮度增加找到合适的增量。

TensorFlow 2 中的循环学习率计划

这相当于 TensorFlow 2 的循环学习率时间表的文档范围。这是很好的实现,并可在 TensorFlow 插件。

如果您知道参数是什么以及要指定什么,那么实现就不会太复杂,而文档在这方面有所欠缺。

你需要安装 TensorFlow 插件与 pip 或其他。

pip install tensorflow-addons

然后在代码中导入循环学习率

from tensorflow_addons.optimizers import CyclicalLearningRate

然后创建一个循环学习率计划,每个参数将在下面详细介绍。我相信,这些参数的不明确可能是 TensorFlow 学习率计划没有被广泛使用的原因之一。

cyclical_learning_rate = CyclicalLearningRate(
 initial_learning_rate=3e-7,
 maximal_learning_rate=3e-5,
 step_size=2360,
 scale_fn=lambda x: 1 / (2.0 ** (x - 1)),
 scale_mode='cycle')

然后将其指定为优化器,例如使用 Adam 算法(在 TF . keras . optimizer . Adam 中实现)进行训练。

tf.train.Checkpoint(
 model = model,
 optimizer = Adam(learning_rate=cyclical_learning_rate))

初始学习率

初始学习率是基础或最低的学习率,是每个训练周期开始时的学习率。

最大学习率

最大学习率是最高的学习率,是第一个训练周期中间的学习率,随后取决于你的尺度函数。

步长

步长是半个周期。步长是每步使用的迭代次数,一个循环由两个这样的步骤组成:一个步骤中学习速率增加,另一个步骤中学习速率减少。在论文中,Leslie Smith 建议实验表明步长等于一个时期中迭代次数的 2 到 10 倍是好的。

因此,步长应设置为每个时段内的次迭代(在 TensorFlow 2 中,训练集中的项目数除以批量大小)乘以 2 到 10 之间的因子。

来源:训练神经网络的循环学习率

标度函数

比例函数是控制从初始学习速率到最大学习速率再回到初始学习速率的变化的函数。在本文中,这是三角形、三角形 2 或指数范围之一。在我自己的实验中,我发现三角形 2 是最有效的。

三角:基本三角循环,无幅度缩放;

lambda x: 1.0

三角 2 :基本三角周期,每个周期将初始振幅减半;

lambda x: 1 / (2.0 ** (x — 1))

指数范围:将初始振幅按γ缩放至每个周期的循环迭代次数的循环;

lambda x: gamma ** x

培训步骤

莱斯利·史密斯在论文中指出:

实验表明,用至少 3 个周期来替换恒定学习速率的每一步,可以在大部分时间内训练网络权重,并且运行 4 个或更多周期将获得甚至更好的性能。

因此,训练步数应该是步长乘以 2(一个周期中的两步),然后乘以 3 或更多(周期)。这导致至少 12 个时期的训练。

有趣的是,通过我的实验,我经常发现 3 个周期比 4 个周期训练出更高性能的模型,更多周期的训练在精度/性能上有小的增加。

这个参数应该由相对于较长的训练时间,精确度的非常小的增加有多重要来确定。

此外,莱斯利·史密斯在论文中指出:

此外,最好在一个周期结束时停止训练,这是学习率处于最小值和准确性达到峰值的时候。

正确计算以确保列车在一个周期结束时停止非常重要。

步长

Leslie Smith 在论文中观察到,在实验中,每步中的 8 或 10 个时期在 2 个时期内通常只有边际改善。这个参数应该由精确度的微小增加的重要性来决定。

选择初始和最大学习率

2017 年,Leslie Smith 和 Nicholay Topin 发表了一篇题为“超级收敛:使用大学习率非常快速地训练神经网络”的论文。本文描述了如何使用学习率范围测试来检查模型是否可能超收敛,以及选择初始和最大学习率的方法。可悲的是,大多数深度学习实践者都没有注意到这一点。

在论文中它建议(CLR 是循环学习率):

当以小的学习速率开始时,网络开始收敛,并且随着学习速率的增加,它最终变得太大,并且导致训练/测试精度降低。当使用 CLR 时,该峰值处的学习率是用作最大学习率界限的最大值。最小学习率可以通过将最大学习率除以因子 3 或 4 来选择。

在我自己的实验和研究中,我发现将学习速度降低一个数量级,因此降低 10 倍会更有效。

有许多方法可以实现一个学习率查找器,通常是检查 Tensorboard 的图形来找到最佳的最大学习率。通常,学习率会随着每批训练量的增加而缓慢增加,直到损失停止改善且模型发散。则最大学习率被选择为稍小于该值的值。

1 个周期

在论文中,它建议使用一个学习率低几个数量级的最终周期,因此可能低 100 或 1000 倍。

来自报纸:

这里,我们建议对超收敛的循环学习率策略稍加修改;始终使用小于迭代/历元总数的一个周期,并允许剩余迭代的学习率比初始学习率降低几个数量级。我们将这种学习率策略命名为“1cycle ”,在我们的实验中,这种策略可以提高精确度。

这以先前的 12 个训练时期到 16 个时期的例子为例,这仍然是非常少的训练时期。

足够好的模型

用超收敛训练的模型可能并不比对更多时期执行数千次的传统分段训练更好。从我的实验和研究中,我发现模型最好接近分段训练的模型。

然而,在许多情况下,它们可能足够接近。在如此短的训练时间内达到接近 99%的准确率可能就足够了,并且实际结果可能与能够更好地概括的模型不那么过度拟合。

一个示例实现

下面是我的示例实现,演示了使用循环学习率计划的超收敛:

https://github.com/chris-thomas/idn-superresolution-tf2

这是 IDN 深度神经网络的改进版本,来自郑辉、王秀梅和高新波的论文通过信息提炼网络快速准确的单幅图像超分辨率。

我使用 SSIM 来衡量质量,因为我不相信跨图像的 PSNR 平均值是准确的,因为它是基于对数的度量。比较多幅图像中的 PSNR 可能没什么意义。

这个 IDN 的修改/改进版本是我正在进行的研究的结果,将在另一篇未来的文章中详细介绍。

使用 BigQuery ML 实现超快速的机器学习

原文:https://towardsdatascience.com/super-fast-machine-learning-to-production-with-bigquery-ml-53c43b3825a3?source=collection_archive---------19-----------------------

如何使用 Bigquery ML 快速部署您的模型,并专注于真正重要的事情。

Patrick Federi 在 Unsplash 上的照片

几个月前,在 Agorapulse,我们启动了两个新的基于机器学习的项目。因为我们已经使用 BigQuery 将近 2 年了,所以我们必须尝试一下 BQML。这是我们所学到的,以及你可以从中学到的!

最大的挑战可能不是你想的那样

作为一名机器学习工程师,你通常会考虑如何创建性能最佳的模型使用什么算法,或者如何优化模型,以从 94%的准确率提高到 96%

但如果你的公司正处于机器学习之旅的开始,这可能不是这个过程中最重要的部分。至少现在还没有。如果你正在训练一辆自动驾驶汽车,并处理人类的生活,这当然是正确的,但对我们其他人来说却不是。

首先,你将不得不面对机器学习中的两个下述挑战。

1.采纳和文化转变

在《哈佛商业评论》2019 年发表的这篇文章中,作者说“技术不是最大的挑战。文化是。”

当你的营销或产品团队要求具体的见解或分析时,你可以自由地专注于技术部分(例如:数据分析)。既然你是在回答他们已经有的问题,领养应该不是问题。

但对于不习惯机器学习的人来说,机器学习被视为一个“黑匣子”:引擎盖下是什么?它能为我做什么?
当启动一个机器学习项目时,你可能会与用户来回沟通,以帮助采用、提高可解释性,或者迭代算法本身来改善结果。采用 ML 需要时间。

在我们的一项调查中,近 90%从事成功扩展实践的公司将超过一半的分析预算用于推动采用的活动,如工作流重新设计、沟通和培训。
—《哈佛商业评论》——构建人工智能驱动的组织

2.部署和可用性

朱庇特笔记本只是一个开始。虽然大多数机器学习课程似乎都专注于笔记本内部发生的事情,但如果你就此止步,你的公司将永远无法使用你的工作。

在我们的案例中,我们希望在我们团队使用的一些工具(CRM、销售工具等)中,在我们的仪表板、数据仓库和核心产品数据库中提供我们的预测。此外,我们需要自动化训练、测试、部署和执行我们的模型的 ML 工作流。

朱庇特笔记本之后还有一段路要走!

BigqueryML 进场

BigQuery ML 是一个通过使用标准 SQL 查询,直接在 BigQuery 中创建、执行和服务机器学习模型的工具。

我们使用 BigQuery 已经快 2 年了,它从未停止改进。尤其是 BigQuery ML,在过去的几年里已经发布了大量的特性和模型

这绝对值得一试。以下是我们的发现!

BigQuery ML 的优点

  • BQML 正在使用 SQL。您不需要使用多种语言,每个曾经与 SQL 数据库交互的人都应该能够使用它。
  • 您可以直接从 BigQuery 为您的模型提供服务。无需管理为外部系统提供信息、培训和服务的工作流程。这省了很多情报部门的工作。
    在 Agorapulse,我们使用 Cloud Composer (GCP 的 Apache Airflow)来管理我们的 SQL 工作流,同时更新和服务 BQML 模型。
  • 测试起来又快又简单。您不必将数据提取到您的本地机器来尝试。也不是为了执行模型并获得好的结果而成为专家机器学习工程师。
  • 文档真的很好。一切都很详细,它包含了大量的例子:https://cloud.google.com/bigquery-ml/docs

大查询 ML 的缺点

  • BQML 可能有点像黑箱。很难知道它在引擎盖下做什么——希望它们有检查功能来获得一些见解。这使得在将数据集注入 Bigquery ML 之前很难对其进行优化,也很难使用各种选项对模型进行微调。
  • 不太灵活。如果您是一位经验丰富的数据科学家,曾经使用过 Python(或 R)和它的大量库,您可能会感到受限。有这么多的 ML 模型是 BQML 上没有的,还有大量的库可以优化你的模型。这是一种权衡,因为自己想出和部署某些东西会花费更多的时间。
    注意,您仍然可以用 TensorFlow 创建一个模型,然后用 BigqueryML 导入并服务它
  • 显然,它有其局限性。您的数据必须在 BigQuery 中。而且你只能通过批处理来提供你的结果:例如,如果你想公开一个 API 端点来动态地执行一个模型,它是不适合的。即使可以导出一个模型

BigQuery ML 发展如此之快,我发现它的缺点可能会在未来几个月内得到极大的改进。

值得吗?

好吧,对于已经在使用 BigQuery 并希望尽快关注业务价值的我们来说:我们肯定要尝试一下 BQML!

它是如何工作的?

让我们以一个我们在 Agorapulse 做过的真实项目为例。出于示例的考虑,我们将使用一个简化的数据集和一个基本的 BQML 模型(没有复杂的选项和微调)。

给一些必要的背景,Agorapulse 是一个 Saas 工具,帮助企业管理他们在 Twitter、LinkedIn、Instagram、脸书和 YouTube 上的社交媒体。基于机器学习,我们想知道一家在免费试用期测试我们的 SaaS 的公司是否有可能转化为付费客户。

创建您的模型

对于每一个 ML 项目,你将从准备数据开始。这可能是整个过程中最耗时的部分。在我们的例子中,我们使用 Airflow (Cloud Composer)来创建数据准备工作流。

下面是我们将使用的简单数据集:

对于每一家尝试我们产品的公司,我们都有使用我们 Saas 的人数、产品内部使用的语言、国家、连接了多少个社交简档,以及一个布尔值(0 或 1)来判断该公司是否测试了我们的一些主要功能:在社交网络上发布、管理收件箱、创建/导出关于你的社交账户的报告。
最后,要预测的值:公司转化了没有?

然后,你必须选择一个模型。正如文档中所写的,BQML 支持以下类型的模型:

  • 线性回归
  • 二元和多类逻辑回归
  • k 均值聚类
  • 矩阵分解
  • 时间序列
  • 提升树(基于 XGBoost 的模型)
  • 深度神经网络(DNN)
  • AutoML 表格
  • 张量流模型导入

测试几个模型来解决我们的示例问题是很有趣的,包括逻辑回归、增强树,甚至用于分类的 DNN。
让我们继续一个二元逻辑回归

CREATE OR REPLACE MODEL `medium.trial_to_paid_prediction_model`
OPTIONS 
(
    model_type='LOGISTIC_REG', 
    input_label_cols=['converted'], 
    auto_class_weights=TRUE
)
AS
SELECT
 *
FROM
`medium.trial_to_paid_prediction_dataset`

这就是创建我们的模型所需要的一切!

一些外卖

  • 唯一的强制选项是 model_type,选择一个模型。和 input_label_cols 来选择要预测的值——尽管如果您将数据集中的列命名为预测“label ”,它也会做同样的工作。
  • auto_class_weights 用于使用权重平衡分类标签。它默认为 false,但由于我们有一个非常不平衡的数据集(6%的公司已经转化),默认值可能会导致模型总是预测为 false,这实际上会导致 94%的“准确性”😉
  • 几十个选项可用于优化你的模型。您甚至可以在模型创建期间使用 transform 对数据进行预处理。
  • 检查功能,如ML.FEATURE_INFOML.TRAINING_INFO将为您提供关于您的模型及其特征的更多信息。
  • BQML 用简单的一键编码处理非数值。

通过使用以下命令,您可以看到它是如何处理不同的特性的:

SELECT *
FROM ML.WEIGHTS(MODEL `medium.trial_to_paid_prediction_model`)

评估您的模型

现在,您可以通过以下方式访问评估指标:

SELECT
 *
FROM
ML.EVALUATE(MODEL `medium.trial_to_paid_prediction_model`)

或者如果您想要指定一个阈值或一些输入数据:

SELECT
 *
FROM
 ML.EVALUATE (MODEL `medium.trial_to_paid_prediction_model`,
 (
   SELECT
    *
   FROM
   `medium.trial_to_paid_prediction_dataset`
 ),
 STRUCT(0.55 AS threshold)
)

根据您选择的模型,评估指标可能会有所变化。

乍一看,对于用几个 SQL 命令创建的模型来说,结果看起来相当不错!请记住,在这个例子中,我们只使用了 7 个特征来支持我们的模型。

一些外卖

  • 评估指标本身不足以解决问题。这取决于问题本身:在我们的案例中,如果我们想要识别出最有可能转化的前 5%的免费试用用户,并将其提供给我们的销售团队,我们可能会提高我们的阈值,这将机械地提高精确度并降低召回率。如果我们想要的是识别那些即使有微小机会转化的人,我们可以降低我们的阈值,这将导致降低精确度和增加召回。
  • 根据您使用的模型,评估指标可能会有所不同。在逻辑回归的情况下,你也可以使用ML.CONFUSION_MATRIX来检查混淆矩阵

执行您的模型

现在你的模型已经准备好了,是时候执行和服务它了!
使用 BigQuery ML,您只需要一个命令:

SELECT *
FROM
 ML.PREDICT(MODEL `medium.trial_to_paid_prediction_model`,
 (
   SELECT
   *
   FROM
   `medium.trial_to_paid_prediction_new_data`
 ),
 STRUCT(0.55 AS threshold)  #Optional - Default to 0.5
)

就是这样!下面是 BigQuery 显示结果的方式:

输出使用 BigQuery 数组。使用 UNNEST()函数访问嵌套值。

由于我们使用了逻辑回归模型,BigQuery ML 根据我们选择的阈值给出了预测值。还有每个值的概率,你也可能会用到。

向世界展示你的模型

我们已经准备好向全世界展示这个模型。由于技术上没有额外的步骤来“部署”它,您可以专注于最重要的事情:用 ML 授权您的团队,并为业务提供价值。

在 Agorapulse,我们使用气流来执行 ML 工作流程,包括:

  • 定期用最新数据重新训练我们的模型
  • 每天对新数据执行我们的模型,并将结果发送到我们需要的不同地方— CRM、销售工具等…

结论

如果像我们一样,您已经在使用 BigQuery,并且想要启动您的第一个机器学习项目,毫无疑问,您应该尝试使用 BQML。

您将在几天内而不是几周内建立并运行您的第一个模型,并能够快速关注该阶段的重要内容:向您的团队展示 ML 的价值,为其采用进行必要的文化转变,并开发技术工作流以将 ML 纳入您的“系统”。

一旦 ML 被采用并且第一批结果已经出来,你仍然有足够的时间来改进模型本身,也许在某个时候,没有 BQML。

在我写这篇文章的时候,我们现在专注于下一步:推动我们的团队采用我们推出的几个基于机器学习的项目。创造良性循环,根据反馈改进我们的模型。为每个工具和团队提供我们模型的结果。基于这些结果触发自动化—以及更多功能。

超分辨率:Adobe Photoshop 与领先的深度神经网络

原文:https://towardsdatascience.com/super-resolution-adobe-photoshop-versus-leading-deep-neural-networks-9758796fcd72?source=collection_archive---------18-----------------------

利用 Adobe 的超分辨率算法对 Unsplash 图像进行超分辨率处理

与领先的超分辨率深度神经网络模型相比,Adobe 的超分辨率效果如何?本文试图对此进行评估,Adobe 的超分辨率效果令人印象深刻。

超分辨率

超分辨率是通过提高图像的表观分辨率来改善图像质量的过程。具有有效地想象如果图像处于更高分辨率时将呈现的细节的算法。

有很多正面评价描述 Adobe Photoshop 的超级分辨率有多好,比如“让我下巴撞到地板”。经过几年对超分辨率的研究和实验,我想提出一个更具经验性的图像分辨率增强和实际图像质量指标的比较。在这篇文章中,我比较了:

  • 双三次插值方法放大
  • Adobe Camera Raw 的超高分辨率
  • 信息提炼网络超分辨率

双三次插值

双三次插值是放大图像最常用的方法,通常会导致放大后的图像外观模糊。几乎每个图像编辑器都允许双三次插值,事实上大多数互联网浏览器使用双三次插值来显示比实际尺寸大的图像。

Adobe Camera Raw 的超高分辨率

Adobe Camera Raw Super Resolution 或等效的 Photoshop Camera Raw 滤镜是最近推出的一种非常快速且易于使用的超分辨率方法,只需在 Adobe 的 Camera Raw 产品中单击“增强”即可实现。

Adobe 表示,这是一种先进的机器学习模型,对数百万张照片进行了训练,但没有给出更多细节。更多信息来自 Adobe 的博客

该算法似乎很可能是一个深度神经网络,Adobe 从推理速度、性能和处理非常大分辨率图像的能力方面取得了显著的成果。

信息蒸馏网络(IDN)超分辨率

通过信息提取网络实现快速准确的单幅图像超分辨率展示了一个由郑辉、王秀梅和高新波的研究人员在深度卷积神经网络架构上训练的模型。

信息提炼网络(IDN)被选为比较对象,因为它的超分辨率性能仍然是最先进的,而且它的通用性很好。

研究人员还评估了他们在相对高分辨率图像上的超分辨率结果,而不是早期基于深度神经网络的超分辨率中常用的典型“邮票”大小的图像。

质量(和损失)指标

哪种质量度量是最好的是一个有争议的话题,不同的研究者有不同的看法。我个人认为 SSIM 和 MAE 是质量的最佳指标,尽管 PSNR 是在超分辨率模型和算法的学术研究评估中最常见的度量。

PSNR 和 MSE 缺乏捕捉感知或特征差异的能力,例如高纹理细节。这些度量非常有限,因为它们是基于逐像素的图像差异来定义的。最高的 PSNR 不一定反映感觉上更好的超分辨率改善。

已经包括双三次插值的度量用于比较,并且在这些分辨率下,双三次放大产生相对高质量的图像。

峰值信噪比定义(PSNR)

峰值信噪比定义(PSNR)非常常用于评估图像增强技术,例如超分辨率,其中信号是地面真实/原始图像,噪声是模型未恢复的误差。尽管 PSNR 是基于对数的指标,但它是基于 MSE 的。作为质量度量,较高的值表示较高的质量。

结构相似指数(SSIM)

结构相似性指数(SSIM)是一个感知指标。SSIM 是基于图像中可见的结构。使用 SSIM 进行图像增强评估是因为对于一些研究人员来说,PSNR 不再被认为是图像质量退化的可靠指标。这是一个感知指标,用于量化由处理导致的图像质量下降。作为质量度量,较高的值表示较高的质量。

均方误差

均方误差(MSE)用于比较地面真实/原始图像的像素与预测/生成图像的像素有多远。取每个像素差值的平均值,然后平方。作为损失或误差度量,较低的值表示较高的质量。

平均绝对误差

平均绝对误差(MAE)是地面真实/原始图像和预测/生成图像之间的绝对差异之和。作为损失或误差度量,较低的值表示较高的质量。

Unsplash 的例子

这些是对高质量和高分辨率图像进行超分辨率处理的各种例子,这些图像来自流行的 Unsplash 免版税摄影网站。

在每个示例中,左图像双三次插值放大,中间图像Adobe 的超分辨率,而右图像IDN 深度神经网络的超分辨率。

如上所述,度量是将每个放大/超分辨率方法的输出与原始地面真实图像进行比较。

对于这些高分辨率图像,来自双三次插值的度量通常非常高,因为通过有效地单独使用模糊滤波器进行放大可以产生高质量的度量,特别是对于 MSE。

从 Adobe 的超分辨率来看,大多数图像的分辨率和质量的视觉改善非常明显,尽管引入或夸大了 IDN 深度神经网络超分辨率中不存在的伪像。

示例 1

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 816x1020 像素升级到 1632x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

从 Adobe 的超分辨率中,大多数图像的分辨率和质量的视觉改善是显而易见的,尽管仔细观察会发现引入或夸大了 IDN 深度神经网络超分辨率中不存在的伪像。

左:双三次放大
PSNR 双三次:38.3776
SSIM 双三次:0.9331
MSE 双三次:9.4475
MAE 双三次:0.0122

中心:Adobe 的超分辨率 PSNR:31.8368
SSIM:0.8905
MSE:42.5988
MAE:0.0358

右:IDN 超分辨率 PSNR:38.9078
SSIM:0.9400
均方误差:8.3619
平均误差:0.0122

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

来自 Unsplash 的图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

示例 2

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 845x1020 像素升级到 1690x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

即使度量标准没有指出这一点,从人类视觉的角度来看,Adobe 的超分辨率的改进优于双三次插值。IDN 模型的超分辨率带来的改进更大。

左:双三次放大 PSNR:28.0634
SSIM:0.8128
均方误差:101.5632
平均误差:0.0278

中心:Adobe 的超分辨率 PSNR:26.6016
SSIM:0.7796
MSE:142.2055
MAE:0.0384

右图:IDN 超分辨率 PSNR:29.0446
SSIM:0.8541
均方误差:81.0245
平均误差:0.0254

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

来自 Unsplash 的图像的超分辨率对比。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

示例 3

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 785x1020 像素升级到 1530x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

通过这张图片,Adobe 的超分辨率和 IDN 模型之间的改进非常相似。IDN 款的皮毛和猫须看起来更加分明和锐利。

左:双三次放大 PSNR:31.5566
SSIM:0.9564
均方误差:45.4386
平均误差:0.0091

中心:Adobe 的超分辨率 PSNR:31.1871
SSIM:0.9319
MSE:49.4732
MAE:0.0147

右图:IDN 超分辨率 PSNR:34.1575
SSIM:0.9712
均方误差:24.9650
平均误差:0.0077

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

实例 4

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 816x1020 像素升级到 1632x2040 像素

来自 Unsplash 的图像超分辨率对比。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

Adobe 的超分辨率增强了分辨率,将一些细节和特征恢复到图像中,尽管夸大了图像中的许多伪像,并且 IDN 模型再次产生了分辨率大大增强的图像。

左:双三次放大 PSNR:28.5939
SSIM:0.7417
均方误差:89.8862
平均误差:0.0559

中心:Adobe 的超分辨率 PSNR:26.5685
SSIM:0.6350
MSE:143.2957
MAE:0.0747

右图:IDN 超分辨率 PSNR:29.4697
SSIM:0.8064
均方误差:73.4695
平均误差:0.0513

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

实例 5

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 680x1020 像素升级到 1360x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

有了这张图片,Adobe 的超分辨率和 IDN 模型的度量都得到了改善。视觉上,分辨率的增强在具有更平滑细节的 IDN 模型中表现得更好。

左:双三次放大 PSNR:31.8182
SSIM:0.9673
均方误差:42.7823
平均误差:0.0062

中心:Adobe 的超分辨率 PSNR:32.6134
SSIM:0.9356
MSE:35.6236
MAE:0.0086

右图:IDN 超分辨率 PSNR:39.0521
SSIM:0.9861
均方误差:8.0886
平均误差:0.0038

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

实例 6

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 680x1020 像素升级到 1360x2040 像素

来自 Unsplash 的图像超分辨率对比。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

这是一个非常复杂的图像,需要用交互式广告牌和不同类型的照明来增强。Adobe 的超分辨率增强了分辨率,恢复了图像中的重要细节和特征,IDN 模型再次产生了分辨率大大增强的图像。

左:双三次放大 PSNR:28.0320
SSIM:0.8890
均方误差:102.3008
平均误差:0.0405

中心:Adobe 的超分辨率 PSNR:27.4427
SSIM:0.8495
MSE:117.1681
MAE:0.0591

右:IDN 超分辨率 PSNR:30.6234
SSIM:0.9383
均方误差:56.3300
平均误差:0.0308

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

例 7

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 680x1020 像素升级到 1360x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

Adobe 的超分辨率增强了分辨率,将细节和特征恢复到图像中的波浪中,尽管 IDN 模型再次产生了分辨率增强的图像。

左:双三次放大 PSNR:30.8357
SSIM:0.8405
均方误差:53.6426
平均误差:0.0307

中心:Adobe 的超分辨率 PSNR:28.0416
SSIM:0.7269
MSE:102.0751
MAE:0.0449

右图:IDN 超分辨率 PSNR:31.9297
SSIM:0.8853
均方误差:41.6971
平均误差:0.0277

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

实施例 8

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 1020x680 像素升级到 2040x1360 像素

来自 Unsplash 的图像超分辨率对比。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

一个复杂的图像,Adobe 的超分辨率通过图像中的一些细节和特征,尤其是标志/标语牌,很好地增强了分辨率,尽管 IDN 模型导致整个图像的分辨率增强。

左:双三次放大 PSNR:26.3684
SSIM:0.8523
均方误差:150.0509
平均误差:0.0413

中心:Adobe 的超分辨率 PSNR:26.2458
SSIM:0.7969
MSE:154.3489
MAE:0.0503

右图:IDN 超分辨率 PSNR:29.0718
SSIM:0.9179
均方误差:80.5191
平均误差:0.0305

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

示例 9

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 1020x632 像素升级到 2040x1264 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

在这些图片比较中,有一些新天鹅堡(Schwangau,德国)的图片变化。这是一个很好的例子,说明通过这些超分辨率方法,分辨率的视觉改善是多么显著。此外,在不同视角和质量的同一主题的不同图像之间,分辨率的提高会如何变化。

左:双三次放大 PSNR:30.0251
SSIM:0.8722
均方误差:64.6507
平均误差:0.0181

中心:Adobe 的超分辨率 PSNR:28.4533
SSIM:0.8154
MSE:92.8427
MAE:0.0234

右:IDN 超分辨率 PSNR:31.3335
SSIM:0.9158
均方误差:47.8331
平均误差:0.0159

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

实例 10

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 680x1020 像素升级到 1360x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

一个带有边缘和反射的复杂图像,Adobe 的超级分辨率通过图像中的一些细节和特征很好地增强了分辨率,尽管夸大了图像中的一些伪像。IDN 模型提高了整个图像的分辨率。

左:双三次放大 PSNR:32.0612
SSIM:0.9570
均方误差:40.4542
平均误差:0.0149

中心:Adobe 的超分辨率 PSNR:31.7344
SSIM:0.9239
MSE:43.6156
MAE:0.0338

右:IDN 超分辨率 PSNR:38.9284
SSIM:0.9804
均方误差:8.3223
平均误差:0.0099

下面的另一个比较也包括超分辨率算法试图重建的原始(地面真实)图像。左上图:双三次放大。右上图:Adobe 的超级分辨率。左下:IDN 超分辨率。右下:原图/地面真相图。

Unsplash 图像的超分辨率比较。左上:双三次放大。右上:Adobe 的超级分辨率。左下:IDN 超分辨率。右下方:原始/地面真实图像

实施例 11

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 680x1020 像素升级到 1360x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

这又是一个有边缘和反射的复杂图像,Adobe 的超级分辨率通过图像中的一些细节和特征很好地增强了分辨率,尽管夸大了图像中的一些伪像。IDN 模型提高了整个图像的分辨率。

左:双三次放大 PSNR:26.6965
SSIM:0.9350
均方误差:139.1342
平均误差:0.0156

中心:Adobe 的超分辨率 PSNR:28.8793
SSIM:0.9115
MSE:84.1695
MAE:0.0161

右图:IDN 超分辨率 PSNR:32.3578
SSIM:0.9759
均方误差:37.7836
平均误差:0.0091

实例 12

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 785x1020 像素升级到 1530x2040 像素

来自 Unsplash 的图像的超分辨率对比。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

即使度量标准没有指出这一点,从人类视觉的角度来看,Adobe 的超分辨率的改进优于双三次插值。来自 IDN 模型的超分辨率的改进更大。

左:双三次放大 PSNR:37.3767
SSIM:0.9313
均方误差:11.8964
平均误差:0.0106

中心:Adobe 的超分辨率 PSNR:30.3778
SSIM:0.8495
MSE:59.6077
MAE:0.0302

右:IDN 超分辨率 PSNR:38.4426
SSIM:0.9476
均方误差:9.3072
平均误差:0.0099

实施例 13

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 1020x744 像素升级到 2040x1488 像素

来自 Unsplash 的图像超分辨率对比。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

新天鹅堡图像的另一个例子显示了分辨率的提高,同一主题的不同图像在不同的视角和质量下会有所不同。

左:双三次放大 PSNR:25.1374
SSIM:0.8437
均方误差:199.2213
平均误差:0.0258

中心:Adobe 的超分辨率 PSNR:24.8581
SSIM:0.8193
MSE:212.4563
MAE:0.0285

右:IDN 超分辨率
PSNR:27.3212
SSIM:0.9104
MSE:120.4940
MAE:0.0203

实施例 14

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 1020x785 像素升级到 2040x1530 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

新天鹅堡图像的另一个例子显示了分辨率的提高,同一主题的不同图像在不同的视角和质量下会有所不同。

左:双三次放大 PSNR:29.3615
SSIM:0.8898
均方误差:75.3227
平均误差:0.0139

中心:Adobe 的超分辨率 PSNR:29.0122
SSIM:0.8530
MSE:81.6319
MAE:0.0170

右图:IDN 超分辨率 PSNR:31.7219
SSIM:0.9300
均方误差:43.7407
平均误差:0.0116

实施例 15

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 1020x680 像素升级到 2040x1360 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

曼谷夜晚的复杂图像,Adobe 的超级分辨率通过图像中的一些细节和特征很好地增强了分辨率,尽管 IDN 模型导致整个图像的分辨率大大增强。

左:双三次放大 PSNR:25.2616
SSIM:0.8842
均方误差:193.6065
平均误差:0.0452

中心:Adobe 的超分辨率 PSNR:25.5575
SSIM:0.8539
MSE:180.8530
MAE:0.0608

右:IDN 超分辨率 PSNR:29.0846
SSIM:0.9545
均方误差:80.2820
平均误差:0.0304

实施例 16

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 680x1020 像素升级到 1360x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

这又是一个有边缘和反射的复杂图像,Adobe 的超级分辨率通过图像中的一些细节和特征很好地增强了分辨率,尽管夸大了图像中的一些伪像。IDN 模型提高了整个图像的分辨率。

左:双三次放大 PSNR:27.7844
SSIM:0.9332
均方误差:108.3041
平均误差:0.0244

中心:Adobe 的超分辨率 PSNR:29.2190
SSIM:0.8874
MSE:77.8356
MAE:0.0321

右:IDN 超分辨率
PSNR:34.6705
SSIM:0.9767
MSE:22.1834
MAE:0.0126

实例 17

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 601x1020 像素升级到 1202x2040 像素

来自 Unsplash 的图像超分辨率对比。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

Adobe 的超分辨率增强了分辨率,将一些细节和特征恢复到图像中,尽管夸大了图像中的伪像,并且 IDN 模型再次产生了分辨率大大增强的图像。

左:双三次升阶 PSNR 双三次:32.3341
SSIM 双三次:0.8897
MSE 双三次:37.9897
MAE 双三次:0.0251

中心:Adobe 的超分辨率 PSNR:29.5855
SSIM:0.7945
MSE:71.5363
MAE:0.0438

右:IDN 超分辨率 PSNR:35.6721
SSIM:0.9354
均方误差:17.6143
平均误差:0.0195

实施例 18

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 1020x680 像素升级到 2040x1360 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

Adobe 的超分辨率夸大了图像中的许多伪像,一些特征如眼睛的分辨率比双三次插值有所提高。IDN 模型的皮毛和狗须看起来更加清晰。

左:双三次放大 PSNR 双三次:40.8572
SSIM 双三次:0.9486
MSE 双三次:5.3378
MAE 双三次:0.0067

中心:Adobe 的超分辨率 PSNR:35.5768
SSIM:0.9001
MSE:18.0053
MAE:0.0140

右图:IDN 超分辨率 PSNR:41.5297
SSIM:0.9559
均方误差:4.5720
平均误差:0.0066

实施例 19

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 823x1020 像素升级到 1646x2040 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

Adobe 的超分辨率增强了分辨率,将一些细节和特征恢复到图像中,尽管夸大了图像中的伪像,并且 IDN 模型再次产生了分辨率大大增强的图像。

左:双三次放大 PSNR:37.0134
SSIM:0.9717
均方误差:12.9344
平均误差:0.0056

中心:Adobe 的超分辨率 PSNR:34.0506
SSIM:0.9461
MSE:25.5872
MAE:0.0123

右:IDN 超分辨率 PSNR:39.1880
SSIM:0.9792
均方误差:7.8393
平均误差:0.0052

实施例 20

左图:双三次放大,中图:Adobe 的超分辨率,右图:IDN 的超分辨率。

分辨率:从 1020x680 像素升级到 2040x1360 像素

来自 Unsplash 的图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

一张多伦多夜晚地平线的复杂图像,Adobe 的超分辨率增强了图像的分辨率,恢复了图像的细节和特征,IDN 模型再次产生了分辨率大大增强的图像。

左:双三次放大 PSNR:29.9861
SSIM:0.8897
均方误差:65.2330
平均误差:0.0269

中心:Adobe 的超分辨率 PSNR:29.2766
SSIM:0.8433
MSE:76.8107
MAE:0.0349

右:IDN 超分辨率
PSNR:32.5325
SSIM:0.9231
MSE:36.2939
MAE:0.0213

来自我自己照片的例子

一张来自我厨房的非典型照片,用来测试超分辨率能力。

克里斯托弗托马斯图像的超分辨率比较。左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。

从度量的角度来看,Adobe 的超分辨率比双三次插值要差得多,但从视觉上看,它确实比双三次插值好,尽管只是略微好一点。

左:双三次放大 PSNR:37.2630
SSIM:0.9419
均方误差:12.2117
平均误差:0.0101

中心:Adobe 的超分辨率
T42 PSNR:34.1691
SSIM:0.8990
MSE:24.8983
MAE:0.0167

右图:IDN 超分辨率 PSNR:39.3837
SSIM:0.9528
均方误差:7.4939
平均误差:0.0089

左:双三次放大。中心:Adobe 的超级分辨率。右图:IDN 超分辨率。照片来自克里斯托弗·托马斯

作为一个额外的比较,这张 Oozells 广场(英国伯明翰)的樱花树照片的超分辨率是对源图像执行超分辨率的一个例子,而不是源图像的低分辨率缩小版本。这种比较是为了将用于创建较低分辨率输入的双三次缩减从任何考虑中去除。

在这里,原始输入图像的分辨率比原始图像的分辨率高,因此没有比较度量的基础事实。从人类视觉的角度来看,与 Adobe 的超分辨率相比,IDN 模型的分辨率增强更大。例如,砌砖、树枝、窗户覆层明显变得更加锐利。

请注意,adobe 超分辨率是在原始相机图像上进行的,以使 Adobe 的算法具有潜在的优势。

这个例子包括在内,因为有研究人员认为缩小图像以用作比较不是真实世界的测试,双三次缩小不等同于最初以较低分辨率捕获的图像。例如,微软研究院的论文image pairs:Realistic Super Resolution Dataset via Beam Splitter Camera Rig,其中数据集是使用具有较低和较高分辨率相机传感器的相机装备拍摄的,从而产生真正的低分辨率和高分辨率图像对。

Set 5 数据集的示例

这些是著名的 set 5 中的图像,非常常用于超分辨率评估:

Set5 数据集:左边双三次,中间 Adobe 超分辨率,右边 IDN 深度神经网络超分辨率。

从度量的角度来看,Adobe 的超分辨率是分辨率的最低增强。然而,从人的视觉角度来看,它与帽子的材料的改进使它可能出现最高的质量。仔细观察 IDN 模型可以更好地增强一些特征,比如睫毛和眼睛。正如我经常提到的,什么是更重要的度量标准或人类感知。

左:双三次放大 PSNR:37.4317
SSIM:0.9554
均方误差:11.7465
平均误差:0.0075

中心:Adobe 的超分辨率 PSNR:32.7958
SSIM:0.9313
MSE:34.1584
MAE:0.0128

右图:IDN 超分辨率

PSNR:38.4256
SSIM:0.9658
均方差:9.3438
均方差:0.0069

Set5 数据集:左边双三次,中间 Adobe 超分辨率,右边 IDN 深度神经网络超分辨率。

对于这个小图像,Adobe 的超级分辨率确实提高了图像的分辨率,尽管 IDN 的超级分辨率进一步提高了分辨率。

左:双三次放大

PSNR:32.6560
SSIM:0.9514
均方差:35.2763
均方差:0.0129

中心:Adobe 的超级分辨率

PSNR 30.5751
SSIM:0.9483
均方误差:56.9603
平均误差:0.0177

右图:IDN 超分辨率

PSNR:35.3274
SSIM:0.9707
均方差:19.0694
均方差:0.0101

来自 Urban 100 数据集的示例:

这是一张来自 Urban 100 数据集的图像,对于超分辨率评估来说,它被认为是相当复杂的。

Urban100 数据集图像:左边双三次,中间 Adobe 超分辨率,右边 IDN 深度神经网络超分辨率。

在增强这个复杂图像的分辨率方面,IDN 模型明显优于 Adobe 的 Super Resolution。

左:双三次放大 PSNR:23.4326
SSIM:0.7692
均方误差:294.9959
平均误差:0.0344

中心:Adobe 的超分辨率 PSNR:24.8960
SSIM:0.8612
MSE:210.6105
MAE:0.0305

右图:IDN 超分辨率 PSNR:27.7919
SSIM:0.9119
均方误差:108.1152
平均误差:0.0210

结论

Adobe 在增强图像分辨率方面的超分辨率性能是内置于图像处理和编辑软件套件中的一项特殊功能。

对于更高分辨率的图像,一些图像的分辨率改善接近于先进的深度神经网络,尽管与 IDN 模型的差异是显著的。改进的变化表明该算法可能不能很好地推广。

从度量的角度来看,Adobe 的 Super Resolution 是本文中许多测试中分辨率提高最低的。然而,从人类视觉的角度来看,它的改进远远优于双三次插值。很有可能它的算法是用更感性的度量标准训练出来的。正如我经常提到的,什么更重要:度量还是人类对质量的感知?

Adobe 的超分辨率对图像中的噪声或伪像的容忍度要低得多,通常在质量较低的图像上表现较差。

Adobe 的超级分辨率只能对图像分辨率进行 2 倍的增强,而许多深度神经网络模型已经被训练对图像分辨率进行 4 倍的增强。

还对 DIV2K 验证数据集进行了评估,该数据集是为超分辨率竞赛和研究而整理的。由于 DIV2K 数据集只被许可用于学术用途,所以不能在这里使用。Adobe 的超分辨率在 DIV2K 验证数据集上表现异常出色。与这里的结果相比,这可能是因为 Adobe 的超分辨率的训练过程包括了这些图像,这不是一个公平的评估。

极高分辨率

Adobe 的超分辨率突出的特点是图像的巨大尺寸,它可以对令人难以置信的 11,205×8,404 像素图像执行超分辨率增强,放大到 22,409×16,807 像素。大多数深度学习模型在较小的分辨率下会导致内存不足的问题。

如何使用 Adobe 的超级分辨率

这似乎是隐藏的,要使用 Adobe 的超级分辨率,从 Adobe Bridge 中选择一个图像并在 Camera Raw 中打开它,然后右键单击该图像时,上下文菜单中会出现“增强”。

超分辨率成为一个常用术语

一个脚注是,我自己的超分辨率文章曾经在谷歌搜索结果中排名前两位,并且是“超分辨率”的特色谷歌片段,现在在搜索引擎排名中直线下降,被关于 Adobe Photoshop 超分辨率的博客和文章超越。当一个技术领域变得更加主流和容易接近时,这是不可避免的。

超级简单的 sci kit——学习 AWS 中的 API

原文:https://towardsdatascience.com/super-simple-scikit-learn-apis-in-aws-301c4f3b5629?source=collection_archive---------18-----------------------

使用 Lambda、API Gateway 和 AWS 让你的模型变得便宜,便于他人大规模使用

里卡尔多·贝托洛的照片

介绍

云是一个神奇的地方!你可以用很少的代码花几分钱创办一家拥有世界一流基础设施的公司。这似乎好得难以置信,但这就是今天的世界。也就是说,这不全是☀️&的问题🌈。我发现每当我尝试在云中做一些事情时,我总是要花比我预期更长的时间才能弄明白。我的意思是,文档是存在的,这没什么,但我经常求助于 blog-o-sphere。如果 blog-o-sphere 没有我的确切用例,那么…很难💩。以一种使开发和部署变得容易的方式来组织项目是困难的。

今天,我希望通过讨论如何立即为您的一个机器学习项目构建 Scikit-Learn API 来帮助解决这个问题。我们将介绍如何:

  1. 使用无服务器来设置和保护 API。
  2. 以合理且可维护的方式创建多个端点。
  3. 将 Scikit-Learn 图层附加到您的 Lambda。
  4. 将本地 python 模块导入您的 Lambdas。

我不打算介绍如何建立一个 AWS 帐户,也不打算详细介绍无服务器。我的目标是让你在最短的时间内从零开始运行到一个你不讨厌的全功能 API。

无服务器

无服务器是一个超载的术语。这通常意味着在按需配置的服务器上运行代码,而不是一直运行。在本教程中,我将使用这个词来指代无服务器框架。我喜欢把这个框架看作是 AWS 云形成模板的包装器。它提供了将基础设施视为代码的能力,以及一些部署代码的便利工具。

确保你的电脑上有 Node.js 。完成后,您可以通过运行以下命令来安装无服务器:

npm install -g serverless

这将使您能够通过一些简单的命令行操作来部署应用程序。您需要为 AWS 设置权限,无服务器文档很好地帮助您完成了这个这里的

TLDR 版本是,为无服务器创建一个 IAM 角色,并赋予它管理员权限。然后使用该角色的键来运行:

serverless config credentials --provider aws --key <YOUR_KEY> --secret <YOUR_SECRET>

Lambda 和无服务器

我们将从返回健康检查的简单 lambda 函数开始。让我们用下面的目录结构和文件创建一个项目。

这将构成项目其余部分的基础。我们有一个根文件夹,里面存放着所有叫做sklearn-api.的东西,我们还有另一个叫做aws的文件夹,我们会把所有的云代码放在那里。我们只构建了一个 API,所以 API 的基础设施将在这个文件夹中。API 只由 lambda 组成,所以我们创建了一个名为lambdas的目录,该文件夹中的每个子目录将保存一个单独的 lambda。

handler.py很简单。它包含一个名为lambda_handler的函数,该函数返回一个状态码 200 和一个表示健康的字符串。您会注意到处理程序接受的两个变量eventcontext.事件是一个 JSON 格式的文档,其中包含 lambda 函数要处理的数据。我们以后会更多地使用这个。Context 是一个包含 lambda 调用环境信息的对象,比如运行时环境、谁调用了它等等。

def lambda_handler(event, context):

    response = {
        "statusCode": 200,
        "body": "healthy"
    }

    return response

我们的serverless.yml文件同样简单。

service: sklearn-api

provider:
  name: aws
  runtime: python3.8
  region: us-west-1
  *# Set the stage to develop unless the --stage option is passed* stage: dev

functions:
  *# Holds the lambda for health checks and status reports* health:
    handler: health/handler.lambda_handler
    events:
      - http:
          path: health
          method: GET

让我们一步一步来。

  1. service定义服务的名称,您将在 AWS 控制台中看到该名称。
  2. provider描述我们将使用哪种云。在这种情况下,它是 AWS。我们将运行时设置为 python3.8,将我们的区域设置为 us-west-1,并将 API 网关阶段命名为dev
  3. functions是我们定义所有 lambda 函数的地方。在本例中,我们正在创建一个名为health的文件,其处理程序位于路径health/handler.lambda_handler处。我们在路径/health中寻找一个http事件,您可以通过 GET 请求访问它。这个事件部分是我们定义 API Gateway 如何与 lambda 函数交互的地方。

我们可以使用以下命令从根目录部署所有这些:

cd aws/api/lambdas && sls deploy

这将提供我们上面列出的所有必需资源。查看 AWS 控制台,我们可以看到有一个名为 sklearn-api-dev-health 的 Lambda。

如果您单击它,您可以看到 API Gateway 被设置为触发器。

如果您单击 API Gateway,您可以看到我们有一个健康端点,它接受 GET 请求。

单击左侧的阶段链接。这将显示您已经部署的所有阶段。对于本教程,我们将只部署一个开发阶段。对于一个真正的项目,您可能需要一个开发和生产阶段。您可以快速试验的产品,以及对您的客户来说更稳定的产品。

点击舞台从顶部抓取 API URL。我们需要它来使用我们的 API。

相当整洁!现在我们可以使用 curl 达到终点,看看它是否工作。

curl -X GET https://gbi16yga18.execute-api.us-west-1.amazonaws.com/dev/health

我们得到了 200 条回复,正文有效载荷为“健康”!就这样,我们的 API 正在进行中!

添加 API 密钥

现在任何人都可以访问我们的 API。总的来说,我们不希望那样:)。添加 API 键很简单。我们只是用几个新行更新了我们的serverless.yml文件。

service: sklearn-api

provider:
  name: aws
  *# Link this function to our API Gateway
***apiGateway:
    *# Setup a basic API key with no usage plan* apiKeys:
      - name: ${self:service}-dev-free
        value: abcdefghijklmnopqrstuvwxyz**
  runtime: python3.8
  region: us-west-1
  *# Set the stage to develop unless the --stage option is passed* stage: dev

functions:
  *# Holds the lambda for health checks and status reports* health:
    handler: health/handler.lambda_handler
    events:
      - http:
          path: health
          method: GET
          *# This indicates that the api endpoint requires a key.* **private: true**

在 provider 下,我们添加了一个带有 apiKeys 列表的 apiGateway 部分。你会注意到一个奇怪的${self:service}这是一个无服务器的注释,它说从我这里获取服务值并放在这里。这使得 API 键的名称成为sklearn-api-dev-free

我们还在健康功能 HTTP 事件下添加了private: true。这告诉 serverless 该端点是私有的,需要密钥才能被访问。

如果我们重新部署并运行上面的 curl 命令,我们会得到:

要解决这个问题,我们需要用适当的 API 键更新 curl 命令,如下所示:

*curl -X GET -H "x-api-key:* abcdefghijklmnopqrstuvwxyz*"* https://gbi16yga18.execute-api.us-west-1.amazonaws.com/dev/health

又成功了!很好,现在我们的 API 安全了!

添加第二个λ

我们的 API 在这一点上没有做任何有趣的事情,所以是时候添加一些功能了。我们来做一个 lambda,预测一个影评的情绪是正面的还是负面的。我们将调用这个端点review并创建第二个 Lambda 函数来完成这项工作。我们添加了另一个名为review 的文件夹,它有自己的处理程序,所以我们的目录结构现在看起来像这样:

首先,让我们的处理程序获取一些数据,并将其发送给我们。

import json
def lambda_handler(event, context):
    event_body = event["body"]
    if event_body is None:
        return {"statusCode": 400, "body": "body cannot be empty"}

    req_body = json.loads(event_body)

    return {"statusCode": 200, "body": json.dumps(req_body)}

我们读取来自 curl 请求的事件体的值,然后将其发送回调用者。

更新 serverless.yml 文件以包含一个名为 review 的附加函数,如下所示。你可以把它粘贴在函数部分下面。确保所有的缩进都是正确的。

**review:**
  handler: **review**/handler.lambda_handler
  events:
    - http:
        path: review
        **method: POST**
        *# This indicates that the api endpoint requires a key.* private: true

运行状况检查端点有三个不同之处。在 YAML,我们把这个叫做回顾。我们在处理程序 URL 中称之为 review (这需要与我们之前创建的目录名相匹配。看看你的 lambda 函数,你会发现它导入了文件夹。).我们把方法改成了 POST。这个端点将接收一些数据,所以我们希望使用 POST 请求。我们重新部署一下,再用 curl 打一下!

curl -X POST -H "x-api-key: abcdefghijklmnopqrstuvwxyz" https://gbi16yga18.execute-api.us-west-1.amazonaws.com/dev/review -d '{"movie_text": "I hate this movie"}'

您应该会在命令行中看到您发送的数据返回给您!我们的 post 请求正在运行。

添加 Sklearn 依赖项

让我们从添加开始

import sklearn

到 lamda_handler 的顶部进行检查。重新部署,然后向该端点发出 curl 请求。您将看到以下响应:

{"message": "Internal server error"}

让我们探索一下。在控制台中进入 Lambda 查看,并点击监视器选项卡。

在 monitor 选项卡中,您可以访问 CloudWatch 中的日志。点击最新日志。

这将让您了解 lambda 失败时发生了什么。您会很快注意到错误行,如果再深入一点,它会显示导入失败。正如我们所料:)。

查看这些日志是调试 Lambdas 的最好方法之一。当我试图创建一个新函数时,我总是来这里。

要添加 SKlearn 依赖项,我们需要创建一个 Lambda 层,或者更准确地说,使用别人已经创建的 Lambda 层😅。层基本上是您的依赖关系的自包含版本。对于 Python 来说,它的核心是所有需要用以下目录结构压缩的已安装库:

python/lib/python<3.x>/site-packages

我不打算谈论如何创建层,有很多关于这个主题的教程。在本教程中,我们将使用来自 modelzoo 的优秀人员的预制 SKlearn 图层。我们不自己做的原因是。Lambdas 可能很挑剔,对内存要求有很多规定。这使得安装 Python 库时会有许多依赖项、二进制文件等。有点挑战性。

看一下 CSV ,有很多层,每层都与不同的 AWS 区域相关联。我们正在使用 Python3.8us-west-1 中部署我们的项目,因此我们需要获取他们支持的最新版本 SKlearn,在撰写本文时该版本为 0.23.1。

将这一层的 arn 复制到 serverless.yml 中我们的 review 函数中

review:
  handler: review/handler.lambda_handler
 **layers:
    - arn:aws:lambda:us-west-1:446751924810:layer:python-3-8-scikit-learn-0-23-1:2**
  events:
    - http:
        path: review
        method: POST
        *# This indicates that the api endpoint requires a key.* private: true

现在,如果我们重新部署和重新卷曲一切工作!我们已经成功地将 SKlearn 导入到我们的 lambda 中。

训练一个模型

让我们在 IMDB 数据集上训练一个快速模型。我们需要在本地安装三个库:

python3 -m pip install scikit-learn==0.23.1 pandas datasets

为了简化数据,我们将使用拥抱面部数据集库。它内置了大量数据集,因此使用传统基准数据非常容易。对于这个项目,我们将使用imdb数据集,但如果你想看看还有什么可用的运行datasets.list_datasets()

我们只需几行代码就可以获得数据并训练我们的模型。

import datasets
import pandas as pd
import pickle
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import LinearSVC# Load in the data
data = datasets.load_dataset("imdb", split="train")
df = pd.DataFrame(data)# Train the model
model = Pipeline([
    ("tfidf", TfidfVectorizer()),
    ("classifier", LinearSVC())
])
model.fit(df["text"], df["label"])# Save off the model
with open("review_model.p", "wb") as f:
    pickle.dump(model, f)

详细描述这里发生的事情超出了本教程的范围。如果你好奇,可以看看我的另一篇关于与 SKlearn 合作的博文。基本上,我们只是训练了一个模型,从文本的一些统计属性来预测好的和坏的电影评论,并将其保存为一个腌文件。

将模型添加到我们的 Lambda 中

上传我们的模型到 S3

拼图的最后一块!创建一个 S3 桶。

我把我的命名为nic-sklearn-models.,这是我们放置腌制模型的地方。

review_model.p上传到那个桶。这是我们将存储模型以供 Lambda 访问的地方。

将我们的模型加载到 Lambda 中

我们需要更新我们的 lambda_handler 来下载我们的模型并运行预测:

让我们来看看新代码:

  • 第 19–23 行—检查并确保将 review_text 参数传递给了 POST 请求。
  • 第 25–30 行——检查我们的 Lambda 是否已经从 S3 下载了模型。如果没有,我们下载它。这加快了 Lambda 的速度,因为我们只有在冷启动时才会呼叫 S3。然而,这里有一个错误,如果我们在 S3 更新模型,这个 Lambda 是活的,它不会抓取新的。我们真的应该检查文件是否存在,S3 哈希是否没有改变。
  • 第 32–37 行—加载酸洗模型并进行预测。

我们还需要在 serverless.yml 文件中添加几行代码。AWS 对安全性要求非常严格,所以你的 Lambda 函数不能访问 S3,除非你明确授权它们这样做。

provider:
  name: aws
  *# Link this function to our API Gateway* apiGateway:
    *# Setup a basic API key with no usage plan* apiKeys:
      - name: ${self:service}-dev-free
        value: abcdefghijklmnopqrstuvwxyz
 ***# Provide additional permissions to access S3* iamRoleStatements:
    - Effect: "Allow"
      Action:
        - s3:GetObject
      Resource: arn:aws:s3:::nic-sklearn-models/***
  runtime: python3.8
  lambdaHashingVersion: 20201221
  region: us-west-1
  *# Set the stage to develop unless the --stage option is passed* stage: dev

重新部署模型,再次用 curl 打!

TADA!!!我们得到了一个关于我们评论的预测!在这种情况下,它是 0,因为审查是负面的。

额外:导入本地 python 模块

制作这个 API 不是一件容易的事,但是开发具有许多功能和可重用部分的大型 API 可能是一件痛苦的事情。这条道路上的一小步是将本地 Python 模块导入到您的 lambdas 中。我喜欢让 lambda_handlers 尽可能不涉及逻辑。为此,我试着把我所有真正的工作代码放在别的地方。让我们快点做那件事。在资源库的底部创建一个名为sklearn_api的新文件夹,并在其中创建一个名为utils.py的新 python 模块。我们将在这里存储所有可重用的 python 代码,我们的项目看起来应该是这样的:

让我们创建一个非常简单的实用函数,以一种更易于阅读的方式格式化我们的响应。与其返回“[0]”和“[1]”作为预测,不如让我们创建一个函数,将它们转换为“负面评价”和“正面评价”在我们刚刚创建的utils.py模块中添加以下函数:

from typing import Iterable

def convert_prediction(prediction: Iterable[int]) -> str:
    if prediction[0] == 0:
        return "Negative Review"
    else:
        return "Positive Review"

现在将下面一行添加到handler.py的顶部:

from sklearn_api.utils import convert_predictions

这将导入我们刚刚创建函数。现在将handler.py的返回语句改为:

return {"statusCode": 200, "body": convert_prediction(pred)}

我们的代码都设置好了。我们需要做的最后一件事是告诉 serverless 我们想要将sklearn_api模块上传到我们的 Lambda。将以下内容添加到我们的 serverless.yml 文件中的 review 函数下。

package:
  exclude:
    - ./**
  include:
    - review/handler.py
    - ../../../sklearn_api/utils.py

这是告诉 serverless,“当你打包它时,排除当前文件夹中的所有内容,包括 review/handler.py 和 sklearn_api/utils.py。”

另外,将这一行添加到 serverless.yml 的基本级别:

package:
  individually: true

这告诉 Serverless 每个函数应该单独打包。重新部署,看看你的 Lambda,你会看到额外的代码。

使用 curl 后,我们得到:

我们的功能成功了!

包扎

我们现在有一个运行在云中的 SKlearn API。只要没有人点击它,它就不会花我们一分钱,而且它会扩展到互联网可以发出的所有请求:)。这个 API 很容易使用,我们可以分离出每个 Lambda 和每个 API 端点,我们可以在它们之间共享可重用的代码段。快乐大厦!

基于迁移学习的增压图像分类

原文:https://towardsdatascience.com/supercharge-image-classification-with-transfer-learning-4b8c52e69c0c?source=collection_archive---------17-----------------------

使用位模型的图像分类

内森·杜姆劳在 Unsplash 上的照片

计算机视觉领域本身可能从 20 世纪 60 年代就已经存在,最初的主要目标是建立一个模拟人类视觉能力的人工系统。像 CNN 这样的深度学习模型在过去十年中引起了复兴,这是由于一些因素,包括更好的算法,更快的计算(GPU),易于使用的软件和工具(TensorFlow,PyTorch)和更多的数据可用性。

CNN 逐渐变得庞大而复杂,但也足以成为大多数与计算机视觉(尤其是分类)相关的任务的 goto 解决方案。然而,并不是每个人(或每个项目)都有资源(或可行性)利用大型 GPU 集群来利用这些最先进的巨型模型。进入 转移学习

在不偏离太多的情况下,迁移学习是一种利用这种先进模型(在大型数据集上预先训练)的方法,用于特定的用例,而无需担心准备大型数据集或访问地球上最新的 GPU 设置的麻烦。要深入了解迁移学习,请查看[ 1 和[ 2 ]

让我们深入到一个展示图像分类或归类背景下的迁移学习的实际例子中。这里的目标是拍摄一些动物的样本图像,看看一些预先训练好的固定模型如何对这些图像进行分类。我们将挑选几个基于复杂性的预训练的最先进的模型,比较和对比它们如何解释输入图像的真实类别。

方法学

这里的关键目标是采用现成的预训练模型,并直接使用它来预测输入图像的类别。我们在这里着重于推理,以使事情简单,而不是深入研究如何训练或微调这些模型。我们解决图像分类关键目标的方法集中于获取输入图像,从 TensorFlow Hub 加载 Python 中的预训练模型,并对输入图像的前 5 个可能类别进行分类。这个工作流程如图 1 所示。

图 1 用预训练的 CNN 进行图像分类。该图描述了使用预先训练的 CNN 模型的给定输入图像的前 5 类概率。图片来源:作者

预先训练的模型架构

在我们的实验中,我们将利用两个最先进的预训练卷积神经网络(CNN)模型,即:

  • ResNet-50: 这是一个残差深度卷积神经网络(CNN),共有 50 层,集中在标准卷积层和池层,这是一个典型的 CNN,带有用于正则化的批量归一化层。这些模型的新颖性包括剩余或跳过连接。该模型在总共具有 1000 个不同类别的标准 ImageNet-1K 数据集上进行训练。
  • BiT multi class ResNet-152 4x:这是谷歌在计算机视觉领域的最新(SOTA)发明,名为 Big Transfer,发表于 2020 年 5 月。在这里,他们建立了他们的旗舰模型架构,一个预训练的 ResNet-152 模型(152 层),但比原始模型宽 4 倍。该模型使用分组归一化层而不是批量归一化来进行正则化。该模型在总共具有 21843 个类的 ImageNet-21K 数据集[ 3 上训练。

这两种模型背后的基础架构是卷积神经网络(CNN),其工作原理是利用具有非线性激活函数的若干卷积和池层的多层分层架构。

卷积神经网络

让我们看看 CNN 模型的基本组件。通常,卷积神经网络(更普遍地称为 CNN 模型)由几个层的分层结构组成,除了输入和输出层之外,还包括卷积、汇集和密集层。典型的架构如图 2 所示。

图 2 典型卷积神经网络的架构。这通常包括卷积和池层的堆叠层次。图片来源:作者

CNN 模型利用卷积和池层来自动提取不同层次的特征,从边缘和拐角等非常普通的特征到如图 3 中输入图像所示的老虎的面部结构、胡须和耳朵等非常具体的特征。通常使用展平或全局池操作符来展平特征图,以获得一维特征向量。然后,该向量作为输入通过几个完全连接的密集层发送,最后使用 softmax 输出层预测输出类。

这种多阶段层次结构的关键目标是学习模式的空间层次,这些模式也是平移不变的。这可以通过 CNN 架构中的两个主要层来实现:卷积层和池层。

卷积层:CNN 的秘制酱就是它的卷积层!这些层是通过将多个滤波器或内核与输入图像的面片进行卷积而创建的,这有助于从输入图像中自动提取特定特征。使用堆叠卷积图层的分层架构有助于学习具有特定等级的空间要素,如图 3 所示。

图 3 从卷积层提取的层次特征图。每一层提取输入图像的相关特征。较浅的层提取更多的一般特征,而较深的层提取属于给定输入图像的特定特征。图片来源:作者

虽然图 3 提供了 CNN 的简化视图,但核心方法在某种意义上是真实的,即在初始卷积层中提取边缘和拐角等粗糙和一般特征(以给出特征图)。这些特征在更深的卷积层中的组合有助于 CNN 学习更复杂的视觉特征,如鬃毛、眼睛、脸颊和鼻子。最后,使用这些特征的组合来构建老虎的整体视觉表现和概念。

汇集层:我们通常使用像 max、min 或 mean 这样的聚合操作,从汇集层中的卷积层向下采样特征图。通常最大池是首选,这意味着我们接受图像像素的补丁(例如 2x2 补丁)并将其减少到最大值(给一个像素最大值)。最大池是优选的,因为它的计算时间更短,并且能够编码特征图的增强方面(通过取图像块的最大像素值而不是平均值)。池也有助于减少过度拟合,减少计算时间,并使 CNN 能够学习平移不变的特征。

ResNet 架构

我们前面提到的两个预训练模型都是 ResNet CNN 架构的不同变体。ResNet 代表残差网络,它引入了一个新概念,即使用残差或跳过连接来建立更深的神经网络模型,而不会面临消失梯度和模型泛化能力的问题。ResNet-50 的典型架构已经过简化,如图 4 所示。

图 4 ResNet-50 CNN 架构及其组件。关键组件包括具有剩余(跳过)连接的卷积和单位块。图片来源:作者

很明显,ResNet-50 架构由几个堆叠的卷积和池层组成,后面是最终的全局平均池和一个具有 1000 个单元的全连接层,以进行最终的类预测。该模型还引入了批量标准化层的概念,这些层散布在各层之间,以帮助标准化。堆叠的 conv 和标识块是在 ResNet 架构中引入的新概念,其利用了如图 4 中的详细框图所示的剩余或跳过连接。

跳过连接(也称为剩余或快捷连接)的整体思想是不仅堆叠层,而且直接将原始输入连接到几个堆叠层的输出,如图 5 所示,其中原始输入被添加到来自 conv 或标识块的输出。使用跳过连接的目的是通过允许梯度的替代路径流过网络,能够构建更深的网络,而不会面临梯度消失和性能饱和等问题。我们在图 5 中看到 ResNet 架构的不同变体。

图 5 各种 ResNet 架构。该图显示了基于模型中存在的总层数的各种 ResNet 模型。图片来源:作者

对于我们的第一个预训练模型,我们将使用 ResNet-50 模型,该模型已经在 ImageNet-1k 数据集上通过多类分类任务进行了训练。我们的第二个预训练模型使用 Google 的预训练大转移模型进行多标签分类(BitM ),该模型具有基于 ResNet 50、101 和 152 的变体。我们使用的模型基于 ResNet-152 架构的变体,其宽度是 ResNet-152 架构的 4 倍。

大转移(BiT)预训练模型

谷歌于 2020 年 5 月训练并发布了大转移模型,作为其开创性研究论文[ 4 ]的一部分。这些预先训练好的模型建立在我们在上一节中讨论的基本 ResNet 架构之上,其中包含一些技巧和增强功能。大转移模型的重点包括以下内容:

  • 上游训练:在这里,我们在大数据集(例如 ImageNet-21k)上训练大模型架构(例如 ResNet ),使用长预训练时间,并使用像带权重标准化的组标准化这样的概念,而不是批量标准化。一般的观察结果是,与 BatchNorm 相比,具有重量标准化的 GroupNorm 可以很好地适应更大的批量。
  • 下游微调:一旦模型经过预训练,它就可以进行微调,并“适应”任何样本数量相对较少的新数据集。Google 使用一种称为 BiT-HyperRule 的超参数启发式方法,其中使用随机梯度下降(SGD ),初始学习率为 0.003,衰减因子为 10,在 30%、60%和 90%的训练步骤中。

在我们接下来的实验中,我们将使用 BiTM-R152x4 模型,这是一个预训练的大传输模型,基于 Google 的旗舰 CNN 模型架构 ResNet-152,其宽度是 ResNet-152 的四倍,经过训练可以在 ImageNet-21k 数据集上执行多标签分类。

履行

现在,让我们使用这些预训练的模型来解决我们预测输入图像的前 5 类的目标。

提示:在位于https://github.com/dipanjanS/transfer-learning-in-action的 GitHub 资源库中可以获得支持代码笔记本

我们首先加载图像处理、建模和推理的特定依赖项。

代码清单:导入 tensorflow 和 tensorflowhub

请注意,我们在这里使用 TensorFlow 2.x,这是撰写本文时的最新版本。由于我们将直接使用预先训练的模型进行推理,因此我们需要知道 ResNet-50 和 BiTM-R152x4 模型的原始 ImageNet-1K 和 ImageNet-21K 数据集的类标签,如清单 1 所示。

代码清单 1:查看 ImageNet 1k 和 ImageNet21k 数据集的样本类标签

下一步是从 TensorFlow Hub 加载我们之前讨论过的两个预训练模型。

代码清单:加载预训练的 resnet 和 bit 模型

一旦我们准备好了预先训练好的模型,下一步将集中于构建一些特定的实用函数,您可以从本文的笔记本中访问这些函数。只是为了获得一些观点,

  • preprocess_image(…)功能帮助我们在 0-1 的范围内对输入图像像素值进行预处理、整形和缩放。
  • visualize_predictions(...)函数将预训练模型、类别标签映射、模型类型和输入图像作为输入,以条形图的形式显示前 5 个预测。

ResNet-50 模型直接给出类别概率作为输入,但是 BiTM-R152x4 模型给出类别逻辑作为输出,其需要被转换成类别概率。我们可以看看清单 2,它展示了visualize_predictions(...)函数的一部分,可以帮助我们实现这一点。

代码清单 2: visualize_prediction 函数,它获取前 5 个预测的模型概率

请记住,logit 基本上是对数优势或非标准化类别概率,因此您需要计算这些 logit 的 softmax,以获得总和为 1 的标准化类别概率,如图 6 所示,该图显示了一个示例神经网络架构,其中包含一个假设的 3 类分类问题的 logit 和类别概率。

图 6 神经网络中的 Logits 和 Softmax 值。图片来源:作者

softmax 函数基本上使用图 6 中描述的变换来压缩逻辑,从而为我们提供标准化的类概率。现在让我们将代码付诸行动吧!使用清单 3 中描述的步骤序列,您可以在任何下载的图像上利用这些函数来可视化我们的两个预训练模型的前 5 个预测。

代码清单 3:分析输入图像并可视化模型预测

瞧啊。我们有来自两个预训练模型的前 5 个预测,如图 7 所示。

图 7 雪豹图像的预测结果。图片来源:作者

看起来我们的两个模型都表现得很好,正如预期的那样,BitM 模型非常具体,并且更加准确,因为它已经在超过 21K 个具有非常具体的动物物种和品种的类上进行了训练。

如图 8 所示,与 BiTM 模型相比,ResNet-50 模型在预测相似属但略有不同物种的动物(如老虎和狮子)时有更多的不一致性。

图 BitM 和 ResNet-50 模型的正确与错误预测。图片来源:作者

局限性和可能的改进

需要记住的另一个方面是,这些模型并不详尽。它们并没有覆盖这个星球上的每一个实体。考虑到这项任务本身的数据收集需要几个世纪,如果不是永远的话,这是不可能做到的!图 9 展示了一个例子,我们的模型试图从给定的图像中预测一个非常特殊的狗品种,阿富汗猎犬。

图 9 我们的两个模型都很难预测阿富汗猎犬。图片来源:作者

根据图 9 中的前 5 个预测,您可以看到,虽然我们的 BiTM 模型实际上获得了正确的预测,但预测概率非常低,表明我们的模型不太自信(鉴于它可能在预训练阶段的训练数据中没有看到太多该犬种的例子)。在这里,我们可以微调和调整我们的模型,使它们更适合我们的特定数据集和输出标签和结果。这形成了许多应用的基础,在这些应用中,我们可以利用预先训练的模型,并使这些模型适应非常不同和新颖的问题。文章“ 用迁移学习增强你的图像搜索” 中介绍了这样一个有趣的用例

摘要

  • 图像分类是深度学习和迁移学习最流行和研究最多的应用之一
  • 卷积神经网络或 CNN 在从图像输入中提取特征时非常强大。
  • ResNets 或残差神经网络及其变体已经在大型多类数据集(如 ImageNet)上证明了性能。
  • Google 的最新 ResNet 变体 BiT model 非常强大,为图像分类任务提供了最先进的性能
  • 我们很容易利用 Tensorflow-Hub 的预训练结果来了解这些模型在新数据集上进行迁移学习/微调的能力

如果你想更多地了解这些有趣的话题,可以看看由迪潘然(DJ)萨卡尔拉格哈夫巴里曼宁出版社合作的《迁移学习在行动中》。你可以在曼宁的 liveBook 平台这里查看一下。

manning.com结账时,将 fccsarkar 输入折扣代码框,即可享受 40%的折扣 转移学习行动

参考

用 C++增强 R 函数

原文:https://towardsdatascience.com/supercharge-r-functions-with-c-dcc951128027?source=collection_archive---------36-----------------------

利用 C++将代码速度提高一倍以上。

照片由 PatrickUnsplash 拍摄

对于统计学家来说,R 一直是一门非常引人注目的语言,因为它已经根据统计数据进行了优化。随着数据变得越来越复杂和庞大,R 开始变得越来越重要,即使 Python 接管了编程领域的“市场份额”,直到今天,R 仍然坚持自己的许多统计范式,需要今天解决。在本文中,我将概述如何在 R 中利用 C++让您能够使用 Rcpp 将代码提高几个数量级。

Rcpp 是什么?

顾名思义,Rcpp 充当 R 和 C++之间的接口。它不仅允许 R 用户使用他们已经在纯 R 中构建的函数,并在 C++中构建它以获得更快的结果,而且它还使您的 C++函数能够很容易地导出并在 R 脚本中使用。

如果您在 R Markdown 笔记本中工作,这可以简单到将 Rcpp 代码块添加到您的项目中并继续您的工作。但是,如果您决定在项目中简单地使用 C++文件,这也很容易做到。

在本文中,我将向您展示一些如何在 R 代码中使用 C++并使其比以前更快的例子。我不会教你 C++的语法,我会假设你知道这篇文章的语言基础。这些例子不会太严格,因为我假设您以前从未在 R 中使用过 C++,所以通过提供简单的例子,您将能够更全面地了解这有多么强大,尤其是当问题需要大量循环时。

考虑到这一点,我们开始吧!

注:无出处图片均为作者。

示例 1 —求一个向量的和

这个例子将寻找长度为n的向量的和。虽然这个例子看起来很乏味,但它是将 C++集成到 R 中的最佳第一个例子。我们将比较 R 中的本机sum函数和我们将在 R 中自己构建的另一个sum函数sumR的性能。

在定义函数之前,第 1–4 行很重要,因为它允许您使用某些数据类型,如NumericVector。如果您在 R-Markdown 文件中使用它,您可以简单地按原样运行代码块。然而,如果您在自己的.cpp文件中定义了函数,您可以简单地使用Rcpp::sourceCpp('path/to/file')来测试和利用该函数。

现在是 R 代码:

我们将使用库bench来比较速度,并通过ggplot2来绘制。

正如我们所见,原生 R 函数执行速度最快。这并不奇怪,这就是为什么它是本机函数的原因。该图的主要目的是比较sumRsumC,因为您构建的大多数东西都没有为您构建的本机函数。

在 C++中循环所花费的时间比在 r 中实现相同的循环要快几个数量级。这是在 r 中利用 C++的主要好处。此外,在 C++中的实现几乎与本机函数本身一样快。

让我们看另一个例子。

示例 2 —寻找方差

我们将继续寻找给定向量x的方差。我们将在 C++中创建自己的函数,并将其与基 R 函数var进行比较。请注意,我们将使用标准差的计算公式,如下所示:

来自统计指南的等式

在这种情况下,方差的 C++实现与内置函数大致相同,其最快的性能稍快一些。

到目前为止,您应该对 C++和 R 如何很好地结合有了很好的了解。

如果您的 R 代码的某些方面需要大量的 for 循环,我强烈建议您利用 C++来完成手头的任务,因为这将显著提高代码的性能。此外,请随意询问关于本文的任何问题,我将很乐意回答您可能有的任何困惑。

感谢您的阅读

通过迁移学习增强您的图像搜索能力

原文:https://towardsdatascience.com/supercharge-your-image-search-with-transfer-learning-75dfb5d29ceb?source=collection_archive---------21-----------------------

使用迁移学习和近似最近邻的反向图像搜索

图片来源:贝卡·泰普特Unsplash

图像相似度

正如你可能知道的,逆向图像搜索的问题是找到相似的图像。但是如何定义图像相似性呢?给定两幅样本图像,从视觉上我们可以很容易地确定它们是否相似。我们如何以编程方式做到这一点?

一种非常幼稚的方法是基于与图像相关联的元数据。换句话说,我们可以将图像大小、RGB 值、类别标签等元数据信息与每张图像相关联。许多 web 应用程序仍在利用这种方式进行反向图像搜索。此类应用程序通常将此类元数据存储在优化的文本搜索平台中,如 ElasticSearch 或 Solr。这种方法很简单,但有许多缺陷。最明显的一个问题是标记每张图片需要大量的人工劳动。

一种更复杂的基于计算机视觉的技术是从图像本身提取不同的特征。传统的计算机视觉算法,如比例不变特征变换 (SIFT)和加速稳健特征 (SURF)在提取特征方面非常稳健,可以通过比较来识别相似的图像。SIFT、SURF 和许多其他这样的传统方法擅长从输入图像中提取关键特征。图 1 描绘了如何利用基于 SIFT 的特征来寻找相似图像。SIFT 识别每个候选人身上突出显示为彩色圆圈的关键特征,然后比较它们以找到相似的特征。

图 1:基于 SIFT 的图像相似性特征。它非常适用于刚性或不变的对象。这个例子展示了两张从不同角度拍摄的自由女神像的照片。两幅图像之间的前 50 个匹配特征已经用彩色线示出。图片来源:作者

这些是快速而强大的方法,在我们有刚性物体的情况下非常有用。例如,用矩形盒子(如包装纸盒)或圆形圆盘(如表盘)来识别图像,这种方法非常有效。另一方面,不太坚硬的物体很难匹配。例如,两个不同的人体模特以不同的姿势展示同一件衬衫/连衣裙,这对于传统技术来说可能是难以处理的。

您可能知道,可以尝试使用基于元数据的方法,甚至使用传统的基于计算机视觉的技术来识别相似的图像。两者都有各自的优势和缺陷。现在让我们从深度学习的角度来探索图像相似性。

图像特征与迁移学习

可以在特征提取、微调和预训练设置中利用迁移学习。在 CNN 的情况下,重新回顾特征提取,我们知道来自预训练模型的初始层集合如何变得善于理解图像。在迁移学习的帮助下,我们可以训练高性能的分类器,它由一个预先训练好的网络作为特征提取器,再加上几个浅层组成。

反向图像搜索用例是对预训练模型(迁移学习)的特征提取属性的巧妙利用。

反向图像搜索用例是对这种特征提取特性本身的巧妙利用。让我们利用预先训练的 ResNet-50 将图像转换为特征。这种特征通常是密集的一维向量。这个将输入转换成矢量的过程也被称为 矢量化 。我们首先需要准备一个预训练的 ResNet-50 模型的实例。接下来,我们需要一个效用函数来预处理输入图像并获得矢量输出。代码清单 1 展示了相同的实现。

代码清单 1:使用预先训练的 ResNet-50 将图像转换成特征向量

如果我们仔细观察代码清单 1,高级的tensorflow.keras API 使得准备预训练模型的实例并将其用于我们预期的特征提取变得非常容易。如图所示,该函数将图像输入转换为 2048 维的密集矢量输出。2048 维向量是从 ResNet 模型的平均池层获得的,该模型在没有顶级分类层的情况下被实例化。

注意:我们利用ResNet-50获得图像向量,但我们可以自由使用任何其他预训练模型。我们只需要记住一些方面,例如预训练网络的域、用于反向图像搜索的数据集以及输出向量的维度。例如,如果我们用VGG-16代替ResNet-50,特征向量将会减少到 512 维。当我们在接下来的小节中讨论一些高级的反向图像搜索方法时,我们将进一步讨论这些选择的影响。

在我们进入反向图像搜索的实际任务之前,我们需要一个数据集。为了便于说明,我们将使用加州理工学院 101 数据集。这个数据集是由费-李非和他的团队在 2003 年收集的,包含 101 个不同物体类别的大约 40 到 800 张图像。该数据集具有相当高质量的图像,非常适合我们的理解目的。

Caltech-101 数据集中的样本图像

我们已经准备了一个实用程序来将图像转换为矢量,让我们利用相同的函数来获得参考数据集中图像的矢量表示。这也有助于形象化这些向量来更好地理解它们。想法是,相似的物体/图像应该有邻近的向量。但是一个人如何想象一个 2048 维的空间呢?为此,我们将采用一种叫做t-分布式随机邻居或 t-SNE 的降维技术。无需深入细节,可以将 t-SNE 视为将高维向量转换到低维空间,同时保留重要特征的一种方式。一个非常简单的例子是一个很长的购物清单作为我们的起点(高维向量)。将清单上的单个项目分成几类,如蔬菜、水果、奶制品等。可以被看作是向低维空间的转换,同时仍然保持重要的特征。在我们目前的情况下,我们将使用 t-SNE 变换 2048 维向量到 2 或 3 维。通过减少维度,我们可以很容易地将它们可视化。代码清单 2 展示了我们的参考数据集到向量的转换,然后为了可视化的目的对它们进行降维。

代码清单 2:矢量化 Caltech-101 数据集和基于 t-SNE 的降维

# output
Num images   =  9144
Shape of feature_list =  (9144, 2048)
Time taken in sec =  30.623387098312378

我们正在为反向图像搜索准备一个解决方案。下一步使用这些特征来识别相似的图像。

讨厌:超快的邻居搜索

骚扰或近似最近邻哦是的是一个高度优化的超快速实现最近邻搜索从 Spotify⁴.asury 由 Spotify 开发,用于为用户提供音乐推荐。因为每天有数百万用户在他们的手机和网络上使用它,所以实现的重点是速度和准确性。用 Python 包装器在 C++中开发,是一种基于树的向量相似性搜索方法,它有效地利用了内存和并行处理。它提供了许多距离度量选项,如欧几里德、余弦、汉明等。让我们看一下在代码清单 3 中使用 ANNOY 的反向图像搜索的快速实现。

代码清单 3 (a):基于骚扰的反向图像搜索

# output
1000 loops, best of 3: 770 µs per loop

代码清单 3 (b):测试更大样本的基于骚扰的反向图像搜索的性能

# output
CPU times: user 139 ms, sys: 0 ns, total: 139 ms
Wall time: 142 ms

如清单 3 所示,使用 ANNOY 非常简单。效率高,搜索时间快得惊人。搜索结果也相当可观,如图图 2 所示。

图 2:基于恼人的反向图像搜索。每行代表一个搜索查询。最左边的列表示查询图像,搜索结果(相似度递减)放在右边。每个匹配结果都用其与查询图像的欧几里德距离来标记。图片来源:作者

ANNOY 在很大程度上克服了与搜索速度和内存需求相关的限制。它还提供了一些额外的选项来进一步提高性能。其中之一与特征向量的大小有关。这也很明显。如果我们减少向量的大小,将直接减少寻找邻居所需的内存量。我们利用了输出 2048 维向量的ResNet-50。如果我们使用像VGG-16VGG-19甚至MobileNet这样的模型,VGG 模型的特征向量将减少到 512,MobileNet 将减少到 1024(几乎减少了 50%)。除此之外,我们甚至可以利用典型的降维技术,如主成分分析(PCA)或 t-SNE,这是一些最广泛使用的技术。这种技术可以帮助我们大幅减少特征向量的大小,从而减少整体计算和内存需求(尽管会有搜索性能的折衷)。

对优化的近似搜索方法的需求如此之大,以至于多年来已经开发了许多可扩展的解决方案。不赘述细节,雅虎的局部优化产品量化 (LOPQ)⁵和邻域图和树 (NGT) 等实现已经为 Flickr 等拥有超过 10 亿个数据点的庞大数据集的商业应用开发出来。同样, Facebook 人工智能相似性搜索或 FAISS 是一个 GPU 优化的实现,速度快得惊人,即使在 Facebook 的规模下使用也非常简单。

我们在本节中讨论的反向图像搜索的不同方法和实现基于这样的核心思想:首先将图像转换为特征向量,然后是相似性搜索算法。优化的实现更进一步,它关注内存的最佳利用,同时返回结果的速度也非常快。

从这一部分可以明显看出,反向图像搜索是一个活跃的研究领域,研究人员正在利用这种技术不断拓展新的领域。这些方法的成功开辟了越来越多的使用案例,其中反向图像搜索是一个重要方面。

既然我们对反向图像搜索有了相当好的理解,我们可以利用这些知识轻松地从电子商务网站上找到类似的产品,甚至从一组照片中删除重复的照片。同样,反向图片搜索也被 Flickr 等服务广泛用于建议相似的图片,谷歌购物,Pinterest 的“相似图钉”功能,亚马逊的产品扫描仪,甚至被专业摄影师用于识别抄袭的作品。不同的场景需要不同的技术,本节讨论的每种方法的快速总结在表 1 中提供,以供快速参考。

表 1:各种邻域搜索方法的总结

如果你想更多地了解这些有趣的话题,可以看看迪潘詹·萨卡尔拉格哈夫·巴厘的《迁移学习在行动》。你可以在曼宁的 liveBook 平台这里查看一下。

manning.com结账时,将 fccsarkar 输入折扣代码框,即可享受 40%的折扣 转移学习行动

参考

【1】弹性搜索:https://www.elastic.co/what-is/elasticsearch

【2】索尔:https://lucene.apache.org/solr/

【3】加州理工学院-101 数据集:【http://www.vision.caltech.edu/Image_Datasets/Caltech101/

LOPQ:http://image.ntua.gr/iva/files/lopq.pdf

【5】NGT 代码:https://github . com/Yahoo Japan/NGT/blob/master/readme . MD # publications

【6】https://arxiv.org/abs/1702.08734NGT 论文

【7】惹怒:https://github.com/spotify/annoy

使用 PyCaret 和 Gradio 增强您的机器学习实验

原文:https://towardsdatascience.com/supercharge-your-machine-learning-experiments-with-pycaret-and-gradio-5932c61f80d9?source=collection_archive---------12-----------------------

快速开发机器学习管道并与之交互的循序渐进教程

亨特·哈里特在 Unsplash 上的照片

👉介绍

本教程是一个循序渐进、初学者友好的解释,说明如何集成 Python 中两个强大的开源库 PyCaretGradio ,并在几分钟内增强您的机器学习实验。

本教程是一个“hello world”示例,我使用了来自 UCI 的鸢尾数据集,这是一个多分类问题,目标是预测鸢尾植物的类别。本例中给出的代码可以在任何其他数据集上复制,无需任何重大修改。

👉PyCaret

PyCaret 是一个开源的低代码机器学习库和端到端的模型管理工具,内置于 Python 中,用于自动化机器学习工作流。它因其易用性、简单性以及快速有效地构建和部署端到端 ML 原型的能力而广受欢迎。

PyCaret 是一个替代的低代码库,可以用来用几行代码替换数百行代码。这使得实验周期成倍地快速和有效。

py caret简单 好用。PyCaret 中执行的所有操作都顺序存储在一个管道中,该管道对于部署是完全自动化的。无论是输入缺失值、一键编码、转换分类数据、特征工程,甚至是超参数调整,PyCaret 都能实现自动化。

要了解更多关于 PyCaret 的信息,请查看他们的 GitHub。

👉格拉迪欧

Gradio 是一个开源 Python 库,用于围绕机器学习模型创建可定制的 UI 组件。Gradio 可以让您轻松地在浏览器中“摆弄”您的模型,方法是拖放您自己的图像、粘贴您自己的文本、录制您自己的声音等。,并查看模型输出的内容。

Gradio 适用于:

  • 围绕您训练有素的 ML 渠道创建快速演示
  • 获得关于模型性能的实时反馈
  • 在开发过程中交互式调试您的模型

要了解更多关于 Gradio 的信息,请查看他们的 GitHub

PyCaret 和 Gradio 的工作流

👉正在安装 PyCaret

安装 PyCaret 非常容易,只需要几分钟。我们强烈建议使用虚拟环境来避免与其他库的潜在冲突。

PyCaret 的默认安装是 pycaret 的精简版本,它只安装这里列出的的硬依赖项。

**# install slim version (default)** pip install pycaret**# install the full version**
pip install pycaret[full]

当您安装 pycaret 的完整版本时,这里列出的所有可选依赖项也会被安装。

👉安装 Gradio

您可以从 pip 安装 gradio。

pip install gradio

👉我们开始吧

**# load the iris dataset from pycaret repo**
from pycaret.datasets import get_data
data = get_data('iris')

iris 数据集中的样本行

👉初始化设置

**# initialize setup**
from pycaret.classification import *
s = setup(data, target = 'species', session_id = 123)

每当在 PyCaret 中初始化setup函数时,它都会分析数据集并推断所有输入要素的数据类型。在这种情况下,您可以看到所有四个特征( sepal_length、sepal_width、petal_length 和 petal_width )都被正确地识别为数字数据类型。您可以按 enter 键继续。

设置的输出—为显示而截断

对于 PyCaret 中的所有模块来说,setup函数是在 PyCaret 中开始任何机器学习实验的第一个也是唯一一个强制步骤。除了默认执行一些基本的处理任务,PyCaret 还提供了一系列预处理功能,如缩放和变换特征工程特征选择,以及几个关键的数据准备步骤,如一次热编码缺失值插补过采样/欠采样等。要了解 PyCaret 中所有预处理功能的更多信息,您可以查看这个链接

https://pycaret.org/preprocessing/

👉比较模型

这是我们在 PyCaret 中推荐的 any 监督实验工作流程的第一步。此函数使用默认超参数训练模型库中所有可用的模型,并使用交叉验证评估性能指标。

该函数的输出是一个表格,显示所有模型的平均交叉验证分数。可使用fold参数定义折叠次数(默认= 10 次折叠)。该表按照选择的度量标准排序(从最高到最低),该度量标准可以使用sort参数定义(默认=‘Accuracy’)。

best = compare_models(n_select = 15)
compare_model_results = pull()

n_select设置功能中的参数控制已训练模型的返回。在本例中,我将它设置为 15,这意味着以列表的形式返回前 15 个模型。第二行的pull函数将compare_models的输出存储为pd.DataFrame

compare_models 的输出

len(best)
>>> 15print(best[:5])

打印输出(最佳[:5])

👉格拉迪欧

现在我们已经完成了建模过程,让我们使用 Gradio 创建一个简单的 UI 来与我们的模型进行交互。我将分两部分来做,首先,我将创建一个使用 PyCaret 的predict_model功能来生成和返回预测的函数,第二部分将把该函数输入 Gradio 并设计一个简单的交互输入表单。

第一部分—创建内部函数

代码的前两行获取输入要素并将其转换为 pandas 数据帧。第 7 行创建了一个显示在compare_models输出中的模型名称的唯一列表(这将在 UI 中用作下拉列表)。第 8 行根据列表的索引值(将通过 UI 传入)选择最佳模型,第 9 行使用 PyCaret 的predict_model功能对数据集进行评分。

https://gist . github . com/moe zali 1/2a 383489 a 08757 df 93572676d 20635 e 0

第二部分——用 Gradio 创建 UI

下面代码中的第 3 行为模型名称创建了一个下拉列表,第 4–7 行为每个输入特性创建了一个滑块,我将默认值设置为每个特性的平均值。第 9 行启动一个 UI(在笔记本和您的本地主机上,因此您可以在浏览器中查看它)。

https://gist . github . com/moe zali 1/a 1d 83 FB 61 e 0 ce 14 adcf 4 dffa 784 b 1643

运行 Gradio 界面的输出

您可以在这里看到这个快速视频,了解无需编写数百行代码或开发成熟的前端,与管道交互和查询模型是多么容易。

使用 PyCaret 和 Gradio 增强您的机器学习实验

我希望你会喜欢 PyCaret 和 Gradio 的易用性和简单性。在不到 25 行代码和几分钟的实验中,我使用 PyCaret 训练和评估了多个模型,并开发了一个轻量级 UI 来与笔记本中的模型进行交互。

即将推出!

下周我将写一篇关于使用 PyCaret 异常检测模块对时间序列数据进行无监督异常检测的教程。请关注我的媒体LinkedInTwitter 以获取更多更新。

使用 Python 中的这个轻量级工作流自动化库,您可以实现的目标是无限的。如果你觉得这很有用,请不要忘记给我们 GitHub 库上的⭐️。

要了解更多关于 PyCaret 的信息,请关注我们的 LinkedIn 和 Youtube。

加入我们的休闲频道。此处邀请链接

您可能还对以下内容感兴趣:

使用 PyCaret 2.0
在 Power BI 中构建您自己的 AutoML 使用 Docker
在 Azure 上部署机器学习管道在 Google Kubernetes 引擎上部署机器学习管道
在 AWS Fargate 上部署机器学习管道
构建和部署您的第一个机器学习 web 应用
使用 AWS Fargate 无服务器
构建和部署机器

重要链接

文档
博客
GitHub
stack overflow
安装 PyCaret 笔记本教程 投稿于 PyCaret

想了解某个特定模块?

单击下面的链接查看文档和工作示例。

分类 回归 聚类
异常检测
自然语言处理 关联规则挖掘

加速您的编辑速度

原文:https://towardsdatascience.com/supercharge-your-vim-skills-f5bb4fe33036?source=collection_archive---------24-----------------------

快速编辑文件的 8 个 Vim 技巧。

(图片由作者提供)

Vim 是一个文本编辑器,在一个熟练的用户手中,可以实现接近思维速度的极快编辑——比传统文本编辑器通常可以实现的速度快得多。

对于我们在计算机上做的每一件事,在我们打算执行一个动作和观察到这个动作完成之间有一个时间延迟。编辑文本只是需要时间,如果这种时间延迟太长,就会妨碍我们的注意力。为了解决这个问题,学习一些花哨的 Vim 操作可以更快地将我们的编辑从大脑印到屏幕上。

我们来看一个编辑例子。

url = "https://www.google.com"

假设我们想改变我们的 URL 来显示localhost

在传统的文本编辑器中,我们可能会做一些事情,比如将光标拖到引号括起来的 URL 上,然后开始键入新的 URL。将我们的手移到鼠标上,精确地高亮显示引号括起来的部分(菲特定律告诉我们,这是一件很难快速完成的事情,因为它是如此精确的移动),然后将我们的手移回到键盘上重新开始键入。

在记事本中更改 URL。将光标准确地放在引号之间是很困难的,我需要在快结束时放慢速度以获得精确度。(图片由作者提供)

在 Vim 中,我们可以将光标移动到引号内的任何地方,键入ci”(这将删除引号内的所有内容并进入插入模式),然后立即开始键入我们的新 URL。

在 Vim 中更改 URL。一旦我把光标放在引号之间的任何地方,我就盲目地发出命令并开始输入。(图片由作者提供)

请注意,与使用传统的文本编辑器完成这项任务相比,Vim 节省了我们大量的时间。在传统的文本编辑器中,我们浪费了大量的时间在键盘和鼠标之间转换我们的手——Vim 保持我们的手在键盘上的风格减少了一些延迟,希望我们在忘记我们正在看什么之前,可以在编辑器中打印更多的大脑转储。

既然您已经看到了 Vim 如何加快编辑速度的实际例子,那么我将向您提供我的最有用的技巧,让您充分利用 Vim 的生产力。

1。开始学习基础知识。

如果您是 Vim 的新手,或者可以重新熟悉一些基础知识,可以在命令行上运行vimtutor来开始。

(图片由作者提供)

2.最好退出插入模式

您可以使用Ctrl-C退出插入模式。escape 键也可以做同样的事情,但是为什么要做那么多的 reaching 呢?

3.升级 vimrc

文件~/.vimrc存储了我们每次打开 Vim 时的配置设置。

这些是一些明智的设置,大多数人都会从启用这些设置中受益。

" Enable mouse usage
set mouse=a" Turn on line numbers
set number" Enable syntax highlighting
syntax on

这些是我个人使用的一些快捷方式设置,但对你来说是有用的例子,让你看看如何制作自己的快捷方式添加到~/.vimrc中。

" Map Ctrl-C, Ctrl-C -> force quit
nmap <C-C><C-C> :q!" Map w, w -> force write
nmap ww :w!" Map Ctrl-W, Ctrl-W -> force write and quit
nmap <C-W><C-W> :wq!

当你感觉到你喜欢什么的时候调整这些设置,并把它们推送到 Github repo。由于 Vim 无处不在,并且几乎在任何 Linux 服务器中都作为一个选项存在,所以您可以将您的设置克隆到您正在使用的任何新机器上,并在相同的熟悉的文本编辑环境中开始。

3.四处跳跃

只用箭头键滚动一个长文件可能会很乏味。学会这些命令,你就不用花那么多时间去滚动了。

在正常模式下:

gg —跳转到文件的顶部

G —跳到文件的底部

<line-num>G —跳到<行号>,例如 7G 跳到 7 行

从命令行:

vim <filename> +<line-num> —打开文件,跳转到<行号>

4.猛拉(复制)、删除(剪切)和粘贴

需要记住的是:猛拉命令包含字母y,删除命令包含字母d,粘贴命令包含字母d

我们将不得不使用视觉模式(我们可以在正常模式下使用vShift-V进入)来选择我们想要编辑的文本。文本在可视模式下高亮显示:

y —猛拉

d —删除

然后我们将回到正常模式,我们可以键入p进行粘贴。

一些其他有用的正常模式命令:

yy —猛拉当前行

dd —删除并拉当前行

p —粘贴在光标或行后

P —粘贴在光标或行之前

5.撤消和重做

每个人都会犯错。

在正常模式下,用u撤销编辑,用Ctrl-R重做编辑。

6.搜索

要在当前文件中搜索字符串,请在正常模式下键入/<SEARCH_TERM>。你甚至可以在<SEARCH_TERM>中使用 regex。

按回车键,光标将跳转到第一次出现的查询。

要循环浏览所有事件,键入n前进,键入N后退。

7.复合命令

在文章的最开始,我们演示了一个复合命令。复合命令可能非常强大,一旦你把它们记下来,你将会以令人难以置信的精确度进行编辑。

要理解 Vim 中的复合命令,您需要一些上下文:

  • 动作按动词分类,如改变删除
  • 动作可以有修饰词,如 in 和 around。
  • 文本按单词、行、句子和段落分类。

这有助于一些非常酷和方便的复合命令——可组合和容易重复的命令。

例如,本文开头使用的复合命令是ci"(“引号中的变化”),它删除了引号中的所有内容,并将我们置于插入模式。

c告诉 Vim 我们想要的动作——change——当命令完成时,我们将进入插入模式。

i"告诉 Vim 我们想要的动作修饰符——在引号中——它将在一对匹配的引号中执行我们想要的动作,并保持引号不变。

一旦你尝试了几个例子,你会很直观地发现,所以这里有一些例子供你参考。

在正常模式下:

cip(“段落变更”)—删除光标所在的段落,进入插入模式

ciw —删除光标所在的单词,进入插入模式

cw —删除光标上和光标后的单词,进入插入模式

diw(“删除单词”)—删除光标所在的单词

dis —删除光标所在的句子

ctX(“更改为 X”)—删除下一个“X”并进入插入模式

dtZ —删除“Z”的下一次出现

da)(“删除括号”)—删除括号内的文本

ci] —删除括号中的文本并进入插入模式

8.重复上一次编辑

所有编辑在您进入插入模式时开始,在您切换回正常模式时结束。无论是手动启动编辑,还是复合命令为您完成编辑,这些离散编辑都是可重复的。

只需在正常模式下键入.即可重复上一次编辑。

结论

Vim 可以做很多事情来加速我们的文本编辑。还有很多我没有提到的。

所以,走出去,开始使用 Vim 来编辑您的文件吧!唯一的方法是练习并坚持使用 Vim,直到命令成为第二天性。想想你将来要编辑的所有文件。现在想想你将来编辑这些文件可以节省多少时间。

(图片由作者提供)

请在评论中告诉我一些你最喜欢的 Vim 技巧和窍门!很期待听听大家的想法。

用 Numba 增压 NumPy

原文:https://towardsdatascience.com/supercharging-numpy-with-numba-77ed5b169240?source=collection_archive---------12-----------------------

以 C/FORTRAN 速度运行循环/数字代码

介绍

对于外行来说,Numba 是一个开源的 JIT 编译器,它使用 LLVM 编译器 库将 Python/NumPy 代码的子集翻译成优化的机器代码。

简而言之,Numba 使 Python/NumPy 代码运行得更快。它通过将 Python 代码编译成本机代码来实现这一点。

在深入 Numba 细节之前,让我们先了解 NumPy 有什么问题,以及 Numba 是如何解决这些问题的。

  1. NumPy 不并行运行。另一方面,Numba 充分利用了计算机的并行执行能力。
  2. NumPy 函数不会使用多个 CPU 内核,更不用说 GPU 了。
  3. 你会变得依赖 NumPy 函数,因为很难编写最佳的自定义 NumPy ufuncs(通用函数)。另一种选择是用原生 Python 编写它们,但是用 Python 循环遍历单个数组元素非常慢。

什么时候用 Numba?

如果你的代码是面向数字的,使用 NumPy,并且有很多循环。

Numba 怎么用?

  1. 添加 decorators 来指导 Numba JIT 编译你的函数
  2. 在 Numba 需要的地方添加带注释的类型
  3. 用支持的函数替换不支持的 NumPy 函数

Numba 怎么安装?

conda install numba # anaconda
pip install numba  # pip

Numba 修饰函数是如何工作的?

第一步
第一次调用时,Numba 对函数进行 JIT 编译,并进行类型推断

第二步
Numba 在推断参数类型后缓存编译好的机器码

步骤 3
在后续的函数调用中,Numba 使用缓存的版本

Numba 是如何工作的?

来源

让我们暂时停止理论,转到代码上来。

示例 1: @jit、nopython 和并行模式

在这个例子中,我们计算一个数组的对角线元素的和,并将其添加到数组中。

下面的代码包含 4 个等价的函数:

*trace_normal*:原生 Python 实现
*pure_numpy_trace*:trace 的纯 NumPy 实现
*trace_numba*:nopython 模式下的 Numba JIT 实现
*trace_numba_parallel* : NUMBA nopython +并行模式

代码片段中使用的 Numba 概念

  1. nopython 模式 【推荐和最佳实践模式】
    在 nopython 模式下,修饰函数将完全在不涉及 python 解释器的情况下运行。为此,必须用 Numba 支持的数据结构/类型替换原生 python 对象。
    使用@njit@jit(nopython=True)decorator 来 Numba JIT 编译你的函数
  2. 对象模式在对象模式下,Numba 识别出只有 nopython 操作的循环,并编译成机器码。剩下的代码将使用 Python 解释器运行。使用@jit调用对象模型编译
  3. 并行运行代码 通过在@njit@jit装饰器中添加parallel=True来调用。Numba 允许您通过使用prange the the 关键字显式地并行运行代码。并行运行时,Numba 会自动优化您的代码。
    这些优化可以通过使用numba_func.paralllel_diagnostics(level=4) 级别来查看,级别是指细节的级别。1 代表最小值,4 代表最大值。

我用两种数组大小运行了上面的代码,100100 和 10001000。

运行时间

绿色阴影单元是最快的实现方式。

对于大小为 100*100 的数组,Numba(nopython + parallel)花费的时间最长。这是因为并行设置任务是有开销的。对于较大的阵列,相同的实现速度最快。

对于大小为 1000*1000 的数组,Numba(nopython)比纯 NumPy 实现花费更多的时间。在某些情况下,NumPy 实现本身是最佳的。在这些情况下,Numba nopython 模式会比较慢,因为它只是增加了额外的开销。

总而言之,在某些情况下,NumPy 的实现可能比 Numba 更快,但在大多数情况下,Numba 会让您的代码运行得更快。

示例 2

在下一个示例中,我将介绍 numba 的@vectorize/@guvectorize decorator,并将它的性能与@njit和原生 numpy 实现进行比较。

@vectorize decorator 对于优化 numpy 数组上的元素操作特别有用。Numba 可以将一个纯 Python 函数编译成一个 ufunc,它对 NumPy 数组的操作和用 c 编写的传统 u func 一样快。

@guvectorize处理任意数量的输入数组元素,并获取和返回不同维度的数组。

vectorize()函数相反,guvectorize()函数不返回结果值:它们将结果值作为数组参数,该参数必须由函数填充。

如果提供了输入类型签名,vectors将创建一个 ufunc(通用函数),否则创建一个 dufunc(动态通用函数)。

@vectorise/@guvectorise修饰的函数可以进行归约、累加和广播操作。

绿色单元是最快的实现方式

运行时间

示例 3

我正在扩展示例 2,以便在 gpu 上运行矢量化/guvectorize。

在第一个截图中,我使用了示例 2 中的@vectorize和附加属性target='cuda'。这将导致以下三个问题

错误 1:
输入数组在 CPU 上,而代码要在 gpu 上运行。这不会抛出任何错误,但 cpu - > gpu - > cpu 数据传输会使代码运行速度变慢。

错误 2:
Numba 修饰函数需要传递一个显式的空输出数组

错误三:
我正在做的数组只有 1000 * 1000,只有 2 次运算。GPU 非常适合较大的阵列或较重的操作。

坚持 CPU,直到你的运行时间保持在 1 ms 以下。

这是在 cuda 上运行@vectorize的正确实现

CPU 和 GPU 的比较是不公平的,因为我使用 cupy 作为 Numba cuda 实现的基准。

对于较小的阵列,cupy 更快,但是对于较大的阵列,cuda 功能更快。

运行时间

进一步阅读

  1. Numba 也支持 cupy/cuda,但是支持的函数集比 numpy 小。
  2. @stencil:定位方式操作

词汇表

  1. JIT:在执行时编译一个函数。
  2. 编译器: 将高级编程语言代码(C/C++)转换为机器专用代码。
  3. 类型推断:Numba 确定正在编译的函数内所有值的专用类型的过程。
  4. AOT —提前
    函数的编译在代码执行产生磁盘上的二进制对象之前单独发生。
  5. 循环 Jitting
    运行在对象模式下的函数的子集可以被优化,如果该子集包含只有 nopython 支持的操作的循环。
    该子集在 nopython 模式下自动编译,可以提供显著的性能提升。
  6. 反射no python 模式的编译不支持 Python 对象。当一个 nopython 函数用 python 对象号传递给 Numba 时,将其转换成 Numba 对象。当代码转换回 Python 解释器时,Numba 将 Numba 对象转换回 Python 对象。
    这样做是为了确保 Python/Numba 之间的语义匹配。这个过程称为反射,对所有原生 Python 数据结构都是如此。
  7. 通用函数(ufunc) 通用函数(或简称 uf unc)是一个以逐个元素的方式对**ndarrays**进行操作的函数,支持数组广播、类型转换和其他几个标准特性。

摘要

Numba 可以增强基于 NumPy 的操作,并以最小的代码变化提供显著的速度。它通过 gu vector se/vector se/njit 支持大量的 NumPy 操作。Numba 也支持基于 gpu 的操作,但与基于 cpu 的操作相比,它要小得多。

特级断续浓缩咖啡

原文:https://towardsdatascience.com/superfine-staccato-espresso-46dca7316222?source=collection_archive---------8-----------------------

咖啡数据科学

向月亮射击

意式浓缩咖啡开启了一个充满可能性的世界。分层喷射能够研磨得更细,而不会产生大的沟流。我想把这个概念发挥到极致,并在利基零上设置为 0。

最初的断奏是筛过的咖啡,然后分层。我开始在利基市场上设置 8 到 14 之间的研磨值。然后我用了两个筛网:400 微米和 500 微米。然后这些被适当地排序:

底部:<400um (~40% of the grounds)

Middle: >500 微米(约占地面的 30%)

顶部:介于 400 微米和 500 微米之间(约占地面的 30%)

所有图片由作者提供

为了达到超细,我使用了 200 微米和 400 微米的屏幕。洞的大小差别相当大。筛孔的面积是直径的平方函数。因此,200 微米屏幕的孔只有 400 微米屏幕的 1/4 大小,这使它的难度达到了一个新的水平。

左图:搅拌器原型,右图:勺子

搅拌器加快了 400 微米筛的研磨速度,但这对 200 微米筛没有太大帮助。让粉末通过 200 微米筛的唯一方法是用勺子或抹刀将它们推过。筛选 400 微米的筛网需要大约 4 分钟,使用勺子筛选 200 微米的筛网需要 15 分钟。

我喜欢克鲁夫筛,但需要更多关注的是小范围。筛子的厚度为 200 微米,所以当直径达到 200 微米时,通过筛子的距离比更大的筛子大得多。

然后我分层使用<200 微米在底部,>400 微米在中间,200 微米和 400 微米之间在顶部。我不得不非常轻地夯实,用天平称只有 200 克或 300 克。然后我就用了很长时间的预输液来减少通灵的机会。

击球后冰球的倒置视图

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。

最终得分 是评分卡上 7 个指标(尖锐、浓郁、糖浆、甜味、酸味、苦味和余味)的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

用折射仪测量总溶解固体量(TDS),这个数字结合弹丸的输出重量和咖啡的输入重量用来确定提取到杯中的咖啡的百分比,称为提取率(EY)** 。**

设备/技术

浓缩咖啡机:金特快

咖啡研磨机:小生零

咖啡:家庭烘焙咖啡,中杯(第一口+ 1 分钟)

镜头准备:筛选断奏

输液:压力脉动

过滤篮 : 20g VST

其他设备:Atago TDS 计、 Acaia Pyxis

看着视频

我会记录我所有的镜头,所以让我们来看看镜头是什么样子的:

我用了更长时间的预灌注来进行超细注射。主要区别在于预输注的开始。超细的好像一开始就把油挤出来了。看起来没什么意思。

投篮表现

我拉了两个正常的断奏镜头和两个超细镜头。在味道方面,超细镜头的味道评分相似,但味道不同。提取了不同的东西。我不认为它一定更好,但肯定是不同的。

****

在提取方面,他们也有相似的提取。仅仅因为你走得更细并不意味着你的提取上升,但是我也能够避免主要的通灵。

拍摄时间非常不同。我考虑到最后一针的预输注时间较长,因为它的流速较慢。我的目标是拍出最好的照片。

TCF 是时候盖上过滤器了

总的来说,我真的很高兴我花时间拍了这些照片。我知道很多人只想在早上喝咖啡,但我想获得一些知识。我想把它推到极限。当然,这个超精细的断奏镜头并不实用,但很有趣。

如果你愿意,可以在推特、 YouTubeInstagram 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以关注我在订阅

我的进一步阅读:

我未来的书

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影飞溅页面

使用图像处理测量咖啡研磨颗粒分布

改进浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维护

咖啡评论和想法

咖啡实验

强力胶——血统、数据可观察性和数据管道之旅

原文:https://towardsdatascience.com/superglue-journey-of-lineage-data-observability-data-pipelines-23ffb2990b30?source=collection_archive---------13-----------------------

使用自助式数据平台工具实现数据民主化

图片来自 shutterstock

数据在商业决策、人工智能/人工智能、产品进化等方面发挥着至关重要的作用。及时性、准确性和可靠性是每个组织的关键基础数据要求。对于数据驱动型组织,让数据工程师、分析师和数据科学家等用户能够轻松地发现、探索、处理、管理和使用数据非常重要。这需要在为数据用户构建数据民主化平台工具方面进行大量投资。

我们在 Intuit 的数据民主化之旅始于两个目标:

1)减少用户在构建数据管道上花费的时间(构建时间)

2)减少用户花费在检测/解决数据问题上的时间(调试时间)

我们在 Intuit 建立了强力胶来帮助用户建立、管理和监控数据管道。我将在这篇博客中介绍强力胶的四个核心方面——血统、可观察性、管道和个性化。如果你是数据领导者、架构师或平台工程师,这篇博客将帮助你学习大规模构建谱系的模式,以及如何借助谱系监控数据和管道。在我们深入探讨之前,让我提供一些背景知识。

数 Pb 的多样化数据、成千上万的工作和多层依赖关系

Intuit 从其产品、应用程序和第三方收集了数 Pb 的各种数据。成千上万的 Hive、Spark 和大规模并行处理(MPP)作业每天都使用这些数据集来生成数百份报告,提供运营和业务见解。类似地,ML 工作流使用这些数据集进行特征工程和模型训练。

使用由多个团队拥有和管理的框架,通过多个摄取、处理和分析层生成见解或功能。例如,一个关键报告依赖于来自 18 个不同数据源的数据,这些数据经过 20 多级处理。

鉴于这种规模和复杂性,当存在度量不准确时(如下所示),确定根本原因变得极具挑战性。

用户会花费几个小时,有时甚至几天去寻找问题的根源。此外,导致此类数据问题的原因可能有很多。

当报告问题时,您从哪里开始寻找故障?您看到的是数百个用户拥有的数千个正在运行的作业。这些工作使用成千上万的表,这些表通过多个团队拥有的许多框架进行处理。这就是 Superglue 的自助式调试体验(构建在沿袭和可观察性的基础上)发挥作用的地方,它有助于检测数据问题的根本原因。

血统

为了找到上游数据管道中可能出现的故障的根本原因,我们必须首先了解端到端的沿袭。企业调度程序为我们提供了用户在调度作业时指定的依赖关系。有趣的是,90%的分析作业是在没有任何作业依赖性的情况下安排的。因此,任何上游延迟或故障都不会阻止下游作业运行;这些工作仍然继续进行,并导致了操作问题、指标不一致和数据漏洞。

我们确定需要在 Git 中基于源代码为运行 Hive、Spark 和 MPP 工作负载的数据处理和数据移动框架构建沿袭跟踪。我们使用开源和定制的 SQL 解析器来导出作业、脚本和输入/输出表之间的关系。对 BI 报告和自主开发的数据移动框架进行类似的解析,以找到相关的表。

使用这些元数据,我们“粘合”了端到端的沿袭,其中包括三个关键的实体类型:作业、表和报告(也称为仪表板)。用户可以搜索这些实体并进入他们的沿袭视图。

用户可以搜索表、作业或报告

以下是从搜索页面中选择的作业的表沿袭示例。作业用椭圆形表示,表用矩形表示。作业的颜色表示作业是失败(红色)、成功完成(绿色)还是处于活动状态(浅绿色)。

表谱系

这是基于企业调度程序中用户指定的作业相关性的同一作业的调度程序沿袭。

调度程序沿袭

这是一个报告的谱系示例,用圆圈表示。

报告沿袭

依赖推荐

有了基于源代码的表沿袭和基于企业调度器中指定的依赖关系的作业沿袭,我们就可以了解哪些表提供给哪些作业,哪些表由哪些作业生成,以及哪些作业依赖于哪些其他作业。这帮助我们在 Superglue 中将依赖推荐构建为一个特性。使用此功能,我们能够查明缺少的作业依赖关系。这就像说— “这个作业依赖于这两个表,这两个表是从另外两个作业创建的,但是你没有将另外两个作业指定为依赖项。请将它们作为依赖项添加到计划程序中。

血统 API

除了向后沿袭,我们还提供了向前沿袭。前向沿袭有助于需要评估源和模式更改对下游管道和/或报表的影响的用例。沿袭 API 使得工程自动化能够检测这些变化的影响。

当我们将数以千计的分析管道、表格和报告迁移到公共云中时,沿袭 API 和数据质量框架也发挥了关键作用。使用前向沿袭 API,当原始源数据在云中就绪时,我们能够检测哪些管道和报告可以被测试。类似地,当我们在迁移期间在云报告中发现度量问题时,我们可以使用向后沿袭 API 来识别原始表中数据问题的来源。

数据可观察性

我们的下一步是为用户构建调试体验,目标是将平均检测时间和平均恢复数据时间从几小时减少到几分钟(调试时间指标)。以沿袭为基础,我们覆盖了以下特性以实现数据的可观察性

  • 作业执行统计和日志:与调度程序集成以捕获开始时间、结束时间、运行时间、执行尝试、失败、日志和作业依赖性
  • Table stats:与定制数据接收框架和大规模并行处理(MPP)平台集成,以捕获行数和表大小。在某些情况下,我们能够利用 MPP 系统表来获得丰富的表/列分析统计数据。
  • 报告统计:与商业智能(BI)工具集成,以捕获报告 SQL、执行统计和刷新日志
  • 变更跟踪细节:与 Git 集成以捕获对 Hive、Spark 和 MPP 作业的变更

启用这些功能可以作为沿袭和调试的单一平台。下面是一个作业详细信息页面的示例,当单击沿袭画布上的作业时会出现该页面。

作业统计页面

类似的详细信息/视图也可用于表格和报告。

异常现象

有了作业统计数据和表统计数据,我们就能够添加异常检测,主动检测异常作业运行(如下例)和表中的数据变化。我们还引入了针对异常的警报订阅/通知,以及针对失败和延迟运行的警报(更多详细信息请参见下面的个性化部分)。

工作 ETA 服务

我们引入的另一个重要功能是 ETA 服务。有了沿袭和作业执行统计数据(开始时间、结束时间、持续时间),它使我们能够主动估计 SLA 绑定作业的预计到达时间。我们将这个特性称为 ETA 服务,它与 Slack 集成在一起,为高度关键的管道提供频繁的 ETA(如下例)。

数据管道

改进了调试时间指标后,我们的下一个目标是将用户构建和测试管道的时间从几小时减少到几分钟(构建时间指标)。我们实现数据管道的目标是多方面的:

  • 构建简化的用户体验
  • 提供现成的沿袭和数据可观察性
  • 通过 QuickETL 在 Spark 运行时支持数据处理,quick ETL 是一个自行开发的配置驱动框架,用于定义和执行 Spark ETL 工作流。它提供了依赖关系链、查询级别度量、监控,以及在工作流的每个步骤之前和之后应用断路器的能力。丰富的管道定义语法以快速、一致的方式定义转换逻辑和依赖关系。
  • 从数据分析师手中抽象出数据工程的复杂性。这包括设置沙盒环境以支持管道可测试性。
  • 支持从数据湖到 MPP 平台的数据移动,MPP 平台用作 BI 的数据服务层
  • 与 BI 工具集成,使报告刷新成为管道的一部分
  • 通过与企业调度程序集成,改善用户的调度和编排体验

这使用户能够构建数据管道来运行 Hive & Spark 数据处理作业,将数据移动到 MPP 平台,刷新 BI 报告,以及在沙盒环境中测试这些管道,并在调度程序上对它们进行调度。一旦管道建立并安排好,用户就可以使用 Superglue 的数据观察能力来管理他们的日常数据操作。

以下是管道开发流程的一些快照:

以上流水线步骤用于展示一个例子。在现实生活中,您可以想象在一个管道中有多种类型的数据处理、数据移动和/或报告刷新步骤。下图显示了创建的管道,其中包含编辑管道、重新运行管道、查看执行日志和查看沿袭的控件。

我的管道页面

个性化

启用管道以及沿袭和可观察性将 Superglue 转变为一个平台工具,用于构建、管理和监控分析管道。

有 250 多名用户使用不同的旅行地图和角色,我们提供个性化的体验变得非常重要。事实上,个性化是由我们用户群的输入驱动的。我们想让用户轻松登陆强力胶,从对他们来说最重要的事情开始他们的旅程。下面是我们介绍的几个功能

  • 已启用 SSO 身份验证
  • 添加了个性化视图—我的报告、我的管道、我的工作和我的[提醒]订阅
  • 使用来自人力资源系统的数据启用组织层次结构,并引入组织级工件和指标
  • 支持管道共享性和可转移性
  • 添加了针对故障、延迟和异常的简易警报订阅(包括订阅他人拥有的资产)
  • 在产品中添加了视频教程、常见问题解答和入职页面的自助功能

以下是“我的报告”登录页面的快照示例

我的报告页面

开放源码

Superglue 的一部分包括 SQL 解析器、表格沿袭和 UI/搜索功能,在 https://github.com/intuit/superglue开源。它会给你一个良好的开端去衍生、坚持和视觉化血统。如果你对强力胶感兴趣,请查看我们的投稿指南

下一步是什么

在过去的几年里,我们一直在研究强力胶,我们在 Intuit 的业务部门和职能部门中实现数据民主化的旅程仍在继续。我们正致力于通过增加可测试性、可调试性和支持多处理运行时的特性来为高级用户提供强力胶。

在 Intuit Data Engineering leadership 的支持下,Anand Elluru、Shradha Ambekar、Sooji Son、周扬、Rama Arvabhumi、Veena Bitra 和 Sunil Goplani 等团队实现了这一美妙的旅程。

超人人工智能与民主和政府的未来

原文:https://towardsdatascience.com/superhuman-ai-and-the-future-of-democracy-and-government-5e57d3e53d42?source=collection_archive---------22-----------------------

播客

本·加芬克尔探索了我们能够和不能够预测人类未来的事情

要选择章节,请访问 Youtube 视频这里

编者按:这一集是我们关于数据科学和机器学习新兴问题的播客系列的一部分,由 Jeremie Harris 主持。除了主持播客,Jeremie 还帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:

苹果 | 谷歌 | SPOTIFY | 其他

随着我们继续开发越来越复杂的人工智能系统,越来越多的经济学家、技术专家和未来学家一直在试图预测所有这些进展的可能终点。人类会无关紧要吗?我们会把所有的决定——从我们空闲时间想做什么,到我们如何治理社会——都交给机器吗?高能力和高度通用的人工智能系统的出现对民主和治理的未来意味着什么?

这些问题是不可能完全直接回答的,但把眼光放长远一点人类技术发展史,或许可以得到一些提示。这是我的客人本·加芬克尔在他关于人工智能未来的研究中采用的策略。本是一名物理学家和数学家,目前在牛津人类未来研究所从事新兴技术风险预测的研究。

除了研究预测人工智能等技术的未来影响,本还花时间探索人工智能风险的一些经典论点,其中许多他不同意。因为我们播客上有很多认真对待这些风险的嘉宾,我认为也有必要和本谈谈他的观点,我很高兴我这样做了。

以下是我们谈话中我最喜欢的一些带回家的东西:

  • 不出所料,预测未来很难。但是,当谈到人工智能及其对经济可能产生的影响时,让它变得特别困难的一件事是,人工智能似乎可能挑战我们标准经济模型中的许多假设。例如,市场是由赚了钱并打算把钱花在产品上的人组成的这一观点,可能无法推广到大多数买卖决策都由机器做出的世界。同样,我们目前假设劳动力(人们为建造物品和提供服务而投入的工作)和资本(他们建造或用于建造其他物品的工具、设备和物品)之间有非常明显的区别。目前还不清楚哪种经济直觉会推广到这样一个世界:人工智能系统被视为资本,但也在做我们的大部分工作。
  • 经济学家、历史学家和未来学家之间的一个活跃辩论是,全球人类经济的增长和发展是平稳渐进的,还是一步一个脚印的?例如,一些人指出工业革命、新石器时代革命和其他类似事件是经济发展离散而突然增长的时刻,而另一些人则认为这些只是环境持续发展水平最终变得引人注目的时刻。有趣的是,人们对人类经济史相对平滑或尖锐的看法,在他们想象向人工智能经济过渡的方式中起着重要作用。如果你通常认为经济增长一直是持续和渐进的,那么你就不太可能认为人工智能会在短时间内给我们的日常生活带来不连续的变革性飞跃。
  • 本对人工智能风险的某些“经典”论点持怀疑态度。虽然没有完全否定它们,但他指出,其中许多是不必要的抽象。他还提出,越来越多像 OpenAI 的 GPT-3 这样的系统的出现给了我们机会,让我们看到具体的和有点通用的人工智能系统在实践中的行为,他认为,结果表明,对来自递归自我改进系统的人工智能风险的担忧可能没有特别坚实的基础。在这里很难用要点的形式来解释这些论点,所以如果你对这方面感兴趣,我真的推荐你听这一集!

你可以在推特上关注本(尽管他还没有发推特:P)或者在推特上关注我

播客中引用的链接:

  • 本在人类未来研究所网站上的页面。

章节:

  • 0:00 介绍
  • 1:21 本的背景
  • 3:14 人工智能的风险
  • 钱的价值
  • 13:38 大赦国际作为一种参与现象
  • 16:01 人工智能与 GDP
  • 生命的进化
  • 30:36 人工智能风险论证
  • 45:23 构建这些系统
  • 51:29 人类自我完善的反馈
  • 观念的转变
  • 1:07:38 总结

请查看以下文字记录:

杰瑞米(00:00:00):
嘿,大家好,我是杰瑞米。欢迎回到迈向数据科学播客。我对今天的这一集感到非常兴奋,因为我们将讨论许多与人工智能有关的长期的、改革的和半未来的话题。人工智能技术将塑造未来的治理方式。人类会变得与经济无关吗?我们有多少日常决策将被转移到机器上?也许最重要的是,高能力和高度通用的人工智能系统的出现对民主和治理本身的未来意味着什么?这些问题不可能有任何确定的答案,但是从人类技术发展的历史中寻找一些线索是可能的。

Jeremie (00:00:41):
这正是我的嘉宾 Ben Garfinkel 在研究人工智能的未来时所采用的策略。现在,本是一名多学科的研究人员,致力于预测先进技术带来的风险,包括牛津大学人类未来研究所的人工智能。本也花了很多时间探索人工智能风险的一些经典论点,其中许多你会在播客中遇到。我们邀请了很多嘉宾来详细讨论和探讨这些问题,其中很多他都不同意。我们将探究他的不同意见,为什么他会有这些不同意见,以及他认为人工智能风险的论点在哪里有点站不住脚。我真的很喜欢这次谈话。我希望你也是。本,非常感谢你参加我的播客。

本(00:01:19):
是的。非常感谢邀请我。

Jeremie (00:01:21):
你能来我真的很开心。你关注的是一大堆长期问题,其中很多都是围绕人工智能的。不过,在我们深入讨论这个话题之前,我想更好地了解一下是什么让你来到这个领域。那么你的背景是什么,你是如何发现人工智能中的长期主义的?

本(00:01:38):
是的,所以我想实际上是相当迂回的。所以在大学里,我学习物理和哲学,对物理哲学非常感兴趣,甚至考虑去读研究生,幸运的是我没有去。是的,我想通过哲学,我开始了解更多关于伦理的知识,并接触到一些关于人口伦理的观点。这种观点认为,围绕着我们应该如何在决策中重视后代,以及我们对后代的义务,存在着不同的问题。或者做对其他人至少有些用处的事情的义务有多强。后来,我对长期主义越来越感兴趣,也试图找出一些似乎有用的东西。我开始想,也许哲学和物理学并不是这样。

Ben (00:02:28):
事实上,我非常幸运,不仅仅是在这个时候,当我试图更多地研究长期或未来的主题时,我碰巧遇到了当时在耶鲁大学的教授 Allan Dafoe。他只是自己转向人工智能治理问题。我想当我还在那里读大四的时候,他就已经开始招聘研究助理了。我对这个话题很感兴趣,我读过一些关于人工智能风险的文章。例如,我开始阅读《超级智能》这本书,我并没有真正涉足这一领域,但似乎那里可能有一些重要的问题。一个机会出现了,我开始和艾伦一起工作。几年后的现在,我实际上仍在和 Allan 一起工作,我刚刚相当确信,从长远的角度来看,研究新兴技术的风险至少是一件相当好的事情。

Jeremie (00:03:14):
这实际上是一个很好的继续,我认为这是我真正想谈论的主要话题之一。这就是你花了很多时间思考人工智能的存在风险及其论据的想法。我知道你并不完全相信其中的很多。也许我们可以从这里开始,当涉及到人工智能时,人们特别是 Allan 和你所担心的存在风险的本质是什么?然后,我们也许也可以对这些论点进行反驳,但首先,风险是什么?

Ben (00:03:44):
是的,所以我认为,在考虑人工智能的长期影响的人群中,至少没有一种风险真正占主导地位。所以我会说有几个主要的,非常广泛的,有点模糊的类别。所以一类风险很快就会出现,那就是不稳定带来的风险。因此,很多人,特别是在国际安全领域的人,担心致命的自主武器系统,可能会增加国家间冲突的风险。也许是偶然的,闪光冲突或潜在的某些 AI 应用,比如说移动第二次打击能力和增加核战争的风险。或者他们担心大国竞争。他们担心的主要问题是,也许人工智能的某些东西会破坏国内或国际政治的稳定,然后可能会有战争,这将带来持久的破坏或其他一些负面的长期冲突。

Ben (00:04:43):
还有另一类关注点,比如一些特定的冲突、崩溃或战争。并且更专注于这样一种观点,即在人工智能重塑社会的过程中可能存在某种程度的偶然性。因此,你可能会认为,人们做出的关于政府和人工智能的某些决定将会产生持久的影响,进而影响后代。事实上,例如,民主有多普遍,权力分配如何,或者人们关心的其他各种事情,例如,坏的价值观在某种意义上根深蒂固。

耶雷米(00:05:23):
因为在那方面,我想那显然是一个非常复杂的地区。但是,人们想象人工智能在多大程度上改变了我们所说的民主在未来是一种有吸引力的治理模式,有哪些方式呢?

Ben (00:05:36):
就民主而言,显然存在一些投机因素,但担心民主的一个理由是民主并不真正正常。如果你纵观历史,追溯到最初的文明,这并不罕见,比如说每周都有民主元素。所以这不是完全的专制,有某种形式的机构,比如罗马元老院之类的,但在罗马,这是一个众所周知的机构。但这与我们现在的情况相去甚远,我们现在的情况就像是在许多国家几乎实行普选制,这些国家的政府反应非常迅速,而且不断地向更多的国家转移。从历史的角度来看,这是极其罕见的。即使事情不是完全的独裁或之前的事情,这是过去 100 年非常不同的事情。关于为什么这种现代形式的民主变得越来越普遍,有不同的理论。关于这一点有很多争论,因为很难进行随机对照试验。但是很多人确实指出,至少工业革命前后发生的某些经济变化是相关的。

Ben (00:06:43):
因此,人们有时会提出的一类变化是机器人,这在工业革命之前是一个非常严重的问题。有人担心,如果你给很多普通人政府的权力,或者利用[听不清 00:06:56]重新分配土地,这是更广泛的富人财富的主要形式,应该会非常具有破坏性。随着国家的工业化,土地作为一种财富变得不那么重要,也许这些土地改革问题不再是阻碍因素。你不再有土地贵族,不再有对政策的恐惧。

本(00:07:18):
还有其他一些问题,就是随着生产力的提高,劳动力的价值也提高了。这在某种模糊的意义上给了人们更多的讨价还价的权力,因为你有典型的工人,他们做什么,更多的价值。他们可能会通过威胁基本上只是拿走他们的劳动力来制造更大的威胁。或者一些组织也被认为是相关的,比如人们聚集在城市里,更容易组织起来,实际上也有成功的革命。有很多不同的因素,人们基本上认为是经济变革,这可能有助于民主的发展,或者至少有助于部分解释为什么它在今天更加普遍。

Ben (00:07:52):
所以你可能会非常广泛地关注民主的普及是否在某种程度上取决于某些物质或经济因素。这种情况只持续了 100 年。也许这是不正常的,也许如果你只是改变许多经济和技术变量,这是不成立的。这里还有一些更具体的论点。所以一个非常具体的论点是,如果人类劳动力的价值变得非常低,甚至在大多数情况下变为零,因为你可以用资本代替劳动力。因为人工智能系统可以做人们可以做的任何事情,也许当我们减少工人的权力时,如果你可以自动化执法或镇压起义,因为军事技术也可以自动化。

本(00:08:33):
这可能会让威权政府更加稳定。这意味着他们甚至不会因为害怕起义而做出让步。也许如果劳动力的价值变为零,那么在这一点上可能会变得非常严重,主要取决于谁拥有资本或谁拥有机器。也许它创造了一个系统,一个与土地改革的小问题非常相似的情况。财富并不是真正基于这些模糊的东西来划分人们的劳动,并没有真正发挥作用,很大程度上,你拥有的东西,你基本上是在收取租金。如果你回到那个系统,那可能对民主的稳定也没有好处。

本(00:09:09):
所以有一个外部视角,这是很罕见的事情。也许我们不应该指望它会持续下去,我们改变了很多。此外,还有一些内部观点的争论,可能会使专制政府更加稳定,并使人们更加担心将权力交给[听不清 00:09:24]。

Jeremie (00:09:24):
非常有趣的是,所有这些问题都是如此错综复杂,要清晰地描绘出所有这些变革发生后的未来是多么困难。当我们开始谈论民主将会发生什么,经济将会发生什么时,我脑海中不断浮现的一件事是。劳动力谈判的力量等等,是一个潜在的假设,即我们有任何一种市场结构,在某种程度上,所有的劳动都是由机器完成的。

Jeremie (00:09:57):
我想我可能会问的一个问题是,在这种情况下,金钱的价值是什么?价格发现的价值是什么?在这种情况下,价格发现是如何发生的?如果…这并不是说我们一定处于后稀缺状态,你会期望稀缺的梯度。但无论如何,我甚至不确定我在这里想表达什么思想,但看起来你有东西要扔进去。

本(00:10:23):
所以我认为这是一个非常严肃的问题。我认为我们不应该期望自己真的能够在任何细节层面上想象一个拥有非常先进的人工智能的未来,并且真的是正确的。因此,我有时使用的一个类比是,我认为在这个世界的某些方面,人工智能系统至少可以做人类可以做的所有事情。我们可以在某种程度上抽象地推理。我们确实有这些经济模型,我们有劳动力,你有资本,你可以问如果用资本代替劳动力会发生什么。甚至项目是非常抽象的观点。也许有一些理由希望这些理论足够抽象,即使我们不知道细节。仍然有一些理由认为,有足够的一般抽象,我们仍然可以用它们来推理未来。但是肯定有一个担忧,就像任何关于政府如何运作的细节。我们可能会认为政府的功能是完全错误的。

Ben (00:11:19):
我有时使用的一个类比是,让我们假设你在 1500 年,有人用非常抽象的术语向你描述互联网,就好像通信将会快得多。检索信息和学习东西会快得多。它给了你一些抽象的属性。有些东西你或许可以推理一下。

本(00:11:40):
所以你可能会想,“哦,你可能会有更少的自主权,因为人们可以更快地与他们沟通,而不是他们在海外和失去联系。或者企业可能会更大,因为这些协调成本可能会下降。”有些事情你可能会说这是真的,或者你可以说,“哦,也许人们远程工作,”你可能甚至不知道很多细节。但是如果你试着去弄清楚到底发生了什么,你可能会认为这是完全错误的。因为你根本不了解电脑到底是什么样子,也不知道人们是如何与电脑互动的。

Ben (00:12:15):
你不会得到像 Reddit 和 GameStop stock 这样的细节。所有这些问题,你不可能在任何细节层次上预见到。还有很多你可能想象不到的问题,因为你使用了不太合适的抽象概念。所以这是一种有点啰嗦的说法,我确实认为我们有一些理论和推理方法,足够抽象,我希望它们至少能支持一点。但是我认为有很多事情是我们无法预见的。很多我们不能谈论的问题。我们今天说的很多东西,从未来的角度来看,可能会变得愚蠢。

耶雷米(00:12:51):
是的,我想是的,“这一次会有所不同,”在任何时候说都是一件危险的事情。但当谈到人工智能革命的下一个阶段时,如果你想这么说的话。我知道这也是你经常使用的语言,在这种情况下似乎很合适。我确实想知道的一件事是一种几乎类似于抽象的泄漏,我们依赖抽象来定义像市场这样的东西。当我们谈论预测未来时,这是我们推理的一个非常基本的要素。市场隐含地围绕着人,因为最终价格只是个人愿意为一件东西支付的价格。我们拓宽了市场参与者的定义。

Jeremie (00:13:38):
在这里,我们进入了这样的问题,我们如何考虑一个人工智能代理?在哪一点上是社会的参与成员?在什么程度上,价格发现真的围绕着非人类系统的需求和欲望之类的东西?我想这就是我开始怀疑的地方,这是一个默认的非建设性的观点。所以对我来说,说“市场是一个糟糕的抽象概念”是没有帮助的,但是你认为这是一个严重的问题吗?

本(00:14:06):
是的,是的,我确实认为这是一个问题,我认为你指出了一个很好的、具体的问题,我们有一个非常明确的区别……目前,人与机器和软件非常不同。这很像[相声 00:14:19]经济演员与经济相关的东西[听不清 00:14:23]。公司在某种程度上是模糊的,出于某种目的[听不清 00:14:29]在某些方面类似于人。但是区别非常非常明显。即使只是在资本和劳动力之间,目前也没有任何含糊之处。

Ben (00:14:41):
但是,如果你认为未来会有非常强大、温和的人工智能系统。我们认为,也许人们与人工智能系统有着有趣的关系,他们在那里创建评估,这意味着追求他们的价值。我认为我们做出的许多区别实际上可能会变得比现在更加模糊。它们在未来变得模棱两可的方式可能会使我们依赖于清晰区分的任何理由,可能会以目前难以预见的方式失败。

耶雷米(00:15:12):
是的。预测这是一个有趣的风险,因为它确实是不可预测的,而且从根本上来说具有挑战性。这似乎也是其中的一个问题,你在你的一些关于技术历史的作品中探索了这个问题,那就是你将会看哪一个指标来讲述这个技术的进化故事。你能就此谈一点吗,你的历史观点,你觉得哪些指标有趣,为什么它们在未来可能相关或不相关?

本(00:15:36):
是的。所以我认为人们经常使用的一个指标是全球生产总值。GDP 作为一个指标很有意思,因为它要衡量的基本上是某种程度上的生产能力,比如你能生产多少东西或者你能生产多少人们看重的东西。和

耶雷米(00:16:01):
我有一个愚蠢的问题。那么什么是 GDP 呢?GDP 的实际定义是什么?

Ben (00:16:08):
因此,至少名义 GDP 是指在一个经济体中销售的所有最终产品的总价格。所以最终产品基本上是某种类似于最终结果的东西。如果你卖给某人螺丝钉,然后他们把螺丝钉卖给某人,某人用螺丝钉做吊扇之类的东西。螺丝不应该被计算在内,因为你在重复计算。如果有人买了一个吊扇,当他们买吊扇的时候也买了螺丝,他们也买了螺丝。所以它基本上意味着把一个经济体中除了中间产品之外的所有东西的销售价格加起来。

本(00:16:48):
但人们也经常想谈论实际 GDP,这与名义 GDP 不同。所以名义 GDP 就是,你把基本上所有的价格加起来。名义 GDP 的一个问题是,如果你有通货膨胀,那么你可能会因为与实际基础股票无关的原因而增加名义 GDP。所以政府决定印更多的钱,突然所有东西的价格都上涨了 1000 倍,但是你仍然有同样的东西。从名义上看,GDP 的增长并不真的非常快,但这并不是说你实际上生产了更多的东西。

耶雷米(00:17:25):
是啊。委内瑞拉做得很好。

本(00:17:27):
是的,没错。所以实际的 GDP,应该是为此而调整的。至少粗略地说,它的工作方式是,你试图定义一切相对于过去某个时间点的价格。假设你有一个经济体,唯一出售的产品是黄油,由于通货膨胀,黄油的价格上涨了 1000 倍。但是你在经济中只卖出了双倍的黄油。真实的 GDP 只会说,“哦,因为你卖的黄油量增加了两倍。你们的经济规模只增长了两倍。”经济规模的定义是,用过去的黄油价格,乘以现在存在的数量,这就是真实的 GDP。这变得非常复杂,因为随着时间的推移,人们不断推出新产品。那么,鉴于人们在 2020 年购买的大部分东西在 1700 年并不存在,你如何将 2020 年的经济与 18 世纪的经济进行比较呢?你实际上是如何进行比较的呢?人们使用各种不可靠的方法,但他们并不真正理解。

Ben (00:18:36):
但在问这个问题时,你也提到了 GDP 的一个主要问题。它意味着跟踪社会的生产能力,比如我们基本上制造了多少东西。如果你使用短期内的实际 GDP,这似乎不成问题,因为你通常不会推出那么多新产品。但随着时间的推移,这些比较实际上是如何进行的变得越来越模糊。所以非常直接的比较还是很好的。所以你仍然可以说公元前 10000 年的人均 GDP 和今天的相比。即使我不知道如何准确定义 100 个其他社会的人均 GDP,我仍然很有信心它会更低。

本(00:19:21):
从某种意义上来说,它就像一个钝器,我认为它的有用性取决于你希望你的讨论或预测有多精确。假设有人做了一个非常大胆的预测,由于自动化,人均 GDP 增长率将增加 10 倍。如果有人做出这样大胆的预测,那么在某些疯狂的未来经济中,实际 GDP 意味着什么就有点模糊了。但是,即使你看起来有点模糊,GDP 和增长率之间的差异并没有改变,增长率增加了 10 倍,这仍然足够直接了。这是一种表达主张的有用方式。

Ben (00:19:57):
这是一种啰嗦的说法,我认为 GDP 或人均 GDP 通常很好地代表了生产能力增长的速度。它对工业革命很有用,在人均 GDP 中表现得很明显。或者当一个国家似乎真的停滞不前时,比如不发达国家没有发展,人均 GDP 通常是相当平稳的。然后,当中国,例如,开始在一个真正明显的质量意义上起飞,人均国内生产总值跟踪得很好。因此,这是有用的,但它也有各种问题。除此之外,还有一些问题,人们经常想用它来代表人们的生活有多好,比如人均 GDP。

Ben (00:20:38):
但是有很多事情通常不会被考虑进去,比如医疗质量,不会直接被考虑进去,空气污染也不会被考虑进去。如果每个人都只是非常沮丧或麻醉,正在开发的麻醉的价值就真的不会显现出来。威廉·诺德豪斯的一篇经典论文表明,100 多年前,灯的质量提高,灯泡比蜡烛好得多的事实,并没有真正显现出来。因此,这是一种冗长的方式来说同样的财政问题,至少作为一个粗略的衡量标准,相当不错。但实际上并不一定与你可能对幸福和其他感兴趣的事情有所帮助。

耶雷米(00:21:15):
有趣的是,当你在最后一块上加标签时,它与幸福没有很好的关联。我想不出更好的封装一种对齐问题。基本上,问题是要拿出一个指标,说明这就是我们想要的。人类真的很坏,或者说不是我们坏。指定有意义的指标可能真的是一个困难的问题。你看股票市场,我们决定关注这个指标。有一段时间,股票市场是一个很好的衡量标准,一般来说,经济怎么样,普通人怎么样?但接下来会出现脱钩,我们最终会看到股市与普通人的生活大相径庭。无论如何,对不起。我不是有意打断你,但你刚才提到了-

本(00:22:00):
是啊。所以我应该说,作为一个小小的警告,我认为目前,GDP 实际上是一个很好的指标。如果你经常定义你关心的事情,比如预期寿命或者生活满意度。事实上,目前,这两者之间有很强的相关性。我认为你就像,什么都不知道,你落后于[听不清 00:22:17]或什么,你需要选择一个国家生活。你唯一得到的是人均 GDP。这通常会是对你有用的信息。我想我的想法更符合对齐问题,如果它在未来变得更加解耦,我不会感到惊讶。

Ben (00:22:30):
特别是,假设我们最终用资本和机器完全取代了劳动力,人们不再为工资而工作。经济增长主要是机器制造其他机器,工人并没有真正参与其中。如果经济增长 10 倍,我不会感到震惊,但一个人的生活不会增长 10 倍。

耶雷米(00:22:47):
是啊。这也很有趣,并提出了什么的问题,这又回到了价格发现,这是 GDP 的一个重要方面。有很多领域的事情变得复杂。但有趣的是,看看你在这个技术的历史探索中所做的一些工作。这些指标中有很多确实是相互关联的。在某种程度上,你测量什么并不重要,在过去的 2000 年或 20000 年里发生了一些戏剧性的事情。但是,你要衡量一下,要么是文化革命,要么是新石器革命,要么是工业革命。就好像人类这个超级有机体,地球上的所有人类都是一个优化算法,只是捆绑在某种最优或局部最优或其他什么上。我们现在正在非常陡峭地爬坡。

耶雷米(00:23:44):
你认为人工智能是它的连续体极限吗?这是自然的下一步吗?或者我们应该把它看作是一个量子飞跃,就像一个阶跃函数,事情只是质的不同?

本(00:23:56):
是的。我认为这是一个非常好的问题。我确实认为,这是一场关于如何确切解释经济增长或社会能力增长的历史的争论。或者不管你想用什么模糊的术语来描述人们在这个世界上制造东西或改变东西或完成事情的能力。实际上存在一场争论,例如,在对工业革命的不同解释之间。因此,对大约发生在 1750 年至 1850 年间的工业革命的一种解释是,在工业革命之前,英国和一些周边国家的经济增长非常停滞。然后发生了一些变化,一些有趣的转折,可能发生在工业革命的另一端,也可能是另一个世纪。因为某种原因,技术进步的速度加快了。

本(00:24:55):
人们从农业经济转向工业经济。人们开始使用非有机能源。所以不再是木材和动物肥料。现在是化石燃料和通过电力传输的能源,诸如此类。T4 研发现在在经济增长中发挥作用,而以前它并没有真正发挥作用。在过去的 100 年里,发生了一些有趣的相变。我们刚刚从一个经济体过渡到一个几乎完全不同的经济体,这个经济体的增长和变化可能会更快。

Ben (00:25:29):
现在有另一种解释,基本上是说至少在人类文明史上有一种长期趋势,增长率越来越快。这种解释认为,随着经济整体规模的增长,增长率本身,也就是增长,会不断上升。这是一个有趣的反馈循环,经济规模越来越大,增长率越来越大,这在工业革命中非常明显。只是因为这里的速度终于变得足够快,让人们注意到这一点,但实际上有一个相当一致的趋势。这并不是真正的相变。

本(00:26:12):
例如,大卫·罗德曼最近做了一些工作,他是一名经济学家,为开放慈善项目工作。他最近写了一篇报告,我想是《人类轨迹建模》,讨论或探索了这种连续视角。经济史上也有争论。所以有一个经济学家,迈克尔·克莱默,为这种平稳加速的观点辩护,很多经济史学家也这么认为。实际上,当你从一个经济体转换到另一个经济体时,会有一些奇怪的事情发生。

Ben (00:26:42):
我只想说有不同的解释。所以人们只是偶尔会说,这有点奇怪,有点特殊。发生了一些事情,一些不连续的变化。我们转向了增长更快的新经济。另一种解释说,不,实际上这是一个相当一致的森林。只是事情变得越来越快,这不是相变,也不是不连续,只是有一个平稳的,真正的长期趋势,只是世界继续加速越来越多

Jeremie (00:27:11):
有趣的是,这几乎像两个不同的子问题一样纠缠在一起。其中一个问题是,人类是否几乎不间断地学习?换句话说,是不是穴居人一代又一代地逐渐掌握了越来越多的技能,这只有在一万年后才变得明显。或者是这样的情况,不,他们基本上是停滞的,一切都是真正平坦的,然后你得到一些起飞。这似乎可以被视为一个更深层次问题的一部分,如果你不断缩小,不断缩小。这不再是一个人工智能接管的人类向未来经济迭代的故事。而是从完全的生物物质和宇宙大爆炸,纯粹没有任何价值创造到…

Jeremie (00:28:01):
我想这是一个阶梯函数,生命进化的第一个时刻。这就是我好奇的地方,这个观点似乎更倾向于量子跳跃角或者阶跃函数方法,除非我错了。

本(00:28:15):
是的。所以我觉得没错。毫无疑问,至少从直觉上来说,历史上有某些转变,看起来确实像是一些不同的事情发生了。所以第一个可以被称为生命形式的自我复制的东西,在某种意义上看起来像是一个相当离散的边界。或者像这样的事情,我真的不知道进化史,但我认为首先你进行一些像线粒体成为细胞的一部分。这是一个相当独立的事件,我相信其中一个生物体比另一个小,[听不清 00:28:48]整个真核生物分支都是从这个事件中进化而来的。还有各种有趣的事情,比如人们从那里掉下来,这似乎也是一种直觉上的不连续变化,我也不太清楚。

Ben (00:29:06):
从直觉上看,确实有些事情。另一个例子是在工业革命时期,人们开始大规模地从事农业。我认为普遍的想法是,从历史的角度来看,这实际上是相当快的,因为人类已经存在了 10 到 1000 年。然后可能在几千年的时间里,像西亚和后来的其他大陆的人们,过渡到定居的农业文明。

本(00:29:35):
我认为这是一个大约持续了 10 万年的大规模冰河时期,然后冰河时期结束了。气候发生了变化,在某种程度上变得更有利于人们真正过渡到定居农业,然后这一切发生得非常非常快。所以,是的,我确实认为你是对的,确实有一些历史案例,至少在我个人对它们了解不多的情况下,感觉像是不连续的变化。我也认为在某种程度上对人工智能来说也是如此。我不认为这是一个,你明天醒来的事情。但我确实认为,如果我们最终实现完全自动化,或者如果增长率因人工智能而再次提高。人们可能不会把它仅仅视为自 1950 年以来就存在的经济趋势的稳定延续。现在我们有非常稳定的经济增长率,我们有非常稳定的自动化填充率。如果增长率变得疯狂,我认为人们会觉得那里有一些拐点或支点或临界点。

Jeremie (00:30:36):
这实际上是一个很好的过渡点,可以想象到我真正想讨论的你一直在看的第二个领域,即你对人工智能安全的看法…不一定是人工智能安全,让我们说人工智能风险和这种平稳过渡到人工智能驱动的世界的想法,或者让我们说一种非常突然的过渡到一种反主题或存在致命的场景。那么你对此有什么看法吗?也许我会以此开始。所以,你能不能把你的想法放在你认为人工智能风险的论点在哪里是强有力的,也许在哪里是失败的?

本(00:31:14):
是的。所以我想我可以先说一点连续性问题,或者至少与连续性问题的相关性。正如你提到的,这也是人们关于人工智能的辩论,即人工智能会有多突然…让我们假设我们最终会进入一个人工智能系统可以基本上使人类劳动过时并做各种其他疯狂事情的世界。这种转变会有多突然?它会是那种类似于工业革命的东西吗?它会持续几十年的时间,这种渐进的东西会以渐进的方式传播到世界各地吗?

Ben (00:31:48):
我认为即使是像蒸汽动力这样的东西,人们从不使用化石燃料过渡到使用化石燃料,这也是一个极其漫长的过渡。它会更像那些案例吗?还是会让人感觉更突然?会不会有一个时间点,比如说两年的时间,我们从基本正常的东西到现在一切都是人工智能,甚至不到两年。这是一场长期或未来的辩论[听不清 00:32:15]。在某些方面,它似乎是相关的,某些方面应该是增加风险或最终降低风险。

Ben (00:32:24):
就增加风险而言,突然或非常快速的变化意味着它可能会突然出现。所以这是非常连续的,你会看到很多事情提前发生了。然而,如果它真的很突然,如果这是一个需要两年时间的过程,这意味着原则上两年后,如果它碰巧发生,我们可能会生活在一个非常不同的世界。准备的时间更少,适应不同中间水平差异的时间更少,尝试和错误学习的时间更少,对风险的感觉也更少。没有什么风险。如果我们把这个问题说出来,并意识到有机会看到如何发现和习惯问题,并提出中间解决方案,并从你的错误中学习。我认为这方面最大的风险可能是与错位人工智能相关的风险,我想这是最后一个主要风险类别。这些也有一点不同,我相信你已经有一些播客上的人谈论过它们。

Ben (00:33:21):
但很多担忧基本上都归结为我们未来开发的许多人工智能系统可能会在某种程度上表现得好像它们在追求某些目标。或者试图最大化世界的某些事物。从某种意义上说,就像[听不清 00:33:35]系统从刑事司法的角度对犯罪率进行预测,在某种意义上,试图提高预测的准确性或诸如此类的事情。令人担忧的是,目标是人工智能系统在某种意义上有分歧,而[听不清 00:33:58]人往往会有分歧,这将导致灾难性的后果。我们有人工智能系统,它们非常聪明,非常善于实现它们的任何目标,只是做与人们想要的不同的事情。

本(00:34:12):
所以速度确实与此相关,因为如果你认为这将是一个普遍的问题,有人会创建一个人工智能系统并部署它。然后在它的目标和人们的目标之间有一些分歧,这导致了伤害。看起来,如果人工智能系统在世界上扮演越来越大的角色,那么可能有相当多的时间来了解这种担忧的不那么灾难性的版本,或者了解什么可行或不可行。不是每个人都完全相信渐进和试错就足以完全解决问题。但是,实际上能够看到问题的更多次要版本,并提出在次要情况下有效的解决方案,似乎肯定是有帮助的。这种事情总是很突然,假设我们明天醒来,我们有了人工智能系统,原则上可以完全取代人类劳动,可以管理政府,可以做任何事情。

本(00:34:59):
无论出于什么原因,如果我们决定使用它们。他们的目标在某些重要方面与我们不同,那么这可能更令人担忧,我们可能看不到问题的出现。是啊。所以我猜你的问题是,为什么这可能不是一个主要的关注点,或者说这是一个关注点的论据是什么?

Jeremie (00:35:21):
实际上,我认为还有一个更具体的问题,那就是你花了很多时间来整理行李。尼克·博斯特罗姆在他的书《超级智能》中提出的论点就是这种担忧。简单总结一下,放在这里,我的想法是,我要把它切掉,请随意强调我切掉它的各种方式。但这个想法是这样的,如果我们假设人工智能团队,比如 OpenAI 和 DeepMind 以及其他任何东西都在逐步迭代,迭代,迭代。有一天,他们中的一个人有了一个想法或者购买了一整套计算,或者访问了一整套数据。这就是把一个系统从可怜的小 GPT 3 号提升到现在人类水平或更高水平所需要的东西。

耶雷米(00:36:06):
那个系统因为是人类水平或更高,它可能知道如何改进自己,因为人类知道如何改进人工智能系统。所以也许它知道如何改进自己,你得到一些递归循环,因为循环很紧,人工智能可以改进自己。最终,它变得如此聪明,以至于它可以用它的智慧压倒俘虏它的人,接管世界,导致一个完全灾难性的结果。这至少是大致正确的吗?

本(00:36:30):
是啊。所以我认为这基本上是正确的。是啊。因此,一种思考方式是,我认为存在一系列的对齐问题。其中一些是在更模糊的未来视角,随着时间的推移,我们逐渐创造出许多人工智能系统,它们的目标与我们不同,对未来的控制逐渐丧失,诸如此类。还有更极端的情况,就像有一个单一的人工智能系统,并且来得非常突然。从某种意义上来说,这是一种广义的超智能,并没有真正的先例。这个系统会很快地在世界上造成大破坏,就像有一些重大的跳跃到这个单一的非常破坏性的系统,这肯定是令人担忧的版本。它在尼克的书《超智能》和《叙事》中得到了强调,我猜你刚刚描述过了。

本(00:37:18):
所以我自己对人工智能风险的很多思考都是关于这个更极端的领域,所以出于几个原因,对超级智能的担忧出现了。我认为这是我第一次遇到的版本,这让我特别感兴趣,我想这是我感兴趣的部分个人原因。

Ben (00:37:39):
和其他人一样,我认为这只是,即使许多人工智能比对研究人员,也不会首先考虑这个版本的问题。我觉得还是挺有影响力的,挺有知名度的。通常,如果有人了解人工智能风险,这就是我们想到的担忧。所以听起来我认为这可能是一个特别值得关注的问题。所以我的一些想法只是关于看似合理的问题,你实际上有一个非常突然的跳跃,从你没有真正感兴趣的主要人工智能系统,有点像今天。然后某个地方的某个研究人员突然有了重大突破,你就有了这个单一的系统。我想我可能出于无聊的原因对此相当怀疑。

Ben (00:38:15):
最初令人厌烦的一个原因是,这不是技术的工作方式。如果从喜欢的角度出发,我们来看看技术通常是如何改造世界的。通常情况下,这是一个漫长的过程,需要几十年的时间,有人开发了一些东西,然后这是一个漫长的改进过程。然后它在某些领域比其他领域更重要,在某些领域比其他领域更有用。然后人们需要开发互补的发明来利用它。人们需要弄清楚如何恰当地使用它。还有很多你无法预见的调整和问题,这使得它成为一个缓慢的过程。所以就像电一样,我认为电动机是在 19 世纪早期的某个时候发明的。但是直到 20 世纪 30 年代,电动马达才在美国工厂占据主导地位。

本(00:39:02):
或者是 20 世纪中期的第一台数字计算机,但是从 90 年代开始,它们真正以一种大的方式出现在生产力统计中。即使这样,也不是所有的国家,不像在不同的重要场合普遍使用的那样。甚至不像经济中的大部分那样。因此,它成为一个起点,就像你不会太具体地看人工智能的细节,并说:“如果它像我们曾经拥有的任何其他技术一样,我会期待什么?”很可能是经济转型,这将是一个渐进的过程,会发生很多恼人的事情。

Jeremie (00:39:35):
只是稍微探索一下。所以我认为在过去的 100 年里,无论我们选择哪个时期,有一件事加速了技术的进步和传播,那就是交流。我们谈了很多次,互联网扮演的角色等等。尤其是沟通,在设计产品的团队,部署产品的团队,销售产品的团队等等之间的紧密反馈循环方面。就整合而言,一致性是由沟通驱动的。从某种意义上来说,这是否会破坏这一论点,“好吧,如果你有一个内部连贯的单一人工智能系统,它能够本质上收紧反馈回路,不是无限地,而是机器时间。”我想,我想问的是,你觉得那个职位有趣吗?

本(00:40:28):
所以我想我觉得这很有趣,但没有说服力。所以我会说,如果我们突然想象一下,突然出现一个功能极其广泛的人工智能系统,它可以为你提供所有与经济相关的生产任务。它可以挖掘芯片,它可以运行投票中心,它可以进行人工智能研究,它可以建立更多的计算资源,它可以管理没有军事战略。如果我们想象有一个单一的系统突然出现,它只是自己做所有的事情,而不与外界因素相互作用或依靠外部资源。看起来确实有一些直觉,事情可以发生得更快,因为沟通效率成本已经下降了很多。但是有这样的问题,我们应该想象这是发展的方式吗?将会有一个单一的系统突然获得所有这些能力。我想这可能是我对人工智能持怀疑态度的原因,也是因为一些无聊的原因。

本(00:41:32):
所以我们知道你可以同时在不同的领域取得进展。所以,就像……我想可能你的很多听众都很熟悉这个,语言模型或者这个最近由 OpenAI 开发的系统 GPT-3。这是一个系统的例子,通过一个简单的训练过程,在几乎相同的时间里,在许多不同的任务上变得相当好。所以我是在一个基本上是网页的大型语料库上接受训练的。我接受的训练是,根据我在一份文件中已经遇到的单词,试着预测下一个最不令人惊讶的单词。

Ben (00:42:08):
这样你就可以用它来为一篇新闻文章写标题,然后我会试着想想在给定标题的情况下,文章中最不令人惊讶的文字是什么。人们发现的一件事是,你可以用它来做很多不同的事情。所以你可以用它来做翻译,例如,我们可以用西班牙语写一个句子,然后说英语翻译,这个句子是空白的。而且这个系统会出去,至少会发现一个令人惊讶的东西,接下来基本上会像英文翻译它,并用它来写诗。艾米莉·狄金森这首诗最不令人惊讶的结尾是什么?

Ben (00:42:42):
但即使在这些情况下,从某种意义上来说,许多不同的功能同时上线。你仍然可以看到人工智能在不同方面的变化。所以它在很大程度上是很糟糕的,就像可用的计算机代码一样。你可以做到这一点,但目前基本上无法用有用的方式做到。它很擅长写贾巴沃克风格的诗,一首接一首。有理由认为,这甚至可能是一种不断扩展的情况,其中一些功能优先于其他功能。也有一些能力,你真的不能仅仅通过这种 GPT-3 风格来产生,在这个庞大的在线事物语料库上训练它。

本(00:43:23):
如果你想翻译国防部的内部备忘录,你需要接受其他方面的培训。如果你想让它写得像医疗保健立法,可能[听不清 00:43:30]不会为你做到这一点。如果你想让它设定超市价格,或者你个性化电子邮件,它知道什么时候为你安排会议。你需要一种不同的训练方法。或者,如果你想比人类表现得更好,你也需要一种不同的训练方法,因为你需要给它像…它基本上做的是试图说出一个人在互联网上写的最不令人惊讶的事情。但是如果你想比人做得更好,你就需要使用其他东西,某种反馈机制。

Ben (00:43:55):
我认为不同的功能会在不同的时间上线。也可能会有许多讨厌的东西出现在不同的特定领域,并没有真正显示给研究人员。但当你想把类似[听不清 00:44:07]这样的定律应用到工厂里实际使用电动机的人身上时,就好像,你需要重新设计你的工厂车间。因为它不再以中央蒸汽机为基础。你需要重新设计使用硬件的东西,你需要重新设计你的工人使用的流程,实际上是利用这个东西。你有需要发生的规则,等等,等等。或许这些事情在某种程度上需要被处理,至少在最初由不同的团队处理。其中一些会比其他的更难或者需要不同的资源。如果,这就像是说我期待东西上线的一种很长的方式,那我基本上会感到惊讶,那实际上在世界上不同的点上对不同的任务真的很有用。

Jeremie (00:44:40):
有意思。是啊,很有道理。对我来说有趣的是,这正是一个理论家会犯的错误,想象一个系统…这不是一个错误,这种情况很容易发生。但这些有趣的反对意见似乎映射到了那些关注理论优化而非实践中系统和经济优化的人的心理上。有意思。因此,这一切似乎并不意味着,在未来的某个时刻,开发一个具有自我迭代改进能力的人工智能系统是不可能的。

耶雷米(00:45:23):
这个问题有两个部分。首先,A,你认为是这样吗,或者你认为有可能建立这样一个系统吗?第二,你认为这样的系统会被建立或可能被建立吗?有没有一系列的激励因素累积起来,让我们得到一个递归的自我改进的人工智能,它最终会[foom 00:45:47],做任何事情?这个故事可信吗?

本(00:45:51):
是的。所以我这里有一些。所以第一点是,我不清楚递归自我改进是否真的会成为一件事。很明显,现在有反馈回路,将来也会有反馈回路。所以我们以一种更有限的方式看待许多技术。所以现有的软件对于开发软件是有用的。软件开发者使用软件,计算机对于设计计算机是有用的。如果像 Nvidia 或任何种类的硬件制造商这样的人没有电脑可用,他们可能会发现他们的工作会更加困难。因此,在很多情况下,辅助设计开发技术或一种技术辅助另一种技术的开发。它通常不是递归的,或者它通常不是完全相同的自我改进的工件。

Ben (00:46:44):
在 AI 的例子中,我并不认为它是递归的。我当然希望人工智能越来越多地应用在人工智能开发寻找正确架构的背景下。或者学习,找出基本上开发另一个系统或使其良好运行的最佳方式。但我不认为这是一个独立的系统对自己做的事情,而不是一个用来帮助训练其他系统的系统。就像软件不会自我完善一样。我真的看不出递归有什么好处。如果这样做了,情况可能是这样,但我不明白为什么它会是递归的,为什么它天生更有吸引力。从某些方面来看,它似乎没那么有吸引力。这看起来有点混乱,或者如果这是一个有点模块化的东西,这似乎很好。

耶雷米(00:47:33):
是的,我想,从某种程度上来说,只是为了从工程的角度支持这个论点,我可以想象……所以这是不同系统的抽象,这个术语我们用来说有系统 A,有系统 B。系统 A 要么在改进自己,要么系统 B 在改进它,然后可能是系统 A……所有这些东西。我想在这种情况下,我想到的是一个抽象概念,它涵盖了类似于一个封闭系统的东西,这个系统在机器时间上起着关键的作用。所以在我看来,定义这种形式起飞的关键区别在于,这种自我优化或者系统 A 改进系统 B 的过程发生在微秒级。或者你有什么,以至于人类没有在过程中调解,最终对结果感到惊讶,而结果会大大偏离我们的期望。

本(00:48:33):
是的。所以我认为其中一个关键的区别是劳动力基本上参与了改进过程。因此,这种人工智能反馈循环的一个普遍反作用,对于真正提高变化率非常重要。我想我们确实已经有了这些反馈回路,在这些回路中,研究人员或工程师在 20 世纪初会做的大量任务,他们只是不再做了。它们已经完全自动化了。所以实际上手动计算就像一个巨大的时间水槽。这就像是工程学的研究成果。因此,从人们花费的时间来看,已经有了大规模的自动化,其中很大一部分已经实现了自动化。所以从这个意义上来说,这是一个非常强大的反馈循环,技术进步帮助了技术进步。

Ben (00:49:25):
但至少自 20 世纪中叶以来,我们还没有看到生产率像技术进步那样增长,至少在领先国家是这样。如果有什么不同的话,那就是它实际上走得更慢了。现在的比率相当于美国 20 世纪初的水平..所以很明显,这个反馈回路本身是不够的,还有一个抵消的东西,可能意味着同样的事情,就像这个想法越来越难找到现象。科技帮助你制造新的东西,但是你想制造的每一件新东西都比以前的东西更难制造。因为如果很简单,你早就做了。这是一个普遍的反驳论点。

本(00:50:01):
然后是反驳,反驳的论点就像,我们一直在将研究中涉及的许多任务自动化,然后创造机器来完成它们,然后改进机器。人类劳动一直是其中的一部分。如果你有这样一个故事,由资本填充的人力基本上是互补的。我认为我们有劳动力瓶颈的故事,我们不断制造更冷的机器,我们不断制造更多的机器。但是对于固定数量的研究工作来说,你的机器的酷和数量的回报是递减的。所以研究工作真的是瓶颈。它造成了这种收益递减现象,这实际上限制了由研究人员参与、完成或拥有的额外酷技术的边际价值。然后,研究人员的数量以相当恒定的指数速度增长,这实际上不可能轻易改变,因为它与人口等因素相关。

Ben (00:50:57):
所以我刚才说,如果你真的把人类劳动完全从画面中去掉,人们就不再参与研发或制造了。那么也许在这种情况下,你不再有这种收益递减效应,你不再有这种瓶颈,你在固定数量的劳动力上获得的资本收益递减。也许它只是直接反馈给自己,收益递减在某种重要意义上消失了。一旦你完全将人类从反馈回路中移除,反馈回路就真正启动了,这将是你可以讲述的故事,来说明为什么反馈回路在未来会不同于我们在过去一个世纪中所拥有的不明确的反馈回路。

Jeremie (00:51:29):
我想这是人类自我提高的一种反馈。我认为时钟时间是这里的显著特征,但我确实努力提高自己的生产率,我也确实努力做到这一点。我试着用提高自己的方式来提高自己。原则上,我认为我对无穷多的导数,或者接近于物质,都是这样做的。所以这是一个指数性质,但显然我还不是埃隆·马斯克。我还没有实现艰难的起飞,所以在某些地方有所不同。

本(00:52:05):
是的。所以我想我要说的是,我认为你绝对是对的,这是一个真实的现象。我认为,尽管涉及的数量级,你需要自我提高的程度比技术要小。让我们想象一个研究单位是你笔记本电脑里的一个人。这就是产生研究的原因。这个人实际上可以让自己更好地编码,他们可以让自己更好地学习如何快速做事情,他们可以学习如何学习。但是也许生产力的实际差异,也许你可以帮助增加 10 倍的人力资本,相对于 2020 年研究人员的平均水平。而你的笔记本电脑,看起来可能有更多的[听不清 00:52:44]可以比现在更好。

Jeremie (00:52:49):
不幸的是,似乎确实是这样,但我需要继续努力。我认为这是它所需要的。

本(00:52:56):
是的。我祝你在与笔记本电脑进步率的竞赛中好运。

耶雷米(00:52:59):
是的。谢了。如果我按了起飞键,我会告诉你的。所以这真的很有趣,你在这个问题上做了这么多的思考,我可以从自己身上看到你思考这个问题的方式的一些转变,当然还有一些我以前没有考虑到的方面。从经济学的角度来看,从系统的角度来看。这是你认为在技术型 AI 安全人中特别不常见的一种思维方式吗?或者你开始看到它被采用了…我仍然试图拼凑出这个景观是什么样子的,以及随着时间的推移,人们对这个主题的看法是如何转变的。因为举例来说,我记得 2009 年是[听不清 00:53:45]。基本上每个人都在谈论大脑在盒子里的想法,或者一些快速起飞的东西,在那里机器自我改进等等。

Jeremie (00:53:54):
虽然现在 OpenAI、Paul Christiano 和未来人类研究所的许多工作看起来确实很像,但事情正在发生变化。我很乐意听取您对这一转变、时间表以及机构群体目前对所有这些主题的看法。

本(00:54:11):
是的。所以我确实认为这种方式已经发生了转变,比如说这些社区中的普通人正在思考这个问题。对我来说有一点模糊,这在多大程度上是人们从一种思维方式转向另一种思维方式的转变。相对于更多的人带着已经存在的不同思维方式进入社区。我确实认为,有一些人以更具体的方式思考问题。你认为很多旧的分析非常抽象。它非常依赖于…它不完全像数学,它就像人们做一个抽象的代数或什么的。但这肯定更像是一种数学思维。

本(00:54:58):
它会随着时间的推移而改变。我认为其中的一个原因,也是非常合理的,就是当人们在 2000 年代中期谈论这个问题的时候。机器学习并不是一件大事。人们认为,也许面向逻辑的系统会更像 AGI 的样子。任何真正看起来像 AGI 的东西都可以作为思考的模型。我认为,随着机器学习的兴起,人们开始拥有这些系统,像 GPT-3,这里显然不是 AGI,可能 AGI 会有很大不同。这就像是通往 AGI 道路上的一块踏脚石。这有点像 AGI 什么的。

Ben (00:55:41):
我认为有了这些具体的例子,你就会开始以一种稍微不同的方式思考。你会开始意识到,在你之前拥有的这些抽象框架的背景下,它们实际上有点难以描述。那么 GPT-3 有目标吗,或者如果你想预测这种行为,有多有用。我猜它的目标是产生下一个不令人惊讶的词,但这样想有点不太对。尚不清楚它对预测这种行为有多大用处。它似乎并不真的有做一些疯狂的事情的风险,比如杀人来阻止他们阻止它输出。不知怎么的就是感觉不太合身。也只是看到更具体的应用和思考…所以我认为就像保罗·克里斯蒂诺说的那样,例如,在某种程度上是乐观的,“哦,我认为你实际上可能会用机器学习做那件事,在没有重大突破的情况下,在不远的将来。”让人们以更连续的方式思考,而不是全无或全无。就好像你可以看到中间转化的垫脚石。

Ben (00:56:41):
所以我认为这是一种中间应用,更具体一些。感觉有点怀疑抽象的构成,只是因为很难把它们放在你看到的事物上,或者一些有影响的力量。一般来说,我确实认为有很多人认为更数学化、更经典的处理事物的方式仍然很有用,或者这可能是他们处理事物的主要方式。

耶雷米(00:57:09):
是的。我实际上听到了争论…不一定是像 GPT-3 这样的系统会像你描述的那样变得病态。但至少可以讲述的故事听起来内在一致,描述了这样一个系统可能会严重出错的世界。在这种情况下,就像,想象一下 GPT 10 号,无论那一年发生了什么。你有一个系统,它必须像美化的自动完成任务一样做这件事。但是为了完成这项任务,有一点似乎很清楚,那就是它正在开发一个相当复杂的世界模型。关于这在多大程度上是记忆还是真正的概括学习,还存在一些争论。但是让我们假定 GPT-3 是可推广的学习。在这种情况下,系统继续开发一个越来越复杂的世界模型,一个越来越大的上下文窗口。

Jeremie (00:58:06):
最终,这个世界的模型包括了 GPT-3 本身的存在,它是世界的一部分。最终,当它试图优化它的渐变时,这种认识使它意识到,“哦,我可以通过某种走线来直接控制我的渐变,”这通常是它在[crosstalk 00:58:25]社区等中的框架。我认为你描述的问题适用于这种思维方式。但有趣的是,GPT-3 真的导致了对其中一些摘要的具体思考。

本(00:58:39):
是啊。我认为拥有这些具体的系统也是非常有用的,因为我也认为它们迫使直觉产生差异。或者把复出和假设中的分歧强行浮出水面。举个例子,肯定有一些人对这些 GPT 系统表示担忧,或者如果你有 GPT-10,这可能会非常危险。我真的没想到会这样。或者我估计我不会猜到别人有这种直觉只是因为我没有。因为我的基本直觉只是对系统工作方式的粗略估计。它是一个由一些参数组成的模型,然后暴露在一个文本语料库中。它只是基本上输出一个 X 单词,然后下一个单词实际上是对的或者不是。或者基本上有一个梯度,使得输出相对于数据集中的实际单词越来越不令人惊讶。

本(00:59:35):
它基本上是为输出单词而优化的,在一段文本中发现一个 X 单词并不奇怪,这段文本在网上的某个地方。当我想到 GPT-10 时,我想,“哇,我想它只是输出单词,这在网上的网页上发现并不奇怪。”就像它做的事情一样。假设,假设它确实输出单词,导致人们毁灭世界之类的东西。似乎只有当这些词在网上最不令人惊讶时,它才会这样做。如果导致它毁灭世界的词不是,在网上找到会令人惊讶吗,因为人们通常不会在网上写这种东西。那么梯度下降过程似乎发生了一些奇怪的事情。

Jeremie (01:00:15):
所以我认为这是一种非常好的设计方式。我相信,对此的反驳可能听起来像是,我们可能会把 20 万年前的人类视为性优化者之类的东西。然后我们发现,随着进化的展开,我们并不是那样。我认为这里的情况是,首先,有一个深刻的问题,神经网络实际上是在优化什么。实际上并不清楚它是在优化它的损失函数,还是每次梯度更新时它都会感到一阵兴奋。就像,“哦,你错了。以此更新您的所有费率。”

杰里米(01:00:58):
那一脚疼吗?如果是这样的话,这些系统优化的是真的吗?如果是这样的话,那么这整个区域显然是内部对齐的,我们在这里绕着,但我想这是一个很深的兔子洞。

Ben (01:01:15):
所以我有点同意在训练系统时使用的损失函数和这个系统试图做的事情之间有区别。有一种非常简单的说法,那就是如果你从下棋强化学习系统开始。你有一个回报函数,一个与之相关的损失函数,只是你还没有训练它。它不会表现得像是在试图赢国际象棋,因为这就像是一个最简单的例子,它就是没有意义。

本(01:01:40):
然后很明显,你有这些移植的案例,你在比如说一个视频游戏中训练一个系统,每次它打开左边的一个绿盒子,右边就有一个红盒子,它就会得分。你把它放在一个新的环境中,左边有一个红盒子,右边有一个绿盒子。到目前为止,你给它的训练数据实际上还不足以区分,听起来像是实际上被奖励的东西。是打开红色的盒子还是打开左边的盒子?如果系统,比如说,打开左边的盒子,你不应该感到惊讶,即使实际上不是损失函数的东西是红盒子,反之亦然。如果用错误的方式概括,也不奇怪。

Ben (01:02:21):
所以我当然同意存在泛化错误。我很难理解为什么你会以像 GPT-3 这样的情况结束,我只是不明白机械地会发生什么,它会在哪里…所以让我们说,关注是因为它的文本生成系统输出一些文本,如果有人阅读,它是一个杀死所有人的工程蓝图。我不知道是否有一个非科幻的版本,它会导致存在的风险,但假设它确实是这样的。我有时觉得我几乎是…要回答什么的或者我错过了什么。但我只是不明白为什么这个分级设计过程会导致它有一个这样的政策。为什么会朝那个方向优化呢?

Jeremie (01:03:06):
我要给出的答案,我肯定没有充分考虑过,我应该先说。但原则上,如果我们想象一下,比如无限的计算量,无限的数据规模,等等。这个模型会,比方说它开始思考,它思考得越来越多,越来越多,就像一个越来越大,越来越完整的世界图景。同样,根据它试图优化的内容,假设它试图优化以最小化其梯度。这是很自然的,我假设我在某种程度上是错的,但在某种程度上,想象神经网络每次被踢来踢去都感觉不好是对的。我不知道。

Ben (01:03:47):
我认为这实际上没有任何意义,尽管感觉很糟糕。我认为它只是,它有某些参数,然后它输出一些东西,并与训练集进行比较。然后根据差异,它[听不清 01:04:02]踢向不同的方向。但是我不认为实际上有任何内在的…我不认为实际上有一种有意义的感觉它感觉不好。它的参数可以像棍子一样来回移动。这是一个拿着棍子的家伙,在差异或缺乏差异的基础上,将参数推向不同的方向,然后它们最终在某个地方结束。

耶雷米(01:04:23):
是的。所以这本身就是,我认为最酷的方面之一。我快要被内心的兴奋分散注意力了。但对我来说,这是对齐辩论中最酷的一个方面,因为它真的让你对主观体验和意识产生了怀疑。因为如果不说“这是一种学习过程”这样的话,就无法进行对话学习过程往往会产生一个人造物,就像人类一样,它是一个大脑,似乎有一些主观经验,基本上是所有的生命。你可以观察变形虫,在显微镜下移动它。它真的好像在不同的时刻以不同的方式经历了痛苦和快乐。

Jeremie (01:05:02):
无论如何,看到这些系统以类似的方式运行,至少在我心中激发了一些问题,即实际的 Mesa-objective(优化器真正试图改进的功能)和主观体验之间的联系是什么。我将要进入一个我还不够了解的领域。但是也许我可以把这个想法留在,我认为这也是这个问题的一个令人兴奋和有趣的方面。你认为意识和主观经验,在这些机器的环境中的研究,有作用吗?还是你-

本(01:05:44):
我不这么认为。这里有一个困难,很明显人们对意识有不同的理解。所以我想我主要是在我想大卫[听不清 01:05:55]的意识体验中认为这至少是假设的现象学的东西,它不是本质上的一部分……它不像一个物理过程,所以它不是对事物如何处理信息的描述。这是一种叠加在大脑中发生的机械物质之上的体验。然而,如果你是魔术师,你会认为没有这样的东西,这就像一个呜呜呜的东西。但是我想对于意识的概念,它似乎在某种意义上没有直接的关联,因为它实际上没有它的怪异方面。这是一个定义或假设,而不是实际上物理影响任何已经发生的行为。你可以看到僵尸的行为方式也是一样的,但是它们的顶部没有额外的意识层。

Ben (01:06:44):
因此,我认为意识的这个版本与理解机器学习训练如何工作或 MACE 优化问题如何工作没有太大关系。也许有机械论的东西,人们有时指的是使用意识,我认为这有时与信息系统有关。不知何故,当人们使用“意识”这个术语时,他们可能会挑选出自己的表征。似乎有些东西是相关的,或者是关于你自己的目标是什么的信念,诸如此类。也许这与最优化和人类自我意识之类的东西有一些有趣的关系。所以我可以看到其中的联系,但我想这一切都是说,这取决于一个人头脑中意识的概念。

耶雷米(01:07:38):
不,完全有道理。有趣的是,这些东西确实与许多不同的领域重叠,从经济学到意识理论,心智理论。非常感谢你分享你的见解,本,我真的很感激。你有没有一个 Twitter 或个人网站可以分享,这样人们就可以查看你的工作,因为我认为你正在做一些令人着迷的事情。

本(01:07:57):
是的。所以我确实有一个个人网站,上面的内容很少,但是我参考了一些论文。那是 benmgarfinkel.com。我有一个推特账号,但是我从来没有在上面发过微博。我忘记了我的用户名是什么,但如果你想找到它并跟随我,有一天我可能会用它发微博。

耶雷米(01:08:15):
这是一个令人信服的推介。所以各位,看看本发微博的可能性。

Ben (01:08:22):
如果你现在就开始工作,你可能是第一批看到我发推文的人。

耶雷米(01:08:27):
他们正在播种。这是投资种子期的时候了。太棒了。非常感谢,本。我会链接到这两个东西,包括 Twitter。

Ben (01:08:36):
我期待着更多的 Twitter 关注者。

耶雷米(01:08:40):
这就对了。是啊。各位,跟着本,去看看他的网站。我还会在这篇播客的博文中发布一些链接,只是为了…我们在这次对话中提到的本整理的一些具体论文和作品,因为我认为还有很多值得挖掘的内容。本,非常感谢。真的很感激。

本(01:08:56):
非常感谢。这是一次超级有趣的谈话。

通过组合多种模型实现卓越的功能选择

原文:https://towardsdatascience.com/superior-feature-selection-by-combining-multiple-models-607002c1a324?source=collection_archive---------10-----------------------

你最喜欢的模特自己选择特色

图片由 安德里亚 像素

介绍

机器学习中有很多特征选择方法。每一种方法都可能给出不同的结果,这取决于你如何使用它们,所以很难完全信任一种方法。让多种方法投票决定我们是否应该保留一个特性,这不是很酷吗?这就像随机森林算法一样,它将多个弱学习者的预测结合起来,形成一个强学习者。事实证明,Sklearn 已经给了我们工具来自己制作这样的特征选择器。

通过使用这些工具,我们将一起构建一个特性选择器,它可以接受任意数量的 Sklearn 模型。所有这些模型将投票决定我们应该保留哪些功能,我们通过收集所有模型(民主)的投票来做出决定。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

构建选择器的必备知识:权重和系数

在我们继续构建选择器之前,让我们回顾一些必要的主题。首先,几乎所有产生预测的 Sklearn 估计器在被拟合到训练数据之后都具有.coef_.feature_importances_属性。

.coef_属性主要出现在sklearn.linear_model子模块下给出的模型中:

顾名思义,以上是通过拟合线性回归的最佳拟合直线计算出的系数。其他模型遵循类似的模式,并产生其内部方程的系数:

sklearn.treesklearn.ensemble中的模型工作方式不同,它们计算.feature_importances_属性下每个特征的重要性权重:

与线性模型的系数不同,权重之和为 1:

np.sum(dt.feature_importances_)1.0

无论模型如何,随着特征权重或系数的降低,特征对整体预测的贡献越来越小。这意味着我们可以丢弃系数或权重接近 0 的特征。

RFECV 概述

递归特征消除(RFE)是一种流行的特征选择算法。它会自动找到要保留的最佳特征数量,以实现给定模型的最佳性能。下面是一个简单的例子:

上述代码用于查找最少数量的特征,以实现套索回归模型的最佳性能。

在拟合到训练数据之后,RFECV 具有.support_属性,该属性给出布尔掩码,具有应该保留的特征的真值:

然后,我们可以使用该掩码对原始数据进行子集划分:

X.loc[:, rfecv.support_]

定制特性选择器的核心将是这个RFECV类。我没有详细介绍它是如何工作的,但我以前的文章重点介绍了它。我建议在继续之前阅读:

第一部分:选择模型

我们将使用 Ansur Male 数据集,主要是因为它包含了 6000 名美国陆军人员的许多身体测量特征(98 个数字):

我们将尝试预测以磅为单位的体重,为了做到这一点,我们需要降低模型的复杂性——也就是说,使用尽可能少的特征创建一个具有尽可能多的预测能力的模型。目前有 98 个,我们将努力减少这个数字。此外,我们将删除以千克为单位记录重量的列。

ansur.drop("weightkg", axis=1, inplace=True)

我们的第一个模型将是 Lasso Regressor,我们将把它插入RFECV:

我们将从套索生成的布尔遮罩存储在lasso_mask中,稍后你会看到原因。

接下来,我们将对另外两个模型进行同样的操作:线性回归和 GradientBoostingRegressor:

第二部分:合并投票

现在,我们将投票作为布尔掩码放在三个数组中:lasso_maskgb_masklr_mask。由于真/假值代表 1 和 0,我们可以添加三个数组:

结果将是一个数组,其中记录了所有模型选择每个特征的次数。现在,我们可以设置一个投票阈值来决定是否保留该特性。这个门槛取决于我们想保守到什么程度。我们可以设置一个严格的阈值,我们希望所有 3 个成员都选择该特性,或者我们可以选择 1 作为安全阈值:

现在,final_mask是一个具有真值的布尔数组,如果所有 3 个估计器都选择了一个特性。我们可以用它来划分原始数据的子集:

>>> X.loc[:, final_mask].shape(4082, 39)

如您所见,最终的掩码选择了 39 列,而没有选择 98 列。您可以使用数据集的这个子集来创建一个不太复杂的模型。例如,我们将选择线性回归模型,因为我们可以预期身体测量值是线性相关的:

步骤总结

即使需要一些工作才能得到最终结果,这也是值得的,因为多个模型的组合能力可以超过任何其他特征选择方法。

我们在示例中只选择了 3 个模型,但是您可以包含任意多的模型,以使结果更加可靠和可信。

此时,合乎逻辑的一步是将所有这些代码包装在一个函数中,甚至是一个定制的 Sklearn 转换器,但是定制转换器是另一篇文章的主题。为了加强上述观点并给你一个大纲,让我们回顾一下我们已经采取的步骤:

  1. 选择任意数量的具有.coef_.feature_importnances_属性的 Sklearn 估计器。估计量越多,结果就越稳健。然而,多个模型是有代价的——因为RFECV在幕后使用交叉验证,对于集合模型和大型数据集,训练时间在计算上将是昂贵的。此外,确保根据问题的类型选择估计器——记住只传递分类或回归估计器,以便RFECV工作。
  2. 将所有选择的模型插入RFECV类,并确保保存每一轮的布尔掩码(通过.support_访问)。为了加快速度,您可以调整step参数,以便在每轮淘汰中丢弃任意数量的特征。
  3. 对所有估计量的掩码求和。
  4. 设置投票计数的阈值。这个门槛取决于你想保守到什么程度。使用此阈值将投票数组转换为布尔掩码。
  5. 使用最终掩膜对原始数据进行子集化,以进行最终模型评估。

与特征选择相关的进一步阅读

您可能也会感兴趣…

使用预建的 Google BERT 进行高级人名识别

原文:https://towardsdatascience.com/superior-person-name-recognition-with-pre-built-google-bert-e6215186eae0?source=collection_archive---------7-----------------------

当基地需要电梯时

照片由布雷特·乔丹Unsplash 拍摄

使用 spaCy 进行命名实体识别效果很好,但并不是在所有情况下都是如此,尤其是涉及人名时。然而,由于拥抱脸,你可以作为一名 ML 工程师(而不是作为一名数据科学家)使用谷歌伯特模型,轻松提高个人 NER 准确性。

免责声明 : spaCy 可以结合类似于我将要描述的技术,所以不要把 spaCy 排除在外,这篇文章只是结合该技术的一种替代方法。

伯特和拥抱脸上的几个字

拥抱脸将自己描述为一个社区,在这里我们可以“构建、训练和部署由自然语言处理中的参考开源提供支持的最先进的模型。”

这是一个构建模型或使用其他人构建的模型的地方——这最后一点尤其重要。

Google BERT(来自变压器的双向编码器表示)是 Google 为 NLP 创造的技术,没有被它的工作方式所干扰。看看这件由伯特建筑师事务所创作的作品,它深入探究了伯特是如何工作的。简而言之,使用 Google BERT 构建的模型运行良好。是的,我知道,这是一个荒谬的过度简化,但这篇文章是关于使用 BERT,而不是创建基于 BERT 的模型。

具有空间结果的样本

下面是一个为循环抛出(基)空间的名称列表:

names_string = “Hi there Jon Jones Jon Jones Jr. Jon Paul Jones John D. Jones”

下面是一些 Python 代码,使用 spaCy 的基本 NER 和那个名字列表。

结果是:

这并不可怕,但如果你需要它变得伟大,它将功亏一篑。

另一个选择是使用 transformers Python 包,它(多亏了拥抱脸)可以让你访问包括 Google BERT 在内的模型。

transformers Python 包

变形金刚包装是使用拥抱脸模型的关键部分。安装可能有点复杂,这取决于你是否已经安装了 PyTorch 和/或 TensorFlow。在我的一台计算机上,我已经安装了 TensorFlow,我所需要做的(运行我的示例,它可能不完全适合您的情况)就是运行:

pip install transformers[torch]

我通过在命令行输入以下命令打开 interactive Python 来验证我的安装:

发生了几件重要的事情:

  1. 情感分析模型是从拥抱脸自动下载的(这很重要)。
  2. 我从第二行代码中得到以下结果:

[{‘label’: ‘POSITIVE’, ‘score’: 0.9998704791069031}]

模型结果是这样返回的(至少对于我尝试过的所有 NLP 模型是这样):一个字典列表。好的,很好。是时候说出人名了。

NER 谷歌伯特模型

有几个关于拥抱脸的模型用于命名实体识别(NER)。我只关注其中一个——它被称为dslim/bert-large-NER.。使用它,你所需要的(除了安装之外)就是如下代码。

导入引入了一些助手对象,用于随管道引入模型。pipeline允许我指定从拥抱脸中引入什么模型。

执行前三行代码时,会自动从 Hugging Face 下载几个文件(如果您有防火墙限制,可以手动下载这些文件——如果需要,可以留下评论)。重要提示:BERT 型号为 1.3GB,下载需要一点时间。虽然您只下载一次,但是即使在下载之后,也总是需要 4-6 秒来实例化模型(您可能想要找出一种方法来将模型保存在内存中)。

pipeline设置模型以供使用,并返回一个对象,即您的“nlp”引擎。请注意,我给了对象一个字符串,我想为它获取命名实体。就像情感分析的简单例子一样,nlp对象返回一个字典列表,只是这个更大。

[{‘entity’: ‘B-PER’, ‘score’: 0.99802744, ‘index’: 3, ‘word’: ‘Jon’, ‘start’: 9, ‘end’: 12}, {‘entity’: ‘I-PER’, ‘score’: 0.9969795, ‘index’: 4, ‘word’: ‘Jones’, ‘start’: 13, ‘end’: 18}, {‘entity’: ‘B-PER’, ‘score’: 0.99703735, ‘index’: 5, ‘word’: ‘Jon’, ‘start’: 19, ‘end’: 22}, {‘entity’: ‘I-PER’, ‘score’: 0.99666214, ‘index’: 6, ‘word’: ‘Jones’, ‘start’: 23, ‘end’: 28}, {‘entity’: ‘I-PER’, ‘score’: 0.8733999, ‘index’: 7, ‘word’: ‘Jr’, ‘start’: 29, ‘end’: 31}, {‘entity’: ‘B-PER’, ‘score’: 0.9935467, ‘index’: 9, ‘word’: ‘Jon’, ‘start’: 33, ‘end’: 36}, {‘entity’: ‘I-PER’, ‘score’: 0.9749524, ‘index’: 10, ‘word’: ‘Paul’, ‘start’: 37, ‘end’: 41}, {‘entity’: ‘I-PER’, ‘score’: 0.9960336, ‘index’: 11, ‘word’: ‘Jones’, ‘start’: 42, ‘end’: 47}, {‘entity’: ‘B-PER’, ‘score’: 0.9971614, ‘index’: 12, ‘word’: ‘John’, ‘start’: 48, ‘end’: 52}, {‘entity’: ‘I-PER’, ‘score’: 0.9858689, ‘index’: 13, ‘word’: ‘D’, ‘start’: 53, ‘end’: 54}, {‘entity’: ‘I-PER’, ‘score’: 0.4625939, ‘index’: 14, ‘word’: ‘.’, ‘start’: 54, ‘end’: 55}, {‘entity’: ‘I-PER’, ‘score’: 0.9968941, ‘index’: 15, ‘word’: ‘Jones’, ‘start’: 56, ‘end’: 61}]

这是件大事

对我来说,这个 BERT 模型的特别之处在于B-PER entity。根据文档,BERT 模型可以识别几种不同类型的实体:

图片作者来自https://huggingface.co/dslim/bert-base-NER

对 B-PER 的描述有一点误导,因为 B-PER 不仅是另一个人名字之后的一个人名字的开头,它还是第一个人名字中的第一个名字。这里非常重要的一点是,B-PER 是名称列表中每个名称的分隔符。(同样的概念也适用于其他实体类型,这同样很有价值。)

请允许我剖析一下伯特的名单和 NER 实体。

作者图片

太棒了。每个实际的名字都是一个B-PER实体。然后我需要做的就是通过遍历字典将这些名字组合在一起。

输出并不完全是我想要的(很快就会变得更有意义),但是很接近:

[[[‘Jon’, ‘Jones’]], [[‘Jon’, ‘Jones’, ‘Jr’]], [[‘Jon’, ‘Paul’, ‘Jones’]], [[‘John’, ‘D’, ‘.’, ‘Jones’]]]

我可以加入这些,我就完成了,但这并不那么简单(但几乎如此)。

不寻常名字的奇怪结果

我见过的“奇怪”的事情之一(即,我不知道它为什么这样做,但可能有一个完全合乎逻辑的原因)是从 BERT 返回的一个字典条目列表,它似乎分解了不常见的名称。就拿我的姓来说吧——纽格鲍尔。

[{‘entity’: ‘I-PER’, ‘score’: 0.9993844, ‘index’: 2, ‘word’: ’N’, ‘start’: 6, ‘end’: 7}, {‘entity’: ‘I-PER’, ‘score’: 0.99678946, ‘index’: 3, ‘word’: ‘##eu’, ‘start’: 7, ‘end’: 9}, {‘entity’: ‘I-PER’, ‘score’: 0.9744214, ‘index’: 4, ‘word’: ‘##ge’, ‘start’: 9, ‘end’: 11}, {‘entity’: ‘I-PER’, ‘score’: 0.92124516, ‘index’: 5, ‘word’: ‘##ba’, ‘start’: 11, ‘end’: 13}, {‘entity’: ‘I-PER’, ‘score’: 0.82978016, ‘index’: 6, ‘word’: ‘##uer’, ‘start’: 13, ‘end’: 16}]

伯特似乎把我的名字分解成了碎片,我猜测(没有证据)这是因为变形金刚在伯特体内是如何工作的。不管什么原因,这种情况必须处理,这就是为什么我没有从上一节开始完成我的代码。

这是最后一段代码,它建立在最后一段代码的基础上,没有修改最后一段代码。

这不仅消除了不常见名称的标签,还将文本连接在一起。(句点的替换类似于“John J. Jones”中的标签和交易的替换。)

运行这段代码给了我想要的东西:

[[‘Jon Jones’], [‘Jon Jones Jr’], [‘Jon Paul Jones’], [‘John D. Jones’]]

我必须大声承认,当我第一次看到这个 run 时,我震惊地发现所有的名字都是正确的。玩得好谷歌,拥抱脸,和谁建立了伯特的名字模型。打得好。

结论和改进

我发现伯特 NER 引擎非常准确,但注意它并不总是准确,它只是更准确。但更直接的说,它标志着好和伟大的区别。

您可以通过使用分数并保留从 BERT(即 transformers)返回的开始和结束字符串位置来改进我的代码。但是,您可能需要做一些修改:

  • 分数应该是由B-PER类型分隔的名称序列中每个标记的平均分数
  • 开始是一个人序列中B-PER的开始,结束是最后 I-PER的结束

我希望你喜欢这个,并有机会与transformers一起工作。真的很了不起。我还想尽可能地尊重 spaCy 的好人们,并再次声明,我刚才展示的只是另一种做事方式(这可能会被纳入 spaCy)。

参考

[1]HuggingFace.org。(未注明)拥抱脸—AI 社区构建未来。https://huggingface.co/

[2]德夫林,雅各布和陈,刘明伟.(2018 年 11 月 2 日。)开源 BERT:最先进的自然语言处理预培训https://ai . Google blog . com/2018/11/open-sourcing-Bert-state-of-art-pre . html

[3]HuggingFace.org。(未标明) dslim/bert-base-NERhttps://huggingface.co/dslim/bert-base-NER

熊猫超市数据分析

原文:https://towardsdatascience.com/supermarket-data-analysis-with-pandas-e4991f3e0a9?source=collection_archive---------14-----------------------

熊猫综合实用指南

Photo by 卓倩 李 on Unsplash

Pandas 是 Python 中使用最广泛的数据分析和操作库。其直观和多功能的功能使得数据分析过程高效、简单且易于理解。

在本文中,我们将在 Kaggle 上的超市销售数据集上练习熊猫。它包含一家连锁超市不同分店在 3 个月内的销售数据。

让我们从导入库和读取数据集开始。

import numpy as np
import pandas as pddf = pd.read_csv("/content/supermarket.xls", 
parse_dates=['Date'])

我们使用 parse_dates 参数存储 datetime 数据类型的 date 列,这样我们就不必在以后转换数据类型。datetime 数据类型允许使用 dt 访问器下特定于日期和时间的函数。

有些列是多余的,与我们的分析无关。

  • 发票标识:唯一的发票标识号。不具备任何分析信息。
  • Cogs:单价和数量列的乘积。
  • 毛利百分比:由一个值 4.761905 组成。
  • 总收入:可以用总计栏乘以 0.04761905(即毛利率百分比)得到。
  • 城市:与分支列完全相关。每个城市有一个分支机构。

为了简化数据集,我们删除了这些列。

to_drop = ['Invoice ID', 'City','cogs', 'gross margin percentage', 'gross income']df.drop(to_drop, axis=1, inplace=True)df.head()

超市数据集(图片由作者提供)

我们应该经常检查数据集中是否有缺失值。

df.isna().sum().sum()
0

isna 函数返回数据帧,用“True”表示缺少的值。通过链接一个 sum 函数,我们可以得到每一列中缺失值的数量。第二个 sum 函数给出了整个数据帧中缺失值的数量。

我们可能对每个分公司的销售概况感兴趣。可以用 groupby 函数计算每张发票的总销售额和平均销售额。

df[['Branch', 'Total']]\
.groupby('Branch').agg(['mean','sum','count'])

(图片由作者提供)

每张发票的平均金额在 C 分公司更高。因此,尽管发票数量较少,但该分公司的总销售额高于其他分公司。

我们还可以查看每个产品线中产品的平均单价。让我们也按降序对它们进行排序,以获得更有条理的概述。

df[['Product line', 'Unit price']].groupby('Product line').mean()\
.sort_values(by='Unit price', ascending=False).round(2)

(图片由作者提供)

时尚配饰位居榜首,但平均单价彼此非常接近。

我们还可以查看这家连锁超市每周销售额的趋势。第一步是按日期对总销售额进行分组。

dates = df[['Date','Total']].groupby('Date').sum()dates.head()

(图片由作者提供)

日期数据帧包含每日销售额。为了检查每周销售额,我们需要在绘图前重新取样。一个简单的方法是使用重采样函数。

dates.resample('7D').sum().plot(figsize=(9,4))

周销售额(图片由作者提供)

重采样周期由“7D”指定,表示 7 天。我们还需要一个函数来告诉 pandas 如何在重新采样的周期中聚合值(例如,sum 或 mean)。

我们也来看看女性和男性的产品偏好。一种方法是计算每个产品线中购买的商品总数。我们首先使用 groupby 函数获取数据,然后创建一个条形图进行比较。

gender = df[['Gender','Product line','Quantity']]\
.groupby(['Gender','Product line'], as_index=False).sum()gender.head()

(图片由作者提供)

我们现在有了每个类别中男性和女性的数量。下一步是绘制它们。

import seaborn as sns
sns.set(style='darkgrid')sns.catplot(data=gender, y='Product line', x='Quantity',
            kind='bar', hue='Gender', aspect=1.6, orient='h')

(图片由作者提供)

catplot 函数是一个图形级接口,用于生成分类图。绘图类型由 kind 参数定义。

女性购买更多的时尚配饰产品,这是意料之中的。然而,我有点惊讶地看到男性在健康和美容类别中超过了女性。

基于条件筛选数据是数据分析中的典型任务。就如何过滤数据而言,Pandas 非常高效。例如,查询函数接受字符串形式的条件。当然,有一些限制,但它在许多情况下是很方便的。

我们可以使用下面的查询功能过滤总金额大于 300 且数量大于 4 的采购。

df.query('Total > 300 and Quantity > 4').shape
(393, 12)

有 393 次购买符合这些标准。

变量的分布总是为数据分析提供有价值的见解。例如,我们可以检查总销售额的分布情况。一种方法是绘制直方图,这可以很容易地用熊猫的绘图功能来完成。

df.Total.plot(kind='hist', figsize=(8,5), 
              title='Histogram of Total Sale Amounts')

(图片由作者提供)

直方图将连续变量的值范围划分为离散的条块,并计算每个条块中数据点(即行)的数量。结果,我们得到了值的分布的概况。

我们还可以根据一天中的时间段来分析销售额。例如,我们可能对发现人们是否倾向于在早上比晚上花费更多感兴趣。

为了有效地使用 pandas 的 dt 访问器下的日期和时间功能,我们应该将 time 列的数据类型转换为 datetime。

df.Time = pd.to_datetime(df.Time)

hour 方法以字符串形式返回时间的小时。我们需要将其转换为整数以用于过滤。

df[df.Time.dt.hour.astype('int') >= 20]['Total'].mean().round(2)
306.26df[df.Time.dt.hour.astype('int') <= 10]['Total'].mean().round(2)
311.10

下面详细阐述一下上面我们做了什么。dt 访问器的 hour 方法将小时提取为字符串。我们使用 astype 函数将其转换为整数,并使用它来过滤 20 年后购买的产品。最后的操作是取符合指定条件的购买的平均值。然后我们对 10 点前购买的东西做同样的处理。

结论

本文的主要目的是演示各种 pandas 函数,帮助我们分析表格数据。熊猫函数的参数非常重要,因为它们使函数更加强大和通用。因此,了解参数所能达到的效果非常重要。

我喜欢熊猫的一点是,完成一项任务几乎总是有不止一种方法。例如,我们在示例中所做的也可以用不同的方式来完成。事实上,你可以挑战自己用不同的函数做同样的事情。

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

基于 R 的超市数据分析

原文:https://towardsdatascience.com/supermarket-data-analysis-with-r-5284be9541c4?source=collection_archive---------18-----------------------

R 数据科学软件包实用指南

Photo by 卓倩 李 on Unsplash

在本文中,我们将在 Kaggle 上的超市销售数据集上练习 tidyverse,这是一个用于数据科学的 R 包集合。它包含一家连锁超市不同分店在 3 个月内的销售数据。

我以前曾使用熊猫SQL 在同一个数据集上写过文章。我认为学习如何用不同的工具完成给定的任务是一个很好的实践。它让你清楚地看到它们之间的区别和相似之处。此外,它有助于建立一种直觉,了解这些工具的创造者是如何处理特定问题的。

让我们从使用 readr 包的 read_csv 函数读取数据集开始。readr 包是 tidyverse 的一部分,用于读取矩形数据。

> library(readr)> supermarket <- read_csv("/home/soner/Downloads/datasets/supermarket.csv")> head(supermarket, 5)

超市 tibble(图片由作者提供)

readr 中的表格数据结构称为 tibble。它类似于 Pandas 中的 dataframe 和 SQL 中的 table。

注意:这是 Kaggle 上原始数据集的简化版本。我删除了分析中多余的列。

在开始分析之前,我们应该检查一下数据中是否有遗漏的值。is.na 函数可用于查找整个表或特定列中缺失值的数量,如下所示。

> sum(is.na(supermarket)) #entire tibble
[1] 0> sum(is.na(supermarket$branch)) #branch column
[1] 0

数据中没有缺失值,因此我们可以继续。

对于过滤、选择和探索等数据操作任务,我们将使用 tidyverse 的 dplyr 包。它为有效的数据分析和操作提供了几个功能。

> library(dplyr)

我们可能想了解每个分公司的销售概况。每个分店的平均销售额和销售数量可以计算如下:

> by_total = group_by(supermarket, branch)
> summarise(by_total, avg_total = mean(total), qty = n()) branch    avg_total   qty
  *<chr>*     *<dbl>*       *<int>*
1  A         312\.       340
2  B         320\.       332
3  C         337\.       328

在第一行中,观察值(即行)按分支列分组。然后,summarise 函数用于计算每个分支的 total 列的平均值,并计算每个组的观察次数。

C 支既有最高的平均金额,又有最少的销售笔数。

我们还可以查看每个产品线中产品的平均单价。让我们也按降序对它们进行排序,以获得更有条理的概述。我们首先按照 prod_line 列对行进行分组。

> by_prod <- group_by(supermarket, prod_line)

我们现在可以计算每个类别的平均单价,并根据平均值对结果进行排序。

> summarise(by_prod, avg_unitprice = mean(unit_price)) %>%
+ arrange(desc(avg_unitprice)) prod_line               avg_unitprice
  *<chr>*                           *<dbl>*
1 Fashion accessories              57.2
2 Sports and travel                57.0
3 Food and beverages               56.0
4 Home and lifestyle               55.3
5 Health and beauty                54.9
6 Electronic accessories           53.6

我们使用“%>%”将两个操作组合在一个管道中。默认情况下,arrange 函数按升序对结果进行排序。我们通过使用 desc 函数来改变这个设置。

时尚配饰位居榜首,但平均单价彼此非常接近。

我们可能想知道分支机构在一周中的某一天是否有更多的销售。让我们首先创建一个包含日期的星期几的列。我们将使用 lubridate 包的 wday 函数,这使得在 r 中处理日期和时间变得更加容易。

> library(lubridate)> supermarket <- mutate(supermarket, week_day = wday(date))

dplyr 包的 mutate 函数允许在现有列的基础上添加新列。超市 tibble 现在有一个名为 week_day 的新列。

我们可以创建一个条形图来查看每周的购买数量。下面是如何使用 tidyverse 下的 ggplot2 包创建条形图。

> library(ggplot2)> ggplot(supermarket) + geom_bar(mapping = aes(x=week_day, color=branch), fill='white', position='dodge')

我们来详细说明一下语法。ggplot 函数接受数据并创建一个空图。第二步根据给定的映射和绘图类型在图上添加一个新层。geom_bar 函数创建条形图。颜色参数根据给定列中的离散值区分这些值。

position 参数设置为“dodge ”,以便并排放置每个类别的条形。

每周一天的销售数量(图片由作者提供)

另一个重要的衡量标准是总销售额的分配。它让我们大致了解了顾客每次购物可能花费的金额。

检查连续变量分布的一种方法是创建直方图。它将值范围划分为离散的箱,并计算每个箱中的观察值(即行)的数量。

我们可以使用 ggplot2 包的 geom_histogram 函数创建如下直方图。

> ggplot(supermarket) + geom_histogram(mapping = aes(x=total, color=gender), bins=15, fill='white')

性别列被传递给颜色参数,以分别检查男性和女性的分布。箱参数设置箱的数量。

总销售额直方图(按作者分类的图片)

男性和女性总销售额的分布非常相似。

结论

本文的主要目的是演示各种 R 包,帮助我们分析表格数据。当然,我们还可以对这个数据集做更多的研究。

为了提高数据分析技能,我们要学习统计学,也要善于使用库和框架。更好地使用这些工具的最好方法是通过实践。

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

用 SQL 进行超市数据分析

原文:https://towardsdatascience.com/supermarket-data-analysis-with-sql-92c153638ad5?source=collection_archive---------9-----------------------

如何有效地使用 SQL 查询

UnsplashNeONBRAND 拍摄的照片

SQL 是一种编程语言,用于管理关系数据库中的数据,关系数据库以带有标签的行和列的表格形式存储数据。如果你打算从事数据科学领域的工作,SQL 是一个放入你的技能集的基本工具。

我们可以查询数据库来检索数据,而无需任何修改或过滤。然而,这不是一种主动或有效的方式。我们最有可能对原始数据进行一些数据处理或过滤,使其更加有用。

SQL 非常擅长数据操作和过滤操作。使用 SQL 执行此类任务的优势在于,我们只需要检索我们需要的数据,而不是一次性获取所有数据。此外,它允许在检索数据的同时进行数据分析。

在本文中,我们将分析 Kaggle 上的超市销售数据集。我对数据集做了一些修改,并通过排除一些列来简化它。我用数据集的修改版本在 MySQL 数据库中创建了一个表。

超市表格的前 5 行(图片由作者提供)

该数据集包含一家连锁超市不同分店在 3 个月内的销售详情。

注意:我用 Pandas 写了另一篇关于这个数据集的实用文章,Pandas 是一个非常流行的 Python 数据分析和操作库。

我们可能希望根据总销售额对产品类别进行排序。

mysql> select prod_line, sum(total)
    -> from supermarket
    -> group by prod_line
    -> order by sum(total) desc;+----------------------+------------+
| prod_line            | sum(total) |
+----------------------+------------+
| Food and beverages   |   56144.86 |
| Sports and travel    |   55122.88 |
| Electronic accessori |   54337.52 |
| Fashion accessories  |   54305.88 |
| Home and lifestyle   |   53861.87 |
| Health and beauty    |   49193.81 |
+----------------------+------------+

我们首先选择列并应用聚合。下一步是按产品类别对聚合列进行分组。最后,我们根据总销售额对结果进行降序排序。

客户类型和性别列可用于了解客户组合的概况。我们可以计算属于每个交叉类别的购买数量。

mysql> select cust_type, gender, count(*)
    -> from supermarket
    -> group by cust_type, gender;+-----------+--------+----------+
| cust_type | gender | count(*) |
+-----------+--------+----------+
| Member    | Female |      261 |
| Member    | Male   |      240 |
| Normal    | Female |      240 |
| Normal    | Male   |      259 |
+-----------+--------+----------+

就客户类型和性别列而言,分布相当均衡。

where 子句可以在 select 语句中实现,以便对所选行应用条件。例如,我们可以计算总金额高于 500 的平均采购量。

mysql> select avg(qty)
    -> from supermarket
    -> where total > 500;
+----------+
| avg(qty) |
+----------+
|   8.3744 |
+----------+mysql> select avg(qty)
    -> from supermarket;
+----------+
| avg(qty) |
+----------+
|   5.5100 |
+----------+

该条件应用于上面的第一个查询。第二个查询返回整个表的平均数量。

我们可以应用基于日期的条件。例如,以下查询返回 2019 年 1 月 5 日到 2019 年 1 月 7 日之间的所有销售额。

mysql> select *
    -> from supermarket
    -> where date between "2019-01-05" and "2019-01-07";

考虑我们需要找到总销售额最高的前 5 个日期。我们首先需要根据日期对销售额进行分组,因为每天都有许多采购。之后,根据总销售额对结果进行降序排序,并选择前 5 个。

mysql> select date, sum(total)
    -> from supermarket
    -> group by date
    -> order by sum(total) desc
    -> limit 5;+------------+------------+
| date       | sum(total) |
+------------+------------+
| 2019-03-09 |    7474.04 |
| 2019-02-07 |    7228.22 |
| 2019-03-14 |    7214.62 |
| 2019-02-15 |    6830.78 |
| 2019-03-02 |    6560.30 |
+------------+------------+

假设我们需要找到总金额最大的销售日期。完成这项任务有多种方法。一种是使用嵌套的 select 语句,如下所示:

mysql> select date 
    -> from supermarket
    -> where total = (select max(total) from supermarket);+------------+
| date       |
+------------+
| 2019-02-15 |
+------------+

我们使用另一个 select 语句在 where 子句中指定条件。嵌套的 select 语句返回总计列的最大值。

我们可以实现多个嵌套的 select 语句。假设我们想要找出在发生最大总金额的销售的日期发生了多少次销售。

这项任务可以分为三个部分:

  1. 找出最大的总销售额
  2. 查找总销售额最大的日期
  3. 统计这一天的销售额

下面的嵌套查询将给出我们想要的结果。

mysql> select count(*) from supermarket                # 3
    -> where date = (                                  # 2
    ->    select date from supermarket 
    ->    where total = (                              # 1
    ->        select max(total) from supermarket ));+----------+
| count(*) |
+----------+
|       19 |
+----------+

该数据集包含一家连锁超市的 3 家分店。顾客分为两类。我们可以找到这两列中每个交叉类别的平均总销售额。

mysql> select branch, cust_type, avg(total)
    -> from supermarket
    -> group by branch, cust_type
    -> order by avg(total) desc;+--------+-----------+------------+
| branch | cust_type | avg(total) |
+--------+-----------+------------+
| C      | Normal    | 337.656604 |
| C      | Member    | 336.575799 |
| B      | Member    | 325.483273 |
| A      | Member    | 321.182455 |
| B      | Normal    | 314.329341 |
| A      | Normal    | 303.831792 |
+--------+-----------+------------+

最后一行中的 order by 子句根据平均值对结果进行降序排序。

产品分为几个产品线。我们可能希望根据每个类别中售出的商品总数对产品线进行排序。

mysql> select prod_line, sum(qty) 
    -> from supermarket
    -> group by prod_line
    -> order by sum(qty) desc;+----------------------+----------+
| prod_line            | sum(qty) |
+----------------------+----------+
| Electronic accessori |      971 |
| Food and beverages   |      952 |
| Sports and travel    |      920 |
| Home and lifestyle   |      911 |
| Fashion accessories  |      902 |
| Health and beauty    |      854 |
+----------------------+----------+

它类似于前面的例子。我们选择“产品系列”和“数量总和”列。结果按产品线分组,并按数量总和排序。

我们还可以在 select 语句中实现聚合函数的组合。例如,以下查询将返回健康和美容产品系列中最贵和最便宜产品的单价之间的差异。

mysql> select max(unit_price) - min(unit_price) as diff
    -> from supermarket
    -> where prod_line = "Health and beauty";+-------+
| diff  |
+-------+
| 89.88 |
+-------+

我们选择单价列的最大值和最小值,并计算差值。“as”关键字用于为聚合列分配别名。

如果我们希望为每个产品线计算相同的差异,我们可以省略 where 子句,而使用 group by 子句。

mysql> select prod_line, max(unit_price) - min(unit_price) as diff
    -> from supermarket
    -> group by prod_line;+----------------------+-------+
| prod_line            | diff  |
+----------------------+-------+
| Electronic accessori | 89.17 |
| Fashion accessories  | 89.71 |
| Food and beverages   | 89.66 |
| Health and beauty    | 89.88 |
| Home and lifestyle   | 89.39 |
| Sports and travel    | 89.79 |
+----------------------+-------+

结论

我们已经做了几个例子来演示 SQL 如何被用作数据分析工具。它允许编写能够过滤、操作和转换存储在关系数据库中的数据的查询。

这种查询的主要优点是我们只检索我们需要的数据,这可以节省大量的内存。动态应用转换和聚合加快了数据分析过程。

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

Tableau 中的上标和下标——为什么以及如何实现它

原文:https://towardsdatascience.com/superscript-and-subscript-in-tableau-why-and-how-you-can-implement-it-764caf0cc932?source=collection_archive---------20-----------------------

让你的化学/数学方程式对用户更具可读性

Tableau dashboard Tool一直是最成功的商业数据可视化工具之一。虽然自第一次发布以来,它已经有了多个版本的修改,但缺乏实现上标/下标格式的内置规范是非常令人惊讶的,因为 Tableau 用户的一些请求或相关问题在在线论坛上仍然很常见,包括 Tableau 自己的官方平台—Tableau 社区

作者截图|左边 Tableau 社区上的帖子是从 2012 年到 2014 年连续被问的,而右边的另一个相关帖子的日期至少是最近的 2019 年

考虑到描述性数据分析是用户的主要意图,因此其用例往往与研究工作重叠——假设用户往往需要脚注参考和数学/化学符号不会太牵强;这两者都需要上标/下标符号。

虽然通常的做法是用^符号来表示上标(更多示例请参考 用纯文本电子邮件):

图片由作者提供|左等式和右等式表示相同的意思|而左等式用纯文本表示,右等式用上标表示

对于仪表板用户来说,在可视化仪表板时,用纯文本符号处理数学方程是一项额外的脑力劳动,尤其是当数学方程变得令人沮丧地冗长时

幸运的是,虽然 Tableau 没有内置的规范来显示上标/下标符号,但它支持 ASCII 字符的呈现,包括上标和下标数字符号。

图片作者| 1 我过去的 Tableau 仪表板目前部署在 Tableau Public |红色轮廓表示脚注引用的上标符号的用法

虽然您可以参考 Unicode 表获得可用的上标&下标符号的完整列表,但是我通过创建一个 JavaScript 工具让其他 Tableau 用户的生活变得更容易。在文本框中输入需要转换的字符,然后选择【转换】按钮,如下图所示:

作者图片|说明了字符输入到相应文本字段上方的指定 Unicode 字符的转换

另外,还包括了将明文转换成装饰性字体(如𝕺𝖑𝖉 𝕾𝖙𝖞𝖑𝖊 𝕰𝖓𝖌𝖑𝖎𝖘𝖍字体)的附加功能😝

可以在我的 GitHub 直接下载 HTML 文件。只需双击它,在任何支持 JavaScript 的浏览器(Chrome,Edge)中运行它,就可以了!🙃

希望您发现这很有用,如果您对数据分析或其他与 Tableau 相关的内容❤感兴趣,请关注我的 Medium

https://geek-cc.medium.com/membership

以下是您可能感兴趣的其他 Tableau 技巧&窍门(每篇文章的 Tableau 工具已部署在: Tableau 数据实用工具):

</5-lesser-known-tableau-tips-tricks-hacks-with-use-case-demo-463f98fbdc7e>

监督学习算法连接解释

原文:https://towardsdatascience.com/supervised-learning-algorithm-connections-explained-733d2353b7ee?source=collection_archive---------15-----------------------

图片作者。

机器学习模型嵌套——从维恩图到回归、决策树、支持向量机&人工神经网络

你有没有想过复杂的机器学习技术是如何问世的?纯天才还是多年迭代的产物?让我们采用第二种选择,因为它会让我们都感觉好一些。更重要的是,它将帮助我们成为更好的机器学习实践者。

“如果说我看得更远,那是因为我站在巨人的肩膀上”——艾萨克·牛顿,1675

在这篇文章中,我将解释监督机器学习技术是如何联系在一起的,简单的模型嵌套在更复杂的模型中,它们本身嵌入在更复杂的算法中。接下来的将不仅仅是模型的备忘单,不仅仅是监督方法的年表,它将用文字、方程和图表解释机器学习技术的主要家族之间的关系以及它们在偏差-方差权衡难题中的相对位置。

注意:关于无监督学习的例子,参见我的另一篇文章“从零开始的混合建模”,见 R 。

嵌套模型的示例:错误的概率密度< Linear regression < Logistic regression < Feedforward neural network < Convolutional neural network (see text for details). Source: Russian doll photo by cottonbro 来自 pexels ,由作者修改(文本添加在裁剪版本上)。

从维恩图到最简单的机器学习模型

图片作者。

重构机器学习技术的历史让我们回到概率论。概率论可以从 Kolmogorov 公理或简单地从文氏图中推导出来。麦克道尔的《破解编码访谈》对此做了最好的解释。我们有两个事件 A 和 b,两个圆圈的面积代表它们的概率。重叠的区域就是事件{A 和 B}。我们直接得到 P(A 和 B) = P(A)×P(B 给定 A ),因为我们需要事件 A 发生以及事件 B 给定 A 已经发生。A 和 B 可以互换,所以我们也有 P(A 和 B) = P(B)×P(A 给定 B)。瞧,我们通过结合两个关系得到贝叶斯定理😛(A | B)= P(A)×P(B | A)/P(B)。自然,朴素贝叶斯分类器也随之而来。

现在,事件{A 或 B}的概率是多少?在维恩图上,我们观察到它是 A 的面积和 B 的面积之和,然而,为了避免重复计算重叠面积,我们有 P(A 或 B) = P(A) + P(B)-P(A 和 B)。正如我们现在将发现的,两个逻辑关系 AND 和 OR 导致二项式分布,然后导致正态分布,这将是线性回归的基础。

让我们深入探讨一下。二项式分布采用以下形式

在使用二项式系数的 n 次独立伯努利试验中,准确获得 k 次成功的概率是多少

由帕斯卡三角形描述(见上图)。乍一看,这看起来很复杂。然而,它可以很容易地从文氏图中推导出来。独立伯努利试验意味着事件 a 和 b 是独立的,因此 b 不以 a 为条件,a 也不以 b 为条件。从上面可以得出,P(A 和 B) = P(A)×P(B),或者,在本实验中,P(A k 次,而不是 A ( n - k )次,它等于 p^k 次(1- p )^( n 如果我们拿一个硬币来说,有 k 正面(事件 A)和 n - k 反面(事件 B,即不是 A),这种事件有不同的实现方式,用二项式系数来表示。举例来说,假设在 3 次试验中成功了 2 次,我们可能有{H,H,T},{H,T,H}或{T,H,H}。所有那些路径都是互斥的,给出 P(A '或 B') = P(A') + P(B '),或者 3 乘以 p^k 乘以(1-p)^(n-k),这就是二项分布!假设 n 足够大,则正态分布

是具有均值 np 和方差 np (1- p )的二项分布的良好近似(演示不在这篇短文的范围之内)。

n 和小 p 的二项分布(离散)和正态分布(连续)。图片作者。

机器学习和统计的主力是线性回归

为了训练该模型,要最小化的误差函数是残差平方和(观察值和预测值之间的差)。正是高斯在 19 世纪早期成功地将最小二乘法与概率原理和正态分布(具有剩余高斯误差)联系起来。正态分布和线性回归之间的联系在线性回归的概率公式中变得很清楚:

请注意我们是如何从一个简单的维恩图达到这个阶段的!

噪声服从正态分布的线性回归。图片作者。

基于熵的决策树概念。图片作者。

让我们回到概率论来发展我们成长之树的另一个分支(在这个隐含的剧透中没有双关语;参见下面的图表)。香农在 1948 年将 H 定义为-p_i×log_2[p_i]之和,这是一个纯度的度量(也是一个惊奇的度量)。上两节课 y =(🔴,🔵),集合的熵{🔴,🔴,🔵,🔵,🔴}为增加 x 为-p(🔴)×log_2[p(🔴)]-p(🔵)×log_2[p(🔵)]或者这里-3/5×log _ 2[3/5]-2/5×log _ 2[2/5]≈0.97,非常不纯(集合纯时熵从 0 到相反情况下的 1)。然后决策树包括在给定的 x 处进行分裂,使得 2 个子集的组合熵最小化,这是在{{🔴,🔴}, { 🔵,🔵,🔴}}.这是通过信息增益的概念来实现的,信息增益是集合熵减去划分子集的熵的加权和。这里,0.97-(2/5×[-1×log _ 2(1)]+3/5×[-1/3×log _ 2(1/3)-2/3×log _ 2(2/3)])≈0.42,这表明由分裂造成的熵的实质性减少。为了清楚起见,决策树分裂的目标是最大化信息增益。这在 Provost & Fawcett 的书《商业数据科学》中有很好的解释。从那里,通过 bagging(通过 bootstrapping)和 boosting,可以开发一组基于决策树的技术,包括随机森林Boosted 树

嵌套监督学习模型-第一部分。作者图片。

从线性回归到其他一切!

现在让我们从线性回归分支展开进化树。首先,结合线性回归和贝叶斯定理产生了几种机器学习技术。这在墨菲 2012 年的“机器学习的概率视角”中有很好的描述。让我们首先将贝叶斯定理改写为 P(模型|观测值)= P(模型)×P(观测值)/ P(观测值),或者换句话说,后验概率等于先验概率乘以似然概率,用边际函数归一化。线性回归以前被形式化为一个似然函数,忽略了均匀先验。正则化技术(最小化过度拟合)包括在模型的情况下从均匀先验分布移动到正态先验分布,在套索模型的情况下移动到拉普拉斯先验分布。这些技术对非线性回归特别有用;因此,让我们添加基函数展开的概念,以从线性回归移动到非线性回归,例如使用多项式回归:

随着

下图说明了多项式回归以及通过山脊和套索进行正则化的作用。

由脊或套索调整的过拟合多项式回归。图片作者。

最大边缘超平面和分离两类的 SVM 的边缘。图片作者。

仍然有两个机器学习家族要从线性回归中定义:支持向量机和人工神经网络。支持向量机 (SVM)是一个线性模型,它通过一个所谓的最大间隔超平面将两个类别分开,最大间隔超平面可以写成满足以下等式的点集 x :

将两类数据分开以使它们之间的距离尽可能大的两个平行超平面被定义为

叫做利润。不用深入 SVM 的细节,我们马上就能看到它与线性回归的联系。

回想一下,线性回归被定义为正态分布的可能性。如果我们现在用伯努利分布(二项式分布的特殊情况)代替正态分布,我们得到逻辑回归:

这里,在 sigmoid 函数中实现线性回归,以确保结果本质上是概率性的,即在 0 和 1 之间,具有类别而不是连续值。

图片作者。

现在,逻辑回归类似于一个人工神经元,连接几个神经元导致人工前馈神经网络。不同的特征排列和网络架构最终导致卷积神经网络递归神经网络等深度学习模型。

图片作者。

嵌套监督学习模型-第二部分。图片作者。

监督学习的进化树

既然已经描述了所有的连接,让我们在最后一张图中概括所有的内容。就像生命的进化树一样,我们现在可以清楚地看到有监督的机器学习模型的嵌套。它有助于我们理解不同技术之间的联系,但最重要的是,它为我们在探索偏差/方差权衡时测试哪一系列模型提供了一些指导。

作为进化树的嵌套监督学习模型。图片作者。

参考

[1] G.L .麦克道尔,《破解编码访谈》(2015),第 6 版。,CareerCup,687 页。

[2] K.P .墨菲,《机器学习的概率视角》(2012),麻省理工学院出版社,1104 页

[3] F. Provost & T. Fawcett,《商业数据科学》(2013 年),奥赖利媒体,414 页

监督学习算法备忘单

原文:https://towardsdatascience.com/supervised-learning-algorithms-cheat-sheet-40009e7f29f5?source=collection_archive---------10-----------------------

你应该知道的所有监督机器学习算法的完整备忘单,包括优点、缺点和超参数

监督机器学习算法的本质。作者图片

本文提供了不同的监督学习机器学习概念和算法的备忘单。这不是一个教程,但它可以帮助你更好地理解机器学习的结构,或者刷新你的记忆。

要了解更多关于特定算法的信息,只需谷歌一下或者在 sklearn 文档 中查找。

接下来,将回顾或提及以下算法:

  • 线性回归
  • 逻辑回归
  • 支持向量机
  • k-最近邻
  • 决策树
  • 装袋粘贴
  • 随机森林多余的树木
  • 增压
  • 堆垛混合

这篇文章卷帙浩繁,不建议你一次看完。将这篇文章添加到阅读列表中以便稍后回来,通过 GitLab 阅读章节或下载这篇文章的 pdf 版本并打印出来(可在同一位置获得)。

https://gitlab.com/Winston-90/supervised_algorithms

介绍

监督学习是基于示例输入输出对学习将输入映射到输出的函数的机器学习任务。监督学习算法分析训练数据并产生推断的函数,该函数可以在以后用于映射新的示例。

最受欢迎的监督学习任务是回归分类

解决回归任务的结果是一个可以进行数值预测的模型。例如:

  • 房地产价值预测
  • 预测贵公司明年的收入

解决分类任务的结果是一个可以进行分类预测的模型。例如:

  • 垃圾邮件检测
  • 新闻文章分类
  • 根据验血预测患癌概率(0 到 1 之间)。

分类与回归。作者图片

分类算法也可以分为:

  • 硬分类算法预测数据点是否属于特定类别,而不产生概率估计
  • 软分类算法反过来也估计了类别条件概率

分类算法也可以按照要分类的类的数量来划分:

  • 二元分类——只有两类。
  • 多类分类 —两个以上的类。
  • 多标记分类(multi label-multi class)——多个类,但类是二元的(图像中人的存在)。结果— [0,0,1]或[1,0,1]。
  • 多输出分类 (Multioutput-multiclass)又称多任务分类 —多个类,但类不是二进制的(预测项数)。结果— [5,0,1]或[7,0,0]。

有些算法是专为二元分类问题设计的(例如 SVM )。因此,它们不能直接用于多类分类任务。相反,可以使用启发式方法将多类分类问题分成多个二进制分类数据集,并分别训练一个二进制分类模型:

  • OvR(one-vs-rest)——有时OvA(one-vs-all)——你必须为 N 个类训练 N 个分类器,但是是在完整的数据集上。
  • OvO (一对一)——你必须为 N 个类训练 N*(N-1)/2 个分类器,但是是在你的数据集中的子样本上。更适合不平衡的数据。

注意,除了线性回归(仅回归)逻辑回归(仅分类)之外,所有接下来的算法都解决分类和回归任务

简单的算法

我使用短语简单算法并不是指它们实现起来简单(尽管它们中的一些确实很简单),而是指这些是独立的算法,而不是我们稍后将看到的集成学习

线性回归

在最简单的情况下,回归任务是通过数据点画一条线,使得这条线(预测)和真实值之间的误差最小。一般来说,这是最小化损失函数的问题,所以优化问题。通常损失函数是 MSE —均方误差(因为最大似然估计),优化算法是梯度下降。总之,可以使用优化算法的任何其他损失函数。

线性回归的一个重要特性是,最优参数(根据 MSE ,同样是因为最大似然估计)可以用简单的正态方程计算出来。但是这种方法不能很好地适应大量的特征,因此可以应用任何其他优化方法来代替。

如果数据相关性比直线更复杂,我们可以添加每个特征的幂作为新特征(可以使用来自 sklearn多项式特征类),然后训练线性回归模型。这种技术被称为多项式回归。创造新特征的过程(如 xⁿ,或 log(x),eˣ等)。)被称为特征工程,可以显著提高线性模型性能。

这种算法的另一个流行版本是贝叶斯线性回归,它通过建立置信区间,不仅预测数值,还预测概率。多亏了贝叶斯定理,这才成为可能。

避免过度拟合和离群值影响回归的最有效方法之一是正则化。正则化项被添加到损失函数中,因此回归系数必须尽可能小。

  • 套索回归 —实现 L1 正则化,+ |coeff|。
  • 岭回归 —实现 L2 正则化,+ coeff。又称吉洪诺夫正规化
  • 弹性网络回归 —实现 L1 和 L2 正则化。

正则化回归也可以像特征选择工具一样使用。例如,由于某些属性,LASSO 回归可以删除无关紧要的要素(将其系数设置为零)。

如前所述,线性回归只解决回归任务

主要超参数:

  • 特征工程特征选择
  • 正则化类型和参数
  • 求解器—优化算法

优点:

  • 参数少,学习速度快
  • 可使用随机梯度下降进行配置,无需将所有样本存储在存储器中,并可用于在线学习
  • 比复杂的模型更容易解释
  • 非常适用于具有少量数据点和大量要素的问题
  • 非常适合稀疏数据

缺点:

  • 复杂依赖关系恢复不佳
  • 需要数据预处理

逻辑回归

与线性回归模型一样,逻辑回归(也称为 logit regression )计算输入要素(加上偏差)的加权和,但它不是直接输出该结果,而是输出结果的逻辑逻辑是一个 sigmoid 函数,它输出一个介于 0 和 1 之间的数字,因此逻辑回归是一个软二元分类器,它估计实例属于正类的概率。根据某些阈值,可以获得不同的准确度/召回率值。可以使用与线性回归中相同类型的正则化。

乙状结肠函数。公共领域

非常相似的概率单位回归使用了稍微不同的函数——概率单位函数,而不是 sigmoid。

可以将逻辑回归模型推广到直接支持多个类别,而无需训练多个分类器。这被称为 Softmax 回归(或多项逻辑回归)。该模型计算每个类别的分数,然后通过应用 softmax 函数(也称为归一化指数)来估计每个类别的概率。

如前所述,逻辑回归只解决分类任务

基于线性回归,因此继承了该算法的所有超参数、优点和缺点。需要单独说明的是,该算法的解释水平较高,因此通常被广泛用于信用评分任务和医疗诊断

支持向量机

支持向量机算法基于支持向量概念——极值点(图中用黑色圈出)。

支持向量。公共领域

分类任务的情况下,它试图在类别之间画一条分隔线,使得支持向量位于离这条线尽可能远的地方(在一般情况下是分离超平面):

  • 硬边界分类 —假设相同类别的实例无例外地位于分离超平面的同一侧。
  • 软边界分类-允许违反决策边界,由正则化参数控制。

回归任务的情况下,相反,它试图画一条线来适应边界内尽可能多的实例,“在街上”。

由于 SVM 要求计算点与点之间的距离,它也要求特征缩放

SVM 最重要也是数学上最优雅的特征是,对偶问题(这是 SVM 的基础)的解不直接依赖于特征(作为向量),而只依赖于它们的两两标量积。这就允许我们用某个函数 k(a,b) 来代替标量积,这个函数叫做内核。事实上,内核是另一个空间中的标量积。这个过程允许你在不增加新特征的情况下建立非线性分类器(在更大的维度空间中实际上是线性的),被称为内核技巧

不同内核的使用允许该算法在分类回归任务中恢复非常复杂的相关性。最受欢迎的内核是:

  • 多项式
  • RBF —高斯径向基函数
  • 乙状结肠和其他

具有不同内核和默认参数的 SVM。作者图片

一级 SVM 也可以用于异常检测问题。

主要超参数:

  • 内核类型
  • 正则化参数 C——对每个错误分类的数据点的惩罚(通常为 0.1 < C < 100)
  • regularization parameter gamma — controls regions separating different classes. Large gamma leads to too specific class regions (overfitting). (usually 0.0001 < gamma < 10)

赞成):

  • 最强大和最灵活的模型之一
  • 由于线性模型继承了线性回归的优点

缺点:

  • 需要数据预处理
  • 它适用于许多要素,但不适用于样本,因此仅适用于小型和中型数据集

k-最近邻

最近邻算法作为度量方法的代表,对数据分布做了两个假设:

  • 回归的连续性假设——相近的对象对应相近的答案,并且
  • 分类的紧密性假设——接近的对象对应同一类。

对于一个新的对象,我们必须找到 k 个最近的邻居。最近的的定义取决于我们想要使用的距离度量(曼哈顿、欧几里德等。).

k-最近邻算法。结果可能因 k. 公共域而异

最重要的超参数是相邻点的数量——k。k 的一个好的初始近似值是将 k 设置为数据点数的平方根,但是,当然,k 可以通过交叉验证找到。分类然后根据每个点的最近邻居的简单多数投票计算,回归——根据每个点的最近邻居的平均值。

主要超参数:

  • k —邻居的数量
  • 距离度量

优点:

  • 懒惰学习——我们只需将数据载入内存
  • 简单解读
  • 简单实现

缺点:

  • 需要数据预处理
  • 复杂的依赖关系恢复不佳(高度重叠数据的分类)
  • 任何度量算法在处理稀疏的高维数据时都表现不佳
  • 由于任何基于实例的算法都必须将所有训练数据存储在内存中

决策树

在每一步,训练集被分成两个(或更多)部分,这取决于特定的选择。通常,树构建算法是贪婪,这意味着,它们在特定步骤寻找局部最优解。构建树的常用算法有:

  • ID3 (最古老的算法之一,迭代二分法 3 是由罗斯·昆兰发明的),
  • C4.5,c 5.0(ID3 算法的扩展,它们是由同一个人开发的,并且在于在使用 ID3 之后修剪树),
  • CART ( 分类和回归树针对分类(基尼系数作为度量)和回归( MSE 作为度量)树进行了优化,并在 scikit-learn 中实现。

决策树分类器和回归器。作者图片

使用上述示例决策树分类器的决策树结构。作者图片

可以使用不同的方法来计算信息增益。然后决策树算法使用信息增益来拆分特定节点:

  • ——无序的一种度量。
  • 基尼杂质

所谓的决策树剪枝比单纯限制树的长度更能说明问题。这是当我们建立一个完整深度的树时的过程,在此之后,我们移除树的无关紧要的节点。然而,这一过程需要更多的资源。

主要超参数:

  • 树的最大深度:越小-过度拟合越小,通常为 10–20
  • 一个叶中的最小对象数:越大-过度拟合越少,通常为 20+

优点:

  • 简单解读
  • 简单实现
  • 计算简单性
  • 不需要特征预处理,可以处理缺失值
  • 可以使用信息增益来计算特征重要性

缺点:

  • 不稳定且易变(对贪婪算法的研究)-输入数据的微小变化会完全改变树的结构
  • 对训练集的内容和噪声高度敏感
  • 复杂(非线性)依赖关系的恢复较差
  • 在树的较大深度处过度拟合的趋势
  • 与线性模型不同,它们不是外推的(它们只能预测从训练集的最小值到最大值范围内的值)

集成方法

集成方法(也称为集成学习)是创建多个模型,然后将它们组合起来以产生改进结果的技术。集合方法通常比单一模型产生更精确的解。

制袋材料

装袋代表引导汇总

当我们有一个训练集X_train (N x M) N data points and M features时,我们在X上训练n个模型,其中X (N x M)X_train的一个相同大小的随机子样本。当X成型时带替换的算法称为装袋,当X成型时不带替换的算法称为粘贴。当这个模型进行预测时,实际上,它从n个不同的模型中获得n个预测,并汇总它们。分类通过模型的简单多数投票计算,回归通过模型预测的平均值计算。

装袋。作者图片

粘贴最初是为大数据集计算能力有限时设计的。另一方面,Bagging 可以多次使用相同的子集,这对于较小的样本量非常有用,它提高了稳健性。

这种方法允许保持相同的偏差,但是由于中心极限定理而减少了方差。算法的变量越多,其预测的相关性就越低,因此,CLT 的效果就越好(决策树是一个很好的选择)。

如果我们使用装袋,有可能一个样本永远不会被选中,而其他样本可能会被多次选中。一般来说,对于一个大数据集,37%的样本从未被选择,我们可以用它来测试我们的模型。这被称为出袋得分,或 OOB 得分

主要超参数:

  • 型号类型
  • n_estimators —集合中模型的数量
  • max _ samples 从训练集中获取的用于训练每个基本模型的样本数
  • max _ features 从训练集中提取的用于训练每个基础模型的特征数

优点:

  • 质量非常好
  • 训练过程可以简单地并行化,因为模型相互独立地学习
  • 不需要特征预处理和特征重要性的内置评估(在树的情况下)
  • 抗过度配合
  • 抵抗异常值
  • OOB 评分允许使用完整数据集,而无需将其分为训练和验证

缺点:

  • 解释的复杂性
  • 无法很好地处理大量要素或稀疏数据
  • 训练和预测速度明显慢于线性模型

随机森林

尽管装袋可以应用于所有类型的算法,但是装袋超过决策树已经变得很普遍。因为它们是不稳定的和可变的,所以获得了好的结果。实际上,随机森林就是用随机子空间方法对决策树进行打包。

当我们有一个训练集X_train N x M (N data points and M features)时,我们在X上训练n树,其中X (N x m)是带有替换的X_train的随机子样本,但是我们也取m (m < M)特征的随机子集。这被称为随机子空间方法。当这个模型进行预测时,实际上,它从n个不同的模型中获得n个预测,并汇总它们。分类通过模型的简单多数投票计算得出,而回归通过模型预测的平均值计算得出。

这种方法允许保持相同的偏差,但是由于中心极限定理而减少了方差

如已知的隔离森林算法也可用于异常检测问题。

继承套袋的利弊

主要超参数:

  • n _ estimators——集合中树的数量——越多越好
  • max_features —从训练集中提取的特征数,用于训练每个基树—建议使用n/3进行回归,使用sqrt(n)进行分类
  • max _ depth 树的最大深度
  • min_sample_leaf —分割内部节点所需的最小样本数

额外的树

额外的树与广泛使用的随机森林算法有关。

  • 与 bagging 和 random forest 从训练数据集的引导样本中训练每个决策树不同,额外树算法在整个训练数据集上训练每个决策树。
  • 像随机森林一样,额外树算法将在决策树的每个分裂点随机采样特征
  • 与随机森林使用贪婪算法选择最佳分割点不同,额外树算法随机选择分割点

它通常可以实现与随机森林算法一样好或更好的性能,尽管它使用更简单的算法来构建用作集成成员的决策树,因此工作更快

继承所有超参数,随机森林的利弊

助推

A boosting 是顺序训练的弱算法(预测精度略好于随机算法)的集合,每个后续算法考虑前一个算法的误差。

助推。作者图片

升压的一般思想可以以不同的方式实现。三种最受欢迎的升压类型是:

  • AdaBoost

AdaBoost 代表自适应增压。这是一个贪婪的迭代算法。在每一步,它识别错误分类的数据点,并调整权重以最小化训练误差。
这个版本的 boosting 对异常值很敏感。

  • 梯度推进

梯度推进也叫梯度推进机— GBM 。与任何升压实现一样,在每一步,该算法都试图最小化前面步骤中产生的误差。但是 GBM 不是改变权重(像 AdaBoost),而是根据前一个模型的残差训练下一个模型。GDM 的实现之一是 LightGBM

  • XGBoost

XGBoost 代表极限梯度提升。这种实现旨在提高速度和性能,它与 GPU 和 Hadoop 并行工作。XGBFIR 是一个非常棒的 XGBoost 特性重要性分析库。

由于 boosting 的主要实现仍然使用决策树作为基本模型,因此 boosting 与随机森林一样,决定了特征的重要性。但是 boosting 的流行创造了许多允许您进行更详细分析的库(例如,XGBFIR 库允许您不仅分析一个特性的重要性,还可以分析它们的双重甚至三重组合)。

主要超参数:

  • 模型的类型及其相互作用的方式

优点:

  • 质量非常好,通常比随机森林好
  • 功能重要性的内置评估

缺点:

  • 学习比随机森林慢,因为学习过程必须严格按顺序进行(尽管像 XGBoost 或 LightGBM 这样的实现对此有争议)
  • 倾向于过度拟合
  • 仅适用于足够大的数据集

堆垛

堆叠模型的架构涉及两个或更多基础模型,通常称为0 级模型,以及一个组合了基础模型预测的元模型,称为1 级模型

  • 0 级模型(基础模型):训练数据被分成K个折叠。然后K个模特在K-1上训练折叠。
  • 一级模型(元模型):学习如何以最佳方式组合基础模型预测的模型。

堆叠。作者图片

与增压的区别:

  • 与装袋不同,在堆叠中,模型通常与不同(例如,并非所有决策树)。
  • 与增强不同,在堆叠中,使用单个模型来学习如何最好地组合来自贡献模型的预测(例如,代替校正先前模型的预测的模型序列)。

使用一个简单的线性模型作为元模型通常会给叠加起一个通俗的名字混合

主要超参数:

  • 模型的类型及其相互作用的方式

优点:

  • 在没有其他帮助的情况下提高模型的质量
  • 允许您有效地混合不同类别的模型,结合它们的优势
  • 帮助你在 Kaggle 上赢得金牌

缺点:

  • 高计算复杂度
  • 解释的复杂性
  • 很容易出现信息泄露
  • 仅适用于足够大的数据集

结论

这里描述了最流行的监督学习算法(当然,还有其他算法)。总之,我想描述选择一种算法来解决一个典型的监督学习任务(分类或回归)的过程。很简单——你只需要回答两个问题。

你的数据稀疏吗?如果是,那么你将不得不使用线性方法。这通常是一个 SVM ,使用不同的内核,它将允许你恢复复杂的依赖关系。请记住,线性方法需要数据预处理,这在某些情况下可能会有问题。

如果你的数据密集,那么你就比较幸运。现在一切都取决于他们的数量。如果有很多,那就用一个助推,否则——随机森林。这两种算法都很强大,抗噪声,会给你看很好的质量,但是需要很长时间的学习和预测。此外,请记住,升压容易过度拟合。

算法选择框图。作者图片

大量数据是什么意思?多少钱?通常,谈论一个阈值 10 万个样本,但是无论如何,你可以(并且很可能会)尝试不同的算法。

这只是一个建议,您应该使用不同的超参数尝试不同的算法,以最佳方式解决您的任务。

您可能还对以下内容感兴趣:

感谢您的阅读!

  • 我希望这些材料对你有用。在 Medium 上关注我获取更多类似的文章。
  • 如果您有任何问题或意见,我将很高兴得到任何反馈。在评论里问我,或者通过 LinkedIn 或者 Twitter 联系。
  • 为了支持我作为一名作家,并获得数以千计的其他媒体文章,使用我的推荐链接获得媒体会员资格(不收取额外费用)。

参考

[1] Aurélien Géron,使用 Scikit-Learn、Keras 和 TensorFlow 进行机器学习,第二版 (2019),奥赖利媒体公司

监督、半监督、非监督和自我监督学习

原文:https://towardsdatascience.com/supervised-semi-supervised-unsupervised-and-self-supervised-learning-7fa79aa9247c?source=collection_archive---------2-----------------------

揭开每个学习任务的神秘面纱

指数数量的研究和出版物在机器学习领域引入了许多术语和概念,但其中许多已经退化为仅仅是时髦的词汇,人们没有完全理解它们的差异。

本文揭示了机器学习领域的四个核心机制——监督、半监督、非监督和自我监督学习——并讨论了解决这些问题的几个示例/方法。尽情享受吧!

监督学习

图一。监督学习图解。作者使用来自 Unsplash 的资源制作的图像。

最常见的,也许是我们在谈论机器学习时提到的类型是监督学习。

简而言之,监督学习提供了一组输入输出对,这样我们就可以学习一个将输入映射到正确输出的中间系统。

监督学习的一个简单例子是基于图像及其对应类别的数据集来确定图像的类别(即,狗/猫等),我们将图像及其对应类别称为它们的标签。

对于给定的输入-标签对,当前流行的方法将是直接训练深度神经网络(即,卷积神经网络)以从给定图像输出标签预测,计算预测和实际正确答案之间的可区分损失,并通过网络反向传播以更新权重来优化预测。

总的来说,监督学习是最直接的学习方法,因为它假设给定了每个图像的标签,这简化了学习过程,因为网络更容易学习。

半监督学习

图二。半监督学习图解。图片由作者利用来自 Unsplash 的资源制作。

虽然监督学习假设要在任务上训练的整个数据集对于每个输入都有相应的标签,但现实可能并不总是这样。贴标签是一项劳动密集型的处理任务,输入数据通常不成对。

半监督学习旨在解决这个问题:我们如何使用一小组输入-输出对和另一组仅有的输入来优化我们正在解决的任务的模型?

回头参考图像分类任务,图像和图像标签现在仅部分存在于数据集中。是否有可能在没有任何标签的情况下仍然使用这些数据?

简而言之,是的。事实上,有一个叫做伪标签的简单方法可以做到这一点。首先,我们使用具有正确标签的图像来训练分类模型。然后,我们使用这个分类模型来标记未标记的图像。然后,来自模型的具有高置信度标签的图像将被添加到模型中,它们的预测标签作为伪标签用于继续训练。我们重复这个过程,直到所有的数据都被用于最佳分类模型。

当然,这种方法虽然看起来很聪明,但很容易出错。如果标记数据的数量非常有限,则模型很可能过度拟合训练数据,并在早期阶段给出错误的伪标签,从而导致整个模型完全错误。因此,决定置信度阈值以将输入伪标签对包括到训练中也是非常重要的。

为了避免在早期阶段模型过度拟合,还可以采用数据扩充技术来增加训练规模并创建更广泛的数据分布。如果有兴趣,也可以参考我的文章 mixup 作为图像分类任务最占优势的增强策略之一。

无监督学习

图 3。无监督学习的图解。作者使用来自 Unsplash 的资源制作的图像。

现在我们已经了解了如何使用最小标签进行训练,我们可以更进一步考虑:一个完全没有标签的数据集。

无监督学习处于光谱的另一端,只有输入数据没有相应的分类或标记。目标是找到每个数据集的潜在模式。

涉及无监督学习的任务包括客户细分、推荐系统等等。然而,一个人如何在没有任何标签的情况下学习任何东西?

因为我们没有每个输入标签的“正确答案”,所以找到一个模式的最好方法是对它们进行聚类。也就是说,给定一组数据特征,我们试图找到彼此相似的特征,并将它们分组在一起。一些聚类方法包括 K-Means 和 K-Medoids 方法。

仅仅是聚类实际上可能会产生许多见解。以推荐系统为例:通过根据用户的活动对他们进行分组,人们可以向其他用户推荐一个用户喜欢的内容,而无需明确了解每个用户的兴趣是什么。

自我监督学习

图 4。自我监督学习图解。作者使用来自 Unsplash 的资源制作的图像。自我监督学习与无监督学习非常相似,除了自我监督学习旨在处理传统上由监督学习完成的任务。

现在到了棘手的部分。看起来我们已经涵盖了学习的所有方面,那么什么是自我监督学习呢??嗯,答案可能比你想象的要简单!

自我监督学习在某种意义上是一种无监督学习,因为它遵循没有给定标签的标准。然而,自我监督学习不是寻找用于聚类的高级模式,而是试图在没有任何可用标记的情况下仍然解决传统上由监督学习(例如,图像分类)针对的任务。

乍一看,这似乎是不可能的,但最近的许多研究已经提出了创造性的和有趣的技术来学习这一点,其中之一是臭名昭著的积极和消极的对比学习。

简而言之,在相同的图像上执行增强,并将它们标记为正对,将不同的图像标记为负对,并且试图推开负对的学习特征,同时拉近正特征。这使得网络能够学习对相似类别的图像进行分组,这进一步使得像分类和分割这样原本需要固定标签来学习的任务在没有给定地面事实的情况下变得可能。

测试每个概念

如果你想亲自体验个别概念,你可以检索任何数据集,并亲自移除部分或全部标签,以测试每种学习方法。

需要注意的一点是,如果你直接从 torchvision 检索数据集,他们已经为你预定义了标签,如果你想测试半监督或自我监督学习,下载并编写自己的数据加载器会更好。我发现一个对检索数据集特别有用的地方是 Graviti 开放数据集。有这么多不同的数据集和论文,通常很难理解使用什么数据集。开放数据集平台组织了所有受欢迎的数据集,以便您可以轻松找到它们并重定向到它们的官方网站。他们目前也在致力于提供一个好的 API 来帮助简化设计数据加载器的过程,我相信这对未来的使用会很有帮助。

我个人建议在需要较少计算能力的 MNIST 或 CIFAR-10 数据集上进行测试。如果你有一台笔记本电脑,他们会更容易训练。

要阅读的附加论文

有关自我监督学习的更多论文和技术,您也可以参考来自 paperswithcode 的论文,其中包括当前的基准和最先进的方法。

结论

现在你知道了!希望在这篇文章之后,你会知道监督、半监督、无监督和自我监督学习之间的细微差别。玩得开心,不断学习!

谢谢你能走到这一步🙏 我会在计算机视觉/深度学习的不同领域发布更多内容,所以 加入并订阅 如果你有兴趣了解更多!

监督与非监督学习

原文:https://towardsdatascience.com/supervised-vs-unsupervised-learning-bf2eab13f288?source=collection_archive---------5-----------------------

讨论机器学习中监督学习、无监督学习和半监督学习的主要区别

Gert RDA valasevi itUnsplash 上拍摄的照片

简介

在机器学习领域,有两种基本的学习类型,即监督的非监督的方法。现在,根据我们想要解决的问题、我们需要回答的问题以及我们可以访问的数据,我们需要选择合适的学习算法。

因此,整个学习过程依赖于对上述问题的回答。鉴于这些答案可能会有所不同,在选择特定的学习算法之前,我们首先需要明确什么样的学习类型适合我们试图解决的问题的性质。

监督学习

在监督学习中,感兴趣的数据集包含解释变量(也称为输入特征)以及目标响应(也称为输出 标签)。这种算法试图学习一个函数,该函数以某种方式近似特征值和标签之间的关系,它能够很好地将推广到新的看不见的数据。

换句话说,监督学习算法将训练样本的输入特征与相应的输出标签相关联,以便它们能够对所有可能的输入执行足够好的预测。这种学习方法也被称为从范例中学习

需要监督学习方法的问题可以进一步分组为 分类回归 问题。前者是输出变量(标签)对应一个类别时;例如垃圾邮件与业余电子邮件,而后者是当输出变量是一个真实值时;例如距离或价格。

监督学习-来源:作者

监督学习算法的一些例子包括线性回归、随机森林、决策树和支持向量机。

无监督学习

另一方面,无监督学习适用于需要算法来识别和提取输入之间的相似性的问题,以便可以将相似的输入分类到一起。与监督学习相反,当输出变量(即标签)是而不是 时,非监督学习方法是合适的,前提是

无监督学习方法的两种基本类型是聚类密度估计。前者(可能是最常用的)涉及需要将数据分组到特定类别(称为集群)的问题,而后者涉及汇总数据的分布。

无监督学习—来源:作者

无监督学习算法的一些例子包括 K-均值聚类、主成分分析和分层聚类。

半监督学习

现在还有另一种称为半监督的学习类型,当我们没有训练数据集中所有例子的目标标签时,它就派上了用场。因此,这类问题需要监督和非监督学习技术的混合。

需要这种方法的一个非常常见的问题是图像分类或对象检测。通常,包含图像的数据集可能仅具有所包括的示例子集的标签,而其余的则根本没有标签。

最后的想法

在今天的文章中,我们讨论了两种基本的机器学习方法之间的主要区别,即监督学习和非监督学习。

总之,当可用的数据集包含每个示例的特征和正确标签时,监督学习方法是有用的。当我们想要对感兴趣的数据进行某种预测时,例如对一封电子邮件是否是垃圾邮件进行分类,这样的方法非常有用。另一方面,当我们无法访问输出标签并且需要将数据分类(或聚类)到组中时,无监督学习方法就派上了用场。

同样重要的是要提到,在机器学习的背景下,这些并不是唯一的学习方法。其他一些类型包括强化学习和进化学习,这些都超出了本文的范围。

https://medium.com/geekculture/fit-vs-transform-vs-fit-transform-in-python-scikit-learn-2623d5a691e3

使用 R 的供应链设计:不受约束的仓库/客户对齐

原文:https://towardsdatascience.com/supply-chain-design-using-r-unconstrained-warehouse-customer-alignment-9ec11c1e4345?source=collection_archive---------23-----------------------

用 R &运筹学温和地介绍供应链设计

我最近在 R for Data Science(https://www.rfordatasci.com/)Slack 频道上有一个很棒的讨论,关于如何使用 R 编程语言建立一个供应链网络模型,将客户与配送中心(DC)联系起来。因为我总是渴望鼓励供应链设计领域的新手,所以我写了这个小示例脚本。利用ompr进行优化建模,leaflet进行绘图,geosphere进行测距,tidyverse进行数据准备。

在这个例子中,我使用了maps包的us.cities函数,“一个数据库是美国人口超过 40,000 的城市和所有州的首府。”仅过滤德克萨斯州,我们就有 71 个城市的现成客户数据集:

#learning R script on warehouse network design
#install packages if necessary first!
library(tidyverse)
library(magrittr)
library(leaflet)
library(ompr)
library(ompr.roi)
library(ROI.plugin.glpk)require(geosphere)
require(measurements)
require(maps)# customer set are the largest cities in Texastx_cities <- maps::us.cities %>% dplyr::filter(country.etc=='TX') %>%
  #demand is proportional to population
  dplyr::mutate(demand = ceiling(pop/10))#real quick leaflet of the cities
leaflet(tx_cities) %>% addTiles() %>% addMarkers()

现在我们已经使用leaflet验证了所有被过滤的客户城市实际上都在德克萨斯境内,我们需要创建一组潜在的仓库(DC)位置。在大多数现实生活的评估中,你会有 6 个以上的潜在选项,这些选项将使用定性和定量技术的组合来创建。但是在这种情况下,我们将只使用德克萨斯州的 6 个城市。

#potential DC sets are Dallas, Amarillo, Houston, El Paso, San Antonio, Beaumont
tx_dc <- tx_cities %>% dplyr::filter(
  name %in% c('Dallas TX','Amarillo TX','Houston TX','El Paso TX',
              'San Antonio TX', 'Beaumont TX'))

在本例中,我们将要求开立两个跟单信用证,对每个仓库对应的客户总数和 DC 对应的客户总量没有任何限制。这被称为无约束模型。在现实生活中,DC 容量是有限制的,这些限制应该纳入现实生活中的网络设计模型。

在无约束网络设计中,您要做的是最小化或最大化通过将需求点 D_i 与配送中心C _ j对齐而产生的总利益指标。该指标通常与总网络单位英里数相关。例如,如果 D_1 有 50 个单位的需求与 30 英里外的 C_2 对齐,则单位英里数为(50*30=1500)。

在仓库网络优化模型中,您本质上告诉优化求解器,“这里是所有潜在的组合,(i * j)个选项,这里是对我最重要的感兴趣的度量,我希望您最小化。此外,这些选项还有一些限制。”

然后,优化求解器会找到一个解决方案,即一组客户/配送中心组合,该组合可以最小化或最大化该指标。感兴趣的度量通常是成本函数;在这种情况下,您会告诉求解程序最小化。在其他情况下,该指标可能代表您希望求解程序最大化的利润函数。作为建模者,您输入度量标准是什么。(对于那些有优化建模或供应链网络设计背景的人来说,我知道这是一个专业简化,但我只是试图理解优化建模所做事情的本质。)

在本例中,我们希望将客户与配送中心的匹配所产生的总需求里程降至最低。我们将使用geosphere包找出每个客户城市和潜在 DC 之间的直线距离。(这种成对距离被称为哈弗线距离。公式相当复杂,并且考虑到了地球的曲率;geosphere将复杂的公式隐藏在函数后面。)

#create a distance matrix between the demand points and DCs
customer_dc_distmat <- geosphere::distm(
  x=cbind(tx_cities$long,tx_cities$lat),
  y=cbind(tx_dc$long,tx_dc$lat)) %>% 
  #convert from meters (default) to miles
  measurements::conv_unit('m','mi')
row.names(customer_dc_distmat) = paste0('Customer_',tx_cities$name)
colnames(customer_dc_distmat) = paste0('DC_',tx_dc$name)#create a matrix that is the metric you wish to minimize or maximize.
#in this example, the metric is unit-miles
#just multiply the demand by city, into the distance from that city to each DC
unitmiles_customer_dc_matrix <- 
  tx_cities$demand * customer_dc_distmat #define scalars for the number of Customers and DC options
customer_count <- nrow(tx_cities)
dc_option_count <- nrow(tx_dc)

现在是时候使用ompr包来构建我们的优化模型了。如果你没有上过运筹学线性规划的课,这个符号会是新的。网上有很多学习基础知识的资源,我鼓励你去寻找更多。

#now make optimization model
dc_location_model <- ompr::MIPModel() %>%
  #binary decision variables: for each customer, which DC to align to?  Yes/no decisions, align Customer A to DC B yes, or no?
  add_variable(customer_dc_align[customerindex,dcindex],
               customerindex=1:customer_count,
               dcindex=1:dc_option_count,type='binary') %>%
  #binary decision variable: open a DC or no?
  add_variable(open_dc_binary[dcindex],dcindex=1:dc_option_count,type='binary') %>%
  #first constraint: each customer aligned to 1 and only 1 DC
  add_constraint(sum_expr(customer_dc_align[customerindex,dcindex],
                          dcindex=1:dc_option_count)==1,
                 customerindex=1:customer_count) %>%
  #add in "Big M" constraints that activate open_dc_binary when
  #any customers are aligned to a DC
  add_constraint(sum_expr(customer_dc_align[customerindex,dcindex],
                          customerindex=1:customer_count)<=
                   99999*open_dc_binary[dcindex],dcindex=1:dc_option_count) %>%

  #limit the number of opened DCs to EXACTLY 2
  add_constraint(sum_expr(open_dc_binary[dcindex],dcindex=1:dc_option_count)==2) %>%
  #set objective function, the sumproduct
  #of the customer/DC alignment integer variables,
  #and the matrix of the unit-miles for each customer/DC pair
  #sense is either "min" or "max", minimize or maximize the values?
  set_objective(sum_expr(customer_dc_align[customerindex,dcindex]*
                           unitmiles_customer_dc_matrix[customerindex,dcindex],
                         customerindex=1:customer_count,
                         dcindex=1:dc_option_count),sense='min')

优化模型建立后,我们现在将它发送给选择的求解器。这段代码利用了glpk,但是ompr框架允许几个不同的线性规划解算器。更多信息见https://dirkschumacher.github.io/ompr/

solution <- ompr::solve_model(dc_location_model,with_ROI(solver = "glpk"))

solution是具有整体模型解的对象,包括目标函数值。我们现在需要提取我们最关心的决策变量的结果:客户/DC 一致性。然后,我们将做一些数据处理,引入客户和 DC 的姓名、纬度和经度。

customer_dc_alignment_df <- get_solution(solution,customer_dc_align[customerindex,dcindex]) %>%
  dplyr::filter(value==1) %>%
  dplyr::select(customerindex,dcindex) %>%
  #add in customer and DC names and lat/long
  dplyr::mutate(Customer_City = tx_cities$name[customerindex],
                Customer_Lat = tx_cities$lat[customerindex],
                Customer_Lng = tx_cities$long[customerindex],
                DC_City = tx_dc$name[dcindex],
                DC_Lat = tx_dc$lat[dcindex],
                DC_Lng = tx_dc$long[dcindex]) %>%
  dplyr::select(Customer_City,Customer_Lat,Customer_Lng,
                DC_City,DC_Lat,DC_Lng)

我们唯一的限制是每个客户都与一个 DC 相关,并且只选择了两个分拨中心。首先,我们将检查以确保每个客户城市在customer_dc_alignment_df中只出现一次。

View(table(customer_dc_alignment_df$Customer_City)) #View assumes you're using RStudio.

在这个频率表中有 71 行,每个客户城市一行。Freq值将全部为 1,表示每个客户城市与一个且仅一个 DC 相关联。

现在验证是否只选择了两个 DC,达拉斯和休斯顿:

#verify only two DCs selected, should be Dallas and Houston
dc_cities_selected <- unique(customer_dc_alignment_df$DC_City)
dc_cities_selected
[1] "Dallas TX"  "Houston TX"

现在使用leaflet目视检查对准情况:

#leaflet: color customer city by aligned DC.
customer_dc_alignment_df %<>% dplyr::mutate(
  leaflet_dc_color = dplyr::if_else(DC_City==dc_cities_selected[1],'red','blue'))leaflet(customer_dc_alignment_df) %>% addTiles() %>%
  addCircleMarkers(lat=~Customer_Lat,lng=~Customer_Lng,
                   color=~leaflet_dc_color,radius=3)

令人放心的是,靠近达拉斯的城市与达拉斯 DC(红点)对齐;靠近休斯顿的城市与休斯顿 DC(蓝点)对齐。这符合我们的优化模型的目标,即最小化总单位英里数。选择达拉斯和休斯顿作为 DC 的位置也是有道理的,因为它们是得克萨斯州两个最大的大都市区的支柱城市,因此是需求最大的两个大都市区。

就是这样!这是一个非常简单的例子,但是如果你刚刚开始,希望它能对你有所帮助!完整代码位于https://github . com/datadrivensupplychain/teaching _ bits/blob/main/facility _ location . r

如果你有兴趣了解更多关于如何通过优化建模、模拟和高级分析来改善你的供应链,请给我发电子邮件 ralph@datadrivensupplychain.com 讨论。

既然你已经读到这里,如果你觉得这很有价值,你会考虑捐赠吗?

谢谢,学习愉快!

(原载于 https://datadrivensupplychain.com/blog/

用 Python 优化供应链

原文:https://towardsdatascience.com/supply-chain-optimization-with-python-23ae9b28fd0b?source=collection_archive---------3-----------------------

寻找制造工厂的最佳位置,以满足客户需求并降低生产成本

供应链网络优化问题—(图片由作者提供)

供应链优化充分利用数据分析,找到工厂和配送中心的最佳组合,以匹配供应需求。

由于目前运输成本的飙升,公司开始挑战他们目前的足迹,以适应后 covid “新常态”

在这篇文章中,我们将提出一个简单的方法使用线性规划的供应链优化考虑

  • 您工厂的固定生产成本(美元/月)
  • 每生产单位的可变生产成本($/单位)
  • 运费 ($)
  • 客户需求(单位)

在过去 12 个月里运输成本增加了两倍的情况下,我们应该继续外包吗?

💌新文章直接免费放入你的收件箱:时事通讯

如果你喜欢看,你可以看看这篇文章的视频版本

一、如何用 Python 设计供应链网络?

问题陈述

作为一家国际制造公司的供应链管理负责人,考虑到最近运输成本的上涨和对未来需求的预测,您想要重新定义未来5 年的供应链网络

你的供应链网络图—(图片由作者提供)

你的供应链网络

  • 巴西、美国、印度、日本、德国的 5 个市场
  • 2 类 生产设施 : 低产能和高产能场所
  • 运输成本(美元/集装箱)
  • 客户需求(单位/年)

制造设施固定成本

  • 设备的资本支出(机器、存储、..)
  • 公用事业(电、水、..)
  • 工厂管理人员、行政人员
  • 空间租赁

这些费用取决于国家和工厂的类型。

制造场所固定成本—(图片由作者提供)

生产可变成本

  • 生产线操作员
  • 原材料

制造场所固定成本—(图片由作者提供)

例如,在德国生产的一个单位的可变成本是 13 美元/单位。

运输可变成本

  • 每个集装箱的成本(美元/集装箱)
  • 假设:1 个集装箱可以装 1000 个单位

海运运费(美元/集装箱)——(图片由作者提供)

例如,如果你想把一个集装箱从德国运到日本,费用是 1231 美元(每个集装箱)。

按工厂划分的生产能力

制造现场产能—(图片由作者提供)

例如,巴西的高产能工厂可以生产 1,500,000 台(台/月)。

每个市场的客户需求

制造现场产能—(图片由作者提供)

你可以在这个 Github 资源库中找到完整的代码:链接
我的作品集与其他项目: Samir Saci

二。结果

让我们尝试三种场景

  • 场景 1:初始参数
  • 情景 2:我们增加印度的产能(x2)
  • 场景 3:集装箱短缺导致运输成本飙升

-场景 1:初始场景

  • 巴西工厂为当地市场和美国生产
**Facilities: 1 high capacity plant**
('Brazil','Brazil') = 145,000 **(Units/Month)**
('Brazil','USA') = 1,250,000 **(Units/Month)**
  • 印度工厂为除巴西以外的所有国家生产产品
**Facilities: 1 high capacity plant and 1 low capacity plant**
('India','Germany') = 90,000 **(Units/Month)**
('India','India') = 160,000 **(Units/Month)**
('India','Japan') = 200,000 **(Units/Month)**
('India','USA') = 1,550,000 **(Units/Month)**
  • 由于印度产能有限,日本需要在当地生产
**Facilities: 1 high capacity plant**
('Japan','Japan') = 1,500,000 **(Units/Month)**
  • 诉讼结束时的全部
Total Costs = **62,038,000 ($/Month)**

-情景 2:外包到低成本地区

如果我们将印度的高产能工厂规模扩大一倍会怎么样?

让我们试着将印度高生产能力工厂的规模扩大一倍,假设这将使固定成本增加一倍。

  • 巴西工厂仍在为当地市场和美国生产
**Facilities: 1 high capacity plant**
('Brazil','Brazil') = 145,000 **(Units/Month)**
('Brazil','USA') = 1,250,000 **(Units/Month)**
  • 印度工厂为除巴西以外的所有国家生产产品
**Facilities: 2 high capacity and 1 low capacity plants**
('India','Germany') = 90,000 **(Units/Month)**
('India','India') = 160,000 **(Units/Month)**
('India','Japan') = 1,700,000 **(Units/Month)**
('India','USA') = 1,550,000 **(Units/Month)**
  • 日本不再在本地生产。

诉讼结束时的全部

-19.4(%) vs. Scenario 1
Total Costs = **51,352,000** ($/Month)

-场景 3:集装箱短缺导致运输成本飙升

如果我们把集装箱成本乘以 5 会怎么样?

  • 巴西只为当地市场生产
**Facilities: 1 low capacity plant**
('Brazil','Brazil') = 145,000 **(Units/Month)**
  • 美国开始为当地市场和日本生产
**Facilities: 1 high capacity plant**
('USA','Japan') = 200,000 **(Units/Month)**
('USA','USA') = 1,300,000 **(Units/Month)**
  • 印度关闭了其低产能工厂
**Facilities: 1 high capacity plant**
('India','Germany') = 90,000 **(Units/Month)**
('India','India') = 160,000 **(Units/Month)**
('India','USA') = 1,500,000 **(Units/Month)**
  • 日本开始为当地市场生产
**Facilities: 1 high capacity plant**
('Japan','Japan') = 1,500,000 **(Units/Month)**

由于产能有限,日本和美国仍然依赖印度工厂。

诉讼结束时的全部

Total Costs = **92,981,000 ($/Month)**

三。构建您的模型

关注我的 medium,了解更多与供应链数据科学相关的见解。

我们将使用 python 的纸浆库。PuLP 是一个线性(LP)和整数规划(IP)问题的建模框架,用 Python 编写,由 COIN-OR Foundation(运筹学计算基础设施)维护。

1.声明您的变量、参数和模型

  • 你的目标是最小化你的成本
  • 下限=0:生产的单位不能为负值

2.定义目标并添加约束

3.求解模型并分析结果

三。结论和后续步骤

欢迎随时关注我的 medium,获取更多与数据分析和供应链管理相关的文章

结论

该模型允许您模拟影响运营和商业参数的几种情况。

  • 如果印度的需求激增怎么办?
  • 如果我们不得不关闭在巴西的工厂怎么办?
  • 如果我们把日本的产能增加两倍会怎么样?

场景 3 显示的是运输成本飙升的一个例子,这可能会推动公司转向更多的本地足迹,工厂只为当地市场生产。

可持续采购

(图片由作者提供)

类似的方法可以用来选择你的供应商,考虑一个目标函数,将最大限度地减少二氧化碳排放量

可持续采购是在选择供应商时整合社会、道德和环境绩效因素的过程。

这包括根据一套可持续性标准对供应商进行评估和评价,如劳工权利、健康和安全、环境影响、人权等。

基于环境因素的供应商评估—(图片由作者提供)

利用数据分析,结合经济和环境约束,自动选择最佳供应商

在本文中,我们将了解如何使用数据分析来设计最佳供应链网络,以最小化成本和环境影响。

https://www.samirsaci.com/what-is-sustainable-sourcing/

改进您的模型

这个简单的模型可以帮助你获得供应链网络优化的线性优化的潜力。我们可以通过添加约束来快速改进这个模型

请随意分享额外约束的建议,以改进模型并满足您所在行业的业务需求。

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1]运筹学的计算基础设施,优化与纸浆(文档),链接

基于排队论的供应链流程设计

原文:https://towardsdatascience.com/supply-chain-process-design-using-the-queueing-theory-2ad75e58d1f3?source=collection_archive---------17-----------------------

用 Python 应用排队论的几个原理为电子商务履行中心设计一个包裹打包流程****

用排队论设计一个包裹打包过程—(图片由作者提供)

供应链可以被定义为一个为向客户提供服务和商品而构建的流程和库存地点的网络。

这个网络通常支持你公司的商业战略;它的目标可以是多种多样的,如提供市场上质量最好的产品、最低的成本或最个性化的服务或产品。

作为供应链工程师,您的目标是设计最有效的流程,以确保为客户提供良好的服务水平和盈利能力。

本文将利用 Python 中的排队论原理来设计一个电子商务履行中心的包裹打包流程。

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Problem Statement** What is the most efficient solution between single and multiple lines solutions?Scenario
You got the approval from your management for investing in a second packing station and you're wondering how should you design the layout.
**II. Optimal Solution using Queuing Theory** 1\. Introduction to Process Analysis
2\. The Little’s Law
3\. Introduction to the Queuing Theory
4\. How can we estimate this waiting time?
5\. Queueing Theory to estimate tq **III. Build a Simulation Model with Python
IV. Conclusion**

如果你喜欢看,可以看看这篇文章的视频版本

简短的讲解视频—(视频由作者提供)

一.问题陈述

方案

你是一家跨国服装零售公司的出境部经理,这家公司以男女老少的快速时尚服装而闻名。

你面临的一个主要问题是外向生产力;在提货后,您的订单等待发货的时间过长。

根据现场观察和生产率分析,您知道包装过程是瓶颈。

具有单线包装站的出站区域—(图片由作者提供)

  1. 仓库拣货员把包裹放在手推车上,放在传送带上

步骤 1 —(作者提供的图片)

2。包装操作员从传送带上取走包裹,并进行数量检查和包装(放入填充材料,关闭箱子)

步骤 2 —(作者提供的图片)

您的管理层批准您投资第二个包装站,您想知道应该如何设计布局。

解决方案 1:保持单线有两个平行站

解决方案 1 —(图片由作者提供)

解决方案 2:添加第二条带有专用站的线路

解决方案 2 —(图片由作者提供)

问题

最高效的(包装生产率)解决方案是什么?

http://samirsaci.com

二。使用排队论的最优解

排队论可以被定义为使用高级数学概念研究等待时间的科学。

如果你想了解更多,我强烈建议你看看华莱士·j·霍普写的《供应链科学》这本书。

1.过程分析介绍

简单的过程—(图片由作者提供)

在本文中,我们将通过一系列将输入转换为输出的操作来定义流程。

为了简化理解,让我们介绍一些符号:

符号—(作者提供的图片)

2.利特尔法则

过了很长一段时间,当你的系统变得稳定时,你可以使用这个法则来计算系统中的平均项目数(WIP)

符号—(作者提供的图片)

3.排队论导论

在此过程中,生产率问题的原因是包装前需要在传送带上等待包裹的时间。

有等待时间的简单流程—(图片由作者提供)

你的操作员的提货效率相当稳定;但是,当您可能会遇到会减缓流程的问题时:

  • 提货错误:例如,提货人放错了商品数量
  • 损坏:由于损坏,一些项目没有通过质量最终检查

在初始配置中,这些事件会增加包裹在 WIP 中的等待时间,并影响整体平均 ct。

4.我们如何估计这个等待时间?

让我们介绍一些符号:

到达参数—(图片由作者提供)

处理参数—(图片由作者提供)

我们希望改进的主要指标是平均周期时间,其定义如下:

**CT = tq + tp**with
tq: waiting time in the queue (min)
tp: effective process time

5.估计 tq 的排队论

利用排队论,我们可以近似地计算等待时间,

方程式—(图片由作者提供)

http://samirsaci.com

三。用 Python 构建仿真模型

你可以在这个 Github (Follow Me)资源库中找到完整的代码: 链接 我的作品集与其他项目: 萨米尔萨奇

因素

**Arrivals,**
ra = 6 parcels/min
ta = 0.17 min/parcel
CVa: coefficient of variation of ta
**Processing,**
rp = 3 parcels/min
tp = 0.33 min/parcel
CVb: coefficient of variation of tp

1.两种解决方案的等待时间公式

方程式—(图片由作者提供)

我们有 u - > u/2,因为输入流通过两个包装站分流。

2.模拟

方案

  • 到达的确定性分布:CVa = 0
  • 加工时间的随机分布:CVp in [0,2]

这种情况可以基于分批包装:您的提货操作员提前准备订单,并以恒定的时间间隔连续发送包裹。

场景 1 的模拟结果—(图片由作者提供)

评论

  • 对于纯确定性场景(CVp = CVa = 0 ),我们没有区别,因为两种解决方案的排队时间都是零。
  • 当我们引入处理时间的可变性(每个包裹要检查的物品数量、提货错误、质量问题)时,我们看到解决方案 1 优于解决方案 2。

3.结果的解释

  1. 如果您有一个有质量问题的包裹,如果您采取解决方案 2 (50%的输入流量),它将使整个生产线瘫痪。因此,如果处理时间的可变性很高,这种解决方案并不是最佳的。
  2. 使用解决方案 1,我们可以确保第一批进来的包裹或多或少是第一批出去的包裹,而我们无法预测使用解决方案 2 的结果(假设您的一条生产线因为一个包裹而面临巨大的延迟)

四。结论

关注我,了解更多与供应链数据科学相关的见解。

基于这些模拟结果,您可以估计对平均周期时间的影响(通过将处理时间添加到队列中),并在设计中激励您的选择。

幸运的是,最高效的解决方案也是最便宜的,因为您不需要投资购买新的传送带。

将您的模型包含在数字双胞胎中

超出

如果你对仓储流程改进方法感兴趣,可以从下面的文章中获得更多启发。

https://www.samirsaci.com/optimize-warehouse-value-added-services-with-python/ https://www.samirsaci.com/improve-warehouse-productivity-using-order-batching-with-python/ https://www.samirsaci.com/central-limit-theorem-for-process-improvement-with-python/

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1]供应链科学,华莱士·j·霍普

使用 Python 进行供应链可持续性报告

原文:https://towardsdatascience.com/supply-chain-sustainability-reporting-with-python-161c1f63f267?source=collection_archive---------5-----------------------

构建侧重于分销网络二氧化碳排放的 ESG 报告的 4 个步骤

供应链可持续性报告—(图片由作者提供)

多年来,投资者和客户对可持续发展透明度的要求越来越高。

投资者在评估组织的价值和弹性时,越来越重视企业的可持续性。

因此,越来越多的组织投入资源建设可持续发展报告能力,并确定可持续供应链的最佳策略。

在本文中,我们将介绍一种简单的方法来使用 Python 和 power bi报告您的分销网络的二氧化碳排放量。

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY****I. How to create a Supply Chain Sustainability report?** Calculate the CO2 emissions of multi-modal transportation ?
**II. Data Processing with Python** List of the datasets needed to build your report
**1\. Import Shipped Order Lines** All the purchased orders of your customers that have been shipped
**2\. Add Unit of Measure Conversions** Merge with Master Data to convert quantities in weight **3\. Distances Collections** Collect the distances by transportation mode
**III. CO2 Calculation** 1\. Final Calculation of the CO2 Emissions
2\. What can you do if you have missing data? **VI. Example of visualization using PowerBI**

如果你喜欢看,可以看看这篇文章的视频版本

一.如何创建供应链可持续发展报告?

定义

根据 GHG 协议公司标准(链接),温室气体排放分为三个范围:

  • 范围 1:由于公司的活动(公司的设施,如制造厂/仓库、公司的车辆)而释放到大气中的直接排放物
  • 范围二: 间接排放来自发电的外购能源
    (外购电、气、..)
  • 范围 3: 公司价值链中发生的所有间接排放 (范围 2 之外)**(运输、运营浪费、出差……)

在本文中,我们将关注与下游运输相关的范围 3 计算。

你的销售网络对环境有什么影响?

公式

根据法国环境署 Ademe 的协议(链接),估算运输二氧化碳排放量的公式为:

使用排放系数的公式—(图片由作者提供)

**With,**E_CO2: emissions in kilograms of CO2 equivalent (kgCO2eq)
W_goods: weight of the goods (Ton)
D: distance from your warehouse to the final destination(km)
F_mode: emissions factor for each transportation mode (kgCO2eq/t.km)

该公式提供了对二氧化碳排放量的粗略估计,而不需要高水平的运输数据粒度。

一种更准确的方法是,考虑车辆型号(卡车、集装箱运输船、飞机或火车)和装载率,估算每次运输的二氧化碳排放量。

http://samirsaci.com

二。用 Python 处理数据

基于这个公式,我们现在可以开始收集数据来计算排放量。

我的 Github 资源库中带哑数据的完整代码: 链接 (跟随我的:D) 我的投资组合带其他项目: 萨米尔萨奇

数据收集—(图片由作者提供)

导入已装运订单行

让我们首先从 ERP (或 WMS) 中提取已发货订单行:从您的仓库发货的您客户的所有采购订单。

该数据集包括

  • 订单信息:订单号,行号
  • 项目代码:主数据中项目的标识号
  • 仓库编码:订单发货的业务单元(配送中心、工厂)
  • 客户代码:订单交付的最终目的地(商店、配送中心)

代码

结果

已装运订单行数据框—(作者图片)

添加计量单位转换

下一步是将订购数量转换成重量(千克)。

净重与总重 在进入计算细节之前,我们需要解释一下毛重净重的区别。

总重量—(图片由作者提供)

包装是用来覆盖你的成品的容器。在一些 ERP 主数据中,你可能会找到净重(无包装)和毛重(有包装)。

对于这份报告,我们需要确保用毛重来估算包括包装在内的总重量。

处理单位(纸箱、托盘) 根据订单数量,您的客户可以按单位、纸箱(几个单位一组)或托盘(几个纸箱一组)订购。

总重量—(图片由作者提供)

如果你足够幸运,有纸箱或托盘的重量,你可以在你的客户订购整箱或全托盘时使用它们。

混装纸箱的假设 对于某些需要进行 拣件 (奢侈品、化妆品、电商)的物流作业,每订单行的数量很少,很少会出货满箱。

重量参考—(图片由作者提供)

在这种情况下,使用全箱重量是没有意义的;只能靠单位总重量。

对于我们的例子,我们将假设我们处于这种情况。

代码

结果

具有转换率的已发运订单行—(作者图片)

距离集合和 GPS 位置

我们需要按模式收集距离:

  • 航空运费
  • 海运费率
  • 公路运输:卡车
  • 铁路运输:火车

使用排放系数的公式—(图片由作者提供)

我们还将为 PowerBI 报告添加目的地的 GPS 位置。

处理后的最终数据帧—(图片由作者提供)

代码

三。二氧化碳计算

1.二氧化碳排放量的最终计算

我们现在已经有了需要收集在单个数据框架中的所有信息。我们可以开始使用与您的交通网络相关的排放系数来计算二氧化碳排放量。

按订单合计重量 出于报告目的,让我们计算每个订单号的二氧化碳排放量(与客户和日期相关联)。

决赛成绩

最终报告—(图片由作者提供)

2.如果你没有 100%的距离呢?

这里的一个主要挑战是,如果你有几千个送货地点,你需要知道距离。

如果您无法从运营商处收集 100%的距离,您可以:

  • 使用谷歌地图 API /或获取道路距离
  • 使用哈弗辛公式/或估算距离
  • 计算顶级客户的平均距离(以欧元为单位),并将平均值应用于没有距离的位置

3.如果没有 100%的重量转化怎么办?

在某些情况下,主数据不会更新,您无法获得所有物料的单位换算。

那样的话,你可以

  1. 将您的数据收集工作集中在高跑步者身上(营业额)
  2. 估计这些物品每欧元的重量(公斤/欧元)
  3. 将平均比率应用于 c 个剩余项目,不进行换算,以获得它们的重量

http://samirsaci.com

不及物动词使用 PowerBI 的可视化示例

尺寸= f(二氧化碳总量)的气泡图

泡泡地图—(图片由作者提供)

PS:如果您需要使用 GPS 坐标定位您的送货地点的支持。你可以在这个 Youtube 短片中找到一个免费而简单的方法

视觉洞察你可以通过运输方式的颜色编码来观察哪里的二氧化碳排放量最大(大气泡)。

按国家/地区目的地和项目代码划分

条形图—(图片由作者提供)

产品组合洞察 对于每个市场,哪一项对环境的影响最高?

CO2 = f(按城市目的地划分的营业额)

散点图—(图片由作者提供)

财务洞察 对于 PEINE-WOLTORF 的客户来说,您未来减少二氧化碳排放的努力对盈利能力的影响可能会更大。

后续步骤

关注我的 medium,了解更多与供应链数据科学相关的见解。

可视化您的交通网络

测量完你的排放量后,下一步可能是使用下面文章中介绍的方法来分析你的分销网络。

https://www.samirsaci.com/road-transportation-network-visualization/

这个想法是寻找机会

  • 最大化卡车的装载率(占容积的百分比)
  • 合并运输以减少车队中的卡车数量
  • 最小化空载运行距离(回程)

用数字双胞胎模拟不同的计划

数字孪生是物理对象或系统的数字复制品。

供应链数字模型是一种计算机模型,代表供应链中涉及的各种组件和流程,如仓库、运输网络和生产设施。

基于 Python 的供应链数字孪生模型—(图片由作者提供)

在你测量了二氧化碳排放的基线并确定了减排目标后,你就可以开始绘制路线图了。

对于每个计划,您可以使用这个模型来估计对

  • 二氧化碳排放量:减少的百分比
  • 服务水平:交货提前期
  • 成本:额外的资本支出和运营成本

并在遵守预算限制的同时,验证在不影响服务水平的情况下减少排放的计划。

倡议 1:你想建立本地仓库使用电动车进行最后一公里的配送

  • 对运输成本会有什么影响?
  • 仓储成本会有什么影响(地点越多)?
  • 我们能减少多少二氧化碳排放量?

倡议 2:你想停止空运,以减少二氧化碳排放量

  • 对商店的补货周期会有什么影响?
  • 配送计划员需要提前多长时间创建补货订单?
  • 对二氧化碳减排会有什么影响?

倡议 3:你想建立更多的工厂,为所有市场进行本地生产

  • 对生产成本会有什么影响?
  • 运输成本会有什么影响(工厂靠近仓库)?
  • 我们能减排多少二氧化碳?

对于每个计划,调整您的模型以包括该计划,并查看您的服务级别受到了多大影响。

然后,您可以调整其他指标(提高仓库容量、增加卡车数量等),直到恢复服务水平。

这将向您展示实施这些计划所需的投资和额外运营成本。

https://www.samirsaci.com/what-is-a-supply-chain-digital-twin/

考虑当地的倡议

本文中的例子着重于通过优化流程和仓库位置来减少运输网络的二氧化碳排放。

但是,可以实施更小的本地计划,如管理废物和减少耗材使用,以减少仓库运营的占地面积。

减少包装薄膜的使用量—(图片由作者提供)

您的 digital twin 还可以帮助您估计这些小举措对整个网络的影响(如果适用于所有仓库)。

  1. 使用实际运行数据计算电流消耗
  2. 将这些参数包含在您的数字孪生兄弟中
  3. 概念验证后,估计节约目标
  4. 推断整个网络(每个仓库)的节约

所有这些举措都与降低成本和优化运营的努力相一致。

您可以调整您的持续改进方法,以跟踪耗材使用情况,并找到不会影响您工作效率的替代方案。

关于我

让我们连接上 LinkedinTwitter ,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1] GHG 协议企业标准,温室气体协议,链接

[2]法国环境署 Ademe,比兰·GES,链接

[3]包含源代码和数据的 Github 知识库,Samir Saci,链接

使用 Python 的线性规划进行供应计划

原文:https://towardsdatascience.com/supply-planning-using-linear-programming-with-python-bff2401bf270?source=collection_archive---------5-----------------------

您需要将库存分配到哪里,以满足客户需求并降低运输成本?

供应计划的转运问题—(图片由作者提供)

供应计划是管理制造部门生产的库存以满足需求计划产生的需求的过程。

你的目标是平衡供需,以最低的成本确保最好的服务水平。

在本文中,我们将介绍一种简单的方法,使用整数线性规划来回答一个复杂的供应计划问题,考虑:

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Scenario** As a Supply Planning manager you need to optimize inventory allocation to reduce transportation costs.
**II. Build your Model
1\. Declare your decision variables**
*What are you trying to decide?* **2\. Declare your objective function** *What do you want to minimize?*
**3\. Define the constraints**
*What are the limits in resources?* **4\. Solve the model and prepare the results** What are the results of your simulation?
**III. Conclusion & Next Steps**

一、如何用 Python 优化供应计划?

问题陈述

作为一家中型制造公司的供应计划经理,您收到反馈称分销成本 过高

根据运输经理的分析,这主要是由于股票分配规则。

在某些情况下,您的客户不会从最近的配送中心发货,这会影响您的运费。

您的分销网络

  • 2 个生产无限产能产品的工厂 注:我们将在后面看到如何轻松改进这一假设
  • 2 个配送中心,从两个工厂接收成品并交付给最终客户注:我们将考虑这些仓库操作X-Docking,以避免在我们的模型中考虑库存能力的概念
  • 200 家店铺(发货点)

为了简化理解,让我们介绍一些符号

符号—(作者提供的图片)

门店需求 每家店的需求是多少?

符号—(作者提供的图片)

你可以在这里下载数据集

运输费用

我们的主要目标是降低总运输成本,包括入站运输(从工厂到配送中心)和出站运输(从配送中心到商店)

符号—(作者提供的图片)

符号—(作者提供的图片)

问题

我应该选择哪个工厂 i分销 n 以最低成本生产 100 件并交付给商店 p

配送中心出库成本的箱线图—(图片由作者提供)

评论

我们可以在上面的方框图中看到,单位成本的 D1 分布的中值低于 D2。我们可以预期,该模型将引导通过 D1 的流量的主要部分。

http://samirsaci.com

二。构建您的模型

我们将使用 python 的纸浆库。PuLP 是一个线性(LP)和整数规划(IP)问题的建模框架,用 Python 编写,由 COIN-OR Foundation(运筹学计算基础设施)维护。

你可以在这个 Github 资源库中找到完整的代码:链接

1.声明您的决策变量

你想决定什么?

符号—(作者提供的图片)

我们想决定进出运输的数量。

2.宣布你的目标函数

你想最小化什么?

符号—(作者提供的图片)

我们想决定最小化入站和出站运输成本。

3.定义约束

决定你的可行区域的资源限制是什么?

符号—(作者提供的图片)

来自 DCs 的供应需要满足每个店铺的需求。

符号—(作者提供的图片)

我们不在X-Docking平台建立任何股票。

包括可持续性约束

如果您想在优化问题中包括环境影响,您可以计算您的分销网络的二氧化碳排放量。

https://www.samirsaci.com/supply-chain-sustainability-reporting-with-python/

4.求解模型并准备结果

你的模拟结果是什么?

结果

该模型采用最便宜的路线入境,途径 P2 和 D1(分别为。P1 与 D2)。

正如我们预期的那样,超过 90%的出境流量通过 D1 ,以最大限度地降低出境成本

**163** stores are delivered by D1
0 store is delivered by the two warehouses together

三。结论和后续步骤

关注我的 medium,了解更多与供应链数据科学相关的见解。

结论

这种方法为您提供了通过实现简单规则来执行大规模优化的可能性。通常情况下,您会避免商店没有通过最佳路线送货。

接下来的步骤

此处给出的模型可以通过添加操作约束来轻松改进:

  • 工厂生产成本(美元/箱)
  • 配送中心的最大 X 停靠能力(纸箱)

还可以通过增加以下内容来改善成本结构

  • 配送中心的固定/可变成本结构 ($)
  • 固定+可变运输成本结构 y = (Ax +b)

你会发现的唯一限制是约束和目标函数的线性。

你不能

  • 实施非线性生产成本规则= f(例)来模拟生产过程中的规模经济
  • 实施总装运量的非线性(按范围)运输成本规则

一旦你试图触及目标函数或约束的线性,你就离开了线性规划的美好世界,开始面对非线性优化的痛苦。

我们将在下一篇文章中探讨一个例子,并尝试测量对处理时间和算法复杂度的影响。

用数码相机模拟不同的场景

数字孪生是物理对象或系统的数字复制品。

供应链数字模型是一种计算机模型,代表供应链中涉及的各种组件和流程,如仓库、运输网络和生产设施。

(图片由作者提供)

模拟几种降低成本或物流网络脱碳的场景。

场景 1:您想要建立一个本地仓库来缩短最后一英里的配送距离

  • 对服务水平会有什么影响?
  • 仓储成本会有什么影响(地点越多)?
  • 我们能减少多少二氧化碳排放量?

场景 2:您想要建立更多的工厂,为所有市场进行本地生产

  • 对生产成本会有什么影响?
  • 运输成本会有什么影响(工厂靠近仓库)?
  • 我们能减排多少二氧化碳?

对于每个场景,您可以操作与计划相关联的参数,并查看您的整体性能会降低多少。

然后,您可以调整其他指标(仓库容量和位置、补货提前期等),直到您重新达到初始目标。

这将向您展示供应链的改进,以获得适应这些新的绿色倡议的稳健性水平。

https://www.samirsaci.com/what-is-a-supply-chain-digital-twin/

数字孪生模型的例子:绿色库存管理

(图片由作者提供)

绿色库存管理可以定义为以环境可持续的方式管理库存。

对于分销网络而言,这可能涉及一系列旨在减少订单传输、准备和交付的环境影响的流程和规则。

(图片由作者提供)

如果我们降低商场补货的频率,对二氧化碳排放会有什么影响?

使用数据分析来模拟商店补货频率的变化,并衡量对整体环境影响的影响。

https://www.samirsaci.com/green-inventory-management-case-study/

关于我

下面连线 LinkedinTwitter ,我是一名供应链工程师利用数据分析改善物流运营,降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1]运筹学的计算基础设施,优化与纸浆(文档),链接

支持向量机(SVM)

原文:https://towardsdatascience.com/support-vector-machine-svm-719e530a725f?source=collection_archive---------13-----------------------

资料来源:Unsplash.com

所有关于支持向量机(SVM)从推导到面试准备

最近,我有机会为一群数据科学领域的新人和有经验的人准备一个关于 SVM 的讲座。我准备了一个讲座,涉及到基础知识,甚至是对 SVM(向量法)推导的直觉,还有一些问题以及讨论部分的答案。我希望这次讲座能让更多的观众受益。请在评论区告诉我,你对未来的 ML 算法讲座还有什么期待。

SVM 背景

SVM 群岛

  • 监督机器学习算法
  • 用于分类和回归

SVM 的真正优势在于分类,并且是高维向量(具有大量特征的数据点)的特定分类。虽然支持向量回归机(SVR)也使用与支持向量分类机相同的直觉和概念,但对于回归,线性或随机森林回归机也是 SVR 的强大竞争对手。我们将关注使用支持向量分类器的分类,而不是回归。

SVM 的优化

优化取决于向量对的点积

  • 推导(证明 SVM 分类器中的优化仅取决于向量对的乘积的事实)。

假设有一个如图 1 所示的二元分类问题,为了在 2D 区分两个类别,需要确定一个决策边界。如果划分类的边界是线性的,则称这些类是线性可分的。图 1 显示了两个不同类别+和-的向量(数据点)。

图 1

多行可以作为分隔两个类的判定边界(参见图 2)。蓝线、黄线或绿线中的任何一条都可以作为决策边界,因为这三条线都分隔了数据。我们将如何决定这些边界中的哪一个最好地分隔数据?这个决定会给我们一个条件,利用这个条件,我们可以在所有的可能性中拒绝除了一个决定边界之外的所有可能性。

图 2

为了定义最佳决策边界,我们使用最大裕度原则。离两个类的最近成员距离最大的边界被选为最佳边界。在图 3 中,散列线下面显示的是通过+和-类的最近点的线。从黄线到虚线的距离被定义为边距。假设在分隔两个类别的所有可能的线中,如果黄线在页边空白之间具有最宽的间隔,则黄线是最佳决策边界。散列黄线所经过的两个类别的点被称为支持向量。可以有单个支持向量(对于+类)或者可以有多个支持向量(对于-类),散列线的斜率将与决策边界相同。

图 3

为了最大化两条散列线之间的边距或距离,我们需要创建一个表达式,并对其求导以找到最佳(极值)值。假设向量‘w’垂直于决策边界,向量‘u’未知,如图 4 所示。为了确定未知向量 u 位于-ive 还是+ ive 类的边上,我们测量 u 在 w 上的投影的长度,如果它大于某个长度,则它在+ive 类中,否则它属于-ive 类(或者位于边缘)。

图 4

为了区分+类和-类,我们假设如果未知向量是来自+类(x+)的向量,它应该给出大于 1 的值,或者如果它是来自-类(x)的向量,它应该给出小于-1 的值。+1 和-1 值决定了两个类之间的清晰分隔。所以数学上的条件是:

为了数学上的方便,我们引入一个变量 yi,对于+样本 yi = 1,对于-样本 yi = -1。将 yi 乘以上面的等式,我们得到:

来自+类(x+sv)和-类(x SV)的支持向量位于边缘本身。因此,矢量(x+SV x SV)⋅w/|w|在法线 w 上的投影就是两个边距之间的距离。该距离应在上述限制条件下最大化。

  • 最大化:

从上面的等式我们可以破译:

因此,最大化条件变成最大值 2/|w|,或者我们可以说最小值:

  • 最小化:

  • 约束:

为了找到极值和约束,我们使用 Langrangian,

拉格朗日的最小值是:

在上面的表达式中,您可以观察到最小值(我们的优化)取决于两个向量对(数据点)的点积。

如果类是线性不可分的

在这种情况下,添加额外的特征并将向量转换到更高维度可能有助于通过平面(超平面)分离向量。例如,假设有两个类 c1(蓝色)和 c2(橙色),如下图 5 所示。这两类人似乎没有线性的决策界限。数据 x_2 = (x1) 增加一个新的维度怎么办?

非线性可分离数据:

图 5

现在可线性分离的转换数据(如图 6 所示):

图 6

类似地,对于包含 x1 和 x2 维度的二维数据,可以创建像 (x1)、(x2)、(x1)3 这样的新维度,并且可以将数据转换到更高维度以分离类别。

我们有一些函数可以帮助将数据转换到更高的维度。这些函数被称为内核。

SVM 一些受欢迎的果仁

  • 直线型
  • 多项式
  • 高斯的
  • 径向基函数
  • 夸张的
  • 乙状结肠的

讨论(面试 QnA)

  1. 任何算法通用问题:ADA?(优点、缺点和假设)

优点:

  • 交钥匙算法,需要优化的参数很少。
  • 优化是在凸空间中进行的,因此可以达到全局最小值,这与神经网络不同,它不会遇到陷入局部最小值的问题。
  • 内存高效
  • 如果特征数很高(> 1000),线性 SVM 比其他算法更有效

缺点:

  • 特征缩放
  • 随着示例数量的增加,速度会变慢
  • 硬边界导致过度拟合

假设:

  • 没有人

2。结合 SVM 解释硬利润和软利润。

  • 硬边界不允许有任何误差
  • 软余量允许误差,它减少了过拟合的机会

3。为什么例子越多,SVM 越慢?

计算成本取决于向量对的选择(nC2,如优化部分所述)。

4.与 SVM 相关的超参数有哪些?

  • 核心
  • c:允许误差的数量。大 C 给出了一个狭窄的边界,反之亦然。

5。为什么 SVM 算法被认为是内存高效的?

不是所有的数据点都需要作出决定,一旦支持向量被决定,只有支持向量和超平面的方程需要作出决定。

6 。陈述以下陈述是对还是错:“SVM 判定边界是连接两个类的凸包的最近点的直线的垂直平分线”。

真实的陈述。几何解释:制作每个类别的凸包,尝试使用最近点连接凸包,分类边界将是垂直平分线。

7 . 举一个 SVM 将被用于 RandomForest 的典型例子。

文本分类:当特征数量很大时,SVM 是高维空间的一种算法选择。

8。 什么是正规化?SVM 算法是如何正则化的?本质上是 L1 还是 L2 正规化?

' c 参数'实际上是正则化参数。C 参数乘以误差之和,因此正则化本质上是 L1。但是如果代价函数以这样的方式被修改,即 SVM 的代价是 C 乘以误差的平方和,则正则化本质上变成了 L2。

推荐读物

  • 一定要寻找其他的推导方法(线性代数方法)
  • 默瑟定理

支持向量机(SVM)解释说

原文:https://towardsdatascience.com/support-vector-machine-svm-explained-58e59708cae3?source=collection_archive---------28-----------------------

用 Python 解释和实现 SVM

图片来自水花

支持向量机(SVM)是数据科学家使用的核心算法。它可以应用于回归和分类问题,但最常用于分类。它的流行源于模型强大的准确性和计算速度(取决于数据的大小)。由于 SVM 通过核进行运算,它在解决非线性问题方面也很出色。SVM 如何工作的前提非常简单:给定绘制在平面上的数据,该算法将创建一条线/超平面来将数据分成不同的类。

作为我解释和实现机器学习中核心概念的系列文章的继续,这篇文章将着重于给出分类相关问题的 SVM 的概念性理解。

目录:

  • 什么是 SVM
    -支持向量
    -超平面
    -余量
  • 优势
  • 不足之处
  • 履行
  • 结论
  • 资源

什么是 SVM

支持向量机是一种监督学习算法,它识别最佳超平面来划分数据集。有两个主要术语会被重复使用,下面是它们的定义:

  • 支持向量 —最接近超平面的点
  • 超平面 —比其周围空间[ 1 ]低 1 维的子空间。它用于将空间分成多个部分。
    给定一个三维空间,随后的超平面将是一个二维平面。类似地,在二维平面中,超平面将是一维线。
  • Margin —超平面与任一侧最近的数据点之间的距离[ 2
  • 内核 —用于将输入数据转换成不同形式的数学函数。常见的核函数有线性、非线性、多项式等。

对于给定两个特征的简单分类任务,您可以将超平面想象为分隔数据的线性(一维)线。这可以从下图中直观地看到。

图 1 : 2 维空间,1 维超平面将数据分成不同的类。虚线表示超平面和支持向量之间的边界。(图片由作者提供)

给定上图,你可以想象有许多方法来识别一个可以分割数据点的超平面。哪个超平面是最佳选择?我们希望选择一个超平面,该超平面和所有点之间的距离最大。这将产生新数据被正确分类的最大可能性[ 2 ]。

图 2:由于没有逻辑方法用二维形式的超平面分割数据,从而将类别分段,因此将数据转换到三维空间并识别超平面(图片由作者提供)

当我们处理没有明显超平面的数据时(如图 2 所示),我们需要将我们的观点转移到一个更高维的空间。这可以想象为数据点上升或下降,而飞机试图将它们分成适当的类别。SVM 允许用户选择最适合他们正在处理的数据的内核函数。使用核来映射高维视点中的数据将允许超平面分割数据。你可以在这里了解更多关于内核函数的知识【4】。

优势

  • 通用于用户特定的内核函数
  • 内存高效
  • 在维数大于样本数的情况下有效

不足之处

  • 处理噪声数据时容易出错和过度拟合(例如,不同标签的重叠特征)
  • 处理非常大的数据集时计算时间长
  • 未能提供结果的概率解释[ 3

履行

结论

SVM 是一种监督学习算法,它通过使用超平面将数据分成不同的类别。所选择的超平面是在该超平面和所有点之间具有最大余量的超平面,这产生了最大的准确分类的可能性。这是一种非常通用、内存高效的算法,但是它容易过度拟合,根据数据的大小计算开销很大,并且无法提供结果的概率解释。

资源

[1]https://en.wikipedia.org/wiki/Hyperplane

[2]https://www . kdnuggets . com/2016/07/support-vector-machines-simple-explain . html

[3]https://scikit-learn.org/stable/modules/svm.html

[4]https://sci kit-learn . org/stable/modules/SVM . html # SVM-kernels

您可能会对我写的其他文章感兴趣:

支持向量机、对偶公式、二次规划和序列最小优化

原文:https://towardsdatascience.com/support-vector-machines-dual-formulation-quadratic-programming-sequential-minimal-optimization-57f4387ce4dd?source=collection_archive---------3-----------------------

这是一种面向数学的方法,研究支持向量机背后的直觉和用于求解它的优化算法。本文提供了一个一站式指南,帮助您揭开 SVM 内部工作的神秘面纱。

支持向量机(或最初由作者 Vladimir Vapnik 称为支持向量网络)采取了一种完全不同的方法来解决统计问题(在特定分类中)。这种算法已经被广泛应用于一些分类问题,如图像分类、词袋分类、OCR、癌症预测等等。SVM 基本上是一个二元分类器,虽然它可以修改为多类分类以及回归。与逻辑回归和其他神经网络模型不同,支持向量机试图最大化两类点之间的分离。作者用了一个绝妙的主意。

下面是我们将在本文中涉及的概念,它们基本上一步一步地揭开支持向量机的神秘面纱,然后针对其缺陷增强算法。

  1. 香草(平原)SVM &其目标函数
  2. 软裕 SVM
  3. 内核绝招
  4. 附录 1-推导最大余量等式。&目标函数
  5. 附录 2 —寻找目标 fn 的最佳值。利用拉格朗日、对偶公式化&二次规划
    求解极小值的一般方法
    存在约束时求解极小值
    库恩—塔克条件
    对偶&互补松弛度
  6. 附录 3 —推导软边际 SVM 的最优值
  7. 结论
  8. 参考文献

香草 SVM 及其目标函数

让我们从维基百科中获取 SVM 的正式定义:

支持向量机在高维或无限维空间中构造一个超平面或一组超平面,可用于分类、回归或其他任务,如异常值检测。

等等,但是专业术语太多了!让我们简化它&只保留需要的信息!

首先,SVM 创建了一个超平面(n 维中的一条简单的线)。如下面的 GIF 所示,这个超平面需要以最好的方式将两个类一分为二。这就是支持向量机所做的一切……剩下的就是浇头了!(无限维空间、回归、离群点检测等。)

现在,为了构建最优超平面,它需要另外两个超平面的支持,这两个超平面在它的两边平行&并与之等距!

这两个支持超平面位于类别之间的最极值点,被称为支持向量

因此,我们只需要找到支撑超平面(为简单起见使用),它们之间的距离最大!由此我们很容易得到最优超平面。这被简单地称为最大边缘超平面。支撑超平面之间的距离称为余量

来源:作者图片

因此,我们的目标是简单地找到最大余量 m。使用向量运算,我们可以发现(给定最优超平面(w . x+b = 0)),余量等于:

因此,最大余量 M :

为了数学上的方便,目标函数变成(详细解释见附录 1):

观察这里我们的目标已经推导到从方程 w.x+b=0 中寻找最优

然而,这也带来了一个约束,即一个类中的点不能位于两个支持超平面内!数学上可以表示为:

那么这些约束意味着什么呢?

这意味着在如下图所示的超平面内不能有点,这被称为 硬边界 SVM(香草 SVM)。

来源:作者图片

这就是支持向量机的大缺点!这两个类需要完全分离。现实世界的数据集中从来不会出现这种情况!这就是 软边际支持向量机 发挥作用的地方🎉😃!

在我们继续之前,只有一个问题! 支持向量机使用梯度下降寻找最小值 ?不会吧!(大多数人未能认识到这一点)。通过求解目标* 函数的导数直接找到最小值。因为有约束,我们需要首先取目标函数的 Langrangian 来求解最小值。你可以在附录 2 中找到完整的推导(我鼓励你去读!).*

软利润 SVM

如上所述,软间隔支持向量机可以处理具有不可分数据点的类。下图同样解释的很清楚!

因此,软利润背后的理念要点如下:

允许 SVM 犯一些错误,同时保持尽可能大的差距。

来源:作者图片

现在,它是如何做到这一点的,而不是普通的支持向量机?🤔

我们只是在目标函数中使用了一个额外的惩罚因子,叫做𝜉 。这个因子是一个数据点从相应的支持超平面到另一个类超过的距离。

因此,如果数据点在边界内(支持超平面),惩罚因子𝜉 为 0。否则,如果数据点在另一边,这个因子𝜉 等于它在数据点和支持超平面之间的距离。因此,值𝜉 是非负数。

这可以用下面的等式来总结:

理想情况下,它应该代表 SVM 犯的“错误的数量。因此,我们新的目标函数是:

**

这里对于一个小功率的𝜎来说,函数 F 就变成了错误数!(求和用于说明数据集中所有点的𝜉

就像支持向量机一样,最小值可以通过求解其导数(导数的拉格朗日函数)直接找到。

内核技巧

现在回头看看我们所得到的,很明显我们只使用了 w.x+b 。这仅仅是一个线性方程。这意味着当你可以对数据进行线性分类时,SVM 工作得最好!

非线性数据。 来源:图片由作者提供

这是另一个巨大的限制!然而,作者已经找到了一个解决方法💃!!这是内核技巧。简单来说:

内核只是将非线性数据点转换成线性数据点,这样 SVM 就可以将两个类一分为二。

下图显示了同样的情况。

N 维到 N 维的转换。来源:维基媒体

因此,新的线方程将是

这里使用了一个巧妙的技巧将 N 维中的点转换为 N 维中的点,其中 N > n 。**

内核 𝜑 必须遵守以下条件:

**

来源:作者图片

有几个用于支持向量机的核函数。一些受欢迎的是:

  • 高斯径向基函数:

其中 𝛾 > 0

一个特例是 𝛾 = 1/2𝜎

  • 高斯内核:

  • 多项式内核:

  • 乙状结肠内核:

附录 1-推导最大余量等式。&目标函数

为了推导目标函数,我们假设数据集是线性可分的。

我们知道两个支持超平面位于支持向量上,并且它们之间没有点。因此,我们可以首先考虑这两个支持超平面之间的中间超平面为:

并且考虑到这个和支持超平面之间的距离是 1,我们得到

由于没有超过这两个超平面的点,我们可以推导出:

对于所有带有标签的值

&对于所有带标签的值****

我们可以将两者结合起来,如下所示:

因此,这是我们的目标函数的约束条件(参见本文开头的内容)。

现在要找到最大余量,必须用超平面来表示。那么让我们推导边距 M 和超平面之间的关系。

来源:作者图片

在上图中,设向量&z分别为直线上的平行向量【w . x+b =-1&w . x+b = 1。然后,****

其中矢量 k 是垂直于矢量x₀z的直线。**

矢量的大小 kM.

因此,

现在既然**z&x₀躺在w . x+b = 1****w . x+b =-1,**

从上面的 eq。代替zt83】,****

现在我们有了,我们需要最大化它,

因此,新的目标,即目标函数是:

****

&不等式约束是:

****

附录 2 —寻找目标的最佳值 fn。使用拉格朗日,对偶公式和二次规划

求解最小值的一般方法

为了找到曲线的最优解,我们可以

  1. 取一阶导数,
  2. 将导数等于 0(最大值或最小值),得到一个微分方程。
  3. 求解微分方程,找到最优点。
  4. 二阶导数可以提供方向&因此我们可以推断出最优值是最小值还是最大值。

存在约束时求解最小值

如果微分方程中有一些约束,就像我们在目标函数中的约束,我们首先需要应用拉格朗日乘数(老实说,这非常简单)!

如果你观察上面的等式(5),它只是目标函数,减去不等式约束!当约束是等式约束时,它必须仅满足标准【αᵢ】0。然而,上述方程是不等式约束方程。因此,还需要满足一组称为库恩-塔克条件的附加条件。我们稍后将讨论这些条件。

为了找到最优值,就像之前一样,我们取一阶导数并使其等于 0:

为了找到最佳值,我们可以简单地将这些值代入(5),

扩展情商。(5)我们得到,

现在将(6)和(7)中的值代入上面,

我们可以重新代入等式中 w 的值。(6)对于上面的等式,

在这里,称为目标泛函 &它是所有的函数(【αᵢ】…………αₙ)表示为【λ】(大写λ)。****

这种推导对于考虑不等式约束[等式]是必要的。(4)].既然现在考虑到了,目标泛函 W 就是需要优化的新函数,而不是 Eq。(3).这被称为对偶公式,因为初始目标函数已被修改!**

Eq。(3)被最小化。****

由于 W 是一个二次方程,所以它是一个二次规划(QP) 问题&它可以通过一个叫做 序列最小优化(SMO) 的算法来解决。如果您曾经使用过 LibSVM 包,它是 Scikit-Learn 和大多数其他 SVM 库中 SVM 的基础,您会发现 LibSVM 包实现了 SMO 算法来求解最大余量

最后,讨论不等式约束需要满足的条件。

库恩-塔克条件

  1. ****双重可行性:

2.互补可行性:

3.静止状态:

4.初始可行性(我们最初的约束):

二元性和互补性松弛

当一个问题可以转化为另一个问题,而另一个问题的解更容易计算,并且也提供了原问题的解时,这两个问题被称为表现出对偶性,反之亦然。

然而,并非所有的对偶函数都必须有一个为另一个函数提供最优值的解。这可以从下面的图 1 中推断出来,在原始问题和对偶问题之间有一个对偶缺口。在图 2 中,对偶问题表现出很强的对偶性,据说具有互补松弛。此外,从下图可以清楚地看出,最小化问题转化为最大化问题。因此我们需要最大化 W 对抗

来源:作者图片

附录 3——推导软利润 SVM 的最优值

如前所述,软利润 SVM 的目标函数是,

这里,函数 F 是单调凸函数& C 是正则化常数。

因此,上述目标函数的拉格朗日量是,

使用与硬边界 SVM 中相同的方法,我们得到目标泛函 as,

如果你观察,这里的额外术语是,

在哪里,

目标泛函的约束条件是:

因此,求解目标泛函,我们可以获得最优的最大利润。

结论

从以上各节,我们可以得出结论

  1. 基本支持向量机或硬边界支持向量机是二元和线性分类器,只对可分离数据起作用。
  2. 软间隔支持向量机可以处理不可分的数据。
  3. 核可用于将非线性数据转换成线性数据,在此基础上,支持向量机可用于二元分类。
  4. 支持向量机的组合可以用于执行多类分类。
  5. 支持向量机是非常快速的算法,因为它们直接求解最大间隔,并且不使用像梯度下降这样的迭代过程来寻找最小值。

参考

  1. 支持向量网络论文
  2. https://www . SVM-tutorial . com/2014/11/SVM-理解-数学-部分-1/
  3. https://www . SVM-tutorial . com/2014/11/SVM-理解-数学-部分-2/
  4. https://www . SVM-tutorial . com/2015/06/SVM-理解-数学-部分-3/
  5. https://www . SVM-tutorial . com/2016/09/unconstrained-minimization/
  6. **【https://www.svm-tutorial.com/2016/09/convex-functions/ **
  7. https://www . SVM-tutorial . com/2016/09/duality-la grange-multipliers/
  8. 亚历山大·科瓦尔茨克简洁的支持向量机
  9. Ali Ghodsi,Lec 12:软间隔支持向量机(SVM)
  10. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5822181/
  11. https://www.youtube.com/watch?v=JTTiELgMyuM

11.http://fourier.eng.hmc.edu/e161/lectures/svm/

12.http://www . svcl . ucsd . edu/courses/ECE 271 b-F09/讲义/soft VMs . pdf

13.第 70 讲——软间隔支持向量机|海量数据集挖掘|斯坦福大学

支持向量机,图解

原文:https://towardsdatascience.com/support-vector-machines-illustrated-b48a32c56388?source=collection_archive---------15-----------------------

支持向量机背后的直觉和数学

(作者 GIF)

介绍

支持向量机是数据科学中的一类技术,在数据科学界非常流行。它们主要用于分类任务,在训练数据很少的情况下表现非常好。

可悲的是,由于深度学习的广泛流行,支持向量机最近几乎被遗忘了。但我认为它们是每个数据科学家都应该拥有的工具,因为它们训练起来更快,有时甚至超过神经网络。

在这篇博客中,你将了解到支持向量机使用超平面来分离和分类我们的数据。我还会解释什么是超平面,如何用一个方程来描述它们。我们将会看到,支持向量机并不使用全部数据来寻找最优超平面,而是仅使用一些称为支持向量的数据点。你将学习如何计算超平面到一个点的距离。这将使我们能够找到与支持向量具有最大距离的超平面(该距离被称为余量)。

超平面

让我们以虹膜数据集为例。该数据集由 3 个类组成,代表鸢尾花的不同类和总共 4 个特征。由于支持向量机被设计成只对两个类的数据集进行分类,我们将放弃第三个类。我们使用数据集的两个特征。这些特征即花瓣长度和花瓣宽度。

花瓣长度与花瓣宽度(图片由作者提供)

支持向量机使用超平面来分离这两个类别。当我们得到一个未知类的新数据点时,我们必须预测它的类。根据新点位于超平面的哪一侧,我们将预测一个类或另一个类。

我们的数据有两个特征,因此我们说我们的数据是二维的。在二维中,超平面是一条直线。(在一维中,超平面是一个点,而在三维中是一个平面)

(作者 GIF)

问题是,有无限数量的可能超平面可以完美地对数据集进行分类。我们怎么知道该选哪一个?

(作者 GIF)

边缘和支持向量

在支持向量机中用来解决这个问题的方法是最大化超平面与两个类的数据点的距离。这个距离然后被称为余量。但是我们不使用所有的数据来计算边界,我们只使用最接近超平面的点。这些点被称为支持向量

(作者 GIF)

在这个例子中,我们对于每个类只有 2 个支持向量,但是存在更多具有相等余量的支持向量也是可能的。

为什么支持向量叫做支持向量而不是支撑点?点和向量可以被同等对待。与一个矢量具有相同坐标的点将位于该矢量的尖端。因此,如果我们用向量或点来表示坐标,只是个人喜好的问题,SVM 算法的创造者把他们的数据视为向量。

支持向量作为向量和点(图片由作者提供)

超平面方程

超平面有一个权重 𝑤 来决定它的方向。𝑤垂直于超平面它有一个偏差 b. 描述超平面的方程是:

超平面和原点之间的距离是偏差的值除以法向量长度。

(作者 GIF)

任意一点 𝑥 到超平面的距离为:

寻找最优超平面

我们的目标是利润最大化。但是我们不能让边缘任意大,因为不允许任何点到超平面的距离小于边缘。这个问题可以归结为:

  • 最大化利润
  • 距离不能小于边距。

利润最大化

我们可以使用一个简单的技巧,让定义为等于 1/(𝑤的长度)。

在下面的 GIF 中,你可以看到当页边空白减少时,向量 𝑤 (用白色表示)的大小增加。

(作者 GIF)

因为除法在计算机上很慢,所以我们没有最大化边距,而是最小化 1/margin。

计算𝑤需要开平方根,这也是一项计算量很大的工作。相反,我们可以通过最小化𝑤来加快速度。

距离约束

我说过,每一个数据点到超平面的距离必须大于边缘。

该约束简化为:

整体算法

所以整个算法看起来如下。

我们添加支持向量所在的两条线。它们到超平面有一个距离,这个距离等于边缘。

这两条线和超平面一起构成了“街道”。街道内不允许有任何数据点。

(作者 GIF)

你可以看到支持向量一接触到街道的边界就改变了。

(作者 GIF)

观点

大多数情况下,类不能用一条线分开。我在这篇博文中讨论的支持向量机被称为“硬边界”支持向量机。这些不能用于线性不可分的数据集。然而,当我们允许一些错误分类时,我们称之为软边际 SVM。通过使用软边界,我们再次能够在这些数据集上找到超平面。

也有可能使用核函数来转换空间,并完美地分离非常复杂的数据集。

此外,我们到目前为止看到的支持向量机只能用两个类对数据集进行分类,我们必须将问题分成多个二进制分类任务。但是存在直接使用具有两个以上类别的支持向量机的技术。

我将在以后的帖子中讨论所有这些对标准硬利润 SVM 的扩展。

摘要

支持向量机使用超平面来分离数据集中的两个类。为了实现对未来或测试数据的良好预测,我们希望找到一个与两类支持向量的距离最大的超平面。这个距离叫做边缘。

这个最佳超平面可以通过在没有数据点比边缘更靠近分离超平面的约束下最大化边缘来找到。这意味着支持向量是最接近超平面的点,并且它们的距离等于边缘。

想要连接吗?

领英
https://www.linkedin.com/in/vincent-m%C3%BCller-6b3542214/
脸书
https://www.facebook.com/profile.php?id=100072095823739
推特
https://twitter.com/Vincent02770108
中等
https://medium.com/@Vincent.Mueller
成为中等会员并支持我
https://medium.com/@Vincent.Mueller/membership

作者相关文章

作者撰写的其他文章

资源

https://stats . stack exchange . com/questions/440640/what-are-w-and-b-parameters-in-SVM

支持向量机不到 5 分钟

原文:https://towardsdatascience.com/support-vector-machines-in-under-5-minutes-3074762a49bf?source=collection_archive---------22-----------------------

坦纳·博瑞克在 Unsplash 上拍摄的照片

关键概念简介

介绍

在本文中,我将通过一些直观的例子向您介绍支持向量机(SVM)的概念,尽可能将技术细节放在一边。

分类示例

线性情况

假设我们有以下两类数据点集—蓝色方块和橙色圆圈:

图 1

现在我们想确定划分数据的最佳决策边界。决策边界将位于上述两类数据之间,并且可以采取以下形式:

图 2

或者:

图 3

或者甚至:

图 4

哪一个可能是最佳的呢?请注意,当引入新数据时,没有优化的决策边界可能会导致大量的错误分类。

让我们看看上面的最后一个例子。假设我们在两个类别之间定义任意分隔线:

图 5

位于绿色分隔线上的点称为“支持向量”。它们是差值向上推的数据点,或者是最接近其他类的数据点。换句话说,我们只关心算法中的支持向量,其他所有训练数据点都不是主要关心的。准确地说,我们希望 SVM 算法能够查看接近另一类的极端数据点,而不是边缘。最大边缘是支持向量到决策边界超平面的最近距离的总和。请注意,对于 SVM 的情况,红线被称为超平面,因为 SVM 可以处理多维数据,其中数据点被称为向量,因为它们在多维数据空间中具有坐标。

但是,当数据点不像上面的例子那样是线性可分的(即非线性的)时,会发生什么呢?这时候非线性 SVM 就出现了。

非线性情况

考虑下面的例子,其中数据点具有某种二次(非线性)模式:

图 6

为了获得数据的线性映射,我们可以对超平面(红线)进行变换,从而得到上面的 1 维空间。超平面现在是一条抛物线。

但是,此类转换的计算开销可能很大,并且可能需要很长时间才能运行,尤其是对于大型数据集。幸运的是,有一种技术叫做“内核技巧”。这种方法的命名源于核函数的使用,该核函数允许在高维向量空间中操作,而不需要计算空间中数据点的坐标。相反,他们计算特征空间中向量的点积。使用这个“技巧”会导致所有点通过某种变换被映射到一个更高维度的空间。该方法的要点是将非线性空间转换成线性空间,仅此而已!

一些流行的核函数包括线性核、多项式核和径向基函数(RBF)核。支持向量机内核技巧的一个缺点是选择正确的内核并不简单,而且必须进行一些超参数调整。幸运的是,Scikit-learn 等流行的 Python 库已经实现了 SVM 和超参数调整模块,用于直观的集成。关于 Python 实现的大量文档可以在 Scikit-learn 的这里找到,关于 SVM 的这里找到,关于超参数调优的找到。

回归案例呢?

要使用 SWMs 执行回归,需要做的只是颠倒目标,而不是尝试在分类中适应最大可能的裕度(图 5 ),对于回归,我们尝试在裕度定义的空间上适应尽可能多的实例:

图 7

下一步是什么

我将在以后的文章中介绍更多关于支持向量机的内容,陈述它们的优点和缺点,以及更多的实际例子。敬请关注!

参考

[1]t . Hastie,r . TiB shirani 和 j . h . Friedman(2009 年)。统计学习的要素:数据挖掘、推理和预测。第二版。纽约:斯普林格。

[2]超参数调整方法。检索自:https://scikit-learn.org/stable/modules/grid_search.html

[3]sci kit-learn 中的支持向量机。检索自:https://scikit-learn.org/stable/modules/svm.html#svm

评论

  • 图 1 到图 7 是我自己手绘的,就不用引用了。

支持向量机——用 Python 实现的机器学习算法

原文:https://towardsdatascience.com/support-vector-machines-machine-learning-algorithms-with-implementation-in-python-f4337941818?source=collection_archive---------43-----------------------

机器学习算法— 30 天挑战

在本文中,我们将研究支持向量机如何工作,以及如何使用 Python (Scikit-learn)实现它们

在本文中,我们将研究支持向量机,这是另一种重要的机器学习算法,主要用于分类目的,在您的 ML 算法工具箱中。

图片来自 Unsplash

我们将从研究支持向量机做什么开始,然后继续使用scikit-learn来实现它,使用虚拟数据和真实世界的数据集。

  • 什么是支持向量机
  • Python 实现(虚拟数据)
  • Python 实现(真实世界数据集)
  • 应用程序
  • 结论
  • 你能做什么
  • 其他 ML 算法

这是我 30 天文章写作挑战的一部分。请随意查看我的新人帖子上的文章:

https://nouman10.medium.com/lets-publish-30-articles-in-30-days-a0b8111855bb

什么是支持向量机

支持向量机(SVM)是一种用于分类目的的机器学习算法。它通过定义一个最佳超平面来对不同的类进行分类,该超平面以这样一种方式将两个类分开,即它们离超平面的距离尽可能最大。让我们用形象化的方法来解释它。

假设我们有一些属于两个不同类别的二维数据,如下所示:

作者图片

支持向量机要做的是提出一个超平面,将数据分成两个独立的类,如下所示:

作者图片

现在对于分离超平面有很多选择。例如,像这样:

作者图片

注意,所有这些超平面都精确地划分了训练数据,但是所有这些都不是最佳的。对于一个最优的超平面,它应该在每个类的封闭实例之间有一个最大距离,这就是支持向量机的目标。

我们不会研究 SVM 的理论方面,因为它需要一篇自己的文章。但是你可以在这里阅读。

Python 实现(虚拟数据)

为了更好地理解实现,让我们从在虚拟数据上实现 SVM 开始。为此,我们使用了scikit-learn。我们将使用scikit-learn库中的SVC模块,因为我们将它用于分类目的(SVC - >支持向量分类器)。

我们将模型与虚拟数据进行拟合,并做出预测。如果你查看数据,超平面可能会根据正或负的特征来区分实例。这就是为什么如预期的那样,预测属于类别 1。

Python 实现(真实世界数据集)

让我们也在真实世界的数据集上实现 SVM。我们将使用digits数据集。它是包含灰度数字图像的图像数据集。我们将使图像变平,以便像素可以用作特征。

我们将从导入所需的库、加载数据集和绘制一些图像开始:

由于尺寸很小,图像会很模糊

作者图片

我们现在将从展平图像开始,将数据集分为训练和测试,初始化我们的模型,使我们的模型适合训练数据,最后对数据集进行预测。

现在,让我们绘制一些测试数据,以及预测和实际标签。

作者图片

这些预测看起来非常一致。但是,让我们计算分数,并绘制混淆矩阵,以获得更大的图片:

这给了我们大约 94%的准确度,这是相当好的,因为我们没有调整任何超参数。

作者图片

应用程序

  1. 文本分类
  2. 面部表情分类
  3. 语音识别

在这里阅读更多关于的信息

结论

让我们总结一下本文所做的工作:

  • 我们从支持向量机如何工作的一般解释开始
  • 然后,我们用 Python 在一些虚拟数据上实现了它,随后在一个数据集上实现了它
  • 最后,我们研究了 SVM 的应用

您可以做什么:

  • 尝试从零开始实现支持向量机。为此,首先要理解支持向量机背后的数学原理。
  • 将您的实现与scikit-learn中的实现进行比较
  • 在各种其他数据集上测试上面的代码。

如果你有任何问题,请随时联系我。请继续关注我,因为我计划在未来讲述更多的机器学习算法

其他 ML 算法:

  • 线性回归——用 Python 实现的机器学习算法

https://medium.com/mlearning-ai/linear-regression-a-to-z-2ab3d1b7277c

  • k-最近邻——机器学习算法及其 Python 实现

https://nouman10.medium.com/k-nearest-neighbors-a-to-z-with-implementation-in-python-74630ffb79a2

  • 决策树——机器学习算法及其 Python 实现

https://nouman10.medium.com/decision-trees-machine-learning-algorithms-with-implementation-in-python-5bc034e67fc8

  • k-Means-机器学习算法及其在 Python 中的实现
  • 逻辑回归——用 Python 实现的机器学习算法

如果您觉得以上内容对您有用,请分享并随时支持我-->

支持向量机——多项式示例

原文:https://towardsdatascience.com/support-vector-machines-multinomial-example-8d9a86dde1d3?source=collection_archive---------23-----------------------

SVM 非常适合对数据进行分类,你可以看到很多二项式的例子。这是一个很好的 Matlab 多项式例子…

Sani2C 2017

如果你刚到这里,对 SVM 还不是很了解,那么先看看这篇文章。

让我们从一个好的数据集开始。

Iris flower 数据集是由英国统计学家和生物学家罗纳德·费雪在其 1936 年的论文《分类问题中多重测量的使用》中引入的多元数据集。它有时被称为安德森虹膜数据集,因为埃德加·安德森收集的数据量化了三个相关物种的虹膜花的形态变化。该数据集由来自三种鸢尾(刚毛鸢尾、海滨鸢尾和杂色鸢尾)的每一种的 50 个样本组成。测量每个样品的四个特征:萼片和花瓣的长度和宽度,以厘米为单位。你可以从 Kaggle 下载。

图 1:源 Kaggle

加载数据集

我们的第一步是加载数据集,并让归一化我们的特征以获得更好的性能。在创建 y 时,让我们使用 grp2idx 将物种转换成数字。

%% Loading our dataset
clear;
tbl = readtable(‘IRIS.csv’);
[m,n] = size(tbl);X = tbl{:,1:n-1};
[y,labels] = grp2idx(tbl{:,n});nl = length(labels);
[X_norm, mu, sigma] = featureNormalize(X);

分割训练和测试数据集

让我们把数据集分成一个训练集和一个测试集,确保随机进行。分成比例是 80/20。

%% split up train, cross validation and test set
rand_num = randperm(size(X,1));
X_train = X(rand_num(1:round(0.8*length(rand_num))),:);
y_train = y(rand_num(1:round(0.8*length(rand_num))),:);
X_test = X(rand_num(round(0.8*length(rand_num))+1:end),:);
y_test = y(rand_num(round(0.8*length(rand_num))+1:end),:);cv = cvpartition(y_train,’k’,5);

特征选择

我们需要决定哪些是我们最好的特性,所以让 sequentialfs 为我们做这项工作。然而,sequentialfs 需要一个代价函数,它被定义为一个名为' costfun '的内嵌泛函。该函数使用 matlab 的损失函数来评估每个模型的分类误差。最后,删除不需要的列

%% feature selectionopts = statset(‘display’,’iter’);
costfun = @(XT,yT,Xt,yt)loss(fitcecoc(XT,yT),Xt,yt);[fs, history] = sequentialfs(costfun, X_train, y_train, ‘cv’, cv, ‘options’, opts); % Remove unwanted columns
X_train = X_train(:,fs);
X_test = X_test(:,fs);

运行特性选择后,您应该会看到它所选择的列[1 3 4]。这是一个小数据集,你可能会得到不同的结果,但我相信你已经明白了;-).如果你运行一个 corrplot([X y]),看看最下面一行,就能理解为什么 1,3 & 4 在 y 轴上有最好的结果。

图 2

火车 SVM

Matlab 有一个很棒的函数叫做fitcecoc代表我们适合 SVM 的多类模型。

太好了。我们不需要做数学计算…

我们选择使用高斯核来评估我们的模型。如果你需要介绍的话,我会在这里解释高斯。然后让我们用损失函数来计算我们的准确度。

%% check loss against test dataset
t = templateSVM(‘KernelFunction’,’gaussian’);
mdl = fitcecoc(X_train, y_train,’Learners’,t,’Coding’,’onevsone’);
L = loss(mdl,X_test,y_test) * 100

如果选择了[1 3 4]列,那么您应该会看到 0%的损失。

预测的

好,现在我们知道我们有 100%的准确率,因为损失是 0%。Matlab 还有一个方便的预测功能来帮助我们做预测。在下面,我们需要使用 featureNormalize 中的 musigma 来确保我们的比例是正确的。当特征为[5.2 3.5 1.2 0.3]时,我们预测结果。

%% Predict a resultpx = bsxfun(@minus, [5.2 3.5 1.2 0.3], mu);
px = bsxfun(@rdivide, px, sigma);predict(mdl,px([1 3 4]))

一切顺利,你的结果是“1”,也就是“Iris-setosa”。

结论

尽管我们在这里进行了更详细的讨论,多项式 SVM 在 Matlab 中使用起来并不复杂。一如既往,一切都与数据有关,因此拥有一个好的数据集是关键。

支持向量机:基础知识

原文:https://towardsdatascience.com/support-vector-machines-the-basics-5a2acc0db450?source=collection_archive---------36-----------------------

对数据集进行分类时,SVM 是逻辑回归的一个很好的替代方法。它被用于线性和非线性分类,在 Matlab 和 Python 中都得到了很好的处理。

基础知识

SVM 执行的重要工作是找到一个决策边界来分类我们的数据。这个决策边界也被称为超平面

让我们以一个例子来解释它。视觉上,如果你看图 1,你会发现紫线是比黑线更好的超平面是有道理的。黑线也可以完成这项工作,但是稍微滑动一点接近其中一个红点,使它成为一个好的决策线。

从视觉上看,这很容易发现。

图 1

线性分类

所以,问题依然存在,SVM 是如何证明这一点的呢?如果我们坚持将紫色线作为最佳超平面,那么 SVM 将寻找最接近它的点,计算这些点和超平面之间的距离。这个距离被称为余量,如图 2 中绿色虚线所示。

在图 2 中,超平面和我们的数据点之间的这些间隙(亮绿色)被称为支持向量。

一旦它找到了聚类之间具有最大间隔的超平面, BOOM - BAM ,我们就找到了我们的最优超平面。因此,SVM 确保集群之间的差距尽可能大。

图 2

非线性分类

非线性分类在 SVM 也是可行的,事实上,这是 SVM 的闪光点。这里,SVM 使用Kernels将非线性数据映射到更高维度,使其成为线性数据,并找到最佳超平面。

事实上,SVM 总是使用核函数。不管它是线性的还是非线性的数据,但是当数据不是如图 1 所示的直线形式时,它的主要功能就开始发挥作用了。核函数为分类问题增加了维度。

图 3 示出了非线性情况下的 SVM 超平面的简化图示。

图 3

有几个核心选择,我们必须协助我们与 SVM。我发现你需要尝试一下,看看最适合你的数据。最流行的是高斯内核。这里是对这个内核的详细解释。我们选择的参数决定了高斯曲线的形状。我不会去解释数学,因为我们有图书馆为我们做这些。可以说,你可以看到图 3 是图 4 的俯视图。曲线的形状取决于我们接下来将讨论的参数

图 4

重要参数

“C”控制平滑决策边界和正确分类训练点之间的权衡。此参数表示 SVM 错误分类的错误惩罚。它保持了更平滑的超平面和错误分类之间的折衷。

  • 一个大的值意味着你会得到更多正确的训练点,因为你会有一个较低的偏差和一个较高的方差。不要把它做得太小,否则你的数据会不足。
  • 小的值意味着较高的偏差和较低的方差。不要把它做得太小,否则你会使你的数据过多。

【Gamma】方差决定高斯核的宽度。在统计学中,当我们考虑高斯概率密度函数时,它被称为标准差,它的平方 s2 是方差

我们何时使用 SVM、逻辑回归或神经网络?

如果 n =特征的数量,而 m=训练集的行数,则可以将此作为指导:

  • n =大(> 1000),m =小(<1000)

    )使用无内核的逻辑回归或 SVM

  • n =小(<1000), m=small (<10 000)

    )SVM 与高斯核

  • n =小(<1000), m=small (> 50 000)

    添加特性
    物流回归或 SVM 无内核

神经网络在上述所有情况下都能很好地工作,但是训练起来比较慢。

让我们在 matlab 中编码

现在,我们有了基础,让我们开始编码,这样我们就可以看到它的工作。在开始之前,从 kaggle 下载数据集。了解数据,你会发现第一列是不需要的,而我们的分类在第二列。因此,我们的特征是第 3 列到第 31 列。

图 5: 来源

我们将从加载数据开始,然后归一化特征。

%% setup X & Y
clear;
tbl = readtable(‘breast cancer.csv’);
[m,n] = size(tbl);
X = zeros(m,n-2);
X(:,1:30) = tbl{:,3:32};
[y,labels] = grp2idx(tbl{:,2});[X_norm, mu, sigma] = featureNormalize(X);

接下来,我们可以创建我们的训练和测试数据集。我们还将创建“cv ”,它将把训练集分成一个训练集和一个交叉验证集。“cv”将在 SVM 期间使用。

%% split up train, cross validation and test set
rand_num = randperm(size(X,1));
X_train = X(rand_num(1:round(0.8*length(rand_num))),:);
y_train = y(rand_num(1:round(0.8*length(rand_num))),:);X_test = X(rand_num(round(0.8*length(rand_num))+1:end),:);
y_test = y(rand_num(round(0.8*length(rand_num))+1:end),:);cv = cvpartition(y_train,’k’,5);

在运行 SVM 之前,让 sequencialfs 告诉我们哪些是最好的特性

%% feature selection
opts = statset(‘display’,’iter’);% create an inline function which will perform SVM on each column
classf = @(train_data, train_labels, test_data, test_labels)…
  sum(predict(fitcsvm(train_data, train_labels,’KernelFunction’,’rbf’), test_data) ~= test_labels);% fs will hold the most appropriate features
[fs, history] = sequentialfs(classf, X_train, y_train, ‘cv’, cv, ‘options’, opts);

现在,我们可以删除不适合假设的特征

%% retain columns from feature selection
X_train = X_train(:,fs);
X_test = X_test(:,fs);

最后,运行 SVM 并使用测试数据集来检查准确性

%% predict, try linear, gaussian, rbf
mdl = fitcsvm(X_train,y_train,’KernelFunction’,’rbf’,...
  ’OptimizeHyperparameters’,’auto’,...  
  ‘HyperparameterOptimizationOptions’,...
  struct(‘AcquisitionFunctionName’,...
  ‘expected-improvement-plus’,’ShowPlots’,true));
pred = predict(mdl,X_test);
accuracy = (mean(double(pred == y_test)) * 100)

您最终应该得到 98.24%的准确度,而结果图应该如下所示。

图 7:来自 Matlab

最后,在我们结束之前,这里是特征归一化函数

function [X_norm, mu, sigma] = featureNormalize(X)
  mu = mean(X);
  X_norm = bsxfun(@minus, X, mu);
  sigma = std(X_norm);
  X_norm = bsxfun(@rdivide, X_norm, sigma);
end

结论

对数据集进行分类时,SVM 是一个不错的选择。了解它何时是优于逻辑回归的好选择,以及何时使用高斯核或在没有核的情况下运行它是很有用的。

来源

  • 图 1-6 是在 www.desmos.com 建造的

通过大数据分析支持非洲的准过境流动

原文:https://towardsdatascience.com/supporting-para-transit-mobility-in-africa-through-big-data-analysis-7f3042a291b8?source=collection_archive---------21-----------------------

准备好狩猎 nje ma——一次斯瓦希里语的“美好之旅”

一个数据科学多学科项目,旨在研究和减少撒哈拉以南国家的“交通贫困”

莫桑比克大马普托地区的起点-终点矩阵。[图片由作者提供, Safari Njema

在许多发展中国家,包括运输、食品供应和私人交通解决方案在内的基本服务和活动不能被视为理所当然。在世界许多地区,运输服务不是在有组织和有结构的基础上提供的。这意味着您不能期望公共汽车或火车按照官方时间表运行,连接预先定义的位置(即公共汽车站或车站)。

“由于交通贫困,许多居民负担不起前往市中心或企业和机构所在地的费用,从而剥夺了他们享受城市化带来的全部好处”[联合国人居署——城市流动性,2019 年]

取而代之的是,基于自下而上的请求和私人主动倡议,一些类似的运输解决方案被创造出来,司机或公司的合作者建立了他们自己的解决方案。这就是所谓的非正规流动或辅助转移

"准运输类的服务是在没有官方许可的情况下提供的."[R. Cervero,A. Golub,非正规运输:全球视角]

在这种情况下, Safari Njema 项目 是一项数据科学研究活动,旨在重新设计发展中国家当前的辅助运输流动系统。该项目获得了米兰理工大学社会责任项目的 PoliSocial 奖。

该项目旨在实现以下目标:

  • 测试大数据支持辅助运输系统的潜力
  • 开发一种方法,为更有条理的报价和更高效、更安全的运输服务模式奠定基础;
  • 社会创新、组织设计和技术创新之间的交叉点提出一个分析模型,该模型可以被当地机构和决策者应用和复制;
  • 创建数学和统计模型应用于城市研究和城市政策,以开发合理的数据分析模型和算法;
  • 在数据收集困难的情况下支持快速决策

撒哈拉以南非洲的客运服务。photo BYA VerdadeCC-BY 2.0

实际上,这意味着:

  • 研究辅助运输移动模型,整合 GPS 数据、手机网络数据和其他来源
  • 构建客运服务绩效指标
  • 通过可操作的信息和数据可视化提供见解以改进决策
  • 实现移动服务的实时调整

该项目实施了针对这些目标的方法、分析和实验。已经在莫桑比克马普托市进行了实验,整合了实地收集的数据集和合作伙伴的数据集。

这些活动包括以下步骤。

马帕森

Safari 研究人员组织了一次 mapathon 活动,亲身体验马普托市的移动系统,并将交通方式与移动用户的移动联系起来。在 2019 年 9 月由马普托大都会交通局(AMT)组织的第二届可持续移动周(Semana da Mobilidade sustentável daÁ大都会区)期间,一队 Safari 研究人员用正式和辅助运输方法探索了这座城市,跟踪路径并收集数据。

地图马拉松的结果。[图片作者, Safari Njema group]

无障碍和社会包容

文献证明与城市隔离相关的社会成本与公共交通公平和效率相关。该项目强调如何通过测量公共交通对以下资源的物理可达性来分析公平、包容、隔离和财富:医疗服务、教育服务、CBD(中央商务区)、水源和金融服务。

马普托的 Paratransit access。[作者照片,Safari Njema 集团]

例如,获得医疗保健设施至关重要,并对人们的生活产生重大影响。为了让每个人都有平等的机会,卫生设施必须分布合理。到医疗机构的步行距离至关重要,尤其是对于没有汽车的穷人来说。

“两公里范围内没有卫生设施的贫困家庭的数量是非贫困家庭的三倍”。[世界银行关于马普托城市贫困的报告]

在我们的分析中,我们考虑了每个卫生机构产生的等时线及其水平,这是基于可用的护理服务。该指标适用于形态区域,即比现有行政区(区或区)更小的都市地区的详细和同质的细分。此处描述了其他可访问性结果

莫桑比克马普托卫生服务的可及性。[图片由作者 Safari Njema group 提供]

非正式公交地图

在马普托的移动性设置中,通过 GPS 数据测量移动性可能会产生两方面的影响。一方面,地方交通部门可以利用分析结果更好地规划和优化公共交通系统。另一方面,市民也可以访问公共交通系统的更翔实的描述。构建起点-终点矩阵是测量和理解这一现象的第一步。实施的研究分析了市民移动的 GPS 轨迹,描述了城市内形态区域之间的每小时流量。

给定预处理 GPS 轨迹获得的一组轨迹,我们将它们聚集成每小时的起点-终点矩阵。马普托大都市区被划分为无障碍、公平和社会排斥等形态区域。起点-终点矩阵是这样的网络,其中每个节点是一个形态区域,两个区域之间的每条边计算从一个区域开始到另一个区域结束的轨迹的数量。边权重对应于某一小时内离开该区域的轨迹的数量。

莫桑比克马普托市中心的起点-终点矩阵。[图片由作者 Safari Njema group 提供]

这些分析能够:在一天的不同时间找到吸引人的区域;并在一天的不同时间找到孤立的区域。这两个输出可以帮助决策制定者根据实时测量的需求有意识地改进报价。

自动路面检测

路面检测示例。[图片由作者 Safari Njema group 提供]

在像马普托这样的非洲大城市,道路状况严重影响着交通系统,阻碍了一些交通工具进入特定的道路,阻碍了沿特定路线的乘车,并使少数维护良好的走廊交通泛滥。自动道路路面检测包括基于路面的颜色及其特定位置开发旨在对路面进行分类的机器学习管道。

绩效评估系统

该项目综合分析了(1)涉及正规和准运输流动系统的现有研究和项目,(2)关于绩效测量系统和指标的二手资料,以及(3)通过马普托行动研究方法收集的主要资料,为发展中国家的流动系统评估制定了一个理论框架。

非正规交通的绩效指标模型。[图片由作者 Safari Njema group 提供]

进一步的结果和分析见项目网站:

*https://www.safari-njema.polimi.it/

您还可以在 YouTube 上观看该项目的介绍视频(意大利语音频)😗

调查医疗保健支出数据

原文:https://towardsdatascience.com/surveying-healthcare-spending-data-aee5e320e40b?source=collection_archive---------37-----------------------

医疗费用数据的简短调查

图片由 RF 提供。_.工作室像素

随着人口老龄化和疾病患病率的增加,美国的医疗保健支出继续快速增长。发表在《美国医学会杂志》( JAMA)上的一项研究报告称,1996 年至 2015 年间,美国的医疗支出增长了近 1 万亿美元。

由于缺乏医疗保健透明度,医疗成本和质量对消费者来说往往是不透明的。如果消费者能够获得高质量的医疗保健信息,他们可能会在其医疗保健服务中有更多的代理。例如,发表在《美国心脏杂志》上的另一项研究发现,在调整了患者风险和住院时间后,纽约州冠状动脉旁路手术费用中 42%的可变性是由实施手术的医院解释的。医院考虑了成本的可变性,而不是住院时间和病人风险。如果患者能够获得这些信息,他们就有可能通过寻找医疗服务提供商来节省数千英镑的医疗支出。

实现医疗支出透明的一个步骤是向公众提供高质量的医疗数据。在本帖中,我们将简要调查一些包含医疗费用信息的可用公共数据源。你可以在这里探索阿维森纳。

经济合作与发展组织( OECD)

经合组织是一个国际组织,报告世界各地的卫生支出和医药支出。在这里,您可以找到按年份和国家报告人均医疗总支出的图表。您可以用图表或表格的形式查看数据。您甚至可以下载一个. csv 格式的数据用于进一步分析。

合格健康计划(QHP)数据

Healthcare.gov 向公众提供 QHP 景观数据。这些数据集包括联邦政府运营市场的各州的个人和家庭健康计划。这些数据包括发行人名称、县名称、计划营销名称、医疗最高自付费用、医疗免赔额、初级保健医生、急诊室和专家等信息。如果你有兴趣探索 Python 中的数据,请查看 分析健康保险市场数据 数据可用此处

阿维森纳健康科技

阿维森纳是用户搜索和比较医疗服务价格的免费平台。目前,该网站上充斥着来自用户的匿名帖子,这些用户报告了正常分娩、剖腹产、健康检查等服务的医疗支出。

每个职位的服务名称,费用,保险和医院显示。如果你点击一个帖子,你可以看到更具体的人口统计信息,如年龄,性别,体重和身高。

这些信息对消费者来说非常有价值。考虑到研究发现冠状动脉旁路手术成本中 42%的可变性是由实施手术的医院解释的。如果洛杉矶需要冠状动脉旁路手术的患者可以搜索他们覆盖的所有医院,并选择最便宜的选项,这可以大大减少美国的医疗支出,同时支持竞争激烈的医疗市场。目前,阿维森纳没有很多用户,但随着用户群的增长,医疗保健支出信息的数据库将继续增长。该平台允许用户匿名免费注册,并开始发布和搜索医疗支出信息。

阿维森纳健康技术公司的任务是收集高度描述性的服务成本数据,提供服务价格估计,并解释医疗保健价格的可变性。这可以帮助用户选择最佳的医疗服务。具体来说,它可以增加医疗保健市场的竞争,从而为患者提供更好的服务,并改善医疗保健结果。

结论

总之,在这篇文章中,我们讨论了访问医疗支出数据的 3 个公共数据源。首先,我们讨论了经合组织的人均总支出数据。这包含由附加描述符(如政府和强制医疗保险)索引的特定国家医疗保健支出数据。这提供了关于哪些国家在医疗保健服务上花费最多,哪些国家花费最少的高层次见解。

接下来,我们讨论了 healthcare.gov 可用的 QHP 景观数据,这些数据提供了大量有用的信息,例如县一级的自付费用。分析县级自付费用对于寻求不同医疗保健财务选择的患者非常有用。

虽然经合组织和 QHP 等来源很有用,但详细程度有限。这些来源没有提供重要的人口统计信息,这些信息可能对成本有重大影响,如性别、年龄和体重。例如,像超重的老年人这样的高风险患者可能比年轻的超重者有更高的冠状动脉搭桥术自付费用。

阿维森纳医疗保健技术平台旨在向公众提供高度具体和高质量的医疗保健支出数据。这个公开的匿名平台允许用户安全地共享和搜索医疗保健支出信息,这可以促进医疗保健服务的健康竞争市场。我希望你觉得这篇文章很有趣。感谢您的阅读!

生存分析:删失,生存函数和风险函数。

原文:https://towardsdatascience.com/survival-analysis-censoring-survival-functions-and-hazard-functions-35a3325ece40?source=collection_archive---------19-----------------------

塔尼娅·科托阿加在 Unsplash 上拍摄的照片

在最流行的机器学习和统计分析框架的实现中,经常被忽略的是生存分析。简单地说,生存分析是一个感兴趣的事件发生所需要的时间。虽然这看起来很简单,但现实要复杂一些。在本文中,我们将介绍一些在进行生存分析或决定它是否是解决您问题的正确工具时需要理解的高级概念。

生存分析解决什么问题?

正如你可能已经猜到的名字,生存分析在历史上一直被医学研究团体用来测量在各种情况下某些药物或治疗的存活率。这远不是它的唯一用途,因为它也常用于商业。你可以使用生存分析来预测你当前的一个客户何时会停止使用你的服务(流失),或者你制造的一台机器何时会坏掉(故障时间分析)。社会学家使用生存分析来预测事件的发生和时间(事件历史分析)。

你可能会问自己“难道没有其他工具,比如回归或分类,可以解决这个问题吗?”。答案是,没有,原因呢?审查。

审查

删截的受试者是那些在观察窗内没有经历过感兴趣的事件的受试者。让我们假设我们是被派往小笠原群岛的研究人员,研究当地蜗牛种群的生存,对抗在岛上横行的船鼠( Rattus rattus )研究显示岛上船鼠数量的增加导致了陆地蜗牛种类的减少(具体来说,是生活在地上/树上的壳更大的蜗牛)。我们到达这个岛,带着足够的资金和物资去观察更大的地上蜗牛一个月。

小笠原群岛无助的陆生蜗牛的凶手。鸣谢:克里桑,CC BY-SA 3.0<https://creativecommons.org/licenses/by-sa/3.0>,通过维基共享

在我们的例子中,假设我们可以观察到 500 只上述提到的蜗牛,当它们进入我们的观察区域时,观察区域是森林中 1 英亩的土地。当蜗牛进入这个区域时,我们可以观察到它们。我们还神奇地拥有很多蜗牛的数据,比如:壳的直径,重量,在树上呆的时间,在地上呆的时间。现在我们要坐下来,等着记录我们被老鼠吃掉的蜗牛朋友,或者活着讲述这个故事。

一个月后,我们记录了所有蜗牛被老鼠吃掉的次数,但是我们的资金已经用完了,我们不得不离开。我们在一个月中观察到的 B:仍然活着或 C:离开观察区域的所有蜗牛都被认为是正确审查的。在观察期内未发生感兴趣的事件(他们的死亡)。

图片作者。

右删截是最常见的删截类型,也是我们的蜗牛示例中唯一有意义的类型。使用传统的分类和回归模型,所有属于 B 类和 C 类的观察值都必须被丢弃。通过生存分析,我们可以利用所有的观察结果来预测某一事件在特定时间发生的概率。

生存和危险函数。

图片作者。

生存函数 S(t),通常用 x 轴上的时间和 y 轴上事件发生的概率来表示。如果上图中的蓝线是平坦的,随着时间的推移保持接近 100%,那么这对蜗牛来说是个好消息——这意味着许多蜗牛在观察期内存活下来。然而,在上面的例子中(图中使用了虚构的数据),我们可以看到存活率逐渐下降,然后在第 20 天急剧下降。这表明蜗牛的存活率很低。

风险 h(t) ,是在时间 t 被观察的蜗牛在那个时间发生“事件”(被老鼠杀死)的概率。生存函数和风险函数之间的唯一区别在于,前者侧重于不发生事件,而后者侧重于事件发生。

随着日子一天天过去,死亡的概率越来越大。

结论

说到底,小笠原群岛上可怜的蜗牛的前景是暗淡的。但是通过生存分析,我们能够比其他方法更有效地预测蜗牛死亡的时间。这只是一个非常复杂的主题的皮毛,但是在进入更难的东西之前,掌握这些基本概念是很好的。以后打算再深入一点,用 pysurvival 实现一些生存分析模型。

在那之前,编码快乐!

💻可以随意查看我的网站

来源:

https://square.github.io/pysurvival/intro.html http://userwww.sfsu.edu/efc/classes/biol710/survival/surv-anal.htm http://www.sthda.com/english/wiki/survival-analysis-basics https://sphweb.bumc.bu.edu/otlt/mph-modules/bs/bs704_survival/BS704_Survival_print.html

临床试验中的生存分析— Kaplan-Meier 估计量

原文:https://towardsdatascience.com/survival-analysis-in-clinical-trials-f87b8cbc2b1a?source=collection_archive---------19-----------------------

药物功效建模及其背后的数学

照片由 Unsplash 上的拍摄

从发现一种活性物质到确定其剂量、安全性和有效性,任何药物上市的过程都是漫长而昂贵的。最终,当局如何决定一种新的治疗方法对患者有益,并且应该从现在开始由医生来管理?

药物开发中最昂贵也可以说是最重要的部分是临床试验的后期阶段。在此期间,新的治疗方法被给予目标患者群体,并且(通常)还有一个对照组,给予安慰剂。病人不知道他们正在接受哪种治疗,医生也不知道。这被称为双盲,确保结果不受对新疗法的信任程度的影响。

数据格式

在评估临床试验数据时,第一个也是最常见的分析是用 Kaplan-Meier 估计量对生存函数进行非参数估计。我们将在来自 R 包survival的数据集ovarian上解释这个估计器。它来自于 1979 年发表的一项研究,包括对 26 名卵巢癌患者的观察。在研究开始时,一半的患者被随机分配到标准治疗组,另一半被分配到联合治疗组。在本文中,我们仅使用数据集中的以下变量:

  • futime :生存或审查时间
  • fustat :审查状态(0 =审查,1 =观察)
  • rx :治疗组(1 =单用环磷酰胺,2 =环磷酰胺加阿霉素)

现在让我们看看前六个观察结果。

library(survival)
data(ovarian)
head(ovarian)##   futime fustat     age resid.ds rx ecog.ps
## 1     59      1 72.3315        2  1       1
## 2    115      1 74.4932        2  1       1
## 3    156      1 66.4658        2  1       2
## 4    421      0 53.3644        2  2       1
## 5    431      1 50.3397        2  1       1
## 6    448      0 56.4301        1  1       2

对于存活的患者(fustat=0),我们只知道他们存活到分析时,但没有关于他们存活时间的更多信息。函数Surv()在 R 中的输出是生存时间的数组,加上那些没有观察到死亡的患者的加号。

Surv(ovarian$futime, ovarian$fustat)## [1]   59   115   156   421+  431   448+  464   475   477+  563 
## [11]  638   744+  769+  770+  803+  855+ 1040+ 1106+ 1129+ 1206+
## [21] 1227+  268   329   353   365   377+

有了这些信息,我们如何去估计,比如说,这项研究中患者的中位存活时间?

关于生存函数的直觉

首先,我们估计所谓的生存函数。如果 T 是表示死亡时间的随机变量,生存函数 S(t) 定义为

这只是对死亡概率在 t 之前或之时的补充,是 T: 的累积分布函数 F(t)

那么 S(t) 怎么估计呢?让我们首先只关注在随访期间死亡的患者子集。您可以检查有十二个这样的患者(fustat=1)。基于这个数据集,我们如何估计一个病人在治疗开始后至少能活 10 个月的概率?

直觉上,答案很简单。我们计算存活时间超过 10 个月的患者比例,这将是我们对 10 个月生存函数的估计。在这种情况下,它是 8/12 = 2/3。

事实上,我们可以在我们选择的任何时间点重复这个练习。如果在 10 至 11 个月之间没有患者死亡,那么存活 11 个月的估计值将与存活 10 个月的估计值相同。

一般来说,只有在所讨论的时间点之间至少有一人死亡,答案才会不同。计算并绘制所有时间点的这种概率,我们得到以下曲线:

图 1:仅使用观察到死亡的患者的存活函数估计。

该函数的步长正好是死亡时间。

正确估计生存概率

显然,忽略仍然存活的患者会导致对真实存活概率的低估,因为根据定义,我们只分析了存活时间最短的患者子集。对于所有其他患者,我们不知道死亡时间,但我们有他们生存时间的下限。

假设我们想估计存活过去 20 个月的概率,但现在是以正确的方式,考虑到分析时还活着的患者。这一次,我们首先看一下我们使用plot.survfit()从 R 得到的图

km <- survfit(Surv(futime/30.42, fustat) ~ 1, data = ovarian)

曲线上的点出现在患者被审查的时候,即在此之后我们没有关于该患者存活时间的信息的时候。

图 2:r 中的生存函数估计。曲线上的点表示一个删失事件。

R 是怎么算出这些估计值的?直到第一次审查事件,我们可以用和上面一样的方法计算,除了现在我们有更多的病人。而且由于那些增加的病人都是幸存者,这样会让存活的概率更高。

现在,存活超过 10 个月的概率的(正确)估计是存活 10 个月或更长时间的所有患者的比例。这个比例是(26–4)/26,大概是 0.846。

推导卡普兰-迈耶估计量

为了计算首次删失事件后的生存概率,我们使用全概率法则。让我们用 tᵢ.来表示第 i 个事件(死亡或审查)的时间那么至少生存到 t 的概率是

第一个被审查事件后的第一个死亡发生在 t₁₀ (总共是第 10 个事件)大约 14 个月。在图表上,活到 t₇t₈t₉ 的概率似乎是相同的。直觉上,这是因为没有已知的死亡发生,所以我们不能相应地更新我们的估计。因此,上面的等式变成了

鉴于一名患者一直存活到 t₉.,仍需估计在 t₁₀死亡的概率这很容易做到,因为根据我们的数据,我们知道在 t₁₀ ,在我们知道仍然活着的剩余 26–9 = 17 名患者中,有一名患者死亡(这被称为 t₁₀ 的风险人数)。因此我们认为这个概率是 1/17。

但是现在我们有了一种方法来找出直到最后一次事件发生的所有时间的生存概率, t₂₆

我们刚刚推导了所谓的生存函数的 Kaplan-Meier 估计量 S(t),生存时间长于 t 的概率通常,对于任何 t 和患者的生存时间 T ,我们可以将上面的详细等式改写为

t 是小于 t. 的最大事件时间,更准确地说,卡普兰-迈耶估计量可写成

变量 r 是在时间 t d 是在 t 发生的死亡人数(注意,在我们的方法中这总是等于 1)。

当事件数趋近于无穷大时,这个估计量收敛到真生存函数 S(t) ,为此它也被称为乘积极限估计量

上式中计算卡普兰-迈耶估计量所需的所有项在 R 中很容易得到,如下所示。

summary(km)##   time n.risk n.event survival std.err lower 95% CI upper 95% CI
##   1.94     26       1    0.962  0.0377        0.890        1.000
##   3.78     25       1    0.923  0.0523        0.826        1.000
##   5.13     24       1    0.885  0.0627        0.770        1.000
##   8.81     23       1    0.846  0.0708        0.718        0.997
##  10.82     22       1    0.808  0.0773        0.670        0.974
##  11.60     21       1    0.769  0.0826        0.623        0.949
##  12.00     20       1    0.731  0.0870        0.579        0.923
##  14.17     17       1    0.688  0.0919        0.529        0.894
##  15.25     15       1    0.642  0.0965        0.478        0.862
##  15.61     14       1    0.596  0.0999        0.429        0.828
##  18.51     12       1    0.546  0.1032        0.377        0.791
##  20.97     11       1    0.497  0.1051        0.328        0.752

使用上面的公式计算第四列survival需要前三列。 t ᵢ' s 是列timers 是列n.riskd 是列n.event。标准误差和相应的置信区间将在后面讨论。

可视化治疗效果

我们希望与安慰剂或目前常用的治疗药物(称为“标准治疗”)相比,新疗法将延长预期生存期。

由于事件被删截,我们不能简单地比较两组间存活时间的样本均值,因为我们没有这个统计数据。在本文中,我将只展示如何可视化效果,而不是如何正式测试。这是现在真正容易的部分,因为我们简单地为两个不同的治疗组绘制了两条不同的曲线,再次使用plot.survfit(),与拟合

km_groups <- survfit(Surv(futime/30.42, fustat) ~ rx, data = ovarian)

图 3:两个治疗组分别估计的 Kaplan-Meier 曲线。

这种联合治疗似乎可以延长生存期,但是我们现在还不知道这种效果是否显著。

置信区间

到目前为止,我们还没有处理不确定性。但是由于只有少数患者,因此事件数量相对较少,曲线估计可能相当不准确。即使我们碰巧在其他研究中有更多的患者和事件,就像任何估计一样,评估精确度也很重要。使用summary.survfit()函数可以很容易地获得 R 中的逐点置信区间。本例中的配置项如下所示:

图 4:带置信区间的卡普兰-迈耶曲线。

请注意,曲线的右边部分具有相当大的置信区间,这是由后来观察到的少量事件给出的。但是这些置信界限从何而来呢?

为了计算置信区间,我们需要估计 KM 估计量的方差及其(渐近)分布。

格林伍德公式

r 在计算方差估计的置信区间时使用格林伍德公式,即

然后,我们可以利用以下性质:在某些条件下,KM 估计值的分布收敛于正态分布,格林伍德方差为渐近方差:

这允许我们在任何 t,使用公式得到逐点置信区间

具有标准正态分布的分位数。然而,R ( conf.type=log)中的默认conf.type参数实际上是利用了 S(t) 估计的对数分布,置信区间具有以下形式:

最后,使用的另一种置信区间是对数减对数(conf.type=log-log)。它的边界总是位于(0,1)区间内,这是一个理想的性质,因为我们正在估计概率。

摘要

卡普兰-迈耶图显示了对生存函数的估计,通常是临床研究的第一个分析点。它可以用于可视化治疗效果,并且具有不依赖于关于数据分布的任何假设的优点。我们观察的事件越多,就越接近真实的生存函数。

因此,主要的总结点是,知识管理估计器

  • 充当生存函数的估计量。
  • 不依赖于任何分布假设(即非参数)。
  • 通常用于可视化临床研究的结果。

一个主要的限制是我们无法用这种方法控制协变量。因此,我们无法可靠地比较治疗组,以防某些协变量的不平衡对存活时间产生显著影响。

限制

  • KM 估计值只是描述性的。例如,它不能用于测试治疗效果。这可以通过对数秩测试来完成。
  • 曲线的右边部分往往很不准确,在解释图表时应该考虑到这一点。
  • 我们无法控制协变量。

参考

[1] J.H. Edmunson,T.R. Fleming,D.G. Decker,G.D. Malkasian,J.A. Jefferies,M.J. Webb 和 L.K. Kvols,晚期卵巢癌与微小残留病的不同化疗敏感性和影响预后的宿主因素(1979) 癌症治疗报告,63:241–47。

[2] M 格林伍德,《癌症的自然持续时间》(1926)。关于公共健康和医疗主题的报告,女王陛下办公室,伦敦,33,1–26。

临床试验中的生存分析——对数秩检验

原文:https://towardsdatascience.com/survival-analysis-in-clinical-trials-log-rank-test-8f1229e7f0f0?source=collection_archive---------11-----------------------

我们如何模拟药物疗效?第二部分

在本系列的第 1 部分的中,我解释了 Kaplan-Meier 生存曲线估计量背后的推理。虽然它是一种用于可视化临床试验结果的无处不在的工具,涉及到时间-事件分析,但它只是描述性的。为了能够得出结论并展示新疗法的益处,我们需要一个正式的测试程序。一个这样的程序是对数秩检验。

我将看看它是如何得到的,为什么它仍然被认为是药物疗效的最重要的指标之一。

我们从一个survfit对象的ggplot开始,使用与第 1 部分相同的数据集:

library(survival)
library(survminer)
data(ovarian)fit <- survfit(Surv(ovarian$futime, ovarian$fustat) ~ rx, 
               data = ovarian, conf.type="log")p_fit <- ggsurvplot(
  fit, conf.int = TRUE, pval = TRUE
)
p_fit

如何获得生存概率估计值和置信区间在第 1 部分中描述。如果pval被设置为TRUE,该函数还打印出p-值 0.3,这是一个对数秩测试的结果。那么是怎么计算出来的呢?

费希尔精确试验

对数秩检验基本上是多个独立的 Fisher 精确检验汇集在一起。稍后我会解释我的意思。但是有必要首先了解费希尔精确测试是如何工作的。所以让我们从一个虚构的例子开始。

假设大学二年级有一门统计学导论课。他们可以在学期中参加辅导课,有些人参加,有些人不参加。期末考试后,我们想看看考试不及格是否与辅导课出勤有关。因此,对于每个学生,除了他们是否通过外,我们还记录他们是否至少有 75%的时间出席辅导课。我们得到了下面的图片:

图:四个类别的学生人数。

现在要测试补习出勤和通过考试是否独立。概率表如下所示:

图:概率表。

例如,这意味着

而我们要检验的假设是h₀:π₁₁/π₁₊=π₂₁/π₂₊.现在假设这个假设是真的。这意味着,我们预计辅导出勤率高的小组中不及格学生的比例与出勤率低的小组中不及格学生的比例相似。换句话说,

通过并参加了 75%以上辅导课的学生的期望值是整个样本中通过的学生的比例乘以参加了 75%以上辅导课的学生人数。

其中 A 是随机变量,其值是参加了 75%以上的辅导课并通过考试的学生人数。 A 的分布如何?

注意 n++ 以及余量(失败/通过&出勤-是/否计数)是固定的。在零假设下, A=a 的概率(通过并参加 75%+辅导课的学生人数等于 a 的概率)是如果在 n++= 343 名学生中,其中 217 名参加了 75%+辅导课,我们随机挑选 281 名, a 将参加 75%+辅导课的概率。

这是因为我们假设这 281 名通过测试的学生和全部 343 名学生在去补习班的时间上没有什么不同。 A 的分布被称为超几何分布,人们可以从维基百科推导或复制其概率质量函数和方差:

为这么大的样本计算精确的 p- 值是有问题的,但是我们可以使用以下统计的卡方近似值来代替:

分析来自多个站点的数据

假设同样的实验在 12 所不同的大学进行。我们不想将这些合并到一个表中,因为各个大学之间可能会有差异。我们想检验以下假设:

h₀:π₁₁=π₁₂, π ₂₁ = π ₂₂,…, πk ₁ = πk₂ ,其中 k 为站点数量(本例中为 12)。

这可以使用Mantel–Haenszel 统计 : 来完成

i 是组指数,O 是观察到的死亡的总和, E 是预期死亡的总和, V 是所有地点的人口 1 中死亡的方差的总和。我们将总和代入 MH,注意它的渐近分布:

这是用来测试零假设通常的方式。现在,我们可以使用同样的统计数据,并将其应用于我们的审查数据。

对数秩检验

这与对数秩检验有什么关系?本质上,我们把死亡被观察的每个时间点看作上面例子中的“大学”,并为每个时间点创建一个列联表。

即使样本(“大学”)不是独立的,门泽耳-海恩斯泽尔统计量的渐近分布仍然是一个自由度的卡方分布。

实际上,我们测试了假设 H₀: F₁ = F₂,或者联合治疗和标准治疗组的生存曲线相等。

手工对数秩检验

现在让我们检查一下他们是如何从文章开头的图上获得p-值的。我们基本上为一个事件的每个时间点 t 创建一个列联表。

手工进行对数秩检验。仅显示了 4 个事件时间,但整行都是针对所有事件时间计算的。审查时间对统计数据没有贡献,但是如果将风险数据包含在表格中,就更容易跟踪这些数据。

从这个表中,我们可以计算出在零假设下每个 t i 的死亡数 a 以及 A 的期望和方差。剩下的就是将这些相加,并代入我们的测试统计量 MH 的表达式。在这种情况下,MH =(7–5.23)/2.94 = 1.066。

注意

  • 请注意,事件时间不进入统计计算,只有他们的排名。

R 中生存包的对数秩检验

在 R 中,可以使用包survival中的函数survdiff()进行对数秩测试。

logr <- survdiff(Surv(ovarian$futime, ovarian$fustat) ~ rx, 
                 data = ovarian)
logr## Call:
##   survdiff(formula = Surv(ovarian$futime, ovarian$fustat) ~ rx,
##            data = ovarian)
## 
##       N Observed Expected (O-E)^2/E (O-E)^2/V
## rx=1 13        7     5.23     0.596      1.06
## rx=2 13        5     6.77     0.461      1.06
## 
## Chisq= 1.1  on 1 degrees of freedom, p= 0.3

除了由于四舍五入造成的一些差异,测试给出的答案与上面手动计算的答案相同。特别是(O-E)^2/V是 1.06,这是 MH 统计。具有 1 个自由度的卡方分布变量大于该值的概率为 0.3,可以使用以下代码进行检查:

1 - pchisq(1.06, df = 1)## [1] 0.3032152

因此,我们不能拒绝联合治疗不比标准治疗更好(或更差)的无效假设。

控制协变量:分层

为了解释协变量,我们可以将样本分层。在这种情况下,数据集中有一个变量 resid.ds ,指示在研究开始时是否存在最小的残留疾病(resid.ds=1),或者疾病是晚期的(resid.ds=2)。

分层的作用是对每一层的一系列列联表分别进行分析,然后汇总结果。这确保了如果患有轻微残留疾病的妇女与患有广泛残留疾病的妇女之间存在差异(这是可以预期的),这将不会扭曲对治疗效果的估计。

协变量不平衡

在对照组中,患有广泛残留疾病的患者比患有轻微残留疾病的患者多(8 比 5),而在治疗组中,这一比例更平衡(7 比 6)。

table(ovarian$resid.ds, ovarian$rx, dnn=c("resid.ds", "rx"))##         rx
## resid.ds 1 2
##        1 5 6
##        2 8 7

survdiff()函数如何分层

为了确保我们测试的是治疗的差异,而不是晚期和非晚期疾病患者之间的差异,我们分别计算了每一层中的观察计数和预期计数及其方差(广泛残留疾病和微小残留疾病)。右上方列出了每个治疗组的事件时间(审查时间后有一个加号):

为有广泛残留疾病的组单独计算的对数秩检验值。

为残留疾病最少的组单独计算的对数秩检验值。

将结果汇总在一起(取两组的 a 、E( A )和 Var( A )之和,我们得到 MH =(7–5.09)/(0.743+2.093)= 1.286。现在,我们检查在公式中添加了strata(resid.ds)参数时survdiff()函数的输出:

logr_strat <- survdiff(Surv(ovarian$futime, ovarian$fustat) ~ rx + 
                         strata(resid.ds), data = ovarian)
logr_strat## Call:
##   survdiff(formula = Surv(ovarian$futime, ovarian$fustat) ~ rx + 
##              strata(resid.ds), data = ovarian)
## 
##       N Observed Expected (O-E)^2/E (O-E)^2/V
## rx=1 13        7      5.1     0.712      1.28
## rx=2 13        5      6.9     0.525      1.28
## 
## Chisq= 1.3  on 1 degrees of freedom, p= 0.3

同样,除了舍入误差之外,我们获得了 MH 的相同结果,即(O-E)^2/V是 1.28。

在这种情况下,p-值仍然是 0.3 ,因此与分层前的值相比变化不大。请注意,对于预计对存活率有显著影响的重要协变量,在随机化阶段(即设计实验时)进行分层至关重要。这意味着,我们必须确保每个治疗组中来自各个阶层的患者比例大致相同,以便检测出足够有效的潜在治疗效果。

摘要

当我们想要确定两组的生存分布是否不同时,使用对数秩检验。这是证明药物具有积极治疗效果的最普遍和公认的方法之一。它是对 Fisher 精确检验的一种改编,或者更准确地说,是对删失数据的 Mantel Haenszel 检验。为事件的每个时间创建一个列联表,然后汇集结果以计算所需的统计数据。

如果我们想避免意外测试另一个组间不平衡的协变量,或防止治疗效果被协变量掩盖,我们可以使用分层。在这种情况下,为协变量的每个级别分别创建列联表,并将结果汇总在一起,如上所示。

关于对数秩检验的进一步说明

  • 对数秩检验是非参数的:我们没有假设事件时间的任何分布。
  • 然而,它是作为半参数 Cox 比例风险模型中的得分测试出现的(下一篇文章将详细介绍)。
  • 请注意,在比较两条存活曲线的情况下,“检验显著的治疗效果”是一项任意的任务。这里很好地展示了所有具有积极治疗效果的不同场景。log-rank 面向这些场景中的一种。

组织病理学生存模型

原文:https://towardsdatascience.com/survival-models-for-histopathology-b26efffdba1b?source=collection_archive---------18-----------------------

思想和理论

从整张幻灯片图像预测患者结果的机器学习技术综述。

组织病理学图像的机器学习算法变得越来越复杂。从检测和分类细胞和组织到预测生物标志物和患者结果。更简单的任务依赖于病理学家对组织中特定特征的注释。但是生物标记和结果更加复杂。算法必须在事先不知道组织的哪些区域或其外观特征是重要的情况下解读大的整个载玻片图像。

已经可以使用癌症分期、分子特征或临床变量进行风险分层。然而,改善预后的洞察力是一个活跃的研究领域。预后是指患者接受标准治疗后的可能结果,例如,患者肿瘤复发、发生远处转移或死亡的可能性。

不管目标是什么,创建这样一个算法的挑战都是相似的。H&E 全片图像较大,组织外观多样。与寻找有丝分裂或分割组织类型的方法不同,病理学家无法注释组织的哪些区域与患者结果相关——至少没有任何高度的确定性。

肿瘤分级指定了细胞外观的测量,但并不总是预后的良好测量。病理学家对等级的观察也伴随着观察者之间的高度可变性。

结果预测模型的目标是根据风险对患者进行分层。本文将概述使用深度学习的组织病理学图像的结果预测模型的关键组件。我将概述选择图像块进行建模的策略、生存模型优化的损失函数选项、聚合图像块以形成整个幻灯片预测的技术,以及一些有趣的模型扩展。

三个风险群体的卡普兰迈耶曲线[ Wulczyn2020

选择图像补丁

在 gigapixel 整张幻灯片图像上训练深度学习模型的第一个挑战是,图像太大,不适合 GPU,因此无法进行端到端训练。患者水平的存活时间适用于整张载玻片(或多张载玻片)。虽然病理学家可以在幻灯片中标注肿瘤区域,但他们无法准确识别哪些小块对模型有帮助,这是模型的工作。一些研究让病理学家注释肿瘤区域,深度学习模型仅使用这些区域。其他人训练 CNN 模型来区分肿瘤和非肿瘤,然后仅将肿瘤区域用于生存模型。还有一些包括模型中的所有组织区域。本节概述了这些策略。

随机补丁

Zhu 等人让病理学家注释每个肿瘤内图像区域。然后,他们从每个 ROI 中随机采样一个大块,并训练一个 CNN 生存模型[ Zhu2016 ]。Wulczyn 等人也随机对小块进行采样来训练他们的模型。

从由病理学家注释的感兴趣区域中随机取样的片[ Zhu2016 ]

预测补丁

其他方法不是随机抽取补丁,而是找出最有预测性的补丁。Courtiol 等人训练了一个 CNN 来预测每个图像斑块的风险[ Courtiol2019 ]。然后,该模型为每个患者选择最高和最低得分的补丁,以训练最终的生存模型。

为生存模型训练选择最高和最低得分的图块[court io 2019

检查最高和最低的生存补丁是特别有见地的。Courtiol 等人发现存活差的斑块主要位于基质区域,并让病理学家识别它们的共同特征。

通过识别得分最高和最低的图块进行模型解释[court io 2019

补丁聚类

在随后的工作中,朱等人对训练集中所有幻灯片的图像块进行聚类。然后,他们为每个集群训练了一个单独的 CNN 生存模型。几乎没有预测能力的聚类被丢弃。来自其余集群模型的特征在来自每个集群的补丁上聚集。另一个生存模型使用线性生存模型将聚集的特征转化为风险预测。

图像块聚类和聚集特征以预测风险[ Zhu2017

岳等人采用了相同的方法,对补丁进行全局聚类,并分别为每个聚类训练生存模型[ 岳 2019 ]。仅取被确定为有区别性的聚类,他们计算了斑块预测的归一化直方图,并使用 SVM 来学习聚类级别的预测。

Muhammad 等人同时学习了图像碎片的全局聚类和生存模型,该生存模型用来自每个聚类的一个图像碎片来表示每张幻灯片[ Muhammad2021 ]。

Yao 等人对每个患者的图像补片进行聚类,使他们能够选择具有不同外观的补片子集[ Yao2020 ]。

聚类图像补片还可以实现组织的空间排列的测量。Abbet 等人对图像块进行聚类,并将每个图像的特征向量计算为聚类概率和聚类转移概率[ Abbet2020 ]。根据这些特征,他们训练了一个线性生存模型。这些可解释的特征确定了与较差或较好结果相关的组织相互作用。

组织分割

其他技术为模型训练带来了更高层次的知识,特别是图像中存在的组织类型。病理学家或机器学习模型将组织分割成一组类别,使得每个类别都可以被适当地建模。

Yamashita 等人将图像斑块分类为肿瘤或非肿瘤,并选择最有可能是肿瘤的 100 个斑块[ Yamashita2021 ]。然后他们的生存模型只在这些小块上进行训练。

选择最可能的肿瘤块进行模型训练[ 山下 2021

Klimov 等人还训练了一个 CNN 模型来将图像分割成组织类别。癌症和间质斑块用于训练 CNN 来预测转移风险[ 克里莫夫 2021 ]。

更广泛的分割任务也有助于生存预测。Kather 等人分割了九种组织类型,并为每种类型训练了一个存活模型。他们选择了那些具有高风险比率的人,并在结合 CNN 特征时用这个比率对他们进行加权。

深层基质得分计算为最能预测患者结果的组织类型特征的加权和[ Kather2019 ]

或者,组织分割可用于计算更多可解释的存活预测特征。王等人确定了淋巴结和肿瘤区域的面积,然后根据这两个组织面积的比值来预测患者的风险。

组织分割可以允许模型仅关注特定的组织类型。Bhargava 等人计算了肿瘤内间质的手工特征,以捕捉其形态[ Bhargava2020 ]。特征包括间质结构,细胞核的连接性,以及细胞核的形状和方向。这个特征集使他们能够成功地预测非裔美国患者的结果;这些特征对白种美国人的预后预测性较差。可解释的特征是理解其模型的关键,并强调了基质形态学的重要性。

用于预测患者风险的肿瘤内基质特征[ Bhargava2020

度量和损失函数

上一节讨论了为建模选择图像补片。下一个挑战是为事件时间数据创建一个模型,其中一些患者没有观察到事件。不是二元分类那么简单。患者可能在研究结束时没有死亡,或者他们可能在研究期间失去了随访。这些观察被称为右删失。

让我们将 Ti 定义为患者 I 的事件时间,将 Ei 定义为事件指示符。如果 Ei 为 1,则事件(例如死亡)发生在时间 Ti。如果 Ei 为 0,那么 Ti 是最后一次接触患者的时间——它们是右删截的。

时间-事件预测模型最常用的指标是一致性指数(C-index):一致性对的数量除以可能的评估对的总数。当算法正确地预测一个病人比另一个病人有更大的风险时,就是一致对。

然而,深度学习的损失函数需要是可微分的,以便利用基于梯度的优化器进行有效训练。标准回归模型是不合适的,因为右删失病例需要被丢弃,并且二元分类模型(例如,N 年后存活或死亡)不会利用实际存活时间。

Cox 比例风险

最常见的生存建模方法是 Cox 比例风险 (CPH)模型。

让我们将存活函数定义为在时间 t 存活的患者的比例:

t 时刻的瞬时死亡概率为

CPH 函数对一组协变量 x 的影响进行建模:

其中,λ₀(t)is 是基准风险函数,h(x)是风险函数。在线性 CPH 模型中,风险函数是 hᵦ(x)=βᵀx,可以预测给定这些协变量的特定患者的相对风险。训练这样一个模型是通过最大化似然性来完成的——或者等效地,部分对数似然性。

一些将生存模型应用于组织学的早期工作使用手工制作的特征作为协变量。深度学习模型通过应用一组非线性运算来利用相同的公式,以产生一组网络权重ᵠ.的输出 hᵩ(x

深度生存模型的第一次尝试使用了专家选择的少量特征,从临床变量预测心脏病发作风险,从基因和蛋白质表达预测乳腺癌风险[ Katzman2018 ]。为了将该模型应用于组织学图像,将 CPH 损失函数置于 CNN 之上。

CPH 模式的一个缺点是它是不可分的。在模型训练的每次迭代中,通过比较当前批次中患者的相对风险来估计其值。

替代生存损失

除了 CPH 损失之外,还有几个替代方案可以适应生存数据的右删失性质。迈耶等人对 Uno 损失和 logrank 损失进行了实验,Uno 损失基于一致性,log rank 损失使用非参数检验比较右偏和删失的生存数据[ 迈耶 2020 ]。他们比较了 CPH 损失和 5 年二元分类器。与二元分类器相比,所有三个风险分数形成了更好的风险热图。Uno 和 logrank 的业绩在数量上优于 CPH。

另一种利用存活时间和右删失观测值的方法是将数据转换为多任务模型[ Li2016Fotso2018Vale-Silva2020 ]。时间轴被分成多个间隔,并且对每个间隔应用二元分类器来预测患者是否已经存活到该时间点。通常,添加一些额外的约束,以确保特定患者在时间间隔内的预测是非增长的和平滑的。针对其他形式的数据,提出了其他离散时间生存模型[ Gensheimer2019Zhong2019a 。]

Wulczyn 等人比较了 cph(C 指数的指数下限)和使用交叉熵的多任务分类,发现后者表现最好[ Wulczyn2020 ]。

Muhammad 发现,将 CPH 损失与二进制分类术语相结合,比单独使用任何一种方法都能更好地将患者分为高风险和低风险,并极大地改善了测试集的结果[ Muhammad2021 ]。

什拉济等人采取了一种相关的方法,将时间轴分为 4 类:0-6 个月、6-12 个月、12-24 个月和> 24 个月。他们的模型显示了胶质母细胞瘤的巨大成功,但也显示了在整个幻灯片图像上训练的一些挑战。将每个患者的存活时间应用于载玻片内的每个贴片。这是弱监督问题的一个可能的解决方案,但是我们接下来将看一些在整个幻灯片图像上训练生存模型的替代方法。

从补丁到幻灯片

不管选择的损失函数和选择哪个图像补片用于建模,它们都必须被组合成对患者的单个风险预测。最简单的方法是独立地在图像补片上训练模型,并对每个患者在所有补片上产生的分数进行平均。然而,在最终预测之前整合斑块特征的模型通常被认为是更好的。

本节将概述一些弱监督学习方法,这些方法已用于整个幻灯片的生存模型。可以使用其他弱监督或多示例学习方法来代替。参见我写的这篇关于该领域其他方法的文章

独立补丁

对整个幻灯片图像最简单的方法是独立地在图像小块上训练模型。Meier 等人用 IHC 和 H&E [ Meier2020 ]对来自组织微阵列的 160 x 160 像素图像块训练了 CNN。什拉济等人也对补丁进行了独立的训练,但他们对补丁预测进行了多数投票。

应用于图像补丁的深度生存网络

补丁功能聚合

Wulczyn 等人没有聚合补丁预测,而是聚合补丁特征[ Wulczyn2020 ]。在应用生存模型之前,他们计算了每个病人所有补丁的每个特征的平均值。

Yao 等人首先对每个患者的图像块进行聚类,然后将 CNN 应用于每个块,并使用注意力模型在各个聚类之间进行聚合。自注意机制学习每个特征向量的权重,并计算加权和。他们在顶部应用了一个完全连接的层,然后是生存模型。

一种聚集图像斑块特征的注意力模型[ 姚 2020

作为处理来自同一张幻灯片的多个补丁的另一种方法,比契科夫等人将递归神经网络应用于从组织微阵列核心图像补丁中提取的 CNN 特征[ Bychkov2018 ]。

其他型号扩展

对上述生存建模方法也有多种扩展。

以上对整个幻灯片图像的应用都以某种方式使用 CNN 来模拟图像。陈等人还使用了一种图卷积网络,他们通过连接原子核来提取拓扑结构,以形成一个图[ Chen2020 ]。李等用图模拟组织拓扑 CNN [ Li2018 ]。

用于生存预测的图卷积网络

陆等人关注的不是组织拓扑结构,而是细胞形态学[ Lu2020 ]。他们开发了一种细胞多样性的描述符,并发现它可以预测患者的结果。

多模态模式

其他形式如临床数据、基因组学和蛋白质组学也可以用于生存模型。Vale-Silva 等人训练了一个融合多种数据形式的模型,但发现组织学并没有改善仅使用临床特征的模型[ Vale-Silva2020 ]。钟等人也研究了成像和基因表达特征[ 中 2019b ]。他们发现,以基因表达为条件,组织学特征的预测能力有限;然而,它们的图像特征仅限于手工制作的形态学特征。

多模式生存模式[ 淡水河谷 2020 年

Hao 等人还对整个载玻片图像和基因组数据的组合进行了实验,并发现该模型优于仅使用单一模态的模型[ Hao2020 ]。陈等人也得出了类似的结论。他们测试了多种建模策略:基因组特征和整个幻灯片,CNN 和组织学上的图形 CNN 模型。

共识似乎是基于组织学的特征可以促进使用基因组或临床变量的生存模型。然而,成功可能取决于所使用的图像特征、模型类型和数据集等因素。

泛癌建模

生存模型也被同时应用于多种癌症。Wulczyn 等人训练了一个跨越 10 种癌症类型的生存模型,并评估了他们的模型在每种癌症类型中的预测能力[ Wulczyn2020 ]。Vale-Silva 等人训练了一个涵盖 33 种癌症类型的泛癌和多模态模型[ Vale-Silva2020 ]。

总结和建议

上面的一些方法使用了一个从头开始训练的小型 CNN。其他人将迁移学习应用于更大的 CNN 架构,如 VGG、ResNet 或 GoogLeNet。给定足够的训练数据和计算能力,较大的架构通常更优越。

上面讨论的建模方法都捕捉了肿瘤形态学的不同视角。我还没有看到关于最佳方法的一致意见。每一个都为影响患者结果的因素提供了不同的见解。

从整个幻灯片图像中模拟患者结果比仅仅弱监督学习更复杂。解释导致好的或差的结果的因素对于增进我们对癌症的理解也是至关重要的。

可解释的模型已经揭示了一些重要的见解,消除组织类型的歧义是成功的关键。组织类型面积比[ Wang2021 ]和连接性[ Abbet2020 ]影响结果。与肿瘤本身相比,肿瘤内间质形态可能是一个更强有力的预后指标[ Beck2011Bhargava2020 ]。

Bhargava 等人甚至表明,在一群患者身上成功的建模方法可能在另一群患者身上不成功[ Bhargava2020 ]。虽然这为成功的生存模型提供了机会,但也证明了评估模型可推广性的重要性。

在开发新模型时,了解哪些因素已经与正在研究的癌症类型的结果相关可能是至关重要的。

或者,将弱监督模型应用于整个载玻片图像可以发现尚未与预后相关联的组织特性。但是,要将一个成功的模型转化为新的见解,一些解释能力的手段是必不可少的。

适应生存数据的正确删失性质的损失函数优于单个二元分类器。然而,将多个二元分类器或生存损失与二元分类器结合的多任务方法可能产生更好的风险分层。

生存建模的新领域包括多模态和泛癌方法。

当前模型的最大限制可能是训练数据量少。随着向数字病理学过渡的进展和新合作的建立,更大的训练集将变得可用。当数据隐私成为问题时,联合学习可以处理位于不同中心的数据集。

基于组织学图像的预后模型刚刚开始显示其潜力。但是,可能需要更大的数据集才能在这些千兆像素图像中找到最具预测性的模式。

希望从您的图像和算法中获得最大的洞察力?

Heather D. Couture 是 Pixel Scientia Labs 的创始人,该实验室提取最新的机器学习研究,以帮助研发团队抗击癌症。

联系她,了解如何实施更好的模式并产生影响。

参考文献

[Abbet2020] C. Abbet,I. Zlobec,B. Bozorgtabar,J.P. Thiran,分而治之:结肠直肠癌生存分析的自我监督学习 (2020),医学图像计算和计算机辅助干预国际会议

M. Andreux,A. Manoel,R. Menuet,C. Saillard,C. Simpson,离散时间 Cox 模型联合生存分析 (2020),arXiv 预印本 arXiv:2006.08997

[Beck2011] A.H. Beck,A.R. Sangoi,S. Leung,R.J. Marinelli,T.O. Nielsen,M.J. Van De Vijver,R.B. West,M. Van De Rijn,d .柯勒,乳腺癌形态学的系统分析揭示了与生存相关的基质特征 (2011),《科学转化医学》

[Bhargava2020] H.K. Bhargava,P. Leo,R. Elliott,A. Janowczyk,J. Whitney,S. Gupta,P. Fu,K. Yamoah,F. Khani,B.D. Robinson,T.R. Rebbeck,通过计算得出的基质形态图像信号是非洲裔美国患者前列腺切除术后前列腺癌复发的预后指标 (2020),临床癌症研究

[Bychkov2018] D .比契科夫,n .林德,r .图尔基,s .诺德林,P.E .科瓦嫩,c .韦里尔,m .沃兰德,m .伦丁,c .哈格伦德,j .伦丁,基于深度学习的组织分析预测结肠直肠癌的结果 (2018),科学报告

[Chen2020] R.J. Chen,M.Y. Lu,J. Wang,D.F.K. Williamson,S.J. Rodig,N.I,F. Mahmood,病理学融合:融合组织病理学和基因组特征用于癌症诊断和预后的综合框架 (2020),IEEE 医学成像汇刊

[Courtiol2019] P. Courtiol,C. Maussion,M. Moarii,E. Pronier,S. Pilcer,M. Sefta,P. Manceron,S. Toldo,M. Zaslavskiy,N. Le Stang,N. Girard,基于深度学习的间皮瘤分类改善了对患者结果的预测 (2019),《自然医学》

【Fotso 2018】s . Fotso,基于多任务框架的生存分析深度神经网络 (2018),arXiv 预印本 arXiv:1801.05512

[Gensheimer2019] M.F. Gensheimer,B. Narasimhan,神经网络的可扩展离散时间生存模型 (2019),PeerJ

[Hao2020] J. Hao,S.C. Kosaraju,N.Z. Tsaku,D.H. Song,M. Kang, PAGE-Net:使用组织病理学图像和基因组数据进行生存分析的可解释和整合深度学习 (2020),生物计算

[Kather2019] J.N. Kather,J. Krisam,P. Charoentong,T. Luedde,E. Herpel,C.A. Weis,T. Gaiser,A. Marx,N.A. Valous,D. Ferber,L. Jansen,利用深度学习预测结肠直肠癌组织切片的存活率:一项回顾性多中心研究 (2019),PLoS Medicine

[Katzman2018] J.L. Katzman,U. Shaham,A. Cloninger,a .等人, DeepSurv:使用 Cox 比例风险深度神经网络的个性化治疗推荐系统 (2018),BMC 医学研究方法

[Klimov2021] S. Klimov,Y. Xue,A. Gertych,R. Graham,Y. Jiang,S. Bhattarai,S.J. Pandol,E.A. Rakha,M.D. Reid,R. Aneja,使用深度学习图像分析预测胰腺神经内分泌肿瘤(PanNET)的转移风险 (2021),肿瘤学前沿

[Li2016] Y. Li,J. Wang,J. Ye,C.K. Reddy,生存分析的多任务学习公式 (2016),ACM SIGKDD 知识发现与数据挖掘国际会议

[Li2018] R. Li,J. Yao,X. Zhu,Y. Li,J. Huang, Graph CNN 用于全切片病理图像的生存分析 (2018),医学图像计算与计算机辅助介入国际会议

[Lu2020] C. Lu,K. Bera,X. Wang,P. Prasanna,J. Xu,A. Janowczyk,N. Beig,M. Yang,P. Fu,J. Lewis,H. Choi,早期非小细胞肺癌患者总生存期的预后模型:多中心回顾性研究 (2020),The Lancet Digital Health

[Meier2020] A. Meier,K. Nekolla,L.C. Hewitt,S. Earle,T. Yoshikawa,T. Oshima,Y. Miyagi,R. Huss,G. Schmidt,H.I. Grabsch,应用于胃癌肿瘤微环境的无假设深度生存学习 (2020),《病理学杂志:临床研究》

[Muhammad2021] H. Muhammad,C. Xie,C.S. Sigel,M. Doukas,L. Alpert,T.J. Fuchs,EPIC-生存:生存分析的端对端部分推断聚类,以预后分层增强为特征 (2021),arXiv 预印本 arXiv:2101.11085

【shirazi 2020】a . z .扎德、e .福纳奇阿里、N.S .巴盖瑞等人 DeepSurvNet:基于组织病理学图像的脑癌生存率分类深度生存卷积网络 (2020),医学&生物工程&计算

L. Vale-Silva,K. Rohf, MultiSurv:使用多模态深度学习进行长期癌症生存预测 (2020),medRxiv 2020 . 08 . 06 . 20020202005

[Wang2021] X. Wang,Y. Chen,Y. Gao,H. Zhang,Z. Guan,Z. Dong,Y. Zheng,J. Jiang,H. Yang,L. Wang,X. Huang,使用深度学习从切除的淋巴结组织病理学图像预测胃癌结果 (2021),自然通讯

[Wulczyn2020] E. Wulczyn,D.F. Steiner,Z. Xu,A. Sadhwani,H. Wang,I. Flament-Auvigne,C.H. Mermel,P.H. Chen,Y. Liu,M.C. Stumpe,利用组织病理学图像对多种癌症类型进行基于深度学习的生存预测 (2020),PLoS One

[Yamashita2021] R. Yamashita,J. Long,A. Saleem,D.L. Rubin,J. Shen,深度学习从数字组织病理学图像中预测肝细胞癌的术后复发 (2021),科学报告

[Yao2020] J. Yao,X. Zhu,J. Jonnagaddala,N. Hawkins,J. Huang,利用注意力引导的深度多示例学习网络进行基于全幻灯片图像的癌症生存预测 (2020),医学图像分析

[Yue2019] X. Yue,N. Dimitriou,O. Arandjelovic,使用机器学习和自动推断的表型谱从 H & E 整片图像预测结直肠癌预后 (2019),arXiv 预印本 arXiv:1902.03582

[Zhong2019a]钟超,S. Tibshirani,作为分类问题的生存分析 (2019),arXiv 预印本 arXiv:1909.11171

[Zhong2019b] T. Zhong,M. Wu,S. Ma,检验癌症中基因表达和组织病理学影像特征的独立预后能力 (2019),癌症

[Zhu2016] X. Zhu,J. Yao,J.Huang,用于病理图像生存分析的深度卷积神经网络 (2016) IEEE 生物信息学和生物医学国际会议

[Zhu2017] Y. Zhu,J. Yao,F. Zhu,J. Huang, WSISA:从全切片组织病理学图像进行生存预测 (2017),IEEE 计算机视觉与模式识别会议

SVM 分类器和 RBF 核——如何用 Python 制作更好的模型

原文:https://towardsdatascience.com/svm-classifier-and-rbf-kernel-how-to-make-better-models-in-python-73bb4914af5b?source=collection_archive---------2-----------------------

机器学习

支持向量机(SVM)和径向基函数(RBF)核的内部工作的完整解释

具有 RBF 核和高伽玛的 SVM。在本文结尾的 Python 部分,您将看到它是如何创建的。图片由作者提供。

简介

要想在数据科学项目中取得成功,了解不同的机器学习算法是非常重要的。

我写了这个故事,作为深入解释其机制的每个 ML 算法系列的一部分,并辅以 Python 代码示例和直观的可视化。

故事涵盖以下主题:

  • SVM 分类所属的算法类别
  • 对算法如何工作的解释
  • 什么是内核,它们在 SVM 是如何使用的?
  • 使用 Python 示例和图表深入了解 RBF 内核

支持向量机分类属于哪一类算法?

支持向量机(SVMs)最常用于解决分类问题,属于监督机器学习范畴。

同样,通过使用支持向量回归算法(SVR ),支持向量机也可以用于回归

你可以在下面的交互图中找到这些算法的确切位置。确保点击👇对不同的类别进行放大并揭示更多。

机器学习算法分类。由作者创建的互动图表。

如果你也热爱数据科学和机器学习 ,请 订阅 每当我发布新故事时,你都会收到一封电子邮件。

SVM 分类算法——简要说明

让我们假设我们有一组属于两个独立类的点。我们希望将这两个类分开,以便我们能够正确地将任何未来的新点分配给一个类或另一个类。

SVM 算法试图找到一个超平面,以尽可能高的裕度将这两个类别分开。如果类是完全线性可分的,可以使用一个硬边界。否则,它需要一个软余量

注意,结束于页边空白的点被称为支持向量

为了帮助理解,让我们回顾一下下图中的例子。

硬利润

用 SVM 算法分离两类点。硬利润场景。图片由作者提供。

  • 名为“ H1 ”的超平面不能准确地分开这两个类;因此,这不是解决我们问题的可行办法。
  • H2 ”超平面正确地划分类别。然而,超平面和最近的蓝点和绿点之间的差距很小。因此,很有可能对任何未来的新点进行不正确的分类。例如,当新的灰点(x1=3,x2=3.6)显然应该属于蓝色类时,该算法会将其分配给绿色类。
  • 最后,“ H3 ”超平面正确地将两个类分开,并具有最高可能的余量(黄色阴影区域)。找到解决方案了!

请注意,找到最大可能的余量可以对新点进行更准确的分类,从而使模型更加健壮。你可以看到,当使用“H3”超平面时,新的灰点将被正确地分配给蓝色类。

软利润

有时,可能无法完全区分这两个类别。在这种情况下,使用软边界,允许某些点被错误分类或落入边界内(黄色阴影区域)。这就是“松弛”值的由来,用希腊字母ξ (xi)表示。

用 SVM 算法分离两类点。软利润场景。图片由作者提供。

使用这个例子,我们可以看到“H4”超平面将边缘内的绿点视为异常值。因此,支持向量是更靠近主绿点组的两个绿点。这允许存在更大的余量,增加了模型的稳健性。

请注意,该算法允许您通过调整超参数 C 来控制您对错误分类(和边距内的点)的关注程度。本质上,C 充当分配给ξ的权重。低 C 使决策表面平滑(更稳健),而高 C 旨在正确分类所有训练示例,产生与训练数据更接近的拟合,但使其不那么稳健。

请注意,虽然为 C 设置较高的值可能会使模型在训练数据上有更好的性能,但存在过度拟合模型的高风险,从而在测试数据上产生较差的结果。

内核绝招

上面对 SVM 的解释涵盖了蓝色和绿色类可线性分离的例子。然而,如果我们想将支持向量机应用于非线性问题呢?我们该怎么做?

这就是内核技巧的用武之地。一个内核是一个函数,它将原始的非线性问题转化为高维空间中的线性问题。为了解释这个技巧,让我们研究下面的例子。

假设您有两个类—红色和黑色,如下所示:

原始二维数据。图片由作者提供。

如你所见,红点和黑点不是线性可分的,因为我们不能画一条线将这两个类放在这条线的不同边上。然而,我们可以通过画一个圆来区分它们,这个圆里面是所有的红点,外面是黑点。

如何将这个问题转化为线性问题?

让我们添加第三维,并使其成为 x 和 y 值的平方和:

z = x² + y²

使用这个具有 x、y 和 z 坐标的三维空间,我们现在可以绘制一个超平面(平坦的 2D 表面)来分隔红点和黑点。因此,现在可以使用 SVM 分类算法。

使用内核技巧转换数据。红色和黑色类现在是线性可分的。图表作者作者

径向基函数(RBF)内核和 Python 示例

RBF 是 sklearn 的 SVM 分类算法中使用的默认核,可以用以下公式描述:

其中 gamma 可以手动设置,并且必须大于 0。sklearn 的 SVM 分类算法中 gamma 的默认值为:

简单来说:

**||x - x'||²** is the squared Euclidean distance between two feature vectors (2 points).**Gamma** is a scalar that defines how much influence a single training example (point) has. 

因此,根据上面的设置,我们可以控制单个点对整个算法的影响。gamma 越大,其他点必须越靠近才能影响模型。我们将在下面的 Python 示例中看到改变 gamma 的影响。

设置

我们将使用以下数据和库:

让我们导入所有的库:

然后我们从 Kaggle 获得国际象棋游戏数据,你可以通过以下链接下载:https://www.kaggle.com/datasnaek/chess

一旦你在你的机器上保存了数据,用下面的代码接收它。请注意,我们还派生了几个新变量供我们在建模中使用。

带有新派生字段的 Kaggle 的国际象棋数据集的片段。图片来自作者

现在,让我们创建几个函数,以便在构建不同的模型和绘制结果时重用。

第一个功能是将数据分为训练和测试样本,拟合模型,预测测试集的结果,并生成模型性能评估指标。

以下函数将使用测试数据和模型预测表面绘制一个 Plotly 3D 散点图。

用 C 和 Gamma 的默认值建立一个模型

让我们使用“rating_difference”和“turns”字段作为我们的独立变量(属性/预测值)并使用“white_win”标志作为我们的目标来构建我们的第一个 SVM 模型。

注意,我们在这里有点作弊,因为总移动次数只有在比赛后才知道。因此,如果我们想在比赛开始前生成模型预测,则“回合”将不可用。然而,这仅仅是为了说明的目的;因此,我们将在下面的例子中使用它。

因为我们使用了之前定义的‘fitting’函数,所以代码很短。

该函数打印以下模型评估指标:

SVM 模型性能指标。图片由作者提供。

我们可以看到,模型在测试数据上的性能类似于在训练数据上的性能,这再次保证了模型可以使用默认的超参数很好地概括。

现在,让我们通过简单地调用 Plot_3D 函数来可视化预测:

Plot_3D(X, X_test, y_test, clf)

具有默认超参数的 SVM 分类模型的预测平面。图片由作者提供。

注意,上面的黑点是实际 class=1(白棋赢了),下面的黑点是实际 class=0(白棋没赢)。同时,表面是由模型产生的白胜的概率。

虽然概率存在局部变化,但决策边界位于 x=0 附近(即评级差异=0),因为这是概率越过 p=0.5 边界的地方。

SVM 模型 2 —伽玛= 0.1

现在让我们看看当我们为 gamma 设置一个相对较高的值时会发生什么。

伽玛=0.1 的 SVM 模型性能指标。图片由作者提供。

我们可以看到,增加 gamma 会导致模型在训练数据上表现更好,但在测试数据上表现更差。下图有助于我们了解这到底是为什么。

伽马=0.1 的 SVM 分类模型的预测平面。请注意所使用的特色图像 colorscale='Aggrnyl '。图片作者作者

我们现在有一个非常“尖锐”的预测面,而不是像以前一样有一个平滑的预测面。为了理解为什么会发生这种情况,我们需要更仔细地研究一下内核函数。

当我们选择高伽玛时,我们告诉函数,近点比远点对预测更重要。因此,我们得到这些“尖峰”,因为预测很大程度上取决于训练示例的单个点,而不是它们周围的情况。

另一方面,减少 gamma 值会告诉函数,在进行预测时,不仅是单个点,它周围的点也很重要。为了验证这一点,让我们看另一个 gamma 值相对较低的例子。

SVM 模型 3—伽玛= 0.000001

让我们重新运行这些函数:

伽玛=0.000001 的 SVM 模型性能指标。图片由作者提供。

正如预期的那样,随着模型在测试数据上的性能提高(精确度= 0.66),降低伽马值会使模型更加稳健。下图说明了对较远的点赋予更多影响后,预测表面变得更加平滑。

伽马=0.000001 的 SVM 分类模型的预测平面。图片由作者提供。

调整超参数 C

我决定在这个故事中不包括使用不同 C 值的例子,因为它以类似于 gamma 的方式影响预测平面的平滑度,尽管是由于不同的原因。您可以自己尝试一下,向“fitting”函数传递一个值,比如 C=100。

结论

SVM 算法强大而灵活。虽然我只讲述了一个可用内核的基本用法,但我希望这已经让你理解了 SVM 和 RBF 的内部工作原理。这将使您能够自己探索所有其他选项。

如果你有任何问题,请给我打电话,感谢阅读!

干杯👏
T5【索尔多比拉斯】

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:

https://solclover.com/membership

SVM 说话算法:使用内点方法进行 SVM 训练

原文:https://towardsdatascience.com/svm-talking-algos-using-interior-point-methods-for-svm-training-d705cdf78c94?source=collection_archive---------21-----------------------

实践教程

使用优化方法从头开始训练支持向量分类器

好了,伙计们!我们已经讨论了约束优化的预备知识将支持向量机分类问题公式化为二次规划 (QP)。今天我们学习如何数字训练支持向量分类器

这篇文章可以分为两部分:理论和实践!如果你以前遇到过内点方法,你可以跳过理论部分,向下滚动到我们的实际例子!

首先,我们试图从障碍方法出发,给内点方法提供一些直观。第二,我们制定原始对偶方法,直接来自修改 KKT 条件。这可能现在没有意义,但是当你读的时候会明白的!最后,我们从头开始编写我们的分类器——这是之前学习的所有构建模块汇集的地方。

理论!支持向量分类器如 QP

我们从开始,回忆支持向量分类器可以通过它的对偶表示为二次规划

SVM 扮演 QP

在哪里

这是我们的优化问题!现在让我们学习如何用数字来解决它。

建立你的直觉:内点方法

内点法背后的重要思想是,它们试图通过将牛顿法应用于一系列的等式约束问题或一系列的修改的版本的 KKT 条件,来解决问题(上文所述)或 KKT 条件(为上文问题制定的)。两个自然的问题是:不平等约束在哪里消失,什么是 KKT 条件的修改版本?

前者可以很容易地通过屏障方法观察,帮助后者建立直觉。让我们直入主题吧🚀

不等式约束在哪里消失?

我们试图将不等式约束问题(如上所述)近似公式化为等式约束问题,牛顿的方法可以应用于该等式约束问题。我们的第一步是通过使不等式约束隐含在目标中来重写问题(让我们采用这里讨论的一般形式)。这是通过引入指示器函数来实现的。因此我们有

到目前为止一切顺利。这里唯一的问题是,这个目标不能是两次可微的,这意味着我们的假设被违反,我们不能对它应用牛顿的方法。那么我们能做什么呢?

我们再近似一次!现在我们想用可微的东西来近似指标函数。可能我们有一个!我们用另一个函数来近似指示函数

其中 t > 0 是设置近似精度的参数。

作者创建的图像。灵感来源于[1]

该图显示了不同的 t=0.5,2,4,5 的近似精度。蓝线( t=5 )表明随着 t 参数的增加,我们有了更好的近似值。

这给了我们一个新的优化问题。通过将目标乘以 t,我们得到具有相同最小化器的等价最小化问题

新函数 phi 被称为对数障碍,它说明了不等式约束

什么是修正的 KKT 条件?

我们现在考虑上面写的问题。对于每一个 t > 0 我们定义 x(t)* 为解。当我们应用牛顿法时,我们有中心点,它们是 x(t)。*该中心路径是严格可行的,这意味着这些中心点也满足等式条件。我们记得在梯度为零的地方发现了最小值。我们写出了拉格朗日函数

想知道 nu 是哪里来的?如前所述,我们将最小化问题全部写成拉格朗日形式的一个表达式(这意味着用拉格朗日乘数为等式约束增加目标函数)。然后我们求导,让它等于零,我们记得这是最小的地方。我们陈述存在最优的 nu ,使得表达式书面打击成立。

从上面的表达式中,我们可以推导出中心路径的一个重要性质:每个中心点 x(t)* 产生一个对偶可行点,因此是最优解的下界 p* 。回忆阅读此处?

如果我们将λ定义如下

这给了我们一个双重功能,通过插入我们的 lambda,我们有

然而在我们说二元性差距实际上为零之前,实际上我们表明它不完全是那样的。我们的二元差距等于 -m/t.

这就改变了我们所说的 KKT 条件的形式。新的KKT 条件简称为修正的** KKT 条件。因此,我们的最后一个条件被我们讨论过的二元差距所取代!**

因此,新的修改 KKT 条件,又名中心性条件,是

修正的 KKT 条件

到目前为止一切顺利!我们提供了修改的 KKT 条件从何而来的直觉,这有望帮助你更好地理解内点算法背后的思想。从这一刻起,你应该记住的是修正的 KKT 条件,我们正试图用牛顿法解决这个系统!😃

数值求解:原始对偶方法

本质上,我们将修改后的条件表示为

非线性方程 rt

我们定义的地方

并且 f(x) 是不等式约束的向量,而 Df 是它的导数。

一旦我们找到满足第一个方程的 x,λ,nu ,这意味着我们找到了最小化器!你知道这些方程矩阵是从哪里来的吗?这确实是我们修改后的 KKT 条件,所有条款都在左边!

现在应该怎么解决呢?我们考虑对于固定的 t 求解非线性方程 r_t 的牛顿步骤。我们将当前点和牛顿步表示为

分别是。牛顿步骤的特征在于非线性方程

所以根据 x,λ和 nu,我们有

最终系统

练习!翻译成代码

终于,我们到了!我们有最终的非线性方程,我们想用牛顿法数值求解。我们如何编码?在本教程中,我们使用 Matlab

关于我们数据的注释

我们使用合成生成的数据集,该数据集包含两个类,并且不容易被直线分开。这个数据集是使用 Python 代码生成的,可以在这里访问

第一步。从 CSV 文件中读取数据

第二步。将问题翻译成代码

还记得吗,在本文的开始,我们讨论了支持向量机的 QP?将它翻译成代码非常简单,因为我们 1)知道目标,2)知道我们的不平等和平等约束。让我们把它放在一起。

我们首先需要创建我们的三维矩阵。回想一下,它包含 x 和 y 的乘积,因此我们写 for loop 来找到它。一旦找到 D,我们就写出它的一阶和二阶导数。然后我们把不平等和平等约束以及它们的派生物放在一起。

第 33–38 行显示了问题设置。回想一下,我们正试图优化 x,λ和 nu ,所以我们应该从某个地方开始!我们如何选择一个起点?你真的可以从什么开始,唯一的要求:选择应该是可行的,这意味着在这一点上问题的约束没有被违反!

第三步。选择默认参数

之前,我们只讨论了参数 t,,然而,我们也可以默认选择其他参数。原始对偶算法假设在每次迭代中 t 都在变大,所以我们引入了 m 常数,我们在每次迭代中用它乘以 t (我们将在代码中进一步看到)。 tol 和 maxIter 是作为停止标准的两个参数。

tol 控制代理二元差距,所以我们只在代理二元差距非常非常小时停止。代理对偶间隙的引入是由于原始对偶方法不一定在每次迭代中都产生一定可行的点,这意味着在每次迭代中我们不一定计算对偶间隙并在它非常非常小时停止—因此,我们引入了代理对偶间隙。

maxIter 只是确保我们进行一定数量的迭代,这样我们就不会永远都在求解。

回溯选项允许确定步长。我们将看到它是如何在算法中使用的。

第四步。编写算法代码

首先,我非常感谢 Marta Betcke 博士,当我在 UCL 学习的时候,他给我介绍了数值优化。本节介绍的算法是受伦敦大学学院数值优化讲师 Marta Betcke 博士的启发。

我们创建一个单独的函数,它将上面定义的所有参数作为输入。

我们通过将 r_t 转换为deltaY【1】找到了我们的 deltaY

第五步。确定步长

我们找到了我们需要走的方向,但我们还没有朝这个方向迈出一步。我们应该如何确定我们的步长?我们使用线搜索,但是对其进行调整以适用于原始对偶算法。

基本线搜索应该通过考虑残差的范数和通过确保两个约束成立来修改。第一个约束是

回溯的第一个约束

为了简单起见,这里我们假设第一个约束永远不会被违反。因此我们设置 s_max=1。

第二个约束确保

回溯的第二个约束

为了确保第二个约束,我们需要开始回溯减少 s,直到满足约束。这就是我们之前介绍的 optsBT 选项发挥作用的地方!因为我们不希望在不满足约束的情况下永远回溯,所以我们希望确保在满足一定数量的迭代时停止。

我们一直做这个练习,直到我们的代理对偶间隙小于容许水平,或者达到最大迭代次数!最终三重奏 x_k,lambda_k 和 nu_k 将是我们的解!

第六步。行动呼吁

我们调用我们命名为 PrimalDual 的创建函数来工作!

第七步。绘制决策边界

我们到了!由于我们已经记录了迭代,我们现在可以找到大于某个阈值(我们使用 0.001)的支持向量!

作者图片

作者图片

回想一下,我们的 infoPD 结构还包含了每次迭代中代理对偶间隙的信息。通过将它绘制成迭代次数的函数,我们可以看到它在快速下降。它不会精确地归零,但它比我们一开始设置的 tol=1e-12 要小。

参考文献:

[1] V. L. Boyd Stephen,凸优化。2004.

SVM 谈数学:将支持向量机公式化为二次规划问题

原文:https://towardsdatascience.com/svm-talking-maths-formulating-support-vector-machine-as-a-quadratic-programming-problem-ab5d30a8d73e?source=collection_archive---------28-----------------------

从分离超平面的想法到最终的二次规划分 4 步

作者 GIF

上周,我们介绍了约束优化,但没有给你任何提示,说明这如何有助于在数值上解决支持向量机问题。这一次我们将通过把支持向量机公式化为 QP 问题来把一切放入上下文中!

在这篇文章中,我们引入了卡鲁克-库恩-塔克特(KKT)条件,将支持向量机问题公式化为一个凸优化问题,并引入了几个变换,使其更便于数值求解!

让我们直入主题吧。

这些 KKT 条件是什么,我们为什么要关心?

简单地说,KKT 条件是一阶导数测试,它允许我们检查是否确实达到了最优解我们记得,假设目标函数、不等式和等式约束是可微的,我们的拉格朗日函数具有以下形式

其中 x*是最优解。因此,我们有以下 KKT 条件

KKT 条件

所有这些符号对你来说都有意义吗?如果没有,让我知道我会提供更多的解释!

这里有好消息!😃如果我们假设目标是凸的,这些条件就变得必要和充分。换句话说,我们保证 x,lambda** 和 nu* 是原始的和对偶最优的,对偶间隙为零。还记得是什么意思吗?

所以现在,我们完全准备好了!我们有我们的拉格朗日和 KKT 条件,我们应该如何制定 SVM 作为一个约束优化问题?

作为二次规划问题的支持向量机

我们记得,支持向量机本质上是寻找一个最优超平面,其中“支持向量”是超平面的位置和边缘的宽度。

分离超平面的思想

如果我们在一个 p- 维空间中有向量 x ,超平面或仿射集 L 由以下等式定义

分离超平面

图片作者。灵感来源于[1]

那才是你心目中应该有的画面(抱歉画的乱七八糟)。大主意!🙂这些贝塔是控制线方向的——因此,我们希望通过最小化贝塔找到最佳分离!

我们现在列出一些重要的属性:

  1. 对于位于 L,中的任意两点 x1 和 x2,我们有

因此,我们可以构造曲面 l 的法向量 B* 。因为我们在 2D,我们有一条线而不是曲面。我们记得矢量法线是在给定点垂直于表面的矢量。

2.对于 L,中的任意给定点 x_0 ,我们有

直接从上面分离超平面的定义

3.从 x 的任意点到 L符号距离由下式给出。我注意到,我们在最终表达式的分母中有一个导数,因为对目标求一阶导数,我们将只剩下β。

步骤 1——制定一个优化问题。

目标是通过最大化到任一类中最近点的距离,找到分隔数据点的超平面。如果 M 是一个带符号的距离,那么我们有如下优化问题

以下不等式条件确保所有点距离由βas定义的决策边界至少有符号距离 M

第二步——再想想!为方便起见重新表述。

现在仔细观察,我们应该对上述优化公式进行三个重要的调整,以解决分类错误的问题,从而使数值求解稍微容易一些。我们引入了以下变化:

  1. 任意设置

这允许我们以这样一种方式重写最初的问题,在将来我们将最小化平方范数,这样做纯粹是为了方便。

2.现实世界的问题通常是不可分的,因为它总是包括一些在未来空间重叠的观察。这叫做软余量。因此,我们需要允许一些点位于边缘的错误一侧。数学上,我们引入松弛变量 ( 字母 xi) 其总和不应超过指定的值 C

该约束以这样的方式公式化,以表达预测f(x _ I)在其余量的错误侧的比例量。

我们现在有以下优化问题。我们注意到,在平方范数完成之前引入 1/2 纯粹是为了方便——回想一下,一旦我们求一阶导数,2 的幂将下降,因此 1/2 将抵消它。此外,我们将边界约束重写为“正则化”项,这本质上与我们惩罚错误分类是一回事!

重写优化问题

第三步——写拉格朗日(我们快到了)。

前面提到的给了我们约束优化问题,现在我们把所有东西放在一起得到拉格朗日!

所以我们的新目标是最小化贝塔的矢量、贝塔 _0阿尔法的矢量Xi 的矢量。你能看出这些术语是从哪里来的吗?如果没有,让我知道,我会分解它。

我们还遗漏了什么?对!我们仍然需要应用我们的一阶导数测试(KKT 条件)来看看我们试图找到的最优解是否是真正最优的。让我们现在把这些写下来。

我们先介绍平稳性条件。这就好像我们试图确定一个函数导数为零的驻点。由于我们是针对β的向量β_ 0α、Xi 的向量进行优化。我们需要确保这三个都通过这些静态测试!因此,我们写道

平稳条件

从问题的原始形式,我们有所谓的原始可行性条件。可行性简单来说就是我们的最优点位于满足约束的可能区域!

最初的可行性约束

更进一步,我们有乘数条件!因为这两个是直接来自 KKT 的条件。我们有一个等式约束的乘数和一个不等式约束的乘数。因此,我们写道

拉格朗日乘数条件

最后但同样重要的是,我们有互补的松弛条件。引入这些约束是因为我们有零对偶间隙,因此它们保证了原始和对偶的值是相同的!你可以在这里阅读更多关于这些条件是如何获得的

互补松弛条件

第四步——拉格朗日看起来有点吓人。我们来写对偶形式吧!

我们的拉格朗日看起来很吓人我们也有 9(!)要考虑的约束。我们已经知道我们有一个凸问题,因此我们可以找到全局最优解,即使我们通过写对偶形式来处理这个问题。

让我们试着把我们的原始问题转换成对偶形式。我们使用前三个平稳性条件,并将它们代入拉格朗日方程。我们写作

总而言之,我们有以下问题

最终二次规划问题!

这比我们之前见过的拉格朗日简单多了。它也更加灵活,因为我们引入了允许错误分类的松弛变量!

仔细看这个表情。它让你想起了什么?完全正确,它具有二次规划的形式!

二次问题的标准形式

这意味着现在我们可以应用 QP 方法来数值解决这个问题🚀

最好的事情——来了一个内核函数!

关于对偶形式最好的事情之一是数据(我们的 x )以点积的形式出现。这意味着我们可以事先对我们的数据应用任何类型的转换!这非常方便,因为几乎没有真正的数据集可以线性分离!

参考文献:

[1] T. et。全部。哈斯蒂,“统计中的斯普林格系列统计学习的要素”,数学。智能。,2009 年第 27 卷第 2 期,第 83–85 页【在线】。可用:http://www.springerlink.com/index/D7X7KX6772HQ2135.pdf.

SVM 与 Scikit-学习:你应该知道什么

原文:https://towardsdatascience.com/svm-with-scikit-learn-what-you-should-know-780f1bc99e4a?source=collection_archive---------7-----------------------

为什么 LinearSVC 和具有线性核的 SVC 不是同一个函数?

为了在 scikit-learn 中创建线性 SVM 模型,有两个来自同一个模块svm : SVCLinearSVC的函数。由于我们想要创建一个具有线性内核的 SVM 模型,并且我们可以在函数LinearSVC的名称中读取Linear,我们自然选择使用这个函数。但事实证明,我们也可以将SVC与参数kernel='linear'一起使用。

现在的问题是:LinearSVCSVC(kernel='linear’)是同一个功能吗?如果不是,哪一个是真正的 SVM 模式?

(如果你不知道什么是 SVM,那么本文末尾有一个链接,可以非常直观地定义一个 SVM。)

乔纳森·博尔巴在 Unsplash 上拍摄的照片

经验方法

为了找出差异,可以有两种不同的方法:

  • 理论方法:我们可以阅读文档,找出与这些函数相关的数学公式的不同之处
  • 经验方法:我们可以对这两个函数做一些测试,我们可以看看它们的结果是否有任何不同

让我们从经验方法开始。

数据集

为了直观显示差异,数据应该简单。并且有必要测试数据中的不同行为。这里有一个将帮助我们:这个数据集有两个线性可分的类;然而,有一个异常点(与真实的类 1)实际上接近于类 1。让我们看看这两个函数将如何处理这个异常点。

X=np.array([1,3,4,5,6,9,20,21,23,24]).reshape(-1,1)y=np.array([-1,-1,-1,-1,-1,1,1,1,1,1])plt.scatter(X,y)

作者图片

线性模型

现在我们可以应用LinearSVC模型:

from sklearn.svm import LinearSVC
linsvc = LinearSVC(C=1)
linsvc.fit(X,y)

我们现在可以用橙色线来显示一些测试数据的预测:

X_test=np.linspace(-1, 30, 300).reshape(-1,1)
plt.scatter(X,y)
plt.scatter(X_test,linsvc.predict(X_test),marker="_")

作者图片

目前,我们看不到任何奇怪的东西:分类似乎是正确的。为了测试模型,让我们使用超参数C的一些极值。让我们回忆一下C的含义:

  • 对于C的大值,误分类会被认为是大损失。在我们的例子中,C=1可以被认为是大的,因为异常点被(正确地)分类为 1,而它更接近于 1 类。
  • 对于C的小值,错误分类将被容忍:理论上,异常点应被分类为-1…,让我们看看会发生什么
linsvc = LinearSVC(C=0.001)
svm_lin.fit(X,y)

我们得到以下结果:发生了什么?

作者图片

不是(理论上)错误分类异常点,而是很多-1 被错误分类。

也许我们对理论的理解是错误的?让我们用SVC做一些测试…

带 SVC 的模型

使用相同的数据集,我们可以拟合一个SVC模型:

from sklearn.svm import SVClinsvc = SVC(kernel = 'linear',C=0.01)

我们得到了:

作者图片

这更符合我们对超参数C在 SVM 模型中如何工作的理解。

理论方法

要验证的数学公式

既然我们可以从经验上看到这两个函数之间的差异,那么让我们更深入地从理论上寻找一些差异。

根据各种来源( scikit-learnWikipedia普林斯顿 SVM 讲座斯坦福 SVM 讲座),损失函数如下(铰链损失):

我们可以注意到正则化超过了β项,即不包括截距。

由于LinearSVC函数来自LIBLINEAR库,我们可以阅读文档中损失函数定义为:

min_w w^Tw/2 + C \sum max(0, 1- y_i w^Tx_i)^2

w 项包括截距,我们可以这样写

模型中的系数

现在,我们可以回到 python 代码,使用以下代码从两个模型中获取系数:

print(linsvc.coef_)
print(linsvc.intercept_)

对于LinearSVC,截距为零,而在SVC中,截距没有被规则化。我们可以通过这张图来比较它们

结论

由于各种包(python,R,spark)的出现,创建机器学习模型似乎变得越来越容易。然而,理解实现的函数背后的真正含义是很重要的。

在 SVM 的例子中,我们可以看到来自LIBLINEAR库的LinearSVC使用了一个损失函数,它不同于在来自LIBSVM库的SVC中实现的通常形式。对于高维,截距项的重要性会降低,但是对于小维,正则化截距项会导致不正确的结果。

群体机器人:项目、新商业模式和技术挑战

原文:https://towardsdatascience.com/swarm-robotics-projects-new-business-models-technical-challenges-d6fa845e56af?source=collection_archive---------19-----------------------

如何提高群体机器人应用程序、集体 AI 算法和硬件限制的可扩展性

Unsplash剂量媒体拍照

受群体智能和机器人学的启发,群体机器人学是一个很有前途的研究领域。目标是控制大量简单的机器人来完成复杂的任务。

尽管研究论文越来越多,可扩展的应用仍然很遥远,新的商业模式仍然需要在机器对机器经济的背景下找到(M2M)。

最近,我有机会与一个群体机器人团队合作。目标是利用一组小型机器人来识别大型设施中的漏水情况。

在这篇文章中,我将解释群体机器人发展的主要问题,展示不同的用例,以及要使这项技术可扩展需要实现的目标。

什么是群体机器人

有必要清楚地定义我们所说的“群体机器人”是什么意思。Erol Sahin [ 1 ]给出了一个完美的定义:

“群体机器人学是研究如何设计大量相对简单的实体代理,以便从代理之间以及代理与环境之间的本地交互中产生所需的集体行为。”

iniaki Navarro 和 Fernando Matía 概述了将群体机器人与其他多机器人类型的系统区分开来的几个条件。

图片由作者提供,创意来自伊尼基·纳瓦罗和费尔南多·马蒂亚

集体行为和群体机器人

为了更好地理解当前的挑战,理解研究人员关注什么是至关重要的。群体机器人的大部分研究工作都是针对集体行为 [ 3 ]的分析。根据 Marco Dorigo 等人(2014) [ 4 ]的说法,集体行为可分为五大类:

作者图片,来自 Marco Dorigo 等人(2014)

今天的情况和使用案例

今天大多数关于群体机器人的研究主要是使用模拟软件进行的。这种情况可以用机器人平台的成本和硬件复杂性来解释。这种情况阻碍了可伸缩解决方案的开发。

在构建原型时,我意识到在机器人群体应用程序中对大量机器人的模拟是相当复杂的,并且由于外部条件的建模不良而经常不准确。

尽管有这些限制,群体机器人还是可以在几个领域找到应用:从环境监测到灾难恢复、基础设施维护、物流和农业。

  • 应用#1 桑迪亚国家实验室开发的一个机器人搜索团队(被称为“雪机器人”)在雪地里定位雪崩受害者的速度比人类用狗快四倍。
  • 应用#2 在军事工业中,通过利用无人机作为蜂群一起行动,可以达到更好的战场感知(测绘)。蜂群会自主行动,同时搜寻目标并将信息传递给所有的蜂群成员。
  • 应用#3 群体机器人可用于检测化学品泄漏或污染。除了监测,蜂群可以定位源头,向该区域移动并采取快速行动。在紧急情况下,机器人可以聚集成一个补丁来阻断源头,作为临时解决方案[ 7 ]。
  • 应用#4
    在发生自然灾害或事故的情况下,群体可以证明非常有用。机器人可以搜寻受害者,并为特定区域的未来研究提出建议。
  • 应用#5 在维修中,群体机器人可以用来检查特定的元件。这种系统可以基于一群自主的微型机器人,只使用机载的本地传感器。
  • 谈到污染,麻省理工学院的 Senseable 城市实验室开发了一组名为 Seaswarm 的低成本吸油机器人,用于掠海和除油。

商业模式

群体机器人将受益于机器对机器时代。机器对机器是设备之间使用任何通信信道的直接通信,包括有线和无线。在不久的将来,大多数公司将提供群体机器人解决方案,或者与他们直接竞争(安全、物流等)。).

同样有把握的是,大多数运营机器人群体的公司会将收集的数据出售给参与 M2M 经济的其他公司,作为额外的收入来源( 感知作为服务** ) )。

例如,自动驾驶汽车可以从在附近工作的群体机器人那里购买与路况或交通信息相关的数据,这些机器人能够提前收集这些数据。

作者图片

我希望群体机器人也能从区块链中受益。由于 P2P 网络、智能合约和数字钱包,一群人工智能代理可以达成协议并记录下来,而不需要控制机构(公司)。

公司也可能决定在某种市场上将群体机器人“出租”给他人。例如,建筑经理可能决定租用群体机器人来分析建筑工地并寻找问题。因此,群体机器人可能最终成为分散的自治组织。

技术挑战

使群体机器人对许多未来用例(自主、分散等)具有战略意义的几个特征。)也限制了技术从学术机构向可扩展的工业解决方案的发展。

迄今为止,研究人员主要试图找到合作方案如何与现有的传感和计算能力相结合的答案。我们还需要精确地找出如何在一个数学模型中描述一个群体机器人系统,该模型可以预测个体和群体水平上的系统行为。

适应

根据我的经验,要开发可扩展的群体机器人,我们需要找到离线资源限制的解决方案。换句话说,完全在群体中运行计算密集型自动设计过程的能力。

我们还需要达到这样一种水平,即机器人群体可以在现实生活条件下自动发现合适的群体策略。不幸的是,大多数项目仍然缺乏这一关键能力。理想情况下,可扩展的机器人群体应该自主地、持续地调整它们的行为,以适应不断变化的任务和环境。

替代技术,如体现进化,已经被提出来允许机器人在群体中发展自主发现。不幸的是,这些方法非常耗时,因为可能的解决方案是在真实的机器人上测试的,而不是模拟的。此外,配备有缺陷控制器的真实机器人可能会对自身或外部元件造成损坏,使其不适合现实世界的条件。

沟通

第二个挑战与沟通有关。在某些情况下,如果全局通信被阻断,机器人群体就无法完成任务。

虽然有几种现有的无线技术可用,但专门用于群体机器人的协议仍未被发现。

感觉

机器人分析环境中的物体或目标,并完成必要的任务,如避障、目标搜索、群集等。应谭和钟【 9 】、表示:“该方案的主要问题是如何高效地整合群体中的所有传感器进行协作。”关于这个元素,Cortes 等人[ 10 ]实现了一个有趣的工作。他们探索了如何以自适应、分布式和异步的方式控制和协调一组自主车辆,这些车辆被视为带有传感器的代理。

更精确和频繁的通信需要更复杂的硬件和同步;随着群体变得越来越大,带宽、能源和所需处理时间的成本将会增长得非常快。理想情况下,可扩展的机器人集群应该尽量简化通信部分,尽可能依赖感知。

算法

除了上述挑战之外,群体机器人搜索算法是研究人员最关心的问题之一。

大部分算法都是针对每一个遇到的应用而设计的。例如,可扩展的机器人群需要具有高可用性的算法。不幸的是,这样的算法还没有被发现。

以下要素可以解释这种情况:

  • 群体机器人系统和应用问题缺乏标准定义。
  • 在群体机器人研究中抽象出各种各样的问题,有不同的问题定义、范围和设置。

安全性

机器人集群的另一个重要障碍是安全性。一些研究人员强调了开发系统的重要性,在这个系统中,群体成员可以发现并信任他们的同伴。

事实上,已经证明包含恶意的群体成员可能是群体目标[ 12 ]的潜在风险和安全漏洞。

不同的行为

如前所述,可扩展的机器人群体将需要处理许多不同的行为,例如,通过从一种控制算法转换到另一种控制算法来达到明确定义的目标。不幸的是,群体中不同行为的组合在现有的文献中还没有被深入研究。

群机器人技术还远未被认为是一项成熟的技术,研究人员的主要关注点是一些“基本”任务,如编队控制、避障等。

尽管商业应用和模型前景看好,但一些限制因素仍在阻止可扩展的现实世界群体机器人系统的发展。

从技术角度来看,需要在几个层面上进行进一步的研究。硬件缺陷限制了当前机器人系统的可扩展性,而更好的算法和通信系统对于提高群体机器人的自主性是必要的。

有关此主题的更多信息,我推荐以下链接:

动摇说服力:预测 Python 中的营销提升

原文:https://towardsdatascience.com/swaying-the-persuadables-predict-marketing-uplift-in-python-c5e9fd855b80?source=collection_archive---------7-----------------------

端到端示例:使用 sci kit-upgrade 模拟客户对营销活动的响应

日落照片 Unsplash 上的自由湖蒂勒里图像/Dottie Mabry

1.我们正在寻找的洞察力

我之前的一篇文章提到了客户流失:我们如何发现那些想去其他商店购物的客户?营销团队将接触他们,并试图对抗竞争对手的诱惑。

今天的文章超越了客户流失风险预测。

我们想确定营销活动的效果如何;并预测当我们将试点活动的范围从一小部分客户扩大到更大的群体时,我们可以期待哪些客户共鸣。哪些客户会对我们的促销活动做出积极回应?营销团队将寻找有说服力的

传统上,在计划客户拓展活动时,营销人员会区分四类 客户:

  • 确定的东西购买者会购买该企业的产品,无论我们是否针对他们采取促销行动。试图增加他们购买更多商品的倾向是一种浪费。相反,资源应该花在还没有成为目标受众的客户群上。如果促销活动提供了经济激励,例如折扣,即使顾客没有折扣也会购买商品,那么营销活动会给企业造成直接损失。

女孩向我竖起了大拇指。股票图片—立即下载照片—iStock(istockphoto.com)/Melpomenem 根据标准许可提供

  • 失败原因从不购买者不会购买更多的企业产品,无论营销团队是否接触他们。花费在营销沟通上的努力、时间和预算将是浪费。

一个表情恶劣的年轻女子在粉红色上排斥一些单独的东西。股票图片—立即下载照片—标准许可下的 iStock(istockphoto.com)/by master 1305https://www.istockphoto.com/th/รูปถ่าย/หญิงสาวที่มีการแสดงออกที่น่ารังเกียจขับไล่บางสิ่งบางอย่างแยกบนสีชมพู-gm1044676028-279591282

  • ****睡狗、蔑视者、勿扰者对营销传播表现出强烈的厌恶。如果他们没有受到促销活动的困扰,他们会有更高的购买倾向。被广告纠缠会惹恼这些顾客;或者提高他们的意识,他们还不如取消他们几个月或几年前已经订购的服务。向他们传达营销信息不仅是浪费,而且会适得其反。

成年红发腊肠犬正躺在白色的床上休息,戴着粉色的眼镜睡觉。股票图片—立即下载照片—iStock(istockphoto.com)/Oksana Restenko 在标准许可下提供

  • ****有说服力的人积极响应推广行动。营销传播会增加他们购买企业产品的倾向。当有人联系他们时,他们可能会购买,但当他们独处时,他们不太可能购买。

Alexas _ Fotos 在 Pixabay 上的免费照片

为了集中营销团队的努力和资源,我们需要确定活动中唯一重要的客户群:有说服力的人。

客户的分类不是一成不变的。这将取决于我们想要测试的具体营销行动。10%的折扣可以让顾客进入可说服的类别——而免费赠送电影《猫》门票的促销活动可能会让他成为输家——反之亦然。

提升建模旨在确定处理对目标变量的影响。如果治疗包括营销活动,那么客户响应率将是目标。回复率可以通过购买订单、网站访问或点击的频率来衡量。如果有一个控制数据集——营销活动没有接触到的客户——那么我们可以确定提升:治疗组和对照组之间的响应率差异。

治疗对顾客的因果影响通过结果的差异来表达。Y(1)表示客户接受治疗后的反应;Y(0)是没有接受治疗的结果。

  • 治疗的因果效应= Y(1)-Y(0)

对于单个客户来说,因果关系无法衡量,因为两个操作数中的一个是未知的。客户在观察时间窗口内接受或不接受治疗。

因此,上升被定义为反应概率的差异,通过观察治疗组和对照组中的等效客户组得出。响应代表客户将采取的行动。

  • 隆起= P(给予治疗的反应)-P(未给予治疗的反应)

我们希望估计每个客户的提升分数;然后总结整个治疗组的升高模式:

作者图片

根据定义,这些有说服力的人将会形成一类可以被这种治疗所左右的顾客。他们的反应将决定这场运动的整体提升。典型的确定的事情和失败的原因都会表现出零的提升,因为治疗不会改变他们的反应。睡狗的特点是负隆起。提升建模旨在从可说服的客户中挑选出高提升客户。

例如:一家在线零售商针对其部分客户投放广告或电子邮件,并以后续网站访问量来衡量其成功与否。企业记录显示,他们中有 18%的人登录了网站,而对照组中只有 11%的人在观察期内出现。因此,治疗组与对照组的反应率上升了 7%。

必须明确定义目标变量:例如,通过网站访问量来衡量,或者更严格地说,通过治疗开始后给定时间段内完成的购买交易来衡量。

提升分析在销售和营销之外的许多领域都有应用。每当需要预测治疗对目标变量的影响时,可以应用提升技术:在临床试验、政治运动或筹款活动中。

传统的反应模型将其范围限制在治疗组,而隆起分析建立了一个更全面的模型,包括治疗组和对照组。

柏林电梯 Pixabay 上的免费照片3093594

让我们来解决一个上升问题。

2.属国

除了我们的核心库,如 pandas 和 numpy,我们 pip-install 并导入 Scikit-uplift ,又名 sklift。

我们还导入了 Scikit-learn 的 train_test_split 类和 catboost 分类器。除了 catboost,您可以使用任何替代的分类器,只要它的语法与 scikit-learn 的分类方法兼容,例如 xgboost。

https://www.uplift-modeling.com/en/latest/install.htm

3.数据争论

sklift 附带的 Hillstrom 数据集包含 64,000 名在营销活动开始前的 12 个月内从在线零售商处购买商品的客户。该公司向其中 2/3 的客户发送了促销电子邮件,其中“男性电子邮件”和“女性电子邮件”各占一半。邮件描述了治疗过程。64,000 人中的第三组作为控制组,不接收电子邮件。

在活动结束后的两周时间里,该公司追踪了哪些顾客——接受治疗的或未接受治疗的——访问了它的网站。它使用访问次数来衡量回复率。

零售商记录了以下客户特征:

  • 最近=自上次购买以来的月数
  • history_segment =过去 12 个月的美元支出等级
  • 历史=过去 12 个月花费的实际美元价值
  • 男士=顾客购买了男士商品(该特征不表示顾客的性别),二进制 1 或 0
  • 女装=顾客购买了女装商品
  • 邮政编码
  • 新手=客户在 12 个月之前没有购买过任何商品
  • 渠道=通过电话、网站或多渠道购买订单
  • 细分=处理=男性电子邮件、女性电子邮件或无电子邮件
  • 访问=目标=客户在促销电子邮件后访问零售商网站,二进制 1 或 0
  • 或者,数据集可以加载两个备选目标变量之一:
  • — target_col = conversion —客户提交了采购订单,二进制 1 或 0
  • — target_col = spend —客户在两周观察期内花费的美元

作者图片

fetch_hillstrom() 函数将数据集作为 sklearn 的 bunch 对象之一进行检索。bunch db 由几个字典、数据帧和系列组成,其中:

  • db.data =特性列,数据框架
  • db.target =客户访问次数,一个系列
  • db。治疗=拓展行动——男人发邮件,女人发邮件,或者不发邮件——一系列

对于数据探索和争论,我更喜欢 pandas 的工具包,而不是 bunch 相关的方法。因此,让我们将三个源元素组合在一个数据帧 df0 中。

作者图片

源数据不包含空值。

作者图片

作者图片

每个分类列都包含相对较少数量的唯一值,这将使提升模型更容易在它们之间找到模式。

作者图片

作者图片

“治疗”一栏的图表显示,营销实验将 64,000 名顾客分为三组,每组实力相当。

作者图片

为了更深入地了解源数据结构,笔记本为其他特性绘制了类似的条形图。

作者图片

通过应用 numpy 的 setdiff1d() 函数,我们隔离了特征列,排除了目标和治疗变量,并将它们组合在单独的数据帧 dfX 中。

作者图片

为了理解特性的相关结构,让我们将分类列转换成数字变量。我们使用 pandas 的 get_dummies() 函数进行一次性编码,然后将转换后的数字列放入新的数据帧 dfXn 中。

作者图片

相关矩阵显示了一些强关联:“男士(商品)”和“女士(商品)”之间的负关联——有一些重叠,但不是完全的负关联,因为一些顾客显然购买了这两个类别的商品。“channel_Web”和“channel_Phone”之间也存在负相关关系:很少有客户在购买订单时同时使用这两个渠道。

作者图片

当我们交叉列表处理和目标变量时,我们发现男性和女性的电子邮件活动明显增加了观察期内网站访问的频率。在这两个星期中,“没有电子邮件”的客户出现的比率为 11%。零售商统计邮件收件人的回复率较高,分别为 15%和 18%。我们将通过应用提价模型和估计每个客户的提价来确定这种假设的影响。

作者图片

为了隔离“男性电子邮件”活动的治疗效果,我们将“男性电子邮件”编码为 1;而“女性邮箱”和“无邮箱”均为 0。

作者图片

Scikit-learn 的 train_test_split 方法保留了数据集的 30%,相当于 19200 个随机抽取的行,用于验证。

作者图片

我们准备将数据集输入到第一个模型中。

4.隆起模型

4.1 阶级转化模式

类别转换回复标签方法由 Jaskowski 和 Jaroszewicz 于 2012 年设计,着眼于临床试验(隆起建模)。**

它区分了四种情况:

  • 对照反应者:没有接受治疗但有反应(访问网站)的个人
  • 对照组无应答者:没有访问网站的对照组成员
  • 治疗反应者:接受治疗后有反应的个体
  • 治疗无反应者:接受治疗但无反应的个体

该模型背后的想法是,对照组中的无反应者可能包括一些可说服的人。这些患者没有接受治疗,因此没有被提示做出反应(隆起建模)。为了考虑到这一点,模型定义了一个新的目标变量 z。如果客户属于治疗组并表现出目标行为,则它等于 1,Y = 1;如果顾客属于控制组并且没有表现出目标行为,则它也等于 1,Y=0。

  • Z = YW + (1 — Y)(1 — W),其中 W 表示处理,Y 表示响应
  • 隆起= 2 * P(给定特征 X,Z = 1)—1(【gutierrez17a.pdf】T2)

该方法将上面列出的四个组分为两组。第一组包括所有的说服,一些失败的原因和肯定的事情。另一组包含所有不要打扰,剩余的失败原因和确定的事情。这种方法将问题转化为二元目标模型,任何机器学习技术都可以应用于该模型(提升)。

作者图片

训练完成后,我们在测试数据集上运行模型,然后检查其预测。

下面第 2 行中的函数 predict() 估计了对每个客户的提升效应:收到或未收到促销电子邮件时,响应(是否访问网站)之间的差异。

第 3 行计算了整个测试数据集的平均提升或治疗效果,5.39%,略低于上面建议的简单交叉表:治疗组和对照组的响应率之间的差异。

虽然了解所有客户的平均提升很好,但了解提升分数之间的差异会更有用。

第 7 行到第 10 行中的函数upload _ by _ percentile()根据客户的提价幅度从高到低对测试数据集中的客户进行排序。它分别计算治疗组和对照组的平均缓解率,然后将这些平均值的差异显示为给定百分位组中的提升效应。

我们在函数中选择 10 个箱。这将创建一个表,将客户分成 10 组。该表使我们能够辨别在最初几个十分之一的客户之后,提升效应是否会逐渐消失。在我们的例子中,情况并非如此。治疗组的缓解率并未显示出下降的模式,仍远高于对照组。

事实上,这不是我们想要的结果。80-20 法则的一个变种会更有效率。如果 20%的客户创造了 80%的总提升,我们可以得出结论,营销活动可以局限于最积极响应的客户。我们可以将反应最差的客户从我们的收件人列表中排除,以避免浪费时间、成本和精力。在我们的例子中,我们没有发现这样的分界点——所有十分之一的人对治疗反应积极,其中大多数人的反应程度适中。

作者图片

方法plot _ upgrade _ by _ percentile()将治疗组和对照组的缓解率可视化。除了少数例外,沿 x 轴方向上的抬升效应保持在 0.05 以上。

作者图片

希尔斯特罗姆的顾客似乎相当同质。如果他们表现出更强的差异,我们会看到:

  • 有说服力的人会把红色上升曲线的左腿抬高到高于 0.0539 的平均水平;
  • 其次是肯定的事情和失败的原因,谁会把上升曲线降低到零;
  • 接下来是“请勿打扰”,他们会将上升曲线拉到最右边的零以下。

几乎所有的 Hillstrom 客户都属于可说服类,至少如果我们使用网站访问量作为目标回应变量的话。不同的目标,例如采购订单,会给出不同的答案。

跨客户十分位数的提升效果的幅度也可以显示在条形图中。

作者图片

知道营销活动增加了客户的兴趣,我们现在可以再跟进两个步骤:

  • 就采购订单而言,我们可以期待哪种提升?事实上,Hillstrom 数据集包含一个可选的目标变量“conversion”(到采购订单)。自然,只有相对较少的一部分访问产生了采购订单,平均 10 次中有 1 次。这一替代目标的增幅仅为 0.5%。为了隔离一个更实际的效果用于演示目的,到目前为止我使用了目标变量“visits”。
  • 我们可以用金钱来表达活动的结果:估计采购订单的平均利润率。然后将提升的增量利润与营销活动的成本进行比较。这将使我们能够计算 ROMI,营销投资的回报。

4.2 单人模式

Solo 模型,又名 S-Learner 或虚拟治疗方法,基于卢大伟在 2002 年发表的一篇论文。它在处理样本和控制样本之间划分训练数据集。它的一个特征列由二进制治疗标志 0 或 1 组成:顾客是否接受了治疗。

Solo 模型的 Python 语法与类转换方法的语法相同,只是在设置上做了一些修改。

作者图片

平均涨幅为 5.43%。

Solo 模型,像下面的方法一样,提供了一组图表,这些图表对于类转换对象是不可用的:plot _ upgrade _ preds方法,它可视化了响应率的分布及其差异,即提升。属性 trmnt_preds_ 和 c trl_preds_ 将这些特定于客户的响应概率列表成数组。

作者图片

作者图片

另一个属性feature _ importances _,根据特性对目标变量的影响对其进行排序。这些重要性分数加起来是 1.0。上表强调了这种处理方式——男人的电子邮件活动——是第第二最重要的网站访问触发因素。新手往往比普通的电子邮件收件人更热衷于研究零售商的产品范围。这一结果提示了一个可能的后续项目:再次调查促销活动及其提升,但分别针对新手和老顾客。在今天的练习中,我们将在没有修改过的范围的情况下进行。**

接下来,我们将分析特定于客户的提价预测。****

热气球冒险 Pexels 在 Pixabay 上的免费照片

我们可以使用 predict() 函数和 trmnt_preds_ctrl_preds_ 属性提供的数组将我们的客户分类。首先,我们创建一个新的数据帧 dfZ。它的三个数字列由所有客户的提升分数和计算这些分数的两个概率组成——被减数:如果治疗,响应概率;减数:如果不治疗,反应概率。然后我们插入一个新列——客户类别“cats”——并通过计算三个数字列来自动填充它。在第 9 行,我定义了对应于类别标签的提升间隔:

  • 接近零的上升意味着肯定的事情或者失败的原因。在第 9 行到第 11 行中使用 pandas 的 cut 方法,我将它们都括在-0.01 和+0.01 之间的小区间中,并初步将它们都标记为“确定的事情”。
  • 低于-0.01 的负上升表示睡着的狗。
  • 那些正上升超过 0.01 的是可说服的。

失败的原因需要与确定的事情分开。失败的原因将减少访问网站的频率。由于缺乏精确的阈值,我们必须做出判断性的决定。在本例中,我定义低于 0.20 的概率将客户归入失败原因类别。其他客户在推广后没有改变他们的行为,但继续频繁地与网站互动,被标记为肯定的事情。当然,我们可以通过使用其他标准,而不是他们访问网站的倾向,来区分从不索取者和索取者。营销人员必须想出一个他们认为可行的信息标准。

作者图片

当我们回顾客户类别时,我们观察到睡眠狗的特征是负中值上升-1.3%;有说服力的,中位数为 4.7%。确定的事情和失败的原因徘徊在零左右。在 2 周的时间间隔内,失败原因访问网站的中值频率为 16%——尽管在这个例子中,确定的事情只是稍微活跃一些。

作者图片

作者图片

在测试数据集中的 19,200 个客户中,绝大多数属于可说服客户:其中 18,944 个客户的提价超过了我们设定的+1%的阈值。他们中很少有人对涨幅超过 7%的促销做出反应。Hillstrom 的客户很难通过电子邮件促销来说服。

作者图片

为了使营销团队能够做出更好的区分,我们可以标记最热切或最易被说服的人,例如那些涨幅高于 8%的人。可选地,我们还可以区分 1%到 8%之间的其他客户子集。然后,营销人员可以考虑类别列中的哪些子集应该包含在活动中。

作者图片

4.3 两个独立的模型

双模型方法在治疗数据集上训练第一个模型,在对照组上训练第二个模型。通过从治疗模型分数中减去对照模型分数,我们获得提升效应(gutierrez17a.pdf

拟合模型后,我们使用与 Solo 模型相同的 sklift 方法来获得预测。

平均提升效应达 5.34%。

作者图片

作者图片

作者图片

4.4 两个非独立模型,控制组领先

依赖模型方法依次运行这两个模型。第二个模型接受第一个模型的结果作为附加的特征变量。

第一个模型,如果它的【方法】参数设置为" ddr_control ",训练分类器对数据进行控制。分类器预测具有特征简档 X 的顾客主动访问网站(目标结果 Y=1)而没有接受治疗的概率,W=0:

  • PC = P(Y = 1 | X;W=0)

第二个分类器接受这些控制组预测作为另一个特征变量:

  • pw = P(Y = 1 | X;w = 1;Pc)

Pw 和 Pc 之间的差异代表了所有客户的提升效应矢量。

这种方法预测平均上升 5.38%,同样非常接近于前两种方法(转换和 Solo 模型)的结果。

作者图片

作者图片

作者图片

4.5 两个依赖模型,治疗组领先

我们可以颠倒模型的顺序,而不是将对照组模型的结果提供给治疗分类器。方法“ddr_treatment”建议该方法首先处理处理模型;然后将其结果用作控制组模型中的附加特征列。

作者图片

平均抬升效果比之前略有下降,5.33%。

5.模型比较

5.1 奇尼曲线和 AUUC 隆起曲线下的面积

该模型根据客户的提升分数从高到低对他们进行排名:从最热情的可说服者到最不喜欢打扰的人。然后绘制出治疗组和对照组的响应率之间的累积差异。由此产生的曲线被称为累积抬升、抬升增益或 Qini 曲线(抬升模型)

如果客户是随机抽取而不是排名,则直对角线衡量的是提升。

****Qini 系数测量 Qini 曲线(蓝色)和随机线(橙色)之间的面积。

典型地,Qini 曲线沿着 x 轴的前几个十分位数显示出稍微陡峭的上升。这些代表了那些反应提供最强提升增益的可说服者。稍后,如果客户子集包括失败原因和总是购买者,则曲线将变平,这些人对上升的贡献接近于零。如果它还包括“请勿打扰”(其提升分数将为负),则它可能会向下转,并降至随机线以下。

  • 随机线的 Qini 系数为零。Qini ≤ 0 的模型不会增加任何有价值的见解。
  • 最大 Qini 值取决于源数据。
  • 在处理相同源数据的替代模型中,产生最高 Qini 值的方法是优选的。

在我们的例子中,我们没有观察到一群狂热的可说服者会在早期做出显著的提升:曲线没有显示陡峭的上升。但是在 16,000 个客户之后,Qini 曲线移动到随机线以下一个档次,这是一个信号,表明在曲线用尽 16,000 个可说服客户之后,存在失败的原因,这些原因贡献了零提升和一些不要打扰。

AUUC 分数(上升曲线下的面积)是另一个性能指标。

从 AUUC 开始,Qini 系数可推导如下( hec.ca ):

  • 奇尼差=模型 AUUC —随机 AUUC
  • Qini 比率= Qini 差/(最优 AUUC-随机 AUUC)

这篇论文将 Qini 置于 AUUC 之上,声明 Qini 对群体选择效应更具鲁棒性。

5.2 模型性能

作者图片

作者图片

作者图片

作者图片

作者图片

我们观察到最高的奇尼系数和 AUUC 评分的 2 个独立模型的方法。

蓝色的 Qini 曲线相对平坦,而不是明显的凹形,这表明 Hillstrom 的大多数客户,如果他们有反应的话,往往是适度可说服的。

6.结论

我们已经了解到,我们可以预期“男士电子邮件”活动将提高客户参与度,根据网站访问量衡量,提高了 5.4%。

量化的提升将使我们能够做出明智的决策。

  • 我们可以将增量网站访问量乘以平均转化率:每次访问的购买订单;
  • 然后将额外订单量乘以平均订单价值,以获得增量销售收入的估计值;
  • 接下来,将收入乘以平均利润率,以获得该活动将产生的增量利润。
  • 这将把我们带到 ROMI,营销投资的回报:营销活动的利润除以营销活动的成本,减去 1。

货币价值将为决策者提出的问题提供答案:扩大我们试点活动的范围是否值得?或者,营销团队应该测试一种承诺更高提升的不同方法吗?

Jupyter 笔记本可从 GitHub 下载: h3ik0th/sklift:用 sci kit-lift(github.com)进行隆起建模

**https://medium.com/subscribe/@h3ik0.th

数据集:Hillstrom,内置于各种 Python 包如 sklift、py upon、causalinfer,以及微软的 ML Studio:使用样本数据集。可以单独从下载 csv 文件。**

宽松的运动裤——不光彩服装的数据科学

原文:https://towardsdatascience.com/sweatpants-unleashed-the-data-science-of-an-ignominious-garment-2e0c006202b0?source=collection_archive---------24-----------------------

新冠肺炎如何解开宽松服装时间序列分析

我们将运行一个 SARIMA 模型及其诊断,进行 KPSS、ADF、OCSB、CH 和正态性检验。一步一步,用 Python,在文明磨损的接缝处。

运动裤是失败的标志。你失去了对自己生活的控制,所以你买了一些运动裤。”卡尔·拉格费尔德

迈克·冯,unsplash.com

我们将分析从 2010 年到 2021 年 9 月的关键字“运动裤”的每月谷歌趋势数据;然后研究我们能从历史和人类文明的进程中获得哪些新的见解。

(PSA:末日就要到了!)

运动裤—探索—谷歌趋势

0.属国

1.数据处理

1.1 阅读和争论

从 Google Trends 下载 pants.csv 文件后,我们将其读入 Jupyter 笔记本。

“Month”列已经作为对象/字符串导入,因此我们将其转换为 datetime,然后定义一个索引。

我们的分析仅限于 2010 年以来运动裤时尚的起伏。

现在我们准备坐下来,开始一些严肃的数据争论,以了解运动裤时尚周期是由什么组成的。

迈克·冯,nsplash.com

1.2 视觉分析

1.2a 图表原始数据

我们观察到一个上升的长期趋势。不可否认,在过去的十年里,文明一直在向悬崖边缘漂移。

我们看到稳定的季节性波动——一直稳定到最近。该模式显示每年都有一个单独的波峰和波谷。

我们还察觉到一种漏斗状的波动模式。峰值和谷值在接近时间线末端时表现出更高的振幅。这表明异方差:方差不是时不变的。

1.2b 异常值、热图、趋势和季节性

我们将创建一个数据透视表,从中我们将得到两个图表,这将使我们能够关注时间序列的不同方面。

数据透视表为我们提供了一种聚集、排序和过滤源数据的好方法。

数据透视表显示,运动裤的受欢迎程度在接近年底时会飙升。让我们想象一下热图中宽松裤子的热区。

我们在每年 12 月观察到季节性高峰,搜索活动在 10 月和 11 月开始增加。

  • 要么人们倾向于在寒冷的仲冬 1 月和 2 月前 3 个月,通过谷歌搜索舒适温暖但不太紧身的舒适服装,为寒冷的季节做好心理准备;
  • 或者成堆的包装好的运动裤——不幸的是——真的把圣诞树下的地板弄得乱七八糟。

在 2020 年的热图中,我们可以辨别出运动裤出轨的时刻:2020 年 4-5 月和 2020 年 11/12 月。这些尖峰将成为我们分析的焦点。

让我们想象一下长期趋势。我们取我们的数据透视表,应用聚合函数‘mean’,选择作为数据透视表中的‘index’;然后绘制年利息的逐年趋势。

巴黎时尚沙皇卡尔·拉格费尔德可能会惊呼“末日将至!”十多年来,如果卡尔是对的,我们的文明似乎一直在集体失去对我们生活的控制。

在经历了 2010 年以来不可阻挡的增长路径后,我们在 2020 年达到了裤子宽松的峰值,至少是暂时的。

接下来,让我们更仔细地调查源数据中的季节性。我们选择作为数据透视表中的索引,并让该表计算我们的时间序列中所有年份中每个月的平均值;然后画出 12 个月的曲线。

我们在每个第四季度末观察到一个季节性的裤子口袋高峰。该图表明,通常情况下,每年都会在 6 月/7 月出现一个低谷,然后在 12 月出现一个高峰。

总而言之,让我们将时间序列分解为趋势、季节性和残差,并在一个函数中加入相关图(ACF 和 PACF)。

pmdarima 包提供了 tsdisplay 方法来可视化时间序列。除了我们上面创建的图表,tsdisplay 还显示了观察结果的直方图(右下角)。显然,观察值不是正态分布的;他们是左倾的。非正态性不会使我们想要开发的 SARIMA 预测模型无效。但是常态会给我们提供更可靠的预测和置信区间。

更令人担忧的是顶部观察曲线的漏斗形状。加宽的漏斗表明方差不是时不变的,这对于时间序列预测是强制性的。

2.诊断和转换

2.1 同伦方差和正态性

直方图显示的观察值似乎不是正态分布的。让我们运行 scipy.stats 的常规测试

该检验证实了原始时间序列不是正态分布的,其 p 值小得几乎为零。

所以我们不得不坐下来,穿着时髦的黑色运动裤,思考我们的下一步。

迈克·冯,unsplash.com

如果可能的话,我们决定尝试两种变换来解决这两个问题:非正态性和——更迫切的——异方差(非恒定方差)。

2.1a 对数转换

首先,我们对观察值进行对数变换。

转换的目的是以缩小其扩张漏斗(减少其异方差)的方式重塑观察曲线;并且理想地还通过调整它们分布的偏斜度和峰度来弯曲曲线,使得它与正态分布的数据更接近地对齐。

拟合预测模型后,我们将能够对预测值进行逆变换,使它们与原始的、未变换的时间序列数据具有可比性。

pmdarima 包提供了 LogEndogTransformer 方法。

经过对数变换的折线图已经失去了它大部分有关的漏斗形状。方差似乎也是时不变的。直方图类似于正态分布,没有明显的向左或向右倾斜。正态性检验的高 p 值证实了这一点。

2.1b Box-Cox 变换

作为对数转换的替代方法,我们运行 Box-Cox 转换器,它通常比对数转换更有效。

这些图表看起来类似于经过对数变换的序列。正态性检验返回一个更有利的 p 值。

我们将继续讨论 Box-Cox 变换系列。

2.2 自相关结构

接下来,我们研究 Box-Cox 变换序列的相关图。

我们在 ACF 中看到一个季节性的模式。因此,时间序列还不是静止的。

2.3 平稳性

如果时间序列的均值、方差和自相关结构不随时间变化,则时间序列是稳定的。如果它们不是时不变的,我们今天用来准备预报的属性将不同于我们明天观察到的属性。一个不稳定的过程会避开我们利用过去的观察来预测未来发展的方法。时间序列本身不需要在过去和未来期间保持平坦、恒定的直线才能被认为是平稳的,但决定其随时间变化的模式需要是平稳的,以使其未来行为可以预测。

时间序列需要展示:

  • 非时变均值
  • 非时变方差
  • 非时变自相关

变化无常的意思

显示强劲上升或下降趋势的序列没有恒定的平均值。但是如果它的数据点在扰动后趋向于回复到趋势线,时间序列就是趋势-平稳的。通过差分时间序列——取观察值 y(t)和早期观察值 y(t-n)之间的差值——我们可以获得变化的平稳(均值回复)序列。

具有季节性的时间序列将显示出在恒定数量的周期之后重复的模式:一月份的温度与七月份的不同,但是一月份的温度将在几年之间处于相似的水平。季节差异是指一个观测值与其前一个观测值之间的差异,即消除了 S 个滞后,S 是一个完整季节的周期数,比如一年 12 个月或一周 7 天。

如果趋势和季节模式都是相对时间不变的,差分时间序列(相对于趋势的第一差分;和相对于季节性的季节性差异)将具有近似恒定的平均值。

在将预测模型拟合到数据之前,所需的差分阶数是应该预先确定的参数。“重要的是要注意,这些信息标准往往不是选择模型差分(d)的适当阶次的良好指南,而只是选择 p 和 q 的值。这是因为差分改变了计算似然性的数据,使得具有不同差分阶次的模型之间的 AIC 值不可比。所以我们需要使用一些其他方法来选择 d,然后我们可以使用 AICc 来选择 p 和 q”(hynd man, 8.6 估计和顺序选择|预测:原则和实践(第二版)(otexts.com))。

为了确定是否需要差异,我们可以运行四个测试:

  • 一阶差分的增广 Dickey-Fuller ADF
  • 科维亚特科夫斯基-菲利普斯-施米特-申 first 获得第一名
  • Osborn-Chui-Smith-Birchenhall OCSB 季节性差异
  • 卡诺瓦-汉森季节差异研究中心

2.3a 一阶差分

我们使用 pmdarima 的 ADF 和 KPSS 检验来获得建议的一阶差分。

我们有一个矛盾。KPSS 要求 1 阶差分,而 ADF 要求 0 阶差分。

  • 如果 ADF 测试没有找到单位根,但是 KPSS 测试找到了,这个序列就是差分-平稳的:它仍然需要差分。
  • 相反,如果 KPSS 检验没有找到单位根,但是 ADF 检验找到了,那么该序列将被认为是趋势-平稳的:它将需要差分(或其他变换,如去趋势)。
  • 一般来说:如果测试不一致,我们需要取两个测试结果中较高的(变量 n_diff )作为适当的差分顺序。只有当两个检验都认为数列是平稳的,我们才能避免求差。

2.3b 季节差异

我们对 Box-Cox 变换系列进行 OCSB 和 CH 检验。两种测试都认为不需要季节差异。

2.3c 转换后的检查

我们结合平稳性的测试结果,并计算一个不同的时间序列。

  • 下面数据框中的“裤子”一栏包含了关于运动裤流行度的原始谷歌趋势数据。
  • 列“y_bc”包含经过 Box-Cox 变换的值。
  • 列“y_bc_diff”显示了差异值和转换值。

**

最后一轮诊断,现在是差异数据:

  • 差异数据仍然通过了 p 值高于 0.05 的正态性检验
  • 平稳性测试并不坚持额外的差分轮次

2.4 训练和测试数据集的拆分

我们将 Google 趋势观察分为训练数据集和测试数据集。在持续的测试中,我们保留了最后的 24 个月用于测试。

3.萨里玛

3.1 训练:自动 ARIMA 搜索超参数

pmdarima 包的 AutoARIMA 方法对 SARIMA 模型中的自回归 AR 项和移动平均 MA 项运行超参数搜索。

我们选择逐步搜索,它使用 Hyndman 和 Khandakar 在 2008 年开发的算法(自动时间序列预测:R(r-project.org)的预测包)。该算法比全网格搜索快得多,因为它避免了在搜索空间中处理无意义的参数元组。

我们将 AutoARIMA 方法的输入公式化为所谓的管道。管道由我们的 Box-Cox 转换组成(但是如果我们想要包含它们的话,可以包含额外的转换)。管道语法将使我们能够在计算预测时对模型结果进行逆变换。

模型摘要显示了优秀的诊断结果:

  • Ljung-Box 测试返回非常高的 p 值 0.91。所以残差代表白噪声。它们不包含萨里玛模型未能发现的信号,而这些信号本可以用来提高其预测的准确性。
  • Jarque-Bera 正态性检验得出非常高的 p 值 0.72。偏斜度接近 0,峰度接近 3,因为它们应该类似于标准的正态分布。因此,我们得出结论,残差是正态分布的。预测值和置信区间将比具有可疑正态性的残差更可靠。
  • 异方差测试得出非常高的 p 值 0.78。我们得出结论,残差具有恒定的方差。
  • 大部分的萨里玛参数都有远离零的系数,所以它们的影响是不可忽略的。第二个季节性 AR 术语 ar 是个例外。S.L24 ,其系数接近于 0,具有跨越零的宽置信区间。它的 SAR 项也显示出非常高的 p 值。我们的结论是,第二个 SAR 术语可能应该跳过。它对模型的贡献不大。

3.2 预测准确性指标

我们定义了一些预测准确性指标,这将使我们能够将我们刚刚准备的训练数据集的 SARIMA 模型与即将到来的样本外预测进行比较。

我们用公式来填充字典:

  • 平均绝对误差(MAE),
  • 平均绝对百分比误差(MAPE),
  • 均方根误差(RMSE)和
  • 预测值和观测值之间的相关性

3.3 训练:样本内预测

pmdarima 的 predict_in_sample 方法将拟合的 SARIMA(0,1,1)x(3,0,0)(12)模型应用于我们培训期间的月份。

参数 inverse_transform 告知该方法以与原始时间序列相似的结构提供预测值及其置信区间:预测值不会被报告为 Box-Cox 变换值。

训练数据集的预测精度不会太差。

自动安装的 SARIMA 模型已经捕获了 ca。91.5%的历史运动裤流行度起伏:平均绝对百分比误差 MAPE 相当于预测值和实际值之间的 8.5%的差异。8.5 %由随机波动组成,模型无法提取稳定的模式。

均方根误差 RMSE 是残差的标准偏差。RMSE 讲述了预测与实际观测曲线的紧密程度。

预测值和实际值之间的(线性)相关性为 97%。

3.4 测试:测试数据集的预测

接下来,我们在测试数据集中运行相同的 SARIMA 模型 24 个月。

我们得到的预测准确度要差得多。MAPE 现在达到了 23%。预测和实际观测的相关性从 97%下降到 78%。

那么,在 2020-2021 年,是什么在困扰着我们的萨里玛模式呢?

训练和测试数据集之间预测准确性的巨大差异通常意味着过度拟合

  • **欠拟合的模型在拟合的训练数据集和测试数据集中都会表现出较低的精度。
  • **过度拟合的模型将在训练数据集中呈现高精度,但是处理新数据(例如测试数据集中的数据)的能力很差。

在我们发布的运动裤案例中,一旦 2020 年 4 月在家工作月开始,时间序列在之前 10 年遵循的模式不再适用。这意味着一个过度拟合模型,但过度拟合是不可避免的,因为 2020 年的中断无法从训练数据集中的 2010-2019 年历史数据中分离出来作为一种可预测的模式。

3.5 2020 年,过去的模式将不复存在

让我们回顾一下我们在源数据调查中创建的热图。我们注意到 2020 年是不同寻常的一年,

  • 2020 年 4 月至 5 月,运动裤的谷歌搜索出现了不寻常的“非季节性”高峰;
  • 另一个高峰出现在 2020 年 11 月/12 月,这与前几年的季节模式更相似,但作为一个热门时尚项目,它的增幅远远高于前几个冬季。**

我们不能仅从谷歌趋势数据中提取原因。但 2020 年的这种模式表明,4 月份对运动裤的兴趣飙升,当时许多人不得不挤在家里温暖的笔记本电脑屏幕周围,而不是继续早晚通勤去工作场所。显然,我们大多数人选择不穿正式的办公室服装,而是坐在餐桌旁敲键盘。

在 2020 年 11 月至 12 月,我们观察到运动裤欢呼的幅度高于往常,这可能是因为新冠肺炎病例在 2021 年初疫苗上市前的几个月里快速上升。在 2020 年的秋天,人们可能已经预料到不得不撤回到他们家的洞穴里度过一个漫长而可怕的冬天。

从我们的数据科学工具箱中,我们可以拉出用于协整* & 格兰杰因果关系( 格兰杰因果关系)的测试工具包。如果我们比较 2020 年在家工作和运动裤受欢迎的程度,我希望看到一些重要的格兰杰因果关系。*

我们的下一步是什么?

让我们调查一下在家工作的突然兴起对过去十年一直有效的时间序列模式造成了多大的破坏。

4.2020 年的可预测趋势与趋势突变

4.1 将 SARIMA 模型训练到断点

从我们的谷歌趋势原始数据 2010 年至 2021 年,我们切下了一个训练数据集,该数据集于 2020 年 3 月结束,就在封锁和在家工作的惯例建立新的现实之前。

我们将新的 SARIMA 模型拟合到代表旧常态的训练数据集。

然后我们对 2020 年 4 月以来的几个月进行预测。

新的训练模型返回到 2020 年 3 月运动裤流行的预测。

4.2 在 2020 年 4 月的转折点之后测试 SARIMA 模型

让我们看看运动裤在 2020 年 3 月后不受新冠肺炎影响的另一个宇宙中会如何发展。

正如预期的那样,预测精度相当差,说明 Covid 的破坏从 2020 年 4 月开始将宽松裤趋势置于一条非常不同的、不可预见的道路上。

4.3 自 2020 年 4 月以来不可预见的“在家工作”影响

为了辨别新冠肺炎对运动裤时尚角落的影响程度,让我们比较一下 2020 年 4 月后在那个替代宇宙中的预测和在我们的宇宙中发生的事情。

  • 我们可以看到 2011 年至 2020 年第一季度间,萨里玛预测(橙色)与实际观测(蓝色)的接近程度。
  • 在 2020 年第二季度初,运动裤突然出现了额外的蓝色尖峰,这在任何季节模式中都从未出现过。未预料到的 4 月/5 月峰值导致了我们预测指标报告的大部分不准确性。
  • SARIMA 模型确实预测了 2020 年 11 月+12 月的峰值。
  • 然而,该模型没有预见到运动裤会在 2021 年,也就是新年伊始之后,突然流行起来;甚至在许多在家工作的安排被改变之前。
  • 我们可以推测,家庭已经在 2020 年储备了运动裤。到 2021 年 1 月,他们在接下来的 2 到 3 年里都有宽松的裤装。所以对运动裤的寻找在 2021 年失去了紧迫性。
  • 运动裤行业在 2020 年蓬勃发展,随后在 2021 年初陷入萧条。

下一步可能是进行干预分析,分离出在家工作的影响,例如将其定义为外生变量

但我们今天不会这么做。相反,我们会把穿着宽松衣服的腿翘起来小睡一会儿。

迈克·冯,nsplash.com

用伯特回答瑞典语问题

原文:https://towardsdatascience.com/swedish-question-answering-with-bert-c856ccdcc337?source=collection_archive---------27-----------------------

如何微调非英语 BERT

乔恩·泰森在 Unsplash 上的照片

问题回答是自然语言处理领域中研究得最多的任务之一,过去几年中的一个亮点是 BERT 的出现。

BERT 和其他基于 Transformer 的模型现在可用于多种语言。然而,对于相对次要的语言,例如瑞典语,可用的模型是有限的或者根本不存在。当我们试图将瑞典语 BERT 微调到一个问题回答任务时,我们面临了几个挑战。这篇文章的目的是记录我们是如何解决这些问题的。

这篇文章的主要重点将是使用 SQuAD 2.0 的问答任务。

StanfordQuestionAnsweringDataset(SQuAD)是一个阅读理解数据集,由一组维基百科文章上的问题组成,其中每个问题的答案都是相应阅读文章中的一段文字或跨度,或者问题可能无法回答。squad 2.0【Pranav Rajpurkar,Robin Jia & Percy Liang,2018】将 SQuAD1.1 中的 10 万个问题与超过 5 万个无法回答的问题结合在一起。

用 BERT-family 构建瑞典问答系统的三种方法

如果你想用 BERT-family 做一个瑞典语(或者你首选的非英语语言)的问答任务,你可以想出三种方法。

  1. 将瑞典语问题翻译成英语,用英语 BERT 处理,并将英语答案翻译回瑞典语
    👍有许多英文资源,包括微调模型。
    👎对每个推理都要进行翻译,这增加了计算成本。有误译的可能。
  2. 使用多语言模型处理瑞典语问题
    👍多语言模型也是许多研究的主题,因此有许多可用的资源。
    👎多语言模型比单语模型具有更大的模型大小,这使得当您只想处理瑞典语时,它们的效率很低。
  3. 将英语数据集翻译成瑞典语,微调预训练的瑞典语 BERT,并将微调的瑞典语 BERT 用于瑞典语 QA
    👍可以获得相对较小的模型以进行有效的处理。
    👎数据集的误译可能会导致意外的偏差。

在本文中,我们将重点讨论第三个选项,即使用瑞典语 SQuAD 构建一个瑞典语 QA BERT。

小队 2.0 的翻译

我们已经使用谷歌翻译 API 自动翻译了 SQuAD 2.0。这听起来像是一项简单的任务,但事实并非如此,原因如下。

  • 上下文中决定答案起止的跨度,翻译后可能会发生变化。
  • 如果上下文和答案是独立翻译的,则翻译的答案可能不包括在翻译的上下文中。

让我更详细地解释一下第一点。比如《小队 2.0 dev》中的文字有以下语境(摘自一整句话)、问题、答案。

上下文 氧是一种化学元素,符号 O,原子序数 8。

问题
元素周期表中氧的原子序数?

回答 8

——摘自 小队 2.0 dev、氧气

在这种情况下,答案的跨度是从 60 到 61,这表明了摘录的上下文中答案的开始和结束的位置。

这个上下文可以翻译成瑞典语如下。

Syre är ett kemiskt grundämne med symbol O och atomnummer 8.

现在,答案的正确跨度是从 53 到 54。因此,我们不仅需要翻译上下文和答案,我们还需要正确地跟踪它们在上下文中的位置。

例如,关于第二点,我们在氧气文本中有以下上下文、问题和答案。

关于燃烧和空气之间关系的第一个已知实验是由公元前 2 世纪的希腊力学作家拜占庭的菲洛进行的。

问题
已知的第一个关于燃烧和空气的实验是在哪一年进行的?

答案 公元前二世纪

——摘自 小队 2.0 dev、氧气

由 Google 翻译这个上下文,至少现在,会产生以下输出。

Ett av de första kända experimenten om förhållandet mellan förbränning och luft utfördes av den grekiska författaren om mekanik under 2000-talet f.Kr. Philo of Byzantium.

然而,如果我们独立翻译答案公元前二世纪,我们得到如下。

2: a århundradet fvt.

因此,如果你独立地翻译上下文和答案,在上下文中可能找不到基本事实答案。我们需要连贯地翻译上下文和答案。

克服问题的简单策略

为了克服上述困难,我们采用了以下策略。

  1. 在翻译之前,在上下文中的答案周围插入特殊标记。比如《小队 2.0 dev》中的文字有以下语境(摘自一整句话)、问题、答案。

上下文 双原子氧气构成了地球大气的 20.8%。然而,对大气含氧量的监测显示,由于化石燃料的燃烧,全球含氧量呈下降趋势。

问题
哪种气体占地球大气的 20.8%?

答案 双原子氧

——摘自 小队 2.0 dev、氧气

在这种情况下,我们在答案双原子氧周围插入特殊标记【0】,得到

[0] Diatomic oxygen [0] gas constitutes 20.8% of the Earth's atmosphere. However, monitoring of atmospheric oxygen levels show a global downward trend, because of fossil-fuel burning.

注意,特殊标记不限于【0】,我们也可以使用其他标记。

2.翻译标记的上下文。结果会是这样的;

[0] Diatomiskt syre [0] gas utgör 20,8% av jordens atmosfär. Övervakning av syrehalten i atmosfären visar dock en global nedåtgående trend på grund av förbränning av fossila bränslen.

3.从翻译的上下文中提取标记的句子。这将是翻译的答案。标记的句子的开始和结束将是答案的跨度。

产生的数据集在github repo拥抱脸数据集中可用。

我承认这个策略并不完美。有些答案在上下文中找不到,所以这些不合适的例子必须删除。因此,转换后数据集的大小约为原始数据集的 90%。

评估班 2.0 开发

我们微调了由瑞典国家图书馆(KB 实验室)预先训练的瑞典语 BERT ,并在我们的 SQuAD 2.0 dev 数据集的瑞典语翻译版上评估了三个模型。

第一个型号是由 deepset GmbH 公司在班培训的多语种 XLM-罗伯塔。这是上面列出的第二个选项的示例。

第二个模型是在小队上训练的 KB 实验室模型。这种模式被贴上了“实验性”的标签,但效果很好。

第三个模型是我们的 BERT,它在我们的瑞典版 SQuAD 2.0 训练数据集上进行了微调。

评估结果总结在下表中。

╔═════════════════════════════════╦═════════════╦═══════╗
║              **Model              ║ Exact Match ║  F1 **  ║
╠═════════════════════════════════╬═════════════╬═══════╣
║ Multilingual XLM-RoBERTa(large) ║    56.96    ║ **70.78** ║
║ Swedish BERT (base, KB Lab)     ║    65.65    ║ 68.89 ║
║ Swedish BERT (base, Ours)       ║    **66.73**    ║ 70.11 ║
╚═════════════════════════════════╩═════════════╩═══════╝

我们的模型具有大约 110M 的参数,获得了比 KB 实验室模型更好的分数,并且与具有大约 550M 参数的 XLM-罗伯塔相比,建立了接近的 F1 分数。

如果你有兴趣使用微调过的模型,该模型可在 HuggingFace 模型中枢中获得。

诺贝尔奖数据集

出于评估目的,我们在内部创建了瑞典语的诺贝尔奖数据集。该数据集包含最近诺贝尔物理学奖的描述作为上下文和手动创建的问答对。该数据集包含 91 个问答对,因此大小很小,但对评估很有价值。

由于该数据集是独立创建的,并且该模型以前没有见过该数据集,因此如果我们使用微调模型而不进行进一步训练,则该结果是真实的。

评估结果总结在下表中。我们的模型在精确匹配和 F1 分数上都取得了更好的结果。

╔═════════════════════════════════╦═════════════╦═══════╗
║              **Model              ║ Exact Match ║  F1 **  ║
╠═════════════════════════════════╬═════════════╬═══════╣
║ Multilingual XLM-RoBERTa(large) ║    13.19    ║ 60.00 ║
║ Swedish BERT (base, KB Lab)     ║    32.97    ║ 52.41 ║
║ Swedish BERT (base, Ours)       ║    **46.15**    ║ **61.54** ║
╚═════════════════════════════════╩═════════════╩═══════╝

摘要

提出了一种正确翻译抽取式问答任务数据集的方法。我们在翻译数据集上将我们的微调模型与其他微调模型的性能进行了比较,并确认我们的模型表现相对较好。

关于我们

图片由 Savantic AB 提供

我们是斯德哥尔摩的 博学 AB安艾公司。我们喜欢解决不可能的问题!

参考

用于无监督任务解决的瑞士军刀

原文:https://towardsdatascience.com/swiss-army-knife-for-unsupervised-task-solving-26f9acf7c023?source=collection_archive---------26-----------------------

伯特是从业者工具箱中的一个额外奖励

图一。除了对下游任务进行微调这一众所周知的用途之外,BERT 成为从业者工具箱中一个有价值的补充的原因很少。 (1) BERT 学习的向量词汇(比如 768 维空间中)用作目标,屏蔽输出向量在训练期间预测并从预测误差中学习。在训练之后,这些移动目标被安置到标志中,这些标志可以被聚集和注释(一次性步骤),并用于在各种任务中对模型输出向量进行分类 After、关系提取等。(2)预训练足以实现低下一个句子预测损失(除了屏蔽词预测损失之外)的模型产生代表任何输入术语/短语/句子的高质量 CLS 向量。CLS 矢量需要从 MLM 头部获取,而不是从最顶层获取,以获得输入的最佳可能表示(如下图)。(3) MLM 头解码器偏差值是词汇表检索词的重要性的有用分数,并且相当于词汇表检索词的 TF-IDF 分数。(4)在大多数情况下,除了用于 NER 标记之外,BERT 间接通过该位置的词汇单词替换来预测句子中单词的实体类型的能力可以是非常方便的。偶尔,对位置的预测甚至可能是正确的实例,但是这对于任何实际应用通常都是不可靠的。(5)任何输入术语/短语(及其拼写错误的变体)的矢量表示,或者直接从 BERT 的学习词汇中获取,或者使用 CLS 创建,在很大程度上包含了先前模型如 word2vec、Fasttext 的上下文无关矢量,使得 BERT 成为获取上下文相关矢量和上下文无关矢量的一站式商店。唯一的例外是输入的表示涉及 BERT 词汇表中不存在的字符(例如,精心选择的自定义 BERT 词汇表,以避免来自应用领域之外的语言,如中文、泰米尔语等)。).获取这些好处的核心是如何在我们的应用程序感兴趣的特定领域语料库上使用自定义词汇表对模型进行预训练。作者创建的图像

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

传统上需要标记数据的自然语言处理任务可以通过利用 BERT 模型的自监督学习来完全或部分地解决,而不需要标记数据,只要这些任务本身被完全或部分地视为相似性度量问题。

除了语义搜索(这是固有的相似性度量)之外,可以完全被视为相似性度量问题的任务的例子是像 NER 这样的序列标记问题。虽然某些种类的句子分类任务可以被视为相似性度量问题,但是情感分类不能利用相似性度量,给定的 BERT 模型不考虑概念的负面或正面情感而对其进行聚类,并且即使给定完整的句子上下文也不能可靠地将它们分开。收获一个不基于相似性度量(例如依赖解析器)的图,也在 的范围之外(尽管有可能收获一个具有监督学习的转换的依赖图) 。然而,与相似性度量(用于检测实体类型,依赖解析器边缘链接)一起使用的依赖解析器可以用于关系提取。

这篇文章回顾了一些任务,在这些任务中,BERT 的自我监督学习被用来完全或部分地解决一个任务。这些任务通常通过微调 BERT(它在 NLP 任务解决中的主要用途)使用标记数据来解决。

是什么让伯特成为了瑞士军刀?

一般来说,网上有关于 BERT 和 transformer 模型的优秀详细文章。

本节的重点是 BERT 的内部工作原理,它可以用来避免传统的监督 NLP 任务中的标记数据。

从头开始预训练 BERT 模型之前的关键步骤是选择最能代表用于训练的语料库的词汇。这通常是由字符、完整单词和部分单词(子单词)组成的大约 30,000 个术语,它们可以被拼接以组成完整的单词。模型的任何输入都将使用这大约 30,000 个术语构建(如果输入包含一个不能分解成这 30,000 个术语的术语,它将被表示为一个特殊的未知标记,也是这个集合的一部分。一个例子是说一个在 30k 集合中不存在的汉字)

在训练期间,

  • 该模型学习其词汇表中所有术语的向量表示。当每个句子被输入到模型中时,通过将输入训练语料库中的句子分解成词汇表中的术语(标记化)来促进这种学习。在训练之前,模型从其词汇表中的每个术语的随机向量表示开始,由于这些向量的高维度(例如,768) ,使得它们几乎彼此正交 (本质上是一种密集表示,其行为类似于一个热点向量,其中每个词汇表术语被唯一地表示,并且几乎与所有其他术语正交)。
  • 该模型学习由 BERT 模型的所有层组成的转换。这个学习转换(本质上是学习实现转换的权重),是一个函数,它接收表示输入句子(前面提到的向量)中每个符号化术语的向量,并为每个输入向量产生转换后的输出向量。在训练期间,大约 15%的那些输入向量被占位符向量或者被另一个单词(从词汇表中随机选取)的向量替换,并且强制转换以产生输出向量(利用输入句子中其他向量提供的上下文),该输出向量可以相对于其他词汇表向量被评分,以预测被替换的相同原始向量。输出向量和被屏蔽/替换的原始向量之间的余弦距离是确定分数的关键因素。与直觉相反,屏蔽/替换位置的最高得分输出向量和实际词汇向量(被预测的向量)之间的角度可以更接近正交而不是共线——即,相隔高达 80 度。然而相对于其他词汇向量,它仍然使输出向量成为最佳预测(图 5)
  • 一个关键事实是词汇项的向量表示和模型转换权重是同时学习的。乍一看,这似乎很奇怪,因为转换的学习依赖于词汇向量,这些词汇向量既作为输出端的参考向量,又在输入端表示句子,而这些词汇向量本身是不断变化的。这种同步学习方法是可行的,因为在训练过程中,句子中很少的标记被占位符/随机单词向量取代 (~15%) 。因此,通过从输入端参与替换向量的预测,每个词汇向量比其自身在输出端被用作参考向量以使变换后的替换向量向其靠拢的机会多得多。一旦训练完成,这些词汇向量就作为静态标志向量来推断输出向量的含义,这将在下面详细解释。
  • 另一个有趣的事实是,即使单词的相同目标向量用于影响单词的上下文不同含义的学习,词汇表中捕捉上下文不同含义的单词向量也不一定在一个群集中混合在一起——这是一个有用的属性,在下面描述的无监督应用中被利用。例如,词汇向量空间中单词细胞 (在用生物医学领域语料库上的自定义词汇从头开始预训练的模型中)的余弦邻域主要是生物学术语(图 4) 。术语捕捉到了另外的含义(细胞 电话 监狱 细胞)远离向量细胞。这与像 word2vec 这样的模型形成了鲜明的对比,在这种模型中,一个单词的所有义项(含义)将混合在顶部邻域中。然而,在某些情况下,词义的混合也可以在潜在的习得词汇中观察到,如 word2vec 模型。例如,学习词汇向量空间中的余弦邻域,对于术语 her 来说,是两种意义的混合——代词和基因——his,she,hers,erbb,her2 (图 2) 这是一个事实的结果,即在一个未装箱的模型中,HER——一个基因,被转换成 her,增加了与代词 her 的歧义。然而,转换仍然根据句子上下文(这是假设两个不同意思的句子上下文是不同的)来分离这些意义。总之,对于输入句子中的每个术语,学习转换通过利用句子上下文,为屏蔽/替换的术语找到新的向量,相对于该向量,词汇向量空间中的余弦邻域由语义相似的术语组成,而不管屏蔽术语的语义不同的含义在词汇向量空间中被群集或分离的事实(尽管在大多数情况下,在良好训练的模型中,词汇向量群集倾向于捕获单个实体意义,达到一定的粒度水平)

图二。根据从医学语料库创建的词汇表创建的聚类,并且根据在医学语料库上训练的模型创建其向量。聚类反映了实体类型的混合—代词和基因。这是因为“ her ”这个词——大写形式通常指的是基因。无案例模型增加了模糊性。尽管在词汇向量空间中存在这种实体类型的混合,但是所学习的转换在使用句子上下文的句子中的屏蔽位置的模型输出中清楚地分离了这些意义。例如,第一句中的空白位置在基因上下文中,第二句中的空白位置在代词上下文中。作者创造的形象

人们可以在一个句子中看到完整的转换,其中一个单元的所有不同含义都基于它在句子中的位置/上下文出现。注意力——转型的一个关键组成部分是实现这一目标的核心。通过对单元的每个出现执行句子(其中权重不是静态学习的权重,而是作为句子中的单词的函数创建的动态权重)中的特定术语的加权求和,捕获单词单元的不同上下文含义。

他带着一部细胞手机去监狱细胞从犯人身上抽取血液细胞样本

图 3。接近某个位置的模型输出向量的前三个词汇向量。请注意,余弦距离值非常小,向量更接近于正交,而不是共线。黄色突出显示的单元格反映了输出分数受到词汇向量偏差或词汇向量幅度影响的情况,如下图 13 所示。作者创造的形象

图 4。术语单元格与 BERT 模型词汇表中其他单词之间的余弦距离值直方图。对于细胞来说,最接近矢量的邻居很大程度上是由生物学术语组成的。一位数计数尾部从 0.53 的余弦距离(忽略 1)一直延伸到 0.16 的余弦距离(80 度)。作者创作的图片

图 5。上半部分显示了与图 4 相同的词汇向量单元邻域的直方图。它还显示了捕捉单词 cell 的三种不同“感觉”的选择术语的余弦距离——生物感觉、“房间/位置”感觉和电话感觉。捕捉生物意义的术语在尾部,更接近于细胞的向量。单元格的向量沿着 x 轴。单词细胞的另外两个意义几乎与细胞向量正交,并且与生物学意义完全分离。下半部分示出了句子“他去监狱细胞细胞电话从囚犯身上抽取血液细胞样本”中三个屏蔽位置的模型输出向量的顶部余弦邻居。请注意,尽管三个位置的最接近词汇向量反映了术语单元格的不同含义,但这些词汇向量几乎与输出向量正交(沿 x 轴显示为红色)。然而,所有位置的直方图分布具有明显的尾部,其中顶部预测与其余项分离得很好。尽管事实上所有的词汇向量都存在于大约. 19 到大约. 24 的小范围内。该模型的学习转换在词汇向量空间中找到有利点,在该空间中,捕获被屏蔽术语的含义的向量在相对意义上而不是余弦值的绝对意义上更接近于输出向量。作者创建的图像

上述使 BERT 成为瑞士军刀的训练过程的结果是,词汇向量在很大程度上形成实体特定的簇以及捕获句法相似性的簇。这些聚类的性质受到其被训练的语料库以及训练过程的超参数的影响,例如批量大小、学习速率、训练步骤的数量等。这些集群可以基于感兴趣的应用的(集群的细节在下面的附加注释中)进行标记——一次性过程。与学习转换结合使用,它们有助于将传统标记的数据问题转换为无监督的任务。

图 6。根据 BERT 大型案例模型和词汇创建的聚类。实体类型反映了模型被训练的语料库的性质。作者创建的图像

图 7。从词汇表创建的聚类,该词汇表是从医学语料库创建的,并且其向量是从医学语料库上训练的模型创建的。注释显示了生物性质的主要实体类型。作者创造的形象

句子中术语的无监督标注

无监督的 NER,在本文中详细解释,简单地利用经过训练的 BERT 模型词汇的聚类属性来标记模型对句子中术语的预测。

图 8使用 BERT 的无监督 NER。 作者创建的图像

应该可以将相同的方法应用于无监督的位置,至少对于一些粗粒度的标记类型,可以通过 BERT 词汇表的不同集群来区分。标签的单数和复数版本将无法区分,因为它们将聚集在同一组中。在这种情况下,转换不能将它们分开,因为单数和复数版本的句子上下文几乎相同。

无监督短语/句子表示

在评估预训练模型的向量时,一个不可错过的关键细节是从获取模型输出向量的。正确的地方是从蒙面 MLM 头(在一个 PyTorch 垃圾场捕获的 cls.predictions)* 。这是因为在预测输出向量之前,在报头中还有一个变换。这种转换在随后的微调中被忽略,这是应该的,但对于评估或直接使用预训练的输出向量是关键的。本文中的无监督任务直接或间接利用来自 MLM 头(对于包括【CLS】)的所有记号)的矢量输出,而不是最顶层矢量。*

通常直接使用模型的预训练输出向量的一个任务是[CLS]向量。该向量通过预测输入中的下一个句子来学习整个句子的表示(训练期间模型的所有输入都是句子对,带有指示两个句子是否相邻的标志)。在给定上述 MLM 头中的额外变换的情况下,从 MLM 头而不是最顶层收获该向量来表示句子在性能上产生了差异。

在预训练之后从 MLM 头部,特别是从具有高下一句预测准确度的模型中收获的[CLS]向量可以用于表示单词、短语或句子。这有一些优点

  • 它扩展了模型为无限词汇有效创建表示的能力(注意将基本词汇中不存在的符号表示为特殊的[UNK]标记)
  • 与其他通常不透明的习得句子表示不同,这种表示在某种程度上是可解释的——我们可以通过检查伯特词汇中向量的邻域项(或伯特词汇的簇)来了解[CLS]表示正在捕捉什么。如下所述,学习的模型偏置权重对于加权这样的邻域来说很方便。

图 9a。在给定输入短语“估计肾小球滤过率”和“表皮生长因子受体”的情况下,【CLS】令牌的邻域术语。句子表示的质量反映在这些邻域中,第一个邻域将输入短语反映为度量,第二个邻域将输入短语反映为蛋白质。然而,这两个词在语义上都有EGFR——这是这两个短语共有的首字母缩写词。[CLS]代表是从 MLM 头上收获的。作者创作的图片

图 9b。对于图 9a 中的两个短语,从最顶层收获的[CLS]术语的邻域。邻域的质量是一个典型的例子,说明了当使用这个[CLS]向量时句子表示评估产生差的结果的原因。作者创建的图像

顺便说一句,在创建句子表示时,与 MLM 头部相反,在少数论文和公开可用的实现(参考下文)中,CLS 的输出似乎过早地从最高层收获。这可能是[CLS]向量在此类评估中表现不佳的部分原因(这一说法需要通过用 STS 这样的基准测试来证实)。当使用从头部获得的 CLS 表示时,我们可以原样使用它,而无需归一化来在底层词汇中寻找邻居。然而,如果我们使用它来寻找句子邻居,为了更好的邻居质量,我们需要规范化它

其他应用

关系抽取

如果我们认为关系是短语的三元组 (e1,relation,e2) ,潜在地出现在三元组的任何排列中,则实体 e1 和 e2 的识别可以使用上述的无监督 NER 来完成。关系的识别可以通过选择词汇空间中表征特定关系的术语来完成——一次性步骤。需要依赖分析器来识别句子中的三元组并找到关系边界,特别是当关系出现在前缀(关系 e1 e2) 或后缀形式 (e1 e2 关系)中时。这种方法用于收获同义词,如本文所述。另一个看似合理的用例不一定是提取关系,而是识别句子中的关系类型,以便对句子进行分类。

图 10。 作者创建的无监督同义词采集 图像

模拟 RNN 的隐藏状态行为

[CLS]向量可用于在每个时间步用 BERT 模拟 RNN 的隐藏状态,BERT 只是一个变换器编码器-当使用变换器时,该功能通常需要编码器和解码器(例如在翻译中)。这在具有时间输入流的应用中可能是有用的。这用下面的几个玩具句子的部分和完整版本来说明(图 11a-11d) ,其中【CLS】向量的邻域很大程度上反映了输入中重要实体的语义相关术语。然而,这可能只是粗略的近似,给定基于 RNN 的语言模型的自回归训练赋予其生成能力,而像 BERT 这样的自动编码器模型显然缺乏这种能力。

图 11a。用 CLS 为单个术语和部分句子模拟 RNN 的隐藏状态。作者创造的形象

图 11b。以 CLS 为偏句效仿 RNN 的隐态。作者创建的图像

图 11c 。模仿 RNN 的隐藏状态,用 CLS 写一个完整的句子。作者创作的图片

图 11d。用 CLS 模仿 RNN 的隐藏状态来完成一个句子。注意在上面的所有句子中,[CLS]的表示捕获了句子中关键术语的关键实体类型以及语义相近的实体类型。作者创建的图像

填空应用程序(用于实体猜测)

这是简单的直接使用 MLM 头,如上面的许多例子所示。尽管该模型在预测任何被屏蔽位置的实体类型方面表现得相当好,但是根据实体实例的事实正确性进行预测的准确性是不可靠的,不管在许多实例中,预测可能落在正确实例的范围内。比如上例 “阿立哌唑用于治疗” ,邻居反映的疾病很大程度上是精神障碍。这对于收集候选实例可能具有潜在价值,这些候选实例随后可被下游模型用来识别确切的实例。

可能有价值的其他模型属性

利用 MLM 头部的学习偏差值

屏蔽位置预测期间的输出分数是输出向量和词汇向量加上特定于每个词汇单词的偏差值的点积,偏差值是在训练期间学习的。像、逗号的符号这样的术语是句子中许多位置的输出预测的一部分——它们的信息含量很低。这种习得的偏差对于为句子中的某个位置加权预测术语可能是有价值的——就像词汇术语的 TF-IDF 一样。

图 12。直方图偏差值按数值的逆序排序。具有最高偏移值的标记是像逗号、the 和[UNK]标记这样的标记。具有负偏移值的令牌是[CLS]、[掩码]和[分离]。具有较大偏差值的标记对应于可能在句子中的许多位置频繁出现的标记——大致相当于停用词。作者创建的图像

输出向量角度以及词汇向量的大小是确定某个位置的模型预测的主要因素,而习得的偏差起次要作用(损失是使用非标准化向量计算的,其中大小对分数下降有影响,如果向量标准化,则不会有影响)。

图 13。MLM 头部模型预测得分的计算。关键字“ val ”是输出向量和词汇向量的点积。这只是“n1”、“n2”和“cos”键的乘积,其中 n1 和 n2 是矢量幅度。学习到的偏差值被加到点积上以产生最终得分。对最终得分起关键作用的是两个向量之间的角度和向量幅度,偏差值的作用最小。作者创建的图像

表示对之间相对重要性的不对称

代替对位于词汇表检索词的邻域分布尾部的检索词进行聚类,可以创建一个有向图,该图的节点是词汇表检索词。由于分布尾部的不同长度,该图将是有向的。像细胞这样的名词,尾部可能有白细胞,但白细胞尾部可能没有细胞。然而,像单元格这样的术语将双向链接到单元格。这种有向知识图的节点既可以用符号访问,也可以用嵌入访问,对于某些应用程序来说,这可能会很方便。

有向知识图不仅可以用词汇向量术语来构建,还可以使用[CLS]表征来包括来自感兴趣领域的短语和句子。这种图的一个优点是所有嵌入都位于相同的 n 维空间中,这为潜在的有意义/有用的矢量算法开辟了范围,尽管迄今为止这种算法还没有被证明在实际意义上是有用的。

句子中相邻标记的输出向量的相似度

在预测得分中捕获的句子中每个位置的输出向量与句子中所有其他标记的相似性可能在应用中被利用。

图 14。相对于输出向量的每个位置处的输入记号的基于预测分数的排序。在应用程序中,可能会利用一致的非统一评分。作者创建的图像****

限于总体实体层面理解的世界模型

该模型能够在实体类型粒度级别预测术语,而不是精确的实体实例(尽管候选预测有时接近实体实例家族)表明可以从纯文本序列中无监督地收集仅限于总体实体级别理解的“原始世界模型”。这可能对下游模型有一些用处,特别是当预测接近实体实例时(之前检查的例子 阿立哌唑用于治疗 …)。下图举例说明了模型执行此操作的能力。

图 15。这些例子表明,原始世界模型可以在实体类型级别的粒度上仅从文本序列中学习。链接实体对的片段可以被仔细选择以收获候选关系。作者创作的图片****

最后的想法

上述所有应用都利用了学习向量的相似性度量。具体地,相似性度量被应用于学习的分布式表示,以及那些分布式表示的学习的转换——这两种学习都是自我监督的。虽然对这些表示和转换中包含的语言的任何理解都仅限于从标记序列中收集的内容,但这种有限的理解仍然被证明有助于在没有监督的情况下解决各种 NLP 任务。

用于聚类和检查模型预测的代码是 此处可用

附加注释

  • PyTorch 模型转储(1)说明模型 MLM 头部和内部学习的参数(2)主要学习的转换和(3)学习的词汇向量(在底部以黄色突出显示)。获取无监督任务求解的隐藏状态的正确位置是在最后一次变换(在顶部以黄色突出显示)之后的 MLM 头部内部,而不是最顶层输出。

图十六。 PyTorch BERT 模型转储。**作者创建的图像**

  • Huggingface 实现中的代码补丁在头中转换后从 MLM 头返回隐藏状态。

****图 17。修补变压器代码,从 MLMHead 返回最终隐藏状态。图片来自变压器代码。作者创造的形象

图 18。 预训练的 Google Tensorflow 实现中的代码显示了在 MLM 头部中使用“cls.predictions”完成的最后一次转换(参见图 15)。**作者创作的图片**

图 19。 来自 BERT 的 Github 库的代码存根。预训练的 Google Tensorflow 实现中的代码显示了总损失,该总损失是掩蔽 MLM 损失和下一句损失的总和。**作者创建的图像**

  • 词汇向量聚类。 (1)对于词汇表中的每个术语,创建该术语与词汇表中所有其他术语的余弦分布直方图。从直方图尾部创建一个带阈值截断的聚类(例如个位数或十几个点)。(2)对词汇表中还没有在步骤 1 中挑选所有术语重复上述步骤。与固定余弦距离截止相反,直方图阈值截止产生高质量的聚类,因为直方图尾部在各项之间的长度不同。一些尾部很短(余弦距离> .5) 而一些尾部一直延伸到. 1。**

参考

  1. 无人监管的 NER
  2. 同义词采集
  3. 检查伯特的原始嵌入
  4. 原始伯特纸
  5. 最大化 BERT 模型性能

其中[CLS]向量似乎过早地从最上面的模型输出层(与 MLM 头部相反)获取句子表示的模型

熊猫过滤瑞士军刀

原文:https://towardsdatascience.com/swiss-army-knife-of-pandas-filtering-24866166ca97?source=collection_archive---------12-----------------------

作者图片

高效、可读、灵活的熊猫过滤方式

熊猫evalquery是熊猫 API 公开的一些最强大、鲜为人知、直观的函数。它允许您以一种可读和直观的方式查询数据框,不同于屏蔽和锁定数据的传统方式。产生的代码是高效的、可读的和灵活的。

过滤数据帧在任何数据管道中都是一个重要的过程,在 pandas 中,它通常是一个两步过程。创建掩膜以选择行,然后使用该掩膜设置数据框的子集。

让我们加载虹膜数据集,

>> import pandas as pd
>> df = pd.read_csv("./data/iris.csv")>> df.columns
Index(['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species'], dtype='object')>> df.shape
(150, 5)

简单的例子

比方说,你想看的行是物种 Setosa 和萼片长度> 5。这种多列/条件过滤在现实世界的 EDA 和数据管道中比你想象的更常见。它通常可以写成,

无查询,

**df**.loc[(**df**.sepal_length > 5) & (**df**.species == "Iris-setosa"), :]

上面代码的问题是,df重复了三次,并且有一对方括号和圆括号。这可以使用查询很容易地重写。

同查询,

df.query("sepal_length > 5 and species == 'Iris-setosa'")

熊猫查询为数据帧过滤提供了一个易读、直观的界面,看起来更舒服,写起来也更快。

使用熊猫查询的提示

既然我们已经看到了如何使用 query,我们将看看释放queryeval.的能力的实用技巧

pd.evalpd.querydf.evaldf.query在后台使用pd.evalpd.eval是解析字符串表达式、替换变量并识别查询中的 dataframe 列的函数。

过滤 NaN 的

使用 NaN 进行过滤主要是通过使用pd.isna完成的,然后用它来屏蔽数据帧。

无查询,

# Set the top 5 rows sepal length as
df.iloc[:5, *0*] = *None*# Filtering rows that are null **df**.loc[~pd.isna(**df**.sepal_length), :]# Filtering rows that are not null
**df**.loc[pd.isna(**df**.sepal_length), :]

通过查询,

# Filtering rows that are null
df.query("sepal_length == sepal_length")# Filtering rows that are not null
df.query("sepal_length != sepal_length")

这是可行的,因为将 NaN 与其自身匹配会返回 false。

使用@ 的运行时动态替换

只要掩码中的比较值是动态的,就可以使用@将该值动态插入到比较字符串中。

length_thresh = 5
species = 'Iris-setosa'

df.query("sepal_length >= **@length_thresh** and species == **@species**")

length_threshspecies值是动态解析的。

如果列名之间包含空格,可以使用反勾号对其进行转义,

df.query("**`Sepal Length`** >= @length_thresh and species == @species")

F 弦

使用 f 字符串可以增加查询语句的灵活性。@让你参数化一个不等式的右边,而 f 字符串让你参数化一个不等式的两边。

ltype = "sepal"
length = 5.0df.query(**f**"{**ltype**}_length >= {**length**}")

通过改变变量ltype,你可以控制sepal_lengthpetal_length是否用于过滤。

您还可以创建一个复杂的查询子串,然后将它们组合起来,使其可读,而不是一个复杂的过滤组合。

# Define setosa filter
species, length, ltype = "setosa", 3.0, "sepal"
setosa_mask = **f**"species == 'Iris_{**species**}' and {**ltype**}_length >={**length**}"# Define virginica filter
species, width, wtype = "virginica", 3.0, "petal"
virginica_mask = **f**"species == 'Iris_{**species**}' and {**wtype**}_width >={**width**}"# combine filter
>> df.query(f"{**setosa_mask**} or {**virginica_mask**}")
*-- Returns a dataframe of (96, 5)*

在后台

除了expressioninplace参数之外,pandas.DataFrame.query接受**kwargs,后者可以接受你传递给pandas.eval的任何参数。Query 在内部调用 Eval 来执行表达式。

pandas.eval类似于 python 的eval,它执行字符串中的 python 代码。

assert **eval**("2 + 3 * len('hello')") == 17

看看这个例子,很明显可以在其中执行任何 python 语句。

不正确的评价是邪恶的!

话虽如此,pandas.eval并没有听起来那么危险。不像 python 的eval pandas.eval不能执行任意函数。

>> **eval**("print('danger!')")
danger>> pd.eval("print('me')")
ValueError: "print" is not a supported function

很明显,pandas.eval类似于 python 的eval,但只针对函数和操作数的有限子集。

争论

还有其他eval的参数可以用于更多的控制。

Parser:eval 函数接受一个名为 Parser 的输入,它可以是pythonpandas。根据解析器的不同,表达式的解析略有不同。

引擎:负责执行表达式的引擎。默认情况下,它被设置为numexpr,比另一个选项python更有效、更快

局部和全局字典:有时在表达式中传递没有在当前作用域中定义的变量是很有用的。

df.query("setosa_length > thresh", local_dict={'thresh': 5.0})

就因为你能,你就不应该!

Pandas eval 还可以执行语句并将它们分配给数据帧。例如,你可以这样做,

df.eval("**length_ratio** = sepal_length + petal_length", inplace=True)

上面的语句将在 dataframe 中创建一个列length_ratio。这与我们为什么要使用query的说法正好相反。与提高可读性的查询表达式不同,这种用法不明确,会影响可读性。

参考

  1. 查询https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html
  2. Eval
    https://pandas . pydata . org/docs/reference/API/pandas . Eval . html # pandas . Eval

作者的 LinkedIn 个人资料

Python 中出现了 Switch-Case 语句

原文:https://towardsdatascience.com/switch-case-statements-are-coming-to-python-d0caf7b2bfd3?source=collection_archive---------0-----------------------

最新版本展示了新的逻辑

作者图片

ython 3.10 开始加入许多迷人的新特性。其中一个特别引起了我的注意——结构模式匹配——或者我们大多数人都知道的 switch/case 语句。

尽管 Switch 语句是大多数语言的共同特征,但 Python 中却没有。

早在 2006 年, PEP 3103 被提出,建议实现 switch-case 语句。然而,在 PyCon 2007 上的投票没有得到对该特性的支持后,Python 开发者放弃了它。

快进到 2020 年,Python 的创造者吉多·范·罗苏姆提交了第一份展示新开关语句的文档,这些语句被命名为结构模式匹配,如 PEP 634 所示。

然而,正如我们将很快看到的那样,我们这里所拥有的远不止一个简单的 switch-case 语句(因此 match -case)。

让我们来看看这个新逻辑是如何工作的。

**> Structural Pattern Matching**
  - Intro
  - Another Example
  - Real Use-Case With JSON

结构模式匹配

模式匹配在match之后取一个值,并允许我们写出几个潜在的情况,每个情况由case定义。当我们发现match - case匹配时,我们将执行各自的代码。

例如:

http_code = "418"**match http_code:
    case "200":**
        print("OK")
        do_something_good()
 **case "404":**
        print("Not Found")
        do_something_bad()
 **case "418":**
        print("I'm a teapot")
        make_coffee()
 **case _:**
        print("Code not found")

这里我们检查多个条件,并根据在http_code中找到的值执行不同的操作。

通过 match-case 语句的逻辑流。

很明显,是的,我们可以使用大量 if-elif-else 语句构建相同的逻辑:

http_code = "418"if http_code == "418":
    print("OK")
    do_something_good()
elif http_code == "404":
    print("Not Found")
    do_something_bad()
elif http_code == "418"
    print("I'm a teapot")
    make_coffee()
else:
    print("Code not found")

然而,通过使用 match-case 语句,我们删除了重复的http_code ==,当测试许多不同的条件时,它看起来更清晰。

另一个例子

我们可以在 PEP 635 中找到一些使用 match-case 语句来提高代码可读性的很好的例子。其中之一就是这个例子,它向我们展示了如何使用 match-case 来检查我们的主题的类型和结构:

match x:
    case host, port:
        mode = "http"
    case host, port, mode:
        pass

在这里,我们希望接收元组格式的连接细节,并将给定值赋给正确的变量。

在这种情况下,如果连接mode没有在元组中定义(例如,只提供了两个值——hostport),我们假设连接模式是“http”

然而,在其他情况下,我们可能期望模式是明确定义的。因此,我们可能会收到类似于(<host>, <port>, "ftp")的元组——在这种情况下,我们不希望将mode设置为“http”

现在,如果我们想使用 if-else 语句编写同样的逻辑,我们会得到这样的结果:

if isinstance(x, tuple) and len(x) == 2:
    host, port = x
    mode = "http"
elif isinstance(x, tuple) and len(x) == 3:
    host, port, mode = x

哪个选项更受欢迎可能会有所不同,但对我来说,匹配用例实现看起来要干净得多。

JSON 的真实用例

另一个有趣的用例是基于字典对象的结构不同地解析它们的能力。一个很好的测试用例是解析 SQuAD 2 数据集。

SQuAD 2 数据集是一组非常受欢迎的问答对,用于训练机器学习模型进行问答。我们可以通过以下方式下载数据:

如果我们看一下班的结构,显然有几个层次,这是我们在解析时需要考虑的:

班 2 训练集的 JSON 格式。

我们的问题是,并非所有的样本都使用相同的字典格式。

如果我们查看最后几个样本,我们会看到qas列表包含了answersplausible_answers——而之前的样本只包含了answers:

SQuAD 2 训练集 JSON 中的最后一个条目显示了不同的字典格式(由整个文件中的几个条目共享)。

让我们尝试应用新的匹配情况语句来构建一个更简洁的替代方案,以取代处理这种情况所需的繁重的 if-else 逻辑。首先,我们加载数据:

我们使用 json.load 加载数据。

小队 JSON 包含多个层。访问squad['data']后,我们需要遍历每个group问题,然后遍历每个paragraph,然后遍历每个qas(问题-答案)——如下所示:

这就是事情变得有趣的地方。使用if-else逻辑,我们得到这样的东西:

不算漂亮,但很管用。现在让我们用一些match-case逻辑来重写这个:

它看起来肯定没那么忙了,是原始版本解析逻辑的一个很酷的替代方案。

以上是对 Python 3.10 中引入的新结构模式匹配的快速浏览!预计将于 2021 年 10 月初全面发布。

就我个人而言,我认为这个新语法看起来真的很好——尽管我现在对它有一半的兴趣。一旦更多的用户开始用 match-case 编码,我相信社区会很快建立共识和最佳实践。

但是现在,它看起来很酷——我很兴奋!

我希望你喜欢这篇文章。如果你有任何问题或建议,请通过推特或在下面的评论中告诉我!如果你对更多类似的内容感兴趣,我也会在 YouTube 上发布。

感谢阅读!

如果您有兴趣阅读 Python 3.10 的其他一些新特性,请查看我的另一篇文章,其中介绍了一些最好的特性:

🤖《变形金刚》NLP 课程 70%的折扣

为您的数据项目环境从 Anaconda 切换到 Miniconda

原文:https://towardsdatascience.com/switch-from-anaconda-to-miniconda-for-your-data-project-environment-8786c9e2dc95?source=collection_archive---------26-----------------------

意见

迷你可以完成任务,甚至比大蛇更好

照片由坦纳·博瑞克Unsplash 拍摄

当我第一次开始我的数据科学家生涯时,我一直被推荐的工具之一是 Anaconda。原始文件中也是这么说的。

为什么 Anaconda docs 说你应该选择它—作者提供的 docs 截图

有一段时间,我也觉得 Anaconda 很酷。我的意思是,看看 Anaconda Navigator 的第一页,一旦你打开这个工具,你就会看到它。

Anaconda Navigator —图片来自官方文件

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

在我第一次担任数据科学家期间,当我第一次看到那个登录页面时,我感觉就像一个孩子想象一个真正的科学家在他复杂而可怕的工具面前工作。

那时我需要的是一副眼镜来完成这一套。

我当时也同意为什么 Anaconda 如此推荐给数据科学家。所有的工具,包括额外的包、代码编辑器和 viz 工具,都已经提供了。

一两年后……

在处理了几十个分析用例之后,每个用例都有其独特的挑战和需求,我对 Anaconda 越来越厌倦了。

总之,它成了我电脑上一个臃肿无用的应用程序。

  1. 数以千计的包是总存储和内存消耗者。更糟的是,毫无用处。所有那些预装的软件包真的降低了我电脑的性能。占用的存储空间只有几 GB,这可能会产生很大的差异,尤其是在 Macbook Pro 128GB 的情况下。即使有了conda clean --all,它仍然占据了相当大的空间。我没有使用 Anaconda 附带的很多包,比如pomegranateproj4pyopengl等等。我不知道它们都是干什么用的。
  2. 管理 Python 包变成了一个非常缓慢的过程。甚至用conda update [some package]更新一个包都感觉拖得太久了。我尝试过只从一个环境中使用(,顺便说一下,并不真正推荐)到不同的虚拟环境,这些虚拟环境具有针对不同用例的特定包(一个用于数据探索,一个用于数值分析和建模,另一个用于图像处理)。两者仍然很慢。
  3. 导航器变得过时了。我可以从开始菜单/应用程序文件夹或通过命令提示符/终端打开我喜欢的代码编辑器应用程序。事实上,通过 Navigator 打开应用程序甚至更慢。通过命令提示符更新和管理软件包也更加方便。创建新的虚拟环境?打开命令提示符/终端,输入conda命令。为什么要为 Anaconda Navigator 中的环境页面费心呢?更有甚者,为什么要为此烦恼呢?
  4. 让我的工作更加困难。一旦我的一些客户端/用户的部署时间表到达,我必须用相同的必需包和配置创建一个虚拟环境,以确保模型可以在他们的生产服务器中平稳运行。出于和我上面列出的完全相同的原因,我绝不会使用 Anaconda(或者可能永远不会)。

那么有什么选择呢…

米尼康达!

基本上就是 conda 包管理系统+ Python +它的基础包而已。

就是这样。

  • 没有多余的(没用!)工具和装置。
  • 需要一些特定用例/项目的包吗?您仍然可以创建虚拟环境,并在其中安装您需要的软件包。
  • 需要安装一些代码编辑器吗?直接从官网下载就可以了。由开发人员直接管理,与通过 Anaconda Navigator 安装的一样好(甚至更好)。

有了 Miniconda,我真的很想做精益数据科学和分析项目。

结论

我并不是说 Anaconda 是一个过时的工具,任何数据科学家/分析师都不应该使用它。它仍然有潜力。甚至还有它的企业版。我认为第一次接触数据科学家/分析师可以从使用 Anaconda 开始他们的职业生涯/培训中受益。例如,了解什么是最适合您的数据项目的虚拟环境。他们甚至可能对那 1500 个额外的包裹有些用处。谁知道呢。

我是说,如果你已经牢牢掌握了你想用 Python 构建或使用的东西(例如,你想成为时间序列专家、深度学习工程师或数据驱动的营销专家),Miniconda 是一个高效且值得推荐使用的工具。

如何用 Python 编写 Switch 语句

原文:https://towardsdatascience.com/switch-statements-python-e99ea364fde5?source=collection_archive---------10-----------------------

编程;编排

了解如何使用模式匹配或字典在 Python 中编写 switch 语句

斯蒂夫·约翰森Unsplash 上拍照

介绍

在编程语言中处理多路分支的典型方法是 if-else 子句。当我们需要对许多场景进行编码时,另一种选择是大多数现代语言都支持的所谓的 switchcase 语句。

然而,对于 Python 版本< 3.10,没有这样的语句能够基于特定变量的值选择指定的动作。相反,我们通常必须编写一个包含多个 if-else 语句的语句,甚至创建一个字典,然后根据特定的变量值对其进行索引。

在今天的简短指南中,我们将演示如何以 if-else 系列或字典的形式编写 switch 或 case 语句。此外,我们将展示 Python 3.10 版本中引入的新的模式匹配特性。

编写 if-else 语句

让我们假设我们有一个名为choice的变量,它接受一些字符串值,然后根据变量值打印一个浮点数。

使用一系列 if-else 语句,如下面的代码片段所示:

if choice == 'optionA':
    print(1.25)
elif choice == 'optionB':
    print(2.25)
elif choice == 'optionC':
    print(1.75)
elif choice == 'optionD':
    print(2.5)
else:
    print(3.25)

在传统的 if-else 语句中,我们在 else 子句中包含默认选项(即,当变量值与任何可用选项都不匹配时应该选择的选项)。

使用字典编写 switch 语句

另一种可能性(如果您使用的是 Python < 3.10)是字典,因为它们可以方便有效地建立索引。例如,我们可以创建一个映射,其中我们的选项对应于字典的键,值对应于期望的结果或动作。

choices = {
    'optionA': 1.25,
    'optionB': 2.25,
    'optionC': 1.75,
    'optionD': 2.5,
}

最后,我们可以通过提供相应的键来挑选所需的选项:

choice = 'optionA'
print(choices[choice])

现在我们需要处理我们的选择没有包含在指定字典中的情况。如果我们试图提供一个不存在的密钥,我们将得到一个KeyError。基本上有两种方法可以处理这种情况。

第一个选项要求在从字典中选择值时使用get()方法,这也允许我们在没有找到键时指定默认值。举个例子,

>>> choice = 'optionE'
>>> print(choices.get(choice, 3.25)
3.25

或者,我们可以使用try语句,这是一种通过捕捉KeyError来处理缺省值的通用方法。

choice = 'optionE'try:
    print(choices[choice])
except KeyError:
    print(3.25)

Python ≥ 3.10 中的模式匹配

Python 3.10 引入了新的结构模式匹配 ( PEP 634 ):

结构模式匹配以模式的匹配语句case 语句的形式添加了相关动作。模式由序列、映射、原始数据类型以及类实例组成。模式匹配使程序能够从复杂的数据类型中提取信息,对数据结构进行分支,并基于不同形式的数据应用特定的操作。

来源— Python 文档

因此,我们现在可以将代码简化如下:

choice:
    case 'optionA':
        print(1.25)
    case 'optionB':
        print(2.25)
    case 'optionC':
        print(1.75)
    case 'optionD':
        print(2.5)
    case _:
        print(3.25)

注意,我们甚至可以使用如下所示的|(‘或’)操作符将几个选择组合在一个案例或模式中:

case 'optionA' | 'optionB':
    print(1.25)

最后的想法

在今天的文章中,我们讨论了在 Python 中实现 switch 语句的几种替代方法,因为在 3.10 版本之前,Python 中没有像许多其他编程语言那样的内置结构。

因此,您可以编写传统的 if-else 语句,甚至初始化一个字典,其中的键对应于 if/else if 语句中使用的条件,当特定条件(键)成立时,值对应于所需的值。

此外,我们展示了如何使用 Python 3.10 中最近引入的新模式匹配 switch 语句。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。

https://gmyrianthous.medium.com/membership

你可能也会喜欢

转向数据行业

原文:https://towardsdatascience.com/switching-to-a-career-in-data-d99d340f6589?source=collection_archive---------29-----------------------

如何有效地推销自己是一名(新)数据分析师

杰斯·贝利在 Unsplash 上的照片

转换职业道路并获得数据分析或数据科学领域的第一份工作可能具有挑战性。我去过那里。招聘经理通常希望有经验,即使是对于的入门级工作,所以能够讲述你的经验——无论是在不同的领域,个人项目,还是在课程中——如何让你胜任这个职位是很重要的。

如果你想在寻找数据领域的第一份工作时更有策略,请继续阅读一些提示和技巧。

求职

在申请过程开始之前,你显然必须找到招聘信息。

接触你的人际网络

我把这一部分放在第一位,因为我有 4 份实习和工作,其中 2 份是通过网络获得的。向你的个人和职业关系网询问机会是非常有益的,因为有一个推荐人——或者更好的是,了解一份还没有发布的工作——可以让工作更容易找到。

2019 年,美国消费者新闻与商业频道表示

“……一些估计表明,多达 70%的工作没有在公开的求职网站上发布,而且长期以来的研究表明,从一半到 80%以上的工作都是通过社交网络获得的。”【2】

所以,向朋友、家人、教授和同事伸出援手吧!有时候,除非你问,否则你永远不知道人们有什么样的关系。

为自己创造一个“品牌”

当我过渡到数据分析时,这种策略最适合我。我不会详述我的个人经历,因为我写了一篇不同的文章:

你可以通过多种媒介为自己创建一个品牌——创建一个 youtube 频道,创建一个作品集网站,在你的 GitHub 个人资料中努力展示技术产品,等等。所有这些都可以向雇主展示你的技能和兴趣,如果你在数据领域没有太多的工作经验,这些都会特别有帮助。

如果你幸运的话,工作可能会找上你。

利用特定领域的求职网站

点击查看 Thinkful 推荐的数据分析师职位网站列表。该列表中的许多网站主要包含技术或数据相关的工作。我个人最喜欢在中小型公司寻找科技行业职位的网站是 builtin.com 的

照片由格伦·卡斯滕斯-彼得斯Unsplash 拍摄

利用你的其他专长

对我来说,这看起来像是在制造业公司寻找数据分析师的工作,因为我的学位是工业工程。对于一个朋友来说,这看起来像是申请生物科学领域的数据科学工作,因为他以前是一名科学家。

当你能与专业领域的专家交流时,这是一个更有吸引力的应用。例如,在一个营销数据分析师职位的面试中,你可以说“虽然我以前没有过分析职位,但我在营销策略方面的经验会让我对你的团队处理的数据有深刻的理解。”

简历/申请

好的,让我们假设你已经找到了一个可以申请的职位。你应该如何帮助你的应用脱颖而出?

包括您的项目

根据事实,

“在简历中列出与你最相关的项目很重要,这样可以传达你的经验和技能,同时也能突出你如何运用自己的能力找到解决方案的实际例子。”【1】

如果你在过去的工作中完成了这些项目,你可以把它们放在简历的工作经历部分。如果项目是个人项目,或者是你在新兵训练营或继续教育中完成的项目,我建议为项目创建一个完整的简历部分。

如果你从一个非常不相关的领域转行,那么把项目部分放在你的工作经历之前可能是有意义的,因为它与你申请的工作最相关。我在 Thinkful 的数据科学训练营学到的一个技巧是将这个部分命名为“数据分析项目”或“数据科学项目”,而不仅仅是项目。(得溜进去那些关键词。)

乔·费罗Unsplash 上的照片

写一封求职信

我想我还没有遇到喜欢写求职信的人。

不管怎样,如果你想转行到数据领域,附上一封求职信是很有说服力的。这是我从 Thinkful 收到的另一条建议:求职信是一个讲述你简历以外的故事的机会。这让你有机会解释简历中的空白,并加入额外的信息,说明你为什么非常适合这个职位(即使你以前的工作经验与此没有直接关系)。)【2】

如果你正在寻找数据分析或数据科学方面的第一份工作,我祝你好运!如果你已经在这个领域找到了一份工作,我鼓励你给那些想转行的人留下你的建议。

人工智能可解释性的符号与次符号人工智能范例

原文:https://towardsdatascience.com/symbolic-vs-subsymbolic-ai-paradigms-for-ai-explainability-6e3982c6948a?source=collection_archive---------10-----------------------

第一部分 |可解释的人工智能—第二部分

自 80 年代以来,亚符号人工智能范式已席卷全球。但是,可解释人工智能的兴起可能会使符号人工智能从坟墓中复活,因为它具有不可替代的特性

图一。附身摄影Unsplash 上拍照

人工智能无疑是 21 世纪最具革命性的技术之一。人工智能专注于设计和制造具有推理、认知、学习、感知和交流等认知能力的机器。为了设计具有这些能力的机器,研究人员通常采用两种主要方法:(I)符号人工智能方法和(ii)统计人工智能(子符号)方法。

符号人工智能

S 符号 AI 是人工智能的一个子领域,专注于问题的高级符号(人类可读)表示、逻辑搜索。在 50 年代和 80 年代之间,符号人工智能是占主导地位的人工智能范式。例如,如果你问自己,在头脑中有了象征性的人工智能范例,“苹果是什么?,答案将是苹果是一种水果有红色、黄色或绿色有圆形这些描述是象征性的,因为我们用符号(颜色、形状、种类)来描述苹果。

符号人工智能是面向推理的领域,它依赖于经典逻辑(通常是单调的),并假设逻辑使机器变得智能。关于实现符号人工智能,一个最古老的,但仍然是最流行的,逻辑编程语言是 Prolog 派上用场。Prolog 植根于一阶逻辑,一种形式逻辑,与其他许多编程语言不同。

图二。象征性的苹果例子(作者图)

Prolog 是一种声明性语言,程序逻辑用关系来表达,用事实和规则来表示。通过对这些关系运行查询来启动计算。因此,Prolog 可以用来表达图 2 所示的关系。这些关系可以用来定义一个苹果。

亚符号(连接主义者)人工智能

I 模型通常用于进行预测,这些模型可以显式表示(如在符号人工智能范例中)或隐式表示。隐式表示来自经验学习,没有规则和属性的符号表示。子符号范式的主要假设是,用有限的经验提取好模型的能力使模型成功。在这里,我们没有明确定义人类可读的关系,而是设计更难解释的数学方程来解决问题。

图 3。象征性的苹果例子(作者图)

神经网络,集成模型,回归模型,决策树,支持向量机是一些最受欢迎的子符号人工智能模型,你可以很容易地遇到,特别是如果你正在开发 ML 模型。

从 80 年代开始,子符号人工智能范式由于其高精度性能和灵活性而取代了符号人工智能作为人工智能主导子领域的地位。

比较符号人工智能和子符号人工智能

L et 对符号 AI 和次符号 AI 做一个简单的比较,了解这两大范式的异同。

轻松学习

亚符号人工智能模型(如神经网络)可以直接从数据中学习,以达到特定的目标。像神经网络这样的模型甚至不需要预处理输入数据,因为它们能够自动提取特征。

易于并行化和扩展

由于亚符号人工智能模型从数据中学习,它们可以很容易地重新调整用途,并针对不同的问题进行微调。它们可以扩展到更多的人群。另一方面,符号化的人工智能模型需要在新环境下进行复杂的重塑。

没有推理能力

虽然亚符号人工智能模型擅长学习,但在推理方面往往不太令人满意。

数据饥渴模型

子符号模型——尤其是神经网络——需要大量数据来实现合理的性能。

这里是符号人工智能和子符号人工智能范例的概览比较表,如表 1 所示:

表 1。符号和次符号人工智能范例的特性(见:来源)

对手或同行

虽然亚符号人工智能是因为符号人工智能范式的缺点而开发的,但它们可以用作补充范式。虽然符号人工智能更擅长逻辑推理,但子符号人工智能在特征提取方面优于符号人工智能。

图 4。将符号人工智能与子符号人工智能结合起来(作者提供图片)

从可解释性的角度评价人工智能范式

如上所述,符号人工智能范式提供了具有令人满意的推理能力的易于解释的模型。通过使用符号化的人工智能模型,我们可以很容易地追溯特定结果的推理过程。另一方面,即使在特定领域中表达整个关系结构也是很难完成的。因此,如果不付出极大的努力,符号化的人工智能模型无法捕捉所有的可能性。

另一方面,亚符号人工智能范式提供了非常成功的模型。与它们的精度性能相比,这些模型可以用相对较少的努力来设计和训练。然而,次符号模型的最大缺点之一是决策过程的可解释性。特别是在推理是结果不可或缺的属性的敏感领域(例如,法院裁决、军事行动、贷款申请),我们不能依赖高性能但不透明的模型。

用于可解释模型的可解释人工智能(XAI)和神经符号计算(NSC)

一个可解释的模型是一个具有内在逻辑的模型,它可以用人类语言清楚地描述。因此,虽然符号人工智能模型可以通过设计来解释,但次符号人工智能模型通常不能通过设计来解释。有两个领域涉及创建具有推理能力的高性能人工智能模型,这通常需要结合符号和子符号范例的组件。虽然 XAI 的目标是通过开发本质上更容易为(人类)用户理解的模型来确保模型的可解释性,但 NSC 专注于寻找将子符号学习算法与符号推理技术相结合的方法。

最后的想法

在这篇文章中,我们讨论了两个主要的人工智能范例:

  • 符号人工智能(Symbolic AI)→可解释性高但准确性低的范例
  • 亚符号人工智能 →可解释性低但准确性高的范例

在下一篇文章中,我们将更详细地介绍可解释的人工智能和神经符号计算,以了解它们在开发方面的重点:

  • 具有高解释能力高精度性能的机型。

订阅邮件列表获取更多内容

如果你想获得我在 Google Colab 上的其他教程文章的代码,并尽早获得我的最新内容,考虑订阅邮件列表 :✉️

现在就订阅

如果你对深度学习感兴趣,也可以看看我的人工智能内容指南:

https://blog.orhangaziyalcin.com/a-guide-to-my-content-on-artificial-intelligence-c70c9b4a3b17

如果你正在阅读这篇文章,我确信我们有着相似的兴趣,并且正在/将要从事相似的行业。那么我们就通过Linkedin来连线吧!请不要犹豫发送联系请求! 奥尔罕·g·雅肯—领英

参考文献

Sovrano,F. (2021),现代人工智能对可解释性的需求,博洛尼亚大学信息学院

明斯基(1991 年)。逻辑与类比,符号与联系,整洁与邋遢。艾杂志12 (2),34–51。【https://web.media.mit.edu/~minsky/papers/SymbolicVs. Connectionist.html

定理,T. (2018)。人工智能—维基百科https://en . Wikipedia . org/wiki/Artificial _ intelligence # approach

Souici-Meslati,l .,& Sellami,M. (2004 年)。一种混合的阿拉伯文字量识别方法。阿拉伯科学与工程杂志29 (2 B),177–194。https://www . research gate . net/publication/228848818 _ A _ hybrid _ approach _ for _ Arabic _ literal _ amounts _ recognition

SymPy:Python 中的符号计算

原文:https://towardsdatascience.com/sympy-symbolic-computation-in-python-f05f1413adb8?source=collection_archive---------0-----------------------

用 Python 象征性地解一个方程和微积分

作者图片

动机

你曾经希望用 Python 解一个数学方程吗?如果我们可以用一行代码解决如下的代数方程,那不是很好吗

[-1/2, 0]

…或者只是使用数学符号而不是枯燥的 Python 代码?

作者图片

这就是 SymPy 派上用场的时候了。

什么是 SymPy?

SymPy 是一个 Python 库,允许你用符号计算数学对象。

要安装 SymPy,请键入:

pip install sympy

现在让我们回顾一下 SymPy 能做的一些令人惊奇的事情!

从导入 SymPy 提供的所有方法开始

from sympy import *

基本操作

通常,当计算平方根时,我们得到一个小数:

作者图片

但是使用 SymPy,我们可以得到平方根的简化版本:

作者图片

这是因为 SymPy 试图精确地而不是近似地表示数学对象。

因此,当使用 SymPy 将两个数相除时,我们将得到一个分数而不是小数。

作者图片

标志

SymPy 的真正力量是它处理符号的能力。要创建符号,使用方法symbols():

作者图片

酷!我们可以用 x 和 y 创建一个表达式,如果我们给这个表达式加上一个数会发生什么?

作者图片

啊哈!+ 2 加到表达式中,表达式保持不求值。

为什么使用符号会有用?因为我们现在可以使用我们在学校学到的各种数学技巧,如扩展、分解和简化方程,以使我们的生活更容易。

方程式

扩展、分解和简化

我们知道左边表达式的展开等于右边的表达式。

作者图片

用 SymPy 能做到这一点吗?是啊!SymPy 允许我们使用expand扩展一个等式:

作者图片

酷!我们也可以通过使用factor来分解我们的表达:

作者图片

我们可以用 SymPy 做的另一件很酷的事情是使用simplify简化一个方程:

作者图片

很好,不是吗?

解方程

在处理数学符号时,我们最常见的问题之一是解方程。幸运的是,这也可以通过 SymPy 来实现。

要解方程,使用solve:

作者图片

代替

如果我们用 2 代替下面的等式,我们会得到什么?

作者图片

我们可以使用eq.subs(x, 2)来解决这个问题:

作者图片

我们也可以用另一个变量代替 x,得到如下表达式:

作者图片

不错!

三角法的

还记得我们高中学的那些好玩的三角恒等式吗?

作者图片

如果我们可以使用 SymPy 来为我们解决这个问题,而不是查找这些身份,这不是很好吗?

要使用三角恒等式简化表达式,请使用trigsimp()

作者图片

导数、积分和极限

有了 SymPy,还可以做微积分!下面表达式的导数是什么?

作者图片

如果你想不出来,不要担心。我们可以用 SymPy 来解决这个问题。

作者图片

现在让我们通过对导数进行积分,回到原来的表达式。

作者图片

当 x 接近无穷大时,我们也可以取极限。

作者图片

作者图片

或者 2:

作者图片

特殊函数

SymPy 还提供了特殊的功能:

  • 求一个数的阶乘

作者图片

  • 用另一种说法改写这个表达式

作者图片

印花乳胶

如果您喜欢这个输出,并且想要获得表达式的 LaTex 形式,那么使用latex:

作者图片

你可以把这个 LaTex 表格粘贴到你笔记本的 markdown 上,得到一个漂亮的数学表达式,如下图所示!

作者图片

结论

恭喜你!您刚刚学习了如何使用 SymPy 在 Python 中用符号计算数学对象。下次你解数学的时候,试着用 SymPy 让你的生活更轻松。

SymPy 还提供了许多其他有用的方法,我无法在这里一一介绍。我鼓励你查看这份文档以获得更多灵感。

在 Github repo 中,您可以随意使用本文的代码:

https://github.com/khuyentran1401/Data-science/blob/master/data_science_tools/sympy_example.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedInTwitter 上和我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

了解熊猫时写 PySpark 的语法陷阱

原文:https://towardsdatascience.com/syntax-gotchas-writing-pyspark-when-knowing-pandas-57ace4ae769b?source=collection_archive---------31-----------------------

米卡·鲍梅斯特在 Unsplash 上的照片

如果您对 Python Pandas 的数据分析有一些基础知识,并且对 PySpark 很好奇,不知道从哪里开始,请跟随我。

Python 熊猫鼓励我们抛弃 excel 表格,转而从编码者的角度来看待数据。数据集变得越来越大,从数据库变成了数据文件,变成了数据湖。Apache 的一些聪明人用基于 Scala 的框架 Spark 祝福我们在合理的时间内处理更大的数量。由于 Python 是当今数据科学的主流语言,很快就有了一个 Python API,叫做 PySpark

有一段时间,我试图用大数据世界中每个人都称赞的非 pythonic 语法征服这个 Spark 接口。我尝试了几次,现在仍在进行中。然而,在这篇文章中,我想告诉你,谁也开始学习 PySpark,如何复制相同的分析,否则你会做熊猫。

我们要看的数据分析示例可以在 Wes McKinney 的书“Python for Data Analysis”中找到。在该分析中,目标是从 MovieLens 1M 数据集中找出排名最高的电影,该数据由明尼苏达大学的 GroupLens 研究项目获取和维护。

作为一个编码框架,我使用了 Kaggle ,因为它带来了笔记本电脑的便利,安装了基本的数据科学模块,只需点击两下就可以使用。

完整的分析和 Pyspark 代码你也可以在 这本 Kaggle 笔记本这本 中找到熊猫代码。这里我们不会重复相同的分析,而是集中在处理 Pandas 和 Pyspark 数据帧时的语法差异上。我将始终首先显示熊猫代码,然后显示 PySpark 等价物。

此分析所需的基本功能是:

  • 从 csv 格式加载数据
  • 组合不同表中的数据集
  • 提取信息

加载数据

Pandas 有不同的读取功能,这使得根据存储数据的文件类型导入数据变得容易。

# Pandas
pd.read_table(path_to_file, sep='::', header=None, names=column_names, engine='python')

使用 PySpark,我们首先需要创建一个 Spark 上下文作为 Sparks 功能的入口点。这并不是说当您将它复制粘贴到代码中时,缩进可能不匹配。

# PySpark
from pyspark.sql import SparkSessionspark = SparkSession.Builder().getOrCreate() *#--> Spark Context**spark.read                        #--> what do you want to do*
 *.format("csv")                #--> which format is the file*
 *.option("delimiter", "::")    #--> specify delimiter that's used* 
 *.option("inferSchema", "true")#--> default value type is string*
 *.load(path_to_file)            #--> file path*

组合数据集

Pandas 中合并数据集的默认函数是https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html****(),,它合并一列或多列上的数据集。就连 Pandas join() 函数也使用 merge 与一个索引列相结合。评级、用户和电影都在这个代码片段中,它们共享各自的列,所以我们可以调用合并函数。在名称不匹配的情况下,我们需要使用 join()来代替。

# Pandas
data = pd.merge(pd.merge(ratings, users), movies)

在 PySpark 中没有 merge 函数,这里默认的是对选择的列使用 join() 。否则看起来相当相似。

# PySpark
data = ratings.join(users, ["user_id"]).join(movies, ["movie_id"])

提取信息

现在我们已经有了可以处理的数据形式,我们可以看看如何真正提取内容。

显示行条目

Pandas 数据帧源自 numpy 数组,因此可以使用方形括号来访问元素。如果我们想查看表格的前 5 个元素,我们可以这样做:

# Pandas
users[:5]

在 Spark 中,数据帧是对象,因此我们需要使用函数。在显示前 5 行的情况下,我们可以使用 show() ,它来自 Spark dataframes 使用的底层 SQL 语法。函数 show 只是表示数据集的一种方式,如果你想从选择的条目中创建一个新的 dataframe,你需要使用 take()

# PySpark
users.show(5) # --> print result users.take(5) # --> list of Row() objects

过滤

在熊猫身上,我们可以用不同的方式过滤。我们可以使用的一个函数是 loc ,这是一个基于标签的过滤器,用于访问行或列。在数据分析示例中,我们希望过滤数据帧中出现在标题列表中的所有行。

# Pandas
mean_ratings = mean_ratings.loc[active_titles]

PySpark 数据帧不支持 loc,因此我们需要使用过滤函数。处理 PySpark 数据帧中的列的一种简单方法是使用 col() 函数。用列名调用这个函数,将从 dataframe 返回相应的列。

# PySpark
from pyspark.sql.functions import col
mean_ratings = mean_ratings.filter(col('title').isin(active_titles))

分组

Pandas 和 PySpark 中的分组看起来非常类似于 groupby() 。Pandas 数据帧有许多为分组对象实现的聚合函数,如中位数、平均值、总和、方差等。对于 Pyspark 数据帧,有必要将其导入,例如从 pyspark.sql.functions 导入,如 mean() 和 standard dev stddev()

# Pandas
ratings_by_title = data.groupby('title')['rating'].std()# PySpark
from pyspark.sql.functions import mean, stddev
coldata_sdf.groupBy('title').agg(stddev(col('rating')).alias('std'))

数据透视表

数据透视表常用于数据分析。熊猫数据框的排列和聚集都在一个函数pivot _ table中。****

# Pandas
mean_ratings = data.pivot_table('rating',
                                index='title',
                                columns='gender',
                                aggfunc='mean')

为了用 Pyspark dataframes 复制相同的结果,我们需要连接分组、透视和聚合函数。

# PySpark
mean_ratings_pivot = data
                       .groupBy('title')
                       .pivot('gender')
                       .agg(mean('rating'))

整理

要对一列中的值进行升序或降序排序,我们可以为 Pandas 数据帧调用 sort_values() 函数。请记住,默认的排序顺序是升序。

# Pandas
top_female_ratings = mean_ratings.sort_values(by='F',
                                              ascending=False)

在 PySpark 中有一个类似的函数叫做 sort() ,但是我们想要排序的列,我们必须作为输入给出。类似地,我们可以使用函数 orderBy() 并得到相同的结果。

# PySpark
top_female_ratings = mean_ratings.sort(mean_ratings.F.desc())

随着时间的推移,Pandas 和 PySpark 的语法将会改变。也许我们运气好,它们会变得更蟒蛇。还有一些模块结合了 provide 和 PySpark 的一个熊猫 API,叫做考拉。如果它的性能可以与 PySpark 竞争,我们可能会在未来看到更多这种情况。

我希望你找到了一些有用的提示,并请让我知道你从学习 Spark,语法和功能的见解!

使用单深度和大气散射模型合成朦胧/多雾图像

原文:https://towardsdatascience.com/synthesize-hazy-foggy-image-using-monodepth-and-atmospheric-scattering-model-9850c721b74e?source=collection_archive---------22-----------------------

思想和理论

当雾是有益的。

最近的深度学习和计算机视觉时代导致了自动驾驶技术的快速发展,其中物体检测发挥了极其重要的作用。提出了 R-CNN 家族(R-CNN,Fast R-CNN,Faster R-CNN,Cascade R-CNN),YOLO 系列(YOLOv1-v4)等各种物体检测器,丰富的驾驶物体检测数据集包括 BDD100K,WAYMO 等。也是可用的。然而,理论研究与现实部署之间仍存在巨大差距。目标检测器的性能在实践中通常会下降,尽管在离线训练期间被训练得很好,具有几乎 99.99%的准确度。那次意外事件最流行的原因之一是因为域名转移的问题。

当测试数据的分布与训练数据的分布不同时,就会发生域转移。例如,自主车辆的物体检测器被训练为在良好天气条件下捕获的有利训练数据上工作良好,而部署阶段期间的实际天气可能包括雨或雾。因此,为了带来更好的性能,对象检测器应该对域转移问题更鲁棒。下图显示了在应用基于原始干净数据(红色:地面真实,绿色:检测)训练的预训练 YOLOv4 模型时,模糊输入(左)和无模糊输入(右)之间的性能比较。从图中,我们可以清楚地看到磁畴移动对检测器性能的影响。

模糊输入(左)和无模糊输入(右)之间的性能差异(红色:地面实况,绿色:探测)(图片由作者提供)

一种简单而有效的解决方案是应用独立的环境条件分类器以及对象检测器来识别环境变化,如本文所述:增强高级驾驶员辅助系统的对象检测模块的鲁棒性 ( 阅读全文)。或者已经提出了另一种称为多尺度域自适应 YOLO (MS-DAYOLO) 的统一系统,其与最先进的一阶段对象检测模型 YOLOv4 和用于域不变特征学习的域自适应网络(DAN)相集成。

对于这样的研究,我们需要准备一个多样化的数据集,它可以帮助训练一个强大的对象检测模型来处理域转换问题。在这篇文章中,我将介绍一个强大的工具,使用单深度和大气散射模型从干净的图像中合成朦胧/有雾的图像数据。该项目的更多细节可以在这里找到

大气散射模型

如上图所示,红框(等式(1))中显示了普遍用于描述模糊图像的大气散射模型,其中 x 是像素位置, I(x) 是我们旨在创建的模糊图像, J(x) 是我们已经拥有的干净图像, A 是通常设置为 1 的大气光, t(x) 是场景的媒介透射。基于等式(1),为了获得 I(x) ,我们需要知道变速器 t(x) 。当大气光线均匀时, t(x) 可以表示为等式(2),其中 β 表示大气的散射系数,因此,现在需要的是场景的深度图 d(x) 。一种使用单幅图像来估计场景深度图的现代方法是 Monodepth,这将在下一节中提到。

单一深度

单幅图像深度估计(单幅深度纸中的图像[ 来源 ])

使用单一 RGB 图像估计场景深度是计算机视觉中一个具有挑战性且长期存在的问题。最近 Monodepth ( ver1ver2 )就是在这个课题上取得突破的方法,建立了单幅图像深度估计的新基线。由于版本 2 与版本 1 相比有几处改进,我想在本教程中使用 Monodepth2。Monodepth2 的可用源代码可以在这里找到

结果

下面的示例图像选自 WAYMO 数据集。WAYMO 数据集提供了驾驶员 5 个不同视角的驾驶场景图像。下图显示了使用本文介绍的方法合成的朦胧图像的几个结果。在图中,第一行:原始图像,第二行:使用 Monodepth2 估计的深度图,第三行:合成的模糊图像。

第一行:原始图像,第二行:估计的深度图,第三行:合成的模糊图像(图像由作者提供)

我们可以通过配置不同的大气散射系数β值来设置合成的雾霾图像中雾霾的厚度。在以下结果中,当使用β=1.2 时,第 2 行中的图像是具有稀疏薄雾的合成薄雾图像,而第 3 行中的图像是β=2 的合成密集薄雾图像。

第一行:原始图像,第二行:具有稀疏薄雾的合成朦胧图像,第三行:具有密集薄雾的合成朦胧图像(图像由作者提供)

结论

在这篇文章中,我介绍了一种合成模糊/多雾图像数据的方法,该方法可以作为训练的数据扩充步骤来实现,以提高对象检测模型对域偏移问题的鲁棒性。完整的实现可以在这里找到。

欢迎读者访问我的脸书粉丝页,这是关于机器学习的分享:投入机器学习。我在约洛夫 4——5D 评论达克拉斯EFPN 发表的关于物体探测的更值得注意的帖子。

感谢您抽出时间!

我们对算法的痴迷如何打破了计算机视觉

原文:https://towardsdatascience.com/synthetic-computer-vision-c53742b4dee1?source=collection_archive---------26-----------------------

以及合成计算机视觉如何修复它

合成计算机视觉旨在将虚拟世界中的内容翻译回现实世界。(图片由作者提供)

深度学习从整体上彻底改善了机器学习。以数据为中心的革命也将如此。在本帖中,我们将看看主流计算机视觉(CV) 的陷阱,并讨论为什么合成计算机视觉(SCV) 是未来。

🗣️计算机视觉的现状

根据 Crunchbase 的数据,截至今天,在过去的 8 年里,超过 1800 家计算机视觉初创公司获得了价值超过 150 亿美元的投资。据《福布斯》报道,这些公司中有 20 多家目前的市值超过了 1B,还会有更多的公司出现。

为什么这些公司被如此看重?简单地说,他们在教计算机如何看东西。通过这样做,他们正在自动化以前使用人类视觉完成的任务。

这一繁荣是在 2012 年计算机视觉的技术拐点之后,随着神经网络的出现——模仿人脑并使用大量人类标记的数据进行训练的算法。自 2012 年以来,算法一直在稳步改进,并在许多视觉任务中成为人类的对手,例如计数物体、唇读癌症筛查

在接下来的 10 年里,每个人都尽了自己的职责:学术界用更好的算法引领潮流;大公司投资了一大批人,他们勤奋地给这些图像数据集贴上标签。为了社区的利益,其中一些工作甚至是开源的,例如 1400 万图像数据集 ImageNet。

不幸的是,现在随着这些系统被部署到生产中,我们遇到了一个难题:

  1. 我们拥有的标记为的数据是不可靠的。麻省理工学院研究人员对流行的 ML 数据集进行的系统研究发现,ImageNet 的平均错误率错误标记率为 5.93% ,其他数据集的平均错误率为 3.4%。
  2. 很少有人致力于解决数据问题。学术界的智力努力几乎完全集中在算法开发上,忽略了对良好数据的基本需求——吴恩达的一项猜测认为,99%的算法关注与 1%的数据关注的比率为
  3. 计算机视觉算法不能很好地从一个领域推广到另一个领域,一个被训练用来在法国南部检测汽车的算法将很难在多雪的挪威检测到同样的汽车。同样,在特定摄像机上训练的系统可能在另一个摄像机品牌和型号上失败。

♟️寻找灵感

早在 1946 年,艾伦·图灵就建议将国际象棋作为计算机能力的基准,此后这一问题得到了深入研究,并引起了媒体的广泛关注。

一种普遍接受的衡量国际象棋比赛表现的方法是通过 Elo 评级系统,该系统提供了对玩家技能的有效比较。下图显示了世界冠军和国际象棋游戏引擎。在过去的 50 年里,人类的表现一直徘徊在 2800 点左右,然后在 2010 年被计算机压制。

直到最近十年,我们人类已经设计了象棋算法,根据我们可以设计和理解的规则进行游戏。深度学习革命让我们突破了人类的理解,带来了一次飞跃——就像它对计算机视觉的影响一样。

国际象棋引擎和人类 ELO 评级(图片由作者提供)

深度学习国际象棋游戏引擎的进展一样好,但它现在被下一级国际象棋引擎压制了:来自 DeepMind 的 AlphaZero 。更令人印象深刻的是, AlphaZero 没有使用任何人工数据来实现这一性能。它是在没有任何历史象棋游戏知识的情况下建造的,也没有任何寻找最佳走法的人类指导。AlphaZero 是老师也是学生——它通过与自己竞争并在这个过程中学习,教会了自己如何更好地玩游戏。

AlphaZero 赢了当时最好的引擎 Stockfish 8,没有输掉一场比赛,即使 Alpha Zero 给了少一个数量级的时间来计算它的下一步行动。

考虑到 AlphaZero 的显著改进,人们不禁要问: 我们能否将其在国际象棋中的成功转化为计算机视觉?

📰新浪潮:以数据为中心的人工智能

以数据为中心的人工智能的新范式中,目标不是创造更好的算法,而是通过改变数据本身来提高性能。即使我们首先忽略获取和标记图像数据集的障碍,围绕数据质量的问题仍然存在:我们是否一致地覆盖了所有可能的用例?数据是否涵盖了边缘案例?

如果我们要走以数据为中心的计算机视觉之路,就必须控制数据源流程。数据需要平衡,我们需要很好地理解影响计算机视觉模型学习内容的参数。

让我们举一个简单的例子,看看如何控制 3 个这样的参数:摄像机角度、照明和遮挡。你能想象收集一个真实的数据集,其中你必须努力控制只有这 3 个参数的值,同时收集 1000 个相关的图像吗?对于真实数据,这项任务是永无止境的。

💾我们现在如何管理数据?

在过去的 5 年里,我们在优化数据收集流程和数据标签质量方面取得了巨大进步。此外,我们已经学会了通过使用各种数据扩充技术来充分利用数据集。给定我们数据集中的一幅图像,我们对其应用数学函数,以便在我们的数据中创建更多种类。

现在有超过 400 家公司,总市值为 1.3 万亿美元(略高于脸书的市值),满足我们最新算法的数据需求。

但是现在的路径是不是通向一个死胡同?我们是否达到了建立在人类数据集之上的算法的极限?就像在国际象棋中一样,只要我们使用人类来源的数据作为算法的输入,我们就会被设计约束,不能明显超越我们自己的能力。

在国际象棋中,一旦我们停止建立在次优的人类数据上,并允许机器建立自己的数据以优化它们的学习,后深度学习的突破就来了。在计算机视觉中,我们必须做同样的事情,让机器生成优化自身学习所需的数据。

🏔计算机视觉的下一步是什么?

真正可扩展的创建训练数据的方式是通过虚拟现实引擎。就保真度而言,输出已经变得与真实世界无法区分,给了用户完全的场景控制。这允许用户生成智能数据,这对计算机视觉模型的学习非常有用。合成数据可以成为新的以数据为中心的人工智能框架所需的基石

我们有充分的理由相信,现在是广泛采用可视化合成数据的时候了。

  • 虚拟现实引擎有专门的组件用于合成数据生成( NVIDIA IsaacSimUnity Perception ),生成的数据不仅赏心悦目,而且对于训练更好的算法也是必不可少的
  • 3D 资产正在迅速成为一种商品——最新的 iPhone 配备了激光雷达并且第一代 3D 扫描应用程序正在产生巨大的效果
  • 元宇宙即将到来,这是一件大事。如果《T2》预测的 600 亿美元增长中的一小部分成为现实,我们将生活在一个虚拟现实将成为习惯的世界中。数字双胞胎今天有了真正的应用:一个例子来自宝马,未来的工厂,另一个例子是谷歌的供应链双胞胎
  • 该行业的创新者已经开始使用虚拟现实来改进计算机视觉算法:特斯拉正在使用虚拟世界来生成驾驶场景的边缘案例和新颖视图。

👁️‍🗨️合成计算机视觉

通过使用正确的工具来构建我们自己的数据,我们可以想象这样一个世界,在这个世界中,计算机视觉算法的开发和训练不再需要繁琐的手动数据标记过程。 Gartner 预测,在未来 3 年内,合成数据将比真实数据更占主导地位。

为什么不更进一步呢?一个不需要人类为计算机视觉标记图像的世界会怎么样?

🚀未来是光明的

通过合成计算机视觉,我们可以在虚拟现实中构建,并为现实世界进行部署。就像 AlphaZero 教会自己在国际象棋中什么是重要的一样,我们让算法决定它们需要看到什么,以便最佳地学习。

合成计算机视觉(SCV) 中,我们使用虚拟现实引擎训练计算机视觉模型,并将模型部署在 现实世界 中。

🔬超越 RGB 图像

现实远不止肉眼所见。我们构建的算法主要关注人类能够理解和标记的东西。但事情并不一定是这样——我们可以为传感器构建算法,以超越人类的感知进行测量。我们可以在虚拟现实中有计划地训练这些算法,而不用怀疑它们的有效性。

🤓更聪明而不是更努力

与其建立更大的模型并使用更多的计算能力来解决我们的问题,我们可以明智地选择我们的算法学习的数据来源。算法不需要更多的相同数据来学习,它们需要各种各样的东西。

Deep Mind 表明 AlphaZero 只是这条路的开始,因为他们已经将相同的原则应用于围棋星际争霸蛋白质折叠。今天,我们已经拥有了为计算机视觉构建 AlphaZero 的所有必要构件,这是一个在设计上不受人类输入限制的自我学习系统。一种能够创建和操纵虚拟场景的系统,通过它可以自学如何解决视觉自动化任务。

🔭合成数据生成的先驱

合成计算机视觉的基础是建立在合成数据之上的。大约有 30 家早期公司在视觉合成数据生成领域运营。有些专注于一个垂直领域的特定用例,而大多数则在多个垂直领域横向运营。

按焦点分组的合成数据公司(图片由作者提供)。

现在是 2021 年,我们才刚刚开始。请记住,合成数据只是等待解决的谜题的一部分。

亲爱的读者,❓Questions 给你

1.很容易想象,10 年后,你的智能手机将比你的普通视觉感知能力更强,但我们如何实现这一目标?

  • (增强的)数据标签会一直存在下去,还是只是一块垫脚石?
  • 标签会从 2D 转移到 3D 世界吗,或者我们可以完全不用这种方法吗?

2.在计算机视觉中使用深度学习算法可以获得最先进的结果——合成计算机视觉可以实现新一波以前无法实现的改进算法吗?

保罗·波普 撰写,联合创始人兼 CEO 于neuro labs

neuro labs为零售业打造合成计算机视觉软件。

合成数据:在数据隐私和机器学习中的应用

原文:https://towardsdatascience.com/synthetic-data-applications-in-data-privacy-and-machine-learning-1078bb5dc1a7?source=collection_archive---------26-----------------------

合成数据如何用于数据隐私保护和机器学习模型开发。

去飞溅

“数据是数字时代的新石油”。软件工程师和数据科学家经常需要访问大量真实数据来进行开发、实验和创新。不幸的是,收集这些数据还会带来安全责任和隐私问题,从而影响个人、组织和整个社会。包含个人身份信息(PII)和个人健康信息(PHI)的数据特别容易泄露,需要加以保护。

《通用数据保护条例》( GDPR)等法规旨在为用户数据提供一定程度的法律保护,但由于限制了数据的使用、收集和存储方法,因此带来了新的技术挑战。有鉴于此,合成数据可以作为一种可行的解决方案来保护用户数据隐私,遵守法规,并仍然保持发展和创新的速度和能力。

在本文中,我们将深入探讨合成数据提供的显著优势的细节:

  1. 支持机器学习模型开发,允许实验和模型构建的更快迭代。
  2. 以更加安全和隐私合规的方式促进数据所有者和外部数据科学家/工程师之间的协作。

什么是合成数据?

顾名思义,合成数据本质上是人工或编程生成的“假”数据,而不是通过真实世界的调查或事件收集的“真实”数据。合成数据的创建源于真实数据,一个好的合成数据集能够捕获底层结构,并显示与原始数据相同的统计分布,使其与真实数据无法区分。

第一个 合成数据的主要好处是其支持机器学习/深度学习模型开发的能力。通常,开发人员需要灵活性来快速测试一个想法或尝试构建一个新模型。然而,有时需要数周时间来获取和准备足够数量的数据。合成数据为模型训练和实验的更快迭代打开了大门,因为它提供了如何在真实数据上建立模型的蓝图。此外,利用合成数据,ML 从业者获得了对数据集的完全主权。这包括控制类分离的程度、采样大小和数据集的噪声程度。在本文中,我们将向您展示如何使用合成数据来改善机器学习的不平衡数据集。

第二 合成数据的主要好处是可以保护数据隐私。真实数据包含敏感和隐私的用户信息,不能自由共享,并且受到法律约束。保护数据隐私的方法,如 k-匿名模型,在一定程度上涉及省略数据记录。这导致信息和数据效用的整体损失。在这种情况下,合成数据是这些数据匿名化技术的绝佳替代方案。合成数据集可以更加公开地发布、共享和分析,而不会暴露真实的个人信息。

1.用于 ML 模型训练的合成数据

在本节中,我们将演示机器学习的合成数据的一个用例——修复不平衡的数据集,以支持更准确模型的训练。

什么是数据集不平衡,为什么它很重要?

“任何一个类分布不平等的数据集,在技术上都是不平衡的。然而,当问题的每一类的实例数量之间存在显著的,或者在某些情况下极端的不均衡时,数据集就被认为是不平衡的。”⁴

当在不平衡的数据集上训练时,机器学习模型的准确性受到严重阻碍。这是因为模型在训练期间没有暴露于足够的少数类样本,抑制了它在测试和实际生产数据上评估时识别实例的能力。例如,在欺诈检测任务中,实际的欺诈记录总是属于少数类别,我们需要能够检测到这些记录。

我们可以用来解决不平衡数据集问题的一种技术是“重采样”。这可以通过欠采样多数或过采样少数来实现。下面,我们展示了如何使用 SMOTE(合成少数过采样技术)对少数类进行过采样,并修复不平衡的数据集。SMOTE 使用 k-最近邻算法,基于现有的少数观测值创建合成观测值。⁵

我们首先使用sklearn库创建一个不平衡的数据集,其中类 1 和类 2 的比率为(90:10)。

通过使用主成分分析(PCA)降低数据集的维度,我们可以在 2D 图中可视化我们的数据集。

接下来,我们应用 SMOTE 对少数类进行过采样,平衡我们的数据集,并绘制出我们的平衡数据集。

我们可以看到,类 1 和类 2 中的样本数量现在相等,数据集达到平衡。

提示

  • 您应该只对定型数据集进行过采样。因此,在应用 SMOTE 之前,请确保将数据集分为训练和测试两部分。否则,测试数据集中会引入偏差,它不会反映对您的模型的真实评估。
  • 解决不平衡数据集的其他方法包括:对多数类进行欠采样、收集更多数据、改变评估指标等。

2.用于隐私保护的合成数据

人们可以使用合成数据来保护数据隐私,而不是屏蔽或匿名原始数据。

合成数据:

  • 保留原始数据的基础结构和统计分布
  • 不依赖于原始数据的屏蔽或省略
  • 提供强大的隐私保证,防止敏感的用户信息被泄露

下图显示了根据真实数据集样本创建的合成数据集。在下一篇文章中,我们将深入探讨使用条件生成对抗网络(GAN)从真实表格数据集生成合成表格数据集的方法,如下所示。

样本合成数据:

通过这样做,数据可以更自由地共享和发布,为政府机构、社会科学、卫生部门和软件公司之间的项目合作开辟了机会,在这些领域,数据受到隐私准则的严格监管。

结论

合成数据提供的最大优势之一是其保护用户数据隐私的能力。这为更大规模的数据共享、发布和协作提供了机会。此外,你可以转向合成数据作为支持机器学习模型和软件工具开发的手段,因为与收集真实世界的数据相比,这是一种更便宜、更快速的方法。

在下一篇文章中,我们将向您展示如何从真实数据集生成合成数据,并讨论一些限制、挑战和合成 data⁶.的未来

喜欢这篇文章吗?加入我们的 项目 Alesia 以获得更多关于个人数据隐私、数字福祉、负责任的机器学习、工程等方面的资源!

https://projectalesia.com/

参考

  1. https://www . economist . com/leaders/2017/05/06/世界上最有价值的资源不再是石油而是数据
  2. https://gdpr-info.eu
  3. 路易斯安那州斯威尼市,2002 年 a。利用泛化和抑制实现 k-匿名隐私保护。里面的 j .不确定。绒毛。知道了。基于的系统。10 (05), 571–588.
  4. 费尔南德斯、加西亚、加拉尔、普拉蒂、科劳兹克和埃雷拉(2018 年)。从不平衡的数据集中学习(第 1-377 页)。柏林:施普林格。
  5. 舒拉、鲍耶、K. W .、霍尔、L. O .、凯格尔迈耶、W. P. (2002 年)。SMOTE:合成少数过采样技术。人工智能研究杂志,16,321–357。
  6. 编辑评论普拉特克·桑亚尔

VHA 的合成数据

原文:https://towardsdatascience.com/synthetic-data-at-the-vha-8124989c7183?source=collection_archive---------37-----------------------

保护病人隐私的方法

供稿人(排名不分先后): Purnell,Amanda L. (VHA 创新生态系统);豪沃思,加里 s .(NIST); Bhattacharya,Avik (博思艾伦汉密尔顿公司);麦考利、艾琳(博思艾伦汉密尔顿公司);亨特·津克、哈利(Sage bio networks);沃特福德,肖恩(环保局);任务,克里斯汀(耐克森研究)。

克里斯·利维拉尼在 Unsplash 上拍摄的照片

简介

数字健康数据的兴起正在推动医疗保健行业的重大变革。生物医学数据,包括临床笔记和成像、可穿戴健身追踪器以及基因组测序,可以被研究人员和临床医生用来寻找新的生物标记,从而潜在地提高医疗服务的效率。此外,收集健康的社会决定因素(SDoH)等非健康数据(如收入、教育水平、就业历史、食品安全和住房状况)有助于揭示地理或人口层面的医疗保健差异。

与此同时,这些数字数据财富带来的新机遇是以个人隐私为代价的。随着消费者、数据经纪人、技术平台等之间数据共享的广度。,患者隐私的风险增加了。

目前正在开发用于数字健康数据的统计和加密方法。这些保护隐私的数据挖掘(PPDM)技术可以给数据添加噪声,掩盖敏感细节,或者使研究人员能够在不移动数据的情况下使用数据进行机器学习。PPDM 技术旨在量化数据效用和隐私之间的权衡。例如,在科学效用受到损害之前,数据中可以加入多少噪声?在密码协议下哪些用例是可行的?

为了加快 PPDM 技术在医疗保健领域的采用,社区将从围绕这些技术的使用制定规范中受益。临床实践者和研究人员如何成功地将 PPDM 方法映射到具体的用例,标准是什么?健康隐私损失的标准和量化门槛是什么?

我们提供了一个在生物医学研究和临床企业中整合 PPDM 技术的问题和考虑的讨论。

什么是合成数据?

riefly,合成数据是模拟现实模式的数据,但与真实数据记录不一致。如果可以生成反映临床 EHR 数据中的模式的数据,而与生成这些数据时使用的实际数据记录没有任何可识别的相关性,这将对研究和临床环境中的数据隐私具有显著的益处。

合成数据有可能解决现实和隐私这两个看似矛盾的挑战。它必须反映用于生成数据集的基础真实数据中的特征频率和相关性,并且在训练模型和预测算法方面具有与使用真实数据集相当的效率。它还必须确保隐私风险的可能性最小化或理想情况下为零。因此,预测用于训练合成数据集的实际样本的能力应该保持尽可能低。

与该受众相关的合成健康数据的应用包括

研究小组和临床医生迄今无法获得的数据。

能够扩充训练数据集,以平衡数据集中代表性不足的组和结果。

能够从时间和日期的角度研究临床数据,以识别聚类和模式。

生成合成数据

马库斯·斯皮斯克Unsplash 上拍摄

合成数据通常通过不同的统计方法生成,具体取决于数据的使用案例。基于规则的方法(如 Synthea)和生成对抗网络(基于 GAN)的方法(如 CorGAN、medGAN 等。)被典型地使用,并且在卫生保健数据中受到了最多的关注。在医疗数据领域之外还使用了其他技术,如多个国家统计机构用于调查数据的多重插补。概率图形模型(PGM)也非常强大,并开始看到更多的用途。Syntegra.io、MDClone、Unlearn、Diveplane 等公司也开发了许多商业应用程序。

生成合成数据的不同模型在风险、收益、要求、工作和使用成本等方面提供了不同的权衡。我们试图在下面的图表中捕捉主要不同数据生成模型的合成数据输出的一些差异。

选择合成数据的方法/工具

【隐私与效用(刘等[1])

选择合适的算法和工具来生成合成数据,对于试图从患者数据中提取有意义信息的临床和研究项目的成功至关重要。成功的项目必须平衡个人在数据中被识别的低隐私风险和导致研究人员得出错误结论的嘈杂数据的低风险。通常,一个好的安全检查是将合成噪声与采样误差噪声进行比较。上图(隐私与效用)强调了这一点,来自刘等人的工作[1]。

因此,合成数据的用户必须沿着隐私-效用/真实性连续体选择方法,以找到最适合他们需求的数据生成算法。下面是一个简单的决策方案,用于根据具体项目的真实性和隐私需求,确定是采用基于 GAN 的方法、混合方法还是基于规则的方法来生成合成数据。

选择合适的合成 PPDM(图片由作者提供)

评估合成数据的方法/工具

对于所使用的任何方法,评估所生成的合成数据的质量是至关重要的。评估工具的一个例子是 k-边际度量。k-边际评估指标是为第一届 NIST 综合数据挑战赛开发的,在四年的比赛中,除了一场比赛外,其他比赛都使用了这一指标。它评估整个数据空间中两个数据集之间的分布相似性(k 个特征的每个可能组合的关系)。NIST 挑战赛发现 k-marginal 可以预测一系列其他分析的解决方案性能:如果一个综合解决方案在 k-marginal 测试中得分很高,它在其他数据质量指标或用例中也表现很好。此处列出了 k 边际评估的正式定义

现代数据合成技术(如 GANS 或 r/synthpop 中使用的基于树的模型)通常使用完全条件合成,这意味着每个变量的模型都适合使用所有可用信息,以便捕捉数据中变量之间所有有意义的关系(包括令人惊讶或意想不到的关系)。这与开发模型时使用少量精选变量的旧方法有很大不同。当两个不同的数据子组在相同的变量上具有非常不同的分布模式时,一些模型可能很难正确地捕捉这两个组。在这种情况下,合成可以被划分以防止组冲突。NIST 的 k-边际度量对于识别数据中出现此问题的位置非常有效。反复评估合成数据质量,然后调整合成过程以解决任何未发现的问题的过程称为合成器调谐。

当前和最近的活动

T 合成数据在保护隐私方面的潜在和有形优势已经导致了一些令人兴奋的新合作。它还刺激了为联邦卫生领域的临床医生和研究人员生成综合健康记录的研究。

  • NIST 的 PSCR 在 2018 年设立了两个连续的数据挑战。第一项是“不可链接的数据挑战”,向提出了保护个人身份信息同时保持数据集的分析效用的机制的概念论文颁奖。第二项是“差分隐私合成数据挑战”,要求参与者创造新方法,或改进现有的数据去识别方法,同时保留数据集的分析效用。所有解决方案都需要满足差分隐私保证,这是一种可证明的个人隐私保护保证。
  • NIH 在 2020 年年中宣布,MDClone 将为国家 COVID 群组协作(N3C)2 的合成工作流提供支持技术,这是一个用于托管新冠肺炎临床数据的集中式安全门户,可通过多种模型接受数据,并将其转换为通用的 OMOP 模型。
  • 继 2018 年成功举办挑战赛后,NIST 于 2020 年举办了 PSCR 差分隐私时态地图挑战赛,该挑战赛提供公共安全数据集,并要求算法在保证保护个人隐私的同时最大限度地保护数据效用。

未来地区

这一领域正在探索多个问题,包括:

  • 量化生成数据的科学有效性。
  • 量化根据生成的数据训练的模型的准确性和相关性,并与从真实数据集导出的模型进行比较。
  • 验证所生成的数据实际上确实保护了隐私,并且真实数据样本中的成员关系推断仅最低限度地可能来自合成数据。上一节提到的 NIST 提出的挑战建立了介绍性基准,可以从隐私保护的政策角度进一步开发和利用这些基准。
  • 评估生成和验证合成数据集的计算资源负载。

参考

[1]刘等.“差分隐私机制的隐私保持单调性”(2018).来源网址

[2] Haley Hunter-Zinck,D-Lab 安全研究数据工作组“验证合成生成的电子健康记录数据的隐私保护属性”(2020)。

[3] Raths D .新闻文章-国家 COVID 群组合作准备向研究人员开放 Enclave(2020)。来源网址

[4]d . Ridgeway,m . Theofanos,m . Manley,t .和 Task,c .挑战设计和从 2018 年差分隐私挑战中吸取的教训,技术说明(NIST TN),马里兰州盖瑟斯堡国家标准与技术研究所(2021)。来源网址PDF 出版

使用条件 GAN 的合成数据生成

原文:https://towardsdatascience.com/synthetic-data-generation-using-conditional-gan-45f91542ec6b?source=collection_archive---------1-----------------------

修改 GAN 架构,以便更好地控制生成的数据类型

照片由 Unsplash 上的西提·拉赫马纳·马特·达乌德拍摄

为什么需要生成数据?

在信息技术领域,公司使用数据来改善客户体验,并为客户提供更好的服务。有时候,收集数据可能会很繁琐,而且成本很高。

在本文中,我们将讨论 GAN 和特殊条件 GAN,一种我们在 Y-Data 用于合成数据生成的方法。以及如何利用它们生成合成数据集。

GAN 是由 Ian Goodfellow 等人提出的。在 2014 年本文中。GAN 架构由两个组件组成,称为发生器和鉴别器。简单来说,生成器的作用是生成新的数据(数字、图像等。)与作为输入提供的数据集一样接近/相似,鉴别器的作用是区分生成的数据和真实的输入数据。

下面我们就来详细参观一下甘的算法工作原理:

o 生成器将一个随机数向量作为输入,并返回由其生成的图像。

发电机输入(来源: 此处 )

o 发生器生成的图像与实像样本一起作为输入传递给鉴别器。

鉴别器输入(来源: 此处 )

o 鉴别器采集两种类型的样本,来自真实数据集的图像和生成图像的样本。它返回一个介于 0 和 1 之间的概率值,其中越接近 1 的值表示属于真实数据集的图像变化越大,否则图像属于生成的图像样本的可能性越大。

o 当我们计算鉴频器损耗时,鉴频器的错误分类会受到惩罚。该鉴别器损失然后反向传播并更新鉴别器权重,这反过来改善了鉴别器预测。

甘鉴别仪训练(来源: 此处 )

o 发电机然后在鉴别器分类的帮助下计算发电机损耗,并通过鉴别器和发电机反向传播以计算梯度。然后,它仅使用这些梯度更新发生器权重。

甘发电机培训(来源: 此处 )

有条件——甘

尽管 GAN 能够生成一些好的数据点示例,但是它不能生成具有目标标签的数据点,并且从其生成的数据集缺乏多样性。

有条件 GAN 是由 M. Mirza 在 2014 年末提出的。他修改了架构,将标签 y 作为参数添加到生成器的输入中,并尝试生成相应的数据点。它还向鉴别器输入添加标签,以便更好地区分真实数据。

以下是有条件 GAN 的架构:

C-GAN 架构

在这种架构中,随机输入噪声 Z 在联合隐藏表示中与标签 Y 相结合,GAN 训练框架允许在如何接收输入方面有很大的灵活性。

数据点 XY 连同生成输出【G(z)一起被传入鉴别器的输入,这与普通 GAN 架构中的情况相同

条件 GAN 的损失函数类似于 GAN:

条件 GAN 损失功能

Python 实现

在这个实现中,我们将在时装-MNIST 数据集上应用条件 GAN 来生成不同服装的图像。该数据集包含 70,000 幅(60k 训练和 10k 测试)大小为(28,28)的灰度格式图像,像素值为 b/w 1 和 255。

数据集中有 10 个分类标签。它们中的每一个都用数字 b/w 0–9 来表示。下表列出了相应的标签:

0: T 恤/上衣

1:裤子

2:套头衫

3:着装

4:外套

5:凉鞋

6:衬衫

7:运动鞋

8:袋子

9:踝靴。

现在,让我们开始编写代码。首先,我们导入所需的模块,我们将 TensorFlow Keras API 来设计我们的架构。一些代码取自这个 book⁴:

现在,我们定义生成器架构,该生成器架构采用随机潜在向量和标签的组合作为输入,并生成该标签的图像。

生成器架构(源代码)

现在,我们定义鉴别器架构,该鉴别器架构将图像和标签作为输入,并输出它是真实的或生成的概率。

鉴别器架构(源代码)

下一步,我们将结合这两种架构,形成完整的 C-GAN 架构:

现在,是时候训练模型了,首先,我们定义采样函数,然后,我们训练模型。

2000 [D loss: 0.097897, acc.: 96.88%] [G loss: 4.837958]
4000 [D loss: 0.084203, acc.: 98.05%] [G loss: 5.004930]
6000 [D loss: 0.111222, acc.: 97.66%] [G loss: 4.664765]
8000 [D loss: 0.091828, acc.: 97.27%] [G loss: 5.158591]
10000 [D loss: 0.110758, acc.: 98.44%] [G loss: 5.750035]
12000 [D loss: 0.152362, acc.: 92.58%] [G loss: 4.261237]
14000 [D loss: 0.075084, acc.: 96.48%] [G loss: 5.566125]
16000 [D loss: 0.108527, acc.: 96.88%] [G loss: 9.546798]
18000 [D loss: 0.043660, acc.: 99.61%] [G loss: 6.730018]
20000 [D loss: 0.075157, acc.: 97.66%] [G loss: 6.238955]

现在,我们把生成的图片生成 GIF,他的一些代码是从这里截取的。

Generated_Images(来源:代码)

结论

在本文中,我们讨论了用于合成数据生成的 GAN 和条件 GAN。而 GAN 则是合成数据生成领域的一个新发现。不同的研究者根据他们的需要修改了 GAN 背后的想法。一个这样的想法是 Conditional-GAN,它允许我们根据所需的标签生成数据。

参考文献

[1]: Ian J. Goodfellow,J. Pouget-Abadie,M. Mirza 等人,(2014)。

[2]: M. Mirza,S. Osindero,条件生成对抗网 (2014)。

[3]: H. Xiao,K. Rasul,R. Vollgraf, Fashion-MNIST:一个新的图像数据集,用于对机器学习算法进行基准测试。

[4]: J. Langr,V.Bok, GANs in Action:深度学习与生成性对抗网络 (2019),Manning Publications

本页面的部分内容是基于 Google 创建和共享的 作品的修改,并根据 知识共享 4.0 归属许可 中描述的条款使用。

合成数据—主要优势、类型、生成方法和挑战

原文:https://towardsdatascience.com/synthetic-data-key-benefits-types-generation-methods-and-challenges-11b0ad304b55?source=collection_archive---------8-----------------------

这里有一个初学者指南,告诉你关于合成数据应该知道些什么

图片来源: Unsplash

研究人员和数据科学家经常遇到这样的情况,他们要么没有真实的数据,要么由于保密或隐私问题而无法利用这些数据。为了克服这个问题,进行合成数据生成以创建真实数据的替代。为了算法的正确运行,需要进行真实数据的正确替换,这在本质上应该是现实的。本文介绍的研究是关于人工智能中对合成数据日益增长的需求以及我们如何生成这些数据。

简介

合成数据是指除了真实世界事件产生的数据之外,手动或人为创建的数据各种算法和工具可以帮助我们生成综合数据,这些数据有多种用途。这通常需要验证模型,并将真实数据的行为方面与模型生成的数据进行比较。合成数据的起源可以追溯到 20 世纪 90 年代,但真正的使用是在过去几年,人们开始了解数据科学中的风险,这些风险可以通过使用合成数据来消除。

合成数据的重要性

合成数据的重要性在于它能够生成满足特定需求或条件的要素,而这些要素在真实世界的数据中是不可用的。当缺乏测试数据时,或者当隐私是您最优先考虑的问题时,合成数据就能派上用场。

人工智能商业世界非常依赖合成数据——

  • 在医疗保健领域,合成数据用于测试某些不存在真实数据的情况和案例。
  • 基于 ML 的优步和谷歌的自动驾驶汽车是使用合成数据进行训练的。
  • 在金融领域,欺诈检测和保护非常重要。新的欺诈案件可以在合成数据的帮助下进行审查。
  • 合成数据使数据专业人员能够使用集中记录的数据,同时仍然保持数据的机密性。合成数据具有复制真实数据的重要特征而不暴露其真实意义的能力,从而保持隐私完整。
  • 在研究部门,合成数据帮助您开发和交付创新产品,否则可能无法获得必要的数据。

方法论

主要有两种方法生成合成数据

  1. 从分布中提取数字:主要思想是观察真实世界数据的统计分布,然后复制相同的分布以产生具有简单数字的相似数据。
  2. 基于主体的建模:主要思想是创建一个观察到的真实世界数据统计分布的物理模型,然后使用相同的模型再现随机数据。它侧重于理解直接影响整个系统的代理之间的交互的影响。

利用合成数据的机器学习

机器学习算法需要处理大量的数据,以便创建一个稳健可靠的模型。否则,生成如此大量的数据会很困难,但有了合成数据,就变得容易多了。它对于计算机视觉或图像处理等领域非常重要,在这些领域中,一旦开发出初始合成数据,模型创建就变得更加容易。

生成对抗网络(GANs)是最近提出的,是图像识别领域的一个突破。一般由两个网络组成:一个鉴别器和一个发生器。生成器网络的功能是生成更接近真实世界图像的合成图像,而鉴别器网络的目标是从合成图像中识别真实图像。gan 是机器学习中神经网络家族的一部分,其中两个网络都通过建立新的节点和层来保持学习和改进。

生成合成数据可以根据需要灵活地调整其性质和环境,以提高模型的性能。标记实时数据的准确性有时非常昂贵,而合成数据的准确性可以很容易地获得高分。

合成数据的类型

合成数据是随机生成的,目的是隐藏敏感的私人信息并保留原始数据中特征的统计信息。合成数据大致分为三类:

  • 全合成数据 —此数据纯属合成,与原始数据无关。这种类型的数据生成器通常会识别真实数据中特征的密度函数,并估计这些特征的参数。随后,对于每个特征,从估计的密度函数中随机生成隐私保护系列。如果只有真实数据的几个特征被选择用于用合成数据替换,那么这些特征的受保护系列被映射到真实数据的其他特征,以便以相同的顺序排列受保护系列和真实系列。用于生成完全合成数据的经典技术很少是自助法和多重插补。由于数据完全是合成的,不存在真实的数据,因此这种技术具有强大的隐私保护功能,并且可以依靠数据的真实性。
  • 部分合成数据 —该数据仅用合成值替换某些选定敏感特性的值。在这种情况下,实际值只有在包含高泄露风险时才会被替换。这样做是为了保护新生成数据的隐私。用于生成部分合成数据的技术是多重插补和基于模型的技术。这些技术也有助于输入真实数据中的缺失值。
  • 混合合成数据 —该数据由真实数据和合成数据生成。对于真实数据的每个随机记录,在合成数据中选择一个接近的记录,然后将两者组合以形成混合数据。它提供了完全和部分合成数据的优点。因此,众所周知,与其他两种方法相比,它提供了良好的隐私保护,具有较高的实用性,但需要更多的内存和处理时间。

挑战

合成数据在人工智能中有很强的根基,具有许多好处,但在处理合成数据时仍有一些挑战需要解决。这些措施如下:

  • 生成合成数据的困难。
  • 在将复杂的数据从真实数据复制到合成数据时,会遇到许多不一致的情况。
  • 合成数据的灵活性使其在行为上存在偏差。
  • 对于用户来说,用合成测试数据来验证它可能还不够。他们可能需要你用真实的数据来验证它。
  • 在用合成数据的简化表示训练的算法的性能上,可能存在一些隐藏的愚蠢行为,这些行为最近可能会在处理真实数据时出现。
  • 许多用户可能不接受合成数据是有效的。
  • 从真实数据中复制所有必要的特征在本质上可能会变得复杂。在此过程中,还可能会遗漏一些必要的功能。

案例分析

合成数据有很多运营用例。一些著名的使用案例如下

感谢阅读!😃

关于作者

Kajal Singh 是牛津大学人工智能-云和边缘实施课程的数据科学家和导师。她还是《强化学习在真实世界数据中的应用(2021) 》一书的合著者

参考文献

https://www . riaktr . com/synthetic-data-become-major-competitive-advantage/

https://www . tech world . com/data/what-is-synthetic-data-how-can-it-help-protect-privacy-3703127/

https://blog.aimultiple.com/synthetic-data/

https://mro . Massey . AC . NZ/bitstream/handle/10179/11569/02 _ whole . pdf?sequence=2 &被允许=y

https://tdwi . org/articles/2019/06/28/adv-all-synthetic-data-ultimate-ai-disruptor . aspx

https://www . techrepublic . com/resource-library/white papers/re-identificati on-and-synthetic-data-generators-a-case-study/

https://arxiv.org/pdf/1909.11512.pdf

合成数据——数据保存人工智能的灵丹妙药?

原文:https://towardsdatascience.com/synthetic-data-the-panacea-for-data-preserving-ai-298b48ec3189?source=collection_archive---------27-----------------------

生成合成数据的不同技术的比较分析

马太·亨利Unsplash 上拍照

介绍

AI 改变了世界

不管是好是坏,这完全是一个哲学上的争论,然而,上面的陈述几乎是真实的,是作为一个定律来陈述的。随着深不可测的数据量的无处不在的入侵,大量的 ML 算法,以及世界日益增加的复杂性,我们几乎处于这样一个点上,即我们快速增长的技术发展速度与计算要求的结合甚至可能使神圣的 摩尔定律过时

然而,正如每一次技术进步一样,我们现在正面临着来自数据爆炸性使用的迫在眉睫的威胁——数据隐私问题,它已经变得与被称为未来十年最重要的问题一样重要。通过这篇文章,我的目标是阐明数据隐私的综合含义,以及对当前技术的广泛观点,重点关注合成数据生成的方法,以及它们的定量-定性分析。尽管我已经尽力以一种简单的方式提出了我的发现,但我已经对人工智能领域有了一个总体的认识,并且通篇使用了其他专门的技术术语(主要是由于本文的简洁性质)。

什么是数据隐私?

尽管对数据隐私的简明定义还没有明确的共识,但它被宽泛地定义为处理敏感的个人数据所涉及的一系列实践,通常与 信息隐私 领域重叠。正如 Patricia Thaine(联合创始人,私人 AI)在她的 文章中提到的,数据隐私一般有四大支柱

  1. 培训数据隐私- 对培训数据进行不良逆向工程以确定个人身份的相关风险。
  2. 输入隐私- 与用户输入数据向外部参与者(包括模型创建者本身)泄露相关的风险。
  3. 输出隐私- 与用户输出数据向用户本身以外的外部行为者泄露相关的风险。
  4. 模型隐私- 与恶意方窃取模型相关的风险。

显而易见,对数据隐私的完整分析包括仔细分析与传统数据/模型管道的所有步骤相关的风险。自然,在人工智能的情况下,隐私问题不仅延伸到软件考虑,也延伸到硬件规范,这带来了自己的威胁。这篇文章将其讨论限制在训练数据隐私的领域,这是一个被认为与人工智能算法领域最兼容的概念。

数据隐私和人工智能

随着利用数据得出有意义结论的方法日益增多,定量执行这些计算的算法也日益增多。从简单的统计方法到监督算法领域,再到强大的深度学习领域,计算能力和得出的结论今天继续以非常高的速度增长。自然,随着这些算法的计算能力的提高,它使模型创建者能够使用比以往任何时候都多得多的数据特征,甚至有可能在一个算法中增加到数百万个特征。因此,这导致了恶性循环,如下所述。

技术的恶性循环(作者图片)

虽然从训练集和参数中获取敏感信息比简单的输入/输出相对更困难,但研究中有明确的证据表明逆向工程模型和重建数据的实际可能性。

例如,[1] Carlini 和 Wanger 在他们的研究中表明,一个模型在一个训练集中记忆罕见的信息是可能的。特别是,他们设计了一种算法,当在不考虑这种记忆的模型上实现时,可以很容易地从中提取稀有信息。暴露度量量化了信息的暴露,这在某种意义上显示了模型有多脆弱。

给定一个金丝雀 s[r]** ,一个带参数θ 的模型,和随机性空间 R ,s[r]的曝光度为:**

作者图片

等级是真实秘密(金丝雀)在所有可能秘密中的索引。虽然这里没有给出详细的分析,但是该度量与测试集的损失最小时暴露达到峰值的事实是一致的。

差分隐私 来救援?

自然,为了防止这种数据泄漏,许多研究已经进入设计防止这种泄漏的方法,其中差分隐私的方法似乎是最有前途的一种。[2] Dwork、Nissim、McSherry 和 Smith 表明,如果某个校准(统计)噪声被引入数据集,那么几乎不可能到达数据集的发起者,因此在该方法中包含了设计隐私的概念。更具体地说,对于每个输出 O,任何对手都无法区分相差一个输入的两个数据集 D1 和 D2,即它们总是受到ε的度量的限制,如下所示。

作者图片

Pr=概率,E =ε(一个小的正实体)

尽管大肆宣传,差分隐私本身并不是一个完美的解决方案。关于什么是/不是私有的问题,该方法无法精确地在大型数据集上工作的问题还没有完全回答。

虽然匿名数据本身似乎是一个不错的选择,但它仍然容易遭到黑客攻击。臭名昭著的 用户身份识别事件 当网飞向其提供匿名用户评级时,却发现它已被去匿名化,这向我们展示了与之相关的风险。因此,可以有把握地说匿名化永远不够

合成数据——新范式

合成数据生成技术的出现极大地促进了数据隐私领域的发展。合成数据概念的历史根源可以追溯到 Little (1993 年)构想的部分同情数据概念,Rubin (1993 年)首先将其付诸实践,他使用多重插补生成十年一次的人口普查的合成版本。

虽然早期的方法使用参数建模,但根据开发精确模型的复杂程度,也使用非参数方法,即装袋、随机森林等。然而,正如我们前面提到的,就像预测完全被深度学习模型重新想象一样,这些模型现在也在生成合成数据方面发挥着重要作用。在本文中,我将讨论限制在合成数据的四种主要方法上。这些如下所述-

重击

合成少数过采样(SMOTE) 是一种生成合成数据的方法,主要用于分类。[3] Chawla、Boyle、Hall 和 Kegelmeyer 在 2003 年引入了这一概念,以处理不平衡数据集,这种数据集往往会在数据集中引入隐含偏差。虽然它是其他深度学习方法的例外,但它的各种版本仍在使用,在实现中引入了轻微的修改。

在一个非常基本的方式中,它可以被概念化如下-

作者图片

考虑数据点的 k 个邻居,其中 y 是 0 到 1 之间的随机数。

VAE

可变自动编码器(VAE) 是自动编码器的最新增强版本,这是一种基于神经网络的合成数据生成方法。它是一个前馈神经网络,其中数据集最初由编码器压缩为压缩表示,然后由解码器尝试解压缩。它使用瓶颈的概念来压缩数据,这实质上涉及到限制信息流。

作者图片

也许没有算法比 Ian Goodfellow 和他的同事引入的生成式对抗网络(GAN)在人工智能领域产生的影响更大[4]。这些算法通常通过查看非常精细的级别来学习测试数据集的分布,以生成合成数据集。它们的本质是其中存在两个相互竞争的神经网络,称为生成器和鉴别器。他们采用了一种两人游戏理论方法,即生成器从噪声中模拟数据分布,鉴别器根据真实数据鉴定生成的数据是真实的还是虚假的,因此随着适应性的增加,当生成器在模拟真实数据方面变得越来越好时,鉴别器在鉴别它方面变得越来越好,从而生成看起来非常真实的合成数据集。

WGAN 和 WCGAN

Wasserstein GANWasserstein Conditional GAN是 GAN 模型的最新扩展,其中用作鉴别器函数的正常 JS 散度 矩阵被 Wasserstein 矩阵替代,wasser stein 矩阵在某种意义上测量概率分布之间的距离,从而提供某种质量测量。当 WGAN 进一步以 C 类为条件以产生一个以上的标签时,WCGAN 开始生效,这进一步提高了进一步学习的质量,这是对通过早期方法产生的合成数据的显著改进。

作者图片

边注 - 上述算法的实现可以通过 Tensorflow 和 Keras 来完成。对于 WGAN 的工作实现,请查看本文

合成数据和数据隐私?

一开始,合成数据似乎是处理数据隐私的最有前途的方法。然而,要注意陈述,需要严格开发质量隐私的参数,以给出明确的结论性事实。在质量领域,成对皮尔逊系数可用于确定合成数据与真实数据的质量【5】。该公式可以表述为-

作者图片

差异越小,合成数据就越接近真实数据。关于哪种模型最适合生成合成数据的问题需要解释一下。一般来说,已经观察到模型的选择取决于数据集。更正式地说,为了找出哪个模型效果最好,我们可以设计一个系统,它通过所有四个模型检查合成数据的质量和隐私,并以系统的方式得出结论。但是纯粹从隐私的角度来说,GANs 是最突出的。简单的原因是,与 VAE 和 SOTE 不同,GAN 不需要真实数据集作为核心输入,即它们的生成器完全与真实数据集分离。随着 WGAN 和 WCGAN 的进一步改进,我们可能会朝着正确的方向快速解决数据隐私问题。

结论

尽管合成数据集的调整可能是朝着正确方向迈出的重要一步,但仅靠它们并不能完全防止隐私泄露。真正的解决方案必须是各种技术的理想组合,如【WCGAN+差分隐私。尽管该研究领域还处于起步阶段,但是已经出现了许多新的解决方案,这些方案综合了学术界和工业界的关注。例如,Synthetic data . community,一个开源社区提供了像 WGAN、Time Synthetic GAN 这样的工作深度学习模型来生成合成数据。不仅如此,学术研究也在迅速赶上。虽然速度令人印象深刻,但这些技术层必须足够强大,以允许我们处理隐私的软件和硬件方面,并维护所谓的四个基本支柱(如上所述)。****

总之,虽然人工智能可能使我们能够扮演上帝之手,但数据的隐私需要得到确保,以便我们不会最终烧伤自己的手。

参考文献

[1] Carlini,Nicholas 等,秘密分享者:评估和测试神经网络中的非故意记忆(2019) ,第 28 届 USENIX 安全研讨会(USENIX 安全 19)。

[2] Dwork C .,McSherry F .,Nissim K .,Smith A. (2006) 在私有数据分析中校准噪声对灵敏度。载于:Halevi S .,Rabin T .(编辑)密码学理论。TCC 2006。计算机科学讲义,第 3876 卷。斯普林格,柏林,海德堡。https://doi.org/10.1007/11681878_14

[3]舒拉、鲍耶、霍尔和凯格尔迈耶(2002 年)。 SMOTE:合成少数过采样技术。《人工智能研究杂志》第 16 期,第 321 至 357 页。

[4]古德费勒等人(2014)。生成对抗网络。神经信息处理系统进展,第 2672 至 2680 页。

[5] Beaulieu-Jones,Wu 等,(2019) 隐私保护的生成式深度神经网络支持临床数据共享,心血管质量与结果杂志

合成数据来拯救!

原文:https://towardsdatascience.com/synthetic-data-to-the-rescue-2241f626303e?source=collection_archive---------27-----------------------

没有足够的数据?放心吧!合成数据在这里!

由于缺乏数据、隐私和保密性,数据短缺已成为卫生、体育、制造和法律等行业中需要解决的重要问题。我喜欢在 Linkedin 上联系。

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

问题陈述:生成合成数据

今天,社会的多个部门正在取得巨大进步,利用机器学习技术来执行预测、分类、分割等任务。虽然它在一些领域有很高的影响,但由于数据匮乏,机器学习技术在一些领域,即医疗保健和体育领域,还没有在最高级别使用。此外,由于缺乏数据,机器学习模型不会产生最佳结果,这不适合误差幅度很小的情况。因此,这里合成数据的生成成为必须。

产生的合成数据将充当真实数据的模仿,模仿其属性,并增加数据量以输入到机器学习模型中。此外,合成数据在产生可用于检查事件并确保事先采取必要行动和预防措施的情况方面发挥着重要作用。

有两种类型的合成数据——完全合成的和部分合成的。

如果一个数据集中没有原始数据,那么它就是一个完全合成的数据集。如果在新生成的数据集中有任何原始数据,那么它在一定程度上就是一个合成数据集。在部分合成的数据集合中,仅使用合成数据生成技术来再生敏感信息。

因此,意识到非常需要有足够的数据来训练具有更高精度和效率的模型,我们提出了一种使用随机数的迭代回归分析集来生成具有与真实数据集相似的统计质量的合成数据的方法。来自 data.world 的 FIFA 视频游戏数据集已被用于支持这种方法并展示其用例。

照片由 Jannik SkornaUnsplash 上拍摄

最初,对数据进行了深入了解。对不同属性之间的相关性进行了观察。选择可以被模仿以获得人工数据的五个最高度相关的属性。属性是-控球,运球,特殊,短传,长传。

观察到的相关性

接下来,我们确保通过检查任何缺失值、重复值或异常值来预处理数据。

让我们深入了解一下方法、架构和结果的概况。

系统结构

首先,使用一个随机整数的 M 维向量,使用一个模型来生成合成数据的 M 维向量。对于接下来的步骤,重复相同的过程,只确保第一步之后新生成的数据也作为第二步的输入数据。这个过程一直进行到所有新列都生成为止。

为了分析所获得的结果,我们提出了以下度量标准来衡量回归模型的准确性

  1. 平均绝对误差

2.残差平方和

3.R2 分数

绩效评估

最后,我想说的是,这是我在 2020 年第四届 ICECA 上提交的论文的简要概述。它成功地在 IEEE Explore 上发表。

目的是使用一种简单而有效的叫做迭代回归分析的技术生成合成数据。

感谢您抽出时间阅读并简要概述我所做的工作;如果你有兴趣了解更多关于这个项目的信息,或者想要讨论它,请随时通过 Linkedin 联系我。

如果你有兴趣阅读这篇文章,请点击查看。

我和我的同事吉尔·科塔里和桑斯卡·沙阿一起写这篇论文。

论文参考文献:

  1. https://ieeexplore.ieee.org/document/1611688
  2. https://ieeexplore.ieee.org/document/6890935
  3. https://ieeexplore.ieee.org/document/1197502
  4. https://ieeexplore.ieee.org/document/8115698
  5. https://data.world/raghav333/fifa-players

对文章的引用:

  1. https://www.simerse.com/synthetic-data

合成生成的数据—它将来会超过真实世界的数据吗?

原文:https://towardsdatascience.com/synthetic-generated-data-will-it-surpass-real-world-data-in-the-future-bf6ef8b05e51?source=collection_archive---------41-----------------------

为什么每个公司都依赖于合成数据集,它是如何生成的

弗兰基·查马基在 Unsplash 上拍摄的照片

为任何数据科学项目找到合适的数据集都是一项具有挑战性的任务。机器学习模型依赖于数据集的质量和数量。而且,训练一个健壮的人工智能模型,需要大量的数据。

什么是合成数据集?

顾名思义,合成数据集类似于真实世界的数据集,但以编程方式生成。与现实世界的数据集不同,它不是通过任何现实生活的手段、调查或实验收集的。合成是根据数据科学项目的要求生成的,用于广泛的活动,包括训练健壮的人工智能模型、测试和验证模型。

(图片由作者提供),合成数据

为什么合成数据集很重要?

合成数据集晚于真实数据集有几个原因:

  • 特定数据需求:可以生成合成数据集,以满足任何数据科学项目对数据集的特定需求,这些项目无法使用真实世界的数据集来完成。
  • 科技巨头对海量数据的控制:每次都会产生大量的数据,但是数据集的控制是由谷歌、微软、亚马逊、脸书等一些科技巨头来完成的。小公司或初创公司无法获得大量准确的数据集,因此他们必须依赖人工生成的数据集或合成数据。
  • 数据隐私:数据隐私是需要考虑的一个重要方面。数据可能会被黑客滥用,因为他们可以通过对模型进行结构化查询来获取个人数据。可以对推断个人数据的模型执行白盒和黑盒攻击,并且可以改变模型输出。
  • 生成数据以处理边缘情况:模型需要针对每种情况进行训练和测试。在某些情况下,现实世界的数据集可能无法用于训练或测试模型。对于自动驾驶汽车项目,为了处理有人突然出现在车辆前面的情况,记录这样的真实世界可能有风险,因此合成数据生成是可行的。
  • 昂贵的真实世界数据集:在某些情况下,记录真实世界数据集可能非常昂贵,在这种情况下,生成符合项目要求的合成数据集可能是最经济的选择。为自动驾驶汽车记录真实世界的数据集可能很昂贵,相反,计算机生成的模拟可能是一种可行的替代方案。

合成数据可能会改变数据科学初创公司或小公司的游戏规则。大部分是。AI 是一个人工智能驱动的合成数据生成平台,它声称真实世界数据集中 99%的信息可以在人工生成的数据集中回收。这使得合成数据完全匿名,就像真实的一样。

(来源:大部分是。AI ,保留数据与收集数据的关系图

合成数据生成:

有多种技术可以生成合成数据集。在确定生成合成数据的方法之前,必须弄清楚他们想要的合成数据的类型。大致有两大类:

  • 全合成数据生成
  • 部分合成数据生成

生成人工数据集的不同技术有:

  • 重击
  • 阿达辛
  • 数据扩充
  • 可变自动编码器
  • 生成对抗网络

阅读下面的文章,了解更多关于如何使用开源 python 库创建人工影像数据集的信息。

https://medium.com/swlh/create-custom-image-dataset-for-ai-ml-projects-using-python-72a62520f072

结论:

在机器学习中,对合成数据集的需求正在快速增长,因为机器学习模型是根据需求使用大量准备良好的数据来训练的,并且获得这样的真实世界数据集非常困难。

合成数据集还有几个额外的好处,例如标注的准确性、敏感信息的替换、数据生成的简便性等等。

感谢您的阅读

合成时间序列数据:GAN 方法

原文:https://towardsdatascience.com/synthetic-time-series-data-a-gan-approach-869a984f2239?source=collection_archive---------1-----------------------

实践教程

定时器生成合成时序数据

时间序列或顺序数据可以定义为任何具有时间依赖性的数据。很酷,嗯,但是哪里可以找到序列数据呢?嗯,无处不在,从信用卡交易、我的日常事务和行踪到医疗记录,如心电图和脑电图。尽管序列数据很容易找到并且非常有用,但是有很多原因导致没有利用它——从隐私法规到其存在的稀缺性。

在我以前的一篇帖子中,我已经介绍了生成对抗网络(GANs)学习和生成新的合成数据的能力,这些数据保留了真实数据集的实用性和保真度,然而生成表格数据比生成应该保留时间动态的数据集要简单得多。到时间序列数据建模成功意味着一个模型不仅必须捕获每个时间点内的数据集特征分布,还应该能够捕获这些特征随时间变化的复杂动态。我们也不能忘记,每一个时间序列都是作为一个可变长度相关联的。

但是这是一项具有挑战性的任务,并不意味着它是不可能的! Jinsung YoonDaniel Jarret 在 2019 年提出了一种新颖的 GAN 架构来模拟顺序数据—time GAN——我将在这篇博文中通过一个实际例子来介绍这种架构。

时序生成对抗网络

TGAN 或时间序列生成对抗网络于 2019 年提出,作为一个基于 GAN 的框架,能够在各种不同的领域生成现实的时间序列数据,即具有不同观察行为的序列数据。与其他 GAN 架构(例如 WGAN )不同,在其他 GAN 架构中,我们对真实数据和合成数据都实施了无监督的对抗性损失,TimeGAN 架构引入了监督损失的概念— 鼓励模型通过使用原始数据作为监督来捕捉数据中的时间条件分布。此外,我们可以观察到一个嵌入网络的引入,它负责减少对抗性学习空间维度。

TimeGAN 框图和训练方案如文中所述

time gan 有什么新特性?

与用于顺序数据的其他 GAN 架构不同,所提出的框架能够生成其训练以处理混合数据设置,其中静态(属性)和顺序数据(特征)能够同时生成。

对超参数变化不太敏感

与其他架构相比,这是一个更稳定的培训流程。

使用 TensorFlow 2 实现

如上所述,TimeGAN 是一个合成由 4 个网络组成的顺序数据的框架,这 4 个网络在数据建模的过程中扮演不同的角色:预期的生成器鉴别器,以及通过恢复嵌入器模型。

用 RNNs 实例化的 TimeGAN 框架

为了这个例子的目的,我决定用一个非常相似的架构来简化所有的 4 个元素:一个 3 层的 GRU 网络。但是这种架构可以改变为更多或更少的层,也可以在 GRUlstm之间选择。

用于实例化 TimeGAN 4 主要组件网络的代码

这导致了每个网络元素的定义,如下面的代码片段所示。

每个框架网络的结果类示例

所有 TimeGAN 类都已实现。

就损失而言,时间由三部分组成:

  • 重建损失,指的是自动编码器(嵌入器&恢复),简单来说就是比较编码数据与原始数据相比的重建情况。
  • 简单地说,监督损失负责捕捉生成器在潜在空间中如何逼近下一个时间步长。
  • 无监督损失,这个我们已经很熟悉了,它反映了生成器和鉴别器网络之间的关系(最小-最大博弈)

给定架构选择和确定的损耗,我们有三个训练阶段:

  1. 在所提供的顺序数据上训练自动编码器以进行最佳重建
  2. 使用真实序列数据训练管理者来捕获历史信息的时间行为,最后,
  3. 四个分量的组合训练,同时最小化前面提到的所有三个损失函数。

详细说明训练阶段的完整代码可在y 数据合成中找到。

使用 TensorFlow 1 可以在这里 找到 TimeGAN 的原始实现。

合成股票数据

用于评估由 TimeGAN 框架生成的合成数据的数据,指的是谷歌股票数据。数据有 6 个时间相关变量:开盘、盘高、盘低、收盘、调整收盘和成交量。

在合成数据之前,我们必须首先确保一些预处理:

  1. 将序列缩放到[0,1]之间的范围。为了方便起见,我决定利用 scikit-learn 的minmax scaler;
  2. 创建滚动窗口——根据最初的论文建议,我创建了包含 24 个数据点重叠序列的滚动窗口。

根据原始论文中的建议,我决定对合成器进行 10000 次迭代训练,但是要记住,为了返回最佳结果,这些值必须针对每个数据集进行优化。

10000 次迭代的合成器训练

你可以在本笔记本中找到包括数据下载、处理和合成的完整流程。

测量合成数据的保真度和效用

现在我们已经能够综合我们的数据,是时候检查新数据是否能够正确地再现原始股票数据中观察到的行为了。

视觉对比

我最喜欢的比较真实数据和合成数据的方法之一是通过可视化。当然,就自动化而言,这对于验证新合成数据的质量并不理想,但它已经给了我们一个很好的想法。为了确保结果的 2D 可视化,应用了具有两个组件的 TSNEPCA

结果非常有希望,因为我们看到合成数据点和真实数据点之间几乎完美的重叠。

主成分分析和 TSNE,包含合成和真实股票数据的两个部分。

综合数据实用程序——列车综合测试真实

有很多不同的指标可以用来衡量数据的效用,如 SRA 和 TSTR

在这个例子中,我们决定采用 TSTR 方法来验证我们合成数据的效用。为了用作回归模型,我决定采用一个简单的结构,有 12 个单元的单层 GRU。

回归网络定义

在训练模型之前,我们必须准备输入:

  • 75%的数据被用作训练数据(对于合成和真实数据集)
  • 25%的真实数据被用作测试集。

对于根据合成数据训练的模型和根据真实数据训练的模型,我都使用验证集损失作为早期停止标准。下面是测试集获得的总结结果。

真实测试集上的结果

结论

该实验获得的结果在合成序列数据的生成方面是非常有前途和令人兴奋的。然而,需要指出一些警告:研究中的数据可以被认为是非常简单的,因为它相对较小,具有每日时间频率,在缺失值方面没有意外,并且维度(列方面)相对较低。更不用说,训练时间非常密集。

但毫无疑问,生成性对抗网络是令人印象深刻的框架,可以用于比合成数据生成更广泛的领域。对于那些希望继续探索合成数据生成的人,可以看看我们的 GitHub 库。我们将用新的生成算法和新的数据更新它,我们邀请你来合作!

法比亚娜 是 CDOy data

人工智能的改进和合成数据。

YData 为数据科学家提供了第一个数据集实验平台。

Instagram 系统设计分析

原文:https://towardsdatascience.com/system-design-analysis-of-instagram-51cd25093971?source=collection_archive---------1-----------------------

如何设计一个像 Instagram 这样的照片分享服务?

照片由赞·李Unsplash 拍摄

系统设计是软件工程中 最重要的 部分之一。开始设计一个系统是令人生畏的。一个主要原因是软件架构书籍中描述的术语很难理解。而且没有固定的准则。你检查的每个地方似乎都有不同的方法。对于一个新的学习者来说,它变得令人困惑。

于是,我根据自己学习建筑课程的经验,着手设计一个系统。这是初学者系统设计系列的一部分(下面给出了链接)。对于这一个,让我们设计一个类似 Instagram 的照片分享服务。

系统的定义:

我们需要明确系统的目标。系统设计是一个如此庞大的话题;如果我们不把它缩小到一个特定的目的,那么设计系统就会变得复杂,尤其是对于新手来说。

Christian Wiediger 在 Unsplash 上拍摄的照片

Instagram 是一项照片分享服务,用户可以上传照片和视频,并与其他用户分享,大多数是他们的粉丝。由于这是一个练习,我们将设计一个 Instagram 主服务的简单版本。

在这项服务中,用户可以分享照片并关注其他用户。每个用户都有一个新闻源。“新闻订阅”由用户关注的所有人的热门照片组成。

系统的要求:

在这一部分,我们选择系统的功能。系统要求分为两部分:

功能需求:

这种类型的需求是系统必须交付的。你可能会说这是系统的主要目标。

首先,对于 Instagram,用户应该能够上传/下载/查看照片。用户可以根据照片/视频标题搜索图像。一个用户可以关注其他用户。另一个重要特性是,系统应该显示用户的新闻提要,其中包含用户关注的所有人的照片。

由于这是系统的惯例,我们不考虑照片中的标签、基于标签的搜索、喜欢和评论功能等。

非功能需求

性能、可用性、一致性、可伸缩性、可靠性等。,是系统设计中重要的质量要求。我们需要分析系统的这些需求。

作为一个系统设计者,我们可能希望有一个高度可用的设计,非常高的性能,系统中一流的一致性,高度安全的系统,等等。但是不可能在一个系统中实现所有这些目标。我们需要将需求作为系统设计的限制。那么,让我们定义一下我们的 nfr:

我们的系统应该高度可用。对于任何 web 服务来说,这都是一个强制性的要求。主页生成延迟应该最多为 200 毫秒。如果首页生成时间过长,用户会不满意,这是不能接受的。

当我们选择系统的高可用性时,我们应该记住这可能会妨碍整个系统的一致性。该系统还应该高度可靠,这意味着用户上传的任何照片或视频都不应丢失。

在这个系统中,照片的搜索和浏览不仅仅是上传。由于该系统将有更多的读取操作,我们将专注于建立一个可以快速检索照片的系统。在查看照片时,延迟需要尽可能低。

数据流:

如果您不确定系统设计从哪里开始,请始终从数据存储系统开始。这将有助于使你的注意力与系统的要求保持一致。

我们需要在高层支持两个场景,一个是上传照片,另一个是查看/搜索照片。我们的系统需要一些对象存储服务器来存储照片,还需要一些数据库服务器来存储元数据信息。

定义数据库模式是理解系统不同组件之间数据流的第一步。我们需要存储用户档案数据,如追随者名单,用户上传的照片。应该有一个表来存储所有关于照片的数据。如果我们想首先显示最近的照片,我们需要索引(PhotoID,CreationDate)。数据库中的表可以是:

表格名称:表格索引 1、索引 2 等

照片:照片 ID (pk)、用户 ID、照片位置、创建日期

用户:用户标识(主键),姓名,电子邮件,出生日期,最后登录时间

跟随:用户 ID1,用户 ID2(成对 pk)

FeedItem: FeedID(pk),UserID,Contents, PhotoID ,CreationDate

  • *主键=主键

我们可以将上面的表存储在像 MySQL 这样的 RDBMS 中,因为我们需要表之间的连接。但是关系数据库也有自己的挑战。尽管跨多个服务器扩展关系数据库是可能的,但这是一个具有挑战性的过程。我们可以将照片存储在分布式文件存储器中,如 HDFSS3

当用户上传照片时,将它们存储在数据库中是一个缓慢的过程,因为它们存储在磁盘上。但是在读取的情况下,这个过程会更快,特别是如果我们从缓存中提供服务的话。

图:独立的上传和下载服务(图片由作者提供)

由于上传是一个缓慢的过程,如果我们把写和读照片放在同一个服务器上,系统可能会因为所有的“写”请求而变得太忙。在设计我们的系统之前,我们必须考虑网络服务器有一个连接限制。

假设一台服务器在任何时候最多可以有 5000 个连接。因此,它不能有超过 5000 个并发上传或下载。为了处理这种类型的瓶颈,我们可以使用责任分离

我们可以将读取和写入分成两个独立的服务。因此,我们将有一些用于读取的服务器和不同的用于写入的服务器。这种分离也将使我们有机会独立扩展每项业务。

可用性和可靠性:

我们不能丢失用户上传的照片。可靠性是这个系统的一个重要因素。因此,我们需要每个文件有多个副本。在这种情况下,如果一个服务器坏了,我们仍然有这些照片的其他副本。

我们不能在系统中有单点故障。如果我们保留一个组件的多个副本,就可以消除系统中的单点故障。为了构建一个高度可用的系统,我们需要在系统中保存服务的多个副本。因此,即使一些服务器关闭,系统也可能保持可用。在系统中创建冗余还可以在危机中提供备份。

图:可用性服务和数据库的多个副本(图片由作者提供)

可扩展性:

为了支持数百万用户,我们需要对数据库进行分区,以便将我们的数据划分和存储到不同的数据库服务器中。我们可以对元数据使用数据库分片。

基于用户标识的分区:

如果我们基于“用户 ID”划分元数据数据库,我们可以将所有用户照片保存在同一个碎片中。一个用户似乎有将近 3 TB 的数据。如果一个数据库碎片是 1TB,我们将需要每个用户的三个数据碎片。

为了更好的性能和可伸缩性,我们可以保留十个碎片。在这种情况下,我们可以通过 UserId%10 找到碎片号,并在那里存储数据。

如果用户是一个受欢迎的名人,我们可能会面临一些问题。那部分碎片会被频繁击中。

此外,一些用户可能会上传比其他人更多的照片。在这种情况下,分布可能不均匀。

更重要的是,如果我们不能在一个碎片中存储所有的用户图片,我们可能需要将照片分布到不同的碎片中。

如果一个碎片宕机,我们可能会面临用户不可用的问题。

基于 PhotoID 的分割:

另一种划分 DB 的方法是使用 PhotoID。我们需要为每张照片创建一个唯一的 ID。每个 DB 碎片都需要有其 photo iD 的自动递增序列,但是每个碎片在其部分都有相同的 photoid。我们可以给每个 photoID 加上 ShardId 这可以使 photoID 在系统内是唯一的。

负载平衡器:

由于我们使用一台服务器的多个副本,我们需要高效地将用户流量分配给这些服务器。负载均衡器会将用户请求均匀地分发到各个服务器。我们可以将基于 IP 的路由用于 Newsfeed 服务,因为相同的用户请求会发送到相同的服务器,并且可以使用缓存来获得更快的响应。

如果没有这样的要求,那么对于负载平衡器的服务器选择策略来说,循环法应该是一个简单而好的解决方案。

API 网关:

我们的系统有很多服务。有些会生成新闻提要,有些帮助存储照片,有些查看照片,等等。我们需要为所有客户提供一个单一的入口。这个入口点是 API 网关。

它将通过将请求发送到多个服务来处理所有请求。对于某些请求,它只会路由到特定的服务器。API 网关还可以实现安全性,例如验证客户端执行请求的许可。

新闻源生成:

任何用户的新闻提要都包含用户关注的人的最新、最受欢迎和相关的照片。如果我们实时生成新闻提要,那么延迟会非常高。因此,我们将尝试预先生成新闻提要。因此,邮政服务将照片存储在数据库中。新闻订阅服务为所有用户预先计算订阅源。

我们需要有特定的服务器,将不断产生用户的新闻提要,并将它们存储在数据库中。因此,当用户需要新闻提要的最新照片时,我们需要查询这个表。

图:新闻提要预计算和通知(图片由作者提供)

现在,用户如何从服务器获取最新的新闻提要呢?我们可以考虑以下方法:

拉动式方法

在这种方法中,每个用户可以定期轮询服务器,以检查是否有朋友有新的更新。服务器必须找到所有的用户连接,并检查每个朋友来创建一个新帖子。如果有新的帖子,数据库的查询将获得由用户的连接创建的所有最近的帖子,并在他们的主页上显示它们。

用户可以在规则的时间间隔之后向新闻订阅源服务器 ping 预先生成的订阅源。时间间隔越短,在提要中找到的最新数据就越多。

这种方法很费时间。由于用户定期轮询数据库,这会给数据库带来大量不必要的负载。

基于推送的方法

在这种方法中,服务器可以在新数据可用时立即将其推送给用户。用户必须维持与服务器的长轮询请求以接收更新。

由于 Newsfeed 服务正在预先生成提要,通知服务将通知活动用户关于新帖子的信息。会话数据库将保存在线用户的连接数据。

您可以在链接查看各种通知方式。

我们可以为拥有大量追随者的所有用户实现基于拉的模型。对于那些有几百个追随者的人,我们可以使用基于推送的方法。

分页:

用户的新闻源可以是一个很大的响应。因此,我们可以设计 API 来返回提要的单个页面。比方说,每次发出提要请求时,我们最多发送 50 个帖子。

用户可以在下一次发送对下一页订阅源的另一请求。在此期间,如果没有足够的提要,新闻提要可能会生成下一页。这种技术被称为分页。

结论:

为了确保系统的可用性,我们使用了服务器复制,这样当一台服务器出现故障时,其他服务器仍然可以提供服务。数据库也被复制以确保数据的可靠性。因为我们不能丢失数据。我们可以对用户新闻提要使用基于拉和推的混合方法。我们正在预计算提要,因为实时预计算需要很长时间。

资源: 系统设计面试, 视频设计 Instagram

本文是系统设计系列的一部分。这里给出了该系列的一些文章链接:

系统设计基础:缓存入门

系统设计基础知识:客户端-服务器架构

系统设计基础知识:分布式系统可用性

系统设计基础知识:负载平衡器 101

谷歌自动建议服务的系统设计

系统设计分析

TinyURL系统设计分析

设计带消息队列的通知系统

系统设计基础:缓存入门

原文:https://towardsdatascience.com/system-design-basics-getting-started-with-caching-c2c3e934064a?source=collection_archive---------5-----------------------

系统设计 101

在系统设计中什么时候使用缓存?

特尔纳瓦大学Unsplash 上拍摄的照片

系统设计是软件工程最重要的概念之一。设计系统的主要问题之一是系统设计资源中使用的术语一开始很难掌握。此外,你需要知道哪个工具或术语用于哪个问题。熟悉系统设计的基本概念和术语对设计系统有很大的帮助。

本文探讨了系统设计的一个基本主题, 缓存 。它是系统设计的基本技术之一。在几乎所有的系统中,我们可能都需要使用缓存。它是一种用于提高系统性能的技术。这个世界上没有一个系统不想拥有更好的性能。在本文中,您可能会了解它的属性和缓存技术以及缓存中数据的回收策略。

缓存:

缓存是一种硬件或软件,它存储的数据可以比其他数据源更快地检索到。缓存通常用于跟踪对用户请求的频繁响应。它还可以用于存储长时间计算操作的结果。缓存是将数据存储在与主数据源不同的位置,这样可以更快地访问数据。像负载平衡器一样,缓存可以用在系统的各个地方。

进行缓存是为了避免一次又一次地重复同样复杂的计算。用于提高算法的时间复杂度;例如,比方说动态编程,我们使用记忆技术来降低时间复杂度。在系统设计概念的情况下,缓存作为一个概念也有点类似。缓存用于加速系统。为了改善系统的延迟,我们需要使用缓存。减少网络请求也是使用缓存的一个原因。

图:图片由 作者

通常,缓存包含最近访问的数据,因为最近请求的数据可能会被反复请求。因此,在这种情况下,我们需要使用缓存来最小化从数据库中检索数据的操作。但是有不同的方法来选择哪些数据将留在缓存中。我们将在文章的后面部分讨论它。

缓存术语:

当在缓存中找到请求的数据时,这被称为缓存命中。当在缓存中找不到请求的信息时,它会对系统产生负面影响。这被称为缓存未命中。这是对糟糕设计的一种衡量。为了提高性能,我们需要增加命中次数,降低失败率。

如果主要数据源得到更新,而缓存没有更新,数据可能会变得陈旧。如果在系统中,陈旧数据不是问题,缓存可以快速显著地提高性能。假设我们正在设计一个 youtube 视频观看计数系统。如果不同的用户在 watch count 中看到不同的值,这真的没有多大关系。因此,陈旧对于这种情况来说不是问题。

客户端缓存:

可以进行客户端级缓存,这样客户端就不需要向服务器端请求。类似地,服务器也可以使用缓存。在这种情况下,服务器不需要总是访问数据库来获取数据。我们也可以在两个组件之间有一个缓存。

图:客户端缓存有助于减少网络呼叫

处理数据库压力:

使用缓存的另一个例子可以是一个流行的脸书名人档案访问。比方说,一位名人在脸书的个人资料中更新了一篇带有照片的新帖子。很多人都在查看个人资料更新。如果所有用户都请求相同的状态更新,而数据库每次都必须检索相同的数据,这将给数据库带来巨大的压力。在最坏的情况下,它可能会使数据库崩溃。在这种情况下,我们可以缓存流行概要文件的概要文件,并从那里获取数据,而不是冒着丢失主要数据源的风险。

图:许多用户请求相同的数据,这给数据库带来了巨大的压力

让我们想象我们正在用媒体写一篇文章。所以,我们有一个浏览器,它是系统的客户端,媒介是服务器。用户请求服务器写文章;然后,它被存储在数据库中。

现在,我们可以将文章存储在服务器缓存中。因此,同一篇文章有两个数据源。因此,问题是在编辑文章时,何时写入数据库,何时写入缓存。因此,我们需要了解缓存失效技术。否则,我们将获得客户端请求的陈旧数据。

缓存失效

我们通常使用缓存作为保存数据库副本的更快的数据源。在 DB 中修改数据的情况下,如果缓存包含以前的数据,那么这就称为陈旧数据。

因此,我们需要一种使缓存数据无效的技术。否则,应用程序将显示不一致的行为。由于缓存的内存有限,我们需要更新存储在其中的数据。这个过程被称为缓存失效

我们可以使缓存数据无效;此外,我们必须更新缓存中的最新数据。否则,系统将在缓存中搜索,找不到数据,并再次到数据库中查找数据,从而影响延迟。一些技术用于高速缓存数据无效。我们将在下面讨论它们:

图:缓存技术

直写高速缓存:

在这种技术中,数据被写入缓存和数据库。在将数据写入数据库之前,先用数据更新缓存。

我们将有两个优势;缓存数据将提供快速检索,因此性能会更快。由于相同的缓存数据存储在数据库中,缓存和数据库之间的一致性将保持不变。因为我们也将数据保存在数据库中,所以我们有备份副本以防系统故障。因此,数据不会丢失。

但是,在系统设计中,没有完美的技术。一个方法总有不好的一面。我们也要考虑到这一点。尽管这种技术最大限度地降低了数据丢失的风险,但是在向客户端返回成功通知之前,我们需要将数据写入两个数据源。因此,写入或更新操作将具有更高的延迟。

回写高速缓存:

这个选项有点不同,因为在其他选项中,我们将数据存储在数据库中,但在这里,数据只写入缓存。数据写入缓存后,会向客户端发送完成通知。在一段时间间隔后,写入数据库。当应用程序需要大量写入时,这种技术非常有用。并且它为这样的应用提供了低延迟。使用这种策略可以降低数据库写入的频率。

但是,正如您已经猜到的,这种性能改进伴随着在缓存崩溃的情况下丢失数据的风险。因为缓存是写入数据的唯一副本,所以我们需要小心。如果在数据库更新之前缓存失败,数据可能会丢失。

缓存放在一边:

在这种策略中,缓存与数据库一起工作,尽可能地减少对数据库的命中。当用户发送请求时,系统首先在缓存中查找数据。如果找到了数据,就把它返回给用户。不需要涉及数据库。如果在缓存中找不到该数据,则从数据库中检索该数据,用该数据更新缓存,然后返回给用户。因此,下次任何人请求相同的数据时,它在缓存中是可用的。

这种方法更适用于读取量大的系统;系统中的数据不经常更新。例如,@Medium 中的用户简档数据,如用户名、邮件 id、用户 id 等。通常不需要经常更新。

这种方法的问题是缓存和数据库中的数据可能会不一致。为了避免这种情况,缓存上的数据有一个 TTL“生存时间”。在该时间间隔之后,数据需要从缓存中失效。

通读缓存

这类似于缓存搁置策略;区别在于缓存总是与数据库保持一致。缓存库必须负责维护一致性。

这种方法的一个问题是,当用户第一次请求信息时,这将是高速缓存未命中。那么系统必须在返回响应之前更新缓存。我们可以将有机会被用户请求最多的信息预加载到缓存中。

缓存回收策略:

缓存不像数据库那样有大量的空间。此外,对于陈旧的数据,我们可能需要将它们从缓存中删除。因此,缓存回收策略是设计缓存时要考虑的重要因素。下面我们可以检查一些最常见的缓存回收策略:

  1. 先进先出(FIFO): 在这个策略中,缓存的行为方式与队列相同。缓存会清除最先访问的数据。它不考虑以前访问它的频率或次数。
  2. 后进先出(LIFO): 这是 FIFO 技术的反面。缓存会删除最近添加的数据。同样,也不考虑数据被访问了多少次。
  3. 最近最少使用(LRU): 在此策略中,缓存会丢弃最近最少使用的数据。如果数据最近没有被使用,我们假设它们被调用的机会较小,因此删除它们为缓存中更新的数据提供了选项。
  4. 最不常用(LFU): 这里,我们需要计算一个缓存项被访问的频率。那些使用频率最低的首先被丢弃。最少使用的数据是在浪费缓存空间,这是一个概念。因此,删除它们并用新数据更新缓存。
  5. 随机选择:在这里,系统从缓存中随机选择一个数据项,并在需要时将其移除以腾出缓存空间。当缓存快满时,可以使用这个策略。否则,您可能会随意删除最需要的数据项。

驱逐策略取决于您正在设计的系统。根据需求,我们可以为系统选择一个驱逐策略。

结论:

缓存是任何系统性能的关键组成部分。它确保了低延迟和高吞吐量。缓存是主数据存储的备份;它的空间有限。从缓存中检索数据比从原始数据源(如数据库)中检索数据更快。缓存可以保存在系统的所有级别,但是我们需要将缓存保存在前端附近,以便快速返回请求的数据。缓存有利于提高性能,但也有一些缺陷。在设计系统时,我们需要小心缓存数据的陈旧性。

如果数据大部分是静态的,缓存是提高性能的一种简单方法。对于经常编辑的数据,缓存的实现有点棘手。缓存将使系统能够确保系统能够更好地使用其资源。

资源:系统设计访谈,系统专家

本文是系统设计基础的一部分。这里给出了该系列的一些文章链接:

设计限速器

系统设计基础知识:客户端-服务器架构

系统设计基础知识:负载平衡器 101

谷歌自动建议服务的系统设计

谷歌驱动 系统设计分析

TinyURL系统设计分析

分布式系统中的可用性

负责任的人工智能的系统设计思想

原文:https://towardsdatascience.com/systems-design-thinking-for-responsible-ai-a0e51a9a2f97?source=collection_archive---------44-----------------------

UX 店Unsplash 上拍照

很少有裸露的 AI 系统。通常情况下,人工智能功能是作为一个更大的产品或服务提供的子组件。这种产品或服务存在于一个社会生态系统中,那里有特定的文化和背景。

因此,当考虑建立一个人工智能系统以及它可能对社会产生的影响时,重要的是采取系统设计思维方法,尽可能全面地评估影响并提出补救机制。

什么是系统设计思维?

本质上,它是考虑系统的组件与环境元素的关系,当系统被部署时,它们将与环境元素交互。这与更封闭的方法形成对比,这种方法从产品/服务将被部署的地方孤立地看待产品/服务。使用系统设计思维方法的目的是,它有助于发现隐藏的反馈循环和外部性,这些反馈循环和外部性可能会以具有道德后果的方式影响人们,如侵犯隐私和面临偏见。

系统设计思维鼓励开发人员和设计人员将系统部署的更大的社会技术背景纳入考虑范围,并规划出他们的产品/服务将如何以及在哪里直接和间接地影响这些元素。

负责任的 AI 如何做系统设计思维?

一个很好的起点是承认你不一定拥有所有的信息来将这种方法应用到你正在构建的系统中,无论是在你的团队中,或者甚至是你的组织中。但是,没关系!

解决这个问题的第一步是引入外部专家和利益相关者,比如那些具有领域专家、政策制定者等。谁能帮助你更好地阐述当你试图在目标环境中部署人工智能系统时会出现的一些挑战?那些有经验的人也可以帮助指出各种系统动态和文化特性,它们会影响你的系统的行为。

这可能需要做一些实地工作来收集人们将如何实际使用你的产品/服务的情报,而实验室并不是一个很好的代理。就现实世界中可能发生的事情而言,有太多的变量隐藏在我们的盲点中。

绘制明确包含外部元素的系统图,然后标记强化和平衡反馈循环是另一个步骤,可以帮助您更全面地阐明这些影响。

另外,要注意系统的学习部分。也就是说,注意系统在与外界交互时将学习的所有流程,这对于在系统中建立弹性非常重要,以便从安全和可靠性的角度来看,它不会偏离操作参数太远。

有哪些事情需要记住?

尤其重要的是,你要考虑系统对游戏的适应能力。这种系统将被部署在复杂、混乱的环境中,在这种环境中,对手可能会试图利用该系统来获取他们无权获得的好处,或者损害该系统的性能,从而使该系统对最需要它的人来说变得不那么高效。在这种情况下,构建能够适度降级的故障保险非常重要。

最后,牢记系统设计思想的核心思想,强调将影响系统的二阶效应和二阶输入。这些通常很难梳理出来,但是在领域专家和过去实践过这种方法的人的帮助下,您不仅可以提高系统的弹性,还可以提高其整体性能,因为您可以更好地理解您正在解决的问题以及您提出的解决方案将会产生的影响。

在这里注册接收更新 可操作的人工智能伦理书 !而你可以在这里 了解更多我的作品

您可以通过订阅 人工智能伦理简报 蒙特利尔人工智能伦理研究所 了解更多这样的见解!

功率 BI 中的 T-profile

原文:https://towardsdatascience.com/t-profile-in-power-bi-58d46b7ebed4?source=collection_archive---------30-----------------------

可视化

概念实施的介绍

字母 T 由来自名词项目的扎姆洛维奇兄弟用真正的天然花和叶子制成

T 设计 T 型轮廓的概念属于设计思维流程,该流程基于以用户为中心的设计,有助于建立用户共情,并引导寻求突破性创新。T 型简介以一种创造性的方式展示了一个人在某个特定领域的专长以及他们在其他领域的经验或知识。准确地说,T 型轮廓描述了一个人知识或技能的广度和深度。换句话说,“T”中的竖线描绘了一个人在特定领域的专业领域,“T”中的横线描绘了这个人在他的专业领域之外的其他领域的知识或经验。这样的人通常被称为具有 T 型技能的 T 型人并且具有跨领域合作的交叉技能。因此,这样的人非常适合在敏捷团队中工作[3–5]。

正如人们正确地说的那样,一张图片胜过千言万语。通常情况下,T 型简历的设计是静态的,就像任何其他简历一样。但是想象一下,如果你能以一种互动的方式设计它,最终用户可以与你的个人资料互动,同时它也变得易于维护!这最终会让它更上一层楼,这也是本文所描述的使用 Power BI 的原因。

因此,让我们快速深入了解它的实现细节,

设计 T 型型材

这是任何创作过程中最主要也是最重要的部分。为了创建我们的个人资料,我们将需要两种类型的信息,一个是垂直栏的深厚专业知识和水平栏的知识领域。

作为我们设计的一部分,我们将保持水平栏静态,并在这里使用文本框作为我们的 Power BI 报告元素。我们将以多排卡 为元素,按照初级、中级、高级、专家的等级分类的技能,进一步将竖条动态化。此外,我们将使用元素 来显示级别,这些级别将作为**多行卡**元素的过滤器。最后,我们将通过添加图像或说明性文本的形式来完成我们的设计。**

在开始实施之前,最好先设计草图,因为它是在实施过程中即兴发挥的初始起点。因此,上面的设计蓝图看起来会像这样:

使用 MS 白板的 t 型剖面设计(来源:图片由作者提供)

请记住,这个阶段是你的创造性的游乐场,你可以随时根据你的喜好或要求调整设计!

数据来源和数据处理

对于我们的输入数据,我们将不使用外部数据源,而是使用内置数据源。我们将为动态竖条创建一个输入表。

表格创建:导航到数据视图,选择输入数据**创建一个名为深度知识的表格,表格中有三列排序号、技能、级别。继续填写你在专业领域的技能,分为初级、中级、高级、专家。在分类编号栏中相应地填入从 1 到 4 的数字,每个数字代表初学者-专家的等级。我们将在后面的视图中使用这个列。最后,点击加载完成表格创建。**

表深识(来源:图片由作者提供)

数据排序:**选择排序号列,导航到列工具,点击向下箭头,选择升序排序。另外,将汇总设置为不汇总

排序排序号(来源:图片由作者提供)

对于剩下的两栏技能和等级设置排序按->-排序号****

排序技巧,水平(来源:图片由作者提供)

数据转换:您可以随时使用超级查询编辑器通过主页- >转换数据来编辑您的数据源。**您需要在这里再次对排序号列进行排序,剩下的两列会自动排序。为了编辑您的数据,您需要点击应用步骤旁边的图标。一旦完成,点击关闭&应用

数据转换(来源:图片由作者提供)

电力查询编辑器(来源:图片由作者提供)

T 型剖面的创建

导航到报告视图,从可视化窗格中选择格式** - > 页面尺寸,并将其设置为自定义 900 x 1056 。以下是设计所需的元素列表:**

报告创建元素(来源:作者图片)

****水平栏:菜单栏中选择插入- >文本框,以字母“T”的水平栏形式排列五个方块。继续输入你的技能/领域,中间部分是你的专业领域,然后你可以在垂直栏中详细说明。

我建议使用最佳数量的技能/领域,这样我们就不会过度拥挤。为了使轮廓更有创意,继续将您选择的相关 icons⁷作为插入- >图像添加到每个模块中。此外,不要忘记对你的模块进行适当的格式和颜色编码,使你的专业领域在视觉上清晰可辨。

单杠(来源:图片由作者提供)

竖条:可视化窗格中选择多行卡片**,并以字母“T”竖条的形式排列四张卡片。每张卡片都代表你在专业领域的技能,并且等级不断上升。请记住,该栏是动态的,我们将动态显示来自输入表深层知识的信息。在卡片上,从字段窗格的输入表中选择技能栏。在滤镜窗格中添加列关卡作为该视觉上的**滤镜,并选择其中一个关卡。对其余的卡重复相同的过程,在每个卡上配置不同级别的过滤器。此外,继续用不同的颜色对你的每张关卡卡片进行颜色编码,添加相关的图标,并相应地对卡片进行格式化,以与你的单杠相协调。****

竖条——带格式的初学者卡片(来源:图片由作者提供)

过滤器:要在竖条上添加过滤器,从可视化窗格中选择表格。在表格上,从字段**窗格的输入表格中选择列级别。接下来,在过滤器窗格的页面上添加列级别作为**过滤器。****

接下来,我们需要对表视图中的每一行进行颜色编码,就像我们的多行卡片一样。为此,从可视化窗格导航到字段窗格,值- >级别- >背景颜色。****

过滤表(来源:作者图片)

根据列分类编号配置以下规则,并相应地设置您定义的颜色。

过滤表格条件格式(来源:图片由作者提供)

最后,加上箭头状的形状- >六边形作为总结,为知识的宽度和深度指明方向。另外,添加一段简短的关于你自己的信息。此外,你可以将你的图标链接到你的开源作品,包括仪表盘、外部 URL,比如你的 GitHub 库、出版物等等。,以便直接向最终用户展示您提到的技能。这可以通过格式图像- >动作来完成。

图片图标上的动作(来源:图片由作者提供)

这是您的 T 型个人资料的最终外观,您可以在创建的过滤器的帮助下轻松过滤技能,该过滤器还将作为一个图例,带有便于导航的图标:

Power BI 中的 T-profile(来源:图片由作者提供)

完成后,您可以继续将您的 T-profile 发布到 Power BI service ,以便与其他人分享。在 Microsoft Docs 中,您可以探索并找到更多与其注册和许可相关的信息。或者,如果您想将其作为文档发送,您可以使用文件- >导出- >导出为 PDF** 在 Power BI 中轻松导出为 PDF。**

综上所述,本文有助于理解 T-profile 的含义和重要性,并同样展示了如何使用商业智能(BI)工具设计交互式 T-profile。使用 BI 工具之一设计您的 T-profile 直接向最终用户展示您使用该工具的实践经验,该工具具有您的 T-profile 中列出的技能/领域。由于基本思想保持不变,本文中的实现步骤是说明性的,可以根据您选择的任何 BI 工具进行相应的调整

参考

[1] 用设计思维设计商业模式

【2】丁字技能

【3】丁字技能

【4】如何留在前 1%的 T 型营销人员?(2018 版)

[5] Scrum 团队——I 型和 T 型人

[6]T 型网络营销者

[7]图标:根据知识共享署名(CC BY) 获得许可。

人工智能图标由矢量指向来自名词项目

机器学习图标由托马斯·T 从这个名词项目得来。

时间序列图标由汤姆从名词项目中获得。

数据分析图标由来自的原符号组成,名词项目

敏捷图标来自名词项目

名词项目中 Setyo Ari Wibowo 的“电子邮件营销”图标。

研究图标由名词项目的 Gregor Cresnar 创作。

数据图标由 OliM 从名词项目中获得。

网络音箱图标由 Mazil 从名词项目中获得。

咨询图标由图标标注来源于名词项目

t-SNE 机器学习算法 Python 中降维的利器

原文:https://towardsdatascience.com/t-sne-machine-learning-algorithm-a-great-tool-for-dimensionality-reduction-in-python-ec01552f1a1e?source=collection_archive---------2-----------------------

机器学习

如何使用 t 分布随机邻居嵌入(t-SNE)来可视化高维数据?

t-SNE 可视化与不同的困惑。Gif 图片由作者提供。

介绍

一个成功的数据科学家了解广泛的机器学习算法,并能向利益相关者解释结果。但是,不幸的是,并不是每个利益相关者都有足够的培训来理解 ML 的复杂性。

幸运的是,我们可以通过使用降维技术创建高维数据的可视化表示来帮助我们的解释。本文将带您了解一种叫做 t-分布式随机邻居嵌入(t-SNE)的技术。

内容

  • t-SNE 在机器学习算法领域的地位
  • 对 SNE 霸王龙工作原理的直观解释
  • 在 Python 中使用 t-SNE 的例子

机器学习算法领域中的 t 分布随机邻居嵌入(t-SNE)

由于特定算法表现出的灵活性,机器学习技术的完美分类并不总是可能的,这使得它们在解决不同问题时非常有用(例如,可以使用 k-NN 进行回归和分类)。

尽管如此,给 ML 世界带来一些结构仍然是有益的,下图就是我试图做的。请确保通过点击来浏览此互动图👇对各种类别进行放大,揭示更多的

机器学习算法分类。由作者创建的交互式图表。

如果你喜欢数据科学和机器学习 ,请 订阅 每当我发布一个新的故事,你都会收到一封电子邮件。

如你所见,t-SNE 是一种降维技术,属于机器学习算法的无监督分支。这意味着我们不需要标记数据来使用它。这与监督技术如线性鉴别分析(LDA)形成对比。

虽然上面没有说明,但值得一提的是,降维可以进一步分为两种类型:

  • 参数 —创建一个显式映射函数,我们可以在测试数据上使用该函数,也就是说,用它来获得低维嵌入中新点的位置(如 PCA);
  • 非参数化 —不创建显式映射函数;因此,它不能容易地将新的点映射到低维嵌入。尽管在实践中,有可能构建一些变通办法来实现新点的这种映射。

t-SNE 属于一组非参数技术。因此,它的主要用途通常是可视化。

t 分布随机邻居嵌入(t-SNE)是如何工作的?

分析 SNE 霸王龙的名字

让我们从剖析 t-SNE 的名字开始,这将让我们对算法应该做什么有一个大致的了解。我们将反向进行(即从右到左)。

注意,下面的陈述不是官方的定义,而是一组帮助我们理解 SNE 霸王龙背后的关键思想的描述。

  • 嵌入 —典型的高维数据在低维空间中表示;
  • 邻居 —位于感兴趣的数据点附近的数据点;
  • 随机—当搜索代表性嵌入时,在迭代过程中使用随机性;
  • t 分布 —算法用来计算低维嵌入中相似性得分的概率分布。

将上述陈述放在一起,我们可以将 t-SNE 描述为一种技术,该技术利用渐进迭代方法来寻找原始数据的低维表示,同时保留关于局部邻域的信息。

请注意,对于该算法的一般理解,您不需要太注意概率分布元素。t 分布用于下面描述的步骤 2 和 3,之所以选择 t 分布而不是正态分布,是因为它具有“更平”的形状和“更高”的尾部。这种形状有助于在低维空间中展开点。否则,你可能会得到一堆相互叠加的点。

SNE 霸王龙采取的步骤

第 1 步 t-SNE 首先根据点与点之间的距离确定点的“相似度”。附近的点被认为是“相似的”,而远处的点被认为是“不相似的”

它通过测量感兴趣的点和其他点之间的距离,然后将它们放置在正常曲线上来实现这一点。它对每个点都这样做,应用一些缩放来考虑不同区域的密度变化。

例如,下图中蓝色点所在的区域密度较高,黄色点所在的区域密度较低。

相似性得分。图片由作者提供。

这些计算的结果是一个矩阵,该矩阵包含来自原始多维空间的每对点之间的相似性得分。

相似矩阵。图片由作者提供。

第二步
接下来,t-SNE 将所有点随机映射到一个低维空间,并按照上述过程计算点之间的“相似度”。不过,这一次有一点不同,该算法使用了 t 分布而不是正态分布。

不过,不出所料,由于随机映射,新的“相似度”矩阵与原始矩阵有很大不同。这是一个可能的例子。

一个新的“相似度”矩阵的例子。图片由作者提供。

第三步 现在算法的目标是通过使用迭代方法使新的“相似度”矩阵看起来像原始矩阵。随着每一次迭代,点从最初的高维空间向它们的“最近邻居”移动,并远离远处的邻居。

新的“相似度”矩阵逐渐开始看起来更像原始矩阵。该过程继续进行,直到达到最大迭代次数,或者不能进行进一步的改进。

用更科学的术语来说,上面的解释描述了一种算法试图通过梯度下降来最小化 kull back-lei bler 散度(KL 散度)的过程。

困惑

我还没有提到的一个重要方面是一个叫做困惑的超参数。它描述了每个点周围的预期密度,也就是说,与感兴趣点的目标最近邻数相关。

困惑参数在决定嵌入的最终结果中起着至关重要的作用。一般来说,您可能希望选择介于 5 和 50 之间的困惑度,但是您应该尝试不同的值。

在本文的开始,我包含了一个 gif 图像来演示当使用不同的困惑值时,最终的可视化效果是如何变化的。较低的值会使算法“关注”较少的邻居,从而产生许多小组。相比之下,高困惑值“扩展了邻域范围”,导致更少、更紧密的组。

如何在 Python 中使用 t-SNE?

最后,我们很好地理解了算法,所以是时候在 Python 中使用它了。

我们将在 MNIST 数据集(手写数字的集合)上应用 t-SNE 来说明我们如何成功地可视化高维数据。

设置

我们将使用以下数据和库:

第一步是导入我们上面列出的库。

接下来,我们加载 MNIST 数据。

导入数据的形状。图片由作者提供。

现在,让我们显示前十个手写数字,以便更好地理解我们正在处理的内容。

前十个手写数字的图像(8×8 = 64 像素,即 64 维)。图片由作者提供。

将 t-SNE 应用于我们的数据

在上一步中,我们将数据加载到形状为(1797,64)的数组 X 中,这意味着我们有 1,797 个数字,每个数字由 64 个维度组成。

我们现在将使用 t-SNE 将维数从 64 降低到 2。注意,我对大多数超参数使用默认值。然而,我也包括了每个参数的简短解释,以便您可以通过尝试不同的设置来进行实验。

上面的代码打印了一些基本的统计数据:

我们植入 t-SNE 的基本数据。图片由作者提供。

最后,让我们在二维散点图中绘制新的 X 数组。请注意,我们还使用颜色来表示数字的实际标签。这有助于我们了解相似的数字如何聚集在一起。

64 维 MNIST 数字数据的 2D t-SNE 嵌入。图片来自作者

我们可以看到,SNE 霸王龙在识别相似的数字方面做得非常好,它们中的大多数形成了紧密的群体。然而,有几个小星团,即 1(红色)、3(紫色)和 9(黄色),似乎离它们的主星团相当远。这样的结果可能表明存在书写相同数字的不同方式。

结论

t-SNE 是一个很好的工具,可以可视化不同数据点之间的相似性,这可以在多方面帮助您的分析。

例如,它可以帮助您找出书写相同数字的不同方式,或者使您能够在执行 NLP 分析时找到具有相似含义的单词同义词/短语。同时,在向利益相关者解释您的分析时,您可以使用它作为视觉辅助。

然而,与每一种机器学习方法一样,t-SNE 也有一些限制,你在使用它时需要记住:

  1. 它是一种非参数的降维方法,这意味着它不会创建一个显式的映射函数供您在新的数据点上使用;
  2. 您可能需要试验不同的困惑值,以找到最适合您的数据的值;
  3. 由于其随机初始化和随机性,每次运行后您可能会得到不同的结果。如果您想要可重复的结果,请确保指定一个种子(random_state)。

我真诚地希望这篇文章给你一些新的见解 t-SNE 和帮助你扩大你的 ML 武器库。如果你有任何问题或建议,我很高兴收到你的来信。

干杯👏
索尔·多比拉斯

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:

https://solclover.com/membership

您可能感兴趣的其他文章:

Tableau + Salesforce —绝配(?)

原文:https://towardsdatascience.com/tableau-salesforce-a-perfect-match-761895a430f0?source=collection_archive---------14-----------------------

这篇文章调查了您应该如何以及为什么利用 Tableau 中的 Salesforce 数据,以及 Salesforce 收购 Tableau 后的协同效应。

Unsplash 上由 Belinda Fewings 拍摄的照片

(你也可以在 我的网站 上找到这篇文章以及其他文章和更多有趣的东西)

介绍

本文的目的是对如何利用 Tableau 和 Salesforce 之间的协同作用给出一个“简短”的解释。和往常一样,这篇文章试图抓住我在开始使用这些工具之前想知道的事情。

在文章的最后,您可以找到参考资料来了解更多关于该主题的信息,以便能够在实践中使用该主题。

大多数阅读这篇文章的人可能听说过工具 Tableau 和 Salesforce,这是数据可视化**和 CRM 世界中最流行的两个工具。**

自 2019 年收购 Tableau 以来,Tableau 归 Salesforce 所有,这可能也是相当普遍的知识。如果没有,现在你知道这两个工具之间的关系是什么样子了。

但是,如果上面的两个方面被广泛传播,第三个方面可能就不太为人所知了,这将是这篇博客文章的主要讨论点之一,也是为什么我认为市场上需要它,更确切地说:

Tableau 和 Salesforce 之间的协同作用如何,您如何在另一个工具中利用一个工具?

这篇文章将讨论三个要点,希望能让你对如何(以及为什么)利用 Salesforce 和 Tableau 有所了解。让我们看看今天的议程。

照片由丹尼斯·詹斯Unsplash 上拍摄

  1. 从 Tableau 访问您的 Salesforce 数据有哪些不同的方式?
  2. 为什么在 Tableau/sales force 的主要限制中可视化您的数据?
  3. 如何在 Salesforce 中利用 Tableau 仪表盘?

1.从 Tableau 访问您的 Salesforce 数据的三种方式

israel palacioUnsplash 上拍摄

在 Tableau 中使用 Salesforce 数据的第一步是以某种方式从 Salesforce 访问数据。在讨论 Salesforce 的局限性以及如何将 Tableau 可视化嵌入到 Salesforce 之前,首先讨论这一点似乎是一个自然的途径。

本文将介绍如何从 Tableau 中访问 Salesforce 数据的三种一般方法。下面列出了每种数据访问方式的优缺点。需要注意的是,每一步的复杂性都在增加,但好处也在增加。

(利弊只与数据的连接有关,不包括本文下一章的利弊。因此,如果一个连接(如 Salesforce Connector)有“3 个优点和 3 个缺点”,那么 Tableau 中关于可视化的所有优点都将添加到这个连接中,从而使其成为“净正面”。)

i)将 Salesforce 的摘录转换成 Excel、CSV 格式或 Google Sheets ,然后将其中的数据放入 Tableau。

(赞成:1,反对:3)

照片由米卡·鲍梅斯特Unsplash 上拍摄

优点

  • 在某种程度上,这可以被视为使用数据的最不复杂的方式。大多数人在日常工作中非常熟悉使用 Excel、或类似的报告工具。因此,这似乎是这些人利用这些工具连接到 Salesforce 的“正常方式”,这也是使用这些连接器的主要优点。

缺点

  • 使用上述报告工具时的常见问题是,手动负担相当大,这次也不例外,例如,您是否设置了到工作表的连接(如果您想使用 Tableau)以及控制,以便如果您将来想再次使用它,工作表不会发生任何特定的变化。
  • 每次您想要获得 Salesforce 数据并在 Tableau 中使用它时,您还需要手动下载和提取,这意味着许多手动时间可以自动化,这就是为什么大多数人后来可能会被下面的选项所吸引。
  • 如果您想通过 Salesforce Cloud Connector 访问数据并利用 Tableau 中的数据,您将需要一个 Salesforce 帐户和一个 Tableau 帐户。如果您只想处理数据,而不是亲自进入 Salesforce,这可能不是最佳选择。

ii)使用 Salesforce 云连接器从 Tableau 直接连接到 sales force

(赞成:3,反对:3)

照片由亚历山大·奈特Unsplash 上拍摄

优点

  • 利用 Tableau 的直接连接器连接到 Salesforce 数据的好处之一是大大减少了前一步的手动负担。如果您将数据发布到 Tableau Server/Online,数据会自动刷新,这将在下面讨论。
  • 使用 Salesforce 连接器的另一个好处是 Salesforce 已经创建了现成的连接 Salesforce 表,您可以在 Tableau 中直接使用。这一点很重要,将在后面关于 Tableau 和 Salesforce 之间的协同作用的章节中讨论。
  • 您还可以利用 Salesforce Starters ,它们是很好的现成报告,将在后面的章节中解释。

缺点

  • 这比使用 Salesforce 数据的第一种方式稍微复杂一些。如果您想对数据进行任何操作,或者如果有些东西工作不正常,那么了解一点 SQL 或查询语言(尤其是连接)会很有帮助。
  • Salesforce 云数据的布局是为支持 CRM 应用程序而组织的,不是为诸如 Tableau 之类的报告工具而组织的,这导致了数据处理的一些限制。
  • 如果您想通过 sales force Cloud Connector to Tableau 访问数据,您将需要一个 Salesforce 帐户以及一个 Tableau 帐户。如果您只想处理数据,而不是自己在 Salesforce 中工作,这可能不是最佳选择。

iii) 将 Salesforce 集成到数据湖/数据仓库中,并从那里访问数据。

(赞成:4,反对:2)

菲利普·施奈德巴赫在 Unsplash 上的照片

优点

  • 数据在数据湖(Dara Warehouse 或您选择保存数据的其他应用程序)中被直接刷新,在指定数据的布局方面有更多的自由度。****
  • 可以在数据湖中直接合并不同数据源的数据。
  • 另一个好处是,数据对于希望利用这些数据的人来说更容易获得,因为您不需要 Salesforce 帐户,如果您希望在其他两个示例中直接利用这些数据,则需要 sales force 帐户。
  • 最后,如果有人使用许多不同的 BI 工具,如果您在 Tableau 中使用 Salesforce Cloud connector,他们将无法使用任何数据。如果数据被转移到一个公共的数据集市,那么使用不同的工具连接数据就有了更多的自由。

缺点

  • 其中一个主要的缺点当然是数据湖或数据仓库的设置,以及将 Salesforce 集成到这个平台中。当然,这是一个比直接连接到 Salesforce 更复杂的过程,这可能是为什么利用 Salesforce Cloud Connector 或将 Salesforce 数据下载到 Excel 的选项在当今实践中仍然流行的主要原因。
  • 除此之外,如果你想在 Tableau 服务器中建立仪表板,当然还有 Tableau 帐户的费用。

2.为什么要在 Tableau/sales force 的主要限制中可视化数据?

Tetiana SHYSHKINA 在 Unsplash 上的照片

现在让我们深入了解一下为什么您希望使用 Tableau 作为可视化工具而不是在 Salesforce 中完成所有的可视化工作。以上段落中的所有不同连接器在从 Tableau 中的 Salesforce 访问数据的方式上都有一些缺点。

将数据从 Salesforce 转移到 Tableau 的好处是否足以抵消坏处?

(在指出下面的原因之前,先假设 Tableau 许可证不仅用于可视化 Salesforce 数据。如果是这样的话,成本会比你的公司已经有 Tableau Server/Online,并且你还使用 Tableau 许可来创建其他可视化效果要高得多。)

看下面的两个可视化,然后阅读为什么我更喜欢 Tableau 可视化而不是 Salesforce 中的可视化数据:

Salesforce 仪表板— Elias Nordlinder

Tableau 仪表板— Elias Nordlinder

i)你的设计师大脑在画面上的限制要少得多,有无限的可能性

  • 上面是 Salesforce 数据的两种不同的可视化,第一种在 Salesforce 中,第二种在 Tableau 中。(您可以在我的 Tableau 公众页与上面的 Tableau 仪表盘互动,此处)
  • 对我来说,我真的很喜欢可视化的设计,在 Tableau 中有更多的可能性和自由来处理数据。自过去几年以来,Salesforce 可视化已经取得了长足的进步,它们比许多其他应用程序更好,随着 Tableau 的收购,这些应用程序现在可能会有更大的改进,但它们还没有达到 Tableau 的水平。
  • 在 Tableau 中创建可视化效果的唯一限制是你的创造力。如果你想到你想做的事情,很有可能其他人已经在 Tableau 中做了,然后你可以逆向工程他们的仪表板,用你的数据做同样的事情。

ii)易于使用计算字段和参数快速重塑数据,并在其他仪表板中重用。

  • Tableau 中的另一个很大的可能性是,当您想要深入某个特定方面时,可以使用动态创建计算字段或参数或者为您的仪表板创建新的过滤器。
  • 您还可以将其他报表中的高级计算字段复制并粘贴到您的 Salesforce 报表中,并利用它们在其中的构建方式。

iii)利用其他表格报告的经验

  • 通过利用关于如何从其他 Tableau 报告中构建仪表板的经验,您当然可以利用这些经验来构建连接到 Salesforce 的仪表板。

iv)“免费观看可视化效果”

  • 如果我们假设您的公司已经拥有 Tableau Server 或 Tableau Online 的帐户,公司中的每个人都可以免费看到这些报告。他们需要一个 Salesforce 帐户才能在 Salesforce 中查看他们现在不需要的报告。

v)将数据连接到其他数据源

  • 如前几章所述,您需要将数据移动到数据仓库或数据湖中,以便能够将数据连接到其他数据源。这并不完全正确,因为当然也有可能在 Tableau 中直接混合数据,这意味着您可以直接将其他数据源与您的 Salesforce 数据合并。

vi)利用 Tableau Salesforce Starters

  • 最后,还必须对的销售人员首发大声疾呼。这些是 Tableau 创建的入门仪表盘,可以在这里免费下载
  • 通过使用 Salesforce Cloud connector 连接到您的 Salesforce 帐户,您可以自动获得带有您的 Salesforce 数据的 17 个预构建 Tableau 仪表板以供进一步探索和构建。这是一个很好的方式来获得灵感,如何利用您的数据,并监控它的未来。

你必须自己权衡这五点与前几章提到的缺点,没有放之四海而皆准的方法。但我希望这能提供更多信息,说明为什么要将数据从 Salesforce 转移到 Tableau。

3.如何在 Salesforce 中利用 Tableau 仪表板?

照片由劳伦提乌·约尔达切Unsplash 上拍摄

前面解释过的 Salesforce 的一些主要限制是数据不能很好地与来自其他来源的数据融合并且缺少特定的报告工具。这个问题的解决方案是将数据传输到 Tableau,利用前面段落中的所有 Pro。

但是,如果您想利用 Tableau 中所有这些令人惊叹的方面,但不是真的想将仪表板移出 Salesforce,该怎么办呢?答案是您现在可以"将这些 Tableau 报告移回 Salesforce。"这是 Tableau 和 Salesforce 合作的巨大成果。

将 Tableau 仪表板移动到 Salesforce 中称为嵌入。更多信息可以在 Tableau 帮助文档Tableau 的这个视频中找到,但我会在下面简单解释一下。

  • OBS —所需权限:为了能够使用 Tableau Lightning Web 组件,您需要在 Salesforce 中拥有管理员或开发人员权限
  • AppExchange - >设置- >编辑页面:要将 Tableau 数据移入 Salesforce,您可以使用 Tableau Viz Lightning 组件,该组件可从 Salesforce AppExchange 下载。如果你点击右上角的“设置”,然后点击“编辑页面”,你将进入可以嵌入 Tableau 视图的地方。
  • Tableau Viz Lightning: 您现在可以将 Tableau Lightning 组件拖到您正在编辑的页面的画布上,见下图。您可以使用 Tableau Viz Lightning 组件嵌入来自 Tableau Public、Tableau Server 或 Tableau Online 的视图。

Lightning Web 组件的表格展示快照

  • 现在您已经将 Tableau 视图直接嵌入到 Salesforce 中。除了添加视图来自哪个 URL 和视图的高度等正常功能,还有一些非常酷的组件也包括在内。一个是您可以根据您在 Salesforce 中查看的 Salesforce 记录过滤 Tableau 视图以及添加新字段以过滤 Salesforce 内部。

结论

本文的目标是对如何将数据从 Salesforce 连接到 Tableau、为什么您想这样做以及如何将数据从 Tableau 连接回 Salesforce 进行“简短”介绍。下面是每章的简短结论。

从 Tableau 访问您的 Salesforce 数据的不同方式?

  • 在 Salesforce 中有许多不同的方法来访问数据。如果您想让它不那么复杂,但又有更少的好处/更多的手工操作,您可以将数据下载到 Excel。稍微复杂一点的是在 Tableau 中使用 Salesforce 连接器,但是它有自动刷新数据的好处。第三种方式是将数据集成到数据仓库/数据湖中,消除了 Salesforce 许可的成本,并使得使用除 Tableau 之外的其他 BI 工具成为可能。

为什么要在 Tableau/sales force 的主要限制中可视化数据?

  • 通过在 Tableau 中可视化数据,与在 Salesforce 中相比,您有更多的创作自由和选择。您可以轻松创建计算字段,参数利用您在其他仪表板中使用的最佳实践您还可以利用Tableau Salesforce Starters来帮助您开始可视化 sales force 数据的旅程。

如何在 Salesforce 中利用 Tableau 仪表盘?

  • 如果您有管理或开发权限,您可以利用 Salesforce AppExchange 的 Tableau Viz Lightning 。当您在 Salesforce 中编辑页面时,您可以添加一个带有 URL 的 Tableau 视图,甚至可以根据您在 Salesforce 中查看的内容过滤此 Tableau 视图,太棒了!

我希望结合使用 Tableau 和 Salesforce 的这三个方面能够给你一些提示,告诉你如何在你的组织内部利用这些工具。如果您想讨论任何关于此数据或其他数据的具体问题,请联系我!

参考

文章

Tableau: 将 Tableau 视图嵌入 Salesforce
Tableau:Tableau Viz Lightning web 组件:将 Tableau 分析引入 sales force 的新方法
Senturus:Tableau Dashboard Sarters for sales force—18 条经验教训

其他

Tableau 即闪电:sales force App Exchange

Youtube

Senturus:sales force 的 Tableau 仪表板启动器

感谢您的阅读

非常感谢你阅读我的博客!

请在下面发表您对内容的看法,或者想讨论与 Tableau 和 Salesforce 相关的内容。

我很想听听其他人是如何看待这些事情的。

如果你喜欢阅读我的故事,并愿意支持我成为一名作家,可以考虑使用这个链接注册成为一名媒体会员,我可以赚取一小笔佣金,不需要你额外付费。

问题或询问

如果您有任何问题或建议,请联系我

领英:www.linkedin.com/in/elias-nordlinder
邮箱:Elias.Nordlinder@gmail.com
网页:eliasnordlinder.com

祝大家这周过得愉快

Tableau 与 Python 构建 COVID 跟踪器仪表板

原文:https://towardsdatascience.com/tableau-vs-python-building-a-covid-tracker-dashboard-b920c70202d3?source=collection_archive---------27-----------------------

构建简单 Tableau 仪表板的教程

作者为博客的视频版本制作的缩略图。

我没有在我的数据科学工作中使用 Tableau,但我做了几个迷你项目来检查界面和宣传的内容。昨天(2021 年 3 月 13 日),我决定用 Tableau 创建一个完整的仪表盘。

为了能够比较仪表板的构建简易性、耗时和质量,我选择构建世界上新冠状病毒病例的仪表板,因为我使用 Python、Jupyter Notebook 和 Voila 构建了一个类似的仪表板来显示 COVID 病例。

本快速教程的先决条件

没什么大不了的,只要确保你有 Tableau public 安装。为了更好地理解这两种方法之间的明显区别,即使用编程构建仪表板与使用 Tableau 构建仪表板,只需浏览一下我在 Jupyter Notebooks 上发表的关于构建新冠肺炎交互式仪表板的文章,或者在这里观看视频

你可以在这里查看我的基于 Python 的仪表盘。

让我们开始构建…

数据源

鉴于我们所选话题的严肃性,第一步是找到一个可信的数据来源。

为此,我们将利用约翰·霍普金斯大学系统科学与工程中心(CSSE)的新冠肺炎数据库

该网站由该大学的一些投稿人维护,并定期更新。

有许多不同类型的数据集,但为了简单起见,我们将使用特定国家的数据,为我们提供不同类型的最新数量(活动、已确认、死亡、已恢复等)。)世界不同国家/地区的案例。

以下是该文件的原始链接:

[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/web-data/data/cases_country.csv](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/web-data/data/cases_country.csv)

它是一个 CSV 文件,如下所示:

图片由作者使用此链接

将数据加载到 Tableau

将数据加载到 Tableau 有几种方法,包括:

  • 从本地机器上传文件 Excel、CSV、text、JSON、PDF、Spatial 等。
  • 连接到存储在服务器上的数据—您可以直接从 Tableau Server、Google Cloud Storage/Analytics、MS SQL server 等加载数据。
    您可以使用现有的数据连接器。
  • 您也可以连接到以前连接过的信号源。

在我们的例子中,我们希望将 GitHub 上的原始 CSV 文件直接加载到 Tableau,为此,我们可以使用 Keshia Rose 开发的 CSV web 数据连接器

作者图片

链接到连接器:https://basic-csv-wdc.herokuapp.com/

以下是加载数据的步骤:

  • 在连接窗格下,点击**Web Data Connector**
  • 在弹出的字段中添加连接器 URL 并点击Enter

作者图片

  • 现在,在搜索字段中添加原始 CSV 文件的链接,并点击**Get Data!**

加载数据需要几秒钟,然后您可以点击Update now查看文件中的可用数据:

作者图片

探索数据

Tableau 以非常直观的方式呈现数据。我们可以从预览和元数据中了解数据的基本属性及其类型。

从预览中,我们可以找到数据集中的特征,这些特征进一步定义了我们有兴趣回答的关于手头问题的问题。

从元数据视图中,我们可以找到这些特征的数据类型(分类/定量/日期时间等),这些数据类型告诉我们如何结合其他特征来分析这些特征。

单击元数据视图会显示列及其名称和类型:

作者图片

了解要素的含义及其数据类型非常重要:

如何找到变量的数据类型——用符号表示。
**#** —表示数值数据类型。
**Abc** —表示分类/字符串数据类型。
🌐 —表示地理值。
除了这些,我们还有日期时间、集群和布尔符号。

这应该让我们对这个数据集能做些什么有所了解。

由于数据已经被清理和格式化,我们可以跳过争论的部分,继续定义我们想要从这个分析中得到什么。

那么,让我们进入下一步。

基于列定义问题

根据我们所拥有的功能及其数据类型,我们可以回答以下简单的问题:

  • 就病例总数(活跃、确诊、死亡)而言,目前世界上 COVID 病例的情况如何?
  • 国家的现状是怎样的——如果我们能在一个框架内将它形象化?
  • 就病例数和死亡率而言,哪些国家受影响最大?

您可以添加/定义更多/不同的问题,但现在我将带您浏览这些问题。

是时候认真回答这些问题了。

Tableau 界面

下面是 Tableau 界面的快速浏览。

→在底部,您会看到有许多图标,它们是为了:

作者图片

  • 检查连接的数据源
  • 添加新工作表
  • 添加新仪表板
  • 添加新故事。

→点击默认情况下为我们创建的第 1 页。

作者图片

在上图中,我只标注了界面的重要部分。大多数分析都是通过将要素拖放到列和行中来完成的。

创建可视化

我们现在将迭代每个问题,并创建一个专用表来分析数据,以便回答这个问题。

案例总数第一

为了回答这个问题,我们将利用以下几个栏目:

  • 确认的
  • 死亡
  • 活跃的

现在,Tableau 知道这些是定量的度量,只要您尝试拖放其中的任何一个,它就会添加一个默认的聚合器(在本例中是 SUM)。您可以使用标记随时更改聚合器。

要直观显示案例的总数,只需拖动上述每个功能,并将其放在顶部的列字段中。

作者图片

在任何时候,如果出现任何问题,您都可以使用Cmd/Ctrl + z来撤销。

此外,您可以使用左窗格中的标记来更改每个条形的颜色。

您还可以通过右键单击想要格式化的数据可视化来试验字体、文本颜色、阴影等。

这是我的格式化可视化在一些改变(颜色和宽度)后的样子。

格式化后—按作者排序的图像

→对于我们付出的努力来说,已经足够好了。编写这个需要更多的时间。

太棒了,让我们继续下一个。

#2 显示每个国家/地区 COVID 病例的世界地图

因为我们在数据中有地理空间维度,我们可以在世界地图上绘制数字,以可视化每个国家的情况。

我将使用纬度和经度(生成的)列在世界地图上绘制病例数(确诊、活跃和死亡)。这些是由 Tableau 从 Lat/Long 变量生成的。这些在“表格”窗格中以斜体显示。

步骤:

  • 第一步是通过点击Sheet 1旁边的图标添加新的工作表
  • 拖动经度(已生成)并将其放入列中
  • 拖动纬度(生成),逐行拖放。这样做之后,你会在主视图中有一个空白的世界地图。
  • 要添加国家名称,请将Country Region列放在标记窗格的详细信息框中。这样做将在工具提示中显示带有国家名称的符号地图。
  • 现在,我们在右上方有一个Show Me窗格,向我们显示所有您可以使用的可视化效果。灰色的图表不适用,当您将鼠标悬停在这些图表上时,它会告诉您需要哪些类型的列来使该图表适用。对世界地图这样做,你会了解到我们至少需要 1 个地理空间维度,0 个或更多维度,以及 0 个或 1 个度量。
  • 是时候添加度量了,即我们想要可视化的变量。我在选择确诊病例的数量。将确认列拖放到标记窗格中的标签框上。

如果您想将其他变量添加到细节框中,也可以将它们添加到细节框中。

以下是我的符号地图的外观:

作者图片

您可以随意使用另一张地图,添加颜色,或者设置您想在地图上看到的内容的格式。

#3 受影响最严重的国家

总人数和世界地图只能给你一个疫情的简要概述。所以,让我们再深入一点,看看哪些国家在确诊病例、死亡人数、死亡率方面受影响最大,哪些国家恢复率高。

这些很容易绘制。以下是步骤:

  • 添加新工作表。
  • Country Region功能拖放到列中。
  • SUM(Confirmed)拖放成行。您将在主视图中看到一个条形图,X 轴表示国家,Y 轴表示确诊病例数。
  • 因为我们应该查看受影响最严重的国家,所以我们需要对数据进行排序,Tableau 使我们很容易做到这一点。我们所需要做的就是点击顶部任务栏中的Sort descending图标。
  • 随着所有的棒线按降序排列,我们现在只想挑选几个高于某个阈值的,或者说前 10 个。将光标保持在点击状态,并将其拖动到您想要列入候选名单的钢筋数量上。
  • 将鼠标悬停在入围栏上,并在出现的弹出窗口中单击仅保留。这会给你一个整洁的图表。
  • 您可以从任务栏打开标签或将 SUM(已确认)放到标签框中。

同样,您可以添加颜色、格式、注释,等等。

以下是我使用上述步骤创建的图表:

作者图片

不要忘记根据它们的使用情况重命名您的工作表。

用这些表创建仪表板

有了足够的可视化效果和数字,我们现在可以将它们全部显示在一个屏幕上,从而创建一个快速的交互式仪表盘。

这最后一步非常简单,你需要做的就是点击底部的New Dashboard图标。

这将创建一个空的仪表板视图,提示您从左侧窗格中删除要在仪表板中显示的工作表。

作者图片

您可以将工作表拖放到仪表板上,然后定位它们,使您的仪表板看起来更有洞察力和吸引力。

这是我最后的仪表板:

作者图片—https://public.tableau.com/profile/harshit.tyagi#!/viz home/covid _ book/dashboard 1

如果您想要对任何可视化进行更改,您可以返回到该表,更改将自动反映在仪表板中。

共享您的仪表板

您可以创建自己的个人帐户,将所有更改保存到 Tableau 公共服务器上的笔记本/仪表板中。

保存仪表板将创建一个公共链接,您可以与您的分析师同事、合作者或朋友共享。

你可以在这里看我的仪表板:

https://public.tableau.com/profile/harshit.tyagi#!/viz home/covid _ book/Dashboard

结论

在使用 Tableau 构建了这个仪表板,并将其与我使用 python 和 jupyter notebook 创建该仪表板所花费的工作量进行了比较之后,我尝试在不同的指标上对这两种方法进行评分,5 分表示最好,1 分表示最差:

一个有趣的比较——分数是根据我在每个方面的经验给出的。

Tableau 显然是这里的赢家!

我可以说,Tableau 似乎是一个明智和省时的选择,至少对于这些类型的场景是如此。

同样,这是我基于我的经验的个人观点,你应该选择最适合你的用例的。

Liveproject

如果你想做一些类似但先进的东西,你应该看看我在 Manning 上的直播项目。

引文:

[1]: Dong E,Du H,Gardner L .一个基于 web 的交互式仪表盘,用于实时跟踪新冠肺炎。柳叶刀新闻杂志。20(5):533–534.doi:10.1016/s 1473–3099(20)30120–1

本博客视频版!

用 TabPy 制作你的时间序列预测表!

原文:https://towardsdatascience.com/tableau-your-time-series-forecast-with-tabpy-5c09c151477f?source=collection_archive---------5-----------------------

用 Tableau 的速度洞察来补充您的预测!

Julian Hochgesang 在 Unsplash 上拍摄的照片

欢迎观看一个简短(希望如此)的演示,演示如何使用 TabPy 将数据科学模型与 Tableau 集成在一起。在这个故事中,我们将特别关注时间序列预测。

我们将使用三个时间序列模型,这些模型是使用 superstore 数据集(零售业数据)在 python 中构建的。我们将使用 Jupyter notebook 构建我们的 python 代码,然后继续学习 Tableau。

本文旨在展示如何将一个模型与 Tableau 的分析扩展相集成,并使其无缝用于消费。

为什么是 Tableau?好吧,我喜欢它,我不能强调它是多么容易探索你的数据。

让我们先来看看数据:

我们只保留日期和销售额列,用于构建时间序列对象。以下代码按升序对销售数字进行排序,并按月对数据进行聚合。

#fetching required columns
data = superstore[[‘Order Date’,’Sales’]] 
data = data.sort_values(by = 'Order Date')#creating a ts object
data['Order Date'] = pd.to_datetime(data['Order Date'])
data.index = data['Order Date']
data = data.resample('M').sum()

我们准备好可视化时间序列:

import matplotlib.pyplot as plt
import seaborn as snsplt.subplots(figsize = (17,7))
sns.lineplot(x = “Order Date”, y = “Sales”, data = data)
plt.show()

以上是我们的时间序列图。时间序列有三个重要组成部分:趋势、季节性和误差。我们可以将该系列视为“加法模型”或“乘法模型”,这取决于该系列的性质和我们假设的假设。我将把模型构建和预测方法放在的下一篇文章中,作为这篇文章的延续,在这篇文章中,我们将涵盖不同的技术、分解、平稳性测试、自相关和部分自相关因子以及模型总结。

现在,在我切换到 Tableau 之前,我将分享我为最终确定模型而编写的代码。

正如文章开头提到的,我们将使用三种模型。这些是霍尔特的线性模型,霍尔特-温特的模型和 ARIMA。前两种是指数平滑法,ARIMA 代表自回归综合移动平均法,这是一种回归方法。

以下是霍尔特线性方法的 python 代码:

该模型在 42 个月内进行训练,最后 6 个月用于预测。可以调整模型参数以提高精度。该模型将两者相加,并将整个系列返回给我们。

我们怎么把这和画面联系起来?

Tableau 具有内置的分析扩展,允许与其他平台集成。

在我们的例子中,我们选择 TabPy。

请确保安装 TabPy,并在您的终端中启动,如以下资源所示:

您可以在上述弹出窗口的 Tableau 中测试连接。

我们还在 python 环境中导入了 TabPyClient 来创建一个连接对象。

我们将使用这个连接对象在我们启动的 TabPy 服务器上部署我们的模型。

让我们看看可以部署在 TabPy 上的 Holt 线性方法的修改代码。

霍尔特线性法

我们已经创建了一个返回模型输出的函数。因为我们将从 Tableau 中读取数据,所以我们使用了接受我们将从 Tableau 中传递的值的参数。您将会注意到,我们已经使用了 connection 对象来在 TabPy 中部署模型。同样,您可以为其他模型创建函数。

霍尔特-温特的方法

ARIMA

现在我们已经在 TabPy 中部署了这些模型,让我们在 Tableau 中使用它。我们将创建如下所示的计算字段:

Tableau 使用四个函数,即 SCRIPT_REAL、SCRIPT_STR、SCRIPT_BOOL 和 SCRIPT_INT,分别用于返回类型 REAL、string、boolean 和 integer。上面的代码告诉 Tableau 运行“季节性 ARIMA 方法”,该方法部署在 TabPy 上,带有 3 个参数(日期、销售额和预测月份),并将“响应”返回给 Tableau 的计算字段。

同样,我们为其他两个模型定义了计算字段。如果我们想在 Tableau 中一览无余,它看起来会是这样的:

请注意,您可以根据需要动态更改预测周期并查看预测。您希望选择最精确的模型。您可以选择在 Tableau 中创建一个参数来在模型之间切换。

需要注意的一个关键点是,我们需要容纳 Tableau 中的预测周期(在我们的例子中是几个月),以便为 TabPy 的返回值腾出空间。这是因为当我们从 Tableau 传递值时,原始数据集没有这些未来日期的空记录。我调整了数据以扩展日期范围,如下所示:

上述代码在将所需月份添加到 forecast 中并将其传递给 TabPy 之后,基本上扩展了日期范围。此外,我们为此计算日期字段选择“显示缺失值”。

这里有一个小交易。因为我们扩展了日期范围,所以最后的日期和销售数字被推到新的预测结束日期。然而,我们只对预测感兴趣;我们可以排除这个数据点,或者在过滤框中使用 LAST()=FALSE。请随意提出相同的想法。

让我们最后把它插入我们的仪表板:

这就对了。在 Tableau 的可视化发现中,我们有一个集成良好的预测模型。你绝对可以在 Tableau 中引入准确度分数和模型参数,让它变得更加活泼!

如前所述,在我的下一个故事中会有更多。

Tableau 的新“快速 LOD”审查

原文:https://towardsdatascience.com/tableaus-new-quick-lod-reviewed-47de0c0ad936?source=collection_archive---------31-----------------------

图片来自 Patrick Tomasso 由作者编辑

Tableau 最近发布了一个新特性“快速 LOD ”,它应该可以更容易地构建 LOD 计算。作为一个密集的 LOD 用户,我想尝试一下这个特性,并与您分享我的想法。

内容:

**·** [**Quick reminder about LOD expressions**](#29cb) **·** [**Testing "Quick LOD**](#1e3a)**"
·** [**Testing Outcomes**](#a0f3) **·** [**In a nutshell…**](#d1e1)

关于 LOD 表达式的快速提醒

当我们构建数据可视化时,我们经常需要通过使用 LOD 计算来同时处理同一度量的多个聚集级别。

如果我们在概念上与 SQL 相似,LOD 表达式允许在同一个查询中定义多个不同的 GROUP BY 子句。或者,使用更高级的 SQL 概念,LOD 将允许在同一个数据集上使用多个窗口函数(尽管有一些差异)。

例如,让我们考虑一个关于住宿的 viz,我们有一个关于每个房间类型和邻居的评论数量的数据。这里我用了一个丑陋但清晰的表示法:

作者截图—示例数据集

如果在同一个数据 viz 中,我们还想只显示邻域的聚集,我们将需要一个 LOD 表达式。

作者截图 LOD 示例

好吧,乍一看,它看起来不是很有用,但是我们可以使用“LOD 评论数”进行其他更复杂和有趣的计算(例如,按邻居加权平均,占总数的百分比,等等)。).

有 3 种类型的 LOD 计算,用于指定应如何构建数据组:

  • 固定LOD 定义了一个静态的独立分组。它仅使用计算中指定的维度来计算聚合度量,而不引用数据可视化中的任何其他维度。此外,固定表达式忽略 viz 中的所有过滤器,除了上下文过滤器、数据源过滤器和提取过滤器。

作者截图—固定 LOD 示例

  • 包含LOD 组数据,达到一个以上的粒度级别。除了视图中的维度之外,它还使用计算中指定的维度来计算聚合度量值。因此,当您需要包含视图中不存在的维度的计算时,这是非常有用的。

作者截图—包含 LOD 的示例

  • " EXCLUDE " LOD 组数据达到比更小的粒度级别。它从表达式中显式删除维度,这意味着指定的维度从分组中排除。

作者截图-排除 LOD 的示例

对 LOD 的深入解释超出了本文的范围,但是如果您需要更多的信息,可以在这里找到:

https://www.tableau.com/learn/whitepapers/understanding-lod-expressions?_ga=2.205069776.1331838473.1617091658-1235017356.1614089650&_fsi=kmTEmxG0 https://help.tableau.com/current/pro/desktop/en-us/calculations_calculatedfields_lod_overview.htm

测试“快速 LOD”

我使用 Tableau 已经有 5 年了,就表达的复杂性和提供的可能性而言,LOD 是一个让我花了更长时间才能理解和流利使用的概念。现在,由于我经常提供包含 Tableau 的培训,我尝试了新的快速 LOD 功能,看看它是否真的可以帮助初学者使用 LOD,或者至少开始使用。

快速 LOD 所做的是通过将一个度量拖放到一个维度上,用标准 LOD 表达式创建一个新的度量。根据我所做的测试,默认的 LOD 类型是“固定的”。

如果你想测试它们:

  1. 打开 Tableau Public 并下载样本数据集“纽约市的 Airbnb 房源”。

注:如果你是一个完全的初学者,我描述了如何获得 Tableau 公共(免费)在这里

作者截图—在 Tableau Public 中获取免费数据集

2.在一个新的工作表中,按住 Ctrl 并单击(在 Mac 上按住 Command 并单击)度量“评论数”,将其拖放到维度“邻域

作者截图—尝试快速 LOD

由于快速 LOD 特性,您应该会看到一个新的对象度量出现。

作者截图—尝试快速 LOD

它的表达式是一个 LOD:

测试结果

好吧,但是..就这些吗?是的:除此之外对开发者没有额外的帮助,或者至少我找到的就是这些。

一个很酷的特性是一个新的专用 LOD 编辑器,帮助用户定义 LOD 范围和聚合方式,但新的“快速 LOD”完全不是这样。它只是一个表情生成器,除了节省 5 秒的开发时间之外没有任何智能。

此外,在现实生活中的仪表板和数据可视化中,LOD 表达式通常处理不止一个维度,因此即使是自动生成的表达式也需要编辑和增强。

另外,我也不清楚为什么固定 LOD 是默认的快速 LOD 类型。

总之,数据可视化开发人员仍然需要学习 LOD 语法、类型和逻辑来正确完成他们的工作,新的快速 LOD 特性几乎没有帮助。

简而言之…

在这篇文章中,我测试了新 Tableau 的“快速细节层次”功能,这是为了帮助开发者处理细节层次的表达。我发现 Tableau 试图夸大其词,因为它相对于手动 LOD 编写的优势可以忽略不计。

感谢阅读。

随时订阅我的【分享数据知识】简讯

如果你想订阅《灵媒》,请随意使用我的推荐链接https://medium.com/@maw-ferrari/membership:对你来说,费用是一样的,但它间接有助于我的故事。

Tableau 的关系很酷

原文:https://towardsdatascience.com/tableaus-relationships-are-pretty-cool-517f0201535b?source=collection_archive---------20-----------------------

与连接不同,关系保留了数据的原始粒度,减少了对 LOD 表达式的需求。

去年夏天,Tableau 引入了一种新的数据整合方式。它叫做关系。使用连接组合数据的老方法仍然可用,我想我们中的许多人可能会暂时坚持使用熟悉的连接。然而,人际关系有很多值得推荐的地方,这篇文章将展示它们的一些来龙去脉。考虑下面的三个表:

图片作者。

使用连接 Tableau 将这些表组合成一个平面文件,如下所示:

将表合并到一个平面文件中会改变一些数据的粒度。图片作者。

将具有不同粒度级别的表连接起来,会在具有更多聚合粒度级别的表中复制观察结果—在本例中,是 director 和 ratings 表。正确总结这些表格中的测量值需要使用 LOD 表达式,这可能具有挑战性。

关系保留每个表的原生粒度级别。用户只需定义表之间的关系,并根据需要执行连接。

关系保留了数据的原生粒度。图片作者。

当我们创建包含这些表中的度量的汇总时,每个度量都使用其固有的粒度级别进行汇总。

图片作者。

我们两位导演的平均年龄是 60 岁——尽管詹姆斯·卡梅隆有五部每周票房收入,而莱恩·约翰逊只有两部。由于年龄来自本机粒度为控制器的控制器表,因此平均值是跨控制器计算的。对于 Tableau 的新手来说,这是很自然的,但是对于我们这些习惯于使用 LOD 表达式来纠正重复,并且习惯于将我们的数据视为一个合并的平面文件的人来说,这是相当具有革命性的。

让我们在下面的散点图中再次说明这个想法。我们正在绘制导演年龄与电影票房总和的关系图。Tableau 从票房表中累加每部电影的票房收入,但它从导演表中取出导演的年龄,因为每个导演在该表中只出现一次,所以年龄不会重复。

图片作者。

还要注意,对于关系,我们不必担心是使用右连接、左连接、全连接还是内部连接。如果一个维度存在于视图中使用的任何一个表中,那么这个维度就包含在 viz 中。对于在一个表中存在而在另一个表中不存在的维度度量,不会生成空值。

图片作者。

关系带来的另一个变化是记录数量字段的消失。现在,有一个(计数)字段与每个表相关联。这很有意义,因为每个表都保留了自己的粒度级别,因此有自己的记录数。

关系并不完美。目前,它们不支持计算“联接”,也就是说,不可能基于计算来定义关系。这意味着建立关系所需的任何操作,如拆分一个字段或拼接两个字段,都需要在连接到源之前完成。让我们希望 Tableau 很快将计算融入到关系中。

同样值得注意的是,数据源过滤器扩展到了相关的表中。您可能认为这两个表是分开的,但事实并非如此:对一个表中的值进行筛选将适用于相关表中的匹配值。例如,添加一个仅包含 50 岁的导演的筛选器,不仅会将詹姆斯·卡梅隆从导演表中排除,还会将他的所有电影从电影表中排除。(它也不包括乔丹·皮尔的美国,除非我们指定包括空值。)

Tableau 很好地解释了关系在这里。虽然习惯关系的逻辑需要一些时间,但绝对值得一试。

图片作者。

TabNet —用于结构化表格数据的深度神经网络

原文:https://towardsdatascience.com/tabnet-deep-neural-network-for-structured-tabular-data-39eb4b27a9e4?source=collection_archive---------6-----------------------

里卡多·戈麦斯·安吉尔在 Unsplash 上的照片

在这篇文章中,我将带你看一个使用 Google 的 TabNet 解决分类问题的例子。

尽管最近图像、音频和文本的深度神经网络(DNNs)激增,但似乎使用良好的结构化表格数据的任务在某种程度上被忽略了。

虽然今天的大部分数据确实是非结构化的(大约 80% ,但重要的是要正确看待绑定到行和列的少得可怜的 20%的数据仍然代表着巨大的数量。事实上,在 2020 年, IBM 估计全世界的数据收集总量将达到 350 亿兆字节(或 350 亿兆兆字节)。

这使得 7,000,000,000,000,000,000 字节的结构化数据需要一些深层的神经关注!

平心而论,正如 TabNet 最初的论文中指出的,这是由于当前的集合决策树(DT)变体(XGBoost、LightGBM、CatBoost 等)的事实。,)在表格数据方面比 DNNs 有一些优势。

然而,这一切都消失了,因为 TabNet 的发布在多个基准数据集上超过了基于 DT 的模型。

弗雷明汉心脏研究

今天,我将通过一个例子来说明如何使用 TabNet 来完成分类任务。该数据集包含来自弗雷明汉心脏研究的结果,该研究始于 1948 年,已经提供(并且仍在提供)对心血管疾病风险因素的重要见解。对于那些有兴趣了解更多关于这项研究的人,请查看此链接

如果你有兴趣了解更多关于 TabNet 架构的知识,我鼓励你看看我上面链接的原始论文。额外的资源包括这个 repo ,在这里你可以看到原始的 TabNet 代码。

最后,在我们深入讨论之前,你可以使用我在这个回购找到的笔记本。

数据

用于该分析的数据由 16 个变量组成,包括目标变量 ANYCHD。每一个的描述可以在下面找到。

表 1-数据集中变量的描述。

这是我们的数据帧的样子。

表 2 —表格形式的数据视图

调查缺失值

接下来,我想看看丢失了多少数据。使用 df.isnull()很容易做到这一点。sum(),它将告诉我们每个变量丢失了多少数据。另一种方法是使用一个软件包 missingno ,它允许我们非常快速地可视化缺失数据之间的关系。

在图 1 中,变量的缺失值(白色)的矩阵表示。这是按行垂直组织的,这允许我们查看丢失的值之间是否有任何关系。例如,HDLC 和 LDLC 的缺失值是相同的,这表明这些值不是为该数据集中的部分患者收集的。

图 1 —按变量排列的缺失数据矩阵。作者图片

我们还可以从另一个角度得到缺失值之间关系的热图,如图 2 所示。在这里,我们可以更容易地看到 HDLC 和 LDLC 之间的关系。值<1 means that it is slightly less than 1. Since al 3 of these variables are measure of cholesterol, it suggests that cholesterol data was not collected for certain patients in the dataset.

Figure 2 — A heatmap demonstrating the relationship between missing values. Image by author

Imputing missing values

Now that we have gathered information about our missing values, we need to decide what to do about them. There are many options depending on your data, and you can read more about the various imputation algorithms available on sklearn 的网页。

我选择了 KNN 估算器,您可以使用下面的代码实现它。总而言之,在第一个模块中,我简单地将数据分为特征和目标。

第二个模块使用 KNN 估算器变换特征。正如您在打印报表中看到的,最初有 1812 个缺失值被估算。

图 3-使用 KNN 估算器处理数据集中的缺失值。

最后一步是分割我们的数据。使用下面的代码,我最初将数据分成 70%用于训练集,30%用于验证集。然后,我将验证集分为验证集和测试集两部分。打印声明为我们提供了关于裂缝形状的信息。

图 4 —将数据分为训练集、验证集和测试集

TabNet

您可以用几行简单的代码来运行 TabNet,如下所示。这是 TabNet 的 pytorch 实现,所以您必须导入(或者安装,如果您还没有导入的话)torch、pythorch_tabnet 和您希望使用的模型(二进制分类器、多分类器、回归器)。

您还需要某种度量来评估您的模型。以下是从 sklearn 获得的列表。我还包含了一个标签编码,以防您的数据与我的略有不同。我的分类变量都是二进制整数,但是如果你有存储为字符串的类别,你会首先使用这个(或者一个替代的,比如一个热编码)。

图 5 —导入必要的库

接下来,我们必须定义我们的模型,这可以在下面的第一个代码块中看到。在第一行,我们定义了我们的优化器,亚当。接下来的几行安排了我们学习速度的逐步衰减。让我们打开它的内容:

  • 学习率最初设置为 lr = 0.020
  • 10 个时期后,我们将应用 0.9 的衰减率
  • 结果仅仅是我们的学习率和衰减率的乘积 0.02*0.9,这意味着在第 10 个时期它将减少到 0.018

在下一个代码块中,我们使模型适合我们的数据。基本上,它说训练和验证集将使用 auc (曲线下面积)和准确性作为总共 1000 次迭代(时期)的度量来评估。

耐心参数表示,如果在连续 50 个时期后没有观察到度量的改善,则模型将停止运行,并将加载来自最佳时期的最佳权重。

256 的批量是根据 TabNet 论文的建议选择的,他们建议批量不超过总数据的 10%。他们还建议虚拟批量小于批量,可以均分为批量。

工人的数量保持为零,这意味着将根据需要装载批量。据我所知,增加这个数字是一个非常消耗内存的过程。

权重可以是 0(无采样)或 1(自动采样)。最后, drop_last 是指在训练过程中,如果没有完成,则丢弃最后一批。

值得注意的是,其中许多都是默认参数。你可以在这里查看参数的完整列表

图 6——定义和拟合我们的 TabNet 分类器

这个分析的结果可以在图 8 中看到,并且可以使用下面的代码重现。前三个代码块绘制了损失分数、准确性(对于训练集和验证集)和特征重要性(对于测试集)。

最后的块简单地计算验证和测试集达到的最佳精度,分别是 68%和 63%。

图 7 —绘制损失分数、准确性和特征重要性

图 8 —(左)损失分数;(中间)训练(蓝色)和验证(橙色)集的准确性;(右)相对特征重要性

无监督预训练

TabNet 也可以作为无监督模型进行预训练。预训练包括有意屏蔽某些单元格,并通过预测屏蔽值来学习这些单元格和相邻列之间的关系。然后,可以保存学习到的权重,并将其用于监督任务。

让我们看看使用无监督的预训练如何影响我们的模型精度!

虽然类似,但代码有一些差异,所以我在下面列出了这些差异。具体来说,您必须导入 TabNetPretrainer。您可以在第一个代码块中看到,TabNetClassifier 被替换为 TabNetPretrainer。

当您拟合模型时,请注意最后一行 pretraining_ratio ,它是在预训练期间被屏蔽的特征的百分比。值为 0.8 表示 80%的要素被遮罩。

下一个代码块引用从 TabNet 的编码表示中生成的重构特征。这些被保存,然后可以在单独的监督任务中使用。

图 9 —使用 TabNet 的无监督表示学习

当对该数据集使用预训练时,验证集和测试集的结果分别为 76%和 71%的准确度。这是一个显著的进步!下面,您可以看到损失分数、训练集(蓝色)和验证集(橙色)的准确性,以及为测试集确定的特性重要性。

图 10 —(左)损失分数;(中间)训练(蓝色)和验证(橙色)集的准确性;(右)相对特征重要性。图片作者。

摘要

在本文中,我们通过一个例子演示了如何为分类任务实现 TabNet。我们发现使用 TabNet 的无监督预训练显著提高了模型的准确性。

在下面的图 11 中,我绘制了有监督(左)和无监督(右)模型的特征重要性。有趣的是,无监督的预训练能够提高模型的准确性,同时减少特征的数量。

当我们考虑特性之间的关系时,这是有意义的。例如,使用 TabNet 进行预训练可以了解到血压药物(BPMEDS)、收缩压(SYSBP)和舒张压(DIABP)是相关的。因此,无监督表示学习作为监督学习任务的高级编码器模型,具有更清晰和更可解释的结果。

图 11-有监督(左)和无监督(右)TabNet 模型的特征重要性值。图片作者。

我希望你喜欢这篇文章!试试看,让我知道它对你有什么效果。

TabNet:梯度推进的终结?

原文:https://towardsdatascience.com/tabnet-e1b979907694?source=collection_archive---------5-----------------------

TabNet 平衡了表格数据的可解释性和模型性能,但是它能取代 boosted 树模型吗?

TabNet 模型架构。图片作者。灵感来自https://arxiv.org/pdf/1908.07442.pdf

介绍

XGBoost、LightGBM 和 Catboost 等梯度推进模型一直被认为是表格数据领域的最佳选择。即使在 NLP 和计算机视觉方面取得了快速进展,神经网络仍然经常被基于表格数据的树型模型超越。

2019 年进入谷歌的 TabNet 。根据这篇论文,这个神经网络能够在各种基准测试中胜过领先的基于树的模型。不仅如此,它比增强的树模型更容易解释,因为它有内置的解释能力。也可以不经过任何特征预处理使用。如果是这样的话…为什么它没有流行起来?

TabNet 平衡了可解释性和最先进的性能。它易于实现,并且需要有限的超参数调整。那么为什么 XGBoost 仍然是 Kaggle 特级大师的首选武器呢?

本文研究了 TabNet 的理论,并展示了如何实现该模型的一些例子。

先决条件

这篇文章是给你的,如果…

  • 你知道什么是神经网络,它是如何工作的。
  • 你了解诸如批量标准化ReLU 和 G 梯度下降等术语。
  • 你在神经网络中遇到过注意力的概念。

目录

什么是 TabNet?

概观

  1. TabNet 输入未经任何预处理的原始表格数据,并使用基于梯度下降的优化进行训练。
  2. TabNet 使用顺序注意力在每个决策步骤中选择特征,启用可解释性和更好的学习,因为学习能力用于最有用的特征。****
  3. ****特征选择是基于实例的,例如,对于训练数据集的每一行,它可以是不同的。
  4. TabNet 采用单一深度学习架构进行特征选择和推理,这被称为软特征选择。
  5. 上述设计选择允许 TabNet 启用两种可解释性:局部** 可解释性,它可视化了特征的重要性以及如何将它们组合成一行;以及全局 可解释性,它量化了每个特征对整个数据集的训练模型的贡献。**

要点

尽管它提供了可解释性,但这是一个复杂的模型。我将尝试总结主要概念,但我强烈推荐阅读原始 TabNet 论文以获得技术细节。

下面的架构图概述了 TabNet 中的不同组件。

TabNet 模型架构。图片作者。受到 https://arxiv.org/pdf/1908.07442.pdf 的启发。红线是为了防止重叠箭头造成的混淆。

步骤

每个步骤都是一组组件。训练模型时,步数是一个超参数选项。增加这将增加模型的学习能力,但也会增加训练时间、内存使用和过度拟合的机会。

每个步骤在最终分类中获得自己的投票,这些投票的权重相等。这模仿了一个集合分类。

特征转换器

****特征转换器是一个拥有自己架构的网络。

它有多个层次,其中一些是每个步骤共有的,而另一些是每个步骤独有的。每层包含一个全连接层批量规格化和一个门控线性单元激活。如果你不熟悉这些术语,谷歌的 ML 词汇表是一个很好的起点。

TabNet 特征转换器模型架构。图片作者。灵感来自https://arxiv.org/pdf/1908.07442.pdf

TabNet 论文的作者指出,在决策步骤之间共享一些层会导致“具有高容量的参数高效且鲁棒的学习”,并且使用根 0.5 的归一化“通过确保整个过程中的方差不会发生显著变化,有助于稳定学习”。特征转换器的输出使用一个 ReLU 激活功能。

功能选择

一旦特征被转换,它们被传送到关注转换器屏蔽用于特征选择。

关注变压器**由全连接层、批量归一化稀疏最大化归一化组成。它还包括先前比例,这意味着知道每个特征在前面的步骤中使用了多少。这用于使用来自先前特征转换器的已处理特征来导出掩模。**

注意变压器模型结构。图片作者。灵感来自https://arxiv.org/pdf/1908.07442.pdf

****掩码确保模型聚焦于最重要的特征,也用于推导可解释性。它本质上掩盖了特征,这意味着模型只能使用那些被关注变压器认为重要的特征。

我们还可以通过查看某个特征在所有决策和单个预测中被掩盖了多少来了解特征的重要性。

TabNet 在端到端学习中采用稀疏度可控的软特征选择

这意味着一个模型联合执行特征选择和输出映射,这导致更好的性能。

TabNet 使用基于实例的特征选择,这意味着为每个输入选择特征,并且每个预测可以使用不同的特征。

这种特征选择是必不可少的,因为它允许将决策边界概化为特征的线性组合,其中系数决定每个特征的比例,最终导致模型的可解释性

PyTorch 中的实现

使用 TabNet 的最佳方式是使用 Dreamquark 的 PyTorch 实现。它使用 scikit-learn 风格的包装器,并且与 GPU 兼容。回购有大量的模型在使用中的例子,所以我强烈建议检查一下。

训练模型实际上非常简单,只需几行代码就可以完成,TabNet 也没有太多的超参数。

密码

Dreamquark 还提供了一些非常棒的笔记本,它们完美地展示了如何实现 TabNet,同时也验证了原作者关于模型在某些基准上的准确性的声明。

分类

**https://github.com/dreamquark-ai/tabnet/blob/develop/census_example.ipynb

回归

https://github.com/dreamquark-ai/tabnet/blob/develop/regression_example.ipynb

这两个例子都是可重复的,并且包括一个 XGBoost 模型来与 TabNet 的性能进行比较。

可解释性

TabNet 相对于 Boosted 树的一个关键优势是它更容易解释。如果不使用类似 SHAP石灰的东西,我们就无法剖析梯度推进中的预测。因为有了掩码,我们可以了解我们的 TabNet 模型全局使用(跨整个数据集)和局部使用(用于单个预测)的特性。****

为了探究这一点,我将使用上面的分类示例,该示例使用了人口普查收入数据集。

特征重要性

我们可以查看我们个人特征的重要性,它们加起来正好等于 1。当我们从基于树的模型中获取这些数据时,它可能偏向一个变量,或者具有大量唯一值的分类变量。在某些情况下,这可能会歪曲模型实际正在做的事情。

在这个例子中,当使用 TabNet 时,我们看到了更大的重要性分布,这意味着它更平等地使用特性。这不一定更好,TabNet 过程中可能存在缺陷。然而,原始论文的作者确实将特征重要性与合成数据示例进行了比较,并发现 TabNet 使用了他们预期的特征。

根据人口普查数据集训练的 TabNet 和 XGBoost 模型的要素重要性。图片作者。

注:以数字作为特征名称的特征(如 2174)似乎是匿名特征。

口罩

通过使用掩码,我们可以了解在预测级别使用了哪些特征,我们可以查看所有掩码或单个掩码的集合。

因此,对于第 0 行,即我们测试数据的第一行,似乎掩码 1 优先考虑数据集中的第 4 个特征。,而其他的面具使用不同的功能。

这可以让我们了解模型使用了哪些特征来进行预测,这给了我们更多的信心,因为我们可以找出模型预测背后的“为什么”,并可以帮助我们了解它如何处理看不见的数据。

然而,尚不清楚这与实际特征值的关系,我们不知道模型使用该特征是因为它是高还是低。更重要的是,我们不能轻易理解交互术语。

Census TabNet 模型中口罩的热图。较浅的颜色表示正在使用该功能。图片作者。

通过自我监督学习改善结果

TabNet 论文还提出了自我监督学习作为预训练模型权重和减少训练数据量的方法。

为此,数据集中的要素被屏蔽,模型尝试预测它们。然后使用解码器输出结果。

这也可以在 Dreamquark 的包中完成

https://github.com/dreamquark-ai/tabnet/blob/develop/pretraining_example.ipynb

使用自我监督学习应该用更少的训练数据产生更好的结果。

结论

TabNet 是用于表格学习的深度学习模型。它使用顺序注意来选择有意义特征的子集,以在每个决策步骤中进行处理。基于实例的特征选择允许模型的学习能力集中在最重要的特征上,并且模型掩码的可视化提供了可解释性。

希望你能看到,TabNet 让我们在保持可解释性的同时实现了最先进的结果。随着人工智能监管变得更加严格,理解我们的模型如何工作在未来只会变得更加重要。我强烈建议在你的下一个项目或 Kaggle 竞赛中尝试 TabNet!

了解更多信息

[## 什么是广义加性模型?

towardsdatascience.com](/generalised-additive-models-6dfbedf1350a)

将我的内容直接发送到您的收件箱!

https://adamsh.substack.com/p/coming-soon **

处理数据项目中不同类型的偏差

原文:https://towardsdatascience.com/tackling-different-types-of-bias-in-data-projects-29e326660639?source=collection_archive---------31-----------------------

这是一个难题

艾伦·布兰科·特耶多尔在 Unsplash 上的照片

昨天(星期一),我在一家户外黎巴嫩餐馆度过了一个晚上。食物是如此丰盛,但作为一名数据专业人员,我不禁被在入口处发生的事情所困扰…

</7-common-gotchas-of-data-projects-62e8646552f2> [## 数据项目的 7 个常见问题

towardsdatascience.com](/7-common-gotchas-of-data-projects-62e8646552f2)

新冠肺炎病毒的风险仍然非常突出,因此所有因英国放松监管而开业的餐厅都必须遵守严格的预防措施,以确保我们尽可能的安全。

在我去过的那家餐厅,安全措施包括面部识别系统,该系统记录你在餐厅的存在,并测量你的体温,以发现新冠肺炎的早期迹象。如果你在“安全”范围内,模型会将你归类为阴性,这意味着你可以被允许进入餐厅——阳性扫描意味着你的体温超出了限制,所以你不能被允许进入。

每个人都在享受这个系统,直到轮到我…我调整我的头以适应框架…

"欢迎尤瑟夫—录取"

该系统已将我识别为餐厅员工之一。

没多久就意识到哪里出了问题;尤瑟夫是餐厅里唯一的黑人员工,他留着胡子——就像我一样。当我问他们以前是否发生过这种事,他们坚持说我是第一个,但我对此表示怀疑。也许这只是这个特殊的员工第一次经历,没有被报道(我这么说是因为像我这样留胡子的黑人经常去那里)。

这个系统显然存在一些偏差。

偏见是支持或反对一个观点或事物的不相称的力量,通常是以一种封闭的、偏见的或不公平的方式。偏见可能是天生的,也可能是后天习得的。人们可能会对某个人、某个团体或某个信仰产生偏见。在科学和工程中,偏差是一种系统误差。[ 来源 : 维基百科 ]

数据所代表的现象可能存在不一致的原因有很多。让我们来探索它们:

选择偏差

当我们对数据源的选择出现偏差,导致无法实现适当的随机化时,我们就在数据中引入了选择偏差。当未被发现时,从业者最终分析和建模不代表总体的样本。

例如,如果我决定收集我的博客帖子的意见,但我只将调查发送给在 LinkedIn 上给我发赞美消息的人,很可能所有这些人都会给我提供大量积极的反馈,但是,这些信息不会给我提供任何关于普通读者观点的信息。如果我们的数据中存在偏差,它很可能会在我们的模型中表现出来。

“选择偏差是倾向于将你对数据源的选择偏向于那些容易获得、方便和/或有成本效益的”——Burk ov,a .机器学习工程。44 页。

为了避免选择偏差进入我们的数据,我们系统地质疑为什么选择一个特定数据源而不是另一个数据源背后的原因是至关重要的。如果原因是因为容易访问或成本低,那么一定要仔细关注并询问更多问题,如为什么以及如何创建数据。

自我选择偏差

自我选择偏差是选择偏差的一种不同形式;它出现在任何情况下,我们用来建立数据集的例子选择自己进入一个组,例如,任何由志愿者创建的数据源。

伦敦将于 2021 年 5 月 6 日投票选举新市长。最近在伦敦对 1000 名成年人进行的民意调查表明,现任伦敦市长萨迪克·汗将会以压倒性优势赢得选举。然而,该调查并没有透露出于任何原因没有参加投票的人数。虽然我认为这不太可能,但有可能是萨迪克·汗确保了他所有的朋友都参加了投票,因此他在投票中领先。

@AdamBikov推特上发推文

不幸的是,消除自我选择偏见并不容易。当某人自愿参加调查时,这是自我选择偏差出现的地方,仅仅是那个人同意回答问题就代表了自我选择偏差。

省略变量偏差

当我们的数据集遗漏了一个或多个准确预测所必需的特征时,就会出现遗漏变量偏差。因此,我们的模型会将缺失特征的影响归因于训练期间出现的特征。

比方说,我们希望建立一个模型,根据一些特征来确定一个人在一份工作中应该获得的报酬。众所周知,学术成就和高薪工作是密不可分的,所以我们把他们的学术成就作为一个特征。也有研究表明,如果一个人在书架上有很多书的家庭中长大,那么他在学校更有可能表现得更好,所以我们也把这作为一个特征。

我们的模型很可能会了解到,更多的书籍等同于更好的学术成就,这意味着更高的工资,但这忽略了非常重要的信息,如你父母的特征——他们的智商高吗?他们在一起吗?通过忽略我们父母的特征[和其他可能的特征],我们忽略了一个可能会使我们的结果产生偏差的变量,这将使其他特征看起来似乎比它们实际上更重要(即书架上的书的数量将被赋予比它应有的更大的重要性)。

你听说过“我们不知道我们不知道的东西”这句话吗?这正是避免遗漏变量偏差极其难以完全避免的原因。

也就是说,我们可以简单地使用所有可用的信息——包括不太有价值的特性。这将增加数据的维度,但通过利用良好的正则化技术,我们的模型将能够确定哪些要素有价值,哪些没有价值。

https://neptune.ai/blog/fighting-overfitting-with-l1-or-l2-regularization

资金偏好

资助偏见是一项科学研究倾向于支持研究资助者的利益[ 来源 : 维基百科 ]。例如,一家公司可能会买一份提供商业世界新闻的报纸。

如果我们在试图预测市场走势时将这份报纸的数据纳入我们的数据集,我们的模型的性能可能是次优的,因为报纸机构可能会压制关于其所有者的负面新闻,并过分强调他们的成就。

我们可以通过对数据源,更具体地说,对数据源所有者提供数据的动机进行彻底的调查来减少资助偏差。

抽样偏误

当用于训练模型的数据不能反映模型在生产时将接收的样本分布时,就会出现采样偏差,这可能是在现实世界场景中观察到的最常见的偏差类型之一。

假设我们想要预测青少年使用毒品的可能性,那么我们去一所中学(11-16 岁)并收集所有青少年的数据(假设他们都诚实地说出他们是否使用非法毒品)。

该数据会有抽样偏差,因为并非每个青少年都在读高中,也就是说,有些人可能在家接受教育,有些人可能不得不辍学,还有许多其他原因。这些数据低估了没有上高中的青少年,而高估了上高中的青少年。

为了避免抽样偏差,对在生产环境中观察到的数据中各种属性的实际比例进行适当的研究是很重要的。下一步是对训练数据进行采样,使其与生产环境中的数据保持相似的比例。

刻板印象偏见

刻板印象仅仅是对某一类人或事物的一种广泛持有的、固定的、过于简单化的形象或想法;每当我们使用来自历史来源的数据时,往往会观察到刻板印象偏差,例如:

  • 照片档案
  • 社会化媒体
  • 在线论坛和评论
  • 等等。

感兴趣的读者可能会决定读一下 男人对于电脑程序员就像女人对于家庭主妇一样?去除词语嵌入的偏见 了解更多关于刻板偏见的流行实例。

为了控制由我们的学习算法做出的有偏见的决定,从业者必须选择将学习算法暴露给更加公平的例子分布。

系统价值扭曲

当用于记录测量值的设备或过程出现问题时,通常会出现系统性的价值扭曲——当模型部署到生产中时,我们的机器学习算法会做出次优的预测。

例如,假设我们想要构建一个 catflap,它会在猫靠近时自动打开,但不会为狗打开。我们使用我们的 iPhone,它有一个白平衡(我想),为我们的训练数据拍照——照片最终看起来有点发黄。

在制作中,团队决定在猫翼上使用质量更好的相机,这个相机看到的是白色。由于相机是在低质量的图像上训练的,因此生产中的模型做出的预测将是次优的。

为了减轻这一困难,我们可以雇佣训练有素的专业人员在测量或观察设备的输出之间进行比较,或者我们可以使用多个测量设备来构建我们的数据集。

实验者偏差

实验者偏差是指研究者无意识地影响结果。数据。或者由于他们先前的信念或假设而成为实验的参与者。

在机器学习环境中,模型构建者可能会无意识地以一种确认他们先前存在的信念或假设的方式处理数据。在另一种情况下,模型构建者可以不断增加训练迭代,直到模型输出与他们的假设一致的结果。

解决实验者偏见的方法是让多个实验者验证所做的决定和提出的问题。

标记偏差

当有偏见的人或过程将标签分配给未标记的数据时,这会引入标签偏见。

例如,假设我们让一些贴标签机在阅读文档后给文档贴标签。一些贴标签机确实会阅读整个文档,并给它贴上一个经过深思熟虑的标签。另一方面,其他标记器会扫描文档中的关键字/短语,并基于这些为文档分配一个标签。

为了避免标记偏差,使用多个标记器来识别同一个例子是值得的——类似于集合模型。

最后的想法

事实上,确切地知道你的数据中存在何种类型的偏差是一项极其困难的任务,更不用说如何避免它们了。一个好的心态是孩子的心态。质疑一切:谁创造了数据?他们为什么要创建数据?数据是如何创建的?等等。本质上,在从事数据项目时,总是要持怀疑态度,会有错误,但只要你愿意学习和改进,你就会做得很好。

“你无法完全避免数据偏差。没有灵丹妙药。一般来说,让一个人参与进来,尤其是当你的模型会影响到其他人的生活时。49 页。

:感兴趣的读者应该深入研究安德烈·布尔科夫的 机器学习工程 以获得更多信息。

如果你喜欢这篇文章,请通过订阅我的免费 每周简讯与我联系。不要错过我写的关于人工智能、数据科学和自由职业的帖子。

相关文章

</4-data-related-books-ill-be-reading-in-april-efd06b367e35>

解决 Node.js Web APIs 的 Heroku H12 超时错误—处理长响应时间

原文:https://towardsdatascience.com/tackling-heroku-h12-timeout-errors-of-node-js-web-apis-handling-long-response-times-8fbafe46cd40?source=collection_archive---------20-----------------------

带有 Redis 缓存的混合(服务器+客户机)API 分页

虽然 Heroku 是 NodeJS 开发人员部署小型项目的一个流行平台,但我还没有遇到任何实用的或深入的解决 h12 请求超时❞问题的方法,这促使我分享我最近处理这个错误的方法。首先,确定这个错误的根本原因是很重要的,即 Heroku 的 web 服务器被设置为当处理 API 响应的时间超过 30 秒时自动终止 HTTP web 请求(通常是 API GET/POST)

假设 API 服务器启动并运行,这将可能的方法列表缩小到只有 ,将每个 API 调用花费的时间减少到 30 秒以内(关键字为 每个))。

用例:我的公交路线可视化网站

为了更好地理解公共交通通勤者的出行行为,几个月前我受命进行一项分析,其中涉及一系列公共汽车出行的出行链。与大多数自动售检票系统一样,公共汽车从起点到终点的行程是根据乘客的上车和下车信息推断出来的。因此,这促使我开发了一个 公交路线可视化网站 ,它允许选择始发地——目的地,以帮助我进行即将到来的公交路线分析:

图片作者|公交路线可视化网站上的起点-终点选择功能 |注:粉色公交路线指的是完整的公交服务路线。绿色公交路线仅包括特定于用户选择的始发地-目的地的公交车站

虽然数据提供者已经在其公共 API 中包含了空间坐标和公交车站序列,但是考虑到在新加坡有超过 ~ 25K 条唯一的公交路线,并且每个 API 响应调用最多返回 500 条记录,我必须在我的端实现数据串联,以便在第一次加载时呈现所有嵌入的公交路线信息

注意:提供的 API 遵循“偏移分页”格式:

作者插图|如果偏移量=0,则应检索记录 1-500。如果偏移量=1600,则应检索记录 1601–2100。

尝试 1:实现 100%的客户端分页

参考一篇关于客户端 vs 服务器端分页客户端分页是指当进行查询时,服务器将所有数据以一大块的形式返回给客户端。

由于所有可用的总线服务都必须在第一次加载时被检索以供用户选择,所以实现客户端分页的决定是很直观的:

作者图片|首次加载 web 应用程序时侧面板上的公交服务列表

作者的代码片段|用 NodeJs 异步等待语法编写的客户端分页(服务器端代码,即 app.js) |数据块的串联(每个数据块的最大记录数=500)在此文件中完成,直到所有记录都已聚合,作为数据对象的单个数组返回。

作者代码片段| 实现客户端分页后从前端获取数据| ` bus _ stops _ mapping obj '是 API 请求后端拼接完成后返回的 JSON 对象

然而,在部署时我很快意识到我必须进行的 3 个主要 API 调用所花费的时间— (1)公共汽车站(2)公共汽车服务;Heroku web 服务器上的公交路线比我在本地主机上花费的时间要多得多。

⚠这对于 API 调用 (3)总线路线来说尤其如此,其中最初从数据提供者检索到超过 25K 条记录,轻松超过触发 H12 超时 error‼ ☹的 30 秒超时规则

尝试 2:实现 100%的服务器端分页

参考客户端 vs 服务器端分页服务器端分页是当托管数据的服务器只返回客户端请求的数据的子集。

由于服务器超时,在单个聚合数组中返回 (3) Bus Routes 的所有记录是不可行的,所以我继续实现服务器端分页,其中多个 Ajax 请求是从前端完成的。每个 Ajax 请求从数据提供者检索 500 条记录,所有聚合代码逻辑都转移到了浏览器端:

作者代码片段|在 NodeJS 中使用异步等待语法的服务器端分页(服务器端代码,即 app.js) |从数据提供者调用每个数据块(每个数据块的最大记录数=500)并返回到前端|变量` client_offset '确定从数据提供者调用 API 的哪个'页面'

作者代码片段| 实现服务器端分页后从前端获取数据| service _ routes _ mapping obj '是通过 callAPI()`函数聚合所有 API 请求后返回的 JSON 对象

虽然最终解决了 H12 错误,但用户体验受到了影响,因为初始加载速度慢得令人失望😐

尝试 3:实现混合(客户机+服务器)分页

为了减少从前端发出的调用数量,我尝试在客户端和服务器数据请求量之间取得平衡,而不是直接从后端向前端返回 500 条记录进行聚合。最终,我决定将 500 条记录的每个 API 请求聚合到服务器(app.js)代码中的多个数组中,其中每个数组包含 5000 条记录,并返回到前端进行处理:

作者的代码片段|在此版本的“app.js”中设置了一个附加变量“LIMIT_PER_CALL ”,以便在返回数组以便在前端进一步聚合之前预聚合数据对象

作者代码片段| 实现服务器端分页后从前端取数据| service_routes_mappingObj '是通过 callAPI()`函数聚合所有 API 请求后返回的 JSON 对象。|请注意,与以前版本的“100%服务器端分页”相比,变量“PAGE_SIZE”已被设置为 5000,而不是 500。然后,每个最大 5000 条记录的数组在前端进一步聚合所有 25K 条公交路线记录。

使用 Redis 缓存提升整体性能

虽然我最终设法平衡了服务器端和客户端发送的 API 请求的数量,但为了进一步改善用户体验,我决定通过 Redis 缓存存储 API 结果,这样在初始加载之后,同一用户的后续访问将使相同的 API 结果能够通过 Redis 实例检索到,并最大限度地减少加载时间。要集成 Redis 缓存,首先需要在https://redislabs.com/设置一个 Redis 账户(自由层版本存储 30MB)。关于设置 Redis 帐户的详细步骤,可以在 Host 和免费使用 Redis-DEV 社区获得由 Ramki Pitchal a 撰写的深入文章🙃

检索 Redis 凭证后,Redis 节点包通过npm install redis安装并导入到服务器文件(app.js)中。所需的 Redis 凭证在一个.env文件中指定,该文件默认包含在.gitignore文件中。 ⚠这一点非常重要,因为这些凭证是保密的,不应该以纯文本形式暴露给其他人来窃取和利用开发人员的帐户。该规则适用于其他令牌,如 Google API 密钥或其他 API 访问密码。为了通过文件检索凭证,还应该安装 dotenv 节点包,并将其作为 **require("dotenv").config()** 包含在服务器文件中。为了成功连接到 Redis 实例,.env至少应该包含以下内容:

REDIS_USERNAME=<email linked to Redis account>
REDIS_PASSWORD=<password token linked to Redis account>
REDIS_ENDPOINT_URI=<Redis instance endpoint provided>
REDIS_DB=<name used to refer to the Redis instance>

作者代码片段|注意,代码首先检查 API 请求调用的结果是否存储在 Redis 实例中。如果是,则检索并返回缓存的值。否则,将对数据提供者进行 API 调用,同时将结果的副本存储在 Redis 实例中

考虑到新加坡公交路线的偶尔变化,我决定将 Redis 内存存储设置为 60 天后(约 2 个月)到期。在将其部署到 Heroku 服务器上的生产环境之前,Redis 凭证必须在 Heroku 的服务器配置页面 进行配置(因为。env 文件用于在开发环境中进行测试):

Image by Author |注意,变量的命名应该与它们在。环境文件

耶!我的 web 应用成功部署到 Heroku 上,没有出现 H12 超时错误:

图片作者|预览目前部署在 Heroku 上的公交路线可视化应用

关于构建该应用的基本原理的小说明:虽然有其他可用的公交路线可视化网站,但我无法找到任何可供用户检索特定公交路线数据的导出功能,以便自定义始发地-目的地配对。哦,威尔斯…

参考消息:完整的源代码可以在 我的 GitHub repo 找到,该应用程序目前部署在:https://sg-transportation.herokuapp.com/

非常感谢您的阅读,如果您想阅读我即将发布的应对工作挑战(包括人员和技术问题)的文章,请跟我来!会非常感激😀

https://geek-cc.medium.com/membership

用预测概率处理不平衡数据

原文:https://towardsdatascience.com/tackling-imbalanced-data-with-predicted-probabilities-3293602f0f2?source=collection_archive---------9-----------------------

在数据世界里争吵

葡萄牙银行营销数据集中优化分类概率的案例研究

图片由 Budarinphoto 通过创意市集

分类算法通常能够输出预测的概率。有时,这些预测的概率本身也很有意义,例如在评估博彩赔率时。预测概率也可以通过给我们调整分类阈值的选项来改善模型预测,从而帮助处理不平衡数据。

本文讨论了各种机器学习算法在预测概率上的差异,以及如何通过案例研究使用它们来提高这些算法的预测能力。案例研究是一个葡萄牙银行营销数据集,其中目标变量是定期存款的“是”或“否”预订。

我将首先讨论目标变量和选择的评分标准。然后网格搜索最佳模型超参数,接着分析预测概率。然后将这些概率校准到数据中的真实观察概率。随后定位使评分度量最大化的召回精度阈值。最后,最优概率阈值用于重新分类模型预测,并计算最终的训练测试分数。

几年前,我在一次数据科学访谈评估中收到了有问题的数据集,它被故意调整为需要一些数据争论,以将数据放入正确的 Pandas 数据框架中进行进一步分析。我提到这一点,是为了让你在我的 Github 页面上查看代码时,不会被最初的数据争论所迷惑,并且对那些可能面临类似调整的采访数据集的人也有帮助。 UCI 数据集可在这里获得,但是我用于案例研究的版本发布在我的 Github 页面上,链接在本文底部。

不平衡数据

调整后的数据集有41176 个观察值目标分类变量不平衡,的“是”率为 11.27%,的“否”率为 88.73%

换句话说,如果这是一个装有九个黑白球组合的袋子,那么(大约)只有一个黑球和八个白球。因此,如果我的目标是选一个黑球,也就是预测营销活动的“是”订阅,我将有很大的胜算。

我将目标变量中的“yes”类编码为“1”****,将“no”编码为“0”。将感兴趣的类别编码为 class 1 非常有用,因为许多重要的 scikit-learn 评分指标,包括 F1 指标,都使用 pos_label=1 作为默认的感兴趣类别。

考虑到不平衡的数据,通常的准确度分数对这个问题帮助不大。即使模型一直简单地说“不”,它的准确率也有 88.73%。说破钟一天对两次!这种模式将被打破,但仍然看起来强大的印象深刻的所有时间。

为了解决这个问题,让我们转向混淆矩阵。假设我们有一个被分类为“正”(1)或“负”(0)的二元变量,这是纯粹用来区分这两个类别的术语。根据下面描述的风格化混淆矩阵,我们有沿着水平轴的二元变量的预测类(左 0 &右 1)和沿着垂直轴的实际类(顶部 1 &底部 0)。这个程式化矩阵的设计遵循了与 scikit-learn混淆矩阵相同的顺序。

自然,预测很可能不是 100%准确的,所以我们可以将那些“积极的”预测分为正确的(真阳性)或错误的(假阳性)。我们可以对“否定”预测做同样的事情,即真否定假否定。矩阵的右上象限保存真正预测,例如,假定它包含预测 1 和真 1。

程式化的混淆矩阵

“阳性”类别的精确率将是真阳性的总和除以总阳性类别预测(或真阳性 + 假阳性)。假阳性是那些被模型错误地标记为“阳性”但实际上是“阴性”的观察结果。在上图的上下文中,它是黑盒除以红盒和黑盒的总和。所以 精度是模型从其预测的正观测值中挑选出真正的概率。

另一方面,召回率将是真阳性的数量除以真阳性假阴性之和的比率。请注意,假阴性是那些被模型错误地标记为“阴性”但实际上是“阳性”的观察结果。在上图的上下文中,它是黑盒除以绿盒和黑盒的总和。回忆描述了模型从实际阳性观察值中挑选出真阳性的概率。

评分标准

当正类在不平衡数据集中占少数时,精确度和召回率是模型预测能力的更有用的度量,并且主要目标(但不是唯一目标)是正确识别那些正观察值。F1 分数是精确度和召回率的调和平均值

F1 分数实际上是 F-Beta 分数的一个特例,其中 Beta > 1 意味着更加重视召回率,而 Beta < 1 则更加重视精确率。在模型预测中追求更高的召回率必然会降低准确率,反之亦然,我将在下面演示。所以 F1 分数在召回率和精确率之间取得平衡。这可能不适合每一种情况,但在我看来,它符合这种情况下的目的。

科恩的 kappa 是评估不平衡数据的另一个有用的统计。它告诉我们这个模型在预测【正面】和【负面】类别时,比单独的随机机会要好得多。kappa 统计值大于 0 意味着模型比 chance 更好,它越接近最大上限 1 意味着模型对数据的分类越好。然而,Cohen 的 kappa 统计不能用于比较不同数据集之间的模型性能。

所以我的模型评测指标会是 F1 评分 科恩的 kappa 。在数据不平衡的情况下,另一个有用的指标是精确召回曲线 (AUC-PR)下的面积,如果人们关心这两个比率之间的平衡的话。****

变量和初始分数

我将省略 EDA 和数据工程的解释,因为这不是本文的重点。感兴趣的读者可以参考我的 Github 页面,跟进具体采取的措施。我选定的变量如下,包括目标变量(名为“target”),其中大部分是虚拟变量:

变量列表

我将比较五种流行的分类算法的结果:

  • 逻辑回归 (Logit),
  • ****随机森林(射频),
  • 天真的贝叶斯 (NB),
  • 支持向量分类器 (SVC),以及
  • XGBoost (XGB)

Python 中的 scikit-learn 库允许您更改 Logit、RF 和 SVC 的class-weight 参数,在处理不平衡数据时,通常建议指明class _ weight = " balanced "。你也可以为 NB 模型设置先验概率来反映目标变量各自的比例,我是这样做的【0.11,0.89】。至于 XGBoost,可以设置scale _ pos _ weight参数来反映负类与正类的比值,我表示为 7.85。通常这些超参数设置只会有边缘帮助,尤其是当数据高度不平衡时,但每一点都有帮助!****

使用最小-最大缩放对数据进行缩放,由于存在大量虚拟变量,因此选择了这种特定的缩放程序。数据通过 70:30 的训练测试分割,对数据的第一次分析得出以下训练测试分数:****

训练集和测试集的初始分数

SVC测试 F1、科恩的 kappa 和精确回忆 AUC 分数中表现最好的,尽管它没有最高的测试准确度分数。 XG Boost 在 F1 测试、Cohen 的 kappa 和 AU-PR 评分中排名第二,而逻辑回归在这些指标中排名第三。随机森林在训练和测试集上获得了最高的准确性分数,但在其他指标上表现不佳,这表明它专注于预测多数类 0。

网格搜索超参数

接下来是使用 F1 Cohen 的 kappa 作为评分标准对这五个模型进行 gridsearch 和分层 KFold 交叉验证(k =3)。gridsearch 程序显示了五种分类算法的以下优化超参数:

网格搜索优化模型

然后,这些数据被用于再次对训练集和测试集上的每个算法进行拟合和评分:

训练集和测试集的网格搜索后得分

grid search-tunedXG Boost model摘得了顶级表演者桂冠。我们看到训练 F1* 和 Cohen 的 kappa 分数在五个模型中表现出混合变化,但是在测试集分数中有一个总体改善。随机森林XG Boost 的测试成绩进步最大,其次是 SVC 。相比之下,Logitnave Bayes只有轻微的改善。***

预测概率

现在让我们检查由各种 gridsearch-tuned 模型提供的类 1* 的预测概率,并将它们与真实的类概率进行比较。这可以通过校准曲线图(或可靠性图表)来完成。预测的概率与目标变量的真实观察值一起被分类并分布到十个箱中。***

然后计算每个箱中预测概率的平均值,并与该箱中类别 1 观察值的真实分数进行比较。这是通过绘制每个箱的平均预测概率来实现的。如果模型校准良好,那么平均概率点将落在对角线附近,这意味着每个箱中的平均预测概率与该箱中的实际 1 类观测值的比例相当。**

校准曲线的计算仅使用上述 gridsearch 程序之前分割的数据集的训练部分进行。模型预测概率的校准曲线如下,不幸的是,它们都没有校准好。几乎每个模型在对角线下都有一致的图,这意味着它们倾向于过度预测每个分类箱中目标变量(第 1 类)的分数,表明算法的精确度较低。**

概率缩放前的可靠性图

朴素贝叶斯因提供偏向极端的预测概率而臭名昭著,而支持向量机倾向于生成偏向中间的预测概率,正如随机森林在较小程度上一样。然而,即使是逻辑回归,通常被认为提供了良好的未校准预测概率,在这种情况下也表现不佳。**

下面的预测概率点提供了他们糟糕表现的另一个视角。NB 的预测概率(红色)确实集中在两个极端,而 SVC 的预测概率(绿色)更多地集中在中间。Logit(蓝色)似乎不太愿意做出接近 0%概率的预测,而 RF(黄色)似乎相反。另一方面,XG Boost (grey)对于做出接近 0%或 100%的预测显得非常害羞。

缩放前的预测概率剥离图

在任何情况下,预测概率的分布在不同的模型中是不同的。在我们可以使用预测的概率来改进分类预测之前,需要通过校准来校正这些偏斜的分布。****

缩放预测概率

通过使用初始概率来预测目标变量(即真实概率)的附加回归器,对预测概率进行校准或缩放,以反映观察到的1 级事件的发生。更简单的程序是使用逻辑回归进行缩放,也称为普拉特缩放sigmoid 回归变量。替代程序是利用等渗回归仪**

令人高兴的是, scikit-learn 具有calibrated classifiercv函数来进行缩放。我将校准函数嵌套在 GridSearchCV 中,使用 brier score 作为计分器,为每个算法找到最佳缩放程序,sigmoid 或等张。仅使用训练数据再次完全执行该第二网格搜索。除了 SVC 显示 sigmoid 校准为更好的选项外,所有模型均显示偏好等张校准。这实际上是非常典型的 SVC 算法。**

下面显示了比例预测概率,人们可以立即看到改进。现在大部分概率曲线大部分时间都在拥抱对角线。然而,朴素贝叶斯是一个主要的例外,因为它似乎无法在校准后以更高的概率生成任何预测。因此,我决定放弃对它的进一步分析。**

概率缩放后的可靠性图

为了提供另一个视角,让我们看看由各种算法提供的预测概率(类别 1)的分布的直方图。下面的第一张图表是预缩放分布图,我们可以看到它们之间的明显差异,尤其是各种分布图的模式和分布图。第二张图描绘了缩放后的分布,现在我们观察到预测概率的分布更加相似。**

概率缩放前的分布

概率缩放后的分布

概括地说,我采取的步骤(为了简化,省略了上面讨论的训练测试评分)是:

  • 训练-测试分割数据;
  • grid 在训练数据(训练验证集)上使用分层三重交叉验证搜索 5 个模型;**
  • 启动根据上述网格搜索参数化的 5 个模型;
  • 将这 5 个模型放入另一个 gridsearch 中,使用对训练数据(训练验证集)的分层三重交叉验证来找到最佳概率比例回归变量。**

换句话说,两种网格搜索都是纯粹使用训练数据完成的。唯一一次使用测试数据是在对网格搜索前后的模型进行评分时。无论如何,感兴趣的读者可以参考我的 GitHub 页面来检查我采取的具体步骤。

对于是否应该为网格搜索后的概率校准分离出完全独立的一批训练数据,存在一些争论。换句话说,将初始数据分成三份* s - gridsearch 训练集、概率标度训练集和测试集-同时注意对所有三个批次中少数类 1 的出现进行分层。如果一个人有很多数据,我想这可能是一个选择,但是你将需要更多的数据,其中的不平衡越大。然而,我不认为这是绝对必要的,因为概率校准不是为了导出新的模型超参数,而是简单地缩放已经参数化的模型的预测概率。***

概率阈值调整

在放弃 NB 之后,我接着在完整的训练数据上拟合剩余的四个模型(Logit、RF、SVC & XGB)。这些网格搜索调整和概率比例模型然后在 y_train 上生成预测概率。这些预测概率用于根据将观察分类为属于类别 1* 的概率阈值来计算召回率和精确率。***

换句话说,这些是给定各种概率分类阈值的混淆矩阵的召回率和精确率。请注意,这些是 而不是 通常 y 轴(纵轴)上的精确率和 x 轴(横轴)上的召回率。召回率和精确率都映射在 y 轴上,将预测分类为 1 类的概率阈值沿着 x 轴。

如前所述,在召回率和精确率之间有一个权衡,我们在下面的每个图中都看到了这一点,召回率随着概率阈值的上升而下降,反之亦然,精确率随着阈值的上升而上升。所以如果我们想要 100%的召回率,就把门槛定在 0%就好了!不幸的是,在这种情况下,你将被海啸般的假阳性*预测淹没,导致极低的准确率。*****

如果你还记得的话,F1 分数仅仅是更广泛的 F-Beta 统计的一个子集。例如,如果偏好相对于精度更高的召回,那么你应该调整 Beta > 1。总会有一个权衡,深思熟虑的分析师会决定什么是服务于他们目标的最佳权衡。召回精度阈值组合是使用预测概率阈值优化召回精度权衡的关键。**

下一步是找到最大化 y_train 上 F1 分数的概率阈值。然后使用拟合* 网格搜索调整和概率比例模型来预测 y_test 的概率。对测试集的预测概率应用最佳阈值,以重新分类类别预测(分类为新的类别 1 或 0 标签)。然后对阈值调整后的类预测进行评分。同样,如果你有不同的偏好,调整 F-Beta 会给你不同的概率阈值和结果。***

寻找使 F1 分数最大化的概率阈值的代码

对预测类进行重分类的代码(针对 Logit 模型)

最终分数

阈值调整后的重新分类预测的最终得分如下所示。为了便于比较,我再次加入了上面的初始和后网格搜索评分表。记住朴素贝叶斯模型已经从这部分分析中去掉了。****

最终的培训* F1 和 Cohen 的 kappa 分数显示所有四个模型都比 gridsearch 后的分数有所提高。测试分数当然更重要,它们揭示了阈值调整后的一个一般改进,除了随机森林算法。***

训练集和测试集的初始分数

训练集和测试集上的网格搜索后得分

训练集和测试集上的阈值后调整分数

阈值调整显著提高了 Logit 模型在 F1、Cohen 的 kappa 和 precision-recall AUC 指标上的测试分数。在这三项指标中,SVC 和 XG Boost 模型得分的增长更加适度。然而, XG Boost 算法凭借在所有三项指标上的最佳测试分数,保住了其顶级性能的桂冠。根据培训和测试分数,SVC 是第二名,但 Logit 在测试分数中非常接近第三名,F1 分数略高,但 Cohen 的 kappa 和 AUC-PR 较低。**

有趣的是,所有四个模型的训练和测试准确性分数都上升了,尽管准确性分数从来不是网格搜索和校准措施的重点。事实上,所有车型(除 NB 外)最终测试准确度得分是整个练习中最高的。因此,概率阈值调整不仅改善了除 RF 之外的少数类 1 的预测,还改善了两个类中模型的总体准确性。这表明,即使在处理平衡数据时,阈值调整也可能是有用的。**

达到这一点所采取的步骤是:

  • 启动 5 个网格搜索调整的概率比例模型;**
  • 对完整的训练数据进行模型拟合,预测y _ train**
  • 导出召回-精度-阈值曲线,并计算每个模型在预测的 y_train 上最大化 F1 分数的概率阈值**
  • 最后,预测 y_test ,输出预测概率,应用上面的概率阈值对预测类进行重新分类;
  • 对重新分类的类别预测进行评分。

当然,永远不要将测试数据用于任何网格研究、概率缩放或计算最佳概率阈值。通过这种方式,您可以保持测试数据的完整性,作为前面的步骤在提高分类算法性能方面有多成功的最终仲裁者。最后一步,我们转向得到的混淆矩阵**

混淆矩阵

让我们看看精度矩阵,以便更好地评估这些模型的细节。为了保持简洁,我将只关注表现最好的模型——XG Boost 和改进最多的模型——逻辑回归的矩阵。**

下面的图表是 XGB 的混淆矩阵,左边是后网格搜索矩阵,右边是后阈值调整矩阵。矩阵的右上象限包含预测的真阳性。两个右侧象限共同组成预测的正类,两个顶部象限共同保存实际的正类。**

因此,后网格搜索矩阵(左)的精确率为 830/(830+1065)= 43.80%召回率为 830/(562+830) = 59.63% 。对于后阈值调整矩阵(右图)精确率为 799/(799+969) = 45.19%召回率为 799/(593+799) = 57.40% 。阈值调整提高了召回率,降低了准确率,导致 F1 得分从 50.50%小幅攀升至 50.57%****

左侧为网格搜索后矩阵,右侧为阈值调整后矩阵

下面的图表是 Logit 的混淆矩阵。后网格搜索矩阵(左)的准确率为 898/(898+1813) = 33.12%召回率为 898/(494+898) = 64.51% 。对于后阈值调整矩阵(右图)精确率为 795/(795+1055) = 42.97%召回率为 795/(597+795) = 57.11% 。在这种情况下,阈值调整非常显著地提高了准确率,导致 F1 得分从 43.77%跃升至 49.04%****

左侧为网格搜索后矩阵,右侧为阈值调整后矩阵

基于混淆矩阵,很明显,XGB 模型始终比 Logit 有更好的准确率。换句话说,XGB 模型的 1 类预测更有可能是真正的 1 类预测。阈值调整有助于大力提高 Logit 模型的准确率,但仍不足以在这一指标上超过 XGB。

如果我们考察准确度得分, XGB 的后 gridsearch 准确度得分为(830+9896)/sum(所有象限)= 86.83%后阈值调整准确度得分为(799+9992)/sum(所有象限)= 87.36% 。对于 Logit 型号同样的数字是(898+9148)/sum(所有象限)= 81.32% 和(795+9906)/sum(所有象限)= 86.63%**

细节显示,即使在 XGB 和 Logit 模型(右上象限图)中预测的真阳性 的数量下降,在阈值调整后,准确度得分仍有所提高。这是因为模型在变得更好,而不是误分类误报(右下象限数字),对 Logit 来说尤其如此。**

结论

这是一个不平衡数据的例子,大约八个 0 类目标观测值与一个 1 类观测值之比。因此,我选择了 F1 分数科恩的 kappa 作为评分标准。选择了五个流行的分类模型(Logit、NB、RF、SVC & XGB),在将数据分成训练测试集之后,我继续进行通常的超参数网格搜索**

gridsearch-tuned 模型的预测概率被发现校准不良,因此它们必须被缩放以反映真实的观测概率。然后将 gridsearch-tuned 概率标度算法拟合到训练数据中,以预测 y_train ,而不是朴素贝叶斯模型,该模型由于其极差的校准结果而被放弃。**

下一步是在每个概率阈值下生成精确度和召回率。找到了在 y_train 预测中最大化 F1 分数的阈值。然后对模型进行 paces 预测 y_test ,并提取预测概率。然后根据最大化概率阈值对类预测进行重新分类,并进行评分。****

结果显示,算法的后网格搜索训练测试分数在概率阈值调整后普遍提高,除了随机森林(以及被丢弃的朴素贝叶斯)。逻辑回归显示测试分数有显著提高,但仍不足以在性能排名中挤掉 XG Boost (榜首)和支持向量分类(亚军)。**

所有模型的总体准确度分数也从阈值调整中受益,尽管准确度从来不是练习的重点。这表明,即使在平衡数据中,调整预测的概率阈值也可能是有用的。总而言之,这些发现展示了使用预测概率和调整它们的阈值如何能够提高分类算法的性能。**

(这个练习的完整 Python 代码和数据可以在我的 GitHub 资源库中找到。如果直接渲染 GitHub 笔记本文件有问题,使用 nbviewer 。)

如果你在阅读这样的文章中看到了价值,你可以在这里订阅 Mediumhttps://at-tan.medium.com/membership来阅读我和无数其他作家的其他文章。谢谢你。****

**** https://medium.datadriveninvestor.com/bitcoins-shifting-relationship-to-macro-factors-5465d542078f ****

用强化学习解决 UNO 纸牌游戏

原文:https://towardsdatascience.com/tackling-uno-card-game-with-reinforcement-learning-fad2fc19355c?source=collection_archive---------3-----------------------

从头开始的完整演练

第三发球Unsplash 上拍照

在这样的隔离时期,经典的 UNO 纸牌游戏成了我和女友之间最常玩的游戏之一。在无数轮比赛和双方的几次连胜之后,我很好奇是否可以通过分析得出一个最优的游戏策略,从长远来看,这将大大超过。

我的旅程由以下几部分组成:

  1. 用 Python 从头开始创建 UNO 纸牌游戏的游戏引擎
  2. 从模拟一系列 100,000 个游戏中获得游戏统计数据
  3. 实施基本的强化学习技术,以发现最佳的游戏策略

1.UNO 卡牌游戏引擎

为了训练强化学习(RL)代理如何智能地玩游戏,需要一个成熟的游戏环境。它必须捕捉所有的机制和规则,以便代理可以像真正的人类玩家一样与游戏进行交互。

Python 面向对象的特性允许将代码直观地组织成卡片、卡片组、玩家、回合和游戏的类对象。以下是主要观点…

1.1 卡

游戏最细粒度的元素是卡片本身,它具有“颜色”和“值”属性。还可以根据当前打开的牌来评估一张牌是否可玩。

1.2 甲板

一个固定的 UNO 牌列表代表一副牌。它在每个游戏开始时被初始化和洗牌。如果这副牌用完了,可以从中抽牌,并重新填牌。

1.3 玩家

玩家拥有手牌、可玩手牌作为属性,需要执行多种功能。他必须:

  • 确定他当前的状态(他持有的牌等)。)
  • 认识到他可能采取的行动(他可以出的牌)
  • 合并来自 RL 代理的决策逻辑

1.4 圈

这个类将一个回合中玩家的动作序列聚集在一起。在将 7 张起始牌分发给每个玩家的初始化之后,活动的玩家(轮到的玩家)要么抽一张牌,要么出牌。在这个设置中, player_1 正在利用 RL 代理,而 player_2 遵循随机策略。

1.5 游戏

最后,纸牌游戏只包括一系列回合。因此,执行一轮迭代,直到任何玩家满足获胜条件(没有手牌)。

描述的代码片段试图传达基本的游戏机制。完整的脚本可以在我的 Github repohttps://github.com/bernhard-pfann/uno-card-game_rl上获得。

2.来自模拟的游戏统计

有了一个全功能的游戏引擎,我们现在可以运行尽可能多的游戏模拟。这有助于深入了解游戏的统计特征,但也有助于训练 RL-agent。我主要对以下问题感兴趣:

  • 游戏持续多少回合?
  • 玩家第一个转身的优势有多大?
  • 游戏过程中最有可能出现的情况是什么?

2.1 游戏时长

在生成的 100,000 个模拟样本中,平均游戏长度为 41 回合。13 回合的低得多的模式是由右偏度(超过 100 回合的游戏部分)导致的。

100,000 个模拟游戏中每个游戏的回合分布

样本中最长的游戏持续了 327 个回合,而最短的只花了 3 个回合,这只有通过多张特殊牌(跳过,反转, +2,+4 )的组合才有可能。

2.2 先发优势

开始游戏的玩家比他的对手有一定的优势。为了量化这种优势,在以下两种情况下观察两个随机游戏代理的累积长期胜率:

  1. 玩家 1 总是先行动(红色模拟)
  2. 玩家 1 在每两局游戏中开始第一步(紫色模拟)

模拟 30,000 场游戏的累积胜率

正如预期的那样,在一个先发制人的公平设置中,两个随机参与的代理人的胜率收敛到 50%。这表明游戏引擎按预期工作。

更有意思的是,始终主动出击的玩家赢得了所有游戏的 52% 。这对应着一个 ca。战胜对手的可能性提高了 4% (52%对 48%)。

2.3 比赛过程

像体育分析一样,热图可以用来显示比赛过程的焦点。通过跟踪玩家经历的每一个状态和动作,我们可以识别游戏中最有可能出现的情况。

100,000 个模拟游戏中状态动作出现的次数

热图的轴表示玩家手牌的数量,以及在相应时间点采取的行动。显而易见的是,大多数时候玩家拿着 4-5 张牌在“游戏中期”徘徊。所有颜色的普通牌(0-9)最常被使用是有道理的,因为它们是一副牌中最常见的牌。

3.强化学习的应用

在 UNO 纸牌游戏中搜索最优策略是强化学习的经典用例。因此,游戏本身可以被构造为有限马尔可夫决策过程(MDP),这意味着以下特征:

  • 状态:游戏的每一步都可以用一个状态来描述
  • 动作:决策者根据自己所处的状态采取动作与游戏互动
  • 奖励:采取某些行动可以导致一个令人满意的最终状态(例如赢得游戏),这是有奖励的

随机因素是通过随机抽取的牌以及对手的移动而固有的,需要大量的模拟来确定长期最优。我应用的基本技术是蒙特卡罗和带有离散状态-动作矩阵的 Q 学习。

3.1 定义状态空间

在受监督的机器学习设置中,拟合一个函数来将可用特征映射到输出变量。另一方面,RL 在每一步顺序地和单独地评估每一个动作。因此,需要定义状态、行动和奖励。

状态可以代表决策者可用的任何信息,这些信息对于描述游戏的当前情况是有用的。这可能是他持有的牌的类型,对手持有的牌的数量,或者关于已经打出的牌的信息。

乍一看,UNO 似乎是一个非常简单的纸牌游戏,因为它的规则有限。然而,当计算出一个玩家可能持有的牌的组合时,事情很快就失控了。准确地说,大约有 10 种⁶组合。由于 RL-agent 必须学习每个状态的最佳动作,因此限制状态的数量是有意义的。

因此,我形成了一个 16 位的状态标识,它捕获代理人持有的牌和他可以使用的牌,只区分颜色和特殊牌(跳过、反转等)。)

国家的识别

通过将状态标识的每个属性的最大值限制为 2,状态空间被成功地限制为 270,000 种可能性。

3.2 可能的行动

代理人决定玩的牌代表他正在采取的行动。应用与上述相同的聚合逻辑会产生 9 种不同的动作:红色、绿色、蓝色、黄色、跳过、反转、+2、+4、野生颜色

q 表初始化为零

3.3 蒙特卡洛代理

给定离散的状态-动作矩阵,代理通过模拟多个游戏来导航字段。当矩阵被初始化为所有值为零时,蒙特卡罗(MC)在每个完成的游戏之后更新所有被访问的状态动作值。

q 值更新功能

状态 s 采取行动 a 时的 q 值根据本集 R 中实现的奖励以及步长参数α进行更新。为了决定在相应的状态下采取哪个动作,算法的ε-贪婪形式选择:

  • 以ε概率:随机行动
  • 具有 1-ε概率:具有最大 q 值的动作

3.4 Q-学习

在其基本形式中,Q-learning 以类似的方式工作。然而,当 MC 在更新 Q 值之前等待每一集的完成时,Q-learning 在每一步都以一个步长的滞后来更新它们。

q 值更新功能

因此,q 值取决于步长参数、下一步的回报 r、以及在状态 s-hataction-hat 下一步的 q 值。

因此,两种算法都采用相同的 2 个参数,具有以下效果:

  • Alpha: 较高的步长参数会在每次更新时增加 q 值的变化,同时阻止值收敛到更接近其真正的最优值
  • T21:较高的ε允许更多的探索行动,这些行动乍看起来并不有利可图。与此同时,当最优博弈策略被代理人获得时,它会被稀释。

4.结果

现在我们已经指定了模型,让我们看看它们是否有用。因此,用一个随机玩家和另一个利用 RL 算法来模拟游戏。作为评价标准,我用的是 RL-player 的累计长跑胜率。

100,000 场模拟游戏的累积胜率

在对两个 RL 模型中的每一个运行 100,000 次模拟之后,可以证明相对于随机代理的一致性能。考虑到运行事件的巨大数量,统计显著性是可以保证的,即使超出的幅度似乎是有限的。

51.5%的胜率意味着 RL 算法比随机玩家多赢 3%。

4.1 问题表

为了了解算法对游戏的了解程度,仔细检查 Q 表可能会有所帮助。由于整个表的大小为 270,000 x 8,所以状态是通过手牌的数量来聚集的。

稳步下降的紫色曲线描述了这样一个事实,即手牌较少的州更容易赢得比赛。因此,这些状态具有更高的 Q 值,这有助于 RL 代理选择尽可能快地减少其手牌数量的动作,以便获得奖励。

来自 Q 学习模型的聚合 Q 值

4.2 国家行动覆盖面

为了判断模型是否已经在足够的模拟上被训练,可以评估状态-动作覆盖。因此,在 100,000 个游戏中已经出现的不同的状态-动作对可以被计数。

总的来说,这两种模型都经历了 ca。六万种不同的组合。乍一看,这低于预期,因为我们现在知道 100,000 个游戏平均有 41 个回合(41 x 100,000 = 410 万)。转弯)。然而,我们也展示了游戏过程是如何集中于在样本中多次出现的某些牌组合。

100,000 个模拟游戏期间的状态动作覆盖

由于其更新功能的性质,蒙特卡罗模型的更快的初始覆盖增加并不令人惊讶。

5.结论

尽管 RL 模型能够持续地以一定的优势超过随机玩家,但仍然不清楚与真正的人类玩家相比,这种表现会如何。有几个限制阻碍了该算法获得更令人印象深刻的结果:

  • 每场游戏中只有很少的几步棋需要战略评估,因为大多数时候,玩家手中不会有超过一张的牌。仅在加州。32%的可玩回合,玩家有多种选择,聪明的行为可以带来更好的表现。

  • 没有包括所有相关的状态信息,因为这种具有离散状态-动作矩阵的简单形式的 RL 仅适用于有限的一组状态。关于对手拥有的牌的数量或者已经打出的牌的颜色分布的信息可能有助于微调游戏策略。
  • 最后,这是一场运气的游戏!与大富翁或国际象棋等其他棋盘游戏相比,UNO 带来了大量的随机性,这削弱了战略优势的潜力。

底线是,在下一场 UNO 的比赛中受到挑战时,我会继续相信我的直觉。我展示的作品可以在我的 Github 资源库中找到,任何熟悉高级 RL 方法的人都可以从这里获得。

https://github.com/bernhard-pfann/uno-card-game_rl

使用 Geopandas 将位置标记到 Shapefile 区域

原文:https://towardsdatascience.com/tagging-a-location-to-a-shapefile-area-using-geopandas-5d74336128bf?source=collection_archive---------34-----------------------

GeoPandas 简化的另一个地理空间用例

照片由 Marjan Blan | @marjanblanUnsplash 上拍摄

我以前写过一个使用 Geopandas 和 Matplotlib 绘制地图的简单方法。

现在,另一个非常常见的地理空间分析用例是将特定位置标记为预定位置/区域/地区等。例如,假设您是一家实体商店的分析师,想要绘制其关键领域的竞争程度。这些关键区域可以是企业预定义的区域,也可以基于预定的国家区域(如省、区等)。).

你的团队已经收集了足够多的竞争对手地址及其经度坐标列表。要么从第三方公司购买,要么进行艰苦的谷歌搜索,或者两者都有。所以现在你的任务是用一个自定义的城市名来映射这些地址的纬度和经度。您的公司已经有了包含策略性绘制的边框的 shapefile。你所需要做的就是将城市名称与竞争者的位置联系起来。

你不需要任何花哨的算法,GeoPandas 包已经得到了你的支持!

在这个练习中,我们将使用印度尼西亚省的 shapefile,您可以在这里获得,以及我收集的一些随机的印度尼西亚商场地址。你可以在我的 Github repo 获得它和完整的源代码。

第一步是加载我们需要的包,然后是我们的参考 shapefile 和我们想要标记的地址列表。

印度尼西亚省参考 shapefile 来源于作者

要标记的地址坐标—来源于作者

现在,Geopandas 实际上是一个非常强大的地理空间包,使这项任务变得如此简单。它已经为我们提供了within命令,所以我们只有几行简短的代码!

地址标记结果-来源于作者

within代码检查我们地址的纬度和经度点是否在我们的参考 shapefile 中。注意,我们需要一次用一个省的参考来检查它。否则,我们将无法正确地标记它(因为两个地址可能在两个不同的省份,如果我们一次对所有参考进行标记,我们将很难正确地标记它)。

就是这样!希望本教程能对您的地理空间分析有所帮助。完整的源代码和数据,你可以在我的 Github repo 上查看。

尾部事件,它们为什么重要以及如何建模

原文:https://towardsdatascience.com/tail-events-why-they-matter-and-how-to-model-them-4ba979a40aae?source=collection_archive---------7-----------------------

如何用贝叶斯方法为意外和不可能建模?

图片作者。

罕见事件的定义是,嗯,罕见。但是,它们不可避免地会发生,而且当它们发生时,会产生巨大的后果。911 是一个尾部事件。2007/08 年的金融危机是一个尾部事件。冠状病毒是一个尾部事件。你每天使用的许多产品、参与的服务和工作的公司都是尾事件。所以,是的,尾部事件很少发生,但一旦发生,其影响是巨大的。

预测尾部事件或极值是固有的困难。事实上,作为一名数据科学家,我处理过的最具挑战性的问题之一是估计跨业务关键系统的极值的可能性。虽然精确预测罕见事件实际上是不可能的,但是估计它们的概率可能的,但是这需要脱离通常的商业建模。具体来说,它要求使用建模方法,即考虑显著超出条件均值的值或事件的可能性。

估计罕见事件概率的原则性方法有助于为决策、风险调整和对策提供信息。虽然有很多方法可以解决这些问题,但以我的经验来看,最容易理解、最可靠和最实用的方法是贝叶斯方法。在这篇文章中,我将提供一个尾部事件的实例,以及如何使用贝叶斯模型来估计它们的概率。

极值理论

极值理论(EVT)是统计学的一个分支,处理明显偏离概率分布中心趋势的值。值得注意的是,一个极值问题从根本上不同于罕见事件预测问题。例如,欺诈检测是一种罕见的事件分类问题,但这不是一个极值问题。为什么?因为欺诈等罕见事件很少发生,但却是可预测的,而 EVT 所关注的极端值类型通常难以预测。

EVT 的最终目的是估计极值发生的概率。这有许多使用案例,特别是在自然科学领域(例如地震和海啸等极端天气事件),但也包括经济学、金融和工程领域的许多应用问题。

极值可以非常低,也可以非常高。值的方向并不重要。重要的是用于估计其可能性的统计分布。这些分布统称为极值分布。有许多极值分布,但是我发现在实践中最直接和有用的是 冈贝尔分布

Gumbel 分布类似于正态分布,因为它仅由两个参数定义,即位置和比例。但是,与正态分布不同,它是不对称的。这意味着分布的尾部可能向极值的方向倾斜。在实践中,这意味着与正态分布相比,Gumbel 分布赋予更多极端事件(即分布尾部的事件或数值)更大的可能性。你可以在下面的图中看到这一点。

np.random.seed(123)
n = 100000
fs = {"fontsize" : 16}
plt.figure(figsize=(20, 12))
sns.kdeplot(stats.distributions.gumbel_r().rvs(n), label="Gumbel") 
sns.kdeplot(stats.distributions.norm().rvs(n), label="Normal")
plt.legend(**fs)
plt.xticks(**fs)
plt.yticks(**fs)
plt.ylabel("Density", **fs)
plt.xlabel("X", **fs);

图片作者。

估计极值的概率

为了在实践中演示 EVT,我将使用风速数据集,其中包括极值。数据绘制如下。您可以在该数据中发现强烈的季节性模式,但也可以发现明显超出正常范围的周期性值。我们需要做的第一件事是分离出这些值。为此,我们可以使用块最大值方法。该方法简单地提取一个范围(即一个块)内数据的最大值。在这种情况下,我们将提取数据中每个月的最大值。这些点由图中的红点标出。

block_maxima_month = (
    df
    .set_index("date")
    .resample("M")
    .max()
    .wind_speed
    .reset_index()
    .query("wind_speed > 5")
)fs = {"fontsize" : 16}
plt.figure(figsize=(24, 10))
plt.scatter(df.date, df.wind_speed, alpha=.3)
plt.plot(df.date, df.wind_speed, alpha=.7, c="b")
plt.scatter(block_maxima_month.date, block_maxima_month.wind_speed, c="red", s=80)
plt.xticks(**fs)
plt.yticks(**fs)
plt.ylabel("Wind speed", **fs)
plt.xlabel("Date", **fs);

图片作者。

下一步是拟合块最大值的分布(如下图所示)。为此,我将使用 PyMC3 对分布拟合一个简单的贝叶斯模型。为了便于说明,我将对数据进行正态和耿贝尔分布拟合。

作者图片

下面的代码使分布符合块最大值。在这两种情况下,我使用相同的前科。

Gumbel fit 作者图片。

正常拟合-按作者排序的图像

轨迹图显示了对冈贝尔(顶部)和正态分布的拟合(底部)。在这两种情况下,分布可靠地拟合了数据,如对每个参数的一致探索所示。比较这两种分布是很有趣的,因为它们是由相同的两个参数定义的,但每个都估计了不同的参数值。让我们看看每个分布与极值的实际分布的拟合程度。

对于每个模型,我们首先需要从后验分布中取样。这实质上包括从由估计的位置和比例参数定义的分布中抽取独立的样本。一旦我们有了后验分布,我们就可以将它们与实际数据进行比较。

# Extract posterior distributions
ev_post = pm.sample_posterior_predictive(ev_trace, model=ev_model)["lik"].T
norm_post = pm.sample_posterior_predictive(norm_trace, model=norm_model)["lik"].T# Plot density 
plt.figure(figsize=(20, 10))
pm.plot_dist(ev_post, label="Gumbel", textsize=20, hist_kwargs=fs)
pm.plot_dist(norm_post, label="Normal", textsize=20, )
sns.kdeplot(block_maxima_month.wind_speed, label="Actual")
plt.legend(fontsize=14)

图片作者。

上图显示了拟合的耿贝尔分布和正态分布以及数据的实际分布。您可以看到,虽然正态分布在拟合数据方面做了合理的工作,但它没有遵循 Gumbel 分布。例如,您可以看到正态分布偏离实际分布的位置相当多,并且也有一个较轻的尾部。相比之下,Gumbel 似乎更符合实际数据。同样值得注意的是冈贝尔分布的长尾效应— 冈贝尔并不排除数据中观察到的更极端事件的可能性。这正是我们使用这些发行版的原因!

现在我们有了分布,我们可能想做的一件事是估计一个极值被超过的概率。在实践中,这通常是一个非常有用和重要的量化指标。为此,我们可以使用 Gumbel 的后验分布。问题是; 我们看到超过指定阈值的值的概率是多少?

上面的代码简单地迭代指定的值,并使用后验 Gumbel 分布来估计看到更大值的概率。这些超越概率绘制如下。例如,风速超过 20 的概率约为 0.38。

作者图片

摘要

极值预测是一个有趣但具有挑战性的问题。这篇文章展示了一个通用的方法,你可以用它来开始解决这些问题,但是这可能会变得更加复杂。此外,在这篇文章中,我没有对任何协变量设定极值的可能性。这种分析的一个有趣的扩展是,看看在模型中包括额外的协变量是否有任何价值(例如,前一天或前一周的风速或其他天气模式,如湿度)。最重要的一点是使用极值分布,如 Gumbel 分布。当一个值或事件的可能性大大超过分布的条件均值时,那么你需要一种方法来考虑尾部事件的似然性。

感谢阅读!

附:这个帖子的所有代码可以在这里找到。

双标图分析简介:基于印度尼西亚贫困数据的洞察

原文:https://towardsdatascience.com/take-a-decision-based-on-biplot-analysis-on-indonesian-poverty-data-679c28d4ad46?source=collection_archive---------35-----------------------

迪卡塞娃Unsplash 上的照片

动手教程

双标图分析是多元数据的图形表示,它以笛卡尔坐标绘制观察值和变量之间的信息

背景

根据 Nurwati (2008)的观点,贫困是人类一直面临的问题。它的问题与人类本身一样古老,其影响可能涉及人类生活的各个方面。换句话说,贫困是一个全球性的社会问题,这意味着这个问题已经引起了全世界的关注,存在于世界上所有的国家,尽管影响是不同的。即便如此,有时人类并不认为贫穷是一个问题。对于那些被归类为穷人的人来说,这是他们日常生活中真实的事情,因为他们生活在贫困中。然而,很难断定他们了解自己的生活状况。

造成贫困的因素包括教育意识水平低、健康状况差、就业机会有限以及与世隔绝。

因此,需要双标图分析来根据人口和贫困因素确定印度尼西亚各省的特征。它的分析可以通过更有吸引力、信息量更大、更具交流性和艺术性的图形表示提供一种简单的理解。此外,使用双标图分析,可以直观地确定每个省的人口和贫困之间的关系。

目标

这项研究的目标是:

  • 确定印度尼西亚人口和贫困变量之间的关系,如各省人口、贫困线、农民人口比例、平均贫困差距指数(P1)和平均贫困严重程度指数(P2)
  • 确定各省之间的相对位置,以便寻找相似的特征
  • 了解印度尼西亚各省在人口和贫困变量上的特征
  • 根据人口和贫困变量找出贫困水平最低的省份

利益

这项研究的好处是:

  • 确定与印度尼西亚贫困水平密切相关的变量
  • 根据人口和贫困变量确定各省的特点,以便在公共政策讨论中考虑调查结果
  • 评估地方政府在实施区域发展以减轻印度尼西亚贫困水平方面的表现

领域

研究的范围是,所使用的数据是来自 2010 年印度尼西亚贫困数据和 2010 年村庄潜力数据的二手数据。这些数据可以在 印尼中央统计局 获得。该文档可在https://github.com/audhiaprilliant/Multivariate-Analysis获得。

方法学

数据

使用的数据是来自 2010 年印度尼西亚贫困数据和 2010 年村庄潜力数据的二手数据。这些数据可以在印度尼西亚中央统计局获得。该数据有如下几个变量:

表 1 研究数据(图片由作者提供)

数据分析的程序

2010 年印度尼西亚贫困和村庄潜力对应分析研究的步骤如下:

  1. 汇总印度尼西亚各省的贫困数据。使用的变量是贫困人口的百分比、P1 指数、P2 指数和贫困线
  2. 汇总各省的村庄潜力数据。使用的变量是男性人口、女性人口、家庭人口、农民人口的百分比
  3. 基于省名合并印度尼西亚贫困和村庄潜力数据

结果和讨论

数据预处理和集成

这项研究的第一步是数据预处理。其执行如下:

  • 标准化印度尼西亚贫困和村庄潜力数据的省名格式(以大写字母开头)
  • 检查印度尼西亚贫困和村庄潜力数据的省名格式
  • 检查印度尼西亚贫困和村庄潜力数据的省名格式错误

双标图分析

双标图分析是一种多元分析,它试图压缩信息,并使用 主成分分析 在笛卡尔坐标中显示它们。为了识别成分的方差,需要计算特征值。该特征值如表 2 所示。

# Load the libraries
library(factoextra)
library(FactoMineR)
# Read the data
data_biplot = read.csv(file = 'Social Poverty Indonesia 2010.csv',
                       header = TRUE,
                       sep = ',')
colnames(data_biplot)
data_biplot = data_biplot[,-10]
str(data_biplot)
# Province as Rownames
data_biplot_no_province = data_biplot[,-1]
rownames(data_biplot_no_province) = data_biplot[,1]
data_biplot = data_biplot_no_province

双标图分析

# Biplot analysis
res_pca = PCA(data_biplot, 
              graph = FALSE
)
print(res_pca)
# Biplot graph
fviz_pca_biplot(res_pca,
                repel = TRUE,
                col.var = "#2E9FDF", # Variables color
                col.ind = "#696969"  # Individuals color
)
# Calculate the eigenvalue
eig_val = get_eigenvalue(res_pca)
fviz_eig(res_pca,
         addlabels = TRUE,
         ylim = c(0, 50)
)

表 2 主成分分析的特征值(图片由作者提供)

从表 2 可以看出,第一个和第二个分量解释了分量方差的 72.148% 。因此,双标图分析得到的结果很好地解释了数据的方差。

图 1 双标图分析和碎石图(图片由作者提供)

根据图 1(右)中的碎石图,发现在第二个组成部分中,可以解释的方差百分比没有急剧下降。但在第三个组成部分,可以解释的方差百分比的下降急剧下降。这表明第三个成分的添加对解释的方差有影响。但是,对于双图分析,仅选择第一个和第二个组件。两个分量可以解释的方差的总百分比在 72.148% 左右。

对照双标图分析的结果分析观察值

双标图分析完成后,在确定和评估双标图分析的结果时,对每行(观察值)或每列(变量)进行另一次分析。表 3 显示了两个组成部分(PCA)中每个省的坐标。因为双图分析仅使用第一个组分和第二个组分,所以我们将重点放在前两列。

# Graph of observations
ind = get_pca_ind(res_pca)
# Coordinates of observations
ind$coord

表 3 观察坐标(图片由作者提供)

根据第一和第二成分解释的方差的总百分比为 72.148% ,意味着 27.852% 的信息缺失。使用第一个分量和第二个分量,我们得到的结果是,可能有观察点不能由双标图正确表示。正确的衡量标准是余弦的平方。如果观察点由双标图充分表示,则第一分量和第二分量中的平方余弦之和接近 1。

# Squared Cosine of observations
ind$cos2

表 4 观测值的平方余弦值(图片由作者提供)

根据表 4,可以得出结论,在双标图中有几个省没有得到很好的代表。它们是万丹、DKI 雅加达、哥伦打洛、中加里曼丹、亚齐、廖内、南苏拉威西、东南苏拉威西、北苏拉威西和南苏拉威西。这是由于那些省份的平方余弦很小,低于 0.7 。从视觉上看,平方余弦的值如图 2 所示。

# Color by cos2 values: quality on the factor map
fviz_pca_ind(res_pca,
             col.ind = 'cos2',
             gradient.cols = c('#00AFBB', '#E7B800', '#FC4E07'),
             repel = TRUE # Avoid text overlapping
)
# Cos2 of individuals on 1st component and 2nd component
fviz_cos2(res_pca,
          choice = 'ind',
          axes = 1:2
)

图 2 双标图分析和观察值的平方余弦(图片由作者提供)

根据双标图分析结果分析贫困和村庄潜在数据指标

两个分量(PCA)中每个变量的坐标如表 5 所示。因为双图分析仅使用第一个组分和第二个组分,所以我们将重点放在前两列。

# Graph of variables
var = get_pca_var(res.pca)var
# Coordinates of variables
var$coord

表 5 变量的坐标(图片由作者提供)

使用第一部分和第二部分,其结果是有可能存在双标图不能很好表示的贫困和村庄潜在变量。为了探究这种情况,我们将查看表 6 所示的余弦平方

如果这些指示符被很好地表示,那么第一分量和第二分量中的余弦平方之和将接近 1。变量的余弦平方的值如表 6 所示。

# Squared Cosine of variables
var$cos2

表 6 变量的平方余弦(图片由作者提供)

根据表 9,可以得出结论,有几个变量没有得到很好的体现。这些是贫困人口的百分比和平均贫困线。他们有一个平方余弦非常小,低于 0.7

# Color by cos2 values: quality on the factor map
fviz_pca_var(res_pca,
             col.var = 'cos2',
             gradient.cols = c('#00AFBB', '#E7B800', '#FC4E07'),
             repel = TRUE # Avoid text overlapping
)
# Cos2 of variables on 1st component and 2nd component
fviz_cos2(res_pca,
          choice = 'var',
          axes = 1:2
)

图 3 双标图分析和变量的平方余弦(图片由作者提供)

变量的相关性

从这些变量之间的相关性可以看出变量之间的关系。相关性就是这两个向量(变量)形成的角度的 余弦 。如果向量重合或者两者的角度都接近 0,则相关性接近 1。在 1 附近的两个变量之间的相关性暗示了这两个变量之间的显著关系。男性群体和女性群体的相关性最高,约为 0.9996。另一个最高值在 P1 指数和 P2 指数之间,为 0.9910。

变量的相关性(图片由作者提供)

结论和解释

根据图 1,观察值和变量之间的关系可以分为以下四类:

  • 第一类 。它主要由女性人口、男性人口和家庭人口组成。围绕这些变量分布着几个省份,即 西爪哇省、中爪哇省、东爪哇省和北苏门答腊省 。这表明,与印度尼西亚其他省份相比,这些省份的人口相当多
  • 第二类 。它只有一个变量,那就是贫困线。其类别对应 万丹、邦加勿里洞、廖内、巴厘、东加里曼丹、中加里曼丹、南加里曼丹、占碑、西苏门答腊、占碑、廖内、DKI 雅加达 。这些省份的贫困线高于印度尼西亚的其他省份
  • 第三类 。它由 P1 指数和 P2 指数主导。由 楠榜、东努沙登加拉、南苏拉威西 组成。他们有更高的 P1 指数和 P2 指数
  • 第四类 。它有两个主要变量。它们是贫困人口的百分比和农民人口的百分比。由 西努沙登加拉省、中苏拉威西省、北苏拉威西省、东南苏拉威西省、亚齐省、明古鲁省 组成。

参考

[1]努尔瓦蒂。Kemiskinan:model pengukuran,permasalahan,and Kemiskinan alternative kebijakan(2008),Jurnal Kependudukan Padjadjaran。10(1): 1–11.

完全控制 Matplotlib 中的支线剧情

原文:https://towardsdatascience.com/take-full-control-over-the-subplots-in-matplotlib-71b3bc11ff0b?source=collection_archive---------37-----------------------

腾雅特Unsplash 上拍摄的照片

使用支线剧情和 GridSpec 一起更好地控制

使用支线剧情,将多个情节放在一个图中,对于在一个小空间里总结大量信息非常有用。他们有助于做报告或演示。本文将关注如何有效地使用支线剧情并对网格进行精细的控制。

我们将从基本的子图函数开始,首先制作大小相等的图。让我们进行必要的导入:

%matplotlib inlineimport matplotlib.pyplot as plt 
import numpy as np 
import pandas as pd

下面是 Matplotlib 中的基本 subplots 函数,它生成两行三列大小相等的矩形空间:

fig, ax = plt.subplots(2, 3, sharex = 'col', sharey = 'row', figsize = (9, 6))
fig.tight_layout(pad =3.0)

“sharex”参数使同一列中的图具有相同的 x 轴,将“sharey”参数设置为“row”使同一行中的图共享相同的 y 轴。这就是为什么只有外层有 x 轴和 y 轴的值。共享轴心有利也有弊。我们以后再谈。

如何访问这个数组中的一个图?

这些矩形存储在一个二维数组中。让我们把“斧头”打印出来:

ax

输出:

array([[<AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>],
       [<AxesSubplot:>, <AxesSubplot:>, <AxesSubplot:>]], dtype=object)

从上面的输出可以清楚地看出,它实际上是一个二维数组。因此访问其中的一个元素应该使用嵌套的 for 循环。首先在每个矩形中放一些文本:

fig, ax = plt.subplots(2, 3, sharex = 'col', sharey = 'row', figsize = (9, 6))
fig.tight_layout(pad = 2)for a in ax:
    for b in a:
        text = 'I am a plot'
        b.annotate(text, (0.3, 0.45), fontsize = 12)

主要目的是在那些矩形里放一些真实的图形和地块。下一步我会这么做。但为此,我们需要一个数据集。我将使用这个数据集:

https://github.com/rashida048/Datasets/blob/master/nhanes_2015_2016.csv

请随意下载数据集并跟随。

在这里,我使用 pandas 导入数据集:

df = pd.read_csv('nhanes_2015_2016.csv')
df.columns

输出:

Index(['SEQN', 'ALQ101', 'ALQ110', 'ALQ130', 'SMQ020', 'RIAGENDR', 'RIDAGEYR', 'RIDRETH1', 'DMDCITZN', 'DMDEDUC2', 'DMDMARTL', 'DMDHHSIZ', 'WTINT2YR', 'SDMVPSU', 'SDMVSTRA', 'INDFMPIR', 'BPXSY1', 'BPXDI1', 'BPXSY2', 'BPXDI2', 'BMXWT', 'BMXHT', 'BMXBMI', 'BMXLEG', 'BMXARML', 'BMXARMC', 'BMXWAIST', 'HIQ210'], dtype='object')

我将再次制作一个 2x3 的绘图数组,并在“ax”元素中设置绘图。我们将像二维数组一样简单地通过索引来访问每个“ax”元素。我希望你记得如何索引一个二维数组。如果您需要复习,请查看这篇文章:

因此,下面是如何访问“ax”元素并在其中设置绘图。我给你留了两个空位。请随意装满它们。我的想法是演示如何去做。

fig, ax = plt.subplots(2, 3, figsize = (15, 10))
fig.tight_layout(pad = 2)ax[0, 0].scatter(df['BMXWT'], df['BMXHT'])
ax[1, 1].plot(df['BMXBMI'])
df['DMDHHSIZ'].hist(ax = ax[0, 2])
df.groupby('DMDEDUC2')['BPXSY1'].mean().plot(ax = ax[0, 1], kind='pie', colors = ['lightgreen', 'coral', 'pink', 'violet', 'skyblue'])
plt.show()

请注意,我没有将“sharex”设置为“col”、“sharey”或“row”。这样剧情就没什么帮助了。因为饼图没有传统的 x 轴和 y 轴。直方图和散点图具有非常不同的范围。请你自己试试。

上面所有的图都是一样大的。我是说同样的高度和宽度。事情不一定是这样的。一个子绘图组中的绘图可以有不同的高度和宽度。这可以使用“add_gridspec”函数来完成。

fig = plt.figure(constrained_layout=True, figsize=(8, 8))s = fig.add_gridspec(3, 3, width_ratios = [2, 3, 4], height_ratios = [3, 3, 2])for row in range(3):
    for col in range(3):
        ax = fig.add_subplot(s[row, col])

对网格进行更精细的控制

这可以使用“支线剧情”和“GridSpec”来完成。这里有一个例子。我会在图后说明:

plt.figure(figsize = (15, 12))
grid = plt.GridSpec(3, 4, wspace =0.3, hspace = 0.3)plt.subplot(grid[0, :3])
plt.subplot(grid[0, 3])
plt.subplot(grid[1:, :2])
plt.subplot(grid[1, 2:])
plt.subplot(grid[2, 2:])

让我解释一下这里发生的事情。首先,我们做了一个 3x4 的网格。这意味着三行四列。接下来,我们通过网格索引来定制地块的大小。

plt.subplot(grid[0, :3])

使用这些代码,我们可以索引网格并定制形状。grid[0,3]'这里是取第一行的前三个地块,做一个更大的地块。我们将行索引放在首位。因为它是第一行,所以 row-index 是 0,而 column index 是 0 到 3,因为我们取前三列。可以写成 0:3。但当它以 0 开头时,可以写成:3。

下一个是“grid[0,3]”。这个更简单。0 表示行索引为 0,3 表示列索引为 3。

使用“grid[1::2]”,我们正在制作一个大的正方形。行索引从 1 开始,一直到末尾。列索引从 0 开始,包含 2 个图。所以,它需要指数为 0 和 1 的图。所以列索引变成 0:2,可以写成:2。

“[1,2:]”引用行索引 1。列索引从 2 开始,一直到末尾。

grid[2,2:]'表示行索引 2 和列索引 2 到结尾。

现在你知道了如何索引网格和定制形状的图,让我们再做一个并在其中放一些真实的图。

plt.figure(figsize = (12, 12))
grid = plt.GridSpec(4, 4, wspace =0.3, hspace = 0.8)g1 = plt.subplot(grid[0:2, :3])
g2 = plt.subplot(grid[2:, 0:2])
g3 = plt.subplot(grid[:2, 3])
g4 = plt.subplot(grid[2:, 2:])df.groupby('DMDMARTL')['BPXSY1'].mean().plot(kind = 'bar', ax = g1)
g1.set_title("Bar plot of Systolic blood pressure for different marital status")df['BPXSY1'].hist(ax = g3, orientation = 'horizontal', color='gray')
g3.set_title("Distribution of systolic blood pressure")df.plot('BPXSY1', 'BPXDI1', kind='scatter', ax = g2, alpha=0.3)
g2.set_title("Systolic vs Diastolic blood pressure")df['BMXHT'].plot(ax = g4, color='gray')
g4.set_title('Line plot of the Weight of the population')

在这里!完整的情节。

结论

如果你已经运行完了上面的所有代码并且能够理解它们,使用支线剧情应该很容易,并且你现在可以完全控制支线剧情了。以下是该内容的视频版本:

欢迎在推特上关注我,并喜欢我的脸书页面。

更多阅读:

带回家的练习可以成就或毁掉你的 DS 面试

原文:https://towardsdatascience.com/take-home-exercises-can-make-or-break-your-ds-interviews-5aac8b63f6d1?source=collection_archive---------10-----------------------

91 杂志在 Unsplash 上拍摄的照片

办公时间

如何处理你的课后练习——可以说是面试中最重要的部分,也是你最能控制的部分

什么是带回家的练习?

如今,越来越多的公司将带回家练习作为数据科学(DS)面试流程的一部分。事实上,到目前为止,我面试过的 90%以上的科技公司都有带回家的面试,通常是在技术筛选之后和现场面试之前。通常会给你一个样本数据集和一系列开放式问题,比如这里的示例。大多数公司会给你一个机会在现场面试中向面试官或小组展示你的结果。

作者图片

为什么雇主都爱带回家的练习?

带回家练习是从雇主的角度评判候选人的一个很好的方式,因为它最接近你作为 DS 的日常工作,让雇主看到你的真正潜力,并让他们看到你如何从头到尾处理一个复杂的问题。正是因为这个原因,许多公司都非常重视带回家的练习(我知道这一点,因为我自己也参加过几次面试)。我目睹过现场编码做得不够好的考生通过带回家的练习来救赎自己;我也见过那些以优异成绩通过技术考试的候选人,由于不重视带回家的练习而毁掉了他们成功的机会。

你应该如何对待带回家的练习?

因为我知道带回家练习的重要性,它们过去似乎让我望而生畏:“我从哪里开始?”“即使招聘人员告诉我不应该花费超过 2-3 个小时,我还应该花费超过 2-3 个小时吗?”“我应该在网上查资料吗?”。我读了很多关于如何准备 DS 面试的文章,我自己也写了几篇关于如何准备和完成课后练习的文章,但是我没有找到任何好的资源,所以我决定整理一下我作为面试官和被面试者的经验,为你如何利用课后练习脱颖而出提供一些想法。

  1. 总是,总是,总是对给你的数据进行质量检查

正如我提到的,带回家的练习通常包含一个小样本数据集,供您探索并帮助回答提出的问题。以我的经验,给考生的数据几乎总有一些“错误”或“不准确”在里面;这可能是一些错误标记的时间戳,或者是明显不准确的后期信息。这些“陷阱”被放入数据集中,以测试 DS 应该具备的最重要的资格之一——对现实生活中数据不准确性的意识,以及有效审查和清理数据集的能力。

通常,样本数据集足够小,足以发现任何明显的错误;如果没有,尝试从数据集中随机抽取一些行来测试数据的完整性。这只是 QA 的起点,旨在捕捉数据中任何明显的不准确之处(例如,某个日期的所有时间戳都在午夜,而所有其他日期的时间戳分布在一天中的不同时间)。在您进入分析的下一步— EDA(探索性数据分析)时,QA 将继续进行。

2。从 EDA(探索性数据分析)开始分析

法卡斯特英语维基百科

每个 DS 应该已经熟悉 EDA 过程以及如何进行;但如果你不是,

EDA 是在任何建模之前对数据执行的初始过程。它旨在提供对数据的初步理解,帮助确定数据清理的必要性(如果数据中存在异常值或异常),并提供使用汇总统计和可视化快速形成和/或测试假设的机会

Python Pandas 包中有方便的函数(形状、信息、描述等。)和 R dplyr 这一步可以派上用场的包。在本文中,我不打算深入探讨 EDA 的细节,但我想简要指出关于带回家练习需要注意的几个重要事项:

  • 缺失值:特别注意缺失值是很重要的,尤其是如果你认为它将是你后续分析的关键变量。为缺失值制定缓解计划也同样重要(例如,删除行或使用中值/平均值填充缺失值)。
  • 异常值:通过绘制变量的分布图,应该很容易发现任何异常值;对异常值存在的原因以及是否需要修正/清理数据进行假设是很重要的。
  • 相关性:快速绘制所有变量之间的相关性图通常会让你对要测试的假设有一个很好的想法,如果你决定为这个练习建立一个模型,相关性分析还可以在特征选择方面提供指导。

3。假设驱动

在我的上一篇文章中(麦肯锡教给我的能让你成为更好的数据科学家的 5 课),我提到了在钻研数据之前拥有假设 的重要性。这将帮助您限制范围,并为您的分析提供方向。这也有助于你创建一个叙述来组织你的分析,这将有助于你稍后向面试官展示你的结果。

GIF 的

如前所述,EDA 将有助于提出这些假设,您可以稍后证明或反驳。不要害怕假设会被证明是错误的;只要假设一开始是合理的,这本身就是一个有趣的结论,可以包含在你的文章中。

4。清楚地陈述假设,并尽可能支持它们

与现场面试相比,带回家练习的最大缺点是很难问清楚问题,也很难与面试官交流。你可能没有完成练习所需的所有信息;可能是你不确定面试官对问题的哪个方面最感兴趣,或者是你缺少分析所需的数据。克服这个缺点的最好方法是清楚地陈述你所做的任何假设;许多候选人忘记了这一点,这使得评审人员很难理解你的分析。这些假设可以基于研究,甚至轶事证据或简单的常识(尽管如果你有一个强大的来源或数据点来支持它们通常会更好)。面试官可能会在你带回家练习的现场演示中挑战你的假设,所以确保你的选择总是有一个好的理由。

5。始终将其与业务影响联系起来

在我之前的文章中(麦肯锡教给我的让你成为更好的数据科学家的 5 课),我也提到了将所有分析与业务影响联系起来的重要性;同样的规则也适用于带回家的练习。

大多数公司提供了他们真实数据的样本,或者至少是代表他们真实数据的数据。他们问的问题可能与他们的业务相关,因此展示你的商业头脑(相信我,这是 DS 中罕见的技能)并证明你将能够产生可衡量的影响是很重要的。

6。有结构化的可交付成果

每个人(希望)都知道招聘人员在每份简历上花的时间不超过 2 分钟,所以以一种容易理解的方式组织你的简历是非常重要的。带回家的练习也是如此——它们通常由招聘团队成员审查,他们在日常工作之外帮助招聘过程,所以他们可能会花2 分钟以上,但不会超过 20 分钟“评分”你的带回家练习。让他们的工作变得简单,让你的交付物有条理,关键信息清晰。

我的 DS 带回家的可交付成果通常有三个组成部分— 代码+写作+演示文稿。确保你的代码简洁易读,格式良好,并且有注释来帮助读者理解。在注释中清楚地陈述任何假设,而不是隐藏在代码本身中(参见上面的第 4 点)。报告可能是大多数面试官在陈述之前用来判断你的分析的,所以确保你遵循报告或研究论文的格式,并在开始时有一个执行摘要。当把一副牌放在一起时,记住自上而下的沟通是很重要的,在深入细节之前,从关键信息开始你的牌。

8。准备演讲

除非你是一个经验丰富的演示者,否则一定要练习演示。保持条理并记住你想表达的所有观点是很难的,尤其是当你在面试中处于压力之下的时候;因此,请务必记下演示者的笔记。当然,你不可能预料到面试官会问的所有问题,但要试着对你的假设和设想进行压力测试,这样你就不会措手不及,可以为你在分析中做出的任何选择辩护。

10。不要害怕利用外部资源

通过外部资源,我不是说让你的朋友做你的练习;我的意思是在网上查资料。与现场面试相比,带回家练习的最大优势是你可以利用你能找到的任何资源。这就像是学校的开放式网络考试,好好利用吧。无论是第三方数据还是竞争对手研究,只要是公开信息,都是公平博弈。从我的经验来看,大多数面试官会欣赏你的额外努力和主动性。

GIPHY 制作的 GIF

你可能会想,“招聘人员让我花 2-3 个小时做这个练习,我怎么能完成你提到的所有事情?”。事实是,你不能。我每次带回家练习都要花 2-3 个小时以上,尽管招聘人员总是告诉我并非如此。我并不是要你花一周的时间来完成它(那太夸张了),而是要认真对待它,就像你在为团队做一个迷你项目一样。毕竟,你会希望这份工作能准确地反映你的工作质量,因为面试官会把它作为一个窗口来一窥你的能力和态度。让带回家的练习成为你的 DS 面试,或者至少,不要破坏它。

希望这篇文章对你以后 DS 面试的带回家练习有帮助。我将在下一篇文章中继续我的面试系列,我将介绍在 面试中需要注意的

把它带到推特上:国会议员的社交媒体分析

原文:https://towardsdatascience.com/take-it-to-twitter-sentiment-analysis-of-congressional-twitter-in-r-ee206a5b05bc?source=collection_archive---------10-----------------------

实践教程

通过情感分析理解国会对社会和政策问题的观点

图片由作者提供,肖像来自政府印刷局

推特和美国政治

自特朗普政府上台以来,推特的使用在美国政治中已经被讨论得令人生厌。虽然前总统特朗普已经离任,但社交媒体应用的重要性仍然保持不变。Twitter 现在已经成为国会议员与选民接触并就政策问题发表意见的主要途径。

随着新的拜登政府上台,国会两党合作已经成为政治中每一个重大问题的前沿。由于参众两院的差距很小,两党成员都支持立法对于有效的政府来说是至关重要的。虽然双方都在谈论两党支持的必要性,但在这个极度极化的时代,他们在社交媒体上反映了这种需求吗?

为了检验这个问题,我收集了现任国会议员的推文。一名国会议员拥有和(似乎是)操作的所有账户都被抓取了推文。虽然许多政治家都有团队运营他们的社交媒体,但这项分析的具体目标是查看来自国会议员自己的账户的推文。

为了研究这个问题,我收集了现任国会议员的推文。国会议员拥有和运营的所有账户都被取消了。虽然许多政治家都有团队运营他们的社交媒体,但这项分析的具体目标是查看来自国会议员自己账户的推文。

对于这个具体项目,主要关注领域是:

  1. 国会议员是如何在推特上谈论彼此的(包括本党成员和反对党成员)?
  2. 他们在推特上谈论社会和政策问题的方式是积极的还是消极的?
  3. 什么关键词最常用于社会和政策问题?这些关键字在不同的政党中有什么不同?

推文收集和预处理

为了进行这项分析,必须确定国会议员的推特账户。癌症分类组织在他们的网站上有一个电子表格,上面有所有国会议员的主要信息。虽然这是一个坚实的基础,但我注意到名单上有一些成员不再任职。这份名单的一个局限是,它只列出了国会议员的政府账户;但是,许多人有其他帐户,这些帐户通常使用频率更高。因此,我手动在 Twitter 上查找每个成员,以确认国会账户是准确的,并发现现任国会成员拥有的任何其他个人资料。我把这些额外的账户分为三类:个人账户、竞选账户和新闻办公室账户。个人账户通常在他们的简历中如此陈述,并且通常比国会议员的国会账户更活跃。当且仅当推文呈现为来自国会议员时,才会收集竞选账户。任何披露由国会议员团队运营的账户都被排除在外..最后,新闻办公室账户是在与竞选账户类似的条件下收集的。如果该账户的个人资料表明推文并非来自国会议员本人,则该账户不包括在内。以这种方式收集账户的目的是为了只分析来自国会议员的推文。

在所有 535 名国会议员中,有 532 人被发现至少有一个推特账户。2021 年 4 月去世的前众议员阿尔西·黑斯廷斯(D-FL)没有推特账户。他的席位目前也是空缺的;因此,没有来自佛罗里达州第 23 区的推文可以分析。众议员克里斯·史密斯(新泽西州共和党)也被发现没有推特账户。最后一个没有分析的成员是众议员杰夫·范·德鲁(新泽西州共和党)。众议员范·德鲁拥有一个推特账户;然而,它在 2021 年 2 月被删除。把任何可以收集到的推文都包括进来是不合适的,因为他的推文的时间跨度与所有其他账户不一样。

还有另外两个账户无法收集推文。共和党众议员道格·拉玛尔法(Doug LaMalfa)和民主党众议员佐伊·洛夫格伦(Zoe Lofgren)的私人账户不包括在这项分析中。考虑到一般观众无法接触到这些内容,将它们包括在内是没有意义的,因为这项分析的目的是了解国会议员如何公开展示自己。

最终,1016 个与国会议员有关的账户被确认。这包括 517 个政府账户、320 个个人账户、166 个竞选账户和 17 个新闻办公室账户。

推文收集于 2020 年 11 月 3 日至 2021 年 7 月 25 日期间。第一批推文是在 4 月 25 日发布的,6 月 15 日和 7 月 25 日又增加了一些推文。因为额外的推文被附加到现有的数据帧,所以被删除的推文可能被包括在数据帧中。tweet 是使用 Twitter API 和 get_timeline 函数从 r 中的 rtweet 包中收集的,由于 Twitter API 的限制,只能从任何帐户中提取最近的 3,200 条 tweet。自 2020 年 11 月 3 日执行最初的收集以来,没有任何国会议员发推文超过 3200 次。当额外的 tweet 被追加到之前的集合中时,会根据 tweet 的内容、tweeter 的屏幕名称以及创建时间来检查重复的 tweet。这允许新的推文被保留,任何重复的被删除。下面的嵌入式代码中提供了收集推文和检查重复项的示例代码,其中“TwitterAccounts”是包含国会账户的数据框,“Handle”是包含每个 Twitter 屏幕名称的列。

library(rtweet)Tweets <- vector()
for (i in TwitterAccounts$Handle){
  df <- get_timeline(i, n=3200) #Collects the most recent 3,200 Tweets from each handle
  Tweets <- rbind(Tweets, df) #Binds into one large df 
}#Used when appending additional tweets to existing dfNewTwitterDf <- rbind(OldTwitterDf, Tweets)
NewTwitterDf <- NewTwitterDf %>% mutate(screen_name= tolower(screen_name)) %>% #Standardizes handles to all be lowercase
  distinct(text, screen_name, created_at, .keep_all = TRUE) #Checks for dups based on tweet, user, and time tweeted

虽然确定了 1016 个与现任国会议员有关的账户,但只有 976 个账户在 2020 年 11 月 3 日至 2021 年 7 月 25 日期间发布过推文。大部分被删除的账户都是 11 月 3 日之后不再活跃的活动账户。从这些账户中,收集了指定时间段内的 541,689 条推文。这些作为分析中使用的推文。

国会议员的推特资料和行为

在对任何文本进行处理之前,对以下简单措施和国会议员的参与进行了审查。下图中,976 个账户的关注者数量(截至 2021 年 7 月 25 日)按州进行了分析和细分。在所有账户中,只有 35 个账户拥有超过 100 万的关注者,最受欢迎的账户由下面图 1 中的账户标识。

图一。按账户统计的国会议员追随者总数。作者图片

可以看到,大多数高关注度账户(超过 1,000,000 个关注者)由民主党人拥有(35 个中的 20 个)。这也反映了总体趋势。共和党国会议员账户的平均粉丝数为 106,521 人,中位数为 15,024 人,而民主党或无党派人士(与民主党一起组成两个独立参议员核心小组)的平均粉丝数为 253,327 人,中位数为 31,570 人。然而,如果将独立人士(主要由伯尼·桑德斯推动)的追随者数量从民主党的数量中剔除,平均追随者数量将降至 199,693 名,中位数为 31,496 名。不管怎样,总体趋势似乎是民主党比共和党更受欢迎。

收集国会议员推文的参与度也很重要。这是用每个账户在每条推文中获得的收藏和转发的平均数计算出来的。只有原始推文被用于这些计算,这意味着转发没有被用来准确衡量国会议员的参与度。民主党人似乎再次略胜共和党人,民主党人平均每条推文获得 1171 个收藏夹,共和党人平均每条推文获得 627 个收藏夹。由于某些成员收到了大量参与,这些数字可能被夸大了,因为民主党人的平均收藏夹数为每条推文 94 个,共和党人的平均收藏夹数为每条推文 58 个。

图二。通过账户参与国会议员的原创推文。图片由作者提供,肖像来自政府印刷局

尽管如此,看起来大多数账户收到的转发似乎与他们收藏的数量成比例,绝大多数账户收到的收藏不到 500 条。值得注意的是,自 2020 年 11 月 3 日以来,国会议员的所有推文中,只有三条获得了超过 100 万个赞,所有推文都来自众议员亚历山大·奥卡西奥-科尔特斯的个人账户(@AOC)。

文本处理

接下来,对这些账户的推文内容进行了分析。对所有推文进行预处理,使它们能够被分析。首先,所有表情符号都被转换成了文本。这是通过使用 rtweet 包中来自 Unicode.org 的“表情符号”数据帧完成的。数据框包含两列,一列包含每个表情符号,另一列包含表情符号的等效文本。当推文被标记化时,为了使事情可以解释,表情符号描述中的空格被替换为连字符,因此它们被视为单个标记,并且“表情符号”一词被附加到每个描述中。比如说,“😀被转换成了“笑脸表情符号”在此之后,一个简单的循环检查每个表情符号的推文,并将其替换为相应的文本。下面提供了示例代码。

library(rtweet)Emojis <- emojis 
Emojis$description <- str_replace_all(Emojis$description, " ", "-") %>% paste(" ", .,"emoji ", sep="-")for(i in 2284:2623){Election$text <- str_replace_all(Election$text,
                as.character(Emojis[i,1]), #Identify Emoji
                as.character(Emojis[i, 2]))} #Replace with word

接下来,标签被清理。为此,字符“#”被替换为单词“hashtag ”,以帮助识别哪些字符串是 hashtag 的一部分。随后,所有标点符号和大写字母都从文档中删除。所有的数值也被从每条推文中删除;但是,在此之前,数字“45”和“46”被转换为“45”和“46 ”,因此不会被删除。这些被选中,因为它们通常在美国政治中具有重要的语义价值:第 45 任总统特朗普和第 46 任总统拜登。

在进行任何其他处理之前,先创建一个帧。这个框架用于运行情感分析(稍后描述)。然而,为了实现这一点,需要一个没有任何进一步文本处理的框架,因为 tweets 中的单词需要保持不变,以使情感库工作。

该文档还使用 r 中的 tm 库进行词干分析。这允许时态偏差(vote,votes,voted,voting)和复数(ballot,votes)读起来是一样的。由此产生的一个问题是,单词“policy”、“policies”和“police”都被读作同一个字符(词干后的 polici)。鉴于这些词有不同的含义,尤其是在当代政治中,必须加以区分。因此,在词干化之前,单词“policy”或“policies”的所有实例都被更改为“policygov”和“police ”,而单词的其他形式保持不变以进行词干化。这使得两个词之间的区别得以保留。

这项工作完成后,停用词,也就是那些经常使用的单个意义很小甚至没有意义的词,被删除了。虽然 R 中的 tm 库包含一个停用词库,但它包含了像“states”这样的词。当用在动词方面时,这个词没有什么意义;然而,在美国政治领域,这个词需要保留。为了防止排除政治上重要的词,删除了修改后的停用词列表。

最后,使用 tm 包中的 stripWhitespace 函数删除了 tweets 中所有多余的空白。最终结果是两个数据框,一个能够在清理推文后运行情感分析,另一个用于词干提取和停用词删除完成后单词袋模型的标记化。下面提供了所有这些清理是如何完成的代码。

Twitter$text <- tolower(Twitter$text) #Removes capitalization 
Twitter$text <- removePunctuation(Twitter$text) #Removes punctuation 
Twitter$text <- str_replace_all(Twitter$text, "policy|policies", "policygov") #Chnages policy (Document) to "policygov"
Twitter$text <- str_replace_all(Twitter$text, "45", "fortyfive") #Changes number 45 to words
Twitter$text <- str_replace_all(Twitter$text, "46", "fortysix") #Changes number 46 to words
Twitter$text <- gsub("[[:digit:]]+", "", Twitter$text) #Removes all numbersTwitterSentiment <- Twitter #Creates a data frame for sentiment analysisTwitter$text <- stemDocument(Twitter$text) #Stems document
Twitter$text <- removeWords(Twitter$text, StopWords) #Removes all stopwords from a custom vector
Twitter$text <- stripWhitespace(Twitter$text) #Collapses all white space in a tweet

情感分析

一个感兴趣的领域是国会议员推文的情绪。这是一个获取一段文本并分析用于确定情绪或分配一个数值的单词的过程,以便对其积极或消极进行评级。

使用上面描述的情感框架,推文被分配了一个唯一的 ID 号,这样就可以进行标记化,并且每条推文仍然可以在以后被识别。然后使用 tidytext 包中的 unnest_token 函数将 Tweets 拆分成单独的令牌。这产生了一个数据帧,其中每行包含给定的原始 tweet ID 号和每个单词。

接下来,也从 tidytext 包中加载了 afinn 情感库。这就创建了一个包含列的数据框架:一个包含充满感情的单词和相应的情感的数据框架。情绪等级从-5(非常消极)到+5(非常积极)。然后这个库被加入到每个令牌中。如果一个词包含在一条推文中,但不包含在 afinn 库中,则该情感被标记为 n a。在此之后,每条推文被汇总,从而计算出推文中所有词的平均情绪。如果一条推文中的所有单词都是 n a,则该推文的情感编码为 0(中性情感)。下面是一个使用众议员 Val Demings (D-FL)的 tweet 的例子,以及这个过程的代码。

图 3。提取推文情感的示例。作者图片

library(tidytext)TwitterSentiment <- TwitterSentiment %>% mutate(TweetID=1:nrow(TwitterSentiment)) #unique ID for each tweetafinn <- TwitterSentiment %>% unnest_tokens(word, tweet) %>% #extracts each word in a tweet to its own row
  left_join(., get_sentiments("afinn")) %>% #Attaches sentiment from afinn library to each word
  select(-word) #removes word columnafinnTweets <- aggregate(value ~ TweetID, data=afinn, FUN=mean) %>% #Averages sentiment for all words in a tweet
  left_join(TwitterSentiment, ., by="TweetID") %>% #Adds sentiment to original df with complete tweet and data
  mutate(afinn = ifelse(is.na(value)==TRUE, 0, value)) #Changes tweets with NA sentiment to 0

如代码所示,当 tweet 中的所有单词都是 n a 时,NAs 被填充为 0。afinn 库中没有感情色彩的单词不会被替换为 0,因为这将抵消长推文。例如,在上面来自众议员 Val Demings 的推文中,如果 NAs 在聚合平均值之前填充了零,则推文的情绪将为+0.45。然而,假设她在推特上写道,“祝贺坦帕湾海盗队,感谢我们了不起的医疗工作者!”这条推文的情绪将为+0.77,因为它的中性词较少。尽管这两个短语在语义上几乎相同,但它们却有着完全不同的情感。因此,在加入 afinn 库后,除非所有单词都是 NA,否则 NA 不会被 0 填充。

国会情绪

一旦确定了所有推文的情绪,就确定了每个国会议员所有账户的平均情绪。这显示了积极(或消极)的国会议员如何公开展示自己。根据这一分析,发现所有拥有 Twitter 账户的国会议员的平均情绪为+0.56,这意味着,从整体上看,平均国会议员在推特上发表的言论略多一些。事实上,在拥有 Twitter 账户的 532 名成员中,只有 25 人有平均负面情绪。所有国会议员的平均情绪呈现在下面的地图中,情绪最高和最低的议员以及其他经常提到的国会议员分列出来。此外,情感等级(从 1 开始表示最负面,以 532 结束表示最负面)被标记。此外,没有 Twitter 帐户的三个成员在各自的州中显示为灰色六边形。每个六边形都标有州和他们代表的国会选区或参议员的“Sen”。缩写“MAL”代表“一般会员”,在适用的情况下使用。

图 4。国会议员的平均推特情绪。图片由作者提供,肖像来自政府印刷局

值得注意的一件有趣的事情是,一些被谈论最多的政客情绪最低落。在情绪排名中,几乎所有经常被谈论的国会议员都进入了倒数 100 名。这可能是因为他们利用自己的平台对政策提案、时事或其他成员进行批评或负面评论,以向其大量受众推广自己的议程;然而,没有进行正式的分析来测试这一点。

通过提及进行互动

另一个感兴趣的领域是政治家之间如何互动。为了衡量这一点,每个政党收集和汇总了每个政治家的情绪。首先,使用 Twitter 数据集中提供的 mentions_screen_name 变量,任何提到国会议员的 976 个帐户的推文都被提取出来。使用上面讨论的 tweet 情绪方法,每个政治家提到他们的账户时的平均情绪被确定并按党派分开。这意味着民主党人和共和党人的平均情绪可以由每个国会议员来决定。下面的图 5 和图 6 显示了调查结果,以及每个国会议员被一个政党提及的次数。同样,出于分析目的,两位独立参议员都被视为民主党人,但在图表中以独立人士的身份出现。

图 5。基于共和党推文的国会议员平均情绪。图片由作者提供,肖像来自政府印刷局

图 6。基于民主党推文的国会议员平均情绪。图片由作者提供,肖像来自政府印刷局

有趣的是,图表惊人地相似,几乎所有的政治家,不管是哪个党派,都聚集在 0 以上,这意味着,在大多数情况下,所有成员都是以积极的态度被提及的。0 以下的,对于双方来说,几乎都是对方的专属成员。然而,也许最有趣的是,对方的成员大量聚集在 x 轴上的 0 附近。这意味着双方几乎都不会在推文中提到对方。这有两大含义。首先,许多会员的平均情绪是由一两条推文决定的。因此,四肢是高度和应采取的一粒盐。第二,在一个两党合作几乎成为每项立法核心的时代,政客们在谈论自己的成员时倾向于坚持自己的成员,至少在 Twitter 上是这样。虽然积极的一面是,在大多数情况下,政客们没有在推特上负面地谈论对立的政党成员,以促进合作并给选民和追随者留下两党合作的印象,但政党之间需要进行更多的互动。

对于这一点和进一步进行的情感分析,应该注意的一个重要警告是,根据 afinn 库,一些推文可能看起来是负面的,但在上下文中不是。众议员孟昭文(纽约州民主党人)就是一个例子。她是民主党人在推特上提到最多的政治家之一(被提到 440 次),民主党人也有轻微的负面情绪(情绪为-0.15)。这并不是因为她被认为是不受欢迎的,而是因为她是新冠肺炎仇恨犯罪法案 H.R. 1843 的发起人。当提到她时,许多国会议员也提到了她的法案,阿芬图书馆正在将一种负面情绪附加到“仇恨”一词上。虽然对于特定的例子来说,这是一个值得注意的重要警告,但对推文的整体分析更能反映 afinn 图书馆坚定的观点,而不是像这样的例外。

对问题的看法

虽然国会议员可能不会经常谈论彼此,但他们有一个重叠的领域是对社会和政策问题的讨论。确定了所有推文的观点后,可以检查成员如何讨论当代问题。

随机选择了四个有争议的当代问题进行研究:黑人的命也是命、移民、基础设施和最低工资。在 2020 年的竞选活动中,一直到第 117 届国会的立法,这些问题都被频繁讨论,因此产生了许多推文,以便进行彻底的分析。

仅使用提到这些问题的推文,计算了所有国会议员的平均情绪(如果他们有关于所述问题的推文)。下面的图 7、图 8、图 9 和图 10 展示了他们对每个问题的看法以及发推文的频率。

图 7。国会议员提及黑人的命也是命的推文的频率和平均情绪。图片由作者提供,肖像来自政府印刷局

图 8。国会议员提及移民的推特频率和平均情绪。图片由作者提供,肖像来自政府印刷局

图 9。国会议员提及基础设施的推文的频率和平均情绪。图片由作者提供,肖像来自政府印刷局

图 10。国会议员提及最低工资的推特频率和平均情绪。图片由作者提供,肖像来自政府印刷局

从图表中可以明显看出,对于几乎每一个问题,两党在观点上都有明显的分歧。即使在基础设施的情况下,几乎所有的推文在情绪上都略有积极,似乎民主党人整体上仍比共和党人更积极。就推特的频率而言,似乎两党在移民和基础设施问题上有类似的趋势,他们党的大多数人都提到过几次这个问题,少数成员经常在推特上谈论这个问题。对于最低工资的问题,看到几乎所有的推文热门都是民主党人。

至于黑人的命也是命,可以看出,与红色相比,图表中绝大多数是蓝色圆点。这表明,总体而言,与共和党人相比,更多的民主党人至少在一条推文中提到了黑人的命也是命。有趣的是,这个问题最频繁的推特是众议员 Majorie Taylor Greene (R-GA)。事实上,她占了所有共和党关于黑人的命也是命的推特的 25%以上。鉴于她在这个问题上的直言不讳,这并不令人惊讶;但是,值得注意的是,这是四个问题中唯一一个顶级高音有负面情绪的问题。应该注意的是,关于黑人的命也是命的推文自然倾向于负面,因为围绕它的事件(如谋杀)会对 afinn 图书馆产生负面影响。因此,负面情绪可能不反映政治家对问题的看法,而是反映他们选择关注什么事件。

虽然各方在问题上似乎存在分歧,但应进行测试来检验这种分歧。因此,对双方在两个问题上的平均情绪差异进行了双尾学生 t 检验。此外,为了检查这些差异的影响大小,计算了 Cohen's d。所有这些测试的结果如下表所示。

表 1。统计分析结果显示,各方推特情绪存在差异。作者图片

与共和党人的平均情绪相比,民主党人在所有四个问题上的平均情绪之间存在高度静态的显著差异。除基础设施外,所有问题中,民主党人的平均情绪是积极的,共和党人的平均情绪是消极的。根据科恩的 d 估计,基础设施和黑人的命也是命的问题被视为具有较小的影响规模。因此,尽管各方各自问题的平均情绪存在差异,但这种影响的大小相对较小;然而,根据科恩的估计,最低工资和基础设施问题分别产生了中等和大的影响大小。因此,根据关于它们的推文,这些政策问题出现了最大的党派分歧。令人吃惊的是科恩对移民的估计特别高。在 0.93,这个大的影响大小表明,这是当民主党人和共和党人基于他们的推文情绪的观点差异最大时选择的所有问题的政策领域。

谈论问题

鉴于民主党人和共和党人在政策问题上的推文方式存在明显差异,看看每个问题最常使用的关键词会很有趣。为此,使用了移除了停用词和词干的 Twitter 数据帧。再一次,任何提及四个社会或政策问题之一的推文都被分开。从那里,使用 tidytext 包的 unnest_token 函数部分,计算出一条 tweet 中所有 unigram(一个单词的令牌)和 bigrams(两个单词的令牌)的频率。然后对每个政党的这些频率求和,以收集一个政党在关于特定政策或社会问题的推文中使用一元词或二元词的总次数。独立推特再次被归入民主党。

在此之后,找到了一个问题的前 25 个单词或双词。下面的四张图展示了民主党人和共和党人在推特上最常见的标志。

图 11。按党派分列的关于黑人的命也是命的推文中出现频率最高的词和短语。作者图片

图 12。按党派分列的关于移民的推文中最常用的词和短语。作者图片

图 13。按政党分列的关于基础设施的推文中出现频率最高的词和短语。作者图片

图 14。推特上关于政党最低工资的最常用词和短语。作者图片

这些文字云不仅揭示了各方对某一问题的看法,而且有助于解释他们的观点趋势。最令人兴奋的领域之一是政党在黑人的命也是命问题上的分歧。正如在科恩的 d 测试中看到的,情绪差异的影响大小被认为是很小的。然而,这可能是因为双方都在负面地谈论这个问题,但方式不同。从单词 clouds 可以看出,“抗议”是民主党人经常使用的词之一,根据 afinn library,它携带了-2 的情绪。与此同时,共和党人经常用“暴乱”和“暴力”这两个词来形容黑人的命也是命,这两个词分别带有-2 和-3 的情绪。在这里,我们可以看到,虽然双方都在使用负面的词语,但抗议和暴乱的内涵是截然不同的。还应该重申的是,众议员马乔里·泰勒·格林(Marjorie Taylor Greene)占了所有共和党关于黑人的命也是命的推文的大约 27%,这意味着这个词云可能更能反映她的观点,而不是共和党的整体观点。尽管如此,她在这里的突出表明了她对这个问题的关注,但也明显缺乏共和党的推文,特别是与民主党的推文数量相比

需要注意的一个有趣的事情是,“拜登”是共和党推文中所有问题使用频率最高的词之一;然而,“拜登”并没有出现在民主党推文的任何词云上。进一步分析的一个有趣领域是确定拜登的名字在什么背景下被使用:这是否仅仅因为他是现任总统(因此是一个重要的观点),或者更确切地说是因为他们在批评他在这些问题上的做法。

关键外卖

从进行的情感分析和关于问题的推文符号化中,可以看到一些关键的收获。

  1. 民主党人和共和党人在推特上谈论问题的方式有明显的不同。从我们选择的社会和政策问题来看,t 检验和科恩的 d 检验表明,两党的情绪有明显的差异。再看看 clouds 这个词,可以看出民主党人和共和党人很少用类似的词来描述选定的问题。这表明,国会议员不再将 Twitter 作为推动两党合作的平台,而是加倍重视党派分歧,并向选民公开这一点。
  2. 共和党人倾向于在推特上发布比民主党人更负面的问题,即使是在有两党支持的问题上,如基础设施。这种现象的发生可能有几个原因,包括选择的主题,当前政府的民主,或 Twitter 的总体行为。另一种可能性是,这显示了国会的党派分歧,即使在政策协议方面,情绪和热情也是不平等的。
  3. 频繁或充满激情的推特用户有能力在推特上主导一个政党的情绪和观点。正如众议员马乔里·泰勒·格林(Marjorie Taylor Greene)所见,如果一个政客在推特上发布足够多的信息,他就可以主导一个问题。在较小的程度上,这也适用于众议员 Pramilia Jayapal (D-WA),他被发现是 4 期 select 中 3 期的最频繁的推特用户。
  4. 虽然民主党在最受关注的账户方面领先,但共和党高层正在接近相同的参与度。民主党成员拥有 35 个账户中的 20 个,粉丝超过 100 万,众议员亚历山大·奥卡西奥-科尔特斯在她收到的平均点赞和转发中脱颖而出;然而,获得最多参与的账户在共和党和民主党之间的比例接近 50:50。
  5. 要想兴风作浪,你可能必须消极。正如在所有议员的情绪图中看到的,一些谈论最多的人被认为是所有国会议员中情绪最消极的人。从这一分析中,还不清楚是负面情绪得到了更多的关注,还是最知名的国会议员自然地发了更多负面的推文。

需要进一步检查的领域

有几个方面需要进一步检查。首先,应该审查更广泛的问题。虽然这四个问题因其普遍性而被选中,但除了基础设施,它们都是亲民主党的问题(民主党正在推动的问题)。应该检查共和党人正在推动的问题,看看民主党人如何在推特上谈论这些问题。

此外,各方讨论问题的不同方式可以呈现出迷人的洞察力。例如,当谈到枪支立法时,看看“监管”、“控制”或“第二修正案”如何影响参与度(点赞和转发)和情绪,可以揭示出政党如何向其追随者提出这些问题的见解。

最后,对于一些政策问题,使用不同的情感库可能更有用。正如我们在黑人的命也是命看到的,带有负面情绪的词语自然会被双方使用;然而,讨论“骚乱”和“抗议”显示了在这个问题上的不同观点,这在语义价值中不容易捕捉到。使用不同的库或不同的过程可能能够更好地捕捉各方之间的这种差异。

感谢您的阅读。如有任何问题,欢迎在 brm2143@columbia.edu 给我发电子邮件,或通过 LinkedIn 这里 联系我。

注:所有国会议员的照片都是他们的官方肖像,因此是公共领域的一部分。照片取自 政府印刷所的员导照片

带走我的漂移

原文:https://towardsdatascience.com/take-my-drift-away-650d0cd92168?source=collection_archive---------19-----------------------

在你的机器学习模型中定义、测量和修正漂移

这篇博客是与达美航空公司数据科学经理 艾华 合作撰写的。在这一块,华和Aparna Dhinakaran、CPO 和Arize AI的联合创始人,共同探讨如何监控和排除模型漂移。

作者图片

作为一个 ML 从业者,你可能听说过漂移。在这篇文章中,我们将深入探讨什么是漂移,为什么跟踪漂移很重要,以及当漂移发生时如何排查和解决根本问题。

什么是漂移

首先,什么是漂移?漂移是分布随时间的变化。可以对模型输入、输出和实际值进行测量。漂移可能是因为您的模型变得陈旧,坏数据流入您的模型,甚至是因为敌对的输入。

现在我们知道了什么是漂移,我们如何跟踪它呢?从本质上来说,跟踪模型中的漂移相当于跟踪参考分布和当前分布(生产)之间发生了什么变化。

作者图片

模型不是一成不变的。他们高度依赖接受训练的数据。特别是在数据不断发展的高速增长企业中,考虑漂移对于确保您的模型保持相关性非常重要。

模型输入的变化几乎是不可避免的,您的模型不能总是优雅地处理这种变化。一些模型对输入分布的微小变化具有弹性;然而,由于这些分布与模型在训练中看到的相差甚远,手头任务的性能将受到影响。这种漂移称为特征漂移数据漂移

如果唯一能改变的是你的模型的输入,那就太好了,但不幸的是,事实并非如此。假设您的模型是确定性的,并且您的特征管线中没有发生任何变化,如果它看到相同的输入,它应该会给出相同的结果。

虽然这令人放心,但如果正确答案的分布(实际值)发生变化,会发生什么呢?即使你的模型做了和昨天一样的预测,它今天也会出错!这种实际偏差会导致模型性能的下降,通常被称为概念偏差模型偏差

我如何测量漂移?

如前所述,我们通过比较培训和生产之间的输入、输出和实际值的分布来测量漂移。

但是你如何量化这些分布之间的距离呢?为此,我们有分布距离测量。举几个例子,我们有

  1. 人口稳定指数
  2. Kullback — Leibler 散度( KL 散度
  3. 瓦瑟斯坦距离
  4. Kolmogorov Smirnov 测试

虽然这些分布距离度量在计算距离的方式上有所不同,但它们从根本上提供了一种量化两个统计分布差异的方法。

这很有用,因为你不能通过观察图表上的曲线来建立漂移监测系统。如果你有一个客观的、可量化的方法来衡量你的投入、产出和实际的分布是如何随时间变化的,那将是最好的。

作者图片

例如,在上面的图中,我们看到了我去年和前一年的支出分布的比较。Y 轴代表我在每一个类别中花费的钱的百分比,如 x 轴所示。为了查看我的资金分配在过去一年中是否有显著变化,我们可以计算这两种分布之间的总体稳定性指数( PSI )。

对于预算中的每个类别,我们计算参考分布 A(我去年的预算)和实际分布 B(我今年的预算)之间的百分比差异,并将其乘以自然对数(A %/ B%)。对于这些类别中的每一个,取这个值的总和,这就是我们的 PSI。

PSI 越大,您的分布越不相似,这允许您设置分布漂移的阈值警报。

不管您使用的分布距离度量是什么,重要的是不仅要测量分布中的漂移,还要测量这些距离度量与重要业务 KPI 和度量的关系。通过这样做,您可以开始了解漂移实际上会如何影响您的客户,并帮助您了解什么样的漂移阈值会触发对您团队的警报。

作者图片

我可以重新培训我的模型吗?

当我们发现一个训练好的模型漂移了,我们该怎么办?第一个想法可能是,“让我们重新训练它”!虽然再培训通常是必要的,但如何再培训需要更多的思考。简单地将最新的数据添加到您的训练集中并重新部署相同的模型架构可能无法解决问题。

首先,您必须小心如何对这些新数据进行采样并在模型中表示它们。如果您添加了太多的新数据,导致训练集中的数据过多,那么您就有可能过度适应这些新数据。这样做的话,您的模型将来可能无法很好地泛化,并且可能会影响它在以前没有问题的输入上的性能。

另一方面,如果你只添加了几个例子,你的模型很可能根本不会有太大的变化,而且你的模型可能仍然会犯你想要解决的错误。

您可以通过对损失函数中的示例进行加权来调整这种权衡,以在这两种竞争力量之间取得适当的平衡。衡量如何平衡这种权衡的一种方法是,在一个全局采样的排除集上测量您的性能以近似您的泛化性能,并在另一个仅从较新的数据群体中采样的排除集上测量您的性能。如果你在全局保持开始时表现很好,但不是新的数据,你可以尝试在你的训练集中增加新数据的权重,反之亦然。

虽然,在许多情况下,重新培训你的模型是正确的解决方案,但是一些变化是如此的根本,以至于简单的重新培训不能解决任何问题。如果您不能在重新训练的模型上获得可接受的验证性能,可能是时候重新开始了。如果你的业务发生了根本性的变化,你的模型可能也需要改变。

如何排除漂移故障

作者图片

这一切都始于一个警报——一封电子邮件或一个通知,告诉我们有什么不对劲。通常,跟踪性能变化和输入数据的变化是一种很好的做法,因为这些变化可能会提供性能变化的答案。了解特定数据片或特定日期的漂移发生在哪里也很重要。这将有助于诊断模型并提出解决方案。

当重大漂移警报触发一段时间后,需要进行系统评估。决定一个漂移变得有多重要通常是一种艺术而不是科学,因为它取决于预测如何被使用以及预测的商业价值。但是这里有一些步骤让你开始解决漂移。

1.重新提取训练数据

确定哪些输入特征或结果变量发生了漂移,并了解它们的分布是如何变化的。仔细考虑再培训应该包括什么时间段。可以使用重采样或加权观察来重建更平衡的训练数据集。

2.特征工程

有时,我们会注意到一些特性发生了显著变化,但并没有导致模型性能问题。这是不容忽视的,因为这表明了这些特征和结果变量之间的关系。重新构建和选择特征以适应该数据集中的新动态。

这也是与模型的最终用户联系的好时机,以了解他们的业务流程是否发生了变化。通常需要新的特性来捕捉变化。

3.模型结构

有时,模型结构也应该被重新考虑。例如,如果只有一部分预测受到影响,分层模型有助于在不改变整个模型的情况下解决这一问题。

如何走在这个前面?

如果你在消防演习中做这些事情,那将是最糟糕的。您接到业务合作伙伴的电话,要求您解释为什么模型在一天内表现不佳,因为他们需要向利益相关者解释不良的业务结果。用一组特定的数据点来解释一个模型的表现从来都不容易,尤其是在有压力的情况下。它还会导致人们做出短视的决定,过度调整模型以捕捉最新趋势。

一个好的做法是设置一个节奏来定期检查模型性能,而不是完全依赖警报来指示何时出现了问题。定期审查有助于跟踪不断变化的业务动态和主动思考模型调整。此外,建立一个与最终用户沟通的常规渠道,听取他们对模型的反馈,或者了解即将到来的过程变化也是很重要的。在一天结束时,模型在那里支持最终用户。因此,用户感知与模型性能指标同等重要。

把漂移带走!

正如我们所讨论的,漂移是 ML 可观测性的一个方面,测量是不够的。拥有解决漂移问题的工具有助于改善模型的寿命。

联系我们

如果这个博客引起了你的注意,并且你渴望了解更多关于机器学习的可观察性和模型监控,请查看我们其他的博客和资源!如果您有兴趣加入一个有趣的 rockstar 工程团队,帮助模型在生产中取得成功,请随时联系我们,并找到我们的空缺职位!

使用 Manim 将您的 Python 可视化提升到一个新的水平

原文:https://towardsdatascience.com/take-your-python-visualizations-to-the-next-level-with-manim-ce9ad7ff66bf?source=collection_archive---------8-----------------------

提示和技巧

这个 Python 包创建了令人印象深刻的动画,既能让你的观众惊叹,又能清楚地展示数学和编程概念。

高效地将数学思想和结果传达给各种不同的受众是每个优秀的数据科学家都需要的技能。当向非技术观众演示时,包含什么信息总是一个大问题。

来自数学背景,我总是希望包括我的结果背后的过程的简要的高层次的解释。问题是,解释机器学习概念背后的想法并不容易。对于大多数更关心可行见解的股东来说,解释这些概念的好处可能不值得我们在演示中花费时间和精力。

著名的 Lorenz 吸引子蝴蝶模式的范例——图片由作者提供。

虽然大多数时候我们不会在演示文稿中包含技术信息,但仍有必要包含技术信息的时间和地点。

也许你不是在向股东听众演讲,而是在向你的人工智能/人工智能研究团队演讲。或者,也许你很幸运,你的非技术老板对理解数据科学过程感兴趣,并要求你建立一个全面的演示文稿。

在这些情况下,最重要的事情是用快速和简洁的方式有效地解释先进的数学思想。向相对不熟悉的人传达数学思想的最佳方式可能是从高层次清晰地说话,而不是漫无边际的技术细节。

我相信好的视觉化是我们在做这件事时所拥有的最有效的工具。

什么是曼尼姆?

Manim 是一个建立在 Python 之上的强大的数学动画包。如果你的目标是通过动画创建数学思想的高级解释,那么看看 Manim 就知道了。

如果你曾经有幸在 YouTube 上观看过 3Blue1Brown 的视频,格兰特使用 Manim 来创建他所有的动画,并且是以大多数人能够开始理解的方式有效地交流非常复杂的数学思想的最佳之一。如果你真的想看看 Manim 能做些什么,去看看他的视频,你会印象深刻的。

即使你不打算像 3B1B 一样在你的演示中解释数学概念,一个伟大的可视化结果动画也可以吸引你的观众,并使其更上一层楼!

Manim 非常强大,因为它构建在 Python 之上,允许我们利用它的编程工具。这个想法将在下面的例子中展示,我们将学习构建一个基本的 Manim 场景,然后学习如何应用一些 Python 来将相同的动画带到下一个级别。

Manim 入门

首先,一些家务。在将 Manim 安装到您的 Python 环境之前,检查他们的安装文档,因为它确实需要一些依赖项,比如ffmpegpycairo

因为我运行的是较新的苹果硅 M1 芯片,我在安装这些依赖项时遇到了一些问题。所以我选择按照安装指南在 Google Colab 笔记本上运行 Manim,它运行得很流畅。我将把它推荐给任何正在寻找一种不用本地安装就能快速试验 Manim 的方法的人。在 Colab 上运行的说明在这里的 Manim 文档中列出,我将在下面简要概述它们。

首先打开一个新的 Google Colab 笔记本。然后在笔记本顶部复制、粘贴并执行以下代码:

!sudo apt update
!sudo apt install libcairo2-dev ffmpeg \
 texlive texlive-latex-extra texlive-fonts-extra \
 texlive-latex-recommended texlive-science \
 tipa libpango1.0-dev
!pip install manim
!pip install IPython — upgrade

这应该会在 Colab 环境中设置依赖项并安装 Manim。接下来,重启你的运行时(按照上面输出的指示),然后你就可以通过执行from manim import *来导入 Manim 了。*注意:以后重新启动此笔记本时,您可能需要重新运行上面的安装代码。

创建一个 Manim 场景

Manim 的操作是基于类的;创建一个动画通常从定义一个从 Manim 场景类(或三个场景)派生的类开始。动画本身的脚本将放在 Scene 的 construct()方法中。

class ExampleAnimation(Scene):
  def construct(self):
     . . . #animation script here

在这个构造函数中,我们现在可以使用包中包含的各种可用对象(Manim 称之为 Mobjects)、轴、跟踪器以及 play 和 animate 方法来构建动画。

如果您在本地运行 Manim,那么您可以在您的终端中用manim ExampleAnimation或任何您命名的类来调用脚本。如果你像我一样选择了在 Google Colab 中工作,为了呈现包含脚本的单元格的输出,你需要在单元格的顶部添加一行额外的神奇代码。复制并粘贴

%%manim -qm -v WARNING ExampleAnimation

在单元格的顶部,用您使用的名称替换 ExampleAnimation。运行单元将产生一个动画输出,并带有下载选项。

建造一座建筑物

我将在这次演示中使用的示例动画是基于他们文档中的 Manim 示例库中的一个。在这个动画中,曲线上的一个点向函数的最小值移动。我建议你在继续之前看看这个和其他的例子,因为下面的矿从零到一百真的很快。

在我的动画中,我添加了更多的天赋,圆点从页面的顶部开始,下降到曲线上,然后沿着曲线滑动找到局部最小值。该脚本相当长,很难在媒体上观看;请导航到这个 Colab 笔记本来查看实际代码,因为我在下面描述了这个过程背后的想法。该动画的构建需要几个步骤:

  • 首先定义所有特征;轴和极限、点、函数及其图形。将它们添加到 self。
  • 创建两个 ValueTracker 对象,一个用于 x 维度,一个用于 y 维度。这些 ValueTracker 对象可以随着它们的变化而变化。
  • 请注意,当我们为更新程序设置点的初始点和位置时,我们不能只调用点(x,y)。我们必须调用它作为我们定义的轴的属性,并使用 coord_to_point 方法,以便 Manim 理解。那看起来像ax.c2p(. . .)
  • 为点移动对象创建一个更新程序。创建动画时,更新程序会检查并更新每一帧的对象位置。我们实际上需要两个这样的更新函数,一个将点从天花板上放下,一个将它沿着线滑动。
  • 第一个更新器使用move_to()方法将点移动到由 ValueTrackers 定义的适当位置。该点最初被放置在其“初始位置”,但每帧被移动到(ValueTracker_X, ValueTracker_Y)
  • 第一个动画(称为self.play(ValueTracker.animate.set_value(. . . .)))将 Y ValueTracker 从其初始值更改为在 X ValueTracker 位置评估的函数值。
  • 这里也使用了像self.wait(t)这样的方法,允许我们让动画静止‘t’秒钟。
  • 在第一个动画之后,我们必须移除点更新器并创建一个新的。
  • 第二个更新器将使用move_to()方法来保持点位于点(ValueTracker_X, function(Value_Tracker_X))上。随着 X 的变化,Y 的值被设置为在 X 处评估的函数值。
  • 然后,第二个动画将点的 X 值设置为函数最小值的 X 值。使用.argmin()方法计算并提取最小值的 x 索引。
  • 运行动画并保存它!

这些步骤的全部代码可以在我的 Google Colab 笔记本上看到,这是这个 Manim 项目的代码。单点示例的输出如下所示:

最小单点—作者提供的图像

触及表面

信不信由你,这部动画并没有真正触及为什么 Manim 如此强大的表面。一个小点在动?这其中的创意在哪里?线上其他地方的点呢?不难想象我们下一步想做什么——创造同样的东西,但是用一堆点!幸运的是,python 中的编程概念,如 lists 和 for 循环,使这变得非常简单。

多点!

在展示这个动画的整个脚本之前,我将描述一些我们需要做的重要改变。首先,我们需要更多的点。使用 list comprehension 创建尽可能多的对象非常简单,然后将它们全部添加到一个VGroup()类中,该类跟踪一组矢量化对象。

此外,因为每个点将位于不同的位置,所以我们需要对应于每个点的 X 和 Y 对值跟踪器。幸运的是,使用列表理解创建它们也很容易。这里我们暗示 n 索引的点将被附加到 n 索引的 ValueTrackers。对于动画的每一步,我们仍然只需要一个 Updater 函数,但是它要求我们跟踪点的索引和 ValueTrackers,这样它们才能正确应用。同样,python 使这种索引匹配变得简单明了。

然后,我们需要为每个点创建一个动画,如上所述,其中它期待其正确的索引值跟踪。这些动画可以方便地存储在一个列表中,并且可以同时调用。我们还可以在这里利用 python 中的条件语句,因为我们需要两组动画,一组用于移动到左局部最小值的点,另一组用于移动到右局部最小值的点。这就像在列表理解中创建动画一样简单,它检查点的初始点是否在函数中心相对最大值的两侧。

我还在这个版本中添加了一些动画方法,比如LaggedStart(),它错开了每个点的动画开始,给动画一个非常平滑、令人愉悦的外观。

在本文中包含整个代码有点多,所以请再次打开并参考这个 Colab 笔记本获取脚本。输出如下所示:

9 点示例—作者提供的图像

哇,看起来比单点动画好多了!!

甚至更多的点!

从 1 点到大于 1 点需要相当大的变化。但是,现在我们已经有了一个可以做 1 以上事情的脚本,python 使得改变我们想要的点数变得非常容易。它就像改变创建我们的点和值跟踪器的列表的限制一样简单(加上对动画播放时间的一些改变,所以它看起来仍然很平滑)。

下面我制作了一个 100 点的动画,只对上面的代码做了一些改动。但是我觉得有点过了…看看能不能操纵剧本做一个 50 点的动画。你只需要改变 3 个简单的东西(VT 列表和 Dots 列表)就可以让它工作。之后,你可以玩动画设置,让它看起来平滑美观。

100 点!—作者图片

结论

在技术演示中,出色的视觉效果是吸引观众的最佳方式之一。人们对视觉解释的反应很好,尤其是害怕数学的非技术人员。用 Manim 来弥合这个鸿沟吧!即使你没有展示技术信息,你的展示中令人难以置信的 Manim 动画也会吸引你的观众,让你的老板们惊叹不已!

参考资料:

我没有在我的 Manim 教程笔记本中包含洛伦兹吸引子动画。如果你很好奇它是怎么产生的,你应该自己试一试;)或者给我发邮件提问,我会很乐意联系到你——jonny.hofmeister@gmail.com

让您的 SQL 从优秀走向卓越:第 1 部分

原文:https://towardsdatascience.com/take-your-sql-from-good-to-great-part-1-3ae61539e92a?source=collection_archive---------3-----------------------

有了 cte,你可以走得更远。

上周,我看到一条推文,这让我想到:如果可能的话,有哪些 SQL“窍门”我会很快回去自学?这个简单的问题很快变成了一系列文章,阐述了我最喜欢的一些方法,解释了它们为什么有用,以及如何使用它们。我选择的主题是:

第 1 部分:常见的表表达式

第二部分:关于那些日子的一切

第三部分:其他连接

第 4 部分:窗口功能

有没有一个被低估的 SQL 方法对您有所帮助?给我留言吧!

好了,接下来是第一部分:CTE!

什么是 CTE?

公共表表达式(cte)是在单个查询中可用的临时表。

它们使用以下语法:

WITH cte_name AS 
  (SELECT ... FROM ... )
SELECT * FROM cte_name; 

为什么它们很重要

为了说明为什么这种看似良性的查询构造如此有益,让我们看一个例子。假设我有两张桌子:

  1. 比赛:网球比赛统计的大文件
  2. 球员:网球运动员元数据文件

网球比赛预告

网球运动员预览

我想知道每位选手在获得第一个大满贯决赛 时的年龄。

要做到这一点,我需要从表中找到每个球员赢得大满贯的第一个时间,然后使用 球员 表将该日期与他们的生日进行比较。**

解决这个问题有很多方法,但大体上可以归结为两种方法:

作者图片

虽然这两种方法在长度上相似,并且应用的逻辑相同,但是 CTE 方法有几个明显的优势:

1.比较好理解。

如果回答这个问题的第一步包括获得每个球员赢得大满贯的第一时间,那不应该是你读的第一件事吗?

对于子查询,执行的顺序几乎是不可能辨别的,因为您不得不扫描最低级别的缩进,并一步步向上,直到最后到达第一行。

cte 让您能够以一种简单明了的方式构建查询,这不仅有利于您编写查询,也有利于其他被迫解释查询的人。

2.更快的迭代。

如果我想知道最年轻的球员进入大满贯决赛但失败了怎么办?或者是赢得任何锦标赛决赛的年龄最大的球员,而不仅仅是大满贯?

我可以很容易地调整我的 CTEgrand _ slam _ matches来回答这些问题,而不必担心我是否在正确的子查询中进行了更改。

当我们与数据进行“对话”时,很多数据分析都涉及到对查询的快速迭代调整。当我们有复杂的查询时,这些“调整”会膨胀成痛苦的任务;cte 为您提供了一个常识性的结构来快速完成这些调整。

3.可信验证

像每个优秀的分析师一样,我会总是验证我的结果(😉),而 cte 让这变得简单多了。因为我可以检查每个单独的 CTE,所以我可以快速识别任何验证错误的来源,并对单个逻辑步骤进行故障排除,而不是处理混乱的子查询。

我想那是 40——如果你还记得分数的话,我很乐意。

CTE 加电👾

CTE 在单个查询级别上的好处很多,但是如果我们能够利用 CTE 的好处,并将其应用于我们的整个分析,而不仅仅是一个查询,会怎么样呢?

随着 SQL 笔记本最近的进步,我们可以开始看到当我们将 CTE 构造应用到更大规模时会有什么可能。

在这些笔记本中,每个单元格代表一个 CTE,每个单元格都可以被任何其他单元格引用,实际上创建了一个完整的 cte 连通图。

我们的分析在 Count.co 完成

或者作为一个连通图:

我们的分析表现为一个连通图。图片作者。

这能让你做的事情令人惊讶。您仍然可以享受单个 CTE 的好处,例如在逻辑流中构建分析,进行快速迭代和验证检查,此外,它还允许查询和文本的参数化。

累积的效果更像是一个应用程序,而不是一个查询。

如果我们想扩展我们的分析以包括更多的查询,我们可以将更多的单元格链接在一起。如果我们想要包含全局过滤器,我们可以将它们添加到笔记本中,并像其他单元格一样将它们链接起来。

图片作者。

你可以在这里看到上面这张连通图的笔记本:


您可以在这里了解更多关于 SQL 笔记本的信息

CTE 最佳实践

  1. 使用唯一且有意义的列名和 cte 名(请不要用“cte”作为…)
  2. 试着把它们变成“通用的”,这样你就可以很容易地返回并调整逻辑

进一步阅读

敬请关注第 2 部分即将推出的内容!

让您的 SQL 从优秀走向卓越:第 2 部分

原文:https://towardsdatascience.com/take-your-sql-from-good-to-great-part-2-cb03b1b7981b?source=collection_archive---------4-----------------------

当你打电话时,并不总是在那里,但总是准时。

这是关于我最看重的 SQL“技巧”的 4 部分系列的第 2 部分。查看该系列中的其他内容:

第一部分:常见的餐桌用语

第 2 部分:所有关于这些日期的内容

第三部分:其他加入

第四部分:窗口功能

您对一个被低估的 SQL 技巧有什么建议吗? 让我知道

但是,现在我们来看主要事件:

SQL 中的日期和时间⏰

无论您编写 SQL 有多长时间,处理日期和时间从来都不是一项受欢迎的任务。它们非常棘手,会在你最意想不到的时候耽误你几个小时。

因此,在这一期的系列文章中,我将介绍一些有用的日期/时间“技巧”,新手和专家都可以从中受益。

行动卡🎮

在深入研究代码之前,评估一下我们可以使用的高级工具是很重要的。这就像玩棋盘游戏疫情(太快了?),并且让你的角色的动作牌总是可见,这样你就能在每一回合都被提醒该做什么动作。

下面是我们的 SQL 日期/时间操作卡,包括我们可以在日期/时间执行的操作。在每个 is 动作中有一系列单独的函数和语法,但是在这个高层次上计划我们的分析是有帮助的。

例如,如果您有一些带有字符串日期列的销售数据,而您的老板想要查看季度合计,您将需要:

  1. 将字符串解析成日期(“2020 01 10”➡️2020–01–10)
  2. 将日期截短为每个季度的开始日期(2020 年 1 月 10 日➡️ 2020 年 1 月 1 日)
  3. 将这些日期以图表或表格的形式显示出来(2020 年 1 月 1 日➡️“2020 年第一季度”)

SQL 日期/时间动作卡。图片作者。

SQL 的每一种方言都有自己的函数来执行这些操作,可悲的是,还有自己的语法。因此,我不会煞费苦心地详细介绍每一个动作,而是将您引向以下指南:

我的 MVHs(最有价值的黑客)🏆

好了,现在有趣的部分——什么是实际的、有用的技巧。以下是我最喜欢的日期/时间“黑客”列表:

1.隐式铸造

大多数数据库都有一种“隐式转换”的感觉,这意味着在某些情况下,你可以键入一个日期字符串(“2020–01–01”),数据库会自动计算出你想要使用的日期是 2020 年 1 月 1 日。

这对于日期列的过滤特别有用。

例如:下面的查询将获取 2017 年伦敦的所有天气数据。

为什么我喜欢它: 如果我们没有这个,我就必须总是将我的字符串转换/解析为日期,或者在过滤时使用提取函数来获得我想要的日期部分。但是对于像这样简单的日期范围,使用字符串格式“YYYY-MM-DD”作为过滤器是我永远不会停止的事情。

ℹ️ 警告:与我的下一个观点直接冲突的是,大多数数据库都要求这些日期采用标准的 ISO 格式:“YYYY-MM-DD”,但有些数据库允许你自定义这种格式。

2.放眼全球

作为一个生活在欧洲的美国人,每当我看到 2020/10/06 这样的日期,我都会有一瞬间的恐慌,我不确定我们是在谈论 10 月 6 日还是 6 月 10 日。

而且,当我看到 2020/10/06 上午 10:00 的时候,我更迷茫了。是当地时间上午 10 点吗? UTC ?夏令时?

即使您的数据和团队都位于同一时区,考虑如何存储和显示日期和时间也是至关重要的。

为了解决这个问题,我喜欢:

  1. 始终使用 UTC 时间戳,如果需要,为时区调整的日期和时间创建新列
  2. 当显示日期时,我总是在最后一步将日期重新格式化为:年月日(2020 年 10 月 6 日)。(但我知道,世界上大多数国家可能会有不同的做法😂)

示例:在对我的网飞数据的分析中,每个程序的开始时间都以 UTC 时间戳的形式给出。但是为了计算出一天中我看电视最多的时间,我需要将它转换成当地时间。

标准化我的全局时间戳的格式。

我喜欢它的原因: 让我安心地看到用 UTC、当地时间表示的日期和时间,这样我就可以选择如何处理每个问题。

ℹ️ 警告:每个工具都有不同的默认日期显示方式。例如,在许多 BI 工具中,时间戳会自动调整为本地时间,因此您定制的转换可能是多余的。如果有疑问,请更改您的计算机时区,看看查询输出是否会改变!

3.生成日期

如果我想知道事情什么时候没有发生,而不是在我们的数据集中找出事情发生的时间,会怎么样?那个用户不是什么时候用过我们的 app?

这种工作需要一组完全不来自我们数据的统一日期。

这在做队列分析时特别有用。

例子:假设我想知道在给定的时间段内(包括我不看任何网飞的时候),我每天看了多少小时的电视。我需要生成我想看到的日期,然后将其加入我的网飞数据。当我那天没有看任何电视时,该日期应该会出现一个空值:

我喜欢它的原因:发现某件事情没有发生的频率有时就好像并不比它发生的时候更重要。

ℹ️ 警告:令人烦恼的是,每种 SQL 语法都有非常不同的实现方式。

我错过了一些日期/时间 SQL 技巧吗?请在评论中告诉我👇

进一步阅读

让您的 SQL 从优秀走向卓越:第 3 部分

原文:https://towardsdatascience.com/take-your-sql-from-good-to-great-part-3-687d797d1ede?source=collection_archive---------0-----------------------

加入运动的时间到了

这是关于我最看重的 SQL“技巧”的 4 部分系列的第 3 部分。查看该系列中的其他内容:

第一部分:常用表表达式

第二部分:关于那些日子的一切

第 3 部分:其他连接(你在这里📍)

第四部分:窗口功能

有没有一个被低估的 SQL 技巧让你与众不同? 让我知道

卑微的加入

联接不是任何人都喜欢的 SQL 部分。它们不像窗口函数那样华丽,也不像 cte 那样具有变革性。然而,它们无疑是我们访问和转换关系数据的最强大的工具。

所以在进入我最喜欢的使用连接的方式之前,我想我应该提醒自己为什么我们应该更加关注这个长期被忽视的连接。

1.优化能力

SQL 查询不会按照它们被写入(或读取)的顺序运行。事实上,SELECT 语句是查询运行时最后完成的步骤之一。

运行的查询的第一部分是 FROM/JOIN 子句,这意味着如果我们想提高查询性能(谁不想),我们应该首先看看我们的老朋友 JOIN。

朱莉娅·埃文斯拍摄的照片。

2.创造性解决问题

我欣赏连接的另一个不太技术性的原因是,它们允许我们更有创造性地思考我们的数据分析。它们就像我们的乐高积木上的饰钉,允许我们建造比我们的单个表格数据库本身更大的东西。

这种能力和灵活性是我们今天仍然使用关系数据库的主要原因之一,尽管它们已经有将近 50 年的历史了。

默认连接

尽管有太多的连接类型可供我们使用,但大多数人都默认使用左连接。这有一些非常合理的理由。我们(在西方世界中)从左向右阅读,从我们提到的第二个表中添加列对我们来说更容易概念化,并且它的计算开销更小。

但是在有些情况下,将一串左连接链接在一起可能需要更多的工作,并且计算成本超出了您的承受能力。对于这些场景,我们可以看看一些更容易被忽略的连接类型:

常见连接类型。图片作者。

您没有充分使用的 JOIN 功能

1.内部联接,而不是过滤掉空值

我经常看到人们做这样的事情:

SELECT ...
FROM X
LEFT JOIN Y
ON X.KEY = Y.KEY
WHERE Y.KEY IS NOT NULL

这实际上只找到了表 X 和 Y 的共同点(也称为内部连接)。)

SELECT ...
FROM X
INNER JOIN Y
ON X.KEY = Y.KEY

为什么喜欢: 刚刚好。但更具体地说,它更有效,因为你不需要那么多的 WHERE 语句,它更快更容易键入,也更容易让别人理解。这本身并不是一种黑客行为,而是提醒了一个事实,即内部连接是存在的,它通常可以为您处理大量的过滤工作。

举例:

如果我想找到 Spotify 每日播放量最高的 10 首歌曲,我可以:

  1. 查找流量最大的 10 首歌曲
  2. 使用内部连接将其连接回我们的每日流数据:

内部联接示例。(链接)

在这个例子中,上面的查询版本(带有 top_tracks 内部连接 daily_streams)在 BigQuery 中处理 27 MB 的数据需要 0.9 秒。

左连接选项(daily _ streams LEFT JOIN top _ tracks…WHERE…)处理 27 MB 需要 1.9 秒。

虽然这两种方法都很快,但是您可以看到它如何扩展到更大的数据。

2.范围联接

当我们想到连接时,我们倾向于只想到等式,例如 key == key。但是我们经常需要一个更精确的逻辑来将两个表合并在一起。

为此,我们可以做一个范围连接,或者是一个不等式的连接。例如:

SELECT ...
FROM X
LEFT JOIN Y 
ON X.KEY >=Y.RANGE_START AND X.KEY <= Y.RANGE_END

为什么喜欢: 当你需要根据一些时间逻辑来联接两个表的时候,这些真的很棒。想想看,当你的用户购买了他们的第一个产品后,试图找到他们做 X 的实例,或者找到在他们的免费试用窗口内发生的所有行为。如果没有范围连接,所有这些都将是痛苦的,甚至是完全不可能的。

例如:

让我们继续我们的 Spotify 数据,假设我们希望找到热门歌曲的每日流媒体数据,但只针对歌曲发布后 30 天的数据。

范围联接示例(链接)

放大 SQL

在这个例子中,你可以看到,我们简单地扩展了我们的第一个例子,在我们的内部连接中增加了一些条件,以确保我们只选择音轨发布后 30 天内的数据。

ℹ️警告:不是每个 SQL 方言都支持不等式连接。这对我来说是相当惊人的,但在你开始尝试它并得到一个模糊的错误之前,检查一下仍然是一个好主意。然后切换到新的 SQL 方言。

3.横向连接

我参加横向加入派对的时间相对较晚,但我不得不说我喜欢到目前为止我所看到的。我花了一段时间才弄清楚它们到底是什么,但本质上理解横向连接有两个关键:

  1. 它们允许我们访问 FROM 语句后面的列。
  2. 它们的操作类似于 FOR EACH 运算符,因为它们是针对查询的每一行进行计算的。

为什么喜欢: 对 SQL 中的每一个操作做的能力都非常得心应手,尤其是当你需要为你的基表中的每一行生成新行的时候。

此外,横向连接允许您在同一个查询中构建自己,从而简化查询逻辑。这种逻辑合并有两个例子这里这里

举例:

为了与 Spotify 保持一致,假设我们希望找到 Spotify 前 10 名艺术家的前 5 首歌曲。

为此,我们可以:

  1. 查找前 10 名艺术家
  2. 对于每位艺术家,使用横向连接找到他们的前 5 首曲目:

看完整分析这里

放大 SQL

你也可以用一个窗口函数来做这件事,这恰好是本系列的下一个主题!

ℹ️警告:不是每个 SQL 方言都有横向连接的概念。例如,BigQuery 通过 UNNEST 使用隐式横向连接。亲自试用之前,请检查您的工具文档!

进一步阅读

在研究今天的帖子时,我发现以下链接最有帮助:

结束语

所有使用的例子都是在count.co中构建的,这是为分析师构建的 SQL 笔记本。您可以与以下示例互动:

还有这里:

直到下次我们讨论窗口函数的时候!

有我错过的一些加入 SQL 的技巧吗?请在评论中告诉我👇

让您的 SQL 从优秀走向卓越:第 4 部分

原文:https://towardsdatascience.com/take-your-sql-from-good-to-great-part-4-99a55fd0e7ff?source=collection_archive---------8-----------------------

大家最喜欢的 SQL 作弊代码。

这是关于我最看重的 SQL“技巧”的 4 部分系列的第 4 部分。

查看该系列中的其他内容:

这是我计划的最后一部,但如果你想看更多,请在评论中给我留言!

但是,现在我们来看看#内容。

介绍

窗口函数是 SQL 用户最喜欢的功能之一。它们非常强大,可以快速消除嵌套子查询和烦人的交叉连接。

然而,由于它们极其冗长的实现和无用的关键字,许多人害怕深入窗口函数的水域。在深入研究我最喜欢的一些窗口函数用例之前,本文将简要介绍窗口函数的工作原理。

本笔记中的所有示例都是使用 BigQuery 语法构建的,但是不同方言之间基本没有什么区别。这里 可以查看&编辑代码全文

解释的窗口功能

在 SQL 中,窗口函数分析函数是使用一行或多行中的值为每行返回一个值的函数— 大查询

了解窗口函数的关键是它们为指定表格的每一行计算一个值。这与聚合函数形成对比,聚合函数将汇总指定值。

图片作者。

当我们看一些虚构的隐藏神殿的传说数据时,我们可以看到这出戏。为了找到每个团队的最佳事件,我们可以看到如何使用简单的聚合函数 MAX 返回每个团队的最高分,但它不会告诉我们哪个比赛是他们的最佳

要用聚合函数做到这一点,我们必须将初始结果返回到原始表中,以找出红色美洲虎在哪个比赛中获得了 98 分。有点痛苦,☠️.

相比之下,通过使用窗口功能,我们可以快速找到每个团队的最佳活动。让我们来分析一下它是如何工作的。

窗口函数的剖析

乍一看,窗口函数很复杂,但是当你分解它们时,它们比你想象的要简单得多。

要创建一个窗口函数,你必须做两件事:

  1. 定义返回的内容
  2. 定义您的窗口

图片作者。

定义什么是返回↪

一般来说,窗口功能可以分为三种类型:

  1. 导航功能:返回给定特定位置标准的值(例如 first_value、lag、lead)
  2. 编号功能:根据每行在指定窗口中的位置,给每行分配一个编号(如 rank,row_number)
  3. 分析功能:对一组数值(如 sum,avg,max)进行计算

可用的具体函数将取决于您的数据库。使用参考资料部分中的指南来查看您的数据库中有哪些内容,或者查看我在此处构建的深入指南:

https://count.co/sql-resources/bigquery-standard-sql/window-functions-explained

定义您的窗口🪟

在您的窗口函数中,OVER 关键字之后的所有内容都代表您的窗口定义。

OVER 子句具有以下组件:

  • 分区依据:每个窗口由什么组成(例如,重新启动间隔…)
  • 排序依据:如何对每个窗口的行进行排序
  • X 之前和 Y 之后之间的行:在每个窗口中使用哪些行

现在我们有了基本的东西,让我们看看我们能用这些东西做什么…

窗口功能欺骗代码🕹

1.排名结果

像“购买最多的 5 件商品是什么”这样的问题很简单,但是如果加上“按地区”这样的问题,你的查询会变得非常复杂。

能够根据指定的数据分组对结果进行排序,可以开启各种新的分析可能性,例如找到用户购买的第二件商品,或者比较用户第一次和第二次访问您的网站时的使用模式。

举例:如果我想找到三位流行歌手的热门曲目:Drake、T Swift 和 Post Malone,我可以使用 rank 函数,按歌手划分,并按排序,来计算每首曲目的排名。

然后,我们可以很容易地比较每个艺术家的前 3 首歌曲,并看到德雷克和波斯特马龙排名第三的歌曲仍然在泰勒最热门的歌曲中排名第一。

图片作者。内置计数

2.计算两个事件之间的时间

数据的结构通常是每行代表一个事件。这使得查找事件之间的时间变得棘手,因为它涉及到查找 2 行之间的时间增量,而不是 2 列。

但是,这就是窗口函数的用武之地!特别是滞后和超前。

例子:我想找出 Spotify 艺人在他们的第一热门歌曲之间最大的干旱。为此,我:

  1. 找到每天排名第一的曲目。
  2. 找到了前一天的艺术家每次都是第一,使用滞后
  3. 然后我发现了当天他们是第一名和最近一天他们是第一名之间的差异。

图片作者。内置计数

3.“移动”计算

当进行任何类型的时间序列分析时,您通常会看到在很长一段时间内发生的一系列事件。这种数据往往是“嘈杂的”,因为它充满了每天的变化,这使得很难透过树木看到森林。

与移动平均值一样,移动计算是一种将时间序列数据汇总到一定水平的好方法,可以让您确定一些高层次的模式,而不会失去与底层细节的联系。

****示例:在这种情况下,我想查看每日 Spotify 流的 30 天移动平均值。这将让我快速查看流是否随时间增加,以及有多少值得注意的异常值,等等。

图片作者。内置计数

车窗功能注意事项和最佳实践

⚠️窗口函数不能位于查询的 WHERE 或 HAVING 部分,因此您需要使用 cte 或子查询来基于窗口函数结果进行过滤。参见本系列第 3 部分 中的 图,了解为什么不能将窗口函数添加到 WHERE 和 HAVING 查询部分。

⚠️在同一个查询中组合窗口和典型的聚合函数是非常麻烦的,如果不是完全不可能的话。如果可以的话,尽量避免。

💡如果您想要“分组”窗口函数查询的结果,请使用 DISTINCT。

⚠️总是用窗口函数检查你的结果,因为如果数据不是你所期望的那样结构化,你很可能得到错误的结果。

参考资料:

  • big query(docs)(guide)中的分析函数
  • 雪花中的窗口功能(文档 ) ( 向导)
  • MySQL 中的窗口函数( docs )
  • MS SQL 中的窗口函数( docs ) ( guide )
  • PostgreSQL 中的窗口函数( docs )
  • 红移中的窗口函数(文档)

让您的 SQL 从优秀走向卓越:第 5 部分

原文:https://towardsdatascience.com/take-your-sql-from-good-to-great-part-5-7c996dbcc527?source=collection_archive---------15-----------------------

UDF 能为你做什么?

介绍

我知道我说过这是一个 4 部分系列,但谁不喜欢奖金内容?这个版本是关于用户定义函数(UDF)的。

使用以下链接查看该系列的早期版本:

用户定义的函数

UDF(用户定义函数)是在 SQL 中创建定制函数的一种方式。

例如,如果我想找到一个数字的立方,我可以在查询中执行以下操作:

--bigquery syntax
SELECT power(<COLUMN>,3) as cubed
FROM <TABLE>

但是如果我想创建一个函数来立方任何我可以使用的数字,而不是幂,我可以创建一个名为的立方:

--bigquery syntax
CREATE OR REPLACE FUNCTION
   <DATASET>.cubed(x FLOAT64)
   RETURNS FLOAT64 AS ( POWER(x,3) );

然后,每当我想立方体的东西,我可以调用我们的新功能:

SELECT
   <DATASET>.cubed(3),
   <DATASET>.cubed(2.2)-- 27.0 , 10.648000000000003

重要的是,现在任何对我的数据库有查询权限的人也可以使用这个新功能。

UDFs 101

UDF 的实现在您使用的每个数据库中都有所不同(有趣!),所以在使用它们之前,一定要检查您自己的 DB 文档。但是它们都有一些共同点:

  • UDF 可以接受输入参数(比如“x”的立方)
  • 必须输出一个值(任何类型)
  • 通常不能引用其他的 UDF(但是再次检查你的数据库)
  • 可以是本地的,只存在于当前查询中
  • 或者跨模式或数据库共享和存在
  • 通常可以使用 SQL 之外的其他语言(例如 Python、JavaScript、Java)创建,但是请再次检查您的数据库以了解详细信息

数据库概念总结。图片作者。

处于最佳状态

UDF 的功能让我们看到了 SQL 是多么接近于一种“合适的”编码语言。

图片作者。(信不信由你,这个灵感来自这个宝石

Python 或 R 最受欢迎的特性之一是能够通过使用函数来模块化代码以便重用。像 pypi、tidyverse 和 npm 这样的平台更进一步,让用户在团队之外和整个用户社区共享这些功能。

今天,大多数 SQL 都是作为独立的脚本编写的,但是 UDF 便于在脚本之间共享逻辑,模拟其他“真正的”编程语言的模块系统。

更重要的是,UDF 给了我们一个框架,让 SQL 更好地为我们和我们周围的人服务。我们可以使用 UDF 来:

简化不常使用 SQL 的用户的常见操作

假设销售团队经常每季度查看一次数据,但是很难获得正确格式的数据。为了提供帮助,我可以创建一个函数,将任意日期(2020–01–02)转换为四分之一(Q1–2020),这样他们就不会与迂腐的日期格式化函数发生冲突,可以继续进行分析。

做一些在 SQL 中不可能的事情

因为您可以使用其他语言来创建 UDF,所以您有能力为 SQL 注入它没有的功能。例如,您可以使用 JavaScript NLP 库创建一个函数来查找两个单词之间的 Levenshtein 距离(链接),让您更容易地对文本列进行模糊连接,这在 SQL 中是众所周知的困难。

在最坏的情况下

但我们并非都生活在 UDF 乌托邦中,这是有原因的。尽管 UDF可能很棒,但它们的缺点经常让我们怀疑它们是否值得我们去费心。

特别是:

UDF 是孤立的🏝

UDF 通常需要管理员权限来创建和维护,这意味着只有某些用户能够看到它们是如何定义的。但是任何用户都可以使用这些相同的功能,这意味着许多人会盲目地使用他们看不到的功能。

它们的定制性质也意味着,对于那些在这些功能中挣扎的人来说,没有任何帮助。我的销售团队无法使用谷歌来查看他们为什么会在我创建的季度函数上出错,因为我是唯一知道它如何工作的人。

UDF 很难理解🤔

此外,如果我使用 SQL 之外的东西(例如 JavaScript)构建了一个 UDF,我真的不能和很多人分享。如果它突然停止工作,而我又不在身边,我不确定我的数据团队能否修复它。正如一位睿智的大叔曾经说过的那样:“权力越大,责任越大。”

结合起来,这两个缺点威胁到我们使用 SQL 的基本原因之一:它是一种低级查询语言。这意味着虽然它很冗长,但它是相当标准化的。我不用担心有人用不知道函数和方法的奇库;每个人都在使用相同的标准 SQL 函数和语法。

这就是我们的权衡。我们如何使用 UDF 来帮助我们和我们周围的人更好地使用 SQL,而不破坏它作为一种普遍理解的语言的优势?

我最喜欢的 UDF

鉴于这种权衡,我喜欢将 UDF 仅用于两件事:

  1. 不需要真正解释的超级简单的事物(如中位数)
  2. 超级先进的东西,只会被少数人使用,我确信这些人了解它们是如何工作的

⚠️:我建议不要将 UDF 用于任何类似业务逻辑的东西(例如,以某种方式计算收入的函数)。对于这样的事情,最好能够向用户展示你做了什么,并解释为什么,因为这是理解结果的基础。

我最喜欢的 UDF

中位数

来源:big query-utils

BigQuery(以及其他)没有针对 MEDIAN 的原生函数,而是依赖于 PERCENTILE_CONT 窗口函数。这很好,但是我发现它(1)很烦人,并且(2)很难向初级用户解释,因为它需要理解窗口功能。

为 BigQuery 编写的这个代码片段计算一列的中值:

**CREATE** **OR** REPLACE **FUNCTION** <DATASET>.median(arr **ANY** TYPE) **AS** ((      **SELECT** IF (
     MOD(ARRAY_LENGTH(arr), 2) = 0,     (arr[**OFFSET**(DIV(ARRAY_LENGTH(arr), 2) - 1)] + arr[**OFFSET**(DIV(ARRAY_LENGTH(arr), 2))]) / 2,     arr[**OFFSET**(DIV(ARRAY_LENGTH(arr), 2))]
   )
  **FROM
**  (**SELECT** ARRAY_AGG(x **ORDER** **BY** x) **AS** arr **FROM** UNNEST(arr) **AS** x)
 ));

用 UDF 中值绘制盒须图。(链接)

工作日

来源: SQL 片段

这无疑属于“在 SQL 中要做的简单但烦人的事情”一类。一些方言有办法获得实际的星期名称,但在许多情况下,我不得不一次又一次地做这个可爱的 case 语句。所以现在可以是一个叫做 weekday 的函数。

**CREATE** **OR** REPLACE **FUNCTION** <DATASET>.weekday(dt DATE) **RETURNS** STRING **AS** (
     **case when** extract(DAYOFWEEK **from** dt) = 1 **then** 'Sunday'
     **when** extract(DAYOFWEEK **from** dt) = 2 **then** 'Monday'
     **when** extract(DAYOFWEEK **from** dt) = 3 **then** 'Tuesday'
     **when** extract(DAYOFWEEK **from** dt) = 4 **then** 'Wednesday'
     **when** extract(DAYOFWEEK **from** dt) = 5 **then** 'Thursday'
     **when** extract(DAYOFWEEK **from** dt) = 6 **then** 'Friday'
     **when** extract(DAYOFWEEK **from** dt) = 7 **then** 'Saturday'
 **end
**  );

有了这个 UDF,你可以更容易地做一周中的一天的分析。(链接)

Levenshtein 距离

来源: 费利佩·霍法

Levenshtein distance 通过将一个字符串改变为另一个字符串所需的改变来测量两个字符串之间的“距离”,因此这是一种很有帮助的方法,可以找到除了拼写错误或其他轻微差异之外匹配的单词。

从技术上来说,这在不使用 JavaScript 库的情况下用 SQL 实现是可能的,但这要容易得多

CREATE OR REPLACE FUNCTION fhoffa.x.levenshtein(a string, b string)
RETURNS INT64
LANGUAGE js AS """
  return fuzzball.distance(a,b);
"""
OPTIONS (library="gs://fh-bigquery/js/fuzzball.umd.min.js");

使用 Levenshtein 距离解释用户拼写错误。(链接)

UDF 的未来角色

最近一直在想 UDF 会在 SQL 的进化中扮演什么角色。我们对能够轻松重用 SQL 的渴望变得越来越强烈,这也是我从分析师那里听到的最频繁的请求之一。

SQL 如何继续进化?图片作者。

不难想象,UDF 是推动 SQL 走出本地极限并进入新时代的解决方案的一部分——在这个新时代,我们 SQL 用户可以共同构建强大的代码模块,供所有人分发和共享。

为了推动这项工作,我们启动了这个 SQL 片段集合。在这里,SQL 用户可以通过在您公司的数据库之外创建、共享和改进 UDF 并进入更大的社区,开始朝着开源解决方案努力。

在哪里可以找到更多的 UDF👀

知道更多 UDF 的来源?请在评论中告诉我!

从一个关于迷因流行的数据科学项目中吸取的经验教训

原文:https://towardsdatascience.com/takeaways-from-mentoring-a-data-science-project-4d3c95f17483?source=collection_archive---------27-----------------------

指导远程数据科学团队分析新冠肺炎迷因的收获。潮湿不潮湿?

潮湿不潮湿?——这是模因世界中的一个好问题,模因是充满幽默的病毒式互联网内容,反映了当前在网络世界中传播的趋势。就在疫情疫情爆发前,AIT Budapest 的一群才华横溢的学生将这一主题作为他们数据科学项目的核心。

我作为导师加入了他们,帮助他们解决与数据科学相关的问题,并发现自己参与了一个令人兴奋的研究项目,该项目已经从一项大学任务发展成为一篇研究文章,并在最近几天发表。

你可以想象,我们从这个项目中学到了很多。因此,我想分享一些与数据科学相关的一般性观点,这些观点对任何对数据科学感兴趣或从事类似项目的人都很有用。所以,让我们开始吧!

图片由作者根据 Unsplash 改编。

好数据—好项目

在过去的几年里,模因已经成为一种社会现象,尤其是在新冠肺炎疫情时代,人们比以往任何时候都更倾向于在线互动。迷因可以吸引人们对文化和政治主题的注意,并且可以表达公众最关注的东西。它们已经成为一个有趣的研究课题,不仅从数据科学的角度,而且从网络科学和社会计算机科学的角度。在这个小组中,我们旨在用现代机器学习技术研究模因的受欢迎程度与其内容之间的关系。

首先,我们需要高质量的数据,我们必须了解如何利用我们的功能来回答目标问题。

我的学生决定调查最大的社交新闻和娱乐网站 Reddit 上的迷因。虽然已经有一些数据集可供数据科学家探索迷因世界,例如 Kaggle,但我建议我们从 Reddit 收集迷因,以获得我们想要的所有元数据,并拥有更大的数据集。另外,我们收集了 2020 年 3 月 17 日至 2020 年 3 月 23 日的数据,这是全球冠状病毒爆发的开始。在第一次数据清理步骤后,我们有 80362 条基于图像的迷因记录,其中包含大量元数据,如上传投票数、发布迷因的子编辑、标题等。

我认为这是将这个项目从大学小组工作发展成一个严肃的研究项目的第一步,我们收集了大量有趣的数据进行分析。通往成功的下一步是商业理解。

了解您的数据—每个数据科学项目的关键

当我们收集了大量基于图像的迷因时,下一步就是要弄清楚是什么特征表达了迷因的流行。

我们有每个迷因的投票数,但我们不能简单地用它作为我们的目标变量。为什么?

我们的图文模因来自最大的模因子群,代表致力于创造和分享模因的社群。拥有更多订户的子街道往往会获得更多的上行投票,这表明上行投票和订户之间存在正相关。为了消除这种网络效应,我们必须将上传投票数除以发布该迷因的子编辑的订阅人数,从而使上传投票数标准化。

现在我们有了目标变量,下一课是识别 Reddit 上模因的病毒性质使这些数据非常适合二进制分类任务。我们只看归一化 upvotes 的分布。

归一化上票数的分布。来源: 潮湿不潮湿?-分析和预测 Reddit 上的模因流行度

归一化上票数的分布表明,大多数模因获得的上票数很少,而少数模因获得的上票数很多。这给了我们形成二元分类标签的直觉,叫做潮湿或不潮湿。根据我们的目标标签,病毒或潮湿的模因通常与非病毒模因相差两个数量级,我们通过将前 5%的模因算作潮湿而其余的非潮湿来制定目标标签。

这样,我们制定了我们的数据科学任务,使用监督学习算法根据不同的特征集对迷因的受欢迎程度进行分类。

尝试不同的模型

我们深入研究了各种技术,从光学字符识别(OCR)到从图像中提取文本,通过 python 中的 OpenCV 获得低级图像特征,甚至通过 Keras 的 VGG-16 神经网络获得更多特征。研究最受欢迎的迷因的文本和图像内容在疫情疫情爆发时的样子令人兴奋。我们甚至从抓取的迷因中的所有文本生成了一个词云。

从我们搜集的模因中的所有文本生成的词云。来源: 潮湿不潮湿?-分析和预测 Reddit 上的模因流行度

我们用随机森林和梯度推进模型研究了图像或文本特征对确定病毒模因是否有更大的预测能力。我们还尝试用卷积神经网络进行迁移学习,根据原始图像数据预测模因的受欢迎程度。

在我看来,下一个重要的收获是,我们不仅尝试了一种机器学习模型,而且在不同的功能集上尝试了不同的模型。这样,我们可以更好地理解数据,并可以得出更普遍的结论。

准确性与 AUC

在任何数据科学项目中,确定使用哪些指标来评估模型的性能总是很重要的。我们认识到准确性并不总是我们所追求的。为什么?

想象一下我们不平衡的数据集和我们的二元分类任务,其中 5%的数据是潮湿,标记为 1,而其余的是不潮湿,标记为 0。让我们设想一个虚拟模型,它预测每个实例的标签 0。那么,这个模型将有 95 %的准确率!这不是我们真正想要的,是吗?

AUC 得分,也称为 ROC 曲线下的面积,衡量二元分类器的性能。它的值在 0.5-1 的范围内,其中 0.5 是随机分类器的性能,而 1 表示完美的模型。对我们来说,这是一个非常好的指标,因为它也适用于不平衡的数据集。此外,事实证明,这是比 accuracy⁴.更好的衡量标准

取样可能很棘手

处理不平衡数据集并不容易,尤其是当我们知道随机森林和梯度推进集成分类器在原始 form⁵⁶.中处理不平衡数据时表现不佳我们可以尝试使用为此设计的模型,就像我们通过使用来自 im burn pythonpackage⁷的平衡随机森林所做的那样,或者我们可以试验采样技术。

当我们尝试上采样时,我们遇到了一个常见的错误:在将数据集分成训练集和测试集之前,永远不要对其进行上采样。

它导致了“完美”的度量,并且很难猜出哪里出了问题。发生的情况是,在分割之前进行上采样,相同的实例可能落入训练集和测试集中。然后,很容易猜测出模型的测试集具有更好的度量,因为在测试集中有一些模型被训练的实例。

也不建议乱用测试 set⁸.如果我们修改它的分布,它不会反映我们的人口。

我们学到的是,如果我们首先应用分层抽样来获得测试集,效果会更好。然后,我们可以在训练集上应用任何采样技术。

摘要

作为这个数据科学项目的一部分,利用不同的机器学习技术预测模因的流行程度,这是一次很好的经历和挑战。我在上面强调了一些一般的要点,希望你也会觉得有用。总而言之,我分享了关于数据理解、不同模型、评分标准和抽样的想法。如果你对这个项目的细节感兴趣,我推荐你阅读我们的文章。

承认

我为我的组员凯特·巴恩斯、蒂尔农·里森米、Minh Duc Trinh、伊莱·莱希和我们的组长罗兰·莫隆泰教授感到无比自豪。你们都做得非常出色!

参考

[1] Barnes,k .,Riesenmy,t .,Trinh,M.D. et al. Dank or not?Reddit 上模因流行度的分析与预测。 (2021)应用网络科学 6、 21。

[2]https://www.reddit.com/

[3]萨扬·戈斯瓦米。 Reddit 迷因数据集。(2018)Kaggle.com

https://www.kaggle.com/sayangoswami/reddit-memes-dataset

[4],,凌,用 AUC 和精度评价学习算法。 (2005) IEEE 知识与数据工程汇刊,17(3),299–310。doi:10.1109/tkde

[5] Brownlee,J.: 用于不平衡分类的装袋和随机森林。 (2020),机器学习掌握

[6]刘,s,王,y,张,j,陈,c,向,Y.: 利用集成学习解决 Twitter 垃圾邮件检测中的类不平衡问题,(2017),计算机&安全 69,35

[7]Guillaume lematre等人。不平衡学习:一个 Python 工具箱来解决机器学习中不平衡数据集的诅咒。 (2017)《机器学习研究杂志》,18(1)559–563。

[8] 为什么采样提升了我的模型的性能?、(2019) StackExchange。

掌控您的工作流程

原文:https://towardsdatascience.com/taking-control-of-your-workflow-943b9a8e7edf?source=collection_archive---------30-----------------------

使用 pyenv 和 pipenv 在 Python 中建立令人敬畏的虚拟环境,让你的同事再次喜欢你

照片由 Kari SheaUnsplash 上拍摄

读者注意:有许多方法可以创建管理 Python 版本和依赖项的虚拟环境。这篇文章介绍了我的首选方法,但是我鼓励您探索各种选项,并决定哪种方法最适合您!

为什么您需要虚拟环境

也许你创建了一个很酷的机器学习数据管道或开发了一个杀手级应用程序,下一步就是与世界分享它!然而,如果您没有跟踪和记录您使用的 Python 版本或所需的依赖项,那么与您共享它的人将会遇到许多令人头痛的安装错误。

输入 pyenv + pipenv

Pyenv + pipenv 提供了一种方法来指定 Python 版本,并在项目级别安装和跟踪依赖项,从而使将代码交付到生产环境变得更加轻松。

基础知识

  1. 使用这些安装说明安装pyenv
  2. 使用pip install pipenv安装pipenv
  3. 通过在终端中执行以下操作来创建和启动虚拟环境
**# create a project directory**$ mkdir myproject
$ cd myproject**# use pyenv to install and set a specific Python version**$ pyenv versions **# don't use the system version**
$ pyenv install 3.8.5
$ pyenv local 3.8.5**# create a virtual environment with pipenv**$ pipenv install
$ pipenv shell
(myproject) $ python --version **# 'myproject' indicates active****# install dependencies and check dependency list**(myproject) $ pipenv install pandas
(myproject) $ pip freeze**# deactivate Pipenv** (myproject) $ exit **# 'myproject' will disappear**

执行完上面的操作后,您现在将拥有一个pipfile.lock文件。只要这个文件伴随着你的代码,那么就像在文件的位置运行pipenv install一样简单,所有的依赖项都会被安装。

更进一步——Jupyter 笔记本

使用 pipenv 和定制的 IPython 内核管理 Jupyter 笔记本中的依赖项实际上是可能的。扩展上面的myproject示例,在终端中执行以下命令。

**# activate pipenv virtual environment for 'myproject' directory**$ cd myproject
$ pipenv shell**# install ipykernel and map custom kernel to virtual environment**(myproject) $ pipenv install ipykernel
(myproject) $ python -m ipykernel install --user --name=myproject**# launch a Jupyter Notebook**(myproject) $ jupyter notebook

从 Jupyter 笔记本中,你可以在内核列表中选择myproject内核。这将强制笔记本只使用 pipenv 虚拟环境中安装的依赖项!!

在 Jupyter 笔记本中选择自定义 ipykernel

摘要

如果您目前没有管理 Python 版本和依赖项,或者如果您管理了并且看起来很麻烦,那么使用 pyenv + pipenv 是一个很好的解决方案。它很容易安装,一旦你开始使用它,你永远不会回头。编码快乐!

让 Keras 和 TensorFlow 更上一层楼

原文:https://towardsdatascience.com/taking-keras-and-tensorflow-to-the-next-level-c73466e829d3?source=collection_archive---------7-----------------------

充分利用 Keras 和 TensorFlow 的 11 个技巧和诀窍

保罗·赫顿在 Unsplash 上的照片

时代是一个美丽的项目。虽然 TensorFlow 和 PyTorch 过去一直在竞争最先进的技术,但 Keras 的目标是 us ,需要完成工作的专业人士。我们可以使用去年的模型,而不是打赌下一个变形金刚杀手或 ResNet 的崇拜者。作为 TensorFlow 的一部分,Keras 已经有近两年的时间了,这表明该框架支持易用性和生产率,而不是速度。作为 TensorFlow 和 Keras 的用户,我在本文中分享了我多年来开发的一组技巧和诀窍,以将这些框架提升到一个新的水平。

我强调这不是一个优化指南。相反,这些技巧旨在使开发模型和实现定制功能变得更容易——所有这些都不会牺牲 Keras 最可爱的方面,它为您完成了大部分工作。

开始了。

始终使用函数式 API

使用 Keras 定义模型有三种主要方法:作为层列表(顺序方法),作为功能组合(函数方法),或者通过继承模型(子类化方法)。从树中,总是选择功能方法

使用 Keras 功能 API 的一个简单例子

在上面的例子中,我们定义了一个 64 维的输入层,然后定义了一个 256 个神经元的隐藏层,最后是一个两类输出层。功能方面在第 4 行和第 5 行的末尾。隐藏层是处理输入的函数。同样,输出是处理隐藏层的函数。第 6 行定义的模型本身只是这个函数调用链的起点和终点。

你可以在 Keras 文档上阅读更多关于功能 API 的内容。

使用函数式 API 的原因很简单:它有最好的支持,没有限制。相比之下,顺序方法只支持前馈模型(不允许跳过连接或分支),而子类化 API 对保存/加载模型和分布式训练的支持有限。此外,其他不太常见的特性,如 web 或移动平台的移植模型,在使用函数式 API 时也能更好地工作。

使用闭包创建块

使用函数式 API 时,最大的问题是如何在坚持函数式语法的同时创建可重用的代码片段。解决办法?关闭。

闭包的一般定义是指在它之外定义的变量的函数。在计算机科学词汇中,它“捕捉”了这些变量。在 Python 中,这与嵌套函数(在其他函数中定义的函数)的概念密切相关,但并不局限于此。下面是一个例子:

在 Keras 中使用闭包定义简单 ResBlock 的示例

上面的代码片段展示了如何创建一个函数(resblock ),该函数返回另一个函数(_block ),该函数捕获“n_filters”参数。当通过一个层被调用时,这个第二个函数将通过添加一个典型的 ResBlock 的所有步骤来继续函数调用链,如在原始论文( 20152016 )中所定义的。

使用这种语法的好处在于,它允许您将超参数(定义为第一个函数的参数)与调用该层的先决条件(定义为内部函数的参数)分开。此外,它允许您在两个级别上都放置自定义逻辑。例如,上面的示例展示了如何预处理“start”参数,以确保使用 1v1 卷积至少有“n_filter”通道。

使用闭包在 Keras 中实现 2D 自我关注

对于高级用户:展示闭包在一个更复杂的例子中,我们实现了一个 2D 瓶颈查询-值-键关注块,类似于自我关注甘斯上所描述的。首先,我们定义了超参数 n_filters ,在第一个函数的范围内,我们将瓶颈的程度指定为 n_filters 的八分之一。然后,在内部函数中,我们使用 1v1 卷积对查询和值项进行瓶颈处理,并将所有三个输入重新整形为 1D 向量。接下来,我们将注意力得分计算为查询和值之间的最大点积,最后,将其与关键术语相结合以获得输出。

从第 27 行开始,我们创建了第二个闭包来简化我们刚刚编码到 2D 自我关注块中的 2D 关注,该块同时将单个输入映射为查询、值和键。这些实现共同展示了如何使用闭包的外部和内部范围,以及如何组合闭包以进一步扩展它们的功能。

人们可以将第 18-21 行替换为内置的 tf.keras.layers .注意力层,以获得更少的从头开始的解决方案。我刚刚意识到,在编码了这个例子之后:x

将操作用于自定义代码

在层链中,虽然很明显只有层可以链接在一起,但事实是大多数 TensorFlow 操作都可以用作层。我知道的唯一先决条件是它接受并输出张量。使用原始 ops 代替纯层的优势有几个。我强调它的可读性更强,更轻量级,也更透明。另外,使用 ops 有完全的控制权。

尽可能使用 TensorFlow ops 修改 2D 注意力示例

在上面的代码片段中,计算注意力分数和输出所需的操作被转换为简单的 TensorFlow 操作。这种语法更接近于你在 Numpy、PyTorch 甚至 JAX 中看到的语法。

使用 ops 的缺点是当你需要增加重量时。为此,最好尽可能使用内置层。在上面的例子中,我们坚持使用卷积层,其余的使用 ops。对于那些熟悉注意力公式的人来说,有时它包括一个最终的比例参数(gamma)。坦白地说,我不会打扰。

好吧,对于那些有麻烦的人,需要权重的简单缩放和移位操作可以使用 1v1 卷积来模拟,或者更好的是,批量范数或层范数。

为简洁的摘要包装自定义代码

使用 ops 的另一个缺点是在运行 model.summary()时会变得很难看。例如,上面的代码片段产生了以下内容:

调用 model.summary()时,ops 会有多难看

有两种方法可以解决这个问题:

  1. 实现从继承的功能
  2. 实现从包装器继承的功能
  3. 将一切封装在另一个模型

第一种方法是最麻烦的,因为您需要处理 Keras 内部。然而,当您想用其他东西来扩充现有的层实现时,第二种方法非常有效。一个完美的用例是光谱归一化插件的实现。然而,第三个是最实际的(有一些警告)。

这个想法是你可以使用模型作为层(就像你可以使用大多数操作作为层一样)。如果您有一组重复的层(如上面的 Attention 实现),您可以将其打包到一个模型中,并在您的网络中使用该模型。这样,您可以将整个子网命名为一个实体。

警告是两个:(1)模型没有”。“形状”属性,以及(2)模型不会自动命名。如果自定义块试图访问前一层的形状(如上面的 ResBlock 实现),前者会咬你一口,如果是模型,它会失败。后者将触发一个 Keras 异常,要求所有层都有唯一的名称。因此,对于高级用户,我留给您一个的 hacky 装饰器,它会弄乱唯一 id 的全局名称空间,并用 shape 属性对创建的模型进行猴子式修补🙈。

使用自动命名和形状属性将自定义块包装为模型的装饰器

理解这个片段是留给读者的练习。

关于自定义训练循环的注释

当 TensorFlow 2.0 发布时,要创建定制的训练例程,如 GANs 的对抗性训练,需要完全放弃 model.fit()调用,并从头开始重新实现它。这样做是不小的壮举。你必须做你的纪元,有效地得到下一批,写训练和测试步骤,运行你的回调和度量,建立一个进度条,等等。混合精度或分布式培训的加分。这是关于定制训练循环的官方文档

TensorFlow 2.2 给了我们一个使用子类化模型的好理由:你可以在使用 model.fit() 的同时覆盖 train_steptest_step、predict_step 调用来定制训练。对于胆小的人来说,重新执行这些呼叫仍然不是一件事情。然而,你不需要重新发明整个战车,只需要轮子。

到目前为止,我所知道的实现这些调用的最佳参考是源代码本身(它被认为是文档)。你可以在这里找到它。

到目前为止,我建议在所有情况下都坚持使用函数式 API。为了继续,您可以对 train_steptest_step、predict_step 调用进行猴子修补。语法有点问题,monkey patching 是一个相当糟糕的解决方案,但是它很有效:)。毕竟,如果您正在编写定制的训练循环,那么您已经对 Python 的魔力了如指掌。

无论如何,这里是维基百科关于猴子补丁的陷阱部分

Monkey 修补使用函数式 API 定义的模型的训练步骤的示例

这个愚蠢的片段展示了如何对 train_step 调用打猴子补丁,以计算它被调用的次数。注意,第 19 行激活了 eager mode,强制 Keras 不要跟踪这个函数到 graph-mode,这将导致它只被调用两次。现实世界的用例不需要使用渴望模式,只需要像这样愚蠢的演示。

知道如何遍历模型

您是否曾经问过自己如何迭代所有的模型层,并在每个层上做一些事情?当您需要对每个图层应用一些东西或收集内部数据(如每个图层的平均权重)时,遍历会非常方便。这里的技巧是不要忘记迭代子模型。

向模型的所有层添加权重衰减

这是一个如何将权重衰减添加到模型所有层的示例。该算法是对所有层的深度优先扫描,使用递归来深入研究子模型、子模型的子模型等。注意这段代码只支持少数层,但是很容易扩展到其他层。

使用正确的数据类型

使用正确的数据类型可以节省 50%(比如从 float64 到 float32)到 93%的内存(从默认的 int64 到瘦 uint8)。我曾在下面的文章中写过这个问题:

特别是对于 TensorFlow 和 Keras 来说,有一件事人们通常会不假思索地坚持:一键编码和交叉熵。经验法则是用一键编码对标签进行编码,并为每个类输出一个值。这种做法通常是安全和正确的。然而,对于大规模数据集或具有大量类的问题,使用稀疏标注和稀疏交叉熵可能会改变生活。

稀疏标签是以索引形式存储的标签:例如,第七个类由数字 7 表示,而不是由第七个位置设置为 1 的零向量表示。对于 1000 个类的问题,这是更紧凑的数量级。一个 uint16 数对一千个浮点数。默认情况下,大多数数据集使用稀疏标签进行打包,我们强制将它们一次性打包。

稀疏交叉熵分类交叉熵的一个变种,它将你的模型输出以一个热点格式与真实标签以索引格式进行比较。结合这种损失和稀疏标签,你节省了大量的内存,否则将花费在英亩的零。

“关于定制训练循环的注释”的片段展示了一个使用稀疏交叉熵的例子。

额外提示

不要忘记急切模式: TensorFlow 在开始抱怨形状和不兼容数据类型的内部错误时可能会很棘手。大多数这些在渴望模式下很容易被发现或者不会发生。记住使用渴望模式有助于追踪 bug 的源头,或者在将 bug 缩小到图形模式问题(比如使用正确的数据类型)之前关注全局。

对 tf.data 也使用渴望模式:使用数据 API 是一件痛苦的事情,因为它总是将一切追溯到图形模式。从 TensorFlow 2.6 开始,您可以为数据 API 激活调试模式。这项功能仍处于试验阶段,但会非常方便。下面是怎么做的

使用 Lambda 回调:当使用昂贵的指标跟踪训练进度时,使用 Lambda 回调类注入要在 epoch end 上运行的代码是值得的。如果您的度量非常慢,您可以使用 epoch 参数跳过在奇数个时期执行代码,或者每十个时期执行一次。

让自己成为一个库:当你使用深度学习时,你将不得不实现不同的层和架构。使用所有内置的东西作为构建模块,有些很容易实现,有些则不容易。因此,保留一个方便的 layers.py 文件来保存多年来您必须编写的所有自定义内容是值得的。

他的一切都是为了现在。如果您对本文有任何问题,请随时发表评论或与我联系。

如果你是中新,我强烈推荐订阅。对于数据和 IT 专业人员来说,中型文章是 StackOverflow 的完美搭档,对于新手来说更是如此。注册时请考虑使用我的会员链接。

感谢阅读:)

参加 2021 年的数据科学训练营

原文:https://towardsdatascience.com/taking-on-a-data-science-bootcamp-in-2021-af36b9f6613b?source=collection_archive---------23-----------------------

关于我的训练营经历,我喜欢(和不喜欢)的事情

照片由海伦娜·洛佩斯Unsplash 拍摄

介绍

嗨伙计们!这篇文章是关于我在数据科学训练营的个人经历,特别是在新加坡的大会数据科学沉浸式课程。我将涵盖几个方面,包括我为什么决定加入,以及我喜欢(和不喜欢)它的几个方面。

我还在下面提供了一些特定于新加坡的额外资源,以帮助任何对向数据科学转型感兴趣的人。

事不宜迟,请继续阅读我在 2021 年的数据科学训练营经历。

我为什么要加入?

像许多应届毕业生一样,我不知道大学毕业后想做什么。我毕业时获得了全球研究学士学位。2019 年从新加坡国立大学(NUS)毕业,最后在科技公关领域工作了大约一年——这是一份有趣的工作,但我知道这不适合我。

2020 年 7 月,我辞去了工作,专注于向数据分析职业过渡。我选择大会的数据科学沉浸式(DSI)主要是因为它有资格获得 T4 TIPP 计划(T5)下的政府补贴。这大大减少了学费。我还和以前上过这门课的人谈过,到目前为止听到了一些好消息,所以我决定咬紧牙关,在 2020 年 10 月报名参加最近的课程。

值得吗?

简而言之,是的——对我来说绝对值得。虽然我在训练营之前已经取得了一些进步,但有一个结构化的环境确实帮助我推动了自己,完成了比我自己更多的事情。

我觉得我在训练营期间创建的投资组合,以及我获得的技术技能,真的给了我一个找到数据分析师工作的机会。

我喜欢的东西

这门课有很多我喜欢的地方。我认为我的那一批人是幸运的,因为我们有一位非常博学的老师,他花时间分解复杂的概念,并清晰连贯地解释它们。我们的助教也在整个课程中为我们提供了重要的支持,他们既友好又平易近人。

我真的很喜欢训练营,因为我的同学们。当你对一个概念感到困惑时,有一群志同道合的人一起成长并帮助你,这是有道理的。这也意味着在课程结束后拥有一个专业的人际网络。

我也觉得课程的内容符合我的期望。课程材料和笔记写得很好,并且非常好地解释了大多数概念。我们的项目/实验室的说明和要求非常明确,支持我们的学习。

令人惊讶的是,训练营的混合形式也很适合我。由于新冠肺炎,我们的课程有一个线下-线上的结构,其中两天在校园里亲自上课,其余几天在 Zoom 上上课。这让我节省了旅行时间,也让我有机会在一天疲惫的课程后休息和充电。

我不喜欢的东西

我对训练营最大的问题实际上是他们给我们的项目。这些项目有两个目的——让我们亲身体验真实世界的数据,同时作为作品集的一部分。然而,这些项目在过去几年里已经在校园之间重复共享,所以它们并不是唯一的。

想象一下,你要去参加一个面试,面试官一次又一次地看到来自同一个训练营的相同项目(或者相同项目的相似迭代)。不太好。我真的建议投入一些额外的努力来区分你的项目和已经存在的项目。根据我的经验,面试官确实会注意到这一点。

不幸的是,我们的职业教练也在我们的课程中途辞职了。这实际上是相当具有破坏性的,因为没有替代职业教练排队。然而,这可能是我的特殊批次独有的东西。大会团队在那段时间尽了最大努力支持我们,这是我所感激的。

最终外卖

如果我能回到过去,我仍然会选择大会的数据科学沉浸式。我认为我从课程中获得了巨大的价值,总体来说,我真的很喜欢这种体验。我向任何希望深入数据分析的人推荐它,或者作为希望进入数据科学的人的起点。

一个重要的警告是,训练营不一定能保证你找到工作。你必须花时间去消化你所学的东西,并向潜在雇主展示你的能力。在这一点上,我发现在开始训练营之前有一个强大的编码背景是非常有用的。这让我有更多的时间来改进我的项目(而不是担心编码的细节)和做一些有趣的事情,比如创建我自己的个人网站。

额外资源

在结束这篇文章之前,我想分享一些新加坡特有的资源,供有兴趣转向数据科学或数据分析职业的人参考。

在 IMDA 的技术沉浸和安置项目(TIPP)下有资格的训练营的详细列表可以在这里找到。

我接触过的其他相关项目有 BCG's RiseNTUCSUTD淡马锡理工新加坡理工的各种 SGUnited 技能项目。其中一些课程可能已经开始了,但将来有可能会有类似的课程。

最后,我想分享一些有类似训练营经历的人的文章:

https://medium.com/@jeremiahng23/general-assembly-dsi-data-science-immersive-sg-experience-and-advice-660fdd25cafa

我希望你喜欢这篇文章!如果您有任何反馈或想法,请随时通过 LinkedInTwitter 与我联系。

迎接 ML 管道挑战

原文:https://towardsdatascience.com/taking-on-the-ml-pipeline-challenge-3dfeb7b24cc6?source=collection_archive---------30-----------------------

行业笔记

为什么数据科学家需要在生产中拥有自己的 ML 工作流

本文讨论了在生产环境中让数据科学家拥有其工作流的好处。我们还讨论了 ZenML,这是一个开源框架,专门为促进这种所有权而构建。

为什么我们需要 ML 管道?

让我们从最明显的问题开始:为什么我们首先需要 ML 管道?以下是一些确凿的理由:

  • ML 管道是以一种可重复的、健壮的和可再现的方式自动化 ML 工作流程的最佳方式。
  • 组织可以通过标准化界面集中、协作和管理工作流。
  • ML 管道可以看作是不同部门之间协调的一种手段。

然而,尽管 ML 管道很棒,但它们确实存在一些可能会被证明有问题的内在问题。

所有权困境

生产中的 ML 令人困惑——图片由作者提供

开发机器学习的组织需要回答的一个问题是谁拥有生产中的 ML 管道?创建模型的是数据科学家吗?是数据工程师在生产中部署它吗?完全是别人吗?

注意:对于 ML 过程中所涉及的角色的概述,请查看加州大学伯克利分校的全栈深度学习课程的这一部分。

ML 的数据维度使其比生产中的其他部署复杂得多。通常情况下,数据科学家不具备可靠地将模型引入生产的技能。因此,团队以这样一种方式组织是很自然的,即所有权从开发的培训阶段转移到工程部门方向的部署阶段。

以这种方式组织可以很容易地在生产中得到一个模型。然而,当事情(不可避免地)出错时,所有权问题才真正发挥作用。这可能是因为模型/概念漂移,或者某些东西超时,或者数据格式改变,或者工程部门不知道的一百万件其他事情,因为他们没有生产模型

此外,你把数据科学家推得离生产环境越远,就越难建立一个 数据飞轮效应 持续改进你的生产模型。数据科学家需要更广泛的背景,以便在训练模型时能够做出正确的判断。例如,如果这意味着该模型可能在生产中执行得更快并产生更高的收入,我们是否应该牺牲 AUROC 几个百分点?如果只看像 AUROC 这样的模型指标,人们甚至不可能问这个问题。

事实上,我们越是将数据科学家从生产中推出,整个 ML 过程的效率就会越低,协调成本和等待时间就会越长。这对于 ML 来说是不可行的,ML 应该是一个快速迭代的过程。

解决所有权困境

最近,有很多关于数据科学家不应该需要了解 Kubernetes 的讨论,或者底层生产基础设施需要从他们那里抽象出来以在高水平上执行。我不仅同意这一点,而且认为我们必须更进一步。我们不仅需要从数据科学家那里抽象出基础设施,还要帮助他们在生产过程中获得模型的所有权。

如果一个团队把编写 ML 管道留到以后,他们会很快积累技术债务。有了正确的抽象,组织可以激励他们的数据科学家在开发过程的早期开始编写端到端的 ML 管道。一旦数据科学家开始使用容易“转移”的 ML 管道编写他们的培训/开发工作流,一旦这些管道投入生产,他们就会发现自己处于一个熟悉的环境中。然后,他们将拥有必要的工具,也可以进入生产系统,在问题出现时解决问题,或者随着时间的推移进行改进。

理想情况下,管道成为一种机制,通过这种机制,模型的生产者(即数据科学家)可以在生产过程中一直拥有他们的模型。

请注意,这并不而不是意味着数据科学家现在应该知道工程工具箱中的每一个工具箱(比如 Kubernetes 集群的复杂部署)。相反,争论的焦点是我们需要设置数据科学家,以便他们可以在必要工具的帮助下,将他们的代码投入生产。

进入 ZenML:一个为现代 MLOps 设计的框架

ZenML 是一个开源的 MLOps 管道框架专为解决上述问题而构建。让我们来分解一下 MLOps 管道框架的含义:

  • MLOps :它在操作化机器学习的领域中运行,即,将 ML 工作流投入生产。
  • ****管道:它通过帮助创建管道来实现这一点,即在这种情况下执行的一系列步骤,特别是针对 ML 设置。
  • ****框架:最后,它用提供通用功能的抽象来创建这些管道软件,这些功能可以由额外的用户编写的代码有选择地更改。

这是一个让你定义管道的工具,但是它和其他的有什么不同呢?这是它与众不同的地方:

适应爆炸式的 ML 工具环境

众所周知,我们现在正处于 ML/MLOps 工具领域的大爆发之中。ZenML 被明确地设计成对你想要使用的底层基础设施/工具没有意见。相反,它公开了像Metadata StoresArtifact StoresOrchestrators这样具有公共接口的高级概念。然后,ML 团队可以更换他们的管道后端的单个组件,它就会“正常工作”。

仔细看:这不是隐藏技术债务图;-) —作者图片

因此,如果您甚至想使用 MLFlow 来跟踪您的实验,在气流上运行管道,然后将模型部署到 Neptune 模型注册表,ZenML 将为您提供这个 MLOps 堆栈。这个决定可以由数据科学家和工程师共同做出。因为 ZenML 是一个框架,所以也可以在这里添加定制的部分来适应遗留的基础设施。

关注机器学习工作流程(在每个阶段)

有许多工具可以让你将工作流定义为管道,但很少有工具明确地将聚焦于机器学习用例

@trainer
def trainer(dataset: torch.Dataset) -> torch.nn.Module:
   ... 
   return model

举个例子,在上面的代码中,ZenML 会明白这不仅仅是管道中的一个步骤,而是一个训练器步骤。它可以使用该信息来帮助特定于 ML 的用例,如将结果存储在模型注册表中、在 GPU 上部署该步骤、超参数调整等。

还要注意,ZenML 完全支持来自常见 ML 框架的对象,如torch.Datasettorch.nn.Module。这些对象可以在步骤和缓存的结果之间传递,以实现更快的实验。

激励数据科学家编写这些管道

ZenML 明白管道会随着时间而改变。因此,它鼓励在本地运行这些管道,并在产生结果时进行试验。您可以在本地 Jupyter 笔记本中查询管道,并使用不同的预先制作的可视化工具(如统计可视化和模式异常)将其具体化。

运行管道后,无论是否在本地运行,都可以轻松地获取它们并查看结果——图片由作者提供

这是一种不同的管道开发方法,更能代表数据科学家在项目早期阶段的工作方式,即快速迭代和可视化,帮助他们对实验做出明智的决策。我们称这种方法为Pipelines As Experiments (PaE)

简而言之,ZenML 允许您用简单的、可扩展的抽象来创建自动化的 ML 工作流,从而减轻您的公共模式负担。在这样做的时候,它不会对底层基础设施发表意见,而是旨在做到与云和工具无关。

通过帮助目标受众,即数据科学家,在开发生命周期的早期用 ZenML 管道编写他们的代码,从实验阶段到生产阶段的过渡变得更加容易。目标是在 ML 生命周期的实验阶段结束时,数据科学家可以切换到生产 ML 堆栈,让他们的管道在生产中运行。此时,他们将拥有这些管道的完全所有权,并且可以随心所欲地管理、更新和调试它们。****

故事到此为止

迄今为止,ZenML 已收到:

看到人们对最初只是一个简单的想法感兴趣真是太棒了。我们现在公开构建 ZenML(这里没有隐藏),而刚刚发布了一个重大版本,对代码库进行了完全重构。因此,如果以上任何一个吸引你,如果你用一个在生产中部署管道的端到端的例子来给 ZenML 一个旋转,那将是非常好的。欢迎反馈和投稿!

我最诚挚地感谢亚历克斯·斯特里克和亚当·普罗布斯特帮助编辑这篇文章。

参考和欣赏

本帖中引用了一些有用的链接:

** https://fall2019.fullstackdeeplearning.com/course-content/ml-teams/roles https://huyenchip.com/2021/09/13/data-science-infrastructure.html https://eugeneyan.com/writing/end-to-end-data-science/#from-start-identify-the-problem-to-finish-solve-it https://multithreaded.stitchfix.com/blog/2019/03/11/FullStackDS-Generalists/#back-1 https://docs.zenml.io/ **

考虑季节性的时间序列分析

原文:https://towardsdatascience.com/taking-seasonality-into-consideration-for-time-series-analysis-4e1f4fbb768f?source=collection_archive---------3-----------------------

克里斯·劳顿在 Unsplash 上的照片

理解大数据

使用季节性指标或傅立叶分析

顾名思义,季节性是指时间序列数据的季节性特征。它是在一年内以一定频率重复的可预测模式,如每周、每月、每季度等。证明季节性的最直接的例子是看温度数据。在地球上的大多数地方,我们总是认为夏天的温度会高一些,而冬天的温度会低一些。

在时间序列预测中,如需求预测,考虑季节性是非常重要的。例如,我们可以预期冰淇淋的销售有季节性,因为每年夏天的销售额会更高。考虑销售季节性影响的模型在时间序列预测中会更准确。一般来说,时间序列分析的目标是利用数据的时间特性来建立更复杂的模型。为了正确预测事件,我们需要实施技术来发现和模拟数据中的长期趋势、季节性和残留噪声。本文将重点讨论如何检测数据中的季节性,以及如何将季节性纳入预测中。

检测季节性

在将季节性放入模型之前,我们需要知道数据是如何重复的,重复的频率是多少。如果您非常了解数据的背景,检测季节性会非常简单。例如,我们知道一年中夏天的温度会高一些,冬天的温度会低一些。要发现您不熟悉的数据的季节性,简单的方法是绘制数据并观察时间序列的周期性信号:

观察温度的季节性

上图显示了每年重复的模式。即使每个夏天达到的高度各不相同,我们仍然可以看到温度在夏天最高,在冬天最低的模式。

温度数据在一天内也有季节性,我们可能不知道温度在一天内如何波动。我们可以在较低的频率下绘制数据,或者使用一种称为快速傅立叶变换( FFT) 到的算法来检测重复频率。任何周期信号都可以表示为几个幅度、相位和频率不同的正弦波之和。一个时间序列可以用称为 傅立叶变换 的数学工具转换成它的频率分量。FFT 的输出可以被认为是数据的所有频率成分的表示。在某种意义上,它是一个直方图,每个“频率仓”对应于信号中的一个特定频率。每个频率分量都有振幅和相位,并表示为复数。通常,我们只关心振幅,以确定数据中最高的“频率仓”是什么。在这里我不会在数学上讲太多细节,但是如果你感兴趣,Cory Maklin的这篇文章很好地解释了这一点。要在数据集中执行 FFT,我们可以使用 Scipy 中的 FFT 模块。以具有 13 年每小时温度的温度数据集(temps)为例。数据集如下所示:

对数据集执行以下代码:

from scipy.fftpack import fft
import numpy as np
import matplotlib.pyplot as pltfft = fft((temps.Temperature — temps.Temperature.mean()).values)
plt.plot(np.abs(fft))
plt.title("FFT of temperature data")
plt.xlabel('# Cycles in full window of data (~13 years)');

并不是说在第一步中,我们减去温度的平均值,以避免较大的零频率分量。用 13 年的数据绘制整个数据集可能无法很好地显示模式,如下图所示:

没有虚部的实信号的傅立叶变换关于频率范围的中心是对称的。绘制长时间范围内的 FFT 可能无法提供我们想要的最相关的信息。因此,我们可以放大以检查不同频率级别的“频率仓”。我们预计温度具有每日季节性,因此我们放大查看从第 0 天到第 5 天的“直方图”:

plt.plot(1./13 * np.arange(len(fft)), np.abs(fft))
plt.title("FFT of temperature data (Low Frequencies zoom)")
plt.xlim([0,5])
plt.xlabel('Frequency ($y^{-1}$)');

下图显示了每日季节性,因为“频率箱”在“第 1 天”的频率非常高:

同样,我们可以放大到第 365 天左右的频率,以检查每年的季节性:

plt.plot(1./13 * np.arange(len(fft)), np.abs(fft))
plt.title(“FFT of temperature data (High Frequencies zoom)”)
plt.ylim([0,120000])
plt.xlim([365–30, 365 + 30])
plt.xlabel(‘Frequency ($y^{-1}$)’);

下图显示了 365 天达到高峰时的年度季节性。

FFT 是转换时间序列数据的一个很好的工具,因为它可以被绘制成“频率直方图”。图表将显示数据重复模式的频率,从而检测数据的季节性。

增加季节性

检测到季节性后,有几种方法可以将季节性合并到模型中,以更好地执行时间序列预测。本文将介绍利用季节指标、傅立叶分析和 SARIMA 模型在时间序列预测中加入季节性。

1、添加季节性指标

将季节性因素添加到模型中最直接的方法是添加季节性指标。季节指标是描述每次观测的“季节”的分类变量。以温度预测为例。为了指示每日的季节性,在训练模型时,您可以使用“小时”作为观察的特征。该功能将像任何其他功能一样,在预测温度时采用一天中某个小时的固定效果。为了包括每年的季节性,我们应该以同样的直觉在模型中添加“月”和“季度”作为特征。使用上面列出的数据集,每个观测值应包括以下特征:

包括季节性指标

“小时”、“月”、“季度”变量是我们应该包括的特征,以捕捉数据中的季节性。尽管它们是数值形式,但它们实际上是分类变量而不是数值变量。注意,如果我们使用线性模型进行预测,为了包含这些分类变量,我们需要首先使用像一键编码这样转换器来转换这些变量。转换后,“小时”变量应该如下所示:

“小时”变量的五个观察值被转换成四列,显示小时的不同值。您可以说我们没有将 Hour_4 作为一列包含在这里,以避免多重共线性。如果小时只有五个值,不在前四个值中,则自动表示该观察值取第五个值。使用 Pandas 进行一键编码的一个简单方法是使用函数 get_dummies():

pandas.get_dummies(data, drop_first=True)

该函数会将分类变量转换为虚拟变量,从而准备好放入线性模型。这些虚拟变量被称为季节性指标。

如果您的预测模型不假设线性关系,您不需要进行一次性编码。例如,如果您使用树模型,只需将分类变量作为特征放入模型中。如果分类变量是文本形式的,在放入模型之前,给每个类别分配数字。(将“一月”改为“1”)

2、傅立叶分析

任何信号都可以表示为不同频率𝑓𝑛和振幅𝐴𝑛和𝐵的正弦和余弦的线性组合:

傅立叶变换将信号分解成一组频率,使我们能够确定构成时间序列的主要频率。以温度数据为例。从上面的图中,我们知道温度大致是正弦曲线。因此,我们知道一个合理的模型可能是:

其中 y0t0 是待学习的参数。对于季节变化,t 通常为一年。虽然该函数在 y0 中是线性的,但在 t0 中不是线性的。然而,使用傅立叶分析,上述情况相当于:

此函数在 A 和 b 中是线性的。因此,我们可以创建一个包含一个或多个时间尺度上的正弦项的模型,并使用线性回归来拟合数据。以下代码显示了构建年、半年和日季节性作为特征,并在线性回归模型中使用它们来预测温度的过程:

df['sin(year)'] = np.sin(df['julian'] / 365.25 * 2 * np.pi)
df['cos(year)'] = np.cos(df['julian'] / 365.25 * 2 * np.pi)
df['sin(6mo)'] = np.sin(df['julian'] / (365.25 / 2) * 2 * np.pi)
df['cos(6mo)'] = np.cos(df['julian'] / (365.25 / 2) * 2 * np.pi)
df['sin(day)'] = np.sin(df.index.hour / 24.0 * 2* np.pi)
df['cos(day)'] = np.cos(df.index.hour / 24.0 * 2* np.pi)regress = LinearRegression().fit(X=train[['sin(year)', 'cos(year)', 'sin(6mo)','cos(6mo)','sin(day)','cos(day)']], y=train['temp'])

上面的 FFT 图对于确定哪种季节性应该包含在回归中非常有用。请注意,这里没有使用常规日期,而是使用儒略日作为 t 变量。儒略日是自儒略历开始以来的天数(公元前 4713 年 1 月 1 日),因此它是一个连续的数字。

除了加入季节性指标或使用傅立叶分析,我们还可以使用 SARIMA 模型,即在 ARIMA(自回归综合移动平均)模型中加入季节性成分。本教程有兴趣的话详细描述萨里玛模型。

感谢您阅读这篇文章。这是我所有博客帖子的列表。如果你感兴趣的话,可以去看看!

https://zzhu17.medium.com/my-blog-posts-gallery-ac6e01fe5cc3 https://zzhu17.medium.com/membership

posted @ 2024-10-16 09:03  绝不原创的飞龙  阅读(342)  评论(0)    收藏  举报