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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 mbleven 快速计算 Levenshtein 距离

原文:https://towardsdatascience.com/faster-levenshtein-distance-calculation-using-mbleven-b5d96bde7feb?source=collection_archive---------31-----------------------

莱文斯坦永远服用*?如果你的 levenshtein 算法需要很多时间,并且你的边界参数小于 3,请尝试使用 mbleven。*

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

来源

什么是 levenshtein 距离?

Levenshtein 距离是将字符串 a 转换为字符串 b 所需的最小插入、删除和符号替换次数。

举例: 考虑字符串 a: 鼠标 &字符串 b: 莫尔斯

a 与弦 b 之间的 Levenshtein 距离为 2。您需要从字符串 a 中删除 u 并插入 r 以将字符串 a 转换为字符串 b.

levenshtein 距离还有另一个修改:

  1. Damerau Levenshtein 遵循与 Levenshtein 距离完全相同的方法,但您也可以使用换位(相邻符号的交换),因此,它使 Levenshtein 更快、更有效。

在上面的例子中,字符串 a 和字符串 b 之间的 Damerau-Levenshtein 距离是 1。你只需要用 r 替换字符串 a 中的 u 就可以将字符串 a 转换为字符串b

虽然看起来很简单,但是如果你在一个熊猫数据帧中有数千行,那么 Levenshtein 距离需要花费很多时间来运行。

mbleven 来拯救—

与 Levenshtein 不同,mbleven 是一种“基于假设的算法”。它将首先列出将一个字符串转换为另一个字符串的所有可能的假设。

上述例子的可能假设:

  1. 如果 I 插入 r 是否可以将字符串 a 转换为字符串 b
  2. 如果我删除 u 字符串 a 可以转换成字符串 b 吗?
  3. 如果我用代替 u ,字符串 a 能转换成字符串 b 吗?
  4. ….

mbleven 将逐一检查所有的假设。所有的假设都可以在 O(n)次内计算出来。

完整的代码及其实现可以在这里查看:https://github.com/fujimotos/mbleven

mbleven 可以确认是否可以使用提到的 k-bound 将一个字符串转换成另一个字符串&它还可以返回两个字符串之间的编辑距离。提到的几个例子是:

*>>> from mbleven import compare
>>> compare("meet", "meat")
1
>>> compare("meet", "eat")
2
>>> compare("meet", "mars")  # distance 3
-1*

最后一个示例返回-1,因为这两个字符串之间的距离是 3 编辑距离,默认情况下,该算法的上限是 2 编辑距离。

参考文献—

**

https://github.com/fujimotos/mbleven

使用 GPU 或 TPU 进行更快的机器学习训练

原文:https://towardsdatascience.com/faster-machine-learning-training-with-a-gpu-or-tpu-24023501104f?source=collection_archive---------28-----------------------

Google Colab 可以从 GitHub 或 Drive 访问任何公开的 Jupyter 笔记本

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

机器学习 Jupyter 笔记本在 Colab 上免费运行。照片由 Nana DuaUnsplash 上拍摄

为什么要用 Google Colab?

您可以在本地计算机上使用 Jupyter 笔记本。Google Colab 在许多方面改进了 Jupyter 笔记本。以下是使用 Google Colab 的七个最有力的理由:

  1. 你可以从 GitHub 库中获得任何一个公开的 Jupyter 笔记本。
  2. 您可以将任何.ipynb文件加载、编辑并保存到与 Colab 登录相关的 Google Drive 中。每个项目都有一个独立的谷歌账户和不同的谷歌驱动是很有帮助的。

注意:你可以在 Google Drive 上为任何项目文件夹创建 Git 账户。每个团队成员都在各种不同的本地计算机上运行。他们只需要一个浏览器和互联网连接。您的团队可以通过云在地理上完全分散。

3.您可以配置多代 NVIDIA GPU 中的一款。

4.您可以提供多代谷歌 TPU 中的一个。

5.您可以配置多核 CPU。

6.谷歌 Colab 免费。此外,你可以升级到每个账户每月 9.99 美元的高级版本。

7.Colab 笔记本有许多 Jupyter 笔记本的有用扩展。

从 GitHub Repo 加载文件到 Colab

在浏览器中,前往[https://colab.research.google.com](https://colab.research.google.com)。一个指向 Google Colab 的新标签打开:

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

图 Google Colab 的入口。

如果你是 Colab 的新手,在Recent中唯一的文件是Welcome to Collaboratory。由于我不是新来的,你可以在Recent里数五个文件。

从 GitHub 加载文件

点击 GitHub,观察:

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

图 2:点击 GitHub。

输入您想要浏览的 GitHub 帐户。我进入了bcottman,我的 GitHub 顶级库。

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

图 3:选择 bcottman/paso 回购

从回购bcottman/paso中,我选择了文件bcottman/paso/integration_test_pre_all.ipynb

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

图 4:选择文件bcottman/paso/integration_test_pre_all.ipynb.

这导致文件bcottman/paso/integration_test_pre_all.ipynb被加载到 GCP(谷歌云平台)的 Colab 浏览器中。

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

图 5:文件bcottman/paso/integration_test_pre_all.ipynb loaded into Google Colab.

从 Google Drive 加载文件

您可以创建一个 Google Drive,然后为任何项目文件夹创建一个 Git 帐户。你要去[https://colab.research.google.com](https://colab.research.google.com.Going)。安装谷歌账户的谷歌硬盘。当您点击File|Open notebook时,Google Drive 中的所有文件都会出现:

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

图 6:点击File|Open notebook.

选择colab_itils.ipynb文件:

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

图 Google Drive 中的顶层文件。

供应多代 NVIDIA GPU 中的一款

点击Runtime|Change runtime type:配置 Nvidia GPU:

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

图 8:点击Runtime|Change runtime type:配置 Nvidia GPU

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

图 9:选择 GPU。

通过以下方式检查 Nvidia GPU 的配置状态:

The from tensorflow.python.client import device_lib
device_lib.list_local_devices()

输出:

[name: "/device:CPU:0"  
device_type: "CPU"  
memory_limit: 268435456  
locality {  }  
incarnation: 17311008600223054265, 
name: "/device:GPU:0"  
device_type: "GPU"  
memory_limit: 14674281152  
locality {
    bus_id: 1    
    links {    }  }  
incarnation: 7680686309919727928  
physical_device_desc: "device: 0, 
name: Tesla T4, pci bus id: 0000:00:04.0, compute capability: 7.5"]

提供了 14.67 GB 快速内存的 Nvidia Telsa T4。

提供谷歌 TPU

要设置谷歌 TPU,请在“笔记本设置”中选择 TPU:

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

图 10:选择 TPU。

结论

在这篇短文中,我展示了如何:

  1. 您可以从 GitHub 存储库中获取任何公共文件。
  2. 您可以加载、编辑和保存任何.ipynb文件到与 Colab 登录相关的 Google Drive。

3.您可以配置多代 NVIDIA GPU 中的一款。

4.您可以提供多代谷歌 TPU 中的一个。

Google Colab 的一个关键功能是团队成员可以使用 GitHub 上的共享文件在项目上进行协作。此外,每个团队成员都可以在自己的 Google Drive 上创建自己的开发沙盒。

云支持远程工作。编码快乐!

更快的机器学习版本和跟踪:使用 FDS 的例子

原文:https://towardsdatascience.com/faster-machine-learning-versioning-and-tracking-example-using-fds-33fa7183aac8?source=collection_archive---------37-----------------------

使用 FDS,一个开源工具,快速简单地对你的机器学习项目进行版本控制

FDS,快速数据科学,是一个开源工具,使机器学习快速&的版本控制变得容易。它将 Git 和 DVC 结合在一起,负责代码、数据和模型版本控制。

FDS 会帮助你:

  • 使用智能版本控制向导🧙‍♂️.,通过推荐每个文件应该被跟踪的位置来避免错误
  • 通过统一命令(如git status + dvc status = fds status)自动化重复性任务
  • 通过提供以人为中心的 UX,使版本控制更快、更容易使用、更友好——想要保存新版本并将其推送到您的共享遥控器,只需fds save就可以了。

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

快速数据科学,作者图片

这个博客是如何使用 FDS 来版本化你的机器学习项目的分步指南。我们将跟踪“肺炎检测”项目,在该项目中,我们训练一个 TensorFlow 模型来对患病和健康的胸部 x 光图像进行分类。本项目中使用的数据集取自“胸部 X 射线图像(肺炎)”ka ggle 竞赛。通过以下详细步骤,您将获得使用 FDS 的实践经验。

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

肺炎检测数据示例,图片由作者提供

在这篇博客中,我们将介绍如何使用 FDS 执行以下操作:

  • 在本地机器上初始化和配置 Git 和 DVC。
  • 使用 Git 和 DVC 通过一个命令跟踪项目文件。
  • 将文件推送到 Git 和 DVC 远程。
  • 只需一个命令,即可自动对所有项目文件进行版本控制、跟踪、提交和推送

项目设置

我们将首先从名为“Pneumonia-Detection”的终端创建一个新目录,并移动到该目录中。然后,我们将创建一个虚拟环境,将其添加到。gitignore 文件,激活它,通过运行pip install fastds安装 FDS。

注: 因为 DVC 也可以用 brew 安装,所以我们没有把它作为依赖包添加到 FDS。但是,如果 FDS 发现 DVC 没有安装在虚拟环境中,它会建议您安装 DVC。

Mac 和 Linux

$ mkdir Pneumonia-Detection && cd Pneumonia-Detection
$ python -m .venv venv
$ echo .venv/ >> .gitignore
$ source .venv/bin/activate

$ pip install fastds

Windows 操作系统

$ mkdir Pneumonia-Detection && cd Pneumonia-Detection 
$ py -m venv .venv 
$ echo .venv/ >> .gitignore 
$ .venv/Scripts/activate.bat $ pip install fastds

接下来,我们将初始化 Git 和 DVC。我们可以使用fds init命令来初始化这两个工具,而不是使用这两个工具。

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

FDS init,Gif 作者

让我们在 DAGsHub 上打开一个存储库,并将其命名为“肺炎检测”。

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

新存储库设置,按作者分类的图像

接下来,我们将通过运行以下命令,用我们的本地目录配置存储库的 Git 和 DVC 远程设备:

$ git remote add origin https://dagshub.com/<DAGsHub user-    name>/Pneumonia-Detection.git
$ dvc remote add origin https://dagshub.com/<DAGsHub user-name>/Pneumonia-Detection.dvc
$ dvc remote modify origin --local auth basic
$ dvc remote modify origin --local user <DAGsHub user-name>
$ dvc remote modify origin --local password <your token>

添加项目文件

我们准备将文件添加到本地目录中。对于这个任务,我们将使用dvc get命令从 DAGsHub 下载文件。请注意,该命令仅在本教程中是必需的。我选择使用它,这样你就可以按照教程访问这些文件。

注意: 原始数据集很大。我们将使用较小版本的数据集来减少下载、版本控制和上传时间。如果要使用完整的数据集,跳过第一个命令,直接从 Kaggle 竞赛 下载,解压到 *Pneumonia-Detection/data/raw-data* 下。

$ dvc get https://dagshub.com/nirbarazida/Pneumonia-Detection-FDS-Demo data/raw-data -o data/raw-data
$ dvc get https://dagshub.com/nirbarazida/Pneumonia-Detection-FDS-Demo eval 
$ dvc get https://dagshub.com/nirbarazida/Pneumonia-Detection-FDS-Demo model/ -o model/ 
$ dvc get https://dagshub.com/nirbarazida/Pneumonia-Detection-FDS-Demo src

现在,该项目包含以下目录:

  • data/ -保存分成三个子目录的原始数据图像:train、val(验证)和 test。
  • eval/ -保存关于型号及其性能的信息。
  • model/ -拥有最佳性能的预处理模型。
  • src/ -保存项目的代码文件,包括 Python 模块和 Jupiter 笔记本。

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

项目的树,作者的图像

用 Git + DVC = FDS 跟踪文件

此时,我们想用 Git 和 DVC 跟踪项目中的文件。该任务需要以下步骤:

  • 选择和跟踪 DVC 的大文件/目录。
  • 使用 Git 跟踪指针/管道文件。
  • 用 Git 跟踪项目的其余文件。

当使用 Git 和 DVC 来版本化项目时,我们经常执行这些动作。这种重复的工作可能会很麻烦,并且对于一些用户来说,不直观。这正是我们创建fds add向导的原因!

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

与 imgflip.com 一起创建的图像

因为我们想要对所有的项目文件进行版本化,所以我们将运行fds add .

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

FDS 添加,Gif 作者

项目的所有文件都被版本化,并准备好被推送!但是等等,在我们运行 push 命令之前,我们需要先提交文件。fds commit命令将dvc commitgit commit封装成一个。它首先提交对 DVC 的更改,将带有更新哈希的指针文件添加到 git,然后立即将这些更改(加上任何其他阶段的更改)提交到新的 Git 提交。在我们的例子中,FDS 将认识到在 DVC 跟踪的文件中没有任何改变;因此,它将有效地只提交 Git 跟踪的文件,这正是我们所期望的。

$ fds commit “Track all the project files with FDS”

此时,我们希望确保所有文件都已提交。为此,我们将运行fds status命令,检查 Git 和 DVC 跟踪的文件的状态。

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

FDS 状态,作者 Gif

女士们先生们,请系好安全带……正式推送时间到了!

为了推送我们的文件,我们将使用fds push命令…你猜对了——推送由 Git 和 DVC 跟踪的文件!让我们在 DAGsHub 上检查存储库的新状态。

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

存储库的新状态,按作者分类的图像

正如我们所见,Git 和 DVC 跟踪的所有文件都被推到了远程。不仅如此,我们可以在一个地方看到项目的所有组件,包括代码、数据、模型和管道。

将流程缩短为一个命令

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

一条捷径。斯蒂芬·斯坦鲍尔 / Unsplash 摄影

如果您不熟悉 Git、DVC 或 FDS,并且不习惯使用这些命令,或者只是想让您的生活更简单,那么fds save命令就是为您准备的!通过运行这个命令,FDS 将使用 Git 和 DVC 对所有项目文件进行版本控制、跟踪、提交和推送。为了展示这个命令的用法,我们将下载一个处理过的数据目录并运行fds save命令。

$ dvc get [https://dagshub.com/nirbarazida/](https://dagshub.com/nirbarazida/Pneumonia-Classification)[Pneumonia-Detection-FDS-Demo](https://dagshub.com/nirbarazida/Pneumonia-Detection-FDS-Demo) data/processed -o data/processed
$ fds save “Add processed data directory”

让我们在 DAGsHub 上检查存储库的新状态。正如我们所看到的,DVC 跟踪了处理过的数据目录,Git 跟踪了更新过的 data.dvc 指针文件,两者都被成功地推送到 DAGsHub。

摘要

我们已经到了本教程的结尾,但是我们共同的旅程才刚刚开始。

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

与 makememe.org 一起创建的图像

FDS 是完全开源的!

虽然我们的开发人员不断提高 FDS 的能力,但我们欢迎您为 FDS 做出贡献,并获得永恒的荣耀。您可以通过以下方式参与:

  • 创建一个带有错误修复或新增强的拉请求,
  • 使用 FDS,让我们知道我们可以做出的任何问题或改进——通过创建一个问题或在我们的不和谐频道上分享
  • 主演回购并与你的同事和朋友分享。

使用 Python 和深度学习加快笔记速度

原文:https://towardsdatascience.com/faster-notes-with-python-and-deep-learning-b713bbb3c186?source=collection_archive---------9-----------------------

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

格伦·卡斯滕斯-彼得斯在 Unsplash 拍摄的照片

使用基于深度学习的 OCR 转录 pdf 幻灯片

做笔记的管道

传统的讲座通常附带一套 pdf 幻灯片。传统上,记录这类讲座的过程包括从 pdf 中复制或转录大量内容。

最近,我一直在尝试通过使用 OCR(对象字符识别)来自动转录 pdf 幻灯片,以在 markdown 文件中直接操作它们的内容,从而避免手动复制和粘贴 pdf 的内容,从而实现这一过程的自动化。

在本文中,我将向您展示如何使用基于深度学习的 OCR 自动将 pdf 幻灯片转换为文本。

为什么不使用传统的 pdf 转文本工具?

我之所以不选择使用传统的 pdf 文本工具,是因为我发现它们往往会带来更多的问题,而不是解决它们。我尝试使用传统的 python 包,但是它们带来了一些问题,比如必须用复杂的正则表达式模式解析最终输出,所以我决定尝试一下对象检测和 OCR,看看是否可以做得更好。

步伐

接下来的步骤是:

  1. 将 pdf 转换成图像
  2. 检测并识别图像中的文字
  3. 展示示例输出

在这种情况下,我主要修改了这个中的代码,它使用了对 CTPN 模型的 pytorch 修改,以及来自 pytorch_ctpn 的代码用于文本检测,以及来自 CRNN 模型的代码用于文本识别。

现在,让我们来看一下每一步。

1.将 pdf 转换成图像

我将使用 David Silver 的《强化学习导论》中的 pdf 幻灯片。让我们首先编写一些代码,使用pdf2image包将每张幻灯片转换成 png 格式。

现在我有了所有的图像,

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

图片作者。pdf 中的所有幻灯片。

让我们在每张幻灯片上运行文本检测和识别。

2.检测和识别图像中的文本

为此,我们将使用来自 ocr.pytorch 资源库的文本检测器。按照那里的说明下载模型,并将它们保存在checkpoints文件夹中。

在这里,我们设置输入和输出文件夹,然后对所有输入图像(转换后的 pdf 幻灯片)运行一个循环,然后通过运行位于ocr模块中的检测和识别模型的single_pic_proc()函数。然后,我们将输出保存到输出文件夹。

检测继承自 Pytorch 的 CTPN 模型,识别模型继承自 Pytorch 的 CRNN 模型,两者都存在于ocr模块中。

3.展示示例输出

检测输出示例:

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

图片作者。文本检测输出的示例。

文本识别输出:

- AboutRL
Characteristics of Reinforcement Learning
What makes reinforcement learningdifferent from other machine
learning paradigms?
There isnosupervisor,only areward signal
Feedback is delavyed,not instantaneous
Time really matters(sequential,non ii.d data)
Agent sactions affectthe subseauent datait receives

不再复制和粘贴

我喜欢这种方法的原因是,你最终可以拥有一个真正强大的工具来转录各种类型的文档,从检测和识别手写笔记到检测和识别照片中的随机文本。

拥有自己的 OCR 工具来处理您经常交互的内容,比依赖外部软件来处理您想要转录的每个文档要好。

对我来说,这是一个有趣的机会,可以探索 OCR,并建立一个管道来快速转录 pdf 幻灯片附带的讲座。

你可以在这里查看源代码。

如果你喜欢这篇文章,请在 TwitterLinkedIn 上联系我,并在 Medium 上关注我。谢谢,下次再见!😃

参考

CPU 上更快、更平滑、更小、更准确和更鲁棒的人脸对齐模型

原文:https://towardsdatascience.com/faster-smoother-smaller-more-accurate-and-more-robust-face-alignment-models-d8cc867efc5?source=collection_archive---------7-----------------------

思想和理论

人脸标志检测器的训练策略、实现优化和新的评价方法。

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

使用和不使用 GTX 训练的正面人脸图像的 DAN、ERT 和 LBF 方法的推论(图片由作者提供)。

在你的人脸分析项目或应用中,是否使用人脸地标检测作为核心组件?你是否使用流行的计算机视觉库中的人脸对齐方法,如OpenCV【1】或Dlib【2】?如果你想改进你的人脸对齐模型,在这篇文章中,我将解释如何使它们更快、更平滑、更小、更准确、更健壮,特别是对于人脸跟踪应用。此外,我在我的 Gitlab 知识库中提供了一组已经为 OpenCVDlib 改进的模型,该知识库是为我们在实时图像处理杂志 (Springer)上发表的文章而创建的:

Alvarez Casado,c .,Bordallo Lopez,M.
实时人脸对齐:评估方法、训练策略和实现优化。
施普林格实时图像处理杂志,2021 年

ace 对齐在大多数人脸分析系统中是一个至关重要的组件。它着重于识别图像或视频中人脸的几个关键点的位置。尽管在流行的计算机视觉库中,如 OpenCVDlib 中,有几种方法和模型可供开发人员使用,但他们仍然面临着照明不足、极端头部姿势或遮挡等挑战,特别是当他们受到实时应用需求的限制时。

如前所述,我们最近发表了一篇期刊文章,其中我们提出了一套基于数据增强和软件优化技术的最佳训练策略和实施规则,这些规则有助于改进属于几个用于人脸对齐的实时算法的各种模型。我们将它们命名为一般培训扩展 ( GTX )策略。此外,我们还提出了一组扩展的评估指标,允许新的评估来缓解在实时跟踪上下文和真实场景中发现的典型问题。实验结果表明,使用我们提出的技术生成的模型更快、更小、更准确,在特定的挑战性条件下更鲁棒,在跟踪系统中更平滑,如下一个视频所示。

这种训练策略显示出适用于不同类型的设备和算法,使它们在学术和工业应用中通用。

为了评估我们的方法,我们专注于三种被认为是不同应用的最先进的人脸对齐方法, LBF (局部二进制特征)[3]用于 OpenCVERT (回归树的集合)[4]用于 DlibDAN (深度对齐网络)[5],可在 pip (Python)中获得。LBF 和 ERT 方法,也称为快速人脸对齐方法,基于级联回归器,而 DAN 算法基于深度学习方法。我们使用由多饼地标方案定义的 68 个地标位置。

评估度量和基准 面部对齐的标准度量通常包括那些与基础事实注释相比时与预测质量相关的度量。这主要包括准确度误差,在某些情况下还有失败率。此外,通常计算计算效率,通常以每个面的毫秒数表示,以及每秒处理的帧数(fps)。

问题在于,这些度量没有测量在大多数面部对齐模型中观察到的若干现象,例如:

  • 抖动:恼人的帧间噪声和微小变化。这种影响可能是由缺乏训练样本、具有高方差的不精确注释、不干净的数据集或者在例如初始化阶段使用某种(伪)随机信息的非确定性推理方法产生的。
  • 人脸对齐灵敏度:大部分人脸对齐算法依赖人脸检测包围盒进行形状初始化。面部检测器在连续的帧中并不总是一致的。此外,大多数人脸对齐模型是用一个人脸检测器的人脸矩形来训练的。

基于这些现象,我们定义了三个新颖的度量,并使用它们来评估一个模型在跟踪应用期间有多好的性能。我们建议计算两个连续帧估计形状之间的帧间误差:

  • 地标均方位移度量(laMSD),计算地标在静态人脸下如何沿视频移动。
  • 归一化抖动灵敏度均方误差 (NJS-MSE_σ )是通过使用基于水平和垂直轴上的小中心偏移的面部矩形的随机变化来推断一组参考图像上的面部标志而计算的度量。误差测量产生评估度量,以比较面部对准模型的 抖动鲁棒性
  • 归一化人脸检测灵敏度均方误差 (NFDS-MSE_σ )。对于此度量,随机变化基于水平和垂直轴上的面部矩形中心偏移以及面部边界框的大小(宽度和高度)的随机变化。这产生了一个评估度量,用于比较我们的面部对准模型与 不同面部检测器 的鲁棒性。

为了评估我们的模型,我们在文献中先前提出的完善的标准基准和我们精心设计的一组基准的组合中测试它们。大多数相关工作主要关注两个性能指标,准确度效率,但我们认为它们不是评价人脸对齐模型的唯一关键指标。我们相信这种基准组合有助于描述在无约束环境下运行的实时应用程序中更加客观现实的行为。这些基准描述如下:

  • 野外常见的 基准(300-W)【6】,用以测试一般精度和误差作为与其他机型比较的参考。
  • 抖动基准,重点测量模型的抖动效果
  • 特定领域基准,侧重于测试特定领域的模型,如弱光条件、极端倾斜的头部、强背光场景等

训练策略
主要思想是实现“更好”的人脸对齐模型。传统上,这是指更精确的模型。但如前所述,我们通过评估实时应用和真实场景中的其他关键方面,特别是在跟踪地标时,扩展了这一概念。

为了实现这一目标,我们建议在培训过程中执行几条规则,例如:

  • 基于图像处理的数据扩充:几何和颜色变换。
  • 基于统计操作的数据扩充:图像归一化、噪声注入、初始化变化、异常值去除。
  • 添加领域特定数据:我们研究属于已证明在基本模型中失败的特定条件的图像集合。这些图像用一个缓慢而精确的模型和一个教师
    学生建筑来注释。在我们之前的出版物中可以看到关于这项技术的更多细节。

实现和并行化
我们已经描述了从串行优化到并行化策略的一系列实现技术。从性能及其可能的精度折衷的角度分析了这些解决方案。

为了测试这些建议的优化,我们实现了自己的 C++版本的 LBF 方法。因此,我们可以将我们自己的实现与 OpenCV 实现进行比较,例如相同的算法,并在 OpenCVDlib 的实现版本中执行一些其他优化。

在文章中,我们解释了如何加快训练和推理过程。在训练中,我们通常使用OpenMP【7】来加速算法拓扑允许的循环。更准确地说,我们在 LBF 算法中加速了局部特征映射函数的学习,因为如图 1 所示,每个界标都是独立于其余的。

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

图。1(图片由作者提供):LBF 方法中的训练过程。学习过程遵循级联式拓扑。局部特征的线性回归最小化当前形状和目标地面真实形状之间的距离。

在训练我们的面部对齐模型之后,我们通过主要应用三种策略来加速推断:

  • 每个地标计算的并行化(局部特征映射功能)。
  • 加速在上述过程中提取的高维特征和全局线性回归或转移矩阵 w 的相乘。我们应用三种不同的优化技术,如图 2 所示。
  • **对生成的模型进行量化。**我们将模型的数据从浮点数转换成短整数。这提高了推断的速度,尤其是在具有缓存和内存限制的设备上,例如移动设备。

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

图 2(图片由作者提供):稀疏线性投影 W t 的乘法,在面部对齐
过程的每个阶段使用 3 种不同的技术计算。

对比评估
为了更好地理解之前的规则集以改进我们的人脸对齐模型,我们从误差、模型大小、计算时间以及跟踪模式和挑战场景中的性能等方面,对最终模型中的训练策略和实现优化技术的影响进行了实证评估和分析。作为 GTX 训练策略的结果,我们获得了一组被标记为 LBF_gtx 模型的增强模型,这些模型将与 LBF_base 模型和其他互补模型进行比较。

精度与尺寸和速度对比:

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

300 瓦全套测试的平均误差(%)和失败图像(%)。在中间一栏中,每个型号的大小以兆字节(MB)为单位。在上一栏中,基准测试中的平均计算时间是以每张脸毫秒数为单位的。在评估的 LBF 模型中,“q”表示量化模型,“float”是原始模型,它们都已经集成到我们的 C++管道中。DAN 模型是原始论文中提供的原始模型。并且通过 Dlib 库使用 ERT 模型,比较库提供的模型和我们自己训练的 ERT 模型。OpenCV LBF 模型通过 OpenCV 库使用。索引 1、2、3 和 4 表示 OpenCV 默认模型与不同的人脸检测器一起使用,包括板载的哈尔卡斯卡德人脸检测器和 DNN 人脸检测器。该推断是使用配备 2.6 GHz 英特尔酷睿 i7 处理器的笔记本电脑做出的(图片由作者提供)。

我们的抖动基准测试中的抖动评估:

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

在我们自行设计的抖动基准测试中,总抖动量和每帧抖动量按每帧 laMSD 增长排序。该推断是使用配备 2.6 GHz 英特尔酷睿 i7 处理器的笔记本电脑得出的。我们的 LBF 模型是浮动版本,以便与 OpenCV one(图片由作者提供)进行公平的比较。

特定于领域的性能指标评测:

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

在使用领域特定的未标记数据和师生方案训练基础模型之后,在 300W 全套和领域特定的测试子集上的平均误差(%)和失败图像(%)(图片由作者提供)。

模型量化的影响:

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

对于不同的
硬件设备,量化在准确性(300 w-公共数据集)、速度和大小方面的影响(图片由作者提供)。

定性结果

为了查看建议的培训策略和实施优化的影响,我创建了一些视频来观察它们的效果。

结论

本文的结果显示了一组优化和训练策略在人脸对齐系统环境中的影响,该人脸对齐系统旨在集成到在台式计算机和移动设备中实时运行的解决方案中。在没有任何算法开发的情况下,我们展示了训练、实施和系统设计的巧妙策略如何在准确性、速度、模型大小或挑战性条件下的失败率方面对模型的性能产生巨大影响。

感谢阅读。我希望你从阅读这篇文章中学到的和我写这篇文章时学到的一样多。干杯!

这项工作与 米盖尔·博尔达洛 合作完成。

更多详情请见:

Alvarez Casado,c .,Bordallo Lopez,M.
实时人脸对齐:评估方法、训练策略和实现优化。
施普林格实时图像处理杂志,2021

从以下位置下载模型: 从文章的 GitLab 资源库中下载代码、模型、基准数据集和示例视频,文章中生成的模型现在是 Dlib 库模型库中的标准模型。

参考文献

[1] OpenCV 库:
【2】Dlib 库:
【3】s . Ren,X. Cao,Y. Wei,J. Sun,“通过回归局部二值特征实现 3000 FPS 的人脸对齐”, 2014 年 IEEE 计算机视觉和模式识别会议,美国俄亥俄州哥伦布市,2014 年,第 1685–1692 页,doi: 10.1109/CVPR.2014 “使用回归树集合的一毫秒人脸对齐”, 2014 年 IEEE 计算机视觉和模式识别会议,美国俄亥俄州哥伦布,2014 年,第 1867-1874 页,doi:10.1109/cvpr . 2014.241 .
[5]m . Kowalski,J. Naruniec 和 T. Trzcinski,“深度对齐网络:用于鲁棒人脸对齐的卷积神经网络”, 2017 年 “野外 300 人面临的挑战:数据库和结果”。图像和视觉计算(IMAVIS),面部标志定位“野外”特刊。2016.
【7】OpenMP 库:https://www.openmp.org/

更快的 Spark 查询,两者兼得:Python 和 Scala

原文:https://towardsdatascience.com/faster-spark-queries-with-the-best-of-both-worlds-python-and-scala-7cd0d49b7561?source=collection_archive---------34-----------------------

当 Spark SQL 和 Python UDFs 太慢时,如何使用 Scala 和 PySpark 实现高级 Spark 用例

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

Unsplash【CC0】拍摄的图像

S park 是大数据时代的黄金标准和主力。几乎所有数据科学家和数据工程师都依赖 Spark 来处理日常数据工作负载。但是这两个用户群之间有一个典型的分界线:

  • 许多数据工程师使用 Scala 和类型化数据集 API 编写 Spark 作业,而
  • 大多数数据科学家使用 PySpark 和无类型 Spark 数据帧。

Python 是迄今为止数据社区中最受欢迎的语言,Spark 自早期以来取得了长足的进步,统一数据集 API、Arrow、Spark SQL 和矢量化 Pandas UDFs 使 PySpark 用户在使用 Spark 时成为一等公民。

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

[OC]

您可能正在阅读这篇博文,因为您有一些高级用例,其中实现是 Scala,类型化数据集 API 将是有益的。

  • 共享代码库,例如,数据科学家想要重用来自数据工程管道的一些复杂的业务逻辑
  • 您需要实现复杂的业务逻辑,并希望使用 Scala 强大的集合和方法
  • 您希望使用复杂的自定义类型,因为您的数据不太适合表格数据模型
  • 你必须处理组合问题、嵌套循环和大数组,你的 Spark 工人会因为 OOM 错误而死

这只是我多年来在使用 Scala 和类型化数据集 API 时遇到的几个例子,至少是在 PySpark 管道的一部分中。好消息是,您不必用 Scala 培训所有的数据科学家,也不必重写他们所有的 PySpark 工作流。PySpark 只是一个 API,所有的 PySpark 工作流最终都在 JVM 上的 Spark 中运行。这使得我们可以在同一个 Spark 管道中轻松混合和匹配 Python 和 Scala。

下面的例子演示了如何使用一些业务逻辑为每个输入行创建大量的输出行。当然,您可以在 PySpark 中解决这个问题:

def getBigList() -> List[int]:
  return [random.randint(1, 999999) for x in range(10000)]bigListUdf = udf(
  getBigList, 
  ArrayType(IntegerType())
).asNondeterministic()spark.createDataFrame([
  Row(cid='cid1'),
  Row(cid='cid2'),
  Row(cid='cid3')
]).select(
  'cid', explode(bigListUdf()).alias('sku')
).join(
  productDf, ['sku']
)

但是传递一个大的列表并将其分解成大量的新行需要您的节点为这一阶段的这一步留有足够的内存余量。这是一个简单的例子,但是您甚至可能再次过滤掉许多新行,因为它们与您的整个管道不相关。在您的真实世界用例中,您甚至可能有列表列表等。我们如何通过使用类型化数据集来改进这一点呢?

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

[合理使用]

flatMap类型化数据集转换相当于 Dataframes 的explode()方法,重要的是可以使用**迭代器。**这消除了在内存中实现列表的需要。你可能还记得 Python 2 的【https://www.geeksforgeeks.org/range-vs-xrange-python/】,你可以阅读这篇关于生成器优势的文章:

数据工程师可能会将您的 PySpark 代码翻译成某种 Scala 版本,生成带有IteratorflatMap的新行

package business_logiccase class InputData(cid: String)
case class OutputData(cid: String, sku: String)object BusinessLogic {

  private def generateSkus(cid: String): Iterator[OutputData] = ??? def getCidSku(df: DataFrame): DataFrame = {
    import spark.implicits._
    val ds = df.as[InputData]
    ds
    .flatMap( x => generateSkus(x.cid) )
    .toDF
  }}

scala 代码被数据工程师编译打包成一个jar文件。

数据科学家只需将罐子添加到他们的 Spark 会话中

spark = (
  SparkSession.builder
  .config("spark.jars.packages", "business-logic_2.12-1.0.0.jar")
  .getOrCreate()
)

我们希望在使用非类型化数据帧的 PySpark 管道中使用类型化数据集来使用这部分业务逻辑。

from pyspark.sql import SparkSession, DataFramespark = SparkSession.builder.getOrCreate()
sc = spark._sc
sqlContext = spark._wrappedcid_df = spark.createDataFrame([
  Row(cid='cid1'),
  Row(cid='cid2'),
  Row(cid='cid3')
])cid_sku_df = DataFrame(
  sc._jvm.business_logic.BusinessLogic.getCidSku(cid_df._jdf),
  sqlContext
)cid_sku_df.join(
  productDf, ['sku']
)

这不是最令人难忘的语法,但这是您如何从 PySpark 调用任何 Java/Scala 代码来完成 Spark 工作负载,并打破使用 Spark 和 PySpark 的团队之间的语言障碍。

Spark 数据集的 Scala API 文档:https://Spark . Apache . org/Docs/latest/API/Scala/org/Apache/Spark/SQL/Dataset . html

为什么不阅读下一篇文章,了解如何使用 PEX 打包 PySpark 应用程序用于生产—相当于 Python 的 Spark 和 assembly JARs:

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

Jan 是公司数据转型方面的成功思想领袖和顾问,拥有将数据科学大规模应用于商业生产的记录。他最近被 dataIQ 评为英国 100 位最具影响力的数据和分析从业者之一。

在 LinkedIn 上连接:https://www.linkedin.com/in/janteichmann/

阅读其他文章:【https://medium.com/@jan.teichmann】T21

FasterAI:制作更小更快的神经网络的库

原文:https://towardsdatascience.com/fasterai-a-library-to-make-smaller-and-faster-neural-networks-70c3ff2e2ba3?source=collection_archive---------16-----------------------

理解大数据

FasterAI 包括一组用于神经网络的压缩技术,构建于 Fastai 和 Pytorch 之上

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

作者图片

FasterAI 简介

→图书馆可以在这里找到https://github.com/nathanhubens/fasterai

FasterAI 是一个项目,它通过使用 fastai 库来使神经网络变得更小更快。这里实现的技术可以很容易地与普通 Pytorch 一起使用,但是我们的想法是以一种抽象和易于使用的方式来表达它们( à la fastai)。

在本文中,我们将通过一个用例来解释如何使用 FasterAI。

准备好了吗?那我们开始吧!

为了演示的目的,让我们先了解一些背景知识。假设我们想要在存储容量有限的移动设备上部署一个 VGG16 模型,并且我们的任务要求我们的模型运行足够快。众所周知,参数和速度效率不是 VGG16 的强项,但让我们看看我们能做些什么。

我们先来检查一下 VGG16 的参数个数和推断时间。

*learn = Learner(dls, vgg16_bn(num_classes=10), metrics=accuracy)*

因此,VGG16 有 1.34 亿个参数

*Total parameters : 134,309,962*

并花费 4.03 ms 对单幅图像进行推断。

*4.03 ms ± 18.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)*

啪!这超出了我们的部署能力,理想情况下,我们希望我们的模型只需要一半的容量…但是我们应该放弃吗?不,实际上有很多技术可以帮助我们减小模型的尺寸并提高速度!让我们看看如何用 FasterAI 应用它们。

我们将首先训练我们的 VGG16 模型,以便对它的性能有一个基准。

*learn.fit_one_cycle(10, 1e-4)epoch | train_loss | valid_loss | accuracy | time
0     | 2.016354   | 1.778865   | 0.3689170| 1:31
1     | 1.777570   | 1.508860   | 0.5235670| 1:31 
2     | 1.436139   | 1.421571   | 0.5691720| 1:32
3     | 1.275864   | 1.118840   | 0.6300640| 1:31
4     | 1.136620   | 0.994999   | 0.6878980| 1:31
5     | 0.970474   | 0.824344   | 0.7396180| 1:31
6     | 0.878756   | 0.764273   | 0.7656050| 1:32
7     | 0.817084   | 0.710727   | 0.7819110| 1:31
8     | 0.716041   | 0.625853   | 0.8048410| 1:31
9     | 0.668815   | 0.605727   | 0.8109550| 1:31*

因此,我们希望我们的网络具有相当的精度,但参数更少,运行速度更快……我们将展示如何使用的第一项技术叫做知识蒸馏

知识蒸馏

知识提炼是一种简单但非常有效的训练模型的方法。卡鲁阿纳等人于 2006 年推出了这一技术。背后的主要思想是用一个小模型(称为学生)来近似一个更大的高性能模型(称为老师)所学的函数。这可以通过使用大模型来伪标记数据来实现。这个想法最近已经被用来打破 ImageNet 上最先进的精确度。

当我们训练模型进行分类时,我们通常使用 softmax 作为最后一层。这个 softmax 的特点是将低值逻辑值挤向 0,将最高值逻辑值挤向 1。这实际上完全丢失了所有的类间信息,或者有时被称为黑暗知识*。这是有价值的信息,我们希望从老师那里传递给学生。*

为此,我们仍然使用常规分类损失,但同时,我们将使用另一个损失,在老师的软化逻辑(我们的软标签*)和学生的软化逻辑(我们的软预测)之间计算。这些软值是在使用 soft-softmax 时获得的,这样可以避免在其输出端挤压这些值。我们的实施遵循本文,培训的基本原则如下图所示:*

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

作者图片

要在 FasterAI 中使用知识蒸馏,您只需在训练学生模型时使用此回调函数:

**KnowledgeDistillation(student, teacher)**

你只需要给回调函数你的学生学习者和你的教师学习者。在幕后,FasterAI 将使用知识精华来制作您的火车模型。

首先要做的是找到一个老师,可以是任何模型,最好表现良好。我们将选择 VGG19 进行演示。为了确保它比我们的 VGG16 模型性能更好,让我们从预训练版本开始。

*teacher = cnn_learner(dls, vgg19_bn, metrics=accuracy)
teacher.fit_one_cycle(3, 1e-4)epoch | train_loss | valid_loss | accuracy | time
0     | 0.249884   | 0.088749   | 0.9727390| 1:02
1     | 0.201829   | 0.087495   | 0.9742680| 1:02
2     | 0.261882   | 0.082631   | 0.9740130| 1:02*

我们的老师有 97.4%的准确率,这已经很不错了,它已经准备好保护学生了。因此,让我们创建我们的学生模型,并通过知识蒸馏回拨对其进行培训:

*student = Learner(dls, vgg16_bn(num_classes=10), metrics=accuracy)
student.fit_one_cycle(10, 1e-4, cbs=KnowledgeDistillation(student, teacher))epoch | train_loss | valid_loss | accuracy | time
0     | 2.323744   | 2.102873   | 0.4109550| 2:16
1     | 2.099557   | 2.441147   | 0.5714650| 2:16 
2     | 1.829197   | 2.215419   | 0.6076430| 2:16
3     | 1.617705   | 1.683477   | 0.6670060| 2:16
4     | 1.364808   | 1.366435   | 0.7133760| 2:16
5     | 1.257906   | 0.985063   | 0.7880250| 2:16
6     | 1.087404   | 0.877424   | 0.8010190| 2:16
7     | 0.949960   | 0.777630   | 0.8221660| 2:16
8     | 0.868683   | 0.733206   | 0.8377070| 2:16
9     | 0.756630   | 0.707806   | 0.8430570| 2:16*

我们可以看到,老师的知识确实对学生有用,因为它明显超出了基线 VGG16。

好了,现在我们能够从一个给定的模型中得到更多,这有点酷!通过一些实验,我们可以设计出比 VGG16 更小的模型,但能够达到与我们的基线相同的性能!您可以稍后尝试自己找到它,但现在让我们继续下一项技术!

稀疏化

现在我们有了一个比基线表现更好的学生模型,我们有一些空间来压缩它。我们将从稀疏网络开始。

:通常情况下,使网络稀疏的过程称为剪枝。当参数实际上从网络中移除时,我们更喜欢使用术语修剪,这将在下一节中进行。

在 FasterAI 中,稀疏化过程也是通过使用回调来管理的,回调将在训练期间用零替换模型中最不重要的参数。回调函数有各种各样的参数来调整您的稀疏化操作,让我们来看看它们:

**SparsifyCallback(sparsity, granularity, method, criteria, sched_func)**
  • 稀疏度:你想要的网络稀疏度的百分比
  • 粒度:你希望在什么粒度上进行稀疏化操作(weightkernelfilter、…)
  • 方法:无论是local还是global,都会影响参数的选择,是在每一层单独选择(local)还是在整个网络上选择(global)。
  • 标准:用于选择移除哪些参数的标准(large_finalmovement、…)
  • sched_func :你希望按照哪个调度进行稀疏化(目前支持:fastai的任意调度函数,即annealing_linearannealing_cos,…而且还有经典的时间表如one_shotiterativeannealing_gradual、朱古普塔&提出的时间表

但是让我们回到我们的例子上来!

这里,我们将使我们的网络 40%稀疏,并删除整个过滤器,本地选择并基于 L1 规范。我们将以稍小的学习率进行训练,以温和地对待我们的网络,因为它已经被训练过了。所选择的调度是一个退火余弦,所以修剪开始和结束都很温和。

*student.fit(10, 1e-5, callbacks=[SparsifyCallback(40, granularity='filter', method='local', criteria=large_final, sched_func=annealing_cos)])Pruning of filter until a sparsity of 40%epoch | train_loss | valid_loss | accuracy | time
0     | 0.584072   | 0.532074   | 0.8384710| 1:31
1     | 0.583805   | 0.499353   | 0.8445860| 1:31 
2     | 0.599410   | 0.527805   | 0.8364330| 1:32
3     | 0.610081   | 0.544566   | 0.8280250| 1:31
4     | 0.625637   | 0.543279   | 0.8298090| 1:31
5     | 0.628777   | 0.563051   | 0.8196180| 1:31
6     | 0.688617   | 0.617627   | 0.8000000| 1:32
7     | 0.691044   | 0.629927   | 0.8010190| 1:31
8     | 0.669935   | 0.576220   | 0.8140130| 1:31
9     | 0.682428   | 0.562718   | 0.8239490| 1:31Sparsity at epoch 0: 0.98%
Sparsity at epoch 1: 3.83%
Sparsity at epoch 2: 8.25%
Sparsity at epoch 3: 13.83%
Sparsity at epoch 4: 20.01%
Sparsity at epoch 5: 26.19%
Sparsity at epoch 6: 31.76%
Sparsity at epoch 7: 36.19%
Sparsity at epoch 8: 39.02%
Sparsity at epoch 9: 40.00%
Final Sparsity: 40.00*

我们的网络现在有 40%的滤波器完全由零组成,代价是 2%的精度。显然,选择较高的稀疏度会使网络更难保持类似的精度。其他参数也可以广泛地改变我们的稀疏化过程的行为。例如,选择更细粒度的稀疏性通常会导致更好的结果,但在速度方面更难利用。

我们可以仔细检查我们的模型确实被修剪了 40%的参数。

*Sparsity in Conv2d 2: 39.06%
Sparsity in Conv2d 5: 39.06%
Sparsity in Conv2d 9: 39.84%
Sparsity in Conv2d 12: 39.84%
Sparsity in Conv2d 16: 39.84%
Sparsity in Conv2d 19: 39.84%
Sparsity in Conv2d 22: 39.84%
Sparsity in Conv2d 26: 39.84%
Sparsity in Conv2d 29: 39.84%
Sparsity in Conv2d 32: 39.84%
Sparsity in Conv2d 36: 39.84%
Sparsity in Conv2d 39: 39.84%
Sparsity in Conv2d 42: 39.84%*

我们没有确切的 40%,因为当我们去掉完整的过滤器时,我们不一定有一个整数。

现在让我们看看我们在速度方面获得了多少。因为我们删除了 40%的卷积滤波器,我们应该期待疯狂的加速,对不对?

*4.02 ms ± 5.77 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)*

实际上,没有。我们没有删除任何参数,我们只是用零代替了一些,记得吗?参数的数量仍然相同:

*Total parameters : 134,309,962*

这将引导我们进入下一部分。

修剪

重要提示:这目前仅支持全前馈模型,如 VGG 模型,因为更复杂的架构需要越来越困难且通常依赖于模型的实现。

*为什么我们没有看到任何加速度,即使我们去掉了一半的参数?这是因为我们的 GPU 本身不知道我们的矩阵是稀疏的,因此无法加速计算。最简单的办法,就是用物理地移除我们归零的参数。但是这种操作需要改变网络的架构。当移除层 *i+1,*中的过滤器时,它也影响层 *i+2,中的内核,因为它们现在变得无用并且可以被移除。

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

作者图片

这种修剪只有在我们事先将整个滤波器归零的情况下才有效,因为这是唯一可以相应地改变架构的情况。希望稀疏计算很快能在普通深度学习图书馆中可用,所以这一部分在未来将变得无用,但目前,这是我们能想到的最好的解决方案🤷

这是 fasterai 的样子:

*pruner = Pruner()
pruned_model = pruner.prune_model(learn.model)*

您只需传递其过滤器已被稀疏化的模型,FasterAI 将负责移除它们。

注意 :该操作应该是无损的,因为它只移除已经不再参与网络的过滤器。

在我们的例子中,它给出了:

*pruner = Pruner()
pruned_model = pruner.prune_model(student.model)*

现在,让我们看看我们的模型能够做些什么:

*Total parameters : 83,975,344*

就速度而言:

*2.44 ms ± 3.51 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)*

耶!现在我们可以说话了!让我们再次检查我们的准确性没有改变,我们没有在某个地方出错:

*Loss: 0.5641388, Accuracy: 0.8229*

实际上我们还能做更多的事情!让我们继续前进!

批量标准化折叠

批量规范化折叠是一个非常容易实现和简单的想法。要点是批量标准化只不过是对每一层的输入数据进行标准化。此外,在推断时,用于这种标准化的批次统计是固定的。因此,我们可以通过改变卷积的权重将归一化过程直接合并到卷积中,并完全移除批量归一化层,这在参数和计算方面都是一个增益。更深入的解释,请看我的上一篇帖子。

这是如何与 FasterAI 一起使用:

*bn_folder = BN_Folder() 
bn_folder.fold(learn.model))*

注意 :该操作也应该是无损的,因为它重新定义了卷积以考虑批量范数,因此是等价的。

让我们用我们的模型来做吧!

*folded_model = bn_folder.fold(pruned_learner.model)*

参数下降通常不太明显,尤其是在 VGG 这样的网络中,几乎所有参数都包含在 FC 层中,但是,任何增益都是值得的。

*Total parameters : 83,970,260*

既然我们删除了批处理规范化层,我们应该再次看到加速。

*2.27 ms ± 1.22 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)*

再一次,让我们仔细检查我们没有在某个地方搞砸:

*Loss: 0.5641388, Accuracy: 0.8229*

我们还没完成呢!正如我们所知,对于 VGG16,大部分参数都包含在全连接层中,因此我们应该对此有所作为,对吗?

FC 层因子分解

事实上,我们可以分解我们的大的全连接层,并用两个更小的近似层来代替它们。其思路是对权重矩阵进行 SVD 分解,将原矩阵表示为 3 个矩阵的乘积:uσVT。其中σ是沿其对角线具有非负值的对角矩阵(奇异值)。然后,我们定义奇异值的值 k 来保持和修改矩阵 UVT 。结果将是初始矩阵的近似值。

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

作者图片

在 FasterAI 中,要分解模型的全连接层,您需要执行以下操作:

*FCD = FCDecomposer() 
decomposed_model = FCD.decompose(model, percent_removed)*

*percent_removed*对应去除奇异值的百分比( k 值)。

:这次分解不确切,所以我们预计之后业绩会下降,需要进一步的再培训。

在我们的示例中,如果我们只想保留其中的一半:

**fc_dec = FCDecomposer()
dec_model = fc_dec.decompose(folded_model, percent_removed=0.5)**

我们现在有多少参数?

**Total parameters : 61,430,022**

我们赢得了多少时间?

**2.11 ms ± 462 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)**

然而,这种技术是近似的,所以它不是无损的,所以我们应该重新训练我们的网络来恢复它的性能。

**final_learner = Learner(data, dec_model, metrics=[accuracy])
final_learner.fit_one_cycle(5, 1e-5)epoch | train_loss | valid_loss | accuracy | time
0     | 0.795416   | 0.759886   | 0.7729940| 0:51
1     | 0.752566   | 0.701141   | 0.7943950| 0:51 
2     | 0.700373   | 0.650178   | 0.8048410| 0:52
3     | 0.604264   | 0.606801   | 0.8216560| 0:51
4     | 0.545705   | 0.592318   | 0.8231850| 0:51**

这种操作通常对较新的架构用处不大,因为它们的全连接层中通常没有那么多参数。

概括地说,我们在本文中看到了如何使用 FasterAI 来:

  1. 让学生模型向教师模型学习(知识蒸馏)
  2. 使我们的网络稀疏化(稀疏化)
  3. 可选地,物理移除零滤波器(修剪)
  4. 移除批量定额层(批量规格化折叠)
  5. 用较小的层来近似我们的大的全连接层(全连接层因式分解)

我们看到,通过应用这些,我们可以将 VGG16 模型的参数从 134 百万减少到 61 百万,并且还可以将推断从 4.03 毫秒加速到 2.11 毫秒,与基线相比,准确性没有任何下降(甚至实际上略有增加)。

当然,这些技术可以与量化混合精度训练结合使用,Pytorch 中已经提供了这些技术,可以进行更多的压缩和加速。

注意 :请记住,上面介绍的技术不是神奇的🧙‍♂️,所以不要期望每次都能看到 200%的加速和压缩。您能实现什么在很大程度上取决于您正在使用的架构(有些已经通过设计实现了速度/参数效率)或它正在执行的任务(有些数据集非常简单,您可以删除几乎所有网络而不会看到性能下降)

仅此而已!感谢您的阅读,我希望您会喜欢 FasterAI。我不认为它是完美的,你可能会发现很多错误。如果你有,请告诉我,我可以试着解决它们😌

计算出版物 h 指数的最快方法

原文:https://towardsdatascience.com/fastest-way-to-calculate-h-index-of-publications-6fd52e381fee?source=collection_archive---------21-----------------------

一个简单而优雅的算法胜过许多导出 h-index 的普通方法

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

摄影: Jonathan ChngUnsplash

最初由 J.E .赫希提出,作者的 h 指数被认为是他们学术成就的可靠指标。在一个普通的学术术语中,h-index 指的是最高的数字“h ”,这样作者就有 h 篇论文被至少 h 次引用。媒体社区的成员可以这样解释:这是一个最大的数字“h ”,一个作者写了至少 h 篇博客,收到了至少 h 个掌声。

让我们用一个例子来理解这个概念。一个作者发表了五篇博客(或研究文章),收到了以下掌声(引用):【10,1,5,3,15】。h 指数是 3,因为至少有三个博客至少有 3 次鼓掌。另一位作家可能收到了[100,2,1,1,1]个掌声,h 指数只有 2。虽然它不是衡量一个人写作和学术能力的完美标准,但据称它在大多数情况下都能很好地反映一个作者的整体写作质量。

h 指数的假设应用

假设有许多多产的作家,他们每个人都发表了数百篇关于 Medium.com 的各种主题的博客文章,包括其所有的姐妹出版物。自然,对于每个作家来说,有些文章比其他文章更受欢迎(以获得的掌声来衡量)。现在,编辑希望根据他们的 h 指数来衡量他们的表现,并相应地奖励最具生产力和质量的作家——作家的 h 指数值越高,奖励越大。

现在,编辑要求我们编写最快的程序来计算 h 指数。在集思广益会议和快速互联网搜索后,我们确定了四种不同的方法来得出 h 指数,如下所述:

  1. For-loop(我们的想法)
  2. 数字广播(我们的想法)
  3. Python 包(别人的想法)
  4. 好的算法(别人的想法)

接下来的部分将更详细地解释这四种方法,并计算它们在我们的测试用例中的性能。

For 循环

在许多情况下,涉及一个或多个 for 循环的计算在计算上是低效的,然而它们仍然是最直观和最容易的做事方式。在理解 for 循环计算之前,让我们引入一个新的术语 k-index,它指的是任何 k,使得 k 篇文章有 k 次引用。k 的最大值是 h-index,这意味着一个作者可以有多个 k-index,但只有一个 h-index。h-index 的默认值为零,并且不能大于文章数。

基于 for 循环的 h 索引代码如下所示。for 循环技术通过在一个范围内从 1 到文章总数依次迭代来寻找所有可能的 k 索引。k 的最高值被认为是给定引用数组的 h 指数。

在代码中,我已经确保通过“中断”两个循环,只执行必要的计算。在第一个循环中,一旦发现 h 篇文章有 h 个引用,循环就停止迭代其余的值。第二个循环只持续到下一个 h 小于前一个值的点,这表明我们找到了最大 h。

注意:我尝试了非优化(无中断)的循环,效率极低,所以我将其从结果中排除。

数组运算

意识到 for 循环固有的缓慢,我们决定执行数组操作。我们可以用 Numpy 广播操作替换内部和外部 for 循环以及相关的 if 语句。数组允许我们同时确定所有的 k,而不是逐个计算 k 指数。下面分享代码块。

Scholarmetrics 软件包

我们已经在网上搜索了是否存在计算 h 指数的标准 Python 包,正如我们所知,总是有 Python 库可用。Michael Rose 写的【Scholarmetrics 软件包及其代码分享如下。请注意,稍微修改过的代码版本(方法 2)使用了 Numpy sum,而不是 Python 的内置 sum 函数。

资料来源:基于迈克尔·E·罗斯编写的学校计量学软件包 GitHub 代码

专家算法

我们还在其他地方寻找,发现一些专家已经提出了一个简单的算法来推导 h 指数。该算法按逆序(降序)对引文进行排序,并按升序将其与相应的整数序列进行比较。两条曲线交点处的整数值就是我们的答案,编码如下:

确认

在我们比较这四种解决方案之前,我们需要确保它们能产生相同的结果。因此,我们可以随机生成一个样本并验证这三种方法:

上面的代码产生以下结果。所有技术都给出相同的输出,我们知道这是正确的,这验证了我们的代码。因此,我们现在可以继续进行比较测试了。

比较

所有实验运行重复三次,每次重复运行 100 次,并以秒为单位记录时间。正如 Python 文档推荐的那样,我们只使用了最短的运行时间。结果如下所示:

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

作者图片

正如所料,专家算法表现出最佳性能,其次是 Python 包代码。有趣的是,我们在 Scholarmetrics 包中使用 np.sum()而不是 sum()提高了速度,表现几乎与最佳技术相同。

令人惊讶的是,随着大小的增加,for-loop 比数组操作做得更好。这是因为即使我们消除了 for 循环,我们还是进行了计算。没有 if 语句来减少冗余步骤,代码必须处理整个输入数组。

最后的想法

在这篇博客中,我们研究了计算 h 指数的不同方法的计算效率。有三点要记住。首先,高效的算法是无可替代的。其次,精心编写的 for 循环也能以可接受的速度执行。第三,在 Numpy 数组上使用 Numpy 函数比使用内置 Python 函数更快。

全周期数据科学(FCDS)

原文:https://towardsdatascience.com/fcds-b2d2e6b08d34?source=collection_archive---------9-----------------------

行业笔记

扩展数据驱动型组织的关键

在当今世界,没有数据的行动仅仅是一种观点,一个运行良好的数据科学部门不仅仅是“有就好”,而是业务繁荣的一个强烈要求。
然而,如何让一个数据科学部门取得成功并没有单一的秘诀。
虽然许多不同的公式可能适用于小型/直觉驱动/发展中的组织,但随着组织的成长和成熟,真正的问题(以及对解决方案的需求)开始显现。
如今,找到一个可扩展的解决方案是几乎所有值得尊敬的科技公司都面临的难题。
鉴于这一组织问题的本质以及某种程度上的哲学问题,我鼓励读者在他们的组织和需求发生变化时,重新审视这一问题及其首选解决方案。

在我的职业生涯中,我遇到过很多解决数据驱动的规模问题的方法。见鬼,我亲自尝试了至少一半…我很高兴地宣布,我确实找到了一个我爱上了的食谱,我觉得它足够有效,值得分享。我写这篇文章是想告诉你关于它的事情,我的经历,为什么我认为它很棒,以及给那些想在他们的组织中认真评估/实施它的读者一些建议。
为了使这个配方可重复,它需要被很好地记录和命名(这篇文章和所说的)。

为了描述它,我创造了一个术语全周期数据科学 (FCDS),我认为这是对它所包含的内容的恰当描述(下文将详细介绍)。

简而言之,FCDS 是一种生活方式,使单个数据从业者能够结束整个产品生命周期,独立交付端到端产品,只关注它们带来附加值的地方。

达成这个解决方案,包括实现它的理念和技术,是许多同事@Waze & @Google 的团队努力。我很幸运能和这些专业的、以成功为导向的人一起工作,这促进了实验,直到找到这个解决方案。

在本文中,我将宣称这不仅仅是扩展数据驱动型业务的一种功能性方法,而且是迄今为止最有效的方法。

这篇文章代表我自己(丹尼尔·马科斯)的个人信念,与某个特定的组织无关。因此,它非常固执己见。我对自己热衷的事情非常有主见,这是其中之一:)

希望这个食谱和它的想法能引起一些读者的共鸣。如果你最终采纳了其中的一些,那么绝对值得花时间写下来!请不要客气,这样我们就可以交流从难以捉摸的道路到规模的战斗故事。

问题是

定义成功

我是一名数据科学家。作为其中一员,我无法在没有明确定义 KPI 的情况下解决问题。我在这里要展示的东西是否真的可以测量还有待商榷,但我会尽力而为。

那么,我们实际上如何定义一个成功的数据科学单位呢?为了想出一个扩展的方法,我们首先需要定义成功是什么样子。

领导期望通常有些模糊(非常令人惊讶……),但听起来常常像这样—

一个成功的数据[科学]部门应该为决策提供信息,并转变我们经营业务的方式。

这些可以是微观的(例如交易层面)或宏观的(例如我们应该把增长集中在哪里?)级别的决策,这里唯一重要的是它们是数据驱动的,或者像有些人喜欢说的那样是“智能的”。

让我们试着将它分解成业务 KPI(或者对我们的数据组织来说是 OKR )。
一个成功且可扩展的数据科学部门应该针对以下方面进行优化:

  • 业务影响 —我们生产的工件(无论是模型、分析、洞察力、报告、仪表板、演示)转化为影响我们业务的可衡量的结果。
    这些结果可以表现为战略和决策制定指导(通常称为“数据科学洞察”),也可以表现为直接优化 KPI,如给定改进模型的收入(例如欺诈检测、CTR 预测)。
  • 速度 —洞察时间(无论是决策、新业务洞察还是生产就绪型 ML 模型)应尽可能缩短。这里没有经验法则,这在很大程度上取决于项目的性质,但底线是——不要因为效率低下而行动迟缓,从而阻碍产品的决策。
  • 质量——通知和指导决策是一项重大责任。基于仔细审查的干净数据的准确、可理解的见解对于质量决策至关重要。没有比产生见解、让企业根据这些见解采取行动、然后才意识到自己的见解是错误的更好的摧毁数据单位可信度的方法了。有点常识的读者会理直气壮地认为“这是不可避免的”。的确如此,尽管这里的目标是尽量减少这种情况。
    你可能已经明白质量&速度是你需要管理的一个权衡。既然你意识到了这一点,你就可以和你的利益相关者讨论这些选项,并做出明智的决定,在这两者之间划一条线(每个项目/产品都不一样)。
    衡量这一属性是很棘手的,通常是定量(例如,未解决问题的数量,给定时间范围内产品迭代的数量)和定性(例如,利益相关者调查)的结合
  • 可持续发展 —一个成熟的数据驱动型组织会重新评估其成长过程中做出的决策。因此,考虑到新的数据、更新的假设,并且尽可能与之前的决策点相比较,重新考虑这些决策是至关重要的。为了允许这样的工作方式,代码(产生洞察/训练 ML 模型)必须是完全可复制的、自动化的(点击一个按钮就可以重新运行),并且写得很好。可持续产品通常有工件,比如详细的文档,足以让新员工(甚至未来的你)回去,理解它,信任它,调整它,并产生新的结果。

值得注意的是,KPI 的这种构成非常适合数据驱动的业务(“行业”)。对于纯研究和学术数据科学工作来说,情况肯定不是这样(例如,速度-质量权衡优先于质量)。许多成熟的数据组织确实雇用了研究科学家,他们不太受业务驱动,但他们的研究确实与业务目标一致,并最终会对生产产生影响。这些研究人员可能在同一个数据科学部门工作,也可能在不同的部门工作,尽管企业的高层次目标总是优秀的产品、增长和利润。这些目标推动了上述数据科学部门的成功定义。

数据科学生命周期

为了讨论解决方案,我们首先需要稍微了解一下数据科学项目的生命周期。
生命周期是指管理数据科学项目需要采取的步骤及其顺序。
这通常是指主要的项目阶段,如启动/定义、开发/原型、部署&实验和测量。
它有很多种风格,使用不同的命名、序列、ML 规范等等。
在这里讨论一个具体的生命周期是没有意义的,因此我们将只提及一些高级生命周期的重要注意事项:

  • 循环 —数据科学的生命周期总是循环的。当处理数据、创建见解/模型,并与利益相关者/实验验证它们时,随着您对数据越来越熟悉,您往往会发现新的问题。这些可能需要更多的数据清理,重复假设、目标、度量等的定义。因此,这个生命周期被视为循环的,您可以随时返回到上一步,从该点继续循环
  • 研究 VS 生产 —这个周期通常包括两者。您首先从了解领域开始,尝试不同的方法和原型。有时你甚至不知道在这个阶段你正在尝试做的事情是否可行。当你有一个满意的工件时,你将尝试并“生产化”它——调整并使它可用于你组织的生产基础设施,关注部署、资源、规模、延迟、成本、监控、协调等。
    周期中的这两个不同步骤彼此非常不同,在传统组织中需要不同的职能(例如科学家与工程师)和实施。这是我们在这里试图解决的问题的很大一部分。
  • 操作 —周期的最后一步,此时您已经有了生产部署的实施,例如生产 ML 模型/实时仪表板/发送给管理层的报告。在这一点上,您需要确保您的工作持续运行——进行测量、监控,并在出现问题时发出警报(例如,数据偏差、概念漂移、异常、性能不佳等)。).忽略这一部分实际上会让你的工作变成“一次性的”。虽然对某些项目有好处,但在生产中/决策中使用一些您无法重现和/或调整和修复的东西是非常危险的,以防以后发现问题(在您的工作中或甚至在您所依赖的数据中,因为显然您很棒,您不会犯错误)。

我个人在某种程度上与这种(面向 ML 的)数据科学生命周期有关。它描述了原型制作本身就是一个循环,我发现这非常正确。

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

数据科学产品生命周期(图片作者:丹尼尔·马科斯

数据科学挑战

上面提到的多功能循环很难产生有效的、有组织规模的数据工作。
谷歌的论文——机器学习系统中隐藏的技术债务(NIPS 2015)中提出了对这一挑战的补充观点。
用一张图来概括——

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

机器学习系统中隐藏的技术债务— NIPS 2015 ( 作者图片,丹尼尔·马科斯)

现在来解释一下这幅图:)
这意味着当数据科学家(在这种情况下实施 ML 模型——红框,但让我们稍微概括一下)进行研究时,她只关注产生洞察力的核心——例如模型训练/ KPI 测量(有趣的部分!).问题是,当她想要生产那段代码时,有许多其他“隐藏”的盒子,她现在必须实现并注意将它集成到生产就绪系统中。

TL;DR — 让数据科学家不把大部分时间花在他们带来附加值的地方,是扩展数据驱动型组织的最大敌人

这样做的挑战在于:

  • 速度退化——最佳状态意味着她的研究代码是“立即产生可电离的”,所有其他部分(灰色方框)都是现成的(没有方框双关语)。不幸的是,这种情况并不常见。
    • 数据科学家的时间 —上述许多挑战让我们意识到,实际上,一名现实生活中的数据科学家并没有把大部分时间花在她能带来附加值的地方。相反,她经常被拉去做运营和“生产调整”(例如扩展)工作,受到移交的阻碍,最终成为一个效率较低的自己。让数据科学家不把大部分时间花在他们带来附加值的地方,是扩展数据驱动型组织的最大敌人
  • 质量因缺乏重点和极度复杂而受损。
    *技能集 —传统的数据科学技能集不包括扩展(软件工程)、自动化和监控(软件可靠性工程师/“devo PS”),有时甚至不包括数据收集(卸载给其他工程师——有史以来最严重的错误……我们稍后会谈到这一点)。
    一个极端的情况是,数据科学家的研究代码实际上必须由 SWE(软件工程师)在不同的语言/技术堆栈中实现,以便与生产堆栈一起工作。除了速度,它在很多方面都是危险的!试探法,不同的包做不同的事情,训练服务偏差,等等。
  • 可持续发展很难实现,传统上也不被视为一个重要因素。这反过来又通过跳过“非数据”部分,如自动化、再现性、监控、完整文档等,推动了缩短项目时间的愿望。
    *维护 —可扩展的数据驱动型产品是为长期发展而构建的,而不是一次性的。这意味着在你“完成”一个项目后,所有这些可怕的灰色方框不会停止向你袭来。记得 cyclic 吗?当警报触发、模型性能下降、数据更改或技术堆栈升级时,数据科学家被召回维护岗位。灰色方框越多,预计维护就越多。
  • 业务影响 —获得可行见解(=生产)的时间大大高于进行纯研究的时间。在成熟的组织中,这可能意味着需要不成比例的大量劳动力来支持数据驱动的产品。然而,对于一般的组织来说,基于数据驱动(主要是 ML)的产品通常会失败,花费的时间比预期的要长,或者产生“半生不熟”/“某种智能”的结果。
    *移交——几乎是生产力的对立面。不要误解我的意思,我并不是说我或者任何其他人应该承担一切,在没有同事的情况下工作。我想说的是,个人贡献者拥有的越多,生产力就提高得越多,其中最佳的解决方案是拥有整个产品生命周期。将研究工作移交给 SWEs,将自动化工作移交给 SREs,将监控工作移交给 Ops 是对速度和质量的重大打击。
    *所有权 —当很多人参与到一个项目的不同阶段时,一种非常微妙的所有权平衡就出现了。我的部分在哪里结束,你的部分在哪里开始?谁拥有整个过程?最终产品?藏物呢。正在做的决定?警报?当数据或假设改变时,再现性和更新?

所有上述问题都受到组织结构(康威定律)等)的显著影响。)但我不打算在本文中深入探讨这一点(我也不打算声称我已经搞清楚了这一部分)。

解决方案

现在,如果我告诉你所有这些挑战都是可以解决的,会怎么样?(或者至少是可优化的)。我在这里提倡的全周期数据科学生活方式就是建议的解决方案。我有意把它称为一种生活方式,因为它由哲学、文化和技术组成。

你为什么要相信我?(你不应该,不要盲目相信你看的任何东西,而是想一想,觉得有意思就试试)。
它经过了战斗的考验。目前为止。)对我和我的同事有效。
这种方法实际上对数据科学家来说很有吸引力,所以说服人们尝试它并不困难——我基本上是在向你承诺更少的繁重工作和更多有趣的东西。
它是通过实验设计出来的。我(个人)犯了书中几乎所有的错误。这些错误确实有助于找出问题并试图提出解决方案。
这些错误表现为:

  • 从未进入生产的数据科学/ ML 项目
  • 数据科学/ ML 项目在进入生产阶段时遭遇了可怕的失败
  • 无效(至少可以这么说)DS:SWE 协作和移交
  • 需要为生产“重新编码”——例如,将 python ML 代码翻译成 Java,因为这是后端团队使用的代码。
  • 不成比例的维护负荷

如果你认识到以上的一些(或全部),也许这将会引起你的共鸣。

全周期工程是指一个工程师拥有整个产品生命周期

虽然这个概念对于阅读本文的数据人员来说可能是新的,但听众中的工程师可能已经熟悉了全周期开发人员的概念。这是一个很有趣的想法。
借用数据科学领域的信息技术,创建我们所谓的全周期数据科学 (FCDS)是我们扩展数据科学组织的解决方案。

高效的数据科学家

我们已经定义了成功并认识到挑战。下一步是在我们想要设置的解决方案(FCDS)的背景下,创建我们的高效数据科学家档案。
大概是这样的:

  • 专注于你最擅长的事情 —在一个包含多个职能部门(如工程师、科学家、分析师)的大型组织中,当人们将时间集中在能带来最大附加值的地方时,效率会最大化。在软件领域,这意味着关注业务逻辑,而不是样板文件和操作。对于数据科学家来说,“逻辑”部分主要是特征工程和数据操作。利用自己的创造力和领域知识获得正确的数据,思考对要解决的问题有最大影响的特性,并确保它们(或创造性的代理)可供使用。此外,重要的是提出正确的指标、优化方法和实验设计来衡量它们。任何 DS 都会同意,关注数据(质量和丰富性)和度量(例如,优化正确的度量)虽然不那么迷人,但对成功来说比模型本身重要得多。运营不应该是数据科学家的重点,也不应该占用他们大量的时间(请参见下面的“不运营”部分)。
    公平地说,通过调用. fit / .transform 来“训练”模型,甚至使用一个花哨的包来进行 hp 调整,都是非常机械的,与一个刚毕业的学生相比,你并没有增加多少价值。这些是最容易被 AutoML 取代 DS 工作(我是一个大粉丝)的部分,也是最容易根据帕累托原则减少你的努力的部分。在大多数商业(利润驱动)组织中,几乎总是帕累托规则适用的情况,并且 80%的预期交付物和 20%的花费时间足够好,能够做出决策,快速试验并继续下一个项目。这一事实在当今超级数据驱动的世界中更加明显,在这个世界中,数据科学几乎驱动着每一个决策——积压的项目如此之多,以至于很少值得为一个单独的项目超过 80%。
  • 独立性 —在一个完美的世界里,单个 DS 个人贡献者(IC)可以独立完成完整的数据科学产品生命周期(参见该名称的来源?).同一 IC 开发并拥有从研究到生产级服务的所有步骤。不仅如此,同样的 IC 只需要关注逻辑而不是 ops!听起来很理想,但很疯狂,对吗?实际上,2021 年并没有那么疯狂。我想提醒的是,产品生命周期并没有在生产中结束,它包括操作、持续监控和验证、定期再培训/重新验证假设等等。你仍然应该拥有所有这些,关键是使它们足够简单,以适应一个标准的 DS 的技能集,并且在努力方面几乎是免费的。
  • 不行动:我们说过 DS 不应该碰行动,但是必须有人碰。对吗?监控、编排、部署、扩展、延迟和数据质量管理对于一个健壮的生产系统来说都是至关重要的。然而,对于绝大多数数据科学产品来说,它们看起来非常相似。如今,模型性能监视器、持续培训编排、持续模型部署和数据验证框架都很容易集成(并且几乎是“可复制粘贴的”)。这意味着为您的产品设置它们应该是一个简单的配置问题,或者最好的情况是复制/继承一个现有的配置。这将使一切“免费”设置,但维护呢?这部分等式的关键是连续。持续的培训、数据验证、部署(模型&数据——又名特性存储)对于确保系统健康至关重要。一个持续健康的系统和使用连续操作(CI/CD/CT)快速检测问题是一个成熟的数据系统消除维护负载的方式

回顾我们使用数据实现业务转型的目标,全周期数据科学理念表明,这可以通过授权、独立、专注的数据科学家来实现。

全周期数据科学

哲学

E
数据科学家通常从定义/界定问题开始,考虑正确的测量和优化功能。这需要很强的业务理解、领域知识和沟通技巧。然后,她开始研究、查阅文献、实验,并尝试不同的方法。这需要以研究为导向的心态、创造力、有条理的方式和扎实的黑客技术(一点点运气不会有坏处)。
开发/生产化包括编码、测试、与生产系统的集成以及对资源的关注。这需要编码技能(显然,其他的也是,但是我们在这里谈论的是产品级)、强大的数据操作和理解以及架构/设计经验。
最后是衡量和运营,需要深入研究、解释和向利益相关者提供服务的能力。
你可以看到拥有完整的周期需要拥有广泛技能的全面数据科学家

大多数数据从业者都知道,清理数据是 80%的工作。这是周期中非常重要的一部分,如果不是最重要的话,在我们的理念中,这一部分应该永远由数据科学家完全拥有。我怎么强调这有多重要都不为过。
不管你喜欢与否,清理数据是你带来最大附加值的地方。凭借您的领域知识、创造力和商业敏锐度,这对于高性能模型和准确的洞察力来说是最重要的。
作为一名数据科学家,这无疑是你工作时间最长、最重要的一部分。

不,你肯定不太会清理自己的数据

你是说有一个人比你更合适,就是那个建立模型并负责其性能的人,来决定哪些数据适合过滤/清理以及如何过滤/清理?如果是这样,你可以就此打住,和质量说再见。

值得一提的是,为了让您能够独立地结束循环,不得存在任何类型的重新实现—例如,由 SWE 为生产重新实现的 DS 研究代码。它不仅容易出错,是不好的做法,还增加了依赖性。这意味着你需要从一开始就使用正确的工具。这并不难,只是意味着要留意你使用的技术。如果你不能生产它,它就没用了。

C
它不仅减少了移交,还为数据科学家开启了一个全新的业务影响世界。此外,我发现对于我的同事来说,产品所有权意识是必不可少的。当你按下部署按钮,看到流量增加到你的模型,你会尽一切努力来确保它的质量和健壮性。

在大多数组织中,将代码推向生产是 SWE 的任务,如果你做错了,你可能会造成伤害。此外,它可能需要各种各样的软件/SRE 技术,如 CI/CD,而数据科学家对此一无所知。认为这真的会让你失败。使用正确的工具、托管服务、测试和标准程序来推送代码,可以让一个 5 岁的孩子将代码推向生产,而造成(严重)伤害的风险极小。
生产问题呢?作为一名数据科学家,我现在需要支持调用我的模型的生产服务吗?我需要带着呼机(不是真的)在午夜回复生产问题吗?
是的,你有。
你拥有产品。(不是实际的服务器/网络,只是输出预测的服务)。你是支持它的最佳人选。当你的模型开始输出垃圾时,你是唯一一个知道如何修复它的人(这是会发生的)。
老实说,人们倾向于认为这很可怕,但如果你做得对(像其他事情一样),这很容易。也不一定总是你…这就是为什么随叫随到轮换是一件事。

用一张图来总结哲学(来源):

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

FCDS 哲学(作者图片,丹尼尔·马科斯)

当前的行业标准要求 X (~3)人将数据产品(例如 ML 模型)投入生产。
FCDS 承诺让一名独立的(全周期)数据科学家独自完成这项工作,更快、更高质量地专注于他们带来附加值的领域。 还有,你看业界 DS 被气的对不对?这是因为他将大部分时间花在了更接近运营的事情上(如扩展和监控),而不是调用 fit_transform(这是他真正喜欢做的事情)。

如果我在这一点上说服了你,但你在想“这在理论上很酷,但没有任何工具可以做到这一点,我不是谷歌/脸书,所以我不能只是去建立一些东西……”那么我有一个惊喜给你。

我们有技术。

技术

我们希望这项技术能够让普通的数据科学家结束产品周期,专注于逻辑,并让其他一切开箱即用。
这种技术的特点是:

  • 简单——理解、使用、操作
  • 托管 —没有服务器,没有硬件,只有代码
  • 可定制的——免费获得简单的东西,但足够灵活,可以为 5%的人疯狂,这需要到外面去
  • 可扩展的 —自动可扩展的数据处理、训练、推理
  • Pythonic——不要尝试其他东西……我们需要一种生产就绪的东西,它可以与当今大多数工具和代码一起工作,并且适合标准的数据科学家。如今几乎没有其他选择(我已经说过这是固执己见了吗?).

是否存在包含整个数据科学周期的工具?我希望。
但是有许多很棒的工具可以满足上述所有要求,当它们粘在一起时,可以很容易地结束这个循环。
将它们粘合在一起并自动化管道以适应您的组织可能需要一点时间……但这一次的努力是值得的。此外,工具变得越来越好,越来越丰富,正如我们所说的那样,占用了越来越大的周期,所以当你读到这篇文章时,它可能比我必须经历的要容易得多。

在本文的这一点上,值得花一分钟来确保您理解了"全周期"(产品生命周期)!= “全栈”(技术栈——例如后端和前端)
**其实完全相反!**与全堆栈不同,在全周期中,我们的目标是用单个堆栈结束整个产品生命周期!数据科学家堆栈!
Python(和令人敬畏的托管服务)就是你所需要的一切。

工具的选择完全取决于您,我并不试图说服任何读者选择其中一种。这不仅仅是一个纯技术的问题,而是你的组织喜欢什么,云提供商,个人偏好,对黑暗模式的支持(超级重要)等等。
为了充分披露,我在@Google,Waze 工作,使用 GCP 托管服务(我真的很喜欢)。为了让读者对这样的堆栈有一个大概的了解,我将非常粗略地列出我的 FCDS 堆栈中的几个工具(都是可扩展和可管理的):

  • BigQuery:结构化数据存储和 SQL 处理
  • tfX
    *tensor flow2 . x
    • TF . transform over data flow:批处理&流处理,特性工程嵌入到 TF 模型中,因此您只需编写一次代码
      *开箱即用的组件,用于数据验证、模型分析、模型祝福(与以前的模型版本相比)和部署
  • 云 AI 平台(CAIP) ->现在叫顶点 AI
    • CAIP 笔记本:研究&探索
    • CAIP 工作:培训
    • CAIP 机型:高负载&低延迟推断
    • CAIP 管道:TFX 即服务
  • 更多的小补充超出了本文的范围。举几个例子:Git、Gerrit、Jenkins、通过 Cloud Composer 的气流

帮助数据科学家开始使用新 FCDS 技术的一个常用方法是提供生产就绪、可分叉、经过测试的完整管道模板(从数据探索到持续培训和部署)。我发现它极大地缩短了开发时间并简化了采用。

文化

“走向 FCDS”是数据驱动型组织文化中的一项重大变革。数据科学家不仅只能依靠他们自己(可能有些夸张),他们现在还直接为生产做出贡献!
这几乎总是意味着需要以工程为导向提升数据科学家的技能。
新的数据科学文化现在从坚实的工程文化中借用概念。
它现在发现了升值的价值:

  • 代码质量 —我们不构建一次性的,我们构建持久的生产系统
    *代码评审
    *单元测试
    *没有生产代码的笔记本(只是为了原型开发)——关于这个主题已经写了无数的文章。TL;DR 是一个成熟的项目代码,包含。py 文件与。ipynb 文件。它易于重用(可导入)、可测试、可审查、通用、可参数化、可与其他组件集成、不依赖数据等。基本上,它让你走上了可持续发展的正确道路。是的,我知道笔记本领域有几种工具可以尝试解决这些问题。我只想说,你可以给猪涂口红,但它还是一头猪。
  • 系统质量 *研究文档&评审
    *设计文档 &评审
    *成功定义
    • KPI /测量设计
      *实验设计

实施说明

全周期数据科学家简介

数据科学有多种口味。FCDS 方法足够通用,可以应用于其中的许多领域,可能是机器学习,取代试探法和算法,产品分析或传统统计。通常情况下,数据科学家需要平衡这些不同类型的项目。此外,每一个这样的领域(例如 ML)可能包括非常不同的子领域(例如推荐系统、计算机视觉、NLP)。

这就是为什么我们的方法更喜欢数据科学 通才 (缝针修复)——全面发展的个人,他们可以深入新的领域和工作类型,并应用他们的数据导向、技术技能集和领域知识来创造成功的产品。这些人确实存在,我正在和他们中的一群人一起工作!(作为经理,我的职责是让他们意识到他们有能力做到这一点,并提供一些小的指导)。对于专家来说,您的组织足够大吗?(多面手的反义词)请便,但你可能希望专家成为研究科学家,而不是数据科学家。
我很少见过在生产影响导向的岗位上比多面手做得更好的专家。老实说,对于任何多面手来说,使用现成的 keras 架构/领域 SOTA 模型只需几个小时。

FCDS 以影响力为导向。这意味着像每一个值得尊敬的软件开发哲学一样,我们以敏捷的方式工作。

我们从小处着手,我们制作原型,我们建立一个可靠的生产管道(分叉模板,在几分钟内准备好)并实现一个简单的基线(甚至不一定是一个模型!).我们建立测量,然后我们开始迭代和改进。

现在我将进入真正有争议的部分:)
我们可以将世界分为两种类型的数据科学家——行业驱动型和学术驱动型。
FCDS 非常重视产品影响和代码质量,它倾向于前者。
显然两者兼而有之很好,但是为了说明一点,我要声明比起没有生产经验/糟糕的编码技能的博士,我更喜欢雇佣一个优秀的、思维敏捷的、对数据有兴趣和良好感觉的工程师

我们之前提到过,独立性对于高效的数据科学家至关重要。然而,重要的是不要把独立和隐居混为一谈。不善于与他人合作的“独狼”类型不是数据科学家的良好形象。独立意味着你可以快速行动,但是集思广益、相互审查以及与利益相关者的密切沟通对于深入研究和数据解释这种工作来说是非常重要的,而这种工作是数据科学家的谋生之道。

总而言之,一个伟大的全周期数据科学家是一个独立、全面的通才,他喜欢什么都做一点,拥有扎实的编码技能,重视敏捷,喜欢生产影响胜过研究

有效性危险信号

拥抱像 FCDS 这样的新生活方式及其哲学、技术和文化是一个过程。与其指出一大堆要遵循的规则,不如指出清晰的危险信号来表明效率的降低和道路的偏离。

危险信号包括:

  • 角色(非常固执己见)
    数据工程师做的是构建工具以外的事情。这是我怎么强调其重要性都不为过的头号错误。数据工程师是软件工程师,他们构建恰好在数据领域的软件系统。还记得我们说过,我们需要把一堆不同的工具粘在一起,让每样东西都能为普通的 DS 工作吗?适应我们的组织需求,建立稳固的 CI/CD 渠道等。这都是数据工程。
    构建数据管道和仪表板(ETL / BI)是数据科学家的角色。它
    是周期*的重要组成部分!把它交给别人意味着我们没有完成整个周期。如果你认为有些 ETL 对于 DS 来说太复杂了,你没有使用正确的工具或者没有雇佣正确的数据科学家。
    工程师不应该写 ETL (缝合修复)
    *你有一个 ETL / BI 工程师角色。同上,这意味着您的 DSs 没有完成整个周期。
    *你有一个 ML 工程师的角色。如果你需要一个工程师把你的 ML 代码投入生产,那么你的 DSs 就没有做完整的循环。
    *您需要 SREs/Devops 协助将 DS 代码推向生产
  • 处理问题
    *由用户发现的数据/模型问题,而不是由警报发现的问题
    *无法回滚到先前的模型版本
    *不容易复制当前的生产模型
    *重新训练模型是手动的
  • 重新实施
    • DS 需要在研究和生产之间重新实施他们自己的工作
    • DS 移交研究代码(模型/特征工程等。)供 SWE 重新编码到生产堆栈中
  • 错位
    *用于分析/训练(离线)的数据与用于生产/推理(在线)的数据不完全相同
    *特征工程代码使用试探法/代理来补偿未记录的数据

时机

你可能会问自己,这是否是你的组织尝试采用 FCDS 的正确时机。

答案是肯定的。

  • 小型创业公司构建数据组织?以这种方式开始——无论如何你都必须这样做,因为雇佣专家而不是能做所有事情的多面手对你来说是非常昂贵的。你只需要投资合适的工具,让他们的生活更轻松。
  • 大公司?这是最难的,因为文化已经存在,人们对自己的所作所为感到满意。但是,这是您将看到对速度、质量和整体业务影响最大的地方。
  • 中间的某个地方?在你大到难以改变文化之前,开始尝试这种方法。尝试,慢慢过渡,先只做一些项目,投资科技(反正对你有好处)。开始模糊不同职能之间的界限,让 DS 慢慢地从 DE/SWE/SRE 身上咬下一大块,直到你可以结束这个循环。

摘要

扩展数据驱动型组织的最有效方法是采用全周期数据科学,这是一种端到端的方法,其中个人结束整个产品周期,专注于他们带来附加值的地方,并获得其他现成的东西。

这种方法应该创建一个成功的数据组织

  • 速度 * DS 可以专注于创意方面
    *可重用组件和可复制粘贴的生产就绪模板
  • 质量 * DS 清理自己的数据
    *现成的数据验证&监控
  • 可持续性 *自动化
    *可再生
    *可扩展
  • 业务影响 *可操作洞察/生产最小化的时间
    *单个 DS 完全端到端独立
    • DS 拥有生产产品&工件
      *满意度 ** DS 关心生产
      ** DS 感受他们的影响

那么,扩展数据驱动型组织的问题解决了吗?大概不会。我已经在 2020 年左右开始了这项工作,现在效果很好,但那只是在我们遇到下一组问题之前。此外,整齐地结束循环所需的一些工具甚至还没有出现…这些天来,可扩展的训练推理服务的部署很容易找到,但当涉及到功能存储和“数据部署”时,它仍然是一个大烂摊子。

我要感谢我的许多同事@Waze & @Google ,他们通过实验、集思广益、提出问题和不断努力把事情做得更好,为这项工作做出了巨大贡献。

我也要感谢 Alon PalomboPhilippe Adjiman 对这部作品的详细回顾和贡献。

fd:一个简单但功能强大的工具,用于在命令行中查找和执行文件

原文:https://towardsdatascience.com/fd-a-simple-but-powerful-tool-to-find-and-execute-files-on-the-command-line-602f9af235ad?source=collection_archive---------28-----------------------

找到任何文件。很简单。快点。

动机

你有没有想过不用离开终端就能找到文件?find允许你这样做,但是它的语法很复杂。

如果您可以使用如下的简单语法来搜索文件,那不是很好吗?

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

作者图片

这就是 fd 派上用场的时候。在本文中,我将向您展示什么是 fd,以及如何使用它来快速查找任何文件。

什么是 fd?

fd 让你快速找到任何文件。fd 相比find更容易上手。下面是两个命令之间的比较。

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

作者图片

换句话说,你只需要用fd pattern搜索带有pattern的文件。

装置

按照本说明书安装 fd。

其他有用的功能

查找具有特定文件扩展名的文件

如果您想查找具有某种文件扩展名的文件,如.md.py,请使用fd -e extension_name

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

作者图片

使用正则表达式

您也可以使用正则表达式来查找如下文件:

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

作者图片

在特定路径中查找文件

如果你想找到某个目录下的文件,只需使用fd PATTERN directory_name

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

作者图片

命令执行

有时你可能想抓取多个文件,然后对它们做些什么。这也可以用 fd 来完成。要对每个搜索结果执行命令,将-x添加到命令中。

您可以尝试使用此功能做一些有用的事情:

  • 移除以txt结尾的文件

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

作者图片

  • 在您喜欢的编辑器中打开多个文件

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

作者图片

  • 重命名多个文件

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

作者图片

注意{}是搜索结果的占位符(text1.txttext2.txt)。

{.}也是搜索结果的占位符,但没有文件扩展名(text1text2)。

高级功能

忽略大小写

默认情况下,fd 区分大小写。可以添加-i忽略大小写。

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

作者图片

将目录遍历限制到给定的深度

默认情况下,搜索深度没有限制。通过在命令中添加-d,可以将目录遍历限制在给定的深度。

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

作者图片

在命令中添加-d 1告诉 fd 只搜索当前目录中的文件。

查找隐藏文件

fd 的另一个强大功能是显示隐藏文件,比如.git。要查看隐藏文件,在命令中添加-H

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

作者图片

忽略文件

您还可以通过在命令中添加-E来忽略特定的文件

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

作者图片

…或者将您想要忽略的文件添加到同一目录下的.fdignore文件中:

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

作者图片

很酷,不是吗?

要查找 fd 提供的其他功能,请键入:

fd --help

结论

恭喜你!您刚刚学习了如何找到具有特定模式的文件,并使用 fd 执行它们。我希望这个工具能把你从花在小任务上的时间中解放出来,这样你就可以腾出时间来做重要的任务。

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedInTwitter 上联系我。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

💔-tools-to-track-and-visualize-the-execution-of-your-python-code-666a153e435e>

功能选择和公平性:少即是多

原文:https://towardsdatascience.com/feature-choice-and-fairness-less-may-be-more-7809ec11772e?source=collection_archive---------36-----------------------

公平和偏见

深思熟虑的预测值选择对于模型的公平性至关重要

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

布雷特·乔丹Unsplash 上拍摄的照片

我经常听到的一个常见的与人工智能有关的担忧是,机器学习模型将利用隐藏在庞大的个人信息数据库中的古怪事实来做出影响生活的决定。例如,你在简历中使用 Arial 字体的事实,加上你养猫和喜欢 pierogi,会阻止你得到一份工作。与这种担忧相关的是害怕由于这种推断而受到基于性别或种族的歧视。这种恐惧是愚蠢的还是现实的?机器学习模型是基于相关性的,任何与一个结果相关联的特征都可以作为决策依据;有理由担心。然而,这种情况发生的风险取决于模型可用的信息和所使用的特定算法。在这里,我将使用样本数据来说明随机森林与 XGBoost 模型中纳入附带信息的差异,并讨论在评估模型公平性时考虑缺失信息、适当性和因果关系的重要性。

特征选择——检查可能缺少的和包含的——对于模型的公平性非常重要。通常特征包含仅仅被认为是保留或省略了“敏感”特征,如种族或性别,或这些特征的显而易见的代理。然而,模型可以利用与结果相关联的任何特征,并且模型性能和公平性的通用度量将基本上不受影响。偶然的相关特征可能不是合适的决策基础,或者它们可能代表不公平的风险。当模型中不包括适当的预测因子时,附带特征风险最高。因此,仔细考虑可能遗漏的内容至关重要。

资料组

本文基于上一篇博文的结果,并使用相同的数据集和代码库来说明缺失和附带特性的影响[1,2]。简而言之,我使用一个公开可用的贷款数据集,其中的结果是贷款违约状态(二元),预测因素包括收入、就业时间、债务负担等。我倾向于(但随机地)将低收入案例归为虚构的“女性”类别,为了简单起见,只考虑两种性别类别(“男性”和“女性”)。结果是“女性”的平均收入较低,但男性和女性的收入重叠;有些女性收入高,有些男性收入低。通过检查常见的公平性和绩效指标,我发现无论模型是依靠收入还是性别来预测违约,结果都是相似的,这说明了仅依靠指标来检测偏差的风险。

我之前的博文展示了当一个附带特性代替了一个合适的特性时会发生什么。在这里,我将讨论当适当的预测因子和附带特征都包含在数据中时会发生什么。我测试了两种类型的模型,并表明,正如所料,女性身份有助于预测,尽管它不包含额外的信息。然而,偶然特征对随机森林模型的贡献比对 XGBoost 模型的贡献大得多,这表明模型选择可能有助于减少不公平风险,尽管应该考虑权衡。

公平指标和全球重要性

在我的示例中,女性特性没有向已经包含收入的模型添加任何信息。任何对女性身份的依赖都是不必要的,并代表着“直接歧视”的风险。理想情况下,机器学习算法会忽略这样的特征,而支持更强的预测器。

当随机森林或 XGBoost 模型增加了女性地位这一附带特征时,我发现总体性能特征或性能指标几乎没有变化(数据未显示)。ROC 分数几乎没有变化(这是意料之中的)。假阳性率显示非常轻微的变化。

当纳入女性指标时,XGBoost 的人口统计均等(即女性与男性的贷款违约率差异)基本保持不变(5.2%比 5.3%),但对于 random forest,该指标从 4.3%变为 5.0%;我将在下面详细讨论这个观察结果。

对于两种模型类型,全局排列重要性显示出女性特征的微弱影响。这个特性在随机森林模型中排名 12/14,在 XGBoost 中排名 22/26(当女性=1 时)。女性地位相对较低的事实似乎令人放心,但这一特征的任何影响都是公平风险。

当数据中包含女性地位时,全球指标中没有明确的危险信号,但这是意料之中的,因为无论决策是基于偶然因素还是因果因素,公平指标都是相似的[1]。关键问题是:纳入女性地位是否会增加结果的差异?

聚合 Shapley 值

我们可以使用聚集的 Shapley 值来衡量某个特征对群体预测差异的贡献程度[3]。这项技术将预测结果率的差异分布在各个特征之间,这样我们就可以确定是什么导致了女性与男性之间的差异。计算包括构建由随机选择的雄性组成的参考数据集,使用该“箔”计算随机选择的雌性的 Shapley 特征重要性,然后合计雌性 Shapley 值(也称为“phi”值)。

下面显示了带有和不带有“女性”特征的两种模型类型的结果。不包括女性的模型的前 5 个特征与包括该特征的模型的女性状态一起绘制。其他所有特征都被总结为“其他”。

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

显示随机森林(左)和 XGBoost(右)模型中女性与男性预测总体差异相关特征的聚合 Shapley 图。排除(红色条)和包括(蓝色条)女性状态特征的模型的结果包括在内。图片作者。

首先,请注意,对于 random forest 来说,雌性的蓝色条(只存在于包含雌性状态的模型中)比 XGBoost 大得多。条形图大小表示归因于某一特征的女性与男性的概率差异量。对于 random forest,女性状态功能使女性相对于男性的违约概率增加了 1.6%,相比之下,XGBoost 的违约概率为 0.3%,相差约 5 倍。

对于 random forest,女性地位在决定男性与女性预测差异的三大影响特征中排名第一,尽管该特征在全球范围内排名第 12 位。全局重要性没有捕捉到该特征对公平性的影响。

如上一节所述,随机森林模型显示,当模型中包括女性地位时,人口统计均等性下降。这种效应在 Shapley 图中也很明显——女性柱的增加不会被其他柱的减少所补偿。对于 XGBoost 来说,女性地位的微小贡献似乎被其他特征贡献的微小减少所抵消。

当我们考虑算法如何工作时,与随机森林相比,XGBoost 附带特性的影响减少是有意义的。随机森林使用要素的随机子集创建树,并对其进行最佳分割检查。这些初始特征集中的一些将包括附带特征,但不包括适当的预测器,在这种情况下,可以选择附带特征用于分割。对于 XGBoost 模型,分割标准基于对以前模型的改进。偶然特征不能改善基于更强预测器的模型;因此,在几轮之后,我们期望树只包括适当的预测器。

考虑到模型建立机制,也可以理解随机森林的人口奇偶减少。当在随机森林中生成要考虑进行分割的要素子集时,我们基本上有两个“收入”要素,因此更有可能选择(直接或间接)收入信息。

随机森林模型有效地使用了比 XGBoost 更大的功能集。尽管在某种程度上这两种模型类型中都可能出现大量的特性,但是 XGBoost 解决方案将倾向于更少的更具预测性的特性。这降低了但并没有消除与 XGBoost 附带特性相关的风险。

XGBoost 比随机森林公平吗?

在之前的博客文章[4]中,我展示了通过整合交互来减轻特性偏差对于 XGBoost 比对于 random forest 更有效(对于一个测试场景)。在这里,我观察到 XGBoost 模型也较少受到附带信息的影响。这是否意味着出于公平的原因,我们应该更喜欢 XGBoost?

当偶然和适当的特征都包含在数据中时,XGBoost 具有优势,但是当包含偶然特征时,XGBoost 不会降低风险。随机森林模型对大量要素的依赖可能是一种优势,尤其是当附加要素与缺失的预测因子相关时。

此外,XGBoost 不太依赖附带特性的事实并不意味着它完全没有贡献。可能只有少数决定是基于不适当的信息。

抛开公平性不谈,随机森林对你可能认为的“解决方案空间”的更大部分进行采样,并依赖更多的预测器,这一事实可能对模型的稳健性有一些好处。当模型被部署并面临数据中的意外错误时,随机森林模型可能更能弥补这一点。(另一方面,如果随机森林包含受错误影响的相关功能,它可能会受到损害,而 XGBoost 模型不会受到影响)。

XGBoost 可能有一些公平性优势,但是“最公平”的模型类型是依赖于上下文的,并且还必须考虑健壮性和准确性。我觉得公平性测试和可解释性,以及深思熟虑的特性选择,在促进公平性方面可能比模型类型更有价值。

我错过了什么?

在选择可能影响生活的模型的特征时,公平性考虑是至关重要的。存在许多现有的特征选择方法,这些方法通常优化准确度或预测能力,但是不考虑公平性。这些没有解决的一个问题是“我遗漏了什么特性?”

一个依赖于偶然特征的模型可能看起来表现合理,尽管做出了不公平的决定[1]。因此,问自己“缺少了什么”是非常重要的建立模型时。这个问题的答案可能涉及主题专业知识或额外的研究。被认为有因果关系的缺失预测因子可能是特别重要的考虑因素[5,6]。

显然,对于一个缺失的预测器,最好的解决方案是合并它。有时候,这可能是不可能的。有些效果无法测量或无法获得。但是你我都知道简单的不可用性很少决定最终的特性集。相反,通常是“信息在不同的数据库中,我不知道如何访问它”,或者“该来源由不同的团队所有,他们很难合作”,或者“我们可以获得它,但需要支付许可费”。功能选择通常反映了时间和精力——这通常是好的。有可能的时候,权宜之计是伟大的。但是,当便利性损害了公平时,确实需要做出一些让步。这时,可能需要公平性测试、聚合 Shapley 图和主题专业知识来进行额外工作或延迟时间表,以确保做出适当的决策。

我包括什么?

另一个关键问题是“我包括了什么?”,这通常可以重述为“这是什么的代理?”这个问题可以简单地应用于数据集中的每一个要素,但是对于被识别为导致组差异的要素,应该非常仔细地考虑;这些特征可以用聚集的 Shapley 图或单独的解释来识别。调查这些特征是否提供了比其他预测因素更多的信息可能是有用的

我像谁,他们以前做过什么?

预测贷款违约、购买产品的可能性或工作成功的二元分类模型本质上是在问这样一个问题:“我像谁,他们以前做过什么?”这里的“like”一词指的是数据中包含的特征的相似值,根据它们对模型的预测贡献进行加权。然后,我们模拟(或近似)该群组在过去所做的事情,以生成一个概率分数,我们认为该分数是该群组中的人的未来结果的指示。

“我像谁?”这个问题触及了人们担忧的核心,即如果人们吃了太多的意大利馅饼,养了太多的猫,或者只是碰巧是某个种族、性别或民族,就会受到评判。令人担忧的是,不考虑总体人口的平均结果,只根据个人在这些群体中的成员资格来评估他们是不公平的。什么是合适的在很大程度上取决于具体情况——也许在心脏病发作模型中考虑精神病患者没什么问题,但在刑事司法环境中就令人担忧了。

我们的模型将人们分组——即使模型是连续的,我们也可以认为这是非常小的桶的极限——然后我们估计这些人群的风险。这与老派的精算表没有太大的不同,只是我们可能会使用非常大的功能集来确定组边界,并且我们可能不会完全意识到我们在这个过程中使用的信息的意义。

最后的想法

功能选择不仅仅是一个数学练习,可能需要主题专家、合规分析师甚至公众的判断。数据科学家对这一过程的贡献应该包括对人群使用可解释技术,并发现驱动群体差异的特征。我们还可以识别高危人群,并询问与结果有因果关系的已知特征。

法律和法规遵从性部门通常关注所包含的功能,他们关注的可能主要是特定类型的敏感信息。考虑模型中缺少的东西并不常见。然而,问题是,“缺少了什么?”至少和“那里有什么”一样重要在确认模型作出公平和适当的决定。

数据科学家可能斗志昂扬,擅长用有限或嘈杂的数据制作模型。从不太理想的信息中得到一个“有效”的模型是令人满意的。承认有些事情做不到可能很难,但有时公平决定了我们现在所拥有的真的不够——或者还不够。

参考

[1] V. Carey,公平指标不会将你从刻板印象中拯救出来 (2020),走向数据科学。

[2]诉凯里。GitHub 资源库,https://github.com/vla6/Stereotyping_ROCDS

[3] S. Lundberg, (2020),向数据科学解释公平的措施。

[4] V. Carey,如何修正特征偏差 (2021),走向数据科学。

[5] M. Prosperi,Y. Guo,M. Sperrin,J.S. Koopman,J.S. Min,X. He,S. Rich,M. Wang,即和 J. Bian,机器学习中的因果推理和反事实预测,用于可操作的医疗保健 (2020),自然机器智能 2:369–375。

[6]b . schlkopf,机器学习的因果关系 (2019),arXiv:1911.10500v2 [cs .LG】。

特征工程 A-Z

原文:https://towardsdatascience.com/feature-engineering-a-z-aa8ce9639632?source=collection_archive---------25-----------------------

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

Unsplash 上的hkon grim stad拍摄的照片

转换特征以提高模型性能的清单

特征工程是转换数据以提取有价值信息的过程。事实上,如果适当转换,特征工程甚至可以在模型性能中发挥比超参数调整更大的作用。

尽管功能工程有着巨大的作用,但初学者和有经验的数据科学家通常不太理解,有时甚至会误解。最近我问了几个人,他们所说的特征工程是什么意思。有趣的是,他们无法超越缺失值、特征缩放或对数变换。但是当然,这是一个包括各种工具、技术和应用的主题。

在这篇文章中,我把通过特征转换和工程来提高模型性能的许多不同方法放在一起并加以综合。

在进入特征工程之前,我们先来区分一下数据清理。重命名列、更改数据类型(例如,从“对象”更改为“类别”)、将数据分成训练集和测试集—这些都是数据科学项目的重要组成部分,但它们不是功能工程。你可以称之为数据清理。

那特征工程到底是什么?

我将特征工程分为 6 大类:

  • 特征抽出
  • 特征合成
  • 特征转换
  • 异常值处理
  • 缺失值处理
  • 其他(例如多项式变换)

让我们一个一个地了解一下。

特征抽出

假设我们有某种关于消费统计的数据,上面有一个时间戳:

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

带有时间戳的数据

在本例中,“日期”列可以轻松地用于提取附加特征并生成强大的洞察力,例如工作日、周末或一年中特定时间的消费变化(参见下面的黄色突出显示)。

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

数据与特征工程

特征合成

特征合成与特征提取相反。在这种情况下,将一个或多个要素组合起来创建新要素,这些新要素比单独创建的要素信息量更大。

比方说,在一个房价数据集中,你有两列:楼层空间(平方英尺)和总房价(美元)。您可以在分析中单独使用它们,但也可以创建一个名为price _ per _ sqft(US $/sqft)的新计算要素。

特征缩放

特征缩放/变换是指在数据预处理中应用的各种方法,用于将数据重新缩放或归一化到不同的范围。缩放的目的是以这样一种方式转换数据,即它们或者是无量纲的和/或具有相似的分布。三种流行的缩放方法是:

**a)重新调整:**也称为“最小-最大归一化”,这是所有方法中最简单的方法,计算如下:

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

**b)均值归一化:**该方法在转换过程中使用观察值的均值:

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

**c)标准化:**也称为 Z 分数标准化,这种技术使用 Z 分数或“标准分数”进行特征缩放。它广泛用于机器学习算法,如 SVM 和逻辑回归:

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

**d) Log 变换:**在对数变换中,一个特征的每个值都是从 x 变换到 *log(x)的。*对数变换的一个常见应用是构建线性回归模型,其中连续变量的分布被更改为高斯形式,以满足建模假设。

对数转换受欢迎的另一个原因是因为增加了视觉可解释性和外观,尤其是高方差数据(见下图)。

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

显示使用和不使用对数变换时面积和人口之间关系的散点图。来源:维基百科

特征编码

特征编码是指将特征的分类字符串值转换为数字值。

例如,如果您的数据集中有一个“性别”列,并且值表示为女性男性,您可以将这些字符串转换为数字表示,例如男性= 1,女性= 2。这种编码特征的方式被称为标签编码

当然,进行标签编码意味着算法可能会对女性(= 2)值赋予比男性(= 1)值更高的权重。为了克服这种情况,人们转而使用 One Hot Encoding 来创建虚拟变量,其中每个类别变成一个虚拟列,值变成 1 或 0。

下面是一个示例,其中一键编码应用于具有分类要素的数据集:

import seaborn as sns
df = sns.load_dataset('tips')
df.head()

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

没有假人的分类特征

现在在pandas中创建假人:

import pandas
pd.get_dummies(df)

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

转换成虚拟变量的分类特征

异常值处理

每个数据科学家都不得不面对他们项目中的异常问题,没有多少例外。离群值是特定于领域和上下文的。如果您正在构建一个模型来预测一个平均价格为 30 万美元的社区的房价,而您的数据集却有一所售价为 1000 万美元的房子,那么这一定是一个异常值。同样,如果一栋房子卖了 3 万美元,你也不希望它出现在模型中。

那么你有什么选择来改变这些离群值呢?以下是您的选择:

  • 如果它们仅仅在可接受的范围之外,您可以将它们留在数据集中
  • 如果负担得起,您可以删除观察值(例如,您的数据集相当大)
  • 封顶/剪裁异常值,将异常值剪裁到某个范围(例如,四分位间距、IQR)。

缺失值处理

缺失值在大多数数据集中很常见,它们被记录为NANaN。处理缺失数据没有单一的标准方法,人们根据数据集采取不同的方法。这里有 3 种最受欢迎的方法:

  • **删除:**如果数据集很大,并且缺失发生的次数相对较少,则删除带有缺失值的完整记录。
  • **替代/插补:**缺失值通常由适当的替代值替代,如列平均值、中位数、最近邻平均值、移动平均值等。
  • **统计插补:**这是一种复杂的插补方法,使用线性回归作为数据集中其他列的函数来预测缺失值。

其他类型的特征工程

除了我刚刚描述的,在特征工程领域还有一些其他的工作,包括:

  • 减少类别数量:对类别特征进行重新分类,即减少类别数量。例如,如果一列中有 6 个教育水平类别,您可能希望将它们分成 3 个类别。
  • 宁滨:为数字变量创建区间,例如,“年龄”可以分为< 20、20–30、30–40 等。而不是让它们变成 1,2,3,4 ……40 等。
  • 多项式拟合:在回归分析中,除了采用*y = b0+ b1x*形式的线性模型,还可以采用*y = b0 + b1x + b2x²* 形式的多项式函数进行拟合,以找到更好的拟合。

摘要

总之,特征工程的主要目的是提取额外的数据/信息以获得更好的模型性能。进行特征工程有许多不同的方法,但最常用的方法是特征提取、特征合成、缩放、异常值处理、缺失值处理、宁滨、多项式变换等。

在这篇文章中,我总结了它们,但是当然,每一个都有很多深入的内容。但是希望我在这里描述的内容可以作为一个有用的参考。如果我错过了什么,你觉得其他的也应该包括进来,请在评论区写下来。

感谢阅读。请随意订阅以获得我即将发布的文章的通知,或者通过 TwitterLinkedIn 与我联系。

特征工程示例:宁滨分类特征

原文:https://towardsdatascience.com/feature-engineering-examples-binning-categorical-features-9f8d582455da?source=collection_archive---------10-----------------------

如何使用 NumPy 或 Pandas 快速绑定分类特征

出于机器学习(ML)目的使用分类数据有时会出现棘手的问题。最终,这些特征需要以某种方式进行数字编码,以便 ML 算法可以实际处理它们。

您还需要考虑其他方法来为分类要素建模做好准备。例如,您的模型性能可能受益于宁滨分类特征。这实质上意味着将多个类别归入一个类别。通过应用领域知识,您可以设计新的类别和功能,更好地表示数据结构。

在这篇文章中,我们将简要介绍为什么宁滨分类特征是有益的。然后,我们将通过使用 NumPy 和 Pandas 的具体示例,介绍宁滨分类特征的三种不同方法。

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

埃菲社Unsplash 上拍摄的照片

为什么要分类?

对于分类特征,您可能会遇到稀有标签的问题,即在您的数据集中极不常见的类别/组。这个问题通常与基数高的特性有关——换句话说,就是许多不同的类别。

有太多的类别,尤其是很少的类别,会导致一个嘈杂的数据集。ML 算法可能难以穿过这种噪声并从数据中更有意义的信号中学习。

如果你选择一个热编码你的分类特征,高基数也会加剧维数灾难。如果原始变量有 50 个不同的类别,那么基本上就是向数据集添加了 49 列。

类别太多也会导致训练和测试模型时出现问题。一个类别完全有可能出现在测试集中,而不是在训练集中。您的模型将不知道如何处理该类别,因为它以前从未“见过”它。

解决这些问题的一个方法是设计类别更少的新功能。这可以通过将多个类别宁滨(分组)为一个类别来实现。

在下面的例子中,我们将利用关于选民人口统计和参与的信息来探索和设计来自数据集的特征。我选择了 3 个分类变量:

  1. party_cd:登记选民的政党背景
  2. voting_method:登记选民如何在选举中投票
  3. birth_state:美国注册选民出生的州或地区

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

数据框前 5 行的屏幕截图—作者提供的图片

如果您想开始将这些方法应用到您自己的项目中,您只需要确保您已经安装了 NumPy 和 Pandas,然后导入它们。

使用 np.where()绑定类别

首先,我们来看看我为什么选择party_cd。下图显示了每个政党有多少个人选民。

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

Seaborn countplot 显示了按政党划分的选民分布情况—按作者划分的图像

注册的自由主义者、立宪主义者和绿党成员如此之少,以至于我们在图表上几乎看不到他们。这些是稀有标签的好例子。出于本文的目的,我们将罕见标签定义为占观察值不到 5%的标签。这是定义稀有标签的一个常见阈值,但最终这取决于您的判断。

让我们来看看实际数字的细分:

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

属于每个政党的登记选民的原始计数和百分比——图片由作者提供

这三类人各占不到总人口的 5%。即使我们把他们都归为一类,这个新的类别也只能代表不到 1%的选民。

“REP”和“DEM”代表两大政党,而“UNA”代表登记为与某个政党无关的选民。因此,在这里,将我们的三个罕见标签归入无党派团体是有意义的,这样我们就有三个类别:两个主要政党各一个,第三个代表选择不与任何一个主要政党结盟的个人。

这可以用np.where()很容易地完成,它有 3 个参数:

  1. 一种状况
  2. 如果满足条件,返回什么
  3. 如果不满足条件,返回什么

下面的代码使用np.where()从原始的party_cd变量创建了一个新的特性party_grp:

它检查的条件是原始值是否在列表['REP', 'DEM']中。如果是,那么np.where()简单地返回原始的当事人代码(尽管我已经把它作为标题案例返回了,因为我个人讨厌看到全是大写的东西)。如果原始交易方代码不在该列表中,np.where()返回“其他”。我们新设计的party_grp功能现在更加平衡,没有任何罕见的标签:

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

属于每个政党的登记选民的原始计数和百分比——图片由作者提供

使用 map()将类别映射到新组

接下来,我们来看看voting_method的分布:

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

Seaborn countplot 按投票方法显示选民分布情况-图片由作者提供

不是最漂亮的图表,但我们得到了图片。我们有 8 种不同的投票方式。我大胆猜测,其中一半符合我们对稀有标签的定义。

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

通过每种方法投票的注册选民的原始计数和百分比-图片由作者提供

没错。我们的类别中有四个是稀有标签。现在,我们可以将它们全部归入“其他”类别,然后就到此为止,但这可能不是最合适的方法。

根据我对这些方法如何编码的研究,我知道“缺席”意味着有人提前投票。因此,我们可以将任何“缺席”方法归入“早期”类别,将“亲自”和“路边”归入“选举日”类别,将“不投票”作为自己的类别,将“临时”和“转移”归入“其他”类别。

下面的代码通过首先使用原始的voting_method类别作为键定义一个字典来完成这个任务。每个键的值就是我们实际想要的新类别。

最后一行基于voting_method列中的原始值创建了一个新列vote_method_cat。它通过将 Pandas 的map()方法应用于原始列,并输入我们的vote_method_map来将键转换为相应的值。

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

通过每种方法投票的注册选民的原始计数和百分比-图片由作者提供

现在,我们已经摆脱了除了我们的一个罕见的标签。最终,我选择放弃那 733 张“其他”票。投票方式实际上是我试图预测的目标变量,我真正感兴趣的是人们如何选择投票。临时选票和转移选票更多地反映了投票的过程和规则,但我的问题具体涉及选民的主动选择。

因此,您不仅可以考虑工程预测特性来更好地表示数据的底层结构,还可以考虑如何最好地表示与您的特定问题相关的目标变量

使用 apply()应用自定义函数

最后,我们将研究宁滨。这个变量有 57 个类别:每个州一个,缺失信息一个,每个美国领土一个,最后一个类别是在美国以外出生的个人。

所以这张图表看起来滑稽可怕:

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

Seaborn countplot 显示了按出生地划分的选民分布情况——图片由作者提供

如果您在探索分类特征时看到过这样的图表,这是一个很好的迹象,表明如果您打算将宁滨变量用作模型中的一个特征,您应该将其考虑在内。

以下是 15 种最常见的birth_state分类:

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

按出生地统计的原始选民数量和登记选民比例——按作者分类的图片

北卡罗来纳州是最常见的州,这是有意义的,因为该数据是针对北卡罗来纳州特定县的选民的。然后我们会看到很多缺失的值。纽约人和在美国以外出生的人也构成了相当大的一部分人口。基于我们的定义,剩余的 53 个类别是罕见的标签,并将在我们的建模工作中引入大量噪声。

让我们按照美国人口普查地区(东北部、南部、中西部、西部)对各州进行分组。我们还会将出生在美国境内或境外的人归入“其他”组,并将“失踪”作为一个单独的类别。

我们将通过定义我们自己的自定义函数来实现从州到地区的转换,然后将该函数应用于我们的原始变量以获得我们的新特性。有一种方法可以让你编写一个函数来检查每个州并返回想要的地区/类别:

现在用熊猫的apply()方法来创造我们的新功能:

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

按出生地统计的原始选民数量和登记选民比例——按作者分类的图片

好多了!我们已经从总共 57 个有 53 个稀有标签的类别减少到只有 6 个仍然有很多意义的类别,其中只有一个符合我们对稀有标签的定义。我们可以考虑额外的分组,但你明白了。

概括一下

我们涵盖了:

  • 绑定分类特征意味着什么
  • 为什么以及何时需要绑定分类特征
  • 宁滨分类特征的 3 种方法(np.where()、熊猫map()、熊猫自定义函数apply())

我希望你能发现这些信息,并能把你学到的东西应用到你自己的工作中。感谢阅读!

关于特征工程的更多信息:

什么是特征工程?

特征工程实例:宁滨数字特征

特征工程示例:宁滨数字特征

原文:https://towardsdatascience.com/feature-engineering-examples-binning-numerical-features-7627149093d?source=collection_archive---------13-----------------------

如何使用 NumPy 或 Pandas 快速绑定数字特征

特征工程专注于使用数据集中已经存在的变量来创建额外的特征,这些特征能够(希望)更好地表示数据的底层结构。

例如,你的模型性能可能受益于宁滨数字特征。这实质上意味着将连续或其他数字特征分成不同的组。通过应用领域知识,您可以设计类别和功能,更好地强调数据中的重要趋势。

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

照片由纸胡子Unsplash

在本帖中,我们将通过使用 NumPy 和 Pandas 的具体示例,介绍宁滨数字特征的三种不同方法。我们将从一个数据集中设计特征,其中包含关于选民人口统计和参与的信息。我选择了两个数值变量:

  1. 选举年结束时登记选民的年龄
  2. birth_year:登记选民出生的年份

如果您想开始将这些方法应用到您自己的项目中,您只需要确保您已经安装了 NumPy 和 Pandas,然后导入它们。

使用 np.where()表示阈值

想想可能有点奇怪,但是指示每个实例(在本例中是每个注册投票者)是否达到某个阈值是一种宁滨。

例如,假设我们试图预测每个注册选民是否在选举中投票。也许我们怀疑,如果这是年轻选民第一次有资格在总统选举中投票,他们更有可能参加投票。由于法定投票年龄为 18 岁,任何在本届总统选举期间不满 22 岁的人都不能在上届总统选举中投票。

我们可以使用np.where()为这个阈值创建一个指示变量,它有 3 个参数:

  1. 一种状况
  2. 如果满足条件,返回什么
  3. 如果不满足条件,返回什么

以下代码根据个人的年龄创建了一个新特性first_pres_elec:

df['first_pres_elec'] = np.where(df['age']<22, 1, 0)

我们检查的条件是个人是否小于 22 岁。如果他们低于这个阈值,np.where()返回 1,因为这是他们有资格投票的第一次总统选举。如果不是,则返回 0。从我们的连续变量age中,我们创建了一个新的二元分类变量。

也许我们也有理由怀疑老年人或多或少会去投票。如果是这样的话,我们可能希望通过创建另一个阈值指示器来将我们的模型的注意力吸引到这个阈值上:

df['senior'] = np.where(df['age']>=65, 1, 0)

现在我们已经创建了两个阈值指标来划分选民年龄的分布,如下所示。新近有资格在总统选举中投票的年轻人用红色突出显示,老年人用黄色突出显示。

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

突出显示年轻和年长阈值的登记选民年龄分布-图片由作者提供

使用 apply()应用自定义函数

根据出生年份将我们的注册选民分成几代可能是有意义的,因为这似乎常常与一个人的政治密切相关。一种方法是编写我们自己的自定义函数来描述每一代的临界值。

下面是我们编写这样一个自定义函数的一种方法:

然后使用 Pandas apply()创建一个基于原始birth_year`变量的新特性:

现在,我们的注册选民被分成 5 个独立而有意义的类别。我决定将最老的两代人(最伟大的一代和沉默的一代)结合起来,这样就不会产生两个罕见的类别,每个类别只占人口的很小一部分。

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

Seaborn countplot 按代显示选民分布-按作者显示图像

使用 pd.cut()定义箱

我们也可以使用pd.cut()来创建相同的生成库,而不是编写我们自己的函数并应用它。我们仍然需要为每个组定义适当的标签,以及 bin 边缘(截止出生年份)。

在最后一行中,我们通过向pd.cut()提供我们想要分类的列、我们想要的分类以及如何标记每个分类来创建我们的新特性。

我们可以快速创建一个范围,并将其作为我们的 bin 边缘,而不是按代分组。例如,如果我们认为按十年对年龄进行分组是有意义的,我们可以通过以下方法来实现:

第一行定义了一个范围,从 10 开始,一直到 110,但不包括 110,每步增加 10。第二行使用该范围作为绑定边缘,按年龄将注册选民离散化为以下组:

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

几十年来根据年龄划分的原始计数和注册选民百分比——图片由作者提供

第一行显示 33,349 或 19.84%的选民年龄在 40 岁左右。括号表示 40 岁包括在内,而方括号表示 50 岁不包括在内。为了更容易地跟踪每个 bin 的含义,我们可以向pd.cut()输入以下标签:

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

Seaborn countplot 显示了几十年来按年龄划分的选民分布情况-图片由作者提供

概括一下

我们涵盖了:

  • 对数字特征进行分类意味着什么
  • 1 创建阈值指示器的方法(np.where())
  • 将宁滨数字特征分组的 2 种方法(用熊猫apply()自定义函数,用pd.cut()定义 bin 边缘)

我希望你能发现这些信息,并能把你学到的东西应用到你自己的工作中。感谢阅读!

关于特征工程的更多信息:

什么是特征工程?

特征工程示例:宁滨分类特征

Python 中的要素工程

原文:https://towardsdatascience.com/feature-engineering-in-python-2fdb9bb8ee7a?source=collection_archive---------1-----------------------

超越基础

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

安托万·道特里在 Unsplash 上拍摄的照片

在我十多年作为数据科学家的经历中,我的经验很大程度上同意吴恩达的说法,“应用机器学习基本上是特征工程。”从我职业生涯的一开始,在 SAS 建立信用卡欺诈模型,我作为数据科学家的大部分价值来自于我设计新功能和捕捉数据中观察到的业务见解和行为以帮助模型识别目标的能力。Pedro Domingos 博士的声明也与这种观点一致,“在一天结束时,一些机器学习项目成功,一些失败。有什么区别?最重要的因素无疑是所使用的功能。”

通用特征工程内容

尽管有这些经验和该领域领导者的声明,特征工程内容仍然缺乏。虽然在谷歌上搜索“功能工程”会返回许多页面,但基本内容非常相似,并且只关注几个主题:

  • 处理缺失值
  • 处理异常值
  • 宁滨数值变量
  • 编码分类特征
  • 数字变换
  • 缩放数字特征
  • 提取部分日期

这个内容的问题是

这些都是重要的主题,并且在许多情况下,对于底层的机器学习算法甚至能够处理数据都是必要的。然而,它们在三个主要方面有所欠缺。首先,在某些情况下,他们盲目地应用这些技术,却不知道为什么。许多博客讨论了如何在建模前缩放数字要素。这不是真的。基于树的方法,例如 XGBoost、LightGBM 等。对缩放不变。 Praveen Thenraj 在他关于数据科学的帖子中给出了一个很好的例子。

第二,虽然需要这种技术,但在很多问题中,这种技术并不实用,因此需要其他技术。这方面的一个例子是对分类特征进行编码。大多数关于特征工程的讨论都解释了一次性或虚拟编码,并且经常解释标签编码。他们很少讨论高基数分类变量的挑战。我经常在处理邮政编码时看到这种情况,但在处理医疗数据和 ICD-9 或 ICD-10 诊断代码时也会出现这种情况。一键式编码邮政编码可能会产生 40,000 多种新功能。这不是一个实用的解决方案。理解这些代码的结构可以使它们达到更高的聚合级别。即使在聚合之后,对于一键编码或标签编码来说,可能有太多的类别是有用的。此外,一些分类变量没有可减少所需类别数量的易于识别的集合。目标编码或留一编码可以处理这些高基数分类特征。虽然一些特性工程博客讨论了这些技术,但是他们经常没有强调它们在这种情况下的有用性或者一次性编码的不可行性。

特征工程不止于此。

最后,也是最关键的,特性工程远不止这些。当人们谈论特性工程的力量或特性工程的艺术时,他们并不是指这些标准技术。相反,这项工作认识到邮政编码可以聚合到城市、州、DMA 等。并执行这些聚合。通过将这些汇总与该地点的所有采购相结合,可以进一步执行这一工程,以更好地了解当地市场。最后,个人购买和当地整体市场的比较。这只是冰山一角,是数据科学过程中我最喜欢的部分。

公平地说,如果不讨论实际的建模问题,很难展示这种特征工程的例子。但是在讨论特征工程时完全忽略它可能会对它的范围留下一个错误的印象。此外,还有许多强大的技术可以应用于一系列广泛的问题。

时间序列数据的特征工程

例如,许多数据科学问题具有时间序列特征。这并不是说这些问题是时间序列问题,而是有重复的观察结果需要汇总在一起,以表示感兴趣的潜在行为。在构建客户分析模型时(如客户流失、终身价值),单个交易及其随时间变化的方式非常重要。一个特征工程博客可以分享代码,展示如何为此计算公共特征,如下所示。

当处理单个客户在一段时间内的多项观察数据时,聚合这些数据的最常用技术之一是通过滚动窗口,然后在 pandas 中进行聚合。在这种情况下,将创建一个每周聚合,并创建最小、平均、最大和标准偏差。

weekly_resample = df.rolling('7D')
aggregated_df = weekly_resample.agg(['min', 'mean', 'max', 'std'])
aggregated_df.columns = ['_'.join(col).strip() + '_week' **for** col **in** 
                         aggregated_df.columns.values]

注意,要实现这一点,dataframe df需要日期集作为它的索引。

df.set_index('date', inplace=**True**)

使用滚动窗口,aggregated_df包含每笔交易的记录,其中汇总了前七天的所有交易。相反,如果每周之后都需要进行预测,则需要额外的工作来过滤出该周之前的最后一条记录。熊猫用resample支持这个用例。如果改为运行以下代码,则每周返回一条记录。

weekly_resample = df.resample('7D', 
                              origin=pd.to_datetime('2021-01-03'))
aggregated_df = weekly_resample.agg(['min', 'mean', 'max', 'std'])
aggregated_df.columns = ['_'.join(col).strip() + '_week' **for** col **in** aggregated_df.columns.values]

由于 2021 年 1 月 3 日是星期天,所以聚合从每个星期天开始,并包括一周中其余时间的所有交易。如果星期日之前的七天是所期望的,那么可以进行下面的改变。

weekly_resample = df.resample('7D', 
                              origin=pd.to_datetime('2021-01-03'),
                              lavel='right')

一旦创建了这些每周聚合(任一类型),这些聚合的变化率可能会非常强大。从物理学的角度来看,这是基础特征的速度,我们可以查看多个时间段的变化率。

aggregated_df['velocity_1wk'] = (aggregated_df['mean_week'] - 
                              aggregated_df['mean_week'].shift(1))/7 aggregated_df['velocity_4wk'] = (aggregated_df['mean_week'] - 
                             aggregated_df['mean_week'].shift(4))/28

这给出了一周和四周的周均值变化率。接下来,可以计算这个变化率(加速度)的变化率。

aggregated_df['acceleration_1wk'] = (aggregated_df['velocity_1wk'] - 
                           aggregated_df['velocity_1wk'].shift(1))/7

50 多个免费功能工程教程

像这样的技术可以用来构建能够表示感兴趣的潜在行为的特征。在 Rasgo ,我们希望通过分享这些技术来帮助数据科学界。为了做到这一点,我们创建了一个免费库,专门用于功能工程教程,其中包含功能工程代码,包括上面的例子,作为 Jupyter 笔记本。除了功能工程,还有以下示例:

  • 特征分析和 EDA
  • 数据清理
  • 列车测试分离
  • 特征重要性
  • 特征选择

用于数据科学、机器学习的日期时间变量的特征工程

原文:https://towardsdatascience.com/feature-engineering-of-datetime-variables-for-data-science-machine-learning-45e611c632ad?source=collection_archive---------17-----------------------

了解如何从日期时间类型变量中获取更有意义的特征,以供机器学习模型使用

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

日期时间变量的特征工程。图片作者。

介绍

日期时间字段需要功能工程来将它们从数据转换为可以被我们的机器学习模型使用的有见地的信息。这篇文章分为三个部分和一个额外的部分。在最后,我们将结合使用内置的熊猫和 NumPy 函数以及我们的函数来提取有用的特性。

  • 第 1 部分—提取日期/时间部分
  • 第 2 部分—创建布尔标志
  • 第 3 部分—计算日期/时间差异
  • 奖励——使用fast_ml在 2 行代码中实现工程功能

背景

每当我处理与电子商务相关的数据时,以某种方式或其他数据集包含日期时间列。

  • 用户注册日期-时间
  • 用户登录日期-时间
  • 交易日期时间
  • 有争议的交易日期时间
  • …以及更多

一开始,这个日期字段给我们的只是时间线上的一个特定点。但是这些日期时间字段是潜在的数据宝库。如果使用得当,这些领域对于揭示模式是非常强大的。

作为一名数据科学家,你的工作是将洞察力带到桌面上,为此,你需要提出正确的问题。为了前任。

  • 问题 1 —你认为大多数购物车是在什么时候创建的?
  • 问题 2 —你什么时候看到大多数手推车被遗弃?
  • 问题 3 —您认为什么时候的欺诈交易最多?
  • 问题 4 —什么时候订阅的用户最多?
  • 某些商品在什么时候最常被购买?
  • 问题 6 —注册用户发出第一个订单后多少天/小时?
  • 问题 7 —多少天不活动后,客户再也不会回到您的网站?
  • …等等

现在,要回答这些问题,您需要回到数据上来设计这些日期时间字段。然后可以发现大量的模式。

帖子的第 1 部分将为您提供特征工程步骤,以回答类似 1、2 & 3 的问题

  • Ans 1 —您认为大多数购物车是在什么时候创建的? 本月第一周
  • Ans 2 —你什么时候看到大多数手推车被丢弃? 周三下午
  • Ans 3 —你什么时候看到的欺诈交易最多? 周五晚

本帖的第 2 部分将为你提供特征工程步骤来回答类似于第 4 部分的问题

  • Ans 4 —什么时候订阅用户最多? 年初
  • Ans 5——什么时候最常购买某些物品? 月初

帖子的第 3 部分将为您提供特征工程步骤,以回答类似于 6 & 7 中的问题

  • Ans 6 —注册用户发出第一个订单后多少天/小时?2 小时内
  • Ans 7 —多少天不活动后,客户再也不会回到您的网站?14 天不活动后

我使用了一个电子商务数据的例子,在这个例子中,我个人发现了许多用例,但是提取信息的范围决不仅仅与此相关。在这篇文章中,我们将会看到如何通过问正确的问题来学习一些行为。事实证明,在多个行业中,进行正确的特征工程对于解决各种问题是有用的。

我们开始吧

加载数据集

import pandas as pddf = pd.read_csv('/kaggle/input/loan-data/loan.csv', 
                 parse_dates = ['date_issued', 'date_last_payment'])

Pandas 提供了一种非常简单但非常强大的方法来处理与日期时间相关的变量,将它们解析为日期。您可以将参数parse_dates中与日期时间相关的所有变量作为列表进行传递。

假设您事先不知道日期时间变量,在调查数据后,您发现一些变量是日期时间。因此,pandas 没有重新加载数据,而是提供了另一个有用的函数to_datetime来将数据类型转换为 DateTime。

df['date_issued'] = pd.to_datetime(df['date_issued'], 
                                   errors = 'coerce')

第一部分。提取日期/时间部分

如上例所示,我们可以从给定的日期-时间变量中提取日期-时间部分的组成部分(yearquartermonthdayday_of_weekday_of_yearweek_of_yeartimehourminutesecondday_part)。下面的列表提供了几个可以使用 pandas 内置函数提取的组件。

语法:

我们可以使用.dt访问器提取所有这些组件。在这里阅读更多关于日期访问器的信息

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

从日期时间变量 issued_date 中提取组件。作者图片

下面是如图所示的代码。所有其他成分也可以用类似的方法提取

#1
df[‘date_issued:year’] = df[‘date_issued’].dt.year#2
df[‘date_issued:month’] = df[‘date_issued’].dt.month#3
df[‘date_issued:day_of_week’] = df[‘date_issued’].dt.day_of_week#4
df[‘date_issued:week_of_year’] = df[‘date_issued’].dt.week_of_year#5
df[‘date_issued:hour’] = df[‘date_issued’].dt.hour

注:

  • 周一:day_of_week = 0
  • 周二:day_of_week=1
  • 周日:day_of_week=6

创建日部分:

#day_part function
def day_part(hour):
    if hour in [4,5]:
        return "dawn"
    elif hour in [6,7]:
        return "early morning"
    elif hour in [8,9,10]:
        return "late morning"
    elif hour in [11,12,13]:
        return "noon"
    elif hour in [14,15,16]:
        return "afternoon"
    elif hour in [17, 18,19]:
        return "evening"
    elif hour in [20, 21, 22]:
        return "night"
    elif hour in [23,24,1,2,3]:
        return "midnight"

#Run function with apply method
df['date_issued:day_part'] = df['date_issued:hour'].apply(day_part)df.head()

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

为日期时间变量 issued_date 创建日部分。作者图片

第二部分。创建布尔标志

如上例所示,我们可以从给定的日期-时间变量中提取许多布尔标志(is_month_startis_month_endis_quarter_startis_quarter_endis_year_startis_year_endis_weekend)。下面的列表提供了几个这样的组件,可以使用 pandas 内置的函数以及通过创建我们的一些函数来提取。

语法:

同样,我们可以使用.dt访问器来提取许多布尔标志。

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

从日期时间变量 issued_date 中提取布尔标志。作者图片

#1
df['date_issued:is_year_start'] = df['date_issued'].dt.is_year_start#2
df['date_issued:is_quarter_start'] = df['date_issued'].dt.is_quarter_start#3
df['date_issued:is_month_start'] = df['date_issued'].dt.is_month_start#4
df['date_issued:is_month_end'] = df['date_issued'].dt.is_month_end

创建周末标志:

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

为日期时间变量 issued_date 创建周末标志。作者图片

如果我们查看日历,我们会发现 2013 年 10 月 26 日是星期六——周末。

df['date_issued:is_weekend'] = np.where(df['date_issued:day_of_week'].isin([5,6]), 1,0)

第三部分。计算日期/时间差异

通常你的问题/分析会与另一个参考点相关。比如,

  1. 注册后多少天/小时后,用户发出第一个订单?注册 _ 日期&首 _ 订单 _ 日期
  2. 客户投诉在多少天/小时内得到解决?投诉 _ 日期&解决 _ 日期
  3. 从今天开始,客户从您的网站订购了多久?今天&最后 _ 订单 _ 日期
  4. …等等

在我们的示例数据集中,我们有两列 date_last_payment & date_issued。让我们看看当我们取这两列的差时会发生什么。

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

计算熊猫的时差。图片作者。

默认情况下,熊猫提供“天”的差异。注意dtype: timedelta64[ns]

来自 numpy 文档:

因为 NumPy 的核心没有物理量系统,所以创建了 timedelta64 数据类型来补充 datetime64

现在,如果我们只想要数字部分而不是整个字符串947 days,我们可以通过使用。dt 访问器。

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

计算熊猫的时差。dt 访问器。图片作者。

不幸的是,我们不能以类似的方式得到月份。

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

计算熊猫的时差。dt 访问器不可伸缩。图片作者。

这里 NumPy 的timedelta64变得非常有用。

语法:

为了得到贷款发放日期和最后一次付款日期之间的月数,我们将这样写

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

使用 NumPy timedelta64 计算熊猫的时差。图片作者。

(df['date_last_payment'] - df['date_issued'])/np.timedelta64(1, 'M')

timedelta64 可以采用以下参数来计算两个日期之间的差异:

  • d’→持续几天
  • w’→数周
  • ’ M’ →几个月
  • 多年来
  • h’→数小时

奖金!

您可以使用 fast_ml 来创建所有这些日期时间特性

首先,安装fast_ml

!pip install fast_ml — upgrade

然后,从feature_engineering模块导入工程日期时间特征的方法

from fast_ml.feature_engineering import FeatureEngineering_DateTime

现在,这与 sklearn 的其他变形金刚、预处理器的工作方式完全相同。

  • 例示
  • 合适的
  • 改变
#Instantiate
dt_fe = FeatureEngineering_DateTime()#Fit
dt_fe.fit(df, datetime_variables=['date_issued'], 
          prefix = 'date_issued:')#Transform
df = dt_fe.transform(df)
df.head()

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

使用 Fast_ml 对日期时间变量进行特征工程。图片作者。

在屏幕截图中,所有的列都不可见。让我们只看数据集的列

df.columns---Output---
Index(['customer_id', 'disbursed_amount', 'interest', 'market', 'employment', 'time_employed', 'householder', 'income', 'date_issued', 'target', 'loan_purpose', 'number_open_accounts', 'date_last_payment', 'number_credit_lines_12',(Notice from here ------->)
'date_issued:year', 'date_issued:quarter', 'date_issued:month', 'date_issued:day', 'date_issued:day_of_week', 'date_issued:day_of_year', 'date_issued:weekofyear', 'date_issued:is_month_end', 'date_issued:is_month_start', 'date_issued:is_quarter_end', 'date_issued:is_quarter_start', 'date_issued:is_year_end', 'date_issued:is_year_start', 'date_issued:time', 'date_issued:hour', 'date_issued:minute', 'date_issued:second', 'date_issued:is_weekend', 'date_issued:day_part'],
dtype='object')

感谢阅读!!

笔记本可在以下位置获得,并附有完整的功能代码:

https://www.kaggle.com/nextbigwhat/feature-engineering-of-datetime-variables?scriptVersionId=61041780

用于人体活动识别的时间序列数据特征工程

原文:https://towardsdatascience.com/feature-engineering-on-time-series-data-transforming-signal-data-of-a-smartphone-accelerometer-for-72cbe34b8a60?source=collection_archive---------1-----------------------

转换智能手机加速度计的原始信号数据,并从中创建新的功能来识别六种常见的人类活动。

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

简·侯伯Unsplash 上拍照

目标

在出于研究兴趣探索人类活动识别领域时,我看到了一些出版物、研究文章和博客。研究人员在这一领域做了非凡的工作,并通过使用一些复杂的机器学习算法实现了最先进的(SOTA)结果。但是我读过的大多数论文/博客要么使用已经设计好的特征,要么没有详细解释如何从原始时间序列数据中提取特征。

在本文中,我们将探索不同的技术来转换原始时间序列数据,并从中提取新的特征。

我们将在本文中看到的技术不限于人类活动预测任务,而是可以扩展到任何涉及时间序列数据的领域。

关于数据

Smarphones 和智能手表包含三轴加速度计,可测量所有三个空间维度的加速度。这些加速度计能够检测设备的方向,这可以为活动识别提供有用的信息。

我们将在本次演示中使用的数据集来自纽约州布朗克斯福特汉姆大学计算机与信息科学系 WISDM 实验室(链接到数据集)。请注意,我们将使用的文件是原始数据文件— WISDM_ar_v1.1_raw.txt

这些数据是从 36 名不同的用户那里收集的,他们进行了一些常见的人类活动,如行走、慢跑、爬楼梯、下楼梯、坐着和站一段时间。在所有情况下,每 50 毫秒收集一次数据,即每秒 20 个样本。

共有 5 个特征变量——“用户”、“时间戳”、“x 轴”、“y 轴”和“z 轴”。目标变量是我们打算预测的“活动”。

“用户”表示用户 ID,“时间戳”是以纳秒为单位的 unix 时间戳,其余是在给定时间沿 x、y 和 z 轴/维度的加速度计读数。

这是原始数据集的一瞥—

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

如您所见,有超过 100 万行和 6 列。此外,数据需要清理和组织。

数据清理和预处理

我们根据观察结果执行以下步骤—

  • 删除空值。
  • 将“z 轴”列的数据类型更改为浮点型。
  • 删除时间戳为 0 的行。
  • 按照用户和时间戳的升序对数据进行排序。

这是我们的数据经过清理和分类后的样子—

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

如你所见,我们剩下 1085360 行。

探索性数据分析

分析类别标签分布—

sns.set_style(“whitegrid”)
plt.figure(figsize = (10, 5))
sns.countplot(x = ‘activity’, data = df)
plt.title(‘Number of samples by activity’)
plt.show()

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

正如你所看到的,这里有一个明显的类别不平衡,大多数样本的类别标签为“散步”和“慢跑”。站立和“坐着”活动在数据集中最少出现。

现在让我们看看用户是如何对每项活动做出贡献的。这将有助于我们决定如何分割数据用于训练和测试。

plt.figure(figsize = (18, 6))
sns.countplot(x = ‘user’, hue = ‘activity’, data = df)
plt.title(‘Activities by Users’)
plt.show()

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

可以看出,不是所有的用户都在执行所有的活动。他们进行每项活动的时间也各不相同。无论如何,这不会影响我们后续的分析,因为我们有足够多的数据样本,并且我们假设所有的用户都是一样的。

对于一个特定的用户,让我们观察在每个 x,yz 维度上的信号值如何随时间变化。

for i in [‘Walking’, ‘Jogging’, ‘Upstairs’, ‘Downstairs’, ‘Sitting’, ‘Standing’]:
  data_36 = df[(df[‘user’] == 36) & (df[‘activity’] == i)][:400]
  plt.figure(figsize = (15, 6))
  sns.lineplot(y = ‘x-axis’, x = ‘timestamp’, data = data_36)
  sns.lineplot(y = ‘y-axis’, x = ‘timestamp’, data = data_36)
  sns.lineplot(y = ‘z-axis’, x = ‘timestamp’, data = data_36)
  plt.legend([‘x-axis’, ‘y-axis’, ‘z-axis’])
  plt.ylabel(i)
  plt.title(i, fontsize = 15)
  plt.show()

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

我们考虑了 400 个样本的子集来可视化信号。这相当于 20 秒的活动(因为数据收集的频率是 20 Hz)。正如你所注意到的,信号显示了行走、慢跑、上楼和下楼等活动的周期性行为,而坐着和站着等静止活动的运动很少。

现在,让我们观察信号数据沿 x、yz 轴的活动分布,看看是否有任何基于值的范围和分布的明显模式。

sns.FacetGrid(df, hue = ‘activity’, size = 6).map(sns.distplot, ‘x-axis’).add_legend()

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

sns.FacetGrid(df, hue = ‘activity’, size = 6).map(sns.distplot, ‘y-axis’).add_legend()

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

sns.FacetGrid(df, hue = ‘activity’, size = 6).map(sns.distplot, ‘z-axis’).add_legend()

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

据观察,在像上楼、下楼、散步、慢跑和站在所有轴上这样的活动中,数据有非常高的重叠。坐着似乎在 y 轴和 z 轴上有独特的值。

这就把我们带到了文章的核心,那就是数据转换和特征工程。

数据转换

标准分类算法不能直接应用于原始时间序列数据。相反,我们必须首先使用“窗口”技术转换原始时间序列数据。在这种技术中,我们将数据划分为 5 秒的窗口,然后通过聚合这 5 秒时间段内包含的 100 个原始样本来生成新特征。为了根据变换后的特征分配类别标签,我们采用该窗口中最频繁的活动。

例如,假设一个原始数据集有 100 行顺序数据。所以在开窗和聚合(使用窗口大小= 50)之后,它将被转换为 2 行。为这 2 个新行分配的类别标签将是相应窗口中最频繁的活动。同样,对于 100 万行,我们将在转换后的集合中获得将近总共 20k 行。

您一定想知道为什么选择 5 秒的窗口。在查阅了一些文献后,我觉得这可能是我们可以考虑的最佳窗口大小,用于捕捉六种活动中大多数活动所涉及的重复运动。太小的窗口尺寸可能不能正确地捕捉运动,而太大的窗口尺寸导致用于训练的变换数据集中的数据点更少。

这里我们还可以做一件事——我们采用 50%重叠的重叠窗口,而不是离散窗口。这确保了转换后的数据集中的每个后续行也具有来自前一个窗口中的数据的一些信息。

所有这些特征一开始可能听起来有点令人生畏,但是相信我,它并没有那么复杂。慢慢地再读一遍这一部分,因为如果你很好地理解了这一点,后面的部分将会很容易。我在这里附上这张图片,它将帮助您清楚地了解原始信号数据是如何聚合并转换为新功能的。

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

左:原始数据集右:转换数据集|作者的图像

特征工程

在我们开始设计新功能之前,我们必须首先将数据分为训练和测试。通常我们倾向于进行随机拆分,但是在这个特定的场景中,按照用户 ID 进行拆分更有意义。

因此,在总共 36 个用户中,前 27 个用户的数据将形成我们的训练数据,而其余 9 个用户将包括在我们的测试数据中。

# train data -> Users upto User ID = 27 (i.e. 27 users)
df_train = df[df[‘user’] <= 27]# test data -> Users from User ID = 28 to 36 (i.e. 9 users)
df_test = df[df[‘user’] > 27]

通过这样做,我们在训练集中获得了大约 804358 个数据样本,在测试集中获得了 281002 个样本。这就像做 75-25 分割,但方式更复杂。

特征工程阶段 1:统计测量

在特征工程的第 1 阶段,我们将构建总共 18 个简单的统计特征—
1。意思是
2。标准差
3。平均绝对偏差
4。最小值
5。最大值
6。最大值和最小值之差
7。中位数
8。中位数绝对偏差
9。四分位距
10。负值计数
11。正值计数
12。以上数值的数量表示
13。峰值数量
14。偏斜度
15。峰度
16。能源
17。平均合成加速度
18。信号幅度区域

这些特性中的大多数都是不言自明的。

  • 每个轴上信号的能量 通过取该特定轴上窗口中值的平方和的平均值来计算。
  • 窗口上的平均合成加速度通过取三个轴的平方值的平方根的平均值并相加计算得出。
  • 信号幅度面积定义为一个窗口内三个轴的绝对值之和。

下面的 python 代码将更加清晰地给出上述每个特性的数学公式。

x_list、y_list 和 z_list 中的每一个实际上都是窗口的列表。每个窗口由 100 个观察值组成。因此总共应该有 int(804358/50) -1 = 16086 个窗口(您可以从代码中验证这一点)。 X_train 是我们根据转换后的特征构建的新特征数据框架。从今以后,我们将使用这个新的数据框架,并逐步增加新的特征,最终用它来训练 ML 模型。

特征工程阶段 2:快速傅立叶变换(FFT)

傅立叶变换是将时域信号变换到频域的函数。该函数接受时间信号作为输入,并产生信号的频率表示作为输出。现实世界中的每个信号都是时间信号,由许多不同频率的正弦波组成。

傅立叶变换不会改变信号。它只是提供了一个不同的角度来分析您的时间信号,因为信号的一些属性和特征可以在频域中充分探索。

到目前为止,我们一直在处理时间域。让我们从数据中选取任意一个随机窗口,观察它的离散傅立叶变换——

pd.Series(np.fft.fft(pd.Series(x_list)[42])).plot()
plt.show()

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

一些观察—

  • 第一个值异常高。在电气术语中,这被称为“DC 分量”或“DC 偏移”。
  • 波信号关于中心对称。

这些观察结果并不是这个特定窗口所特有的,但是如果你从我们的时域数据中选取任何一个窗口,并在其上应用 FFT,你会得到相同的观察结果。

不要太在意 DC 分量,把它想成一个我们将要丢弃的异常高的值。我们也将只考虑信号的前半部分。这将确保我们从中获得无偏的统计特征。

就像第一阶段一样,在第二阶段,我们将通过聚集傅立叶变换的数据来构建新的特征

到特征工程的前两个阶段结束时,我们现在总共有 94 个特征!这就把我们带到了特征工程的第三阶段。

特征工程阶段 3:捕获索引

在任何机器学习问题中,特征工程阶段的主要目标是为模型提供尽可能多的信息。你提供的信息越多,它学得越好!

那么在这种情况下,为什么不把底层数据的索引值作为潜在的特征呢?

同样,按照上述步骤转换原始测试数据帧 df_test 和从中提取特征,以构建转换后的测试数据集,即 X_test 。为了简洁起见,我在文章中跳过了这一部分。新的 X_test 数据集将具有 int(281002/50)-1 = 5619 行(您可以在自己的终端验证这一点)。

这就把我们带到了本文的最后一节。既然我们已经生成了如此多的特征,是时候看看这些新手工制作的特征能在多大程度上预测人类活动了。

实现用于活动预测的线性模型

对于预测任务,我们将在转换后的训练数据上训练简单的逻辑回归模型,然后评估转换后的测试数据的性能。其思想是,逻辑回归是一个线性分类器,它严重依赖于特征的质量,以便给出好的结果。功能提供的独特信息越多,性能就越好。因此,如果我们能够使用逻辑回归获得更好的性能,那么我们可以说我们已经成功地创建了正确的特征集。

逻辑回归模型

y_train = np.array(train_labels)
y_test = np.array(test_labels)

对于 logistic 回归,建议先将数据标准化。

from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report# standardization
scaler = StandardScaler()
scaler.fit(X_train)
X_train_data_lr = scaler.transform(X_train)
X_test_data_lr = scaler.transform(X_test)# logistic regression model
lr = LogisticRegression(random_state = 21)
lr.fit(X_train_data_lr, y_train)
y_pred = lr.predict(X_test_data_lr)
print("Accuracy:", accuracy_score(y_test, y_pred))
print("\n -------------Classification Report-------------\n")
print(classification_report(y_test, y_pred))

输出—

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

通过对工程特征使用基线逻辑回归模型,我们成功地获得了 84.53 %的测试数据的总体准确度。考虑到我们在开始时只有原始加速度计数据的 3 个特征,这是相当不错的。通过使用一些复杂的分类模型,如基于树的集成、投票或堆叠分类器,在准确性和其他性能指标方面还有改进的余地。

从分类报告中可以看出,大多数活动的总体表现相当不错。尽管在识别这两种爬楼梯活动时有些困难。这是意料之中的,因为这两个活动非常相似。让我们检查一下混淆矩阵。

labels = [‘Downstairs’, ‘Jogging’, ‘Sitting’, ‘Standing’, ‘Upstairs’, ‘Walking’]
confusion_matrix = confusion_matrix(y_test, y_pred)
sns.heatmap(confusion_matrix, xticklabels=labels, yticklabels=labels, annot=True,linewidths = 0.1, fmt=”d”, cmap = ‘YlGnBu’)
plt.title(“Confusion matrix”, fontsize = 15)
plt.ylabel(‘True label’)
plt.xlabel(‘Predicted label’)
plt.show()

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

从分类报告和混淆矩阵可以看出,我们的数据集中最常见的两个类别慢跑步行被正确识别,具有良好的准确性。虽然很少有类的样本,但我们仍然可以很好地识别这些活动,因为这两种活动会导致设备改变方向,这很容易从加速度计数据中检测到。为了更准确地区分楼上的和楼下的活动,现有的一组特征是不够的。通过将三轴加速度计数据与三轴陀螺仪(智能设备中的另一种惯性传感器)的数据相结合,可以区分这些类别,并以更高的精度识别其他活动。**

结束注释

我们从 3 个特征开始——三轴加速度计信号在 xyz 轴上的读数。我们从原始数据中逐步设计特征,最终,我们成功提取了总共 112 个独特的特征!后来我们训练了一个简单的线性分类器并评估了它的性能。

正如你可能已经意识到的,为了形成这些新的特征,我们依赖于统计学和数学的基本概念。没有使用高端信号处理或先进技术。此外,我们在本文中使用的数据准备和特征工程技术是通用的,可以应用于大多数涉及时间序列数据的问题。

参考

  • 詹妮弗·r·夸皮什、加里·m·韦斯和塞缪尔·a·摩尔(2010 年)。使用手机加速度计的活动识别,第四届传感器数据知识发现国际研讨会会议录(KDD-10),华盛顿州 DC。
  • 达维德·安吉塔、亚历山德罗·基奥、卢卡·奥内托、哈维尔·帕拉和豪尔赫·雷耶斯-奥尔蒂斯。使用智能手机进行人类活动识别的公共领域数据集。第 21 届欧洲人工神经网络、计算智能和机器学习研讨会,ESANN 2013。

【免责声明:本文使用的所有图片均为作者所有,除非明确提及】

内容概要:本文围绕无人机自主水下传感网络(UASNs)中自主水下航行器(AUV)的路径规划问题展开研究,提出采用遗传算法(Genetic Algorithm, GA)进行优化求解,并通过Matlab代码实现仿真验证。研究重点在于利用遗传算法的全局搜索能力,解决水下复杂环境中AUV的高效路径规划问题,提升数据采集效率与网络性能。文中详细阐述了问题建模、适应度函数设计、约束条件处理及算法实现流程,展示了GA在应对多目标、非线性、动态变化水下环境中的可行性与有效性。同时,文档还列举了大量相关科研方向与Matlab仿真实例,涵盖路径规划、电力系统、机器学习、通信优化等多个领域,体现出较强的技术综合性与科研指【UASNs、AUV】无人机自主水下传感网络中遗传算法的路径规划问题研究(Matlab代码实现)导价值。; 适合人群:具备一定Matlab编程基础,从事智能优化算法、路径规划、水下传感网络或相关领域研究的研究生、科研人员及工程技术人员,尤其适合正在开展无人机、AUV或智能优化应用研究的1-5年经验研究人员。; 使用场景及目标:①学习遗传算法在复杂路径规划问题中的建模与实现方法;②掌握Matlab在UASNs与AUV路径规划中的仿真技术;③借鉴多领域科研案例拓展研究思路,推动算法在实际水下探测、环境监测、军事侦察等场景的应用。; 阅读建议:建议结合提供的Matlab代码进行实践操作,重点关注遗传算法的编码方式、交叉变异策略与适应度函数设计;同时可参考文中列出的其他研究方向进行横向拓展,强化对智能优化算法在多学科交叉应用的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值