TowardsDataScience 2023 博客中文翻译(一百七十六)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

如何迭代一个 Pandas Dataframe

原文:towardsdatascience.com/how-to-iterate-over-a-pandas-dataframe-5dc15ab147f9

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

照片由Sid Balachandran拍摄,来源于Unsplash

行优先与列优先,Pandas 最佳实践

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

·发表于Towards Data Science ·4 分钟阅读·2023 年 5 月 18 日

如果你有一些数据科学的经验,你肯定遇到过从表格数据中开发算法的情况,这类常见挑战的例子有Titanic — 从灾难中学习机器学习或波士顿房价数据。

以表格形式表示的数据(如 CSV 文件)可以分为行优先格式列优先格式。在计算中,行优先顺序和列优先顺序是存储多维数组的线性存储方法,如随机存取内存。根据格式设计的范式,有最佳实践可遵循,以优化文件的读写时间。数据科学家经常不幸地以错误的方式使用诸如 pandas 之类的库,从而浪费宝贵的时间

行优先格式意味着在表中,连续的行在内存中被连续保存。因此,如果我正在读取第 i 行,那么访问第 i+1 行将是一个非常快速的操作。

遵循列优先格式范式的格式,如 Parquet,会在内存中连续保存列。

在机器学习中,我们经常遇到行代表数据样本,列代表特征的情况。因此,如果我们需要快速访问样本,我们将使用 CSV 文件,如果我们经常需要访问特征(例如计算统计等),我们将使用 Parquet。

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

src: en.wikipedia.org/wiki/Row-_and_column-major_order#/media/File:Row_and_column_major_order.svg

Pandas

Pandas 是一个在数据科学中广泛使用的库,尤其是在处理表格数据时。Pandas 基于 DataFrame 的概念,即数据的表格表示。虽然 DataFrame 遵循列优先格式范式。

所以按行迭代 DataFrame,像通常做的那样,是非常慢的。让我们看一个例子,让我们导入 BostonHousing DataFrame 并进行迭代。

import pandas as pd
import time
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/BostonHousing.csv')
df.head()

在第一次实验中,我们迭代 DataFrame 的列(df.columns),然后访问每列中的所有元素,并计算完成该过程所需的时间。

#iterating df by column
start = time.time()
for col in df.columns:
  for item in df[col]:
    pass
print(time.time() -start , " seconds")

#OUTPUT: 0.0021004676818847656  seconds

而在第二次实验中,我们使用 df.iloc 函数按行迭代 DataFrame,该函数返回整行的内容。

#iterating df by row
n_rows = len(df)
start = time.time()
for i in range(n_rows):
  for item in df.iloc[i]:
    pass
print(time.time() -start , " seconds")

#OUTPUT : 0.059470415115356445  seconds

正如你所看到的,第二次实验的结果远大于第一次。在这种情况下,我们的数据集非常小,但如果你用自己的更大数据集进行尝试,你会注意到这种差异会变得越来越明显。

Numpy

幸运的是,numpy 库来拯救我们。当我们使用 numpy 时,我们可以指定我们想要使用的主要顺序,默认情况下使用的是行优先顺序。

所以我们可以做的是将 pandas DataFrame 转换为 numpy,然后逐行迭代。让我们看一些实验。

我们首先将 DataFrame 转换为 numpy 格式。

df_np = df.to_numpy()
n_rows, n_cols = df_np.shape

现在让我们按列迭代数据,并计算时间。

#iterating numpy by columns
start = time.time()
for j in range(n_cols):
  for item in df_np[:,j]:
    pass
print(time.time() -start, " seconds")

#OUTPUT : 0.002185821533203125  seconds

现在按行迭代同样的操作。

#iterating numpy by row
start = time.time()
for i in range(n_rows):
  for item in df_np[i]:
    pass
print(time.time() -start, " seconds")

#OUTPUT : 0.0023500919342041016  seconds

我们看到使用 numpy 时两个实验的速度都提高了!而且,两者之间的差异很小。

终极思考

在这篇文章中,我们介绍了处理表格数据时行优先和列优先范式的差异。我们指出了许多数据科学家使用 Pandas 时的一个常见错误。在这种情况下,访问数据的时间差异很小,因为我们使用了一个小数据集。但你必须小心,因为数据集越大,这种差异也会变大,你可能会浪费很多时间仅仅在读取数据上。作为解决方案,尽量在可能的情况下使用 numpy。

关注我以获取更多类似文章!😉

结束

马切洛·波利蒂

LinkedinTwitterWebsite

如何使用多功能数据工具(Versatile Data Kit)跟踪数据版本

原文:towardsdatascience.com/how-to-keep-track-of-data-versions-using-versatile-data-kit-f1916f18737e?source=collection_archive---------9-----------------------#2023-05-03

数据工程

学习关于慢变维度(SCD)以及如何在 VDK 中实现 SCD Type 2

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

·

关注 发表在Towards Data Science ·7 分钟阅读·2023 年 5 月 3 日

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

照片由Joshua SortinoUnsplash拍摄

数据是任何组织的支柱,在当今快节奏的世界中,跟踪数据版本至关重要。随着企业的成长和发展,数据经历了许多变化,如果没有流畅的系统,这些变化很快就会变得令人不知所措。技术通过各种工具来帮助我们有效地管理数据。

其中一个工具是 Versatile Data Kit (VDK),它为控制数据版本需求提供了全面解决方案。VDK 可帮助您轻松执行复杂操作,例如使用 SQL 或 Python 从不同来源进行数据摄取和处理。您可以使用 VDK 构建 数据湖 并摄取从不同来源提取的原始数据,包括结构化、半结构化和非结构化数据。

在本文中,我们将探讨 VDK 如何通过提供直观界面和强大功能来简化您的生活,以跟踪对关键业务信息所做的所有更改。

我们将涵盖以下主题:

  • 什么是缓慢变化的维度(SCD)?

  • SCD 类型

  • 如何在 VDK 中实现 SCD 类型 2。

图片注意*:所有图片均为作者所有,除非另有明确说明。*

什么是缓慢变化的维度(SCD)?

在数据仓库中,维度 是一种结构,用于分类事实和度量,以便用户回答业务问题。常用的维度有人员、产品、地点和时间。

缓慢变化的维度(SCD)帮助您跟踪维度数据随时间的变化。它们在数据仓库中存储和管理当前和历史数据。缓慢 意味着它们随时间变化较慢而不是定期变化。SCD 的例子包括地址、电子邮件、工资等。

SCD 对于跟踪数据随时间变化非常重要。我们可以使用它们来跟踪客户、产品或其他可能随时间变化的信息。

使用 SCD 可以更轻松地跟踪数据变更并保留数据如何变化的历史记录。这对分析趋势或回答关于特定数据如何演变的问题非常有价值。

SCD 类型

有三种类型的 SCD:类型 1、类型 2 和类型 3。为了说明每种 SCD 类型的工作原理,我们使用以下示例。考虑以下客户维度表:

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

图 1 — 示例中的客户维度表

如果 John Smith 把他的电话号码改成 555-5668,会发生什么?

SCD 类型 1

这种 SCD 类型不追踪数据变更;新数据会覆盖旧数据。当数据历史不重要且需要了解当前数据状态时,这种类型是合适的。类型 1 是最简单和最常见的 SCD 类型。

考虑图 1 中的示例。在 SCD 类型 1 中,新电话号码替换了旧电话号码,而且没有记录之前的电话号码,如下表所示。

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

图 2 — 应用 SCD 类型 1 后的客户维度表

SCD 类型 2

这种类型通过向维度表添加新记录来跟踪历史更改。旧数据仍然可用,但被新数据标记为废弃。每条记录包含唯一标识符、开始日期和结束日期。

再考虑图 1 中的示例。在 SCD 类型 2 中,创建一个新的记录,包含新的电话号码、唯一标识符和开始日期,同时前一个记录有一个结束日期。开始日期表示新记录生效的日期,结束日期表示旧记录过时的日期。

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

图 3— 应用 SCD 类型 2 后的客户维度表

SCD 类型 3

这种类型通过向维度表中添加一个列以保存新值,仅跟踪最新的更改。当跟踪完整的更改历史记录不是必要时,使用此类型。

再考虑图 1 中的示例。在 SCD 类型 3 中,记录被更新为两个新列:new_phone_number 用于保存新值,effective_date

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

图 4— 应用 SCD 类型 3 后的客户维度表

如何在 VDK 中实现 SCD 类型 2

VDK 是由 VMware 作为开源发布的一个非常强大的框架。使用 VDK 构建数据湖并合并多个数据源。如果你是 VDK 的新手,可以阅读其 官方文档 或这篇 介绍文章。

VDK 支持 SCD 类型 1 和类型 2。要在 VDK 中实现 SCD,请使用 SQL 处理模板。SQL 处理模板是数据加载模板,是 VDK 提供的一个概念结构。根据 VDK 官方文档,

数据加载模板从位于源模式的 source_view 中提取数据,并将源数据加载到位于目标模式的 target_table 中(摘自 VDK 官方文档)。

实际操作中,模板简化了从源中提取数据并加载到目标表中的过程。VDK 提供了适用于 Impala 和 Trino 数据库的 SQL 数据处理模板。

为了说明 VDK 如何管理 SCD 类型 2,请考虑以下场景。

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

图 5 — 如何使用 VDK 管理 SCD 类型 2

从左开始,有 数据源(例如图 1 中的客户维度表),必须定义一个源模式和源视图。VDK数据源 中摄取数据。为了管理 SCD 类型 2,VDK 使用 SCD2 模板,这是一个 SQL 处理模板。通过 vdk-trino 插件,VDK 使用 Trino DB 将数据存储到 数据湖 中。数据湖 必须包含 目标模式,即存储 SCD 类型 2 的模式。

VDK 实现了 SCD2 模板 作为 Input Job 的附加方法。以下代码展示了如何使用 SCD2 模板

def run(job_input: IJobInput) -> None:
    # ...
    job_input.execute_template(
        template_name='scd2',
        template_args={
            'source_schema': 'customer_schema',
            'source_view': 'customer_view',
            'target_schema': 'customer_target_schema',
            'target_table': 'customer_target_table',
            'id_column': 'customer_id',
            'sk_column': 'SID',
            'value_columns': ['name', 'address', 'phone_number'],
            'tracked_columns': ['phone_number'],
        },
    )

代码直接摘自VDK 文档,并根据图 3 中的示例进行了调整,因此请参阅它以获取更多详细信息。实际上,该模板将源和目标模式作为输入,以及其他参数,例如列 ID 和要跟踪的列。

多亏了 VDK,你可以轻松管理数据库中的 SCD!有关完整而详细的示例,请参阅VDK 文档

为了解释 SCD2 模板的工作原理,请再次考虑客户维度表。之前的代码仅跟踪phone_number列,因此如果该列发生变化,系统会将更改存储在新行中,如下图所示:

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

图 6——如果跟踪的列发生变化,系统会将其存储为新行。

然而,如果未跟踪的列发生变化,系统会覆盖它,如下图所示:

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

图 7——如果未跟踪的列发生变化,系统会覆盖它。

总结

恭喜!你刚刚了解了 SCD 是什么以及如何在 VDK 中实现它。

SCD 对希望有效管理和分析数据的组织非常重要。通过识别数据集中哪些属性很少或不经常变化,你可以简化数据处理和存储,减少分析中错误或不一致的可能性。

要轻松识别和管理 SCD,你可以使用 VDK,它帮助你自动化慢变属性的变化。

总体而言,SCD 在大数据管理的宏观框架中可能看起来是一个微小的细节。但它可以显著影响分析过程的准确性和效率。通过利用像 VDK 这样的工具,你可以保持领先并最大化数据资产的价值。

你可能还感兴趣……

有许多相关主题可能会引起你的兴趣:

如何配置 VDK 与 Trino DB 一起使用

使用完整示例,展示了如何使用 Versatile Data Kit 和 Trino DB。

如何使用 VDK 构建 Web 应用

逐步教程,讲解如何构建 Web 应用,结合 Streamlit Python 库和 Versatile Data Kit。

如何使用 VDK 插件

逐步教程,演示如何通过编写 VDK 自定义插件来操作数据湖中的表。

如何处理缺失值

教程,讲解如何使用 VDK 构建数据管道以处理缺失值

只再说一词……

不要忘记加入 VDK Slack 频道,以获取关于 VDK 的最新信息!

如何在 2023 年学习地理空间数据科学

原文:towardsdatascience.com/how-to-learn-geospatial-data-science-in-2023-441d8386284e?source=collection_archive---------1-----------------------#2023-02-21

对于那些想要学习使用 Python 进行地理空间数据分析的步骤指南

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

·

关注 发表在 Towards Data Science ·11 分钟阅读·2023 年 2 月 21 日

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

使用 Dall-E 2 创建的数字图像。说明:一名科学家手持地球的照片。

介绍

为什么这个话题很重要?众所周知,数据科学职业如今需求量很大。当你将地理空间分析的维度加进去时,可能性变得更加令人兴奋。气候变化、食品生产以及向零碳经济的过渡只是需要深入理解地理空间数据的众多重要问题中的几个。通过结合卫星和无人机图像、矢量数据集以及实地测量,我们可以获得更深刻的见解,并推动有意义的变革。

虽然有很多资源可以用于学习使用 Python 进行地理空间数据分析,但这个领域正在快速发展。在过去,我管理了一个 GIS 团队,我们在水资源映射和水文学分析中严重依赖 ArcGIS 或 ENVI 等软件。然而,我与使用 Python 进行地理空间分析的旅程始于 2019 年,当时我开始了我的博士学习。

本周我偶然发现了《Python Geospatial Development》这本书。起初,我认为这将是提升技能的绝佳机会。然而,在查看了目录后,我感到很惊讶。除了 GDAL(我在开始时简要使用过,但很快被 Rasterio 取代)外,我几乎没有使用第三章——地理空间开发的 Python 库中讨论的任何 Python 库。这种差异可以归因于这本书首次出版于 2010 年,且在 2013 年和 2016 年仅进行了小幅更新。在计算机科学的世界里,那已经是很久的时间了。

尽管由于其驱动程序的原因仍然需要安装 GDAL,但其 Python 绑定已经不再必要,并且使用起来可能会令人困惑(姑且这么说)。此外,我从未听说过如 Mapnik 这样的其他库。此外,像 GeoPandas 或 XArray 这样的基本包在书中甚至没有提及。最后,Google Earth Engine(这一领域的真正变革者)在书籍出版时甚至尚不存在,这突显了实际开发书籍的一个常见问题——它们很快会变得过时。

嗯,我并不是反对书籍。书籍仍然对构建特定学科的坚实基础至关重要。然而,要成为一名实用的地理空间分析师,学习如何在大量在线信息中导航并理解这些信息至关重要,因为对于新手来说,这些信息可能会让人感到不知所措。

考虑到这一点,本文是为那些希望在 2023 年学习使用 Python 进行地理空间数据分析的人编写的,提供了有关主要技能和主题的快速指南,并给出了一些如何有效导航大量在线信息和避免某些陷阱的建议。请注意,这份指南基于我自己的经验,可能并不完全符合每个人的期望。

避免陷阱

在开始之前,你需要注意一些陷阱。我列出了四个需要注意的陷阱,但我相信在你的学习过程中还会遇到更多:

1- 信息过载: 地理空间数据科学的世界广阔,知道从哪里开始可能会很具挑战性。如果你开始搜索互联网,你会被大量的信息、文章和课程所吓倒。我知道这令人不知所措。突然间,你发现自己只是从一个网站跳到另一个网站,整整一天过去了却没有实际学到任何东西。为了避免感到畏惧,专注于一个主题一次,并避免干扰。使用你喜欢的方法:番茄工作法、Flowtime,或 Deepwork。没关系,只要你保持专注!

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

照片由 Usman Yousaf 提供,来源于 Unsplash

2- 过时的资源: 这个问题与我在介绍中提到的内容相关……如果你得到一个过时的资源,你可能只是浪费时间,毫无进展。甚至更糟,你可能会回到……过去!

注意: 如果你在学习一些基础知识如统计学或物理学,这点可能不太相关,但如果你涉及某些技术方面,它可能会起到重要作用。

3- 尊重你的学习曲线: 我开始时遇到的第三个问题是,我试图解决一些高级话题,例如创建一个云中的虚拟机来托管地图服务器,但甚至不了解 Docker 或 Git 是什么。结果,我花了很多时间去解决超出我能力范围的问题。例如,如今,当我想发布一张地图时,我只需将 COG(云优化的 Geotiff)直接发布到 Github 上(例如,cordmaur.github.io/Fastai2-Medium/occurrence_map.html),无需设置地图服务器等繁琐操作。但我只有在研究该主题一段时间后才知道 COG 的存在。

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

图 1: 直接托管在 Github 上的 COG 文件。图片由作者提供。

4- 不要试图从头到尾理解一切: 在这里,我们必须使用一些推理。掌握主要话题并迅速补充任何可能缺失的重要概念是至关重要的。但你应该做到这一点,及时地。例如,假设你正在运行一个在过程中使用导数的机器学习模型。如果你像我一样,你会被诱惑去寻找最好的微积分课程,即使你在大学里已经学过两年。请不要陷入这个陷阱;深入理解所有潜在主题是不可能的。相反,进行快速回顾,以保持进度。

如何开始

如前所述,掌握地理空间数据科学所需的一切可能会让人感到不知所措,并且需要时间。如果你试图按照“正确”的顺序学习所有内容,你可能会感到气馁并放弃。在这方面,我同意 fast.ai 的 Jeremy Howard 的观点,他建议采取自上而下的方法。这样,即使你不完全理解所有的底层内容,也可以看到有意义的结果。

所以这是我如果从头开始并尽快学习的话,会考虑的“模糊”顺序。

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

使用 Dall-E 2 创建的数字图像。标题:一只泰迪熊爬楼梯的照片,背景是地球。

1- 基础 Python 编程

这是一个至关重要的主题。如果没有它,学习矢量数据集或栅格数据集等内容将毫无意义,因为一切都会显得抽象,你也没有工具去探索它。我知道你可以使用 QGIS 或其他 GIS 软件。但这与将原始数据导入到 numpy 数组或 geojson 文件并自己探索是不同的。此外,首先学习 Python 编程可以打开你以前没有想象过的其他门。

注意: 请记住,在开始时,你不会编写程序。你只是依赖第三方库来进行分析。因此,此时不建议使用为程序员设计的资源。你可以阅读“如何正确学习 Python 数据科学”来理解其中的区别。

因此,为了学习最基本的内容,我建议选择像 Codecademy 的‘学习 Python 3’这样的课程。该课程只需 25 小时即可完成,时间不足一周,并且提供了对语言的快速概述。此外,我在我的 YouTube 频道上发布了四节名为‘科学家 Python 入门’的课程,这也可以是一个很好的主题入门。

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

使用 Dall-E 2 创建的数字图像。标题:一个小孩在老式计算机上编程的铅笔画。

之后,我建议学习 Jake VanderPlas 编写的《Python 数据科学手册》,可以在作者的 GitHub 上免费获取(jakevdp.github.io/PythonDataScienceHandbook/)。这本书并不专注于讲解 Python 语言的内部工作,如创建复杂函数、定义类、继承或其他面向对象的方面。相反,它提供了对主要库的快速概述,如 numpypandasmatplotlib,这些都是数据分析中必不可少的工具。

2- GEE 和 GIS 基础

现在你已经对 Python 及其主要的数据分析库有了基本了解,是时候开始接触一些 GIS 概念了。参加一个通用的 GIS 课程可能会让你被关于卫星数据收集、大气中的光路径以及这些如何影响传感器读数的信息轰炸。虽然这些主题对于研究很重要,但对于地理空间数据分析的实际入门可能并不必要。

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

照片来自于Krzysztof HepnerUnsplash

从实际角度出发,我建议通过一个使用 Python 的Google Earth Engine实践课程来学习 GIS 基础知识。这样,你将练习 Python 并可以快速访问地理空间数据(包括矢量数据和栅格数据),而无需担心下载或设置复杂的环境。你将立即开始进行首次空间分析。

这样的课程可以在Udemy上找到:Google Earth Engine Python API 中的空间数据分析完整的 Google Earth Engine Python API & Colab 培训营。另一个选择是参加一个完整的 GEE 课程,该课程将使用 JavaScript 环境,但一切可以通过 Python 进行复制,语法仅需稍作调整。

3- 地理空间 Python 库

Google Earth Engine (GEE) 功能强大,提供大量现成的数据,但也有一些缺点。一切都必须在 Google 云端运行。虽然它提供免费访问其资源,但对于大规模处理可能会产生费用。因此,理想的解决方案是使用开源 Python 库来处理来自任何来源的数据。主要库包括:

  • rasterio:用于读取栅格数据并将其加载到数组中。

  • geopandas:类似于 pandas,但具有用于矢量数据的空间字段。

  • xarray:类似于 numpy,但支持坐标和尺度。

  • shapely:用于矢量处理、剪切、交集等。

  • fiona:用于读取标准的 shapefiles。

  • leafmap:用于动态地图可视化。

4- 项目和 Python 环境管理

假设你在没有 Python 编程基础的情况下达到了这一点。在这种情况下,你可能有一个你不完全理解的混乱工作环境,以及一堆不相关的 Jupyter notebooks,使得很难找到你上周发现的重要代码片段。如果你处于类似情况,不要惊慌!每个新手都会遇到这种情况。现在是时候退一步整理你的工作环境了。为此,你需要了解:

  • 包管理工具如 Pip 和 Conda 的重要性。你还可以探索 Miniconda 和 Mamba,以获得更快的性能;

  • 如何为你的 Jupyter notebooks 创建一个内核;

  • 如何使用 Git 控制你的工作版本并通过 GitHub 进行备份。

5- 深入了解 Python 编程

到现在为止,你可能一直在使用 Jupyter notebooks 进行实验。它是一个出色的数据探索和分析工具,但不要指望用它创建一个完全功能的软件(除非你采用了 nbdev)。此外,编写一个执行特定分析的 notebook 与编写一个将部署到服务器上的完全操作的软件是不同的。我在之前的一篇文章 “为什么数据科学家应该适度使用 Jupyter Notebooks” 中讨论了这个问题。

基本上,你需要一些 IDE(如 PyCharm 或 VSCode)来开发函数、类和包。Jupyter notebooks 将用于调用你创建的内容并展示结果。记住列表中的第一个项目,当我提到不要使用针对程序员的 Python 资源时?现在是时候提升你的编程技能了。

6- 高级话题(天空是极限)

接下来,你会很快意识到地理空间分析中的许多任务是易于扩展的,这取决于可用的数据量和处理能力。然而,要进行扩展,你需要了解如何部署具有更多资源的云服务器以及如何进行分布式计算。在这些情况下,了解新技术如以下内容很重要:

  • Dask 库:Dask 是一个用于分布式计算的 Python 库。它可以帮助你处理那些无法完全装入基础内存的大量数据。

  • Docker:Docker 允许你构建、打包和部署作为容器的环境和应用。这些容器可以部署到云服务器上,以提高效率和可扩展性。

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

使用 Dall-E 2 创建的数字图像。标题:牛仔骑着火箭飞往月球

7- 数据科学中的数学和统计

你确定吗?你可能会认为这不是一切的基础?其实,这个话题与陷阱 #4 紧密相关。如果你有良好的数学基础,你应该只挑选那些你真正遇到问题的主题,准确地说。为此,Khan Academy (en.khanacademy.org) 是一个很棒的免费资源,讲座被分成了大约 10 分钟的短视频。

如果你认为你的问题仅在于统计学,你可以考虑 David Forsyth 编写的《计算机科学的概率与统计》这本书,由 Springer 出版。

另一方面,如果你没有扎实的数学基础,应该考虑购买一个专注于数据科学数学的课程。在 CodeAcademy(数据科学基础数学)或 Udemy(数据科学、数据分析和机器学习数学)等平台上有很多这样的课程。这些课程价格不贵,并且可以给你一个良好的概述。

结论

总结来说,我相信地理空间数据科学是我们时代最激动人心和重要的领域之一。通过将 Python 的强大功能与丰富的地理空间数据结合起来,我们有潜力在气候变化、食品生产和公共健康等领域推动有影响的变化。然而,要成为这一领域的熟练从业者,专注于正确的主题和工具非常重要。根据我的经验,这意味着要涵盖以下步骤:

1- 基础 Python 编程

2- GEE 和 GIS 基础

3- 地理空间 Python 库

4- 项目管理和 Python 环境

5- Python 编程深入探讨

6- 高级主题(天高地阔)

7- 数据科学中的数学和统计

在这段旅程中,你还应该注意那些可能会拖慢你进度的常见陷阱和误区。拥有这些技能和资源,我相信任何人都可以学习地理空间数据科学,并在世界上产生真正的影响。

保持联系

如果你喜欢这篇文章,考虑成为一个 Medium 会员 ,解锁像这样的数千篇文章。费用仅为每月 $5。

[## 使用我的推荐链接加入 Medium - Maurício Cordeiro

阅读 Maurício Cordeiro(以及 Medium 上其他成千上万位作者)的每个故事。你的会员费用直接…

cordmaur.medium.com](http://cordmaur.medium.com/membership?source=post_page-----441d8386284e--------------------------------)

如何通过向这些专业人士学习来提升你的 Python 技能

原文:towardsdatascience.com/how-to-level-up-your-python-skills-by-learning-from-these-professionals-3e906b83f355

防止停留在 Python 编程的初级水平

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

·发布于 Towards Data Science ·7 分钟阅读·2023 年 3 月 9 日

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

照片由 Austin Distel 提供,来源于 Unsplash

免责声明:我与本文中提到的任何课程或个人没有关联,也未受到任何组织或个人的经济支持。

互联网上充满了各种 Python 学习课程和资料。其中最著名的有 100 Days of Code: The Complete Python Pro Bootcamp for 2023, codeacademyfreeCodeCamp 然而,完成其中一个(或多个)课程后,很多人会停留在同一水平:初级 Python 开发者水平。

在欧洲,2023 年 3 月 4 日,LinkedIn 上中级/高级 Python 开发者职位的招聘数量几乎是初级 Python 开发者职位的两倍(分别为 23,73912,720)。

许多想学习 Python 的人即使经过多年的编程,也停留在初级水平的原因是,在达到可以自己编程的水平后,你需要继续学习新的方面和理论。简单来说,有三个与提升编程水平相关的原则,你需要应用其中至少两个才能显著提高代码质量。

  1. 自己练习编程。

  2. 从与更有经验的开发人员合作的项目中学习。

  3. 通过积极寻找更高级的编程概念并将其应用于工作相关或个人项目,保持自我学习。

第一个原则是不可避免的。当然,就像你不能通过阅读理论来学习网球的最佳击球点一样,你也不能仅仅通过阅读和观看内容来学习编程。如果你有涉及编程的工作,这就很简单,因为你的老板期望你编程。如果你只是个人编程,你可能需要主动寻找项目来参与。幸运的是,有许多网站提供编程项目,例如:

Advent of Code: 这里你可以找到近 200 个编程挑战,从初学者到专家。

Kaggle: 一个面向数据科学家的在线社区,提供许多数据集供练习和参与竞赛。

或者可以查看Insane,那里建议了 70 多个 Python 项目,附有代码解决方案和解释,有些甚至包括教程!

除了自己积极编程外,最终要超越初级水平,还需要至少遵循第二和第三个原则之一。然而,第二个原则(与更有经验的开发人员合作)更难实现,因为你对它的影响较小。我曾在一个数据科学团队中是最有经验的 Python 开发者,但我自己仍然是初级开发者,我发现这使我的编程技能增长困难。最终,我离开了那个团队,加入了一个可以向比我更资深的同事学习的团队。在被资深同事包围的前几个月,我学到的 Python 知识比我自己最资深的那一年还多。

根据 2023 年 3 月 5 日的数据,glassdoor上的 Python 开发者职位年薪范围为入门级职位的$50k 到$127k,而中级职位的年薪范围为$77k 到$250k

虽然我在数据科学团队中是最资深的 Python 程序员,但仍然是初级水平,我开始在网上寻找高级 Python 内容来学习更高级的概念,因为没有同事可以教我,但我仍然希望提高我的编程技能。

我注意到,比起大多数入门课程,教授更高级 Python 概念的在线材料明显较少,质量也较差。然而,仍有一些出色的在线材料可以帮助你突破初级 Python 开发者的“玻璃天花板”水平。我喜欢推荐以下两位 Python 专家的内容,这些内容非常适合那些已经掌握入门课程中基本概念的初级程序员。

Arjan Egges

我学习如何提升 Python 程序专业性的一个最喜欢的资源是Arjan EggesArjanCodes内容。Arjan Egges 是一位荷兰 Python 开发者,他以非常清晰和愉快的方式从软件设计和开发的角度讲授更高级的 Python 概念。我从他那里学到了许多在格罗宁根大学的 Python 相关硕士课程中未曾教授的概念。

我特别喜欢他关于例如 Data ClassesA/B TestingAbstract Base Classes 等的免费 Youtube 视频,但他也有自己的网站,内容更加丰富:

[## ArjanCodes

嗨,我是 Arjan。我是一位软件设计爱好者和 YouTuber。我制作关于软件设计、开发等方面的视频…

www.arjancodes.com [## Next-Level Python: Become a Python Expert | ArjanCodes | Skillshare

解锁对该 Skillshare 课程的无限访问权限以及由来自世界各地的创作者教授的数千门课程…

www.skillshare.com

这个视频中,Arjan 提出了 14 个项目,你可以将从他的教程视频中学到的概念应用到这些项目中。我强烈推荐这样做,因为与其他项目相比,在这些项目中,你可以有更多的空间自行思考,这实际上迫使你从设计到实现全面考虑一个项目。

我认为这是大多数网上 Python 课程的最大缺陷之一:这些课程通常过于专注于语法,而实际上提出正确的解决方案和设计才是成为开发者最具挑战性的部分。相比之下,Arjan 更加注重软件设计而非语法,在我看来,这是一种非常受欢迎的 Python 教学不同方法。

通过交替观看他的教程视频和进行这些项目,如果你完成了所有这些项目,你的 Python 编程能力肯定会比那些只完成了如这个datacamp 上的标准入门级 Python 课程的同行提高很多,这些课程更注重语法。

在 2023 年 3 月 5 日,Udemy 上有超过6500 门英文 Python 初学者课程,而只有315 门英文高级 Python 课程

Fred Baptiste

另一位教授高质量高级 Python 开发内容的 Python 开发者是Fred Baptiste。如果你想真正理解运行某些 Python 代码时发生了什么,我强烈推荐他的课程。他不仅教你“你可以用这个函数或方法来解决这个问题”,而且深入探讨当调用这个函数或方法时实际执行了什么,以及这段代码在后台的工作原理。

因此,例如,在编写代码时,你可以适当地考虑计算成本和内存效率,这可能非常有用甚至是必要的;运用我们从 Fred 那里学到的知识,我和一位同事成功优化了一个之前无法使用的时间序列交叉验证器,因为它经常导致内存溢出错误或看似无尽的运行时间:

## 一款备受期待的时间序列交叉验证器终于来了

不均匀分布的时间序列数据不再是交叉验证的问题。

towardsdatascience.com

Fred Baptiste 在 Udemy 上发布了四门高级 Python 课程,你通常可以以大约$15 的折扣价格购买(享受30 天退款保证政策):

请确保阅读每门课程的先决条件,因为这些绝对不是初学者课程!

要从这些课程中获得最大收益,正如 Fred 自己所建议的那样,请确保在观看他的解决方案之前,自己先进行编码并尝试得出解决方案。

除了在 Udemy 上提供这些课程外,Fred 还运营了一个名为MathByte Academy的 YouTube 频道,提供关于 Python 的免费视频,包括一些高级概念,如Pydantic 数据模型异步生产者-消费者模型

学习、练习、应用、重复

当然,仅仅观看 Arjan 和 Fred 的视频并做他们的练习并不会立即改变你的初级水平。然而,如果你积极将他们教授的概念应用到工作中或个人项目中,你肯定会显著区别于那些只完成了我在文章开头提到的标准入门课程的其他 Python 开发者。通过 Arjan,你将学会如何正确思考 Python 程序的设计,而 Fred 则帮助你对 Python 代码有比以往更深刻的理解。

我坚信,通过完成他们的所有视频和练习,你有很高的机会成为比那些仅完成了几个 Python 课程的普通毕业生更优秀的 Python 开发者,因为 Arjan 和 Fred 教授的许多概念比我在硕士课程中遇到的要先进。

就这些!祝你在 Arjan 和 Fred 的帮助下顺利脱离 Python 编程的初级阶段!如有任何问题或需要更多建议,比如先做哪些项目,随时与我联系。

如果你想看到实际编码示例,了解高级开发者如何在编码挑战中区别于初级开发者,可以查看我另一篇文章:

## 5 个 Python 技巧让高级开发者与初级开发者区别开来

通过对《Advent of Code》谜题的不同解法进行说明

[towardsdatascience.com

如何将非传统教育或职业路径转化为你的第一个数据科学工作

原文:towardsdatascience.com/how-to-leverage-a-non-traditional-education-or-career-path-into-your-first-data-science-job-f2a5e2ed0585?source=collection_archive---------5-----------------------#2023-02-17

一些关于如何将你的非传统经历作为你的第一个数据科学工作的卖点的建议

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

·

关注 发表在 Towards Data Science ·7 min read·2023 年 2 月 17 日

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

图片由 Joshua Earle 提供,来源于 Unsplash

数据科学是一个有趣的技术领域,你可以与那些曾经学习过哲学、从事护理工作或以遛狗为生的人交谈,而现在他们正在抓取网络数据、构建机器学习模型并向高管展示数据结论。

无论你有什么背景,你都受到数据科学领域的欢迎。

2020 年成为了人们开始自学编程并从各种背景过渡到技术领域的一年,这一趋势似乎延续到了 2023 年。虽然非传统的职业或教育背景可能使进入数据科学变得具有挑战性,但当你知道如何利用现有技能来补充新学到的数据科学技能时,这并不是不可能的。

这里分享的技巧并不具有革命性或改变人生的效果——而是我个人在尝试从非传统背景进入数据科学时发现的行之有效的技巧。你的数据科学技能和过往经验将会证明自己,你只需利用这些技巧将它们转化为新的数据科学职业。

建立作品集

你已经学会了数据科学技能,现在需要展示你能做什么。

当你申请数据科学职位时,你的作品集非常重要,这不仅适用于非传统背景的人,也适用于那些正式学习过数据科学的人。作品集往往是决定招聘人员是否邀请你参加第一次面试的关键,因此它需要成为一个充满你最佳工作的有影响力的资源,并展示你的非传统背景如何使你成为比其他候选人更强的候选人。

大多数数据科学作品集都是在 GitHub 上建立和托管的,GitHub 是行业标准,你应该在这里存储所有个人数据科学项目。你可以在这里学习如何建立 GitHub 作品集:

如何在 GitHub 上创建一个专业的作品集,以帮助获得数据科学领域的第一份工作

你的作品集在向雇主解释为什么他们应该聘用你方面起着至关重要的作用。

towardsdatascience.com

当你从非传统背景进入数据科学领域时,你希望你的作品集能够展示你从以前的经验中获得的可转移技能,使你的项目充满独特的洞察力。洞察力在数据科学中至关重要,这就是为什么选择项目时你需要发挥自己的优势。

例如,如果你是一名护士,你的作品集项目可以集中在如何提高医院的效率、医生如何利用人工智能做出更准确的诊断,或环境条件恶化如何成比例地增加医院的接收率。如果你是一名教师也是一样——如何通过更多教育驱动的儿童电视节目帮助孩子们在成为全面发展的学生方面取得先机?

无论你是否想在之前的行业中成为数据科学家,展示你能够运用已有知识解决问题的能力是至关重要的。这些项目应尝试解决你在工作中遇到的问题(或可能促使你离开那个职位的问题),通过数据集、统计分析、机器学习和人工智能来实现。

此外,这些类型的项目展示了你将现实世界问题拆解为数据科学可以解决的部分的能力。

例如,我目前正在进行一个个人项目,研究如何更好地标准化失踪人员的寻找概率。我从事搜救工作,虽然没有两个电话是相同的,但可以找到呼叫类型与预期寻找人员的位置之间的关联。换句话说,就是将一个非常现实的问题拆解为其组成部分,确定如何利用失踪人员数据使搜救操作更高效。虽然这可能与我下一个申请的数据科学职位不完全相关,但它肯定能展示我能运用数据科学技能解决问题——这最终才是雇主所寻找的。

如何有效展示个人项目在数据科学简历上的价值

简洁的项目描述是吸引招聘人员注意的必备条件。

towardsdatascience.com

关键要点

  • 为你的作品集构建能够解决你在之前行业中遇到问题的项目——这向潜在雇主展示了你致力于寻找更好的解决方案,并且能够将现实世界的问题拆解为可用数据科学解决的部分。

获得简单的数据科学经验

每个人的数据科学首次体验都会有所不同。对我来说,它是志愿服务,而对其他人来说,可能是自由职业工作。对于“Towards Data Science”的一些作者来说,他们通过分享文章来展示自己的专业知识。

获得简单的数据科学经验是获得实践经验和在现实场景中处理数据的好方法。这些机会可能没有报酬,但当你被聘为数据科学家时,它们会在未来得到回报。

简单的数据科学经验可能看起来像是建立一个 Excel 表格,通过历史价格数据预测父母未来的月度支出。或者,它可能是为一个本地在线业务做客户分析,并帮助他们推广表现最好的产品。又或者,它可能是为社交媒体营销人员建立一个仪表盘,以确定客户注册情况与 Google 搜索趋势的关系。如果你真的想利用你非传统的背景,寻找该领域的数据相关经验,并展示你在行业中的实际技能与新获得的数据科学技术技能如何帮助你比单一技能集提供更多见解。

无论如何,你应该完成 3–4 个简单的现实项目,向潜在雇主展示你具备他们需要的技术技能(以及提供比大多数人更多见解的非传统背景)。大多数公司希望他们的数据科学家能够迅速上手(程度有所不同),因此,通过这些简单的项目来掌握基础知识是一个好主意。

这些项目可以作为工作或志愿者经历展示在你的简历上。此外,你还应该争取获得你所做项目的个人或公司推荐,这可以用作参考,或者作为公司聘用你的又一个理由。最重要的是,这些简单的经历向雇主展示了你的非传统背景与作为数据科学家的能力是互补的。

例如,我将大学的最终顶点项目作为进入技术行业的经验。这是与潜在雇主交流的一个很好的话题,并让他们对我的技能有了很好的了解,无论是技术方面还是可转移的技能。通过向他们展示我曾作为团队的一部分为大型客户公司创造了有形结果,他们可以对我在“现实生活”工作中交付同样的结果充满信心。此外,虽然这项工作与职位并不完全相关,但它展示了我具有可转移技能,并因我的非传统背景而增加了洞察力。

关键点

  • 通过志愿服务、实习、自由职业或在社交媒体上分享你的知识来获得简单的数据科学经验。这向雇主展示了你具备完成工作的技术技能,并让他们放心,你的非传统背景与作为数据科学家的能力是互补的。

突出可转移技能

我从寻找学术之外工作的硕士和博士生那里得到的最佳建议之一是,你拥有许多可转移的技能,无论你来自什么教育或职业背景。虽然可能看起来不明显,但请思考一下。

例如,如果你是一名正在转行进入数据科学的护士,你会非常有组织、注重细节、富有创造力、能够在快节奏环境中工作,并且擅长解决问题。或者,如果你是一名教师,你是一位优秀的沟通者,能够将复杂的主题简化,你是一个解决问题的人,并且你对截止日期非常严格。这些技能在数据科学行业中都是被重视的,应当被充分展示。

在优秀的科技公司,你会发现他们会雇佣拥有所有基本软技能(其中一些在上面列出)的数据科学家,即使他们没有完美的技术背景,因为他们知道他们可以培训技术技能——但他们无法培训软技能。

例如,我记得我曾经工作的公司雇了一位也希望从事数据科学工作的开发者。虽然这位开发者的数据科学技能并不完美,但公司还是雇用了他们,因为公司知道这位人员可以在公司培训他们相关的数据科学技能的同时继续作为开发者工作。如果有需要,这位人员将有可能完全转入数据科学角色,或者继续作为开发者工作,并在旁边接受培训。

关键要点

  • 可转移技能将使你与其他候选人区分开来——突出与你申请的职位最相关的技能,并说明你在之前的经验中学到的知识如何适用于数据科学职位。

订阅以将我的故事直接发送到你的邮箱:Story Subscription

请成为会员以通过我的推荐链接无限访问 Medium(对你没有额外费用,我会获得少量佣金):Medium Membership

通过捐款支持我的写作,帮助我创作更多类似的故事:Donate

如何利用预训练的 Transformer 模型进行自定义文本分类?

原文:towardsdatascience.com/how-to-leverage-pre-trained-transformer-models-for-custom-text-categorisation-3757c517bd65

所以,你有一些自定义的文本数据集,想要进行分类,但不知道如何做?好吧,让我展示一下,如何利用预训练的最先进语言模型来实现。

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

·发布于Towards Data Science ·阅读时间 11 分钟·2023 年 3 月 31 日

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

图片来源于Meagan CarsienceUnsplash

好吧,让我们直奔主题!你有一些自定义数据,现在想将其分类到自定义类别中。在本文中,我将展示你如何使用两种方法来实现这一目标。这两种方法都利用了最先进的基于 Transformer 的预训练模型。

请注意,本文的目标是与您分享方法及其使用方式。这不是一个包含最佳实践的完整数据科学教程。不幸的是,这超出了本文的范围。

本文中的所有代码可以在这个GitHub 仓库中找到。

1: 零样本分类

概述

零样本分类是一种技术,它允许你在没有为特定任务训练专门模型的情况下对文本进行分类。相反,它使用已经在大量数据上训练过的预训练模型来执行分类。模型通常会在包括语言建模、文本补全和文本蕴涵等各种任务上进行训练。

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

使用预训练的 LLM 进行零样本文本分类(来源:作者)

要执行零样本分类,你只需向预训练模型提供一些文本和一个可能的类别列表。

模型将利用其对语言的理解和已有知识将文本分类到提供的类别之一。这种方法特别有用,当你为特定分类任务拥有的数据有限时,因为它允许你利用模型的已有知识。

由于它在特定任务上没有任何训练,因此被称为零样本分类。

实现

我们需要做的就是使用pip install transformers安装hugging face transformers 库。我们将使用预训练的 Facebook BART(双向和自回归变换器)模型来完成这项任务。

附注:首次使用时,下载模型可能需要一些时间。

输出是一个包含 3 个键的字典:

  • 序列:由管道分类的输入文本

  • 标签:提供给管道的候选(类别)标签的列表,根据它们的概率分数进行排序。

  • 分数:基于模型对输入文本属于该标签的可能性的预测,分配给每个候选标签的概率分数。

from transformers import pipeline

pipe = pipeline(model="facebook/bart-large-mnli")
pipe("Tesco Semi Skimmed Milk 1.13L/2 Pints ...... £1.30",
    candidate_labels=["groceries", "utility", "electronics", "subscriptions"],
)

# output
>> {'sequence': 'Tesco Semi Skimmed Milk Pints',
 'labels': ['groceries', 'utility', 'subscriptions', 'electronics'],
 'scores': [0.9199661612510681,
  0.05123506113886833,
  0.022794339805841446,
  0.0060044946148991585]}

如你所见,在没有任何训练的情况下,模型已正确地将给定文本分类到“杂货”类别。因为模型是在特定语言的大型语料库上训练的,它能够理解该语言并进行推断。它理解了文本并从候选标签列表中识别了合适的类别。

简而言之,真是太棒了!!😊

模型越大,零样本分类任务的表现越好。有关更多信息,请查看 hugging face 上的零样本分类页面

⚡️ 查看这个笔记本以获取更多示例。

什么时候使用它?

鉴于其在没有任何训练的情况下表现卓越,如果你了解类别的描述,我强烈建议首先尝试这个方法。它利用了最先进的预训练模型,并在没有任何训练的情况下提供了卓越的结果。

这里是一些非详尽的情况,当这些情况适合你的方法时:

  1. 当你拥有有限的标注训练数据时

  2. 当你需要快速原型一个解决方案时

  3. 当你需要对新的或稀有的类别进行分类时

  4. 当你需要将实例分类到多个类别中时

  5. 当你想利用预训练模型对实例进行分类而无需额外训练时

  6. 当你想将实例分类到由自然语言描述定义的类别中,而不是预定义标签时。

有哪些限制?

这里是使用零样本分类方法时需要考虑的一些潜在缺点和限制:

  1. 有限的训练数据扩增:在零-shot 分类中,扩增训练数据以提升模型性能的范围有限,这与传统监督学习方法不同。

  2. 对模型行为的控制有限:零-shot 分类依赖于预训练模型,这意味着你对其行为和学习到的模式的控制有限。这可能导致意外结果,特别是当模型没有在类似于你任务的数据上训练时。

  3. 有限的自定义:由于零-shot 分类依赖于预训练模型,因此自定义或微调以适应特定任务的余地有限。这可能限制模型的准确性和性能,尤其是当任务涉及复杂或领域特定的语言时。

🚀 专业提示:始终清理你的文本!!

尽管基于变换器的 LLM 在处理嘈杂文本方面显著优于其他模型,但在将文本输入模型之前,仍然强烈建议清理文本。

这不仅是良好的数据科学实践,还会产生巨大差异。与干净文本输入相比,生成的嵌入在嘈杂文本数据中的相似性评分可能较低。这无疑会降低类别分类评分。

例如,下面是对这段文本——“Tesco Semi Skimmed Milk 1.13L/2 Pints …… £1.30”——在去除特殊字符和数字前后的分类对比。为什么不在Hugging Face zero-shot classification页面上试试呢?

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

使用零-shot 方法在清理文本前后的文本分类概率比较。(来源:作者)

☕️ 让我们在继续之前休息一下……

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

照片由Victoria Tronina拍摄,来自Unsplash

☕️ 5 分钟后……好吧,让我们开始吧 🏃

2: 迁移学习(预训练模型 + 分类模型)

概述

这是一种比前一种方法更高级的方式。如前所述,零-shot 分类不允许针对特定任务进行自定义。这就是这种方法作为长期解决方案的所在。

在这种方法中,你使用预训练的变换器模型创建文本嵌入,然后训练一个分类模型将这些嵌入分类到各自的类别中。

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

解决方案概述:使用预训练模型将项目描述文本转换为文本嵌入,并使用分类模型将文本分类到不同类别中。(来源:作者)

为了演示这个例子,我们将使用来自 Kaggle 的e-commerce 产品数据集

该数据集包含 4 个产品类别和产品的文本描述。目标是构建一个模型,可以将产品描述文本分类到这 4 个类别中。

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

Kaggle上的电子商务产品描述和类别数据。(来源:作者)

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

这个数据集中有 4 个类别。(来源:作者)

实现

这个方法的实现可以分为 4 个步骤:

  1. 在将文本输入模型之前,请先清理文本。

  2. 使用预训练的大型语言模型(LLM)生成文本嵌入。

  3. 使用嵌入训练一个自定义类别的分类模型。

  4. 使用训练好的模型和预处理管道进行预测。

到此为止,你将拥有一个分类模型,该模型利用了 LLM 在大量数据上训练学到的高质量嵌入。

这些嵌入是 LLM 成功的关键因素,因为它们捕捉了语言的丰富表示,能够有效捕捉文本中的意义和上下文的细微差别。

⚡️ 请注意,完整的代码可以在以下笔记本中找到。

步骤 1:清理文本

如前述方法所提,使用模型之前清理文本始终是一个好习惯。以下是本文中用于清理文本的代码

附注*:清理是高度任务特定的。在这个例子中,我只实现了一些基本的清理。作为最佳实践,最好先了解数据,然后实施一些任务特定的清理。例如,你可能需要根据具体任务的要求决定是否保留或删除数字。此外,通过删除不必要的词语/符号来减少文本量,可以减少后续处理的时间。祝清理愉快!* 😄

import re

pattern = r"(?:\b\w+\b|['\"“”‘’])"
url_pattern = re.compile(r'http\S+|www\S+')
punct_pattern = re.compile(r'[^\w\s]')
digit_pattern = re.compile(r'\d+')
non_ascii_pattern = re.compile(r'[^\x00-\x7F]+')

def clean_text(text):

    # Convert to lowercase
    text = text.lower()
    # Remove URLs
    text = url_pattern.sub('', text)
    # Remove punctuation
    text = punct_pattern.sub(' ', text)
    # Remove digits
    text = digit_pattern.sub('', text)
    # Remove non-ASCII characters
    text = non_ascii_pattern.sub('', text)
    # Tokenize words and remove single characters
    words = [word for word in re.findall(pattern, text) if len(word) > 1]
    return ' '.join(words)

# Example Output  
text = "This is an example text with a URL https://www.example.com, some #hashtag."
cleaned_text = clean_text(text)
print(cleaned_text)
>> "this is an example text with url some hashtag"

# Apply it to both the training and test data.
train_df["clean_desc"] = train_df["item_description"].apply(lambda x: clean_text(x))
test_df["clean_desc"] = test_df["item_description"].apply(lambda x: clean_text(x))

步骤 2:生成文本嵌入

我们将使用来自 Hugging Face 的SentenceTransformer库来创建文本嵌入。该库包含基于变换器的预训练模型,用于生成固定长度的文本数据向量表示,如段落或句子。

具体来说,我们将使用库中的*“paraphrase-mpnet-base-v2”*预训练模型,该模型生成长度为 768 的固定长度向量。

附注:为了节省时间,我减少了训练集和测试集的样本量。生成嵌入表示可能需要一些时间,尤其是在本地机器上。这可能会影响模型的性能。

from sentence_transformers import SentenceTransformer

# Load SentenceTransformer model
model = SentenceTransformer('paraphrase-mpnet-base-v2')

# Example Output
sentence = ['This is a sample sentence for encoding.']
embedding = model.encode(sentence)
print(embedding)
>> [[ 4.99693975e-02 -1.26025528e-01 -9.15094614e-02  1.19477045e-02
   9.89145786e-02  9.02947485e-02  1.74566925e-01  1.84450839e-02
  -1.04984418e-01 ....... 8.46698135e-02  8.69197398e-03 -1.48386151e-01]]

# Generate embeddings for the training data
train_desc = train_df['clean_desc'].tolist()
train_embeddings = model.encode(train_desc)
X_train = np.array(train_embeddings)

步骤 3:训练分类模型

现在我们已经有了嵌入表示,我们准备训练一个分类模型,将这些嵌入表示分类到 4 个产品类别中的其中一个。

在这个演示中,我使用了 XGBoost 模型,但你可以随意使用你喜欢的模型!

附注:为了在训练过程中节省时间,网格搜索中使用了有限的超参数。此外,为了简化,我们使用准确率作为性能衡量标准。确保使用适当的指标来衡量你的分类任务的性能。

from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.preprocessing import LabelEncoder
import xgboost as xgb

# Encode the target variable as categorical with one-hot encoding
le = LabelEncoder()
y_train = le.fit_transform(train_set['category'])

# Split the data into training and validation sets
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42)

# Define the parameter grid for grid search cross-validation
param_grid = {
    'max_depth': [7],
    'n_estimators': [300],
    'learning_rate': [ 0.2, 0.5],
}

# Train an XGBoost model with grid search cross-validation
xgb_model = xgb.XGBClassifier(objective='multi:softmax', num_class=4)
grid_search = GridSearchCV(xgb_model, param_grid=param_grid, cv=5, n_jobs=-1, verbose=0)
grid_search.fit(X_train, y_train)
# -----------------------------------------------------------------

# Print the best hyperparameters found by grid search
print("Best hyperparameters:", grid_search.best_params_)

# Make predictions on the validation data using the best model
y_pred = grid_search.predict(X_val)

# Decode the predicted target variable
y_pred = le.inverse_transform(y_pred)

# Evaluate the performance of the model
accuracy = np.mean(y_pred == le.inverse_transform(y_val))
print(f"Accuracy: {accuracy:.2f}")

# Output
>> Best hyperparameters: {'learning_rate': 0.2, 'max_depth': 7, 'n_estimators': 300}
>> Accuracy: 0.94

步骤 4:运行预测

最后,打包文本处理步骤,加载训练好的分类器模型,你就可以在测试数据集上运行预测了。

import pickle
# Save the trained model to a file
filename = 'xgb_model.sav'
pickle.dump(grid_search, open(filename, 'wb'))

# Load the model from file
loaded_model = pickle.load(open(filename, 'rb'))

# Define function to make predictions on new data
def predict_gl_code(text):
    # Preprocess the text data
    text = clean_text(text)

    # Generate embeddings for the text data
    embeddings = model.encode([text], show_progress_bar=False)
    X = np.array(embeddings)

    # Make predictions using the loaded model
    y_pred = loaded_model.predict(X)
    gl_code = le.inverse_transform(y_pred)[0]
    return gl_code

# Add a new column for predictions to the test dataframe
test_set['preds'] = test_set['clean_desc'].apply(predict_gl_code)

# Compute the accuracy of the model on the test data
accuracy = np.mean(test_set['preds'] == test_set['category'])
print(f"Accuracy: {accuracy:.2f}")

# Output 
>> Accuracy: 0.91

这就是各位的内容!! 😃

在没有进行太多特定任务的文本清理的情况下,我们使用了预训练变换器模型生成的嵌入表示,并构建了一个分类器,将其分类到 4 个类别中,准确率为 91%。

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

测试数据集上的预测(preds)。 (来源:作者)

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

在测试数据集上预测错误的情况。 (来源:作者)

模型未能正确预测的情况可以通过使用更多的数据进行训练和执行特定任务的文本清理来改进。例如,保留维度编号,因为它有助于区分家庭产品与其他产品。

⚡️ 再次提醒,完整代码可在这个笔记本中找到。 🤗

最终想法

在这篇文章中,我们探讨了利用预训练的大型语言模型(LLMs)定制文本分类的两种不同方法。由于它们生成的高质量嵌入,我们可以以最小的努力取得令人印象深刻的结果。

由于这些 LLMs 已经在大量数据上进行过训练,它们对语言有深入的理解,并且能够有效捕捉文本中意义和语境的细微差别。

既然你知道了这两种方法,尝试一下你的文本分类任务吧! 😃

👉 别忘了关注以获取更多类似的文章。 🤗

🚀 希望你觉得这篇文章对你有帮助。考虑使用我的链接加入 Medium,获取我和其他平台上优秀作者的更多精彩内容!

我的其他文章:

[## 如何从 PDF 文件中提取并转换表格到 Pandas 数据框?

所以你有一些包含表格的 PDF 文件,并且想将它们读取到一个 pandas 数据框中。让我来展示给你看。

如何从 PDF 文件中提取并转换表格到 pandas 数据框 [## 如何调度无服务器 Google Cloud 函数以定期运行

你是否有一些代码需要定期运行?

如何定期调度无服务器 Google Cloud 函数 [## 如何在本地开发和测试你的 Google Cloud 函数

因此,你已经编写了无服务器云函数,但不想浪费时间部署它并希望它能正常工作。让…

如何在本地开发和测试你的 Google Cloud 函数 [## 使用 Google Cloud Functions 将机器学习模型作为无服务器端点

因此,你已经构建了一个模型,并且想将它作为无服务器解决方案在 Google Cloud Platform (GCP) 上投入生产。让我来…

使用 Google Cloud Functions 将机器学习模型作为无服务器端点

如何以全新的视角看待常见的机器学习任务

原文:towardsdatascience.com/how-to-look-at-common-machine-learning-tasks-with-fresh-eyes-eeedd99f39e6?source=collection_archive---------12-----------------------#2023-07-20

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

·

关注 发表在 数据科学前沿 · 发送为 通讯 · 3 分钟阅读 · 2023 年 7 月 20 日

我们绝不会推荐仅为了改变而改变稳定且表现良好的工作流程;“如果没坏,就别修” 是一种流行的俗语,原因很简单:这往往是正确的做法。

尽管如此,“非常频繁”和“总是”之间还有相当大的差距,而我们在工作中最令人沮丧的日子通常是当我们经过验证的方法未能产生预期结果或表现不佳时。这时扩展我们的知识基础真的会带来回报:我们不会陷入精神上的“死亡旋转轮”,而是尝试不同的方法,调整我们的过程,并(迟早)找到新的解决方案。

在拥抱新视角的精神下,我们整理了一系列出色的近期帖子,提供了对常见机器学习工作流的新颖解读。它们涵盖了漂移检测和模型训练等过程,以及从图像分割到命名实体识别的任务。为你的工具箱腾出空间——你会想要添加这些内容!

在深入之前,简单更新一下:如果你想寻找其他方式来跟上我们最新的优质文章,我们刚刚推出了几个 Medium 列表以帮助你发现更多精彩阅读。

  • 算法推荐系统无处不在,从电子商务网站到流媒体服务,其输出有时可能显得重复和显而易见。正如Christabelle Pabalan所展示的,我们不必满足于毫无创意的选择—实际上,将推荐系统注入新奇和意外元素可以带来更好的用户留存率。

  • 检测在非结构化数据上训练的模型的漂移,例如用于 LLM 驱动应用的嵌入,“是一个相当新的话题,目前没有‘最佳实践’方法,”Elena Samuylova和 Olga Filippova 表示。为了帮助你选择最有效的方法,他们进行了若干实验,并根据他们的发现分享了清晰的建议。

  • 许多数据科学家和机器学习从业者认为合成数据选项在模型训练中的快速崛起值得庆祝,但也认识到这带来了数据质量和长期表现方面的严重问题。Vincent Vatter为我们介绍了微软的最新研究,指出了前进的有效路径。

  • 模型校准是许多分类任务中的关键步骤,但以优化准确性的方式进行计算可能会很棘手。Maja Pavlovic 提供了关于处理预期校准误差(ECE)的清晰实用教程

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

图片由 Bonnie Kittle 拍摄,发布在 Unsplash

  • 如果你在最近使用卷积神经网络的图像分割项目中遇到了瓶颈,Dhruv MataniNaresh 提供了一个替代方案:不妨尝试基于视觉变换器的模型

  • 作为 NOS——荷兰公共广播基金会的数据科学家,Felix van Deelen 可以访问丰富的新闻故事语料库;Felix 的首篇 TDS 文章探讨了如何在命名实体识别项目中使用这些文本数据

  • 检测数据中的异常没有一种通用的解决方案,这使得熟悉几种选项成为一个好主意。Viyaleta Apgar 向我们介绍了一种基于高斯分布的适合初学者的技术,并展示了如何在多变量模型的背景下实现它

  • 为了更有效地优化你的回归模型,Erdogan Taskesen 提出了在模型训练的超参数调整步骤中加入贝叶斯风格的建议;该教程包括了一个全面的实现,依赖于 HGBoost 库的强大功能。

感谢你对我们作者的支持!如果你喜欢在 TDS 上阅读的文章,可以考虑成为 Medium 会员——这将解锁我们的全部档案(以及 Medium 上的其他每篇文章)。

直到下一个 Variable,

TDS 编辑部

如何制作 40+个互动图表以分析你的机器学习管道

原文:towardsdatascience.com/how-to-make-40-interactive-plots-to-analyze-your-machine-learning-pipeline-ee718afd7bc2?source=collection_archive---------14-----------------------#2023-03-08

一个关于如何制作干净、互动的 Python 图表以验证你的数据和模型的快速指南

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

·

关注 发表在 Towards Data Science ·4 分钟阅读·2023 年 3 月 8 日

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

图片由 Markus WinklerUnsplash 提供

介绍

图表已经成为帮助数据科学家和利益相关者理解机器学习项目过程和结果的事实标准工具。在本故事中,我们将向你展示如何使用ATOM库轻松制作干净的交互式图表,以便快速分析数据集、检查管道、评估模型的性能并解释模型的结果。ATOM 是一个开源 Python 包,旨在帮助数据科学家加速机器学习管道的探索。如果你想对这个库有一个温和的介绍,请阅读这个故事。

数据图表

让我们从图表开始,以帮助你更好地理解你正在处理的数据集。如何转换管道和训练模型使用 ATOM 超出了本故事的范围。阅读这个故事或这个故事以了解更多信息。在这里,我们将直接深入到图表制作中。

初始化atom后,创建图表就像调用适当的方法一样简单。除了一些例外,图表是使用plotly库制作的,并以 html 渲染。点击这里查看所有可用数据图表方法的列表。

from atom import ATOMClassifier
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True, as_frame=True)

atom = ATOMClassifier(X, y)

atom.plot_correlation()
atom.plot_distribution(columns=0)
atom.plot_relationships(columns=(0, 1, 2))

特征选择图表

特征选择图表可以帮助你分析由PCARFECV策略选择的特征。点击这里查看所有特征选择图表的列表。

from atom import ATOMClassifier
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True, as_frame=True)

atom = ATOMClassifier(X, y)
atom.feature_selection("pca", n_features=5)

atom.plot_pca()
atom.plot_components(show=10)

超参数调优图表

ATOM 使用optuna库来应用超参数调优。通过 optuna 提供的图表也可以通过 ATOM 的 API 直接获取,还有一些额外的图表。点击这里查看所有超参数调优图表的列表。

from atom import ATOMClassifier
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True, as_frame=True)

atom = ATOMClassifier(X, y)
atom.run(models="RF", metric="f1", n_trials=15)

atom.plot_hyperparameters(params=(0, 1, 2))
atom.plot_parallel_coordinate(params=slice(1, 5))
atom.plot_slice(params=(0, 1, 2))

预测图表

在训练模型之后,使用其在训练集和测试集上的预测来评估模型的性能或检查特征重要性。ATOM 最强大的功能之一是能够在同一图表中绘制多个模型或数据集(例如,训练集与测试集)的结果。

from atom import ATOMClassifier

X = pd.read_csv("https://raw.githubusercontent.com/tvdboom/ATOM/master/examples/datasets/weatherAUS.csv")

atom = ATOMClassifier(X, y="RainTomorrow")
atom.impute()
atom.encode()
atom.run(models=["LR", "RF"])

atom.plot_roc()
atom.plot_prc(models="RF", dataset="train+test")
atom.plot_feature_importance(show=10)

可解释性图表

SHAP(SHapley Additive exPlanations)Python 包使用博弈论的方法来解释任何机器学习模型的输出。它将最优的信用分配与本地解释联系起来,使用经典的Shapley 值及其相关扩展。ATOM 实现了从其 API 直接绘制 SHAP 的 7 种绘图功能的方法。由于这些图不是由 ATOM 生成的,因此它们既不具备交互性,也不能显示多个模型。

from atom import ATOMClassifier
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True, as_frame=True)

atom = ATOMClassifier(X, y)
atom.run(models="RF")

atom.plot_shap_bar()

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

atom.plot_shap_beeswarm(show=10)

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

atom.plot_shap_decision(index=slice(5), show=10)

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

参数

除了特定于图表的参数外,所有图表共有五个参数:

  • title参数为图表添加标题。默认值不显示任何标题。提供配置(作为字典)以自定义其外观,例如title=dict(text="Awesome plot", color="red")。更多信息请参阅 plotly 的文档

  • legend参数用于显示/隐藏、定位或自定义图表的图例。提供配置(作为字典)以自定义其外观(例如legend=dict(title="Title for legend", title_font_color="red"))或选择以下位置之一:左上角、右上角、左下角、右下角、上中、下中、左中、右中、中间、外部。

  • figsize参数调整图表的大小。

  • filename参数用于保存图表。

  • display参数确定是否显示或返回图表。

from atom import ATOMClassifier
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True, as_frame=True)

atom = ATOMClassifier(X, y)

atom.plot_distribution(
    columns=0,
    title=dict(
        text="Custom left side title",
        font_color="teal",
        x=0,
        xanchor="left",
    ),
    legend="upper left",
)

结论

我们已经展示了如何使用 ATOM 包制作交互式图表,以快速分析机器学习管道的结果。要查看所有可用图表的列表,请点击这里

欲了解有关 ATOM 的更多信息,请查看软件包的文档。如有错误或功能请求,请随时在GitHub上提交问题或给我发邮件。

相关故事:

  • towardsdatascience.com/atom-a-python-package-for-fast-exploration-of-machine-learning-pipelines-653956a16e7b

  • towardsdatascience.com/how-to-test-multiple-machine-learning-pipelines-with-just-a-few-lines-of-python-1a16cb4686d

  • towardsdatascience.com/from-raw-data-to-web-app-deployment-with-atom-and-streamlit-d8df381aa19f

  • towardsdatascience.com/exploration-of-deep-learning-pipelines-made-easy-e1cf649892bc

  • towardsdatascience.com/deep-feature-synthesis-vs-genetic-feature-generation-6ba4d05a6ca5

  • towardsdatascience.com/from-raw-text-to-model-prediction-in-under-30-lines-of-python-32133d853407

参考文献:

  • 本文中的所有图表均由作者创建。

如何在 R 中使用 ggplot2 制作蜘蛛图

原文:towardsdatascience.com/how-to-make-a-spider-chart-in-r-using-ggplot2-85a4f1898cab?source=collection_archive---------4-----------------------#2023-01-11

一步一步构建蜘蛛图/雷达图

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

·

关注 发布于 Towards Data Science ·8 分钟阅读·2023 年 1 月 11 日

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

图片由 Divyadarshi Acharya 提供,来自 Unsplash

了解到雷达图可以制作引人注目的可视化,我尝试寻找合适的 R 库。当我的搜索几乎没有结果时,我感到惊讶**(编辑:在写这篇文章后不久,我创建了**ggvanced**包,其中的**ggspider**函数处理了这个问题。你可以在另一篇文章中了解更多信息。)**。我找到的唯一一个包是ggradar,它不在 CRAN 上,只能从 GitHub 安装。

我决定尝试使用titanic包中的泰坦尼克号数据。为了计算所需的数据汇总并将数据转换为绘图所需的形状,我使用了dplyrtidyrtibblepurrscales包。如果你不熟悉这些,请查看我之前关于 R 数据处理的文章。

## 深入探索 tidyverse 使用泰坦尼克号数据

[towardsdatascience.com

library(dplyr)
library(tidyr)
library(tibble)
library(purrr)

Titanic <- titanic_train

Titanic_gr1 <-
  Titanic %>%
  select(Survived:Fare) %>%
  group_by(Pclass) %>%
  summarise(across(c(Age, Fare), mean, na.rm = TRUE))

Titanic_gr2 <-
  Titanic %>%
  select(Survived:Fare) %>%
  group_by(Pclass, Survived) %>%
  summarise(N = n()) %>%
  pivot_wider(names_from = Survived, values_from = N) %>%
  mutate("Survived (%)" = `1`/(`0` + `1`)) %>%
  select(1,4)

Titanic_gr3 <-
  Titanic %>%
  select(Survived:Fare) %>%
  group_by(Pclass, Sex) %>%
  summarise(N = n()) %>%
  pivot_wider(names_from = Sex, values_from = N)

Titanic_gr <- reduce(list(Titanic_gr1, 
                          Titanic_gr2, 
                          Titanic_gr3), left_join) %>%
  rename(Male = "male", Female = "female")
Titanic_gr

# A tibble: 3 × 6
  Pclass   Age  Fare `Survived (%)` Female  Male
   <int> <dbl> <dbl>          <dbl>  <int> <int>
1      1  38.2  84.2          0.630     94   122
2      2  29.9  20.7          0.473     76   108
3      3  25.1  13.7          0.242    144   347

安装并加载ggradar包并将数据重新缩放到(0, 1)区间后,我们可以通过调用ggradar函数来创建雷达图。

library(ggplot2)
library(scales)
library(devtools)
install_github("ricardo-bion/ggradar", dependencies=TRUE)
library(ggradar)

Titanic_gr %>%
  mutate(across(-Pclass, normiranje)) %>%
  ggradar(legend.title = "Passenger class") +
  theme(legend.position = "bottom", legend.title = element_text(size = 17))

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

使用 ggradar 包制作的雷达图。图片来源:作者

尽管获得的图表整洁且视觉上令人愉悦,但我希望每个变量有独立的轴。虽然雷达图和蜘蛛图的名称通常可以互换使用,但我认为在每个变量都有自己的轴的情况下,蜘蛛图更为合适,而雷达图则适用于上述图片中的情况。不幸的是,因为我更感兴趣的是创建蜘蛛图,并且这个包中没有这种选项,所以我不得不自行解决这个问题。

进入 ggplot2

ggplot2的美在于其底层的图形语法,允许通过将多个图层叠加在一起创建图表。这一强大的概念让我们能够创建几乎任何可视化,只要我们知道如何编码。我将使用它从零开始构建一个蜘蛛图。

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

使用 ggplot2 包构建图表背后的哲学。图片来源:作者

分层方法要求分别构建图表的不同方面。首先我们将创建图表轮廓。由于蜘蛛图涉及极坐标,我编写了一个函数,该函数根据数据集中变量的数量计算多边形顶点的坐标。

library(dplyr)
library(tidyr)
library(tibble)
library(purrr)
library(scales)
library(ggplot2)

p_data <- Titanic_gr %>% rename(group = "Pclass")

circle_coords <- function(r, n_axis = ncol(p_data) - 1){
  fi <- seq(0, 2*pi, (1/n_axis)*2*pi) + pi/2
  x <- r*cos(fi)
  y <- r*sin(fi)

  tibble(x, y, r)
}

central_distance <- 0.2

step_1 <- map_df(seq(0, 1, 0.25) + central_distance, circle_coords) %>%
    ggplot(aes(x, y)) +
    geom_polygon(data = circle_coords(1 + central_distance), 
                 alpha = 1, fill = "gray97") +
    geom_path(aes(group = r), lty = 2, alpha = 0.5) +
    theme_void()

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

第一步:创建图表的背景。图片来源:作者

接下来,我们需要计算坐标轴的坐标并将它们添加到图表中。

axis_coords <- function(n_axis){
  fi <- seq(0, (1 - 1/n_axis)*2*pi, (1/n_axis)*2*pi) + pi/2
  x1 <- central_distance*cos(fi)
  y1 <- central_distance*sin(fi)
  x2 <- (1 + central_distance)*cos(fi)
  y2 <- (1 + central_distance)*sin(fi)

  tibble(x = c(x1, x2), y = c(y1, y2), id = rep(1:n_axis, 2))
}

step_2 <- step_1 + geom_line(data = axis_coords(ncol(p_data) - 1), 
aes(x, y, group = id), alpha = 0.3)

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

为数据集中的每个变量添加坐标轴。图片由作者提供

现在我们可以添加文本标签和坐标轴的名称。

text_data <- p_data %>%
  select(-group) %>%
  map_df(~ min(.) + (max(.) - min(.)) * seq(0, 1, 0.25)) %>%
  mutate(r = seq(0, 1, 0.25)) %>%
  pivot_longer(-r, names_to = "parameter", values_to = "value")

text_coords <- function(r, n_axis = ncol(p_data) - 1){
  fi <- seq(0, (1 - 1/n_axis)*2*pi, (1/n_axis)*2*pi) + pi/2 + 0.01*2*pi/r
  x <- r*cos(fi)
  y <- r*sin(fi)

  tibble(x, y, r = r - central_distance)
}

labels_data <- map_df(seq(0, 1, 0.25) + central_distance, text_coords) %>%
  bind_cols(text_data %>% select(-r))

step_3 <- step_2 + 
    geom_text(data = labels_data, aes(x, y, label = value), alpha = 0.65) +
    geom_text(data = text_coords(1 + central_distance + 0.2), 
              aes(x, y), label = labels_data$parameter[1:(ncol(p_data)-1)])

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

添加坐标轴名称和标签。图片由作者提供

现在剩下的工作就是叠加数据点。

rescaled_coords <- function(r, n_axis){
  fi <- seq(0, 2*pi, (1/n_axis)*2*pi) + pi/2
  tibble(r, fi) %>% mutate(x = r*cos(fi), y = r*sin(fi)) %>% select(-fi)
}

rescaled_data <- p_data %>% 
  mutate(across(-group, rescale)) %>%
  mutate(copy = pull(., 2)) %>% 
  pivot_longer(-group, names_to = "parameter", values_to = "value") %>%
  group_by(group) %>%
  mutate(coords = rescaled_coords(value + central_distance, ncol(p_data) - 1)) %>%
  unnest

step_4 <- step_3 + 
    geom_point(data = rescaled_data, 
               aes(x, y, group = group, col = group), 
               size = 3) +
    geom_path(data = rescaled_data, 
              aes(x, y, group = group, col = group), 
              size = 1)

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

用数据点叠加图表。图片由作者提供

以及一些最后的美学修饰……

step_5 <- step_4 + 
    labs(col = "Passenger class") +
    theme(legend.position = "bottom",
          legend.text = element_text(size = 12),
          legend.title = element_text(size = 12)) 

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

最终的蛛网图。图片由作者提供

哒哒,我们的工作完成了。让我们再花一点时间评论一下显示的数字。头等舱乘客是三者中年龄最大、最富有的。三等舱乘客中男性和女性人数最多,是最年轻的一组——可能大多数是年轻人和寻求更好生活的家庭。然而,头等舱乘客的生还率最高,而三等舱的最低。这可能部分是因为头等舱距离船甲板较近,部分是因为该舱等级的女性比例较高(因为女性和儿童是优先救援的)。

奖励积分

为了使图表更容易复现,我将上述代码制作成了一个函数。

library(dplyr)
library(tidyr)
library(tibble)
library(purrr)
library(scales)
library(ggplot2)

ggspider <- function(p_data, 
legend_title = "Group", 
background_color = "gray97", 
area_fill = TRUE, 
central_distance = 0.2, 
axis_name_offset = 0.2){

circle_coords <- function(r, n_axis = ncol(p_data) - 1){
  fi <- seq(0, 2*pi, (1/n_axis)*2*pi) + pi/2
  x <- r*cos(fi)
  y <- r*sin(fi)

  tibble(x, y, r)
}

(step_1 <- map_df(seq(0, 1, 0.25) + central_distance, circle_coords) %>%
    ggplot(aes(x, y)) +
    geom_polygon(data = circle_coords(1 + central_distance), alpha = 1, fill = background_color) +
    geom_path(aes(group = r), lty = 2, alpha = 0.5) +
    theme_void())

axis_coords <- function(n_axis){
  fi <- seq(0, (1 - 1/n_axis)*2*pi, (1/n_axis)*2*pi) + pi/2
  x1 <- central_distance*cos(fi)
  y1 <- central_distance*sin(fi)
  x2 <- (1 + central_distance)*cos(fi)
  y2 <- (1 + central_distance)*sin(fi)

  tibble(x = c(x1, x2), y = c(y1, y2), id = rep(1:n_axis, 2))
}

text_data <- p_data %>%
  select(-group) %>%
  map_df(~ min(.) + (max(.) - min(.)) * seq(0, 1, 0.25)) %>%
  mutate(r = seq(0, 1, 0.25)) %>%
  pivot_longer(-r, names_to = "parameter", values_to = "value")

text_coords <- function(r, n_axis = ncol(p_data) - 1){
  fi <- seq(0, (1 - 1/n_axis)*2*pi, (1/n_axis)*2*pi) + pi/2 + 0.01*2*pi/r
  x <- r*cos(fi)
  y <- r*sin(fi)

  tibble(x, y, r = r - central_distance)
}

labels_data <- map_df(seq(0, 1, 0.25) + central_distance, text_coords) %>%
  bind_cols(text_data %>% select(-r))

rescaled_coords <- function(r, n_axis){
  fi <- seq(0, 2*pi, (1/n_axis)*2*pi) + pi/2
  tibble(r, fi) %>% mutate(x = r*cos(fi), y = r*sin(fi)) %>% select(-fi)
}

rescaled_data <- p_data %>% 
  mutate(across(-group, rescale)) %>%
  mutate(copy = pull(., 2)) %>%
  pivot_longer(-group, names_to = "parameter", values_to = "value") %>%
  group_by(group) %>%
  mutate(coords = rescaled_coords(value + central_distance, ncol(p_data) - 1)) %>%
  unnest

  step_1 + 
    geom_line(data = axis_coords(ncol(p_data) - 1), 
              aes(x, y, group = id), alpha = 0.3) +
    geom_point(data = rescaled_data, 
              aes(x, y, group = group, col = group), size = 3) +
    geom_path(data = rescaled_data, 
              aes(x, y, group = group, col = group), size = 1) +
    {if(area_fill == TRUE) geom_polygon(data = rescaled_data, 
                            aes(x, y, group = group, 
                                col = group, fill = group), 
                                size = 1, alpha = 0.05, show.legend = FALSE)} +
    geom_text(data = labels_data, 
                     aes(x, y, label = value), alpha = 0.65) +
    geom_text(data = text_coords(1 + central_distance + axis_name_offset), 
              aes(x, y), label = labels_data$parameter[1:(ncol(p_data)-1)]) +
    labs(col = legend_title) +
    theme(legend.position = "bottom",
          legend.text = element_text(size = 12),
          legend.title = element_text(size = 12))
}

现在,我们可以在一些不同的数据上轻松测试这个函数,比如内置于 R 中的mtcars数据集。

p_data <- mtcars %>%
  rownames_to_column(var = "group") %>%
  as_tibble() %>%
  tail(3) %>%
  select(1:7)

ggspider(p_data)

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

mtcars 数据集的蛛网图。图片由作者提供

结论

本文展示了如何在 R 中从头构建蛛网图。虽然我知道的 R 包中没有支持这种图表的,但利用ggplot2包中的分层图形语法方法为我提供了自己创建这种图表的工具。当然,图表的美学方面仍有改进的空间,但那是另一个文章的话题。

就这些了。我希望你觉得这篇文章有用,并将其用于未来制作更多精美的蛛网图。享受吧!

附言:如果你喜欢这篇文章,请点赞并关注,以便未来获得更多类似内容。此外,随时欢迎提出你认为值得在 R 中实现的其他有趣可视化建议。

如何制作 AI 图像编辑聊天机器人

原文:towardsdatascience.com/how-to-make-an-ai-image-editing-chatbot-1ddd0209884

Stable Diffusion InstructPix2Pix 在 Panel 应用中

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

·发表于 Towards Data Science ·阅读时间 5 分钟·2023 年 2 月 1 日

Sophia YangPhilipp Rudiger

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

使用 InstructPix2Pix 进行图像编辑的示例。(原图由 Pietro De Grandi 提供,来源于 Unsplash

InstructPix2Pix 是一种条件扩散模型,将语言模型 GPT-3 和文本到图像模型 Stable Diffusion 结合起来,根据用户提示进行图像编辑。受到 InstructPix2Pix 项目 和在 HuggingFace 上托管的 多个 应用 的启发,我们有兴趣在 Panel 中创建一个 AI 图像编辑聊天机器人。Panel 是一个 Python 仪表板工具,可以让我们通过仅几行代码构建这个聊天机器人。

在本文中,我们将逐步展示如何制作这个聊天机器人:

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

Stable Diffusion InstructPix2Pix 聊天机器人在 Panel 应用中

通过 Anaconda 设置 Python

由于我们要制作一个 Python 应用程序,因此首先需要安装 Python。下载 Anaconda 是获取 Python 和 Conda 环境管理的最简单和推荐的方式。

然后你需要创建一个新的环境(可选但推荐),并安装此项目所需的包。

conda create -n chatbot_env
conda activate chatbot_env
conda install diffusers transformers accelerate xformers hvplot panel notebook -c pytorch -c conda-forge

启动 Jupyter Notebook

接下来,我们可以启动一个 Jupyter Notebook(在命令行中输入jupyter notebook),并在笔记本中导入所需的包:

import io

import numpy as np
import panel as pn
import param
import PIL
import requests
import torch

from diffusers import StableDiffusionInstructPix2PixPipeline

pn.extension('texteditor', template="bootstrap", sizing_mode='stretch_width')

使用 InstructPix2Pix 模型 API

这个 Hugging Face 页面详细介绍了如何使用 InstructPix2Pix 模型 API。我们需要定义 InstructPix2Pix 模型的 ID 并从 StableDiffusionInstructPix2PixPipeline 获取预训练模型。注意,建议在 GPU 上运行此模型。

在我们的面板应用中,我们直接使用这个预训练模型。我们创建了一个辅助函数normaize_image来规范化输入图像的大小和通道,然后创建了一个函数new_image,基于提示、原始图像和一些高级特征设置来创建新图像。

model_id = "timbrooks/instruct-pix2pix"

pipe = pn.state.cache['pipe'] = StableDiffusionInstructPix2PixPipeline.from_pretrained(
    model_id, torch_dtype=torch.float16
).to("cuda")

def normalize_image(value, width):
    """
    normalize image to RBG channels and to the same size
    """
    b = io.BytesIO(value)
    image = PIL.Image.open(b).convert("RGB")
    aspect = image.size[1] / image.size[0]
    height = int(aspect * width)
    return image.resize((width, height), PIL.Image.LANCZOS)

def new_image(prompt, image, img_guidance, guidance, steps, width=600):
    """
    create a new image from the StableDiffusionInstructPix2PixPipeline model
    """
    edit = pipe(
        prompt,
        image=image,
        image_guidance_scale=img_guidance,
        guidance_scale=guidance,
        num_inference_steps=steps,
    ).images[0]
    return edit

创建面板应用

步骤 1:定义面板小部件

为了制作这个应用,我们需要以下小部件:

  • 一个文件输入小部件,用于加载图像file_input

  • 一个文本输入小部件,允许用户输入提示prompt

  • 三个滑块小部件,用于控制特征设置:img_guidanceguidancesteps

  • 一个按钮小部件,用于显示运行应用的按钮run_button

然后,我们将所有小部件组织成一个Panel对象:widgets

file_input = pn.widgets.FileInput(width=600)
prompt = pn.widgets.TextEditor(
    value="", placeholder="Enter image editing instruction here...", height=160, toolbar=False
)
img_guidance = pn.widgets.DiscreteSlider(
    name="Image guidance scale", options=list(np.arange(1, 10.5, 0.5)), value=1.5
)
guidance = pn.widgets.DiscreteSlider(
    name="Guidance scale", options=list(np.arange(1, 10.5, 0.5)), value=7
)
steps = pn.widgets.IntSlider(
    name="Inference Steps", start=1, end=100, step=1, value=20
)
run_button = pn.widgets.Button(name="Run!")

widgets = pn.Row(
    pn.Column(prompt, run_button, margin=5),
    pn.Card(
        pn.Column(img_guidance, guidance, steps),
        title="Advanced settings", margin=10
    ), width=600
)

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

小部件

步骤 2:在一个函数中定义所有对话

这可能是最重要的一步。在这一步中,我们定义了一个名为get_conversations的函数,具有以下功能:

  • 每次加载新文件时,我们都会保存新图像,并准备好进行编辑。

  • 我们将图像规范化为 RGB 通道,并确保它们的大小相同。这在图像尺寸过大时特别有用。如果将大图像输入到模型中,你可能会遇到内存不足的错误。

  • 如果有提示,我们将生成新图像。

  • 所有的提示和图像都会附加到convos列表中,并显示在一个面板对象中。

# define global variables to keep track of things
convos = []  # store all panel objects in a list
image = None
filename = None

def get_conversations(_, img, img_guidance, guidance, steps, width=600):
    """
    Get all the conversations in a Panel object
    """
    global image, filename
    prompt_text = prompt.value
    prompt.value = ""

    # if the filename changes, open the image again
    if filename != file_input.filename:
        filename = file_input.filename
        image = normalize_image(file_input.value, width)
        convos.clear()

    # if there is a prompt run output
    if prompt_text:
        image = new_image(prompt_text, image, img_guidance, guidance, steps)
        convos.extend([
            pn.Row(
                pn.panel("\U0001F60A", width=10),
                prompt_text,
                width=600
            ),
            pn.Row(
                pn.panel(image, align='end', width=500),
                pn.panel("\U0001F916", width=10),
                align='end'
            )
        ])
    return pn.Column(*convos, margin=15, width=575)

步骤 3:将小部件绑定到函数

你可能会想:get_conversations什么时候运行?当我们点击运行按钮或更改任何小部件时会运行。为实现这一点,我们将函数与小部件“绑定”,使函数对小部件的变化做出反应:

# bind widgets to functions
interactive_upload = pn.panel(pn.bind(pn.panel, file_input, width=575, min_height=400, margin=15))

interactive_conversation = pn.panel(
    pn.bind(
        get_conversations, run_button, file_input, img_guidance, guidance, steps
    ), loading_indicator=True
)

步骤 4:定义布局

最后,我们将小部件和对话组织成一个合理的布局,我们使用pn.Column将多个面板对象排列在一个垂直容器中。随意尝试不同的布局 😃

 # layout
pn.Column(
    "## \U0001F60A Upload an image file and start editing!",
    file_input,
    interactive_upload,
    interactive_conversation,
    widgets
).servable(title="Panel Stable Diffusion InstructPix2pix Image Editing Chatbot")

步骤 5:服务应用

现在你已经准备好所有的代码,可以开始服务你的应用了。要在本地服务它,运行panel serve app.py(假设你的文件名为 app.py)。我们还在 Hugging Face 上服务了我们的应用:huggingface.co/spaces/sophiamyang/Panel_InstructPix2Pix。请注意,我们只会保持它在线几天。GPU 是昂贵的!

完整代码

你可以在这里找到完整的代码:

huggingface.co/spaces/sophiamyang/Panel_InstructPix2Pix/blob/main/app.py

你可以在哪里了解更多关于 Panel 的信息?

  • 查看我们之前的博客文章:3 种构建 Panel 可视化仪表板的方法。

  • 查看官方文档:holoviz.org、panel.holoviz.org 和 hvplot.holoviz.org。

  • 查看 awesome-panel.org/ 获取灵感。

  • 如果你有问题或想与其他 Panel 用户联系,请访问 discourse.holoviz.org/.

结论

在本文中,我们展示了如何在 Panel 中构建 AI 图像编辑聊天机器人。使用预训练的 InstructPix2Pix 模型,我们的聊天机器人具备了基于用户提示的惊人图像编辑功能。试试看,并告诉我们你的想法!

致谢:

感谢Jim Bednar的指导和支持!

参考资料:

. . .

Sophia YangPhilipp Rudiger于 2023 年 1 月 31 日发布

Sophia Yang 是 Anaconda 的高级数据科学家。通过LinkedInTwitterYouTube与我联系,并加入 DS/ML 读书俱乐部 ❤️

如何用 Rust 让你的 Python 包真正加速

原文:towardsdatascience.com/how-to-make-your-python-packages-really-fast-with-rust-91a9bebacbc2?source=collection_archive---------2-----------------------#2023-05-31

告别,慢速代码

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

·

关注 发表在 Towards Data Science · 6 分钟阅读 · 2023 年 5 月 31 日

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

照片由Chris Liverani拍摄,发布在Unsplash

Python 是……慢。这并不是什么新发现。很多动态语言都是如此。实际上,Python 的速度如此之慢,以至于许多对性能有严格要求的 Python 包作者转向了另一种语言——C。但 C 并不好玩,而且 C 有足够多的陷阱可以让一个蜈蚣陷入困境。

介绍 Rust。

Rust 是一种内存高效的语言,没有运行时或垃圾回收器。它速度极快,可靠性极高,并且有一个非常优秀的社区。此外,由于像 PyO3 和 maturin 这样的优秀工具,它也非常容易嵌入到你的 Python 代码中。

听起来很兴奋?太好了!因为我接下来将一步一步向你展示如何在 Rust 中创建一个 Python 包。如果你对 Rust 一无所知,也不用担心——我们不会做任何过于复杂的事情,所以你仍然可以跟得上。准备好了吗?让我们来氧化这条蛇吧。

前提条件

在开始之前,你需要在你的机器上安装 Rust。你可以通过访问 rustup.rs 并按照那里的说明进行安装。我还建议创建一个虚拟环境,以便用于测试你的 Rust 包。

脚本概述

这是一个脚本,给定一个数字 n,它将计算第 n 个斐波那契数 100 次,并记录所需时间。

这是一个非常初级、完全未优化的函数,使用纯 Python 也有很多方法可以使其更快,但我今天不会讨论那些方法。相反,我们将利用这段代码来创建一个 Rust 中的 Python 包。

Maturin 设置

第一步是安装 maturin,这是一个用于构建和发布 Rust crate 作为 Python 包的构建系统。你可以通过 pip install maturin 来完成安装。

接下来,为你的包创建一个目录。我将其命名为 fibbers。最后一步是从你的新目录中运行 maturin init。此时,你将被提示选择要使用的 Rust 绑定。选择 pyo3

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

图片来源:作者。

现在,如果你查看你的 fibbers 目录,你会看到一些文件。Maturin 为我们创建了一些配置文件,即 Cargo.tomlpyproject.tomlCargo.toml 文件是 Rust 构建工具 cargo 的配置文件,包含有关包的一些默认元数据、构建选项和 pyo3 的依赖项。pyproject.toml 文件是相当标准的,但它被设置为使用 maturin 作为构建后端。

Maturin 还会为发布你的包创建一个 GitHub Actions 工作流。这虽然是个小事,但在维护开源项目时会让生活变得轻松多了。然而,我们最关心的文件是 src 目录中的 lib.rs 文件。

这是生成的文件结构的概述。

fibbers/
├── .github/
│   └── workflows/
│       └── CI.yml
├── .gitignore
├── Cargo.toml
├── pyproject.toml
└── src/
    └── lib.rs

编写 Rust 代码

Maturin 已经使用我们之前提到的 PyO3 绑定为我们创建了一个 Python 模块的框架。

这段代码的主要部分是 sum_as_string 函数,它被标记为 pyfunction 属性,以及 fibbers 函数,它代表我们的 Python 模块。fibbers 函数实际上只是将 sum_as_string 函数注册到我们的 fibbers 模块中。

如果我们现在安装这个,我们将能够从 Python 调用fibbers.sum_as_string(),一切都会按预期工作。

不过,我首先要做的是将sum_as_string函数替换为我们的fib函数。

这与我们之前编写的 Python 实现完全相同——它接受一个正整数 n 并返回第 n 个斐波那契数。我还将我们的新函数注册到fibbers模块,所以我们可以开始使用了!

基准测试我们的函数

要安装我们的fibbers包,我们只需在终端中运行maturin develop即可。这将下载并编译我们的 Rust 包,并将其安装到我们的虚拟环境中。

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

图片由作者提供。

现在,在我们的fib.py文件中,我们可以导入fibbers,打印fibbers.fib()的结果,然后为我们的 Rust 实现添加一个timeit案例。

如果我们现在运行第 10 个斐波那契数,你会发现我们的 Rust 函数比 Python 快约 5 倍,尽管我们使用的是相同的实现!

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

图片由作者提供。

如果我们计算第 20 和第 30 个斐波那契数,我们可以看到 Rust 比 Python 快约 15 倍。

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

第 20 个斐波那契数结果。图片由作者提供。

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

第 30 个斐波那契数结果。图片由作者提供。

但如果我告诉你我们还没有达到最大速度呢?

你看,默认情况下,maturin develop会构建 Rust crate 的开发版本,这会放弃许多优化以减少编译时间,这意味着程序运行的速度不会达到最佳。如果我们返回到fibbers目录,再次运行maturin develop,但这次加上--release标志,我们将得到优化后的生产就绪版本的二进制文件。

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

如果我们现在基准测试第 30 个斐波那契数,我们会看到 Rust 现在比 Python 快了令人惊叹的40 倍

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

第 30 个斐波那契数,优化版。图片由作者提供。

Rust 的限制

然而,我们的 Rust 实现确实有问题。如果我们尝试使用fibbers.fib()获取第 50 个斐波那契数,你会看到我们实际上遇到了溢出错误,并且得到的答案与 Python 不同。

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

Rust 经历了整数溢出。图片由作者提供。

这是因为,与 Python 不同,Rust 有固定大小的整数,32 位整数不足以容纳我们的第 50 个斐波那契数。

我们可以通过将 Rust 函数中的类型从u32更改为u64来解决这个问题,但这会使用更多的内存,并且可能不是每台机器都支持。我们还可以使用像num_bigint这样的 crate 来解决这个问题,但这超出了本文的范围。

另一个小限制是使用 PyO3 绑定会有一些开销。你可以在这里看到我仅仅获取第一个斐波那契数,实际上 Python 比 Rust 更快,这要归功于这种开销。

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

Python 在 n=1 时更快。图片来自作者。

需要记住的事项

本文中的数据不是在完美的机器上记录的。基准测试在我的个人机器上进行,可能无法反映真实世界的问题。请对像这样的微基准测试保持谨慎,因为它们通常不完美,并模拟了许多实际程序的方面。

希望你觉得这篇文章有帮助,并且它鼓励你尝试用 Rust 重写 Python 代码中的性能关键部分。要注意,虽然 Rust 可以加速很多东西,但如果你的 CPU 循环大部分时间都花在系统调用或网络 IO 上,它不会提供太多优势,因为这些减速超出了程序的范围。

如果你想查看更多用 Rust 编写的 Python 包的完整示例,请查看以下示例:

本文基于我的这段视频脚本,所以如果你更倾向于视觉学习,或者希望有快速参考资料,欢迎查看:

或者查看 GitHub 上的代码:

[## youtube/010-creating-python-packages-with-rust at main · isaacharrisholt/youtube

每个人都知道程序速度不是 Python 的强项。这就是为什么有如此多的数据科学…

github.com](https://github.com/isaacharrisholt/youtube/tree/main/010-creating-python-packages-with-rust?source=post_page-----91a9bebacbc2--------------------------------)

保持快速!

Isaac

如何使用 Azure Synapse 遮蔽 PII 数据

原文:towardsdatascience.com/how-to-mask-pii-data-with-fpe-using-azure-synapse-12902547af2b?source=collection_archive---------16-----------------------#2023-05-23

学习如何在大规模情况下使用格式保留加密(FPE),安全地将数据从生产环境移动到测试环境

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

·

关注 发表在Towards Data Science ·7 分钟读·2023 年 5 月 23 日

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

数据遮蔽 — 图片来自Mika BaumeisterUnsplash

1. 介绍

许多企业需要其测试环境中的代表性数据。通常,这些数据是从生产环境复制到测试环境中的。但是,个人可识别信息(PII)数据通常是生产环境的一部分,必须先进行遮蔽。Azure Synapse 可以利用格式保留加密来遮蔽数据,然后将数据复制到测试环境中。参见下方的架构图。

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

1. 使用 Azure Synapse 的格式保留加密 — 作者图像

在这个博客和库[azure-synapse_mask-data_format-preserved-encryption](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption)中,讨论了如何在 Synapse 中创建可扩展且安全的掩码解决方案。在下一章中,将讨论项目的属性。然后在第三章中部署项目,第四章中测试,并在第五章中得出结论。

2. Synapse 中 PII 掩码应用的属性

Synapse 中 PII 掩码应用程序的属性如下:

  • 可扩展的掩码功能: 基于开源 Python 库如 ff3,可以实现对 ID、姓名、电话号码和电子邮件的 FPE 加密。加密示例为 06–23112312 => 48–78322271,

    Kožušček123a => Sqxbblkd659p, bremersons@hotmail.com => h0zek2fbtw@fr5wsdh.com

  • 安全性: 使用的 Synapse Analytics 工作区具有以下安全措施:私有端点连接到存储账户、Azure SQL(公共访问可以禁用)和其他 100 个数据源(包括本地);托管身份用于验证存储账户、Azure SQL 和 Azure 密钥保管库中的秘密,这些秘密由 ff3 用于加密;RBAC 授权授予对 Azure 存储、Azure SQL 和 Azure 密钥保管库的访问权限,以及 Synapse 数据外泄保护 防止数据被恶意内部人员窃取

  • 性能: 可扩展的解决方案,使用了 Spark。可以通过使用更多 vcores、增加更多执行器(VM)和/或使用更多 Spark 池来扩展解决方案。在一次基本测试中,250MB 数据和 6 列被加密并写入存储中,使用中等规模的 Spark 池,2 个执行器(VM)和每个执行器 8 个 vcores(线程)(总共 16 个 vcores/线程),耗时 1 分 45 秒

  • 编排: Synapse 管道可以端到端地编排整个过程。也就是说,可以使用超过 100 个不同的连接器从云端/本地数据库中提取数据,将其暂存到 Azure 存储中,进行掩码处理,然后再发送回低环境进行测试。

在下图中,定义了安全属性。

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

2. 掩码应用程序的安全属性 — 作者图像

在下一章中,将部署和配置掩码应用程序,包括测试数据。

3. 在 Synapse 中部署 PII 掩码应用程序

在本章中,项目将变得生动,并在 Azure 中部署。将执行以下步骤:

  • 3.1 前提条件

  • 3.2 部署资源

  • 3.3 配置资源

3.1 前提条件

本教程中需要以下资源:

最后,将下面的 git 仓库克隆到本地计算机。如果你没有安装 git,可以从网页上直接下载 zip 文件。

3.2 部署资源

需要部署以下资源:

  • 3.2.1 Azure Synapse Analytics 工作区: 部署启用了数据泄露保护的 Synapse。确保创建了主要存储帐户。还要确保 Synapse 部署时 1) 启用了管理 VNET,2) 有指向存储帐户的私有端点,3) 仅允许向批准的目标发送出站流量,见下图:

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

3.2. 启用管理 VNET 和数据泄露保护的 Azure Synapse — 作者提供的图片

  • 3.2.2 Azure Key Vault: 该 Key Vault 将用于存储用于在 [Synapse/mask_data_fpe_prefixcipher.ipynb](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption/blob/main/Synapse/mask_data_fpe_prefixcipher.ipynb)[Synapse/mask_data_fpe_ff3.ipynb](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption/blob/main/Synapse/mask_data_fpe_ff3.ipynb) 中创建 HMAC 和加密的秘密

3.3. 配置资源

需要配置以下资源

  • 3.3.1 存储帐户 - 文件系统: 在存储帐户中,创建名为 bronzegold 的新文件系统。然后上传 [Data\SalesLT.Customer.txt](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption/blob/main/Data/SalesLT.Customer.txt) 中的 csv 文件。如果需要处理更大的数据集,可以参考 250MB 和 1M 记录的集合

  • 3.3.2 Azure Key Vault - 秘密: 创建名为 fpekeyfpetweak 的秘密。确保为两个秘密都添加了十六进制值。如果 Azure Key Vault 是在启用公共访问的情况下部署的(以便通过 Azure Portal 创建秘密),现在不再需要公共访问,可以禁用公共访问(因为在 3.3.4 中将创建 Synapse 和 Azure Key Vault 之间的私有链接连接)

  • 3.3.3 Azure Key Vault - 访问控制: 确保在 Azure Key Vault 的访问策略中,Synapse 管理标识具有获取秘密的权限,见下图。

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

3.3.3 Synapse 管理标识在 Key Vault 中具有获取秘密的权限 — 作者提供的图片

  • 3.3.4 Azure Synapse Analytics - 私有链接到 Azure Key Vault:从 Azure Synapse 工作区管理的 VNET 和你的密钥库创建一个私有终结点。请求从 Synapse 发起,需要在 AKV 网络中进行批准。见下图,其中私有终结点已获批准。

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

3.3.4 Synapse 和 Key Vault 之间的私有链接连接 — 作者提供的图片

  • 3.3.5 Azure Synapse Analytics - 链接服务连接到 Azure Key Vault: 从 Azure Synapse 工作区和你的密钥库创建一个链接服务,见下图。

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

3.3.5 Synapse 和 Key Vault 之间的链接服务以获取密钥 — 作者提供的图片

  • 3.3.6 Azure Synapse Analytics - Spark 集群:创建一个中型的 Spark 集群,具有 3 到 10 个节点,并且可以扩展到 2 到 3 个执行器,见下图。

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

3.3.6 在 Synapse 中创建 Spark 集群 — 作者提供的图片

  • 3.3.7 Azure Synapse Analytics - 库上传: 笔记本Synapse/mask_data_fpe_ff3.ipynb使用了ff3进行加密。由于 Azure Synapse Analytics 创建时启用了数据泄露保护,因此不能通过从 pypi.org 拉取进行安装,因为这需要在 Azure AD 租户外的出站连接。下载 pycryptodome wheel 这里、ff3 wheel 这里 和 Unidecode 库 这里(Unidecode 库用于将 Unicode 转换为 ASCII,以防在 ff3 中使用大量字母进行数据加密)。然后将 wheels 上传到工作区以使其可信,最后将其附加到 Spark 集群,见下图。

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

3.3.7 从 Synapse 工作区附加的 Python 包到 Spark 集群 — 作者提供的图片

  • 3.3.8 Azure Synapse Analytics - 笔记本上传: 上传笔记本[Synapse/mask_data_fpe_prefixcipher.ipynb](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption/blob/main/Synapse/mask_data_fpe_prefixcipher.ipynb)[Synapse/mask_data_fpe_ff3.ipynb](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption/blob/main/Synapse/mask_data_fpe_ff3.ipynb)到你的 Azure Synapse Analytics 工作区。确保在笔记本中替换存储帐户、文件系统、密钥库名称和 Keyvault 链接服务的值。

  • 3.3.9 Azure Synapse Analytics - 笔记本 - Spark 会话:打开笔记本 Synapse/mask_data_fpe_prefixcipher.ipynb 的 Spark 会话,确保选择超过 2 个执行器,并使用托管身份运行,请参见下面的截图。

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

3.3.9 作为托管身份运行 Spark 会话 — 作者提供的图片

4. 测试解决方案

部署和配置所有资源后,可以运行笔记本。笔记本 Synapse/mask_data_fpe_prefixcipher.ipynb 包含掩盖数字值、字母数字值、电话号码和电子邮件地址的功能,见下面的功能描述。

000001 => 359228
Bremer => 6paCYa
Bremer & Sons!, LTD. => OsH0*VlF(dsIGHXkZ4dK
06-23112312 => 48-78322271
bremersons@hotmail.com => h0zek2fbtw@fr5wsdh.com
Kožušček123a => Sqxbblkd659p

如果使用 1M 数据集并加密 6 列,处理大约需要 2 分钟。这可以通过 1) 使用更多 vcores(从中型到大型)进行扩展,使用更多执行器进行扩展,或创建第二个 Spark 池来轻松扩展。请参见下面的截图。

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

4. 笔记本成功运行 — 作者提供的图片

在 Synapse 中,笔记本可以轻松嵌入到管道中。这些管道可以用于协调活动,首先将数据从生产源上传到存储,运行笔记本来掩盖数据,然后将掩盖后的数据复制到测试目标。一个示例管道可以在 [Synapse/synapse_pipeline.json](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption/blob/main/Synapse/synapse_pipeline.json) 找到。

5. 结论

许多企业需要在测试环境中拥有代表性的样本数据。通常,这些数据是从生产环境复制到测试环境的。在本博客和 Git 仓库 [-synapse_mask-data_format-preserved-encryption](https://github.com/rebremer/azure-synapse_mask-data_format-preserved-encryption) 中,讨论了一种可扩展且安全的掩盖解决方案,该方案利用了 Spark、Python 和开源库 ff3 的强大功能,请参见下面的架构。

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

5. 使用 Azure Synapse 的格式保留加密 — 作者提供的图片

如何测量和改善预测集成的多样性

原文:towardsdatascience.com/how-to-measure-and-improve-the-diversity-of-forecasting-ensembles-2ec899014d6

使用偏差-方差-协方差分解来分析预测集成

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

·发表于 Towards Data Science ·5 分钟阅读·2023 年 1 月 31 日

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

图片来源于 henry perksUnsplash

在本文中,你将学习偏差-方差-协方差分解方法。

回归模型的误差可以通过偏差-方差权衡来分析。对于集成模型,这种误差可以通过协方差项进一步分解。

以下是如何使用这种分解来改进预测集成的方法。

介绍

个体模型之间的多样性是构建成功集成的关键要素

每个模型应该做出准确的预测。但这些预测也应该与其他模型不同。因此,综合预测可以减少个体误差的影响。

这引出了两个问题:

  1. 我们如何测量集成的多样性?

  2. 我们如何在集成中引入多样性?

让我们深入探讨这些问题。

测量多样性

偏差-方差权衡 是分析回归模型的标准方法。偏差涉及预测值与实际值之间的平均距离。方差涉及不同样本上的预测变异性。

低偏差意味着高方差,反之亦然。这种权衡与模型的复杂性有关。越来越复杂的模型往往具有较低的偏差(但方差较高)。

预测集成也是一种回归模型。它可以分解为这两个术语。但,最好使用三重分解来分析:即偏差-方差-协方差分解。

这种分解定义如下:

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

上述方程中的术语是具有M模型的集成的平均偏差、平均方差和平均协方差

我们已经知道了偏差和方差项。除了这些,集成的期望误差还取决于协方差项。协方差衡量一对模型如何一起变化。因此,它是量化多样性的好方法。协方差值越大(即多样性越低),期望误差也越大。

你可以这样理解:

期望误差 = 平均偏差 + 平均方差 - 多样性

因此,集成多样性直接影响其期望的预测性能。

下面是如何编码这个分解的方法:

import numpy as np
import pandas as pd

class BiasVarianceCovariance:

    @classmethod
    def get_bvc(cls, y_hat: pd.DataFrame, y: np.ndarray):
        return cls.avg_sqr_bias(y_hat, y), cls.avg_var(y_hat), cls.avg_cov(y_hat)

    @staticmethod
    def avg_sqr_bias(y_hat: pd.DataFrame, y: np.ndarray):
        """
        :param y_hat: predictions as pd.DataFrame with shape (n_observations, n_models).
        The predictions of each model are in different columns
        :param y: actual values as np.array
        """
        return (y_hat.mean(axis=0) - y.mean()).mean() ** 2

    @staticmethod
    def avg_var(y_hat: pd.DataFrame):
        M = y_hat.shape[1]

        return y_hat.var().mean() / M

    @staticmethod
    def avg_cov(y_hat: pd.DataFrame):
        M = y_hat.shape[1]
        cov_df = pd.DataFrame(np.cov(y_hat))
        np.fill_diagonal(cov_df.values, 0)
        cov_term = cov_df.values.sum() * (1 / (M * (M - 1)))

        return cov_term

你可以在参考文献[1]中找到有关偏差-方差-协方差分解的更多细节。

创建多样化的集成

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

Franki ChamakiUnsplash上的照片

偏差-方差-协方差分解显示了鼓励集成多样性的重要性。你如何做到这一点?

这里有三种可能的方法:

  1. 操作训练数据;

  2. 使用不同的算法或配置;

  3. 剪枝集成。

操作训练数据

一些最成功的集成方法遵循这种方法。例如,bagging 和 boosting。

Bagging 是一个决策树的集成。对于每棵树,使用自助法技术对可用数据进行重采样。因此,每棵树都有不同的训练集,从而引入了多样性。随机森林也进行自助法采样,并且还有更多操作。他们向解释变量的使用方式中添加了随机性,这进一步增加了树之间的多样性。

提升也会改变输入数据,但方式不同。一个关键方面是模型是按顺序训练的。每次迭代后,训练实例会根据之前的错误重新加权。

使用不同的算法或配置

改变算法是一种快速而简便的提高集成多样性的方法。

不同的方法(例如决策树和线性回归)对数据有不同的假设。这导致模型表现不同。

集成剪枝

提高多样性的另一种方法是通过集成剪枝

剪枝指的是从集成中移除不需要的模型。在这种情况下,你会丢弃高度相关的模型。这不仅能获得更好的多样性,还能降低成本。

案例研究:随机森林的分解

让我们使用偏差-方差-协方差分解来分析随机森林的误差。

在这个例子中,我们将使用有关太阳黑子的时间序列。

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

月度太阳黑子时间序列[3]。图片作者。

你可以按如下方式训练随机森林进行预测:

import numpy as np
import pandas as pd

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

from pmdarima.datasets import load_sunspots

# src module here: https://github.com/vcerqueira/blog
from src.tde import time_delay_embedding
from src.ensembles.bvc import BiasVarianceCovariance

# load time series 
series = load_sunspots(as_series=True) # GPL-3

# train test split
train, test = train_test_split(series, test_size=0.3, shuffle=False, random_state=1)

# time series for supervised learning
train_df = time_delay_embedding(train, n_lags=12, horizon=1)
test_df = time_delay_embedding(test, n_lags=12, horizon=1)

# creating the predictors and target variables
target_var = 'Series(t+1)'
X_train, y_train = train_df.drop(target_var, axis=1), train_df[target_var]
X_test, y_test = test_df.drop(target_var, axis=1), test_df[target_var]

# training a random forest ensemble with 100 decision trees 
rf = RandomForestRegressor(n_estimators=100, random_state=1)
rf.fit(X_train, y_train)

# getting predictions from each tree in RF
rf_pred = [tree.predict(X_test) for tree in rf.estimators_]
rf_pred = pd.DataFrame(rf_pred).T

# bias-variance-covariance decomposition
rf_a_bias, rf_a_var, rf_a_cov = BiasVarianceCovariance.get_bvc(rf_pred, y_test.values)

这是预测样本:

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

随机森林中树的预测样本。组合预测用粗体藏青色表示。图片由作者提供。

这里是错误分解成每一项的方式:

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

偏差、方差和协方差项(对数缩放)。图片由作者提供。

你可以利用这些信息来指导集成模型的发展。

在这个例子中,大部分的期望误差是由于协方差项造成的。你可以通过提高集成的多样性来减少它。我们探讨了三种方法来做到这一点。例如,你可以尝试通过移除相关的树来修剪集成。

关键要点

  • 预测集成的期望误差可以分解为三个部分:偏差、方差和协方差;

  • 协方差项衡量集成中的多样性;

  • 这种分解对指导集成模型的发展非常有价值;

  • 提高集成多样性有很多方法。这些方法包括操作训练数据、使用不同的算法或进行集成修剪。

感谢阅读,我们下一个故事见!

相关文章

参考文献

[1] Brown, G., Wyatt, J., Harris, R., & Yao, X. (2005). 多样性创建方法:调查与分类。信息融合, 6(1), 5–20。

[2] Brown, Gavin, 等。“回归集成中的多样性管理。” 机器学习研究杂志 6.9 (2005)。

[3] 太阳黑子时间序列。GPL-3 许可证

如何测量机器学习嵌入的漂移

原文:towardsdatascience.com/how-to-measure-drift-in-ml-embeddings-ee8adfe1e55e?source=collection_archive---------0-----------------------#2023-06-14

我们评估了五种嵌入漂移检测方法

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

·

关注 发表在 数据科学前沿 ·10 分钟阅读·2023 年 6 月 14 日

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

图片来源:作者。

为什么要监控嵌入漂移?

当机器学习系统投入生产时,你通常不会立即获得真实标签。模型会做出预测或分类,但你不知道它的准确性如何。你必须等一会儿(或者很久!)才能获得标签,以衡量模型的真实质量。

当然,测量实际表现是最有效的。但如果由于反馈延迟而无法做到这一点,则可以查看一些有价值的替代指标。其中之一是检测模型预测的漂移(“模型输出是否与之前不同?”)和模型输入的漂移(“输入到模型的数据是否不同?”)

检测预测和数据漂移可以作为早期预警。 这有助于查看模型是否收到了可能难以处理的新输入。了解环境的变化也可以帮助识别改进模型的方法。

你可以检测到什么类型的问题?例如,如果你的模型进行文本分类,你可能需要注意是否出现了新主题、情感的变化、类别平衡的变化、新语言的文本,或者当你开始接收到大量垃圾邮件或损坏的输入时。

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

作者提供的图像。

但是如何准确地检测这种变化呢?

如果你处理结构化数据,有许多方法可以用来检测漂移:从跟踪模型输出的描述性统计(最小-最大范围、预测类别的占比等),到更复杂的分布漂移检测方法,从像 Kholmogorov-Smirnov 这样的统计测试到像 Wasserstein 距离这样的距离度量。

然而,如果你正在处理 NLP 或 LLM 驱动的应用程序,你将处理非结构化数据。通常以数值表示的形式存在——嵌入。你如何检测这些数值表示中的漂移呢?

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

作者提供的图像。

这是一个相当新的话题,目前还没有“最佳实践”方法。为了帮助理解不同的嵌入漂移检测方法,我们进行了一系列实验。在本文中,我们将概述我们评估的方法,并介绍Evidently,一个用于检测嵌入漂移(以及其他功能)的开源 Python 库。

漂移检测基础

漂移检测的核心思想是当“数据发生显著变化”时发出警报。重点是整体分布。

这与异常值检测不同,当你想要检测与其他数据点不同的个别数据点时。

要测量漂移,你需要决定你的参考数据集是什么。 通常,你可以将当前生产数据与验证数据或你认为具有代表性的过去某个时期的数据进行比较。例如,你可以将本周的数据与上周的数据进行比较,并随着时间推移调整参考数据。

这个选择是针对具体用例的:你需要制定一个对数据稳定性或波动性的预期,并选择一个能够充分捕捉你期望的“典型”输入数据和模型响应分布的参考数据。

你还必须选择漂移检测方法并调整警报阈值。 比较数据集的方法和你认为有意义的变化程度有很多种。有时你关注的是微小的偏差,有时则只是显著的变化。为了调整它,你可以使用历史数据来建模你的漂移检测框架,或者选择一些合理的默认值,然后在实际操作中进行调整。

让我们来详细了解一下“如何”。假设你正在处理文本分类用例,并希望比较数据集(以嵌入形式表示)每周如何变化。你有两个嵌入数据集需要比较。你如何准确地衡量它们之间的“差异”?

我们将审查五种可能的方法。

欧几里得距离

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

作者提供的图片。

你可以对两个分布中的嵌入进行平均,从而得到每个数据集的代表性嵌入。然后,你可以测量它们之间的欧几里得距离。通过这种方式,你可以比较两个向量在多维空间中的“距离”。

欧几里得距离是一种直接且熟悉的度量:它测量连接两个嵌入的线段的长度。你也可以使用其他距离度量,例如余弦、曼哈顿或切比雪夫距离。

作为漂移评分,你将得到一个从 0(对于相同的嵌入)到无穷大的数字。值越高,两个分布之间的距离越远。

这种行为是直观的,但一个可能的缺点是欧几里得距离是一个绝对度量。这使得设置特定的漂移警报阈值更困难:“远”的定义将基于用例和使用的嵌入模型而有所不同。你需要为你监控的不同模型单独调整阈值。

余弦距离

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

作者提供的图片。

余弦距离是另一种流行的距离度量。它不是测量“长度”,而是计算向量之间角度的余弦值。

余弦相似度在机器学习中被广泛使用于搜索、信息检索或推荐系统等任务。要测量距离,你必须从 1 中减去余弦值。

余弦距离 = 1 — 余弦相似度

如果两个分布相同,余弦相似度将为 1,距离将为 0。距离可以取值从 0 到 2。

在我们的实验中,我们发现阈值的调整可能不太直观,因为对于你已经想要检测的变化,它可能会取值低至 0.001。请明智地选择阈值!另一个缺点是,如果应用像 PCA 这样的降维方法,它将不起作用,导致结果不可预测。

基于模型的漂移检测

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

图片由作者提供。

基于分类器的漂移检测方法遵循不同的思路。你可以训练一个分类模型,而不是测量平均嵌入之间的距离,该模型试图识别每个嵌入属于哪个分布。

如果模型可以自信地预测特定嵌入来自哪个分布,那么这两个数据集可能是足够不同的。

你可以测量在验证数据集上计算的分类模型的ROC AUC 分数作为漂移分数,并相应地设置阈值。分数高于 0.5 表明至少有一些预测能力,而分数为 1 则表示“绝对漂移”,即模型总是能识别数据属于哪个分布。

你可以在论文《大声失败:检测数据集变化方法的实证研究》中阅读更多关于该方法的信息。

根据我们的实验,这种方法是一个很好的默认选择。它在我们测试的不同数据集和嵌入模型中都表现一致,无论是否使用 PCA。它还具有任何数据科学家都熟悉的直观阈值。

漂移组件的比例

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

图片由作者提供。

该方法的思想是将嵌入视为结构化的表格数据,并应用数值漂移检测方法——这与你用于检测数值特征漂移的方法相同。每个嵌入的各个组件被视为结构化数据集中的“列”。

当然,与数值特征不同,这些“列”没有可解释的意义。它们是输入向量的一些坐标。然而,你仍然可以测量这些坐标中有多少发生漂移。如果很多发生漂移,数据可能发生了有意义的变化。

要应用此方法,你首先必须计算每个组件的漂移。在我们的实验中,我们使用了Wasserstein(地球移动者)距离并设置了 0.1 的阈值。这一指标的直觉是,当你将阈值设置为 0.1 时,你将注意到“0.1 标准差”大小的变化。

然后,你可以测量漂移组件的总体比例。例如,如果你的向量长度是 400,你可以将阈值设置为 20%。如果超过 80 个组件发生漂移,你将收到漂移检测警报。

这种方法的好处在于你可以在 0 到 1 的范围内测量漂移。你还可以重用你可能用于检测表格数据漂移的熟悉技术。(还有不同的方法,比如 K-L 散度或各种统计测试)。

然而,对某些人来说,这可能是一个限制:你需要设置很多参数。你可以调整基础的漂移检测方法、其阈值以及响应的漂移组件的比例。

总的来说,我们认为这种方法有其优点:它与不同的嵌入模型一致,并且计算速度合理。

最大均值差异 (MMD)

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

图片由作者提供。

你可以使用 MMD 来测量向量均值之间的多维距离。目标是根据分布的均值嵌入 µp 和 µq 在 再现核希尔伯特空间 F 中区分两个概率分布 p 和 q。

形式上:

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

另一种表示 MMD 的方法,其中 K 是再现核希尔伯特空间:

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

你可以将 K 视为某种接近度度量。对象越相似,这个值越大。如果两个分布相同,MMD 应该是 0。如果两个分布不同,MMD 会增加。

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

图片由作者提供。使用 MMD 比较不同的分布。

你可以在论文 “A Kernel Method for the Two-Sample Problem” 中阅读更多内容。

你可以使用 MMD 度量作为漂移分数。这个方法的缺点是许多人不熟悉这种方法,阈值也不可解释。计算通常比其他方法更长。如果你有理由并且对其背后的数学有坚实的理解,我们建议使用它。

选择哪种方法?

为了形成本方法的直觉,我们通过引入人工漂移到三个数据集进行了一系列实验,并随着漂移的增加估计漂移结果。我们还测试了计算速度。

你可以在 单独的博客 中找到所有的代码和实验细节。

以下是我们的建议:

  • 基于模型的漂移检测以及使用 ROC AUC 分数作为漂移检测阈值是一个很好的默认选择。

  • 跟踪漂移的嵌入组件比例从 0 到 1 是一个接近的选择。只要记住,如果你应用了降维,请调整阈值。

  • 如果你想衡量时间中的“漂移大小”,像欧几里得距离这样的度量是一个不错的选择。然而,你需要决定如何设计警报,因为你将处理绝对距离值。

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

图片由作者提供。总结来自于 研究博客

需要记住的是,漂移检测是一种启发式方法。 它是潜在问题的代理。你可能需要实验这种方法:不仅选择方法,还需要根据你的数据调整阈值。你还必须仔细考虑参考窗口的选择,并对你认为有意义的变化做出明智的假设。这将取决于你的错误容忍度、用例以及对模型泛化能力的期望。

你也可以将漂移检测与调试分开。 一旦收到可能的嵌入漂移警报,下一步就是调查具体发生了什么变化。在这种情况下,你必须不可避免地回顾原始数据。

如果可能的话,你甚至可以首先从评估原始数据中的漂移开始。 这样,你可以获得有价值的见解:例如,识别顶级词汇,帮助分类器模型决定文本属于哪个分布,或跟踪可解释的文本描述符——如长度或 OOV 词的比例。

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

使用原始数据进行漂移检测的示例。

Evidently 开源

我们在 Evidently 中实现了所有提到的漂移检测方法,这是一个开源 Python 库,用于评估、测试和监控机器学习模型。

你可以在任何 Python 环境中运行它。只需传递一个 DataFrame,选择包含嵌入的列,并选择漂移检测方法(或使用默认设置!)你还可以将这些检查作为管道的一部分实现,并使用 100 多种其他数据和模型质量检查。

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

来源:关于 嵌入漂移检测* 的示例笔记本。*

你可以查看 入门教程 以了解 Evidently 的功能,或直接跳转到关于嵌入漂移检测的 代码示例

结论

  • 漂移检测是生产环境中监控机器学习模型的宝贵工具。它有助于检测输入数据和模型预测的变化。你可以将其作为模型质量的代理指标,并提醒你潜在的变化。

  • 漂移检测不仅限于处理表格数据。你还可以监控机器学习嵌入的漂移——例如,在运行自然语言处理(NLP)或基于大语言模型(LLM)的应用时。

  • 在这篇文章中,我们介绍了5 种不同的嵌入监测方法,包括欧几里得距离和余弦距离、最大均值差异、基于模型的漂移检测,以及使用数值漂移检测方法跟踪漂移嵌入的比例。所有这些方法都在开源的 Evidently Python 库中实现。

  • 我们推荐基于模型的漂移检测作为一种合理的默认方法。这是因为它能够使用 ROC AUC 评分作为可解释的漂移检测指标,易于调整和操作。这种方法在不同的数据集和嵌入模型上表现一致,使其在不同项目中实践起来更加方便。

这篇文章基于 Evidently 博客上的研究。感谢 Olga Filippova 共同撰写了这篇文章。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值