LibRecommender
LibRecommender copied to clipboard
How to server DeepFM or YouTubeRanking ?
Hi, I have tried to train and deploy simplest model possible with csv structure like this : item | user | label I am trying to save the model, but I am receiving this error after training is done...
File "/recommender/libreco/utils/serialization.py", line 53, in save_info
save_to_json(last_interacted_path, model,
File "/recommender/libreco/utils/serialization.py", line 58, in save_to_json
json_data = convert_func(data)
File "/recommender/libreco/utils/serialization.py", line 97, in convert_last_interacted_to_json
seq_len = model.max_seq_len
AttributeError: 'YouTubeRanking' object has no attribute 'max_seq_len'
How to make the model saving and running? I am able to do only DIN model and even that worked only with your example code. When I tried to change the model for DeepFM, i was not able to do it.
The code is:
import numpy as np
import pandas as pd
from libreco.data import split_by_ratio, DatasetFeat
from libreco.algorithms import DeepFM, YouTubeRanking
from libreco.utils import save_info, save_model_tf_serving
from serving.flask import data_info2redis, user_consumed2redis, seq2redis
###############################################################
data = pd.read_csv("mydata.csv", sep=",", header=0)
data["label"] = 1
train_data, test_data = split_by_ratio(data, test_size=0.2)
sparse_col = []
dense_col = []
user_col = []
item_col = []
train_data, data_info = DatasetFeat.build_trainset(
train_data, user_col, item_col, sparse_col, dense_col
)
test_data = DatasetFeat.build_testset(test_data)
train_data.build_negative_samples(data_info) # sample negative items for each record
test_data.build_negative_samples(data_info)
model = YouTubeRanking(task="ranking", data_info=data_info, embed_size=16,
n_epochs=10, lr=3e-5, batch_size=128, use_bn=True,
hidden_units="128, 64,32")
model.fit(train_data, verbose=2, shuffle=True, eval_data=test_data,
metrics=["loss", "roc_auc", "precision", "recall", "map", "ndcg"])
path = "tf_model" # specify model saving directory
save_info(path, model, train_data, data_info)
save_model_tf_serving(path, model, "test_mymodel")
data_info2redis(path)
user_consumed2redis(path) consumed
seq2redis(path)
change interaction_num to max_seq_len in youtube_ranking.py
Yeah YoutubeRanking's attribute is wrong, which will be fixed in the next version. DeepFM doesn't use item sequence as DIN does, and the doc hasn't been updated to adapt to that. Considering refactoring the serving module.
Hi, I have solved the problem by going around :] with fastapi, uvicorn and saving/loading the model directly. Probably not so fast, but good enough for me now.
# model_serve.py
import string
from typing import Tuple, Union
from fastapi import FastAPI
import pandas as pd
from fastapi.middleware.cors import CORSMiddleware
from libreco.data import split_by_ratio, DatasetFeat
from libreco.algorithms import YouTubeRanking, DeepFM, DIN
from libreco.data.data_info import DataInfo
from libreco.utils import save_info, save_model_tf_serving
import os
import tensorflow as tf
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
os.environ["KMP_WARNINGS"] = "FALSE"
tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
origins = [
"http://0.0.0.0:3000",
"http://localhost:3000"
]
def load(model_path = "mymodel"):
tf.compat.v1.reset_default_graph()
data_info = DataInfo.load(model_path)
model = DeepFM.load(path=model_path, model_name="deepfm",
data_info=data_info, manual=True)
return model
mymodel = load()
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/id/{user_id}")
def read_item(user_id, q: Union[str, None] = None):
out = mymodel.recommend_user(user=user_id, n_rec=12, cold_start="popular")
print(type(out[0]))
print(out)
items = []
if type(out[0]) is tuple:
for index, data in enumerate(out):
items.append(data[0])
else:
items = out
return {"items_id": items}
run serve_model.py with
uvicorn serve_model:app
ok glad it works :)