dot Redis 8 已发布——而且它是开源的

了解更多

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

本教程提供了一份分步指南,通过一个端到端的示例,向您展示如何将 Feast 与 Redis 结合使用,并将其作为在线机器学习特征存储。它基于Feast 快速入门教程,但不是使用默认的在线存储,而是使用 Redis 在线存储来大规模提供实时预测。如果您不熟悉 Feast 或 Redis,那么通过本教程是使用 Redis 快速开始使用 Feast 的最快方法。请参阅这篇使用 Redis 构建特征存储:Feast 与 Redis 简介博客文章,以获得高层介绍。关于 Redis 和 Feast 的更详细信息以及其他资源可在本教程末尾找到。

在本教程中,您将

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

您可以按照下面的指导步骤在Google Colab 或您的本地主机上运行本教程。

Feast 简介

Feast(Feature store,特征存储)是一个开源特征存储,是Linux Foundation AI & Data Foundation 的一部分。它可以从低延迟在线存储(用于实时服务)或离线存储(用于模型训练或批量服务)向模型提供特征数据。它还提供了一个中央注册中心,以便机器学习工程师数据科学家能够发现与 ML 用例相关的特征。以下是 Feast 的高层架构图:

Feast 是一个 Python 库 + 可选的 CLI。您可以使用 pip 安装 Feast,本教程稍后将对此进行描述。

Feast 与 Redis 结合解决了流程中的几个常见问题:

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

Feast 与 Redis 教程概述

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

  • 我们对一些司机进行了调查,以确定他们对使用网约车应用程序的体验有多满意。 
  • 我们希望为其余用户生成司机满意度预测,以便联系到可能不满意的用户。

教程步骤

  1. 安装 Redis 并在后台运行 Redis-Server
  2. 安装 Feast 并与 Redis 集成
  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:安装 Feast 并与 Redis 集成

使用 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 中为 online_store 设置 typeconnection_string 值,如下所示:

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
数据列 (共 6 列)
#   列                              非空计数  数据类型             
---  ------                              --------------  -----             
0   event_timestamp                     3 非空      datetime64[ns, UTC]
1   driver_id                           3 非空      int64             
2   label_driver_reported_satisfaction  3 非空      int64             
3   conv_rate                           3 非空      float32           
4   acc_rate                            3 非空      float32           
5   avg_daily_trips                     3 非空      int32             
数据类型: datetime64[ns, UTC](1), float32(2), int32(1), int64(2)
内存使用量: 132.0 字节
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 行 x 6 列]

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

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

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

输出:

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

driver_hourly_stats2021-08-22 16:25:47+00:00 到 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 作为在线存储,您可以非常快速地读取最新特征,从而以低延迟、高吞吐量和大规模的方式满足实时 ML 用例的需求。 

下一步?

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

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