File size: 5,769 Bytes
afadb57
9045f37
 
 
 
112b798
9045f37
 
 
afadb57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9045f37
 
afadb57
 
 
 
9045f37
afadb57
 
9045f37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fdf715a
9045f37
 
 
 
 
 
 
 
 
 
129085b
9045f37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
afadb57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import os
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from joblib import dump, load
from sklearn.preprocessing import normalize
import re

def get_next_version(file_prefix, folder='RecommendationFiles/'):
    """Find the latest version of a file and return the next version's filename."""
    # Regular expression to match files like 'file_0001.joblib'
    pattern = re.compile(rf"{file_prefix}_(\d+)\.joblib")
    files = [f for f in os.listdir(folder) if pattern.match(f)]
    
    # Extract version numbers from matching files
    versions = [int(pattern.match(f).group(1)) for f in files]
    
    # Determine the next version number
    if versions:
        next_version = max(versions) + 1
    else:
        next_version = 1  # If no versions exist, start with 1
    
    # Return the next version filename
    return f"{file_prefix}_{next_version:04d}.joblib"

def get_latest_version(file_prefix, folder='RecommendationFiles/'):
    """Find the latest version of a file to load."""
    # Regular expression to match files like 'file_0001.joblib'
    pattern = re.compile(rf"{file_prefix}_(\d+)\.joblib")
    files = [f for f in os.listdir(folder) if pattern.match(f)]
    
    # Extract version numbers from matching files
    versions = [int(pattern.match(f).group(1)) for f in files]
    
    if versions:
        latest_version = max(versions)
        return f"{file_prefix}_{latest_version:04d}.joblib"
    else:
        raise FileNotFoundError(f"No versions found for {file_prefix}")


def recomienda_tf(new_basket, cestas, productos): 

    tf_matrix_file = get_latest_version('count_matrix')
    count_vectorizer_file = get_latest_version('count_vectorizer')
    
    # Cargar la matriz TF y el modelo
    tf_matrix = load(tf_matrix_file)
    count = load(count_vectorizer_file)
                    
    # Convertir la nueva cesta en formato TF (Term Frequency)
    new_basket_str = ' '.join(new_basket)
    new_basket_vector = count.transform([new_basket_str])
    new_basket_tf = normalize(new_basket_vector, norm='l1')  # Normalizamos la matriz count de la cesta actual
    # Comparar la nueva cesta con las anteriores
    similarities = cosine_similarity(new_basket_tf, tf_matrix)
    # Obtener los índices de las cestas más similares
    similar_indices = similarities.argsort()[0][-4:]  # Las 4 más similares
    # Crear un diccionario para contar las recomendaciones
    recommendations_count = {}
    total_similarity = 0
    # Recomendar productos de cestas similares
    for idx in similar_indices:
        sim_score = similarities[0][idx]
        total_similarity += sim_score  # Suma de las similitudes
        products = cestas.iloc[idx]['Cestas'].split()
        # Usar un conjunto para evitar contar productos múltiples veces en la misma cesta
        unique_products = set(products)  # Usar un conjunto para obtener productos únicos
        # Con esto evitamos que la importancia crezca por las unidades
        for product in unique_products:
            if product.strip() not in new_basket:  # Evitar recomendar lo que ya está en la cesta
                recommendations_count[product.strip()] = recommendations_count.get(product.strip(), 0) + sim_score
                # Almacena el conteo de la relevancia de cada producto basado en cuántas veces aparece en las cestas similares, ponderado por la similitud de cada cesta.
    # Calcular la probabilidad relativa de cada producto recomendado
    recommendations_with_prob = []
    if total_similarity > 0:  # Verificar que total_similarity no sea cero
        recommendations_with_prob = [(product, score / total_similarity) for product, score in recommendations_count.items()]
    else:
        print("No se encontraron similitudes suficientes para calcular probabilidades.")
     
    recommendations_with_prob.sort(key=lambda x: x[1], reverse=True)  # Ordenar por puntuación
    # Crear un nuevo DataFrame para almacenar las recomendaciones
    recommendations_data = []
    
    for product, score in recommendations_with_prob:
        # Buscar la descripción en el DataFrame de productos
        description = productos.loc[productos['ARTICULO'] == product, 'DESCRIPCION']
        if not description.empty:
            recommendations_data.append({
                'ARTICULO': product,
                'DESCRIPCION': description.values[0],  # Obtener el primer valor encontrado
                'RELEVANCIA': score
            })
    recommendations_df = pd.DataFrame(recommendations_data)
    
    return recommendations_df.head(5)

def retroalimentacion(cestas, cesta_nueva):
    # Pasamos de lista a cadena de texto
    cesta_unida = ' '.join(cesta_nueva)
    # Añadimos la cesta nueva al histórico de cestas. Primero comprobamos si la cesta nueva ya está
    if not cestas['Cestas'].isin([cesta_unida]).any():
        # Añadir la nueva cesta si no existe
        cestas.loc[len(cestas)] = cesta_unida
        print("Cesta añadida.")
        # Reescribimos la nueva cesta
        cestas.to_csv('cestas_final.csv')
    else:
        print("La cesta ya existe en el DataFrame.")
    
    # Vectorizamos de nuevo el df de cestas
    count_vectorizer = CountVectorizer()
    count_vectorizer.fit(cestas['Cestas'])
    count_matrix = count_vectorizer.transform(cestas['Cestas'])
    tf_matrix = normalize(count_matrix, norm='l1')

    # Guardar con nueva versión
    count_vectorizer_file = get_next_version('count_vectorizer')
    tf_matrix_file = get_next_version('tf_matrix')
    
    dump(count_vectorizer, count_vectorizer_file)
    dump(tf_matrix, tf_matrix_file)
    

    return None