Milvus와 PaddlePaddle을 함께 사용하여 추천 시스템에서 후보 생성 가속화
추천 시스템을 개발해 본 경험이 있다면, 다음 중 적어도 하나의 문제를 겪어 보았을 가능성이 높습니다:
- 방대한 양의 데이터셋으로 인해 결과를 반환할 때 시스템이 극도로 느립니다.
- 새로 삽입된 데이터를 검색이나 쿼리를 위해 실시간으로 처리할 수 없습니다.
- 추천 시스템 배포가 어렵게 느껴집니다.
이 글은 오픈 소스 벡터 데이터베이스인 Milvus와 딥러닝 플랫폼인 PaddlePaddle을 함께 사용하는 상품 추천 시스템 프로젝트를 소개함으로써 위에서 언급한 문제를 해결하고 몇 가지 통찰을 제공하는 것을 목표로 합니다.
이 글은 먼저 추천 시스템의 최소 워크플로를 간략히 설명합니다. 그런 다음 이 프로젝트의 주요 구성 요소와 구현 세부 사항을 소개합니다.
추천 시스템의 기본 워크플로
프로젝트 자체를 깊이 살펴보기 전에, 먼저 추천 시스템의 기본 워크플로를 살펴보겠습니다. 추천 시스템은 고유한 사용자 관심사와 요구에 따라 개인화된 결과를 반환할 수 있습니다. 이러한 개인화된 추천을 만들기 위해 시스템은 후보 생성과 랭킹이라는 두 단계를 거칩니다.
Figure 1.
첫 번째 단계는 후보 생성으로, 사용자 프로필과 일치하는 상품이나 동영상과 같이 가장 관련성이 높거나 유사한 데이터를 반환합니다. 후보 생성 중에 시스템은 사용자 특성을 데이터베이스에 저장된 데이터와 비교하고, 유사한 데이터를 검색합니다. 그런 다음 랭킹 과정에서 시스템은 검색된 데이터에 점수를 매기고 다시 정렬합니다. 마지막으로 목록의 상위에 있는 결과가 사용자에게 표시됩니다.
상품 추천 시스템의 경우, 먼저 사용자 프로필을 재고 상품의 특성과 비교하여 사용자의 요구에 맞는 상품 목록을 필터링합니다. 그런 다음 시스템은 사용자 프로필과의 유사성을 기반으로 상품에 점수를 매기고, 순위를 매긴 뒤, 최종적으로 상위 10개 상품을 사용자에게 반환합니다.
Figure 2.
시스템 아키텍처
이 프로젝트의 상품 추천 시스템은 MIND, PaddleRec, Milvus라는 세 가지 구성 요소를 사용합니다.
MIND
MIND는 "Multi-Interest Network with Dynamic Routing for Recommendation at Tmall"의 약자로, Alibaba Group이 개발한 알고리즘입니다. MIND가 제안되기 전에는 추천을 위한 대부분의 널리 사용되는 AI 모델이 사용자의 다양한 관심사를 표현하기 위해 단일 벡터를 사용했습니다. 그러나 단일 벡터는 사용자의 정확한 관심사를 표현하기에는 매우 부족합니다. 따라서 MIND 알고리즘은 사용자의 여러 관심사를 여러 개의 벡터로 변환하기 위해 제안되었습니다.
구체적으로, MIND는 후보 생성 단계에서 한 사용자의 여러 관심사를 처리하기 위해 동적 라우팅을 갖춘 multi-interest network를 채택합니다. multi-interest network는 캡슐 라우팅 메커니즘을 기반으로 구축된 다중 관심 추출기 계층입니다. 이는 사용자의 과거 행동과 여러 관심사를 결합하여 정확한 사용자 프로필을 제공하는 데 사용할 수 있습니다.
다음 다이어그램은 MIND의 네트워크 구조를 보여줍니다.
Figure 3.
사용자의 특성을 표현하기 위해 MIND는 사용자 행동과 사용자 관심사를 입력으로 받아 임베딩 계층에 전달하여 사용자 관심 벡터와 사용자 행동 벡터를 포함한 사용자 벡터를 생성합니다. 그런 다음 사용자 행동 벡터는 multi-interest extractor 계층에 입력되어 사용자 관심 캡슐을 생성합니다. 사용자 관심 캡슐을 사용자 행동 임베딩과 연결하고 여러 ReLU 계층을 사용해 변환한 후, MIND는 여러 사용자 표현 벡터를 출력합니다. 이 프로젝트에서는 MIND가 최종적으로 네 개의 사용자 표현 벡터를 출력하도록 정의했습니다.
반면, 제품 특성은 임베딩 레이어를 거쳐 희소 아이템 벡터로 변환됩니다. 그런 다음 각 아이템 벡터는 풀링 레이어를 거쳐 밀집 벡터가 됩니다.
모든 데이터가 벡터로 변환되면, 학습 과정을 안내하기 위해 추가적인 레이블 인식 어텐션 레이어가 도입됩니다.
PaddleRec
PaddleRec은 추천을 위한 대규모 검색 모델 라이브러리입니다. Baidu PaddlePaddle 생태계의 일부입니다. PaddleRec은 개발자에게 추천 시스템을 쉽고 빠르게 구축할 수 있는 통합 솔루션을 제공하는 것을 목표로 합니다.
그림 4.
서두에서 언급했듯이, 추천 시스템을 개발하는 엔지니어들은 시스템의 낮은 사용성과 복잡한 배포라는 과제에 자주 직면해야 합니다. 그러나 PaddleRec은 다음과 같은 측면에서 개발자를 도울 수 있습니다:
사용 용이성: PaddleRec은 후보 생성, 랭킹, 재랭킹, 멀티태스킹 등을 위한 모델을 포함하여 업계의 다양한 인기 모델을 캡슐화한 오픈 소스 라이브러리입니다. PaddleRec을 사용하면 모델의 효과를 즉시 테스트하고 반복을 통해 효율성을 개선할 수 있습니다. PaddleRec은 뛰어난 성능으로 분산 시스템용 모델을 학습시키는 쉬운 방법을 제공합니다. 희소 벡터의 대규모 데이터 처리를 위해 최적화되어 있습니다. PaddleRec을 수평으로 쉽게 확장하고 계산 속도를 높일 수 있습니다. 따라서 PaddleRec을 사용하여 Kubernetes에서 학습 환경을 빠르게 구축할 수 있습니다.
배포 지원: PaddleRec은 해당 모델에 대한 온라인 배포 솔루션을 제공합니다. 모델은 학습 후 즉시 사용할 수 있으며, 유연성과 높은 가용성을 갖추고 있습니다.
Milvus
Milvus는 클라우드 네이티브 아키텍처를 특징으로 하는 벡터 데이터베이스입니다. GitHub에 오픈 소스로 공개되어 있으며, 심층 신경망 및 기타 머신 러닝(ML) 모델이 생성한 대규모 임베딩 벡터를 저장, 인덱싱 및 관리하는 데 사용할 수 있습니다. Milvus는 Faiss, NMSLIB, Annoy를 포함한 여러 일류 근사 최근접 이웃(ANN) 검색 라이브러리를 캡슐화합니다. 필요에 따라 Milvus를 스케일 아웃할 수도 있습니다. Milvus 서비스는 높은 가용성을 갖추고 있으며 통합 배치 및 스트림 처리를 지원합니다. Milvus는 비정형 데이터 관리 프로세스를 단순화하고 다양한 배포 환경에서 일관된 사용자 경험을 제공하는 데 전념하고 있습니다. 다음과 같은 기능을 갖추고 있습니다:
대규모 데이터셋에서 벡터 검색을 수행할 때 높은 성능.
다중 언어 지원과 툴체인을 제공하는 개발자 우선 커뮤니티.
장애 발생 시에도 클라우드 확장성과 높은 신뢰성.
스칼라 필터링과 벡터 유사도 검색을 결합하여 구현되는 하이브리드 검색.
Milvus는 시스템 안정성을 유지하면서 빈번한 데이터 업데이트 문제를 해결할 수 있기 때문에 이 프로젝트에서 벡터 유사도 검색 및 벡터 관리에 사용됩니다.
시스템 구현
이 프로젝트에서 제품 추천 시스템을 구축하려면 다음 단계를 거쳐야 합니다:
- 데이터 처리
- 모델 학습
- 모델 테스트
- 제품 아이템 후보 생성
- 데이터 저장: 학습된 모델을 통해 아이템 벡터를 얻고 Milvus에 저장합니다.
- 데이터 검색: MIND가 생성한 네 개의 사용자 벡터를 Milvus에 입력하여 벡터 유사도 검색을 수행합니다.
- 데이터 랭킹: 네 개의 벡터 각각은 자체
top_k유사 아이템 벡터를 가지며, 네 세트의top_k벡터를 랭킹하여 최종top_k개의 가장 유사한 벡터 목록을 반환합니다.
이 프로젝트의 소스 코드는 Baidu AI Studio 플랫폼에 호스팅되어 있습니다. 다음 섹션에서는 이 프로젝트의 소스 코드에 대해 자세히 설명합니다.
1단계. 데이터 처리
원본 데이터셋은 ComiRec에서 제공한 Amazon book 데이터셋에서 가져왔습니다. 그러나 이 프로젝트는 PaddleRec에서 다운로드하고 처리한 데이터를 사용합니다. 자세한 내용은 PaddleRec 프로젝트의 AmazonBook dataset을 참조하세요.
훈련용 데이터셋은 다음 형식으로 나타날 것으로 예상되며, 각 열은 다음을 나타냅니다:
Uid: 사용자 ID.item_id: 사용자가 클릭한 상품 아이템의 ID.Time: 클릭의 타임스탬프 또는 순서.
테스트용 데이터셋은 다음 형식으로 나타날 것으로 예상되며, 각 열은 다음을 나타냅니다:
Uid: 사용자 ID.hist_item: 과거 사용자 클릭 행동에 있는 상품 아이템의 ID. 여러hist_item이 있는 경우, 타임스탬프에 따라 정렬됩니다.eval_item: 사용자가 상품을 클릭한 실제 시퀀스.
Step 2. 모델 훈련
모델 훈련은 이전 단계에서 처리된 데이터를 사용하며 PaddleRec 기반으로 구축된 후보 생성 모델인 MIND를 채택합니다.
1. 모델 입력
dygraph_model.py에서 다음 코드를 실행하여 데이터를 처리하고 모델 입력으로 변환합니다. 이 과정은 원본 데이터에서 동일한 사용자가 클릭한 아이템을 타임스탬프에 따라 정렬하고, 이를 결합하여 시퀀스를 형성합니다. 그런 다음 시퀀스에서 item``_``id를 무작위로 선택하여 target_item으로 삼고, target_item 이전의 10개 아이템을 모델 입력용 hist_item으로 추출합니다. 시퀀스가 충분히 길지 않은 경우 0으로 설정할 수 있습니다. seq_len은 hist_item 시퀀스의 실제 길이여야 합니다.
def create_feeds_train(self, batch_data):
hist_item = paddle.to_tensor(batch_data[0], dtype="int64")
target_item = paddle.to_tensor(batch_data[1], dtype="int64")
seq_len = paddle.to_tensor(batch_data[2], dtype="int64")
return [hist_item, target_item, seq_len]
원본 데이터셋을 읽는 코드에 대해서는 스크립트 /home/aistudio/recommend/model/mind/mind_reader.py를 참조하세요.
2. 모델 네트워킹
다음 코드는 net.py의 발췌입니다. class Mind_Capsual_Layer는 관심 캡슐 라우팅 메커니즘을 기반으로 구축된 다중 관심 추출기 레이어를 정의합니다. 함수 label_aware_attention()은 MIND 알고리즘의 레이블 인식 어텐션 기법을 구현합니다. class MindLayer의 forward() 함수는 사용자 특성을 모델링하고 해당 가중치 벡터를 생성합니다.
class Mind_Capsual_Layer(nn.Layer):
def __init__(self):
super(Mind_Capsual_Layer, self).__init__()
self.iters = iters
self.input_units = input_units
self.output_units = output_units
self.maxlen = maxlen
self.init_std = init_std
self.k_max = k_max
self.batch_size = batch_size
# B2I routing
self.routing_logits = self.create_parameter(
shape=[1, self.k_max, self.maxlen],
attr=paddle.ParamAttr(
name="routing_logits", trainable=False),
default_initializer=nn.initializer.Normal(
mean=0.0, std=self.init_std))
# bilinear mapping
self.bilinear_mapping_matrix = self.create_parameter(
shape=[self.input_units, self.output_units],
attr=paddle.ParamAttr(
name="bilinear_mapping_matrix", trainable=True),
default_initializer=nn.initializer.Normal(
mean=0.0, std=self.init_std))
class MindLayer(nn.Layer):
def label_aware_attention(self, keys, query):
weight = paddle.sum(keys * query, axis=-1, keepdim=True)
weight = paddle.pow(weight, self.pow_p) # [x,k_max,1]
weight = F.softmax(weight, axis=1)
output = paddle.sum(keys * weight, axis=1)
return output, weight
def forward(self, hist_item, seqlen, labels=None):
hit_item_emb = self.item_emb(hist_item) # [B, seqlen, embed_dim]
user_cap, cap_weights, cap_mask = self.capsual_layer(hit_item_emb, seqlen)
if not self.training:
return user_cap, cap_weights
target_emb = self.item_emb(labels)
user_emb, W = self.label_aware_attention(user_cap, target_emb)
return self.sampled_softmax(
user_emb, labels, self.item_emb.weight,
self.embedding_bias), W, user_cap, cap_weights, cap_mask
MIND의 구체적인 네트워크 구조는 스크립트 /home/aistudio/recommend/model/mind/net.py를 참조하세요.
3. 모델 최적화
이 프로젝트는 모델 옵티마이저로 Adam 알고리즘을 사용합니다.
def create_optimizer(self, dy_model, config):
lr = config.get("hyper_parameters.optimizer.learning_rate", 0.001)
optimizer = paddle.optimizer.Adam(
learning_rate=lr, parameters=dy_model.parameters())
return optimizer
또한 PaddleRec은 하이퍼파라미터를 config.yaml에 작성하므로, 이 파일만 수정하면 두 모델의 효과를 명확히 비교하여 모델 효율성을 개선할 수 있습니다. 모델을 학습할 때 모델 효과가 좋지 않은 것은 모델 언더피팅 또는 오버피팅으로 인해 발생할 수 있습니다. 따라서 학습 라운드 수를 수정하여 개선할 수 있습니다. 이 프로젝트에서는 완벽한 학습 라운드 수를 찾기 위해 config.yaml의 epochs 매개변수만 변경하면 됩니다. 또한 디버깅을 위해 모델 옵티마이저인 optimizer.class 또는 learning_rate를 변경할 수도 있습니다. 다음은 config.yaml의 매개변수 일부를 보여줍니다.
runner:
use_gpu: True
use_auc: False
train_batch_size: 128
epochs: 20
print_interval: 10
model_save_path: "output_model_mind"
# hyper parameters of user-defined network
hyper_parameters:
# optimizer config
optimizer:
class: Adam
learning_rate: 0.005
자세한 구현은 스크립트 /home/aistudio/recommend/model/mind/dygraph_model.py를 참조하세요.
4. 모델 학습
다음 명령을 실행하여 모델 학습을 시작합니다.
python -u trainer.py -m mind/config.yaml
모델 학습 프로젝트는 /home/aistudio/recommend/model/trainer.py를 참조하세요.
3단계. 모델 테스트
이 단계에서는 학습된 모델의 재현율과 같은 성능을 검증하기 위해 테스트 데이터셋을 사용합니다.
모델 테스트 중에는 모든 아이템 벡터가 모델에서 로드된 다음, 오픈 소스 벡터 데이터베이스인 Milvus로 가져와집니다. 스크립트 /home/aistudio/recommend/model/mind/mind_infer_reader.py를 통해 테스트 데이터셋을 읽습니다. 이전 단계의 모델을 로드하고 테스트 데이터셋을 모델에 입력하여 사용자의 관심 벡터 4개를 얻습니다. Milvus에서 4개의 관심 벡터와 가장 유사한 아이템 벡터 50개를 검색합니다. 반환된 결과를 사용자에게 추천할 수 있습니다.
다음 명령을 실행하여 모델을 테스트합니다.
python -u infer.py -m mind/config.yaml -top_n 50
모델 테스트 중 시스템은 Recall@50, NDCG@50, HitRate@50과 같은 모델 효과 평가를 위한 여러 지표를 제공합니다. 이 글에서는 하나의 매개변수 수정만 소개합니다. 그러나 실제 애플리케이션 시나리오에서는 더 나은 모델 효과를 위해 더 많은 epochs를 학습해야 합니다. 또한 다양한 옵티마이저를 사용하고, 다양한 학습률을 설정하며, 테스트 라운드 수를 늘려 모델 효과를 개선할 수도 있습니다. 서로 다른 효과를 가진 여러 모델을 저장한 다음, 성능이 가장 좋고 애플리케이션에 가장 잘 맞는 모델을 선택하는 것이 좋습니다.
4단계. 상품 아이템 후보 생성
상품 후보 생성 서비스를 구축하기 위해 이 프로젝트는 이전 단계에서 학습된 모델을 Milvus와 함께 사용합니다. 후보 생성 중에는 FASTAPI를 사용하여 인터페이스를 제공합니다. 서비스가 시작되면 curl을 통해 터미널에서 직접 명령을 실행할 수 있습니다.
다음 명령을 실행하여 예비 후보를 생성합니다.
uvicorn main:app
이 서비스는 네 가지 유형의 인터페이스를 제공합니다.
- Insert : 다음 명령을 실행하여 모델에서 아이템 벡터를 읽고 Milvus의 컬렉션에 삽입합니다.
curl -X 'POST' \
'http://127.0.0.1:8000/rec/insert_data' \
-H 'accept: application/json' \
-d ''
- Generate preliminary candidates: 사용자가 제품을 클릭한 순서를 입력하고, 사용자가 다음에 클릭할 수 있는 제품을 찾아냅니다. 또한 여러 사용자에 대한 제품 아이템 후보를 한 번에 배치로 생성할 수도 있습니다. 다음 명령의
hist_item은 2차원 벡터이며, 각 행은 사용자가 과거에 클릭한 제품의 시퀀스를 나타냅니다. 시퀀스의 길이는 직접 정의할 수 있습니다. 반환된 결과도 2차원 벡터의 집합이며, 각 행은 사용자에게 반환된item id를 나타냅니다.
curl -X 'POST' \
'http://127.0.0.1:8000/rec/recall' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"top_k": 50,
"hist_item": [[43,23,65,675,3456,8654,123454,54367,234561],[675,3456,8654,123454,76543,1234,9769,5670,65443,123098,34219,234098]]
}'
- Query the total number of product items: 다음 명령을 실행하여 Milvus 데이터베이스에 저장된 아이템 벡터의 총 개수를 반환합니다.
curl -X 'POST' \
'http://127.0.0.1:8000/rec/count' \
-H 'accept: application/json' \
-d ''
- Delete: 다음 명령을 실행하여 Milvus 데이터베이스에 저장된 모든 데이터를 삭제합니다 .
curl -X 'POST' \
'http://127.0.0.1:8000/qa/drop' \
-H 'accept: application/json' \
-d ''
로컬 서버에서 후보 생성 서비스를 실행하는 경우, 위 인터페이스를 127.0.0.1:8000/docs에서도 액세스할 수 있습니다. 네 가지 인터페이스를 클릭하고 매개변수 값을 입력하여 직접 사용해 볼 수 있습니다. 그런 다음 "Try it out"을 클릭하여 추천 결과를 얻습니다.
그림 5.
그림 6.
요약
이 글은 주로 추천 시스템 구축에서 후보 생성의 첫 번째 단계에 초점을 맞춥니다. 또한 Milvus를 MIND 알고리즘 및 PaddleRec과 결합하여 이 프로세스를 가속화하는 솔루션을 제공하며, 따라서 서두에서 제기한 문제를 해결했습니다.
엄청난 양의 데이터셋으로 인해 결과를 반환할 때 시스템이 매우 느리다면 어떻게 해야 할까요? 오픈소스 벡터 데이터베이스인 Milvus는 수백만, 수십억, 심지어 수조 개의 벡터를 포함하는 밀집 벡터 데이터셋에서 초고속 유사도 검색을 수행하도록 설계되었습니다.
새로 삽입된 데이터를 검색 또는 쿼리를 위해 실시간으로 처리할 수 없다면 어떻게 해야 할까요? Milvus는 통합된 배치 및 스트림 처리를 지원하고 새로 삽입된 데이터를 실시간으로 검색하고 쿼리할 수 있으므로 Milvus를 사용할 수 있습니다. 또한 MIND 모델은 새로운 사용자 행동을 실시간으로 변환하고 사용자 벡터를 Milvus에 즉시 삽입할 수 있습니다.
복잡한 배포가 너무 부담스럽다면 어떻게 해야 할까요? PaddlePaddle 생태계에 속한 강력한 라이브러리인 PaddleRec은 추천 시스템이나 기타 애플리케이션을 쉽고 빠르게 배포할 수 있는 통합 솔루션을 제공합니다.
작성자 소개
Yunmei Li는 Zilliz 데이터 엔지니어이며, Huazhong University of Science and Technology에서 컴퓨터 과학 학위를 취득했습니다. Zilliz에 합류한 이후, 그녀는 오픈소스 프로젝트 Milvus를 위한 솔루션을 탐색하고 사용자가 실제 시나리오에 Milvus를 적용하도록 돕는 일을 해왔습니다. 그녀의 주요 관심 분야는 NLP와 추천 시스템이며, 이 두 분야에 대한 관심을 더욱 심화하고자 합니다. 그녀는 혼자 시간을 보내고 독서하는 것을 좋아합니다.
더 많은 리소스를 찾고 계신가요?
- 추천 시스템 구축의 더 많은 사용자 사례:
- 다른 커뮤니티와 협력한 더 많은 Milvus 프로젝트:
- 오픈 소스 커뮤니티에 참여하세요:
계속 읽기

Data Deduplication at Trillion Scale: How to Solve the Biggest Bottleneck of LLM Training
Explore how MinHash LSH and Milvus handle data deduplication at the trillion-scale level, solving key bottlenecks in LLM training for improved AI model performance.

OpenAI o1: What Developers Need to Know
In this article, we will talk about the o1 series from a developer's perspective, exploring how these models can be implemented for sophisticated use cases.

DeepSeek-VL2: Mixture-of-Experts Vision-Language Models for Advanced Multimodal Understanding
Explore DeepSeek-VL2, the open-source MoE vision-language model. Discover its architecture, efficient training pipeline, and top-tier performance.



