recommender / app.py
Intae's picture
Fix app.py
66c3eaf
raw
history blame contribute delete
4.08 kB
import os
import numpy as np
import tensorflow as tf
import pandas as pd
import streamlit as st
import time
from recommenders.models.sasrec.model import SASREC
class SASREC_Vessl(SASREC):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def predict_next(self, input):
# seq generation
training = False
seq = np.zeros([self.seq_max_len], dtype=np.int32)
idx = self.seq_max_len - 1
for i in input[::-1]:
seq[idx] = i
idx -= 1
if idx == -1:
break
input_seq = np.array([seq])
candidate = np.expand_dims(np.arange(1, self.item_num + 1, 1), axis=0)
mask = tf.expand_dims(tf.cast(tf.not_equal(input_seq, 0), tf.float32),
-1)
seq_embeddings, positional_embeddings = self.embedding(input_seq)
seq_embeddings += positional_embeddings
seq_embeddings *= mask
seq_attention = seq_embeddings
seq_attention = self.encoder(seq_attention, training, mask)
seq_attention = self.layer_normalization(seq_attention) # (b, s, d)
seq_emb = tf.reshape(
seq_attention,
[tf.shape(input_seq)[0] * self.seq_max_len, self.embedding_dim],
) # (b*s, d)
candidate_emb = self.item_embedding_layer(candidate) # (b, s, d)
candidate_emb = tf.transpose(candidate_emb, perm=[0, 2, 1]) # (b, d, s)
test_logits = tf.matmul(seq_emb, candidate_emb)
test_logits = tf.reshape(
test_logits,
[tf.shape(input_seq)[0], self.seq_max_len, self.item_num],
)
test_logits = test_logits[:, -1, :] # (1, 101)
predictions = np.array(test_logits)[0]
return predictions
def elapsed_time(fn, *args):
start = time.time()
output = fn(*args)
end = time.time()
elapsed = f'{end - start:.2f}'
return elapsed, output
def load_model():
model_config = {
"MAXLEN": 50,
"NUM_BLOCKS": 2, # NUMBER OF TRANSFORMER BLOCKS
"HIDDEN_UNITS": 100, # NUMBER OF UNITS IN THE ATTENTION CALCULATION
"NUM_HEADS": 1, # NUMBER OF ATTENTION HEADS
"DROPOUT_RATE": 0.2, # DROPOUT RATE
"L2_EMB": 0.0, # L2 REGULARIZATION COEFFICIENT
"NUM_NEG_TEST": 100,
# NUMBER OF NEGATIVE EXAMPLES PER POSITIVE EXAMPLE
}
model = SASREC_Vessl(
item_num=12101, # should be changed according to dataset
seq_max_len=model_config.get("MAXLEN"),
num_blocks=model_config.get("NUM_BLOCKS"),
embedding_dim=model_config.get("HIDDEN_UNITS"),
attention_dim=model_config.get("HIDDEN_UNITS"),
attention_num_heads=model_config.get("NUM_HEADS"),
dropout_rate=model_config.get("DROPOUT_RATE"),
conv_dims=[100, 100],
l2_reg=model_config.get("L2_EMB"),
num_neg_test=model_config.get("NUM_NEG_TEST"),
)
if os.path.isfile('best.index') and os.path.isfile(
'best.data-00000-of-00001'):
model.load_weights('best').expect_partial()
return model
def postprocess_data(data):
predictions = -1 * data
rec_items = predictions.argsort()[:5]
dic_result = {
"Rank": [i for i in range(1, 6)],
"ItemID": list(rec_items + 1),
"Similarity Score": -1 * predictions[rec_items]
}
result = pd.DataFrame(dic_result)
time.sleep(0.5)
best_item = rec_items[0] + 1
return result, best_item
def main():
st.title("Self-Attentive Sequential Recommendation(SASRec)")
elapsed, model = elapsed_time(load_model)
st.write(f"Model is loaded in {elapsed} seconds!")
numbers = st.text_input(
label="Please write input items separated by comma. (e.g. 80, 70, 100, 1)")
if numbers:
integer_numbers = np.array(list(map(int, numbers.split(","))))
result = model.predict_next(integer_numbers)
table, best_item = postprocess_data(result)
st.table(table)
st.write(f"Best item is {best_item}")
if __name__ == '__main__':
main()