dot 快速的未来即将在您所在的城市举行活动。

加入我们在 Redis 发布会

在 Redis 上使用 Feast 入门:机器学习特征存储快速入门教程

本教程提供了一个分步的**Feast for Redis 快速入门**,指导您完成一个端到端的示例,该示例展示了如何使用 Feast 与 Redis 作为其在线 机器学习特征存储。它基于 Feast 快速入门教程,但它使用 Redis 在线存储而不是默认的在线存储来提供大规模实时预测。如果您不熟悉 Feast 或 Redis,那么使用 Redis 开始使用 Feast 的最快方式就是通过本教程。有关使用 Redis 的 Feast 的高级介绍,请参考这篇 特征存储和使用 Redis 的 Feast 博客文章。本教程末尾提供了有关 Redis 和 Feast 的更多详细信息以及其他资源。

在本教程中,您将

  1. 部署一个本地特征存储,其中包含一个 Parquet 文件离线存储和 Redis 在线存储。
  2. 使用 Parquet 文件中的演示时间序列特征构建训练数据集。
  3. 将特征值从离线存储物化(加载)到 Redis 在线存储中。
  4. 从 Redis 在线存储读取最新特征以进行推理。

您可以在 Google Colab 或按照以下分步指南在本地主机上运行本教程。

简而言之的 Feast

Feast(**Fea**ture **st**ore)是一个开源特征存储,是 Linux Foundation AI & Data Foundation 的一部分。它可以从低延迟在线存储(用于实时服务)或离线存储(用于模型训练或批处理服务)为模型提供特征数据。它还提供了一个中央注册表,因此**机器学习工程师**和**数据科学家**可以发现机器学习用例的相关特征。以下是 Feast 的高级架构

Feast 是一个 Python 库 + 可选的 CLI。您可以使用 pip 安装 Feast,本教程稍后会介绍。

使用 Redis 的 Feast 解决此流程中的几个常见问题

  1. **训练-服务偏差和复杂的数据连接**:特征值通常存在于多个表中。连接这些数据集可能很复杂、缓慢且容易出错。
    • Feast 使用经过实战检验的逻辑来连接这些表,以确保时间点的一致性,从而防止未来的特征值泄漏到模型中。
  2. **以低延迟和规模提供在线特征可用性:**在推理时,模型通常需要访问尚未准备就绪的特征,并且需要从其他数据源实时预计算这些特征。
    • 通过使用 Redis 部署 Feast,您可以确保在推理时始终可用并实时重新计算必要的特征,并保证低延迟和高吞吐量。
  3. **特征可重用性和模型版本控制:**组织内的不同团队通常无法跨项目重用特征,导致重复创建特征逻辑。模型具有需要进行版本控制的数据依赖项,例如在对模型版本运行 A/B 测试时。
    • Feast 使得能够发现和协作使用先前使用的特征,并能够对特征集(通过特征服务)进行版本控制。
    • Feast 支持特征转换,因此用户可以跨在线/离线用例和模型重用转换逻辑。

使用 Redis 的 Feast 教程概述

在本教程中,我们使用特征存储来生成训练数据并为拼车司机满意度预测模型提供在线模型推理。在演示数据场景中:

  • 我们已经对一些司机进行了调查,以确定他们对使用拼车应用程序的体验的满意度。
  • 我们想对其他用户的司机满意度进行预测,以便我们可以联系潜在的不满意用户。

教程步骤

  1. 安装 Redis 并将 Redis 服务器在后台运行
  2. 安装使用 Redis 的 Feast
  3. 创建一个特征存储库并将 Redis 定义为在线存储
  4. 注册特征定义并部署您的特征存储
  5. 生成训练数据
  6. 将特征加载到您的 Redis 在线存储中
  7. 获取特征向量以进行推理

步骤 1:安装 Redis 并将 Redis 服务器在后台运行

要安装 Redis,请按照以下方法之一进行操作

Ubuntu:

$ sudo snap install redis

Docker:

$ docker run --name redis --rm -p 6379:6379 -d redis

Mac(Homebrew):

$ brew install redis

有关安装 Redis 的其他方法,请访问 此处。有关其他配置信息,请参阅 Redis 快速入门 指南。

步骤 2:安装使用 Redis 的 Feast

使用 pip 安装 Feast SDK 和 CLI

$ pip install 'feast[redis]'

步骤 3:创建一个特征存储库并将 Redis 配置为在线存储

特征存储库是一个包含特征存储和各个特征配置的目录。

步骤 3a:创建一个特征存储库

创建新特征存储库最简单的方法是使用 feast init 命令。这将创建具有初始演示数据的脚手架。

$ feast init feature_repo
$ cd feature_repo

输出:

Creating a new Feast repository in /Users/nl/dev_fs/feast/feature_repo

让我们看一下由此产生的演示存储库本身。它细分为

  • feature_store.yaml 包含一个演示设置,用于配置数据源和在线存储
  • example.py 包含演示特征定义
  • data/ 包含原始演示 parquet 数据

步骤 3b:在 YAML 配置文件中将 Redis 配置为在线存储

要将 Redis 配置为在线存储,我们需要为 feature_store.yaml 中的 typeconnection_string 值设置 online_store,如下所示

project: my_project
registry: data/registry.db
provider: local
online_store:
  type: redis
 connection_string: localhost:6379

provider 定义了原始数据所在的位置(用于生成训练数据和用于服务的特征值),在本演示中,原始数据存储在本地。 online_store 定义了在在线存储数据库(用于服务)中物化(加载)特征值的位置。

请注意,上述配置不同于为教程提供的默认 YAML 文件,该文件改为使用默认在线存储

project: my_project
registry: data/registry.db
provider: local
online_store:
    path: data/online_store.db

因此,通过在 YAML 文件中添加上述两行用于 online_store (type: redis, connection_string: localhost:6379),Feast 就可以将其在线存储读写到 Redis。Redis 在线存储是 Feast 核心代码的一部分,因此 Feast 可以开箱即用地使用 Redis。

步骤 3c:检查 example.py 中的演示特征定义

让我们看一下 example.py 中的演示特征定义(要查看终端中的内容,您可以运行 cat example.py )。

Example.py

# This is an example feature definition file

from google.protobuf.duration_pb2 import Duration

from feast import Entity, Feature, FeatureView, FileSource, ValueType

# Read data from parquet files. Parquet is convenient for local development mode. For
# production, you can use your favorite DWH, such as BigQuery. See Feast documentation
# for more info.
driver_hourly_stats = FileSource(
    path="/content/feature_repo/data/driver_stats.parquet",
    event_timestamp_column="event_timestamp",
    created_timestamp_column="created",
)

# Define an entity for the driver. You can think of entity as a primary key used to
# fetch features.
driver = Entity(name="driver_id", value_type=ValueType.INT64, description="driver id",)

# Our parquet files contain sample data that includes a driver_id column, timestamps and
# three feature column. Here we define a Feature View that will allow us to serve this
# data to our model online.
driver_hourly_stats_view = FeatureView(
    name="driver_hourly_stats",
    entities=["driver_id"],
    ttl=Duration(seconds=86400 * 1),
    features=[
        Feature(name="conv_rate", dtype=ValueType.FLOAT),
        Feature(name="acc_rate", dtype=ValueType.FLOAT),
        Feature(name="avg_daily_trips", dtype=ValueType.INT64),
    ],
    online=True,
    batch_source=driver_hourly_stats,
    tags={},
)

步骤 3d:检查原始数据

最后,让我们检查一下原始数据。我们在此演示中拥有的原始数据存储在本地 parquet 文件中。数据集捕获了拼车应用程序中司机的每小时统计信息。

步骤 4:注册特征定义并部署您的特征存储

现在,我们运行 feast apply 来注册在 example.py 中定义的特征视图和实体。apply 命令扫描当前目录中的 Python 文件以查找特征视图/实体定义,注册这些对象并部署基础设施。在本示例中,它读取 example.py(如上所示)并设置 Redis 在线存储。

$ feast apply

输出:

注册实体 driver_id
注册 特征视图 driver_hourly_stats
正在部署 driver_hourly_stats 的基础设施

步骤 5:生成训练数据

要训练模型,我们需要特征和标签。通常,这些标签数据分别存储(例如,您有一个存储用户调查结果的表,以及另一个包含特征值的表)。

用户可以查询带有时间戳的标签表,并将该表作为实体数据帧传递给 Feast,以生成训练数据。在许多情况下,Feast 还会智能地连接相关表以创建相关的特征向量。

  • 请注意,我们包含时间戳,因为我们希望在模型中使用同一司机在不同时间戳的特征。

Python

(将以下代码复制到文件 gen_train_data.py 中,然后运行它:)

from datetime import datetime, timedelta
import pandas as pd

from feast import FeatureStore

# The entity dataframe is the dataframe we want to enrich with feature values
entity_df = pd.DataFrame.from_dict(
    {
        "driver_id": [1001, 1002, 1003],
        "label_driver_reported_satisfaction": [1, 5, 3], 
        "event_timestamp": [
            datetime.now() - timedelta(minutes=11),
            datetime.now() - timedelta(minutes=36),
            datetime.now() - timedelta(minutes=73),
        ],
    }
)

store = FeatureStore(repo_path=".")

training_df = store.get_historical_features(
    entity_df=entity_df,
    features=[
        "driver_hourly_stats:conv_rate",
        "driver_hourly_stats:acc_rate",
        "driver_hourly_stats:avg_daily_trips",
    ],
).to_df()

print("----- Feature schema -----\n")
print(training_df.info())

print()
print("----- Example features -----\n")
print(training_df.head())

输出:

----- 特征模式 -----

<class 'pandas.core.frame.DataFrame'>
Int64Index: 3 entries, 0 to 2
Data columns (total 6 columns)
#   列                              非空计数  数据类型             
---  ------                              --------------  -----             
0   event_timestamp                     3 non-null      datetime64[ns, UTC]
1   driver_id                           3 non-null      int64             
2   label_driver_reported_satisfaction  3 non-null      int64             
3   conv_rate                           3 non-null      float32           
4   acc_rate                            3 non-null      float32           
5   avg_daily_trips                     3 non-null      int32             
dtypes: datetime64[ns, UTC](1), float32(2), int32(1), int64(2)
memory usage: 132.0 bytes
None

----- 示例特征 -----

                  event_timestamp  driver_id  ...  acc_rate  avg_daily_trips
0 2021-08-23 15:12:55.489091+00:00       1003  ...  0.120588              938
1 2021-08-23 15:49:55.489089+00:00       1002  ...  0.504881              635
2 2021-08-23 16:14:55.489075+00:00       1001  ...  0.138416              606

[3 rows x 6 columns]

步骤 6:将特征加载到 Redis 在线存储中

现在,我们将特征数据加载或物化到您的 Redis 在线存储中,以便我们可以为在线预测模型提供最新的特征。 materialize 命令允许用户将特征物化到在线存储中的特定历史时间范围内。它将查询批处理源以获取指定时间范围内所有特征视图,并将最新的特征值加载到配置的在线存储中。 materializeincremental 命令只接收自上次物化调用以来到达离线存储中的新数据。

$ CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S")
$ feast materialize-incremental $CURRENT_TIME

输出:

1 个特征视图物化到 2021-08-23 16:25:46+00:00 中的 redis 在线存储中。

driver_hourly_stats from 2021-08-22 16:25:47+00:00 to 2021-08-23 16:25:46+00:00:
100%|████████████████████████████████████████████| 5/5 [00:00<00:00, 592.05it/s]

步骤 7:获取用于推断的特征向量

在推断时,我们需要使用 get_online_features() 从 Redis 在线特征存储中快速读取不同司机的最新特征值(否则这些特征值可能只存在于批处理源中)。然后,这些特征向量可以被馈送到模型中。

Python

(将以下代码复制到文件 get_feature_vectors.py 中,然后运行它:)

from pprint import pprint
from feast import FeatureStore

store = FeatureStore(repo_path=".")

feature_vector = store.get_online_features(
    features=[
        "driver_hourly_stats:conv_rate",
        "driver_hourly_stats:acc_rate",
        "driver_hourly_stats:avg_daily_trips",
    ],
    entity_rows=[
        {"driver_id": 1004},
        {"driver_id": 1005},
    ],
).to_dict()

pprint(feature_vector)

输出

{
'acc_rate': [0.5732735991477966, 0.7828438878059387],
'avg_daily_trips': [33, 984],
'conv_rate': [0.15498852729797363, 0.6263588070869446],
'driver_id': [1004, 1005]
}

恭喜!您已经完成了本教程。要关闭在后台运行的 Redis 服务器,可以使用 redis-cli shutdown 命令。

教程回顾

在本教程中,您部署了一个带有 Parquet 文件离线存储和 Redis 在线存储的本地特征存储。然后,您使用来自 Parquet 文件的时间序列特征构建了训练数据集。然后,您将特征值从离线存储物化到 Redis 在线存储中。最后,您从 Redis 在线存储中读取最新的特征以进行推断。使用 Redis 作为在线存储,您可以非常快速地读取最新的特征以用于实时机器学习用例,并以低延迟和高吞吐量进行大规模扩展。 

下一步是什么?

  • 阅读 Feast 的 概念 页面以了解 Feast 数据模型,并阅读 Feast 的 架构 页面。
  • 阅读有关 Feast 和 Redis 的完整 配置 指南,以及用于在 Redis 中存储特征值的 数据模型
  • 案例研究 - 向您的同行学习:了解公司如何使用带有 Redis 作为在线存储的特征存储 (WixSwiggyComcastZomatoAT&TDoorDashiFood),以及他们如何专门使用 Feast 和 Redis 来进行在线存储 (GojekUdaanRobinhood)。

加入其他 Feast 用户和贡献者在 Slack 中,成为社区的一份子!