text_plain_output_1.png
from implicit.evaluation import mean_average_precision_at_k

from scipy.sparse import coo_matrix

import implicit

import numpy as np

import pandas as pd

transactions = transactions[transactions['t_dat'] > '2020-09-14']
transactions.shape

all_customers = customers['customer_id'].unique().tolist()
all_articles = articles['article_id'].unique().tolist()
customer_ids = dict(list(enumerate(all_customers)))
article_ids = dict(list(enumerate(all_articles)))
transactions['customer_id'] = transactions['customer_id'].map({u: uidx for uidx, u in customer_ids.items()})
transactions['article_id'] = transactions['article_id'].map({i: iidx for iidx, i in article_ids.items()})
del customers, articles

row = transactions['customer_id'].values
col = transactions['article_id'].values
data = np.ones(transactions.shape[0])
coo_train = coo_matrix((data, (row, col)), shape=(len(all_customers), len(all_articles)))
coo_train

def to_customer_article_coo(transactions):
    """ Turn a dataframe with transactions into a COO sparse articles x customers matrix"""
    row = transactions['customer_id'].values
    col = transactions['article_id'].values
    data = np.ones(transactions.shape[0])
    coo = coo_matrix((data, (row, col)), shape=(len(all_customers), len(all_articles)))
    return coo
def split_data(transactions, validation_days=7):
    """ Split a pandas dataframe into training and validation data, using <<validation_days>>
    """
    validation_cut = transactions['t_dat'].max() - pd.Timedelta(validation_days)
    df_train = transactions[transactions['t_dat'] < validation_cut]
    df_val = transactions[transactions['t_dat'] >= validation_cut]
    return (df_train, df_val)
def get_val_matrices(transactions, validation_days=7):
    """ Split into training and validation and create various matrices
        Returns a dictionary with the following keys:
            coo_train: training data in COO sparse format and as (customers x articles)
            csr_train: training data in CSR sparse format and as (customers x articles)
            csr_val:  validation data in CSR sparse format and as (customers x articles)
    """
    df_train, df_val = split_data(transactions, validation_days=validation_days)
    coo_train = to_customer_article_coo(df_train)
    coo_val = to_customer_article_coo(df_val)
    csr_train = coo_train.tocsr()
    csr_val = coo_val.tocsr()
    return {'coo_train': coo_train, 'csr_train': csr_train, 'csr_val': csr_val}
def validate(matrices, factors=200, iterations=20, regularization=0.01, show_progress=True):
    """ Train an ALS model with <<factors>> (embeddings dimension) 
    for <<iterations>> over matrices and validate with MAP@12
    """
    coo_train, csr_train, csr_val = (matrices['coo_train'], matrices['csr_train'], matrices['csr_val'])
    model = implicit.als.AlternatingLeastSquares(factors=factors, iterations=iterations, regularization=regularization, random_state=7, use_gpu=True)
    model.fit(coo_train, show_progress=show_progress)
    map12 = mean_average_precision_at_k(model, csr_train, csr_val, K=12, show_progress=show_progress, num_threads=4)
    return map12

transactions_customers = transactions['customer_id'].unique().tolist()
len(transactions_customers)