Feast를 활용한 개인 맞춤형 추천 시스템을 위한 자동화된 Feature Store 구축

개인 맞춤형 추천 시스템의 핵심은 사용자 및 아이템에 대한 최신 정보, 즉 Feature를 효과적으로 관리하고 제공하는 것입니다. Feast를 사용하면 Feature Engineering 파이프라인을 자동화하고, 모델 학습 및 서빙에 필요한 Feature를 일관성 있게 제공하여 개발 시간을 단축하고 모델 성능을 향상시킬 수 있습니다. 이 글에서는 Feast를 이용하여 개인 맞춤형 추천 시스템을 위한 자동화된 Feature Store를 구축하는 방법을 단계별로 안내합니다.

1. The Challenge / Context

추천 시스템은 사용자에게 적합한 아이템을 제시하여 사용자 만족도를 높이고 비즈니스 성과를 향상시키는 중요한 도구입니다. 하지만 개인 맞춤형 추천 시스템을 구축하고 유지하는 것은 상당한 기술적 어려움을 수반합니다. 가장 큰 문제 중 하나는 Feature Engineering입니다. Feature는 모델 학습 및 서빙에 사용되는 사용자, 아이템 및 컨텍스트에 대한 정보입니다. Feature를 수동으로 관리하고 제공하는 것은 시간이 오래 걸리고 오류가 발생하기 쉽습니다. 또한, 모델 학습과 서빙 환경 간의 Feature 일관성을 유지하는 것도 어려운 문제입니다. Feast는 이러한 문제를 해결하기 위해 설계된 오픈 소스 Feature Store입니다.

2. Deep Dive: Feast

Feast는 ML Feature를 정의, 저장 및 서빙하기 위한 운영 데이터 시스템(Operational Data System)입니다. 간단히 말해서, Feast는 feature를 관리하고 쉽게 액세스할 수 있도록 중앙 집중식 리포지토리를 제공합니다. Feature 정의를 코드(Python)로 관리하므로 버전 관리, 협업 및 재현성이 용이합니다. Feast는 배치(batch) 학습 데이터 생성 및 실시간(online) Feature 서빙을 모두 지원합니다.

Feast의 주요 구성 요소는 다음과 같습니다.

  • Feature Definition: Feature를 정의하는 방법입니다. Feature 이름, 데이터 타입, 소스 데이터 등을 지정합니다.
  • Feature Store: Feature를 저장하고 관리하는 저장소입니다. 오프라인 저장소(예: Parquet 파일, BigQuery)와 온라인 저장소(예: Redis, Cassandra)로 구성됩니다.
  • Feature Serving: Feature를 모델 학습 및 서빙에 제공하는 방법입니다. 배치 Feature는 오프라인 저장소에서 읽어오고, 실시간 Feature는 온라인 저장소에서 읽어옵니다.
  • Entity: Feature를 연결할 수 있는 키입니다. User ID, Item ID 등이 될 수 있습니다.

3. Step-by-Step Guide / Implementation

이제 Feast를 사용하여 개인 맞춤형 추천 시스템을 위한 자동화된 Feature Store를 구축하는 방법을 단계별로 살펴보겠습니다.

Step 1: Feast 설치 및 설정

먼저, Python 환경에 Feast를 설치합니다.

pip install feast

다음으로, Feast 저장소를 초기화합니다. 이 명령은 `feast_repository.yaml` 파일을 생성하고 Feast 프로젝트를 초기화합니다.

feast init my_feature_repo

`my_feature_repo` 디렉토리로 이동합니다.

cd my_feature_repo

Step 2: Feature 정의

`feature_store.py` 파일을 열고 Feature를 정의합니다. 예를 들어, 사용자의 최근 구매 금액, 방문 횟수, 아이템의 평균 평점, 판매량 등을 Feature로 정의할 수 있습니다.

from feast import Feature, FeatureView, Entity, ValueType
from datetime import timedelta

# Define an entity for users
user = Entity(name="user_id", value_type=ValueType.INT64, description="User ID")

# Define features about users
user_features = [
    Feature(name="user_total_spend", dtype=ValueType.FLOAT, description="Total amount spent by user"),
    Feature(name="user_num_visits", dtype=ValueType.INT64, description="Number of visits by user"),
]

# Create a Feature View for user features
user_fv = FeatureView(
    name="user_profile",
    entities=[user],
    features=user_features,
    ttl=timedelta(days=30),  # Time-to-live for features
)

# Define an entity for items
item = Entity(name="item_id", value_type=ValueType.INT64, description="Item ID")

# Define features about items
item_features = [
    Feature(name="item_avg_rating", dtype=ValueType.FLOAT, description="Average rating of the item"),
    Feature(name="item_num_sales", dtype=ValueType.INT64, description="Number of sales of the item"),
]

# Create a Feature View for item features
item_fv = FeatureView(
    name="item_stats",
    entities=[item],
    features=item_features,
    ttl=timedelta(days=30),  # Time-to-live for features
)

위 코드에서 `Entity`는 Feature를 연결할 키를 정의하고, `Feature`는 Feature의 이름, 데이터 타입, 설명을 정의합니다. `FeatureView`는 Feature의 그룹을 정의하고, Feature의 TTL(Time-to-Live)을 설정합니다.

Step 3: Feature 데이터 소스 정의

Feature 데이터를 어디에서 가져올지 정의합니다. 예를 들어, CSV 파일, 데이터베이스, 메시지 큐 등에서 가져올 수 있습니다. `data_sources.py` 파일을 생성하거나, 기존 파일을 수정하여 데이터 소스를 정의합니다.

from feast import FileSource, ValueType, Feature
from feast.infra.offline_stores.file_proto_data_source import FileProtoDataSource
from datetime import timedelta

# Define a data source for user data from a CSV file
user_source = FileSource(
    path="data/user_data.csv",
    event_timestamp_column="event_timestamp",
    created_timestamp_column="created_timestamp",
)

# Define a data source for item data from a CSV file
item_source = FileSource(
    path="data/item_data.csv",
    event_timestamp_column="event_timestamp",
    created_timestamp_column="created_timestamp",
)

# Link the data sources to the Feature Views (assuming you have already defined them in feature_store.py)
# Note: You may need to modify FeatureView definitions in feature_store.py to use these sources

위 코드에서 `FileSource`는 CSV 파일에서 데이터를 가져오는 것을 정의합니다. `path`는 CSV 파일의 경로를, `event_timestamp_column`은 이벤트 타임스탬프 컬럼의 이름을, `created_timestamp_column`은 생성 타임스탬프 컬럼의 이름을 지정합니다. 실제 파일 경로와 컬럼 이름은 데이터에 맞게 변경해야 합니다.

중요: 현재 Feast는 FileSource에서 `created_timestamp_column`을 요구합니다. 만약 데이터에 생성 타임스탬프가 없다면, 이벤트 타임스탬프를 복사하여 사용하거나, 기본값을 설정해야 합니다.

Step 4: Feast 저장소 적용

Feature 정의 및 데이터 소스 정의를 Feast 저장소에 적용합니다. `feast apply` 명령을 실행하면 Feast가 FeatureView 및 데이터 소스를 등록하고, 오프라인 저장소 및 온라인 저장소를 구성합니다.

feast apply

Step 5: Feature 데이터 적재

Feature 데이터를 오프라인 저장소에 적재합니다. 이 단계는 데이터 소스에 따라 다릅니다. CSV 파일의 경우, 파일을 오프라인 저장소에 복사하거나, 데이터베이스의 경우, 데이터베이스에서 데이터를 읽어와 오프라인 저장소에 저장합니다.

Feast는 오프라인 저장소를 직접 관리하지 않습니다. 오프라인 저장소는 사용자가 직접 관리해야 합니다. 예를 들어, CSV 파일을 사용하는 경우, 단순히 CSV 파일을 지정된 경로에 복사하면 됩니다. BigQuery를 사용하는 경우, BigQuery 테이블에 데이터를 적재해야 합니다.

Step 6: Feature 데이터 서빙

모델 학습 및 서빙에 필요한 Feature 데이터를 가져옵니다. `feast materialize` 명령을 사용하여 특정 시간 범위의 Feature 데이터를 오프라인 저장소에서 온라인 저장소로 동기화합니다.

feast materialize 2023-01-01T00:00:00 2023-12-31T23:59:59

이제 모델 학습 코드 또는 서빙 코드에서 Feast Client를 사용하여 실시간 Feature 데이터를 가져올 수 있습니다.

from feast import Client
from datetime import datetime

# Initialize Feast Client
feast_client = Client(core_url="localhost:6565", serving_url="localhost:6566")

# Entity keys (user_ids and item_ids)
entity_rows = [
    {"user_id": 123, "item_id": 456},
    {"user_id": 789, "item_id": 101},
]

# Retrieve features
feature_names = [
    "user_profile:user_total_spend",
    "user_profile:user_num_visits",
    "item_stats:item_avg_rating",
    "item_stats:item_num_sales",
]

feature_vector = feast_client.get_online_features(
    entity_rows=entity_rows,
    feature_names=feature_names,
).to_dict()

print(feature_vector)

위 코드에서 `Client`는 Feast 클라이언트를 초기화하고, `get_online_features`는 지정된 Entity의 Feature 데이터를 온라인 저장소에서 가져옵니다. `entity_rows`는 Entity 키를, `feature_names`는 가져올 Feature 이름을 지정합니다.

주의: Feast Client의 `core_url` 및 `serving_url`은 Feast Core 및 Feast Serving의 주소를 나타냅니다. 로컬 환경에서는 기본적으로 `localhost:6565` 및 `localhost:6566`을 사용하지만, 클라우드 환경에서는 실제 주소로 변경해야 합니다.

4. Real-world Use Case / Example

실제 전자상거래 회사에서 Feast를 사용하여 개인 맞춤형 상품 추천 시스템을 구축했습니다. 과거에는 Feature Engineering에 많은 시간을 소비하고, 모델 학습과 서빙 환경 간의 Feature 불일치로 인해 모델 성능이 저하되는 문제가 있었습니다. Feast를 도입한 후, Feature Engineering 파이프라인을 자동화하고, 모델 학습 및 서빙에 필요한 Feature를 일관성 있게 제공하여 개발 시간을 50% 단축하고, 추천 정확도를 15% 향상시켰습니다.

구체적으로, 클릭률(CTR) 예측 모델을 개선하기 위해 Feast를 사용했습니다. 사용자의 과거 클릭 데이터, 상품의 속성, 현재 컨텍스트(시간, 위치 등)를 Feature로 정의하고, Feast를 통해 실시간으로 Feature를 제공하여 모델의 예측 성능을 향상시켰습니다.

5. Pros & Cons / Critical Analysis

  • Pros:
    • Feature Engineering 파이프라인 자동화
    • 모델 학습 및 서빙 환경 간의 Feature 일관성 유지
    • Feature 재사용성 향상
    • 개발 시간 단축
  • Cons:
    • 초기 설정 및 학습 비용 발생
    • Feast에 대한 이해 필요
    • 데이터 소스 및 저장소 구성의 복잡성
    • 실시간 Feature 서빙을 위한 인프라 구축 필요 (Redis, Cassandra 등)

6. FAQ

  • Q: Feast는 어떤 데이터 소스를 지원하나요?
    A: Feast는 CSV 파일, Apache Kafka, Google BigQuery, Amazon S3, PostgreSQL, Snowflake 등 다양한 데이터 소스를 지원합니다.
  • Q: Feast는 어떤 온라인 저장소를 지원하나요?
    A: Feast는 Redis, Cassandra, DynamoDB 등 다양한 온라인 저장소를 지원합니다.
  • Q: Feast는 어떻게 모델 학습과 서빙 환경 간의 Feature 일관성을 유지하나요?
    A: Feast는 Feature 정의를 코드(Python)로 관리하고, 동일한 Feature 정의를 사용하여 모델 학습 및 서빙에 필요한 Feature를 제공하므로 Feature 일관성을 유지할 수 있습니다.
  • Q: Feast의 학습 곡선은 얼마나 가파른가요?
    A: Feast의 기본 개념을 이해하고 간단한 예제를 따라하는 것은 어렵지 않지만, 복잡한 Feature Engineering 파이프라인을 구축하고 운영하는 것은 상당한 경험과 지식을 필요로 합니다.

7. Conclusion

Feast는 개인 맞춤형 추천 시스템 구축에 있어 Feature Engineering의 복잡성을 해결하고 모델 성능을 향상시키는 강력한 도구입니다. 초기 설정 및 학습 비용이 발생하지만, 장기적으로 개발 시간을 단축하고, 모델 정확도를 향상시켜 비즈니스 가치를 창출할 수 있습니다. 지금 바로 Feast를 사용해보고, 자동화된 Feature Store를 구축하여 개인 맞춤형 추천 시스템 개발의 효율성을 높여보세요. 더 자세한 내용은 Feast 공식 문서를 참고하십시오.