{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\")\n\n## for data\nimport pandas as pd\nimport numpy as np\nimport re\nfrom datetime import datetime ##datathon alicorp\n\n## for plotting\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\n## for machine learning\nfrom sklearn import metrics, preprocessing\n\n## for deep learning\nfrom tensorflow.keras import models, layers, utils  #(2.6.0)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-08-04T23:49:13.950390Z","iopub.execute_input":"2023-08-04T23:49:13.951097Z","iopub.status.idle":"2023-08-04T23:49:24.298270Z","shell.execute_reply.started":"2023-08-04T23:49:13.951060Z","shell.execute_reply":"2023-08-04T23:49:24.297040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rentabilidad = pd.read_csv('/kaggle/input/datathon/RentabilidadProduct.csv',sep='|')\nsubmit_example = pd.read_csv('/kaggle/input/datathon/submit_example.csv')\ndata = pd.read_csv('/kaggle/input/datathon/train.csv',sep='|')\n\nprint('data', data.shape)\nprint('rentabilidad',rentabilidad.shape)\nprint('submit_example',submit_example.shape)","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:49:24.300301Z","iopub.execute_input":"2023-08-04T23:49:24.301072Z","iopub.status.idle":"2023-08-04T23:49:28.379733Z","shell.execute_reply.started":"2023-08-04T23:49:24.301036Z","shell.execute_reply":"2023-08-04T23:49:28.378532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:49:28.381121Z","iopub.execute_input":"2023-08-04T23:49:28.381457Z","iopub.status.idle":"2023-08-04T23:49:28.409382Z","shell.execute_reply.started":"2023-08-04T23:49:28.381428Z","shell.execute_reply":"2023-08-04T23:49:28.408054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"rentabilidad.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:50:19.030049Z","iopub.execute_input":"2023-08-04T23:50:19.030932Z","iopub.status.idle":"2023-08-04T23:50:19.043243Z","shell.execute_reply.started":"2023-08-04T23:50:19.030886Z","shell.execute_reply":"2023-08-04T23:50:19.042078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df=data.merge(rentabilidad, on='product_id', how='inner')\ndf['fecha_compra']= pd.to_datetime(df['fecha_compra'], format = '%Y-%m-%d', errors = 'coerce')\n# df['y']=(df.cantidad_venta*df.monto_venta_transf)\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:50:40.712324Z","iopub.execute_input":"2023-08-04T23:50:40.713206Z","iopub.status.idle":"2023-08-04T23:50:41.747409Z","shell.execute_reply.started":"2023-08-04T23:50:40.713163Z","shell.execute_reply":"2023-08-04T23:50:41.746528Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from datetime import timedelta\nimport pandas as pd\nd=df.fecha_compra.min()+timedelta(days=-1)\nlist_dates=[]\nsemana_dates=[]\ni=1\nfor y in range(0,60):\n    for x in range(0,7):\n        d=d+timedelta(days=1)\n        a='semana'+str(i)\n        semana_dates.append(a)\n        list_dates.append(d)\n    i=i+1\ncalendar=pd.DataFrame()\ncalendar['semana_dates'] = semana_dates\ncalendar['list_dates'] = list_dates","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:50:50.489074Z","iopub.execute_input":"2023-08-04T23:50:50.490553Z","iopub.status.idle":"2023-08-04T23:50:50.508745Z","shell.execute_reply.started":"2023-08-04T23:50:50.490509Z","shell.execute_reply":"2023-08-04T23:50:50.507501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtf_products=df.merge(calendar, left_on='fecha_compra', right_on='list_dates', how='inner')\n\nt=pd.DataFrame(dtf_products.utilidad_bruta_transf)\nmm_scaler = preprocessing.MinMaxScaler()\nutilidad_bruta_transf_mm = mm_scaler.fit_transform(t)\nutilidad_bruta_transf_mm = pd.DataFrame(utilidad_bruta_transf_mm)\ndtf_products['utilidad_bruta_transf_mm']=utilidad_bruta_transf_mm","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:51:02.336878Z","iopub.execute_input":"2023-08-04T23:51:02.337314Z","iopub.status.idle":"2023-08-04T23:51:02.959887Z","shell.execute_reply.started":"2023-08-04T23:51:02.337280Z","shell.execute_reply":"2023-08-04T23:51:02.958742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtf_products['semana_dates']='semana0'","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:51:09.537886Z","iopub.execute_input":"2023-08-04T23:51:09.538332Z","iopub.status.idle":"2023-08-04T23:51:09.563945Z","shell.execute_reply.started":"2023-08-04T23:51:09.538299Z","shell.execute_reply":"2023-08-04T23:51:09.562191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtf_products['utilidad_bruta_transf_mm'].isnull().sum()","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:51:17.162259Z","iopub.execute_input":"2023-08-04T23:51:17.162627Z","iopub.status.idle":"2023-08-04T23:51:17.172649Z","shell.execute_reply.started":"2023-08-04T23:51:17.162600Z","shell.execute_reply":"2023-08-04T23:51:17.171527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df2=dtf_products.groupby(['semana_dates', 'customer_id','product_id','tier_id','family_id','negocio_id','category_id']).agg({\n         'monto_venta_transf':sum,    # \n         'cantidad_venta': sum,  # \n         'peso_venta_transf': sum,  # \n         'fecha_compra': \"count\",  #\n         'utilidad_bruta_transf_mm': \"median\"  #\n    }).reset_index()\ndf2.rename(columns={'fecha_compra':'frequencia'},inplace=True)","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:51:25.088150Z","iopub.execute_input":"2023-08-04T23:51:25.088642Z","iopub.status.idle":"2023-08-04T23:51:26.306414Z","shell.execute_reply.started":"2023-08-04T23:51:25.088605Z","shell.execute_reply":"2023-08-04T23:51:26.305138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ---------------------------------------\n# Construcción de Data Set [User - Item]\n# ---------------------------------------\n\n# Base de datos suma de monto y trx total por cliente:\ncopy = pd.DataFrame()\ncopy = df2.copy()\ntempMontoTot = pd.DataFrame()\ntempMontoTot['montoTot'] = copy.groupby(['customer_id', 'semana_dates']).agg('monto_venta_transf').sum()\ntempMontoTot['trxTot'] = copy.groupby(['customer_id','semana_dates']).agg('frequencia').sum()\n#agregado sandy***************************************************************\ntempMontoTot['cantTot'] = copy.groupby(['customer_id', 'semana_dates']).agg('cantidad_venta').sum()\ntempMontoTot['pesoTot'] = copy.groupby(['customer_id','semana_dates']).agg('peso_venta_transf').sum()\ntempMontoTot['renTot'] = copy.groupby(['customer_id','semana_dates']).agg('utilidad_bruta_transf_mm').sum()\n#agregado sandy***************************************************************\ntempMontoTot = tempMontoTot.reset_index()\ntempMontoTot.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:51:33.880571Z","iopub.execute_input":"2023-08-04T23:51:33.880993Z","iopub.status.idle":"2023-08-04T23:51:34.294003Z","shell.execute_reply.started":"2023-08-04T23:51:33.880959Z","shell.execute_reply":"2023-08-04T23:51:34.292192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Base de datos suma de monto y trx total por cliente y comercio:\ncopy = pd.DataFrame()\ncopy = df2.copy()\ntempMontoProducto = pd.DataFrame() \ntempMontoProducto['montoProducto'] = copy.groupby(['customer_id','product_id','semana_dates']).agg('monto_venta_transf').sum()\ntempMontoProducto['trxProducto'] = copy.groupby(['customer_id','product_id','semana_dates']).agg('frequencia').sum()\n#agregado sandy***************************************************************\ntempMontoProducto['cantProducto'] = copy.groupby(['customer_id','product_id','semana_dates']).agg('cantidad_venta').sum()\ntempMontoProducto['pesoProducto'] = copy.groupby(['customer_id','product_id','semana_dates']).agg('peso_venta_transf').sum()\ntempMontoProducto['renProducto'] = copy.groupby(['customer_id','product_id','semana_dates']).agg('utilidad_bruta_transf_mm').sum()\n#agregado sandy***************************************************************\ntempMontoProducto = tempMontoProducto.reset_index()\n\nprint('****************************')\nprint('  Dimensiones User - Item')\nprint('****************************')\n\ncliUn = tempMontoTot.shape[0]\ncomUn = tempMontoProducto[['product_id','semana_dates']].drop_duplicates().shape[0]\ndimDb = tempMontoProducto.shape\nprint('1. Clientes únicos: '+str(cliUn))\nprint('2. Productos únicos: '+str(comUn))\nprint('3. DataSet Cliente X Producto: '+str(dimDb)+'\\n')\nprint(tempMontoProducto.columns)","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:52:06.913311Z","iopub.execute_input":"2023-08-04T23:52:06.913851Z","iopub.status.idle":"2023-08-04T23:52:09.347932Z","shell.execute_reply.started":"2023-08-04T23:52:06.913793Z","shell.execute_reply":"2023-08-04T23:52:09.346696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ------------------------\n# Construyendo el Ranking\n# ------------------------\n\n## Cálculo de Peso del userXitem en base al monto y transacción por cliente - comercio:\ndbMerge = pd.merge(tempMontoProducto, tempMontoTot, on =['customer_id','semana_dates'], how = 'left')\ndbMerge['preRating_1'] = (dbMerge['montoProducto']/dbMerge['montoTot'])*(dbMerge['trxProducto']/dbMerge['trxTot'])\n#agregado sandy***************************************************************\ndbMerge['preRating_2'] = (dbMerge['cantProducto']/dbMerge['cantTot'])*(dbMerge['montoProducto']/dbMerge['montoTot'])*(dbMerge['pesoProducto']/dbMerge['pesoTot'])\ndbMerge['preRating_3'] = ((dbMerge['cantProducto']/dbMerge['cantTot'])*(dbMerge['renProducto']/dbMerge['renTot'])*(dbMerge['trxProducto']/dbMerge['trxTot']))/((dbMerge['montoProducto']/dbMerge['montoTot'])*(dbMerge['pesoProducto']/dbMerge['pesoTot']))\ndbMerge['preRating_4'] = ((dbMerge['cantProducto']/dbMerge['cantTot'])*(dbMerge['renProducto']/dbMerge['renTot'])*(dbMerge['montoProducto']/dbMerge['montoTot'])*(dbMerge['trxProducto']/dbMerge['trxTot']))/((dbMerge['pesoProducto']/dbMerge['pesoTot']))\ndbMerge['preRating_5'] = (dbMerge['cantProducto']/dbMerge['cantTot'])*(dbMerge['renProducto']/dbMerge['renTot'])*(dbMerge['montoProducto']/dbMerge['montoTot'])*(dbMerge['trxProducto']/dbMerge['trxTot'])\n#agregado sandy***************************************************************\n\n# Creación del \"Rating Final\" a una escala de [0-1]\ncopy = pd.DataFrame()\ncopy = dbMerge.copy()\ntempRatingTot = pd.DataFrame()\n\ntempRatingTot['sumaPreRat_1'] = copy.groupby(['customer_id', 'semana_dates']).agg('preRating_1').sum()\n#agregado sandy***************************************************************\ntempRatingTot['sumaPreRat_2'] = copy.groupby(['customer_id', 'semana_dates']).agg('preRating_2').sum()\ntempRatingTot['sumaPreRat_3'] = copy.groupby(['customer_id', 'semana_dates']).agg('preRating_3').sum()\ntempRatingTot['sumaPreRat_4'] = copy.groupby(['customer_id', 'semana_dates']).agg('preRating_4').sum()\ntempRatingTot['sumaPreRat_5'] = copy.groupby(['customer_id', 'semana_dates']).agg('preRating_5').sum()\n#agregado sandy***************************************************************\ntempRatingTot = tempRatingTot.reset_index()\n\ndataBaseInputPre = pd.merge(dbMerge, tempRatingTot, on=['customer_id', 'semana_dates'], how='left')\ndataBaseInputPre['rating_1'] = dataBaseInputPre['preRating_1']/dataBaseInputPre['sumaPreRat_1']\n#agregado sandy***************************************************************\ndataBaseInputPre['rating_2'] = dataBaseInputPre['preRating_2']/dataBaseInputPre['sumaPreRat_2']\ndataBaseInputPre['rating_3'] = dataBaseInputPre['preRating_3']/dataBaseInputPre['sumaPreRat_3']\ndataBaseInputPre['rating_4'] = dataBaseInputPre['preRating_4']/dataBaseInputPre['sumaPreRat_4']\ndataBaseInputPre['rating_5'] = dataBaseInputPre['preRating_5']/dataBaseInputPre['sumaPreRat_5']\n#agregado sandy***************************************************************\n\n# Base de Datos Final de Recomendación:\ndataBaseInputPre = dataBaseInputPre[['customer_id','product_id','rating_1','rating_2','rating_3','rating_4','rating_5','semana_dates']] #como no filtra, ya no se llama al campo semana_dates\ndataBaseInputPre = dataBaseInputPre.sort_values('customer_id')\ndataBaseInputPre.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-04T23:52:17.616438Z","iopub.execute_input":"2023-08-04T23:52:17.616863Z","iopub.status.idle":"2023-08-04T23:52:18.712599Z","shell.execute_reply.started":"2023-08-04T23:52:17.616804Z","shell.execute_reply":"2023-08-04T23:52:18.711303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df=dataBaseInputPre.merge(rentabilidad,on='product_id', how='inner')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:34:24.427631Z","iopub.execute_input":"2023-08-05T00:34:24.428128Z","iopub.status.idle":"2023-08-05T00:34:24.589878Z","shell.execute_reply.started":"2023-08-05T00:34:24.428090Z","shell.execute_reply":"2023-08-05T00:34:24.588477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtf_products=df[['product_id','family_id','negocio_id','category_id','tier_id']]\n\ndummies_family = pd.get_dummies(dtf_products['family_id'], prefix='family')\ndummies_negocio = pd.get_dummies(dtf_products['negocio_id'], prefix='negocio')\ndummies_category = pd.get_dummies(dtf_products['category_id'], prefix='category')\ndummies_tier = pd.get_dummies(dtf_products['tier_id'], prefix='tier')\n\n# Concatenar las columnas binarias con la columna 'product_id'\ntabla_doble_entrada = pd.concat([dtf_products['product_id'], dummies_family, dummies_negocio, dummies_category, dummies_tier], axis=1)\n\n# Eliminar filas duplicadas para tener un único 'product_id' en la tabla\ntabla_doble_entrada = tabla_doble_entrada.drop_duplicates(subset='product_id', keep='first')\n\n# Configurar 'product_id' como el índice de la tabla\ndtf_products = tabla_doble_entrada.set_index('product_id')\ndtf_products.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:34:37.372163Z","iopub.execute_input":"2023-08-05T00:34:37.373393Z","iopub.status.idle":"2023-08-05T00:34:38.870032Z","shell.execute_reply.started":"2023-08-05T00:34:37.373355Z","shell.execute_reply":"2023-08-05T00:34:38.868830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Crear una tabla dinámica (pivot table) para obtener la matriz de calificaciones\ndtf_users = pd.pivot_table(df, values='rating_1', index='customer_id', columns='product_id')\n# Si prefieres que los valores faltantes sean nulos en lugar de ceros, simplemente omite el argumento 'fill_value=0'.\ndtf_users.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:34:51.069805Z","iopub.execute_input":"2023-08-05T00:34:51.070274Z","iopub.status.idle":"2023-08-05T00:34:51.694871Z","shell.execute_reply.started":"2023-08-05T00:34:51.070238Z","shell.execute_reply":"2023-08-05T00:34:51.693568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtf_users = pd.DataFrame(preprocessing.MinMaxScaler(feature_range=(0.5,1)).fit_transform(dtf_users.values), \n                         columns=dtf_users.columns, index=dtf_users.index)\ndtf_users","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:35:00.098963Z","iopub.execute_input":"2023-08-05T00:35:00.099425Z","iopub.status.idle":"2023-08-05T00:35:00.280521Z","shell.execute_reply.started":"2023-08-05T00:35:00.099387Z","shell.execute_reply":"2023-08-05T00:35:00.278936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Model Desing & Testing (Collaborative Filtering)","metadata":{}},{"cell_type":"code","source":"dtf_users.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:35:48.124425Z","iopub.execute_input":"2023-08-05T00:35:48.125410Z","iopub.status.idle":"2023-08-05T00:35:48.157365Z","shell.execute_reply.started":"2023-08-05T00:35:48.125363Z","shell.execute_reply":"2023-08-05T00:35:48.156270Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtf_products.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:35:55.646790Z","iopub.execute_input":"2023-08-05T00:35:55.647291Z","iopub.status.idle":"2023-08-05T00:35:55.673582Z","shell.execute_reply.started":"2023-08-05T00:35:55.647255Z","shell.execute_reply":"2023-08-05T00:35:55.672541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"split = int(0.8*dtf_users.shape[1])\nsplit","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:36:15.496907Z","iopub.execute_input":"2023-08-05T00:36:15.497342Z","iopub.status.idle":"2023-08-05T00:36:15.503532Z","shell.execute_reply.started":"2023-08-05T00:36:15.497306Z","shell.execute_reply":"2023-08-05T00:36:15.502764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dtf_train = dtf_users.iloc[:split, :]\ndtf_test = dtf_users.iloc[split:, :]\nprint(dtf_train.shape)\nprint(dtf_test.shape)","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:36:20.682472Z","iopub.execute_input":"2023-08-05T00:36:20.682950Z","iopub.status.idle":"2023-08-05T00:36:20.689965Z","shell.execute_reply.started":"2023-08-05T00:36:20.682911Z","shell.execute_reply":"2023-08-05T00:36:20.689117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = dtf_train.stack(dropna=True).reset_index().rename(columns={0:\"y\"})\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:36:26.955268Z","iopub.execute_input":"2023-08-05T00:36:26.955678Z","iopub.status.idle":"2023-08-05T00:36:26.987446Z","shell.execute_reply.started":"2023-08-05T00:36:26.955645Z","shell.execute_reply":"2023-08-05T00:36:26.986336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test = dtf_test.stack(dropna=True).reset_index().rename(columns={0:\"y\"})\ntest.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:36:34.562928Z","iopub.execute_input":"2023-08-05T00:36:34.563348Z","iopub.status.idle":"2023-08-05T00:36:34.844588Z","shell.execute_reply.started":"2023-08-05T00:36:34.563315Z","shell.execute_reply":"2023-08-05T00:36:34.843365Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\n\n# Etiquetar los IDs de usuarios y productos con valores numéricos\nuser_encoder = LabelEncoder()\nproduct_encoder = LabelEncoder()\ntrain[\"customer_id\"] = user_encoder.fit_transform(train[\"customer_id\"])\ntrain[\"product_id\"] = product_encoder.fit_transform(train[\"product_id\"])\n\ntest[\"customer_id\"] = user_encoder.fit_transform(test[\"customer_id\"])\ntest[\"product_id\"] = product_encoder.fit_transform(test[\"product_id\"])","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:36:41.891715Z","iopub.execute_input":"2023-08-05T00:36:41.892693Z","iopub.status.idle":"2023-08-05T00:36:41.970809Z","shell.execute_reply.started":"2023-08-05T00:36:41.892650Z","shell.execute_reply":"2023-08-05T00:36:41.969718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"embeddings_size = 50\nusr, prd = dtf_users.shape[0], dtf_users.shape[1]\n\n# Users (,1,embedding_size) and Reshape (,embedding_size)\nxusers_in = layers.Input(name=\"xusers_in\", shape=(1,))\nxusers_emb = layers.Embedding(name=\"xusers_emb\", input_dim=usr, output_dim=embeddings_size)(xusers_in)\nxusers = layers.Reshape(name='xusers', target_shape=(embeddings_size,))(xusers_emb)\n\n# Products (,1,embedding_size) and Reshape (,embedding_size)\nxproducts_in = layers.Input(name=\"xproducts_in\", shape=(1,))\nxproducts_emb = layers.Embedding(name=\"xproducts_emb\", input_dim=prd, output_dim=embeddings_size)(xproducts_in)\nxproducts = layers.Reshape(name='xproducts', target_shape=(embeddings_size,))(xproducts_emb)\n\n# Product (,1) values[-1,1]\nxx = layers.Dot(name='xx', normalize=True, axes=1)([xusers, xproducts])\n\n# Predict ratings (,1)\ny_out = layers.Dense(name=\"y_out\", units=1, activation='linear')(xx)\n\n# Compile\nmodel = models.Model(inputs=[xusers_in,xproducts_in], outputs=y_out, name=\"CollaborativeFiltering\")\nmodel.compile(optimizer='adam', loss='mean_absolute_error', metrics=['mean_absolute_percentage_error'])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:36:49.604362Z","iopub.execute_input":"2023-08-05T00:36:49.604862Z","iopub.status.idle":"2023-08-05T00:36:49.878985Z","shell.execute_reply.started":"2023-08-05T00:36:49.604805Z","shell.execute_reply":"2023-08-05T00:36:49.877882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''\nPlot loss and metrics of keras training.\n'''\ndef utils_plot_keras_training(training):\n    metrics = [k for k in training.history.keys() if (\"loss\" not in k) and (\"val\" not in k)]\n    fig, ax = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(15,3))\n    \n    ## training\n    ax[0].set(title=\"Training\")\n    ax11 = ax[0].twinx()\n    ax[0].plot(training.history['loss'], color='black')\n    ax[0].set_xlabel('Epochs')\n    ax[0].set_ylabel('Loss', color='black')\n    for metric in metrics:\n        ax11.plot(training.history[metric], label=metric)\n    ax11.set_ylabel(\"Score\", color='steelblue')\n    ax11.legend()\n    \n    ## validation\n    ax[1].set(title=\"Validation\")\n    ax22 = ax[1].twinx()\n    ax[1].plot(training.history['val_loss'], color='black')\n    ax[1].set_xlabel('Epochs')\n    ax[1].set_ylabel('Loss', color='black')\n    for metric in metrics:\n        ax22.plot(training.history['val_'+metric], label=metric)\n    ax22.set_ylabel(\"Score\", color=\"steelblue\")\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:36:59.451974Z","iopub.execute_input":"2023-08-05T00:36:59.452458Z","iopub.status.idle":"2023-08-05T00:36:59.466346Z","shell.execute_reply.started":"2023-08-05T00:36:59.452411Z","shell.execute_reply":"2023-08-05T00:36:59.464995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train\ntraining = model.fit(x=[train[\"customer_id\"], train[\"product_id\"]], y=train[\"y\"], \n                     epochs=100, batch_size=128, shuffle=True, verbose=0, validation_split=0.3)\nmodel = training.model\nutils_plot_keras_training(training)","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:37:08.146766Z","iopub.execute_input":"2023-08-05T00:37:08.147208Z","iopub.status.idle":"2023-08-05T00:40:21.409881Z","shell.execute_reply.started":"2023-08-05T00:37:08.147173Z","shell.execute_reply":"2023-08-05T00:40:21.408659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test[\"yhat\"] = model.predict([test[\"customer_id\"], test[\"product_id\"]])\ntest","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:40:21.411689Z","iopub.execute_input":"2023-08-05T00:40:21.412062Z","iopub.status.idle":"2023-08-05T00:40:51.607631Z","shell.execute_reply.started":"2023-08-05T00:40:21.412029Z","shell.execute_reply":"2023-08-05T00:40:51.606001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"yhat\"] = model.predict([train[\"customer_id\"], train[\"product_id\"]])\ntrain","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:41:37.530981Z","iopub.execute_input":"2023-08-05T00:41:37.531472Z","iopub.status.idle":"2023-08-05T00:41:40.626654Z","shell.execute_reply.started":"2023-08-05T00:41:37.531438Z","shell.execute_reply":"2023-08-05T00:41:40.625441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Establecer el umbral de relevancia\numbral_relevancia = 0.5\n\n# Función para calcular el recall para un usuario específico\ndef calcular_recall(usuario):\n    productos_relevantes_usuario = train[(train['customer_id'] == usuario) & (train['y'] >= umbral_relevancia)]\n    productos_recomendados_usuario = train[(train['customer_id'] == usuario) & (train['yhat'] >= umbral_relevancia)]\n    true_positives = len(productos_recomendados_usuario.merge(productos_relevantes_usuario, on='product_id'))\n    total_relevantes = len(productos_relevantes_usuario)\n    return true_positives / total_relevantes if total_relevantes > 0 else 0\n\n# Calcular el recall promedio para todos los usuarios\nusuarios = train['customer_id'].unique()\nrecall_promedio = sum(calcular_recall(usuario) for usuario in usuarios) / len(usuarios)\n\nprint(\"Recall promedio:\", recall_promedio)","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:41:43.035437Z","iopub.execute_input":"2023-08-05T00:41:43.035853Z","iopub.status.idle":"2023-08-05T00:41:46.159373Z","shell.execute_reply.started":"2023-08-05T00:41:43.035805Z","shell.execute_reply":"2023-08-05T00:41:46.158163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Establecer el umbral de relevancia\numbral_relevancia = 0.5\n\n# Función para calcular el recall para un usuario específico\ndef calcular_recall(usuario):\n    productos_relevantes_usuario = test[(test['customer_id'] == usuario) & (test['y'] >= umbral_relevancia)]\n    productos_recomendados_usuario = test[(test['customer_id'] == usuario) & (test['yhat'] >= umbral_relevancia)]\n    true_positives = len(productos_recomendados_usuario.merge(productos_relevantes_usuario, on='product_id'))\n    total_relevantes = len(productos_relevantes_usuario)\n    return true_positives / total_relevantes if total_relevantes > 0 else 0\n\n# Calcular el recall promedio para todos los usuarios\nusuarios = test['customer_id'].unique()\nrecall_promedio = sum(calcular_recall(usuario) for usuario in usuarios) / len(usuarios)\n\nprint(\"Recall promedio:\", recall_promedio)","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:43:47.926958Z","iopub.execute_input":"2023-08-05T00:43:47.927443Z","iopub.status.idle":"2023-08-05T00:45:23.598791Z","shell.execute_reply.started":"2023-08-05T00:43:47.927407Z","shell.execute_reply":"2023-08-05T00:45:23.597521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sorted = test.sort_values(by='yhat', ascending=False)\n\n# Agrupar los productos por cliente y crear una lista con los productos ordenados\ndf_grouped = df_sorted.groupby('customer_id')['product_id'].apply(list).reset_index()\n\n# Renombrar las columnas\ndf_grouped.columns = ['cliente', 'productos_ordenados']","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:48:03.973639Z","iopub.execute_input":"2023-08-05T00:48:03.974845Z","iopub.status.idle":"2023-08-05T00:48:04.577538Z","shell.execute_reply.started":"2023-08-05T00:48:03.974769Z","shell.execute_reply":"2023-08-05T00:48:04.576275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sorted = test.sort_values(by='y', ascending=False)\n\n# Agrupar los productos por cliente y crear una lista con los productos ordenados\ndf_grouped2 = df_sorted.groupby('customer_id')['product_id'].apply(list).reset_index()\n\n# Renombrar las columnas\ndf_grouped2.columns = ['cliente', 'productos_ordenados']","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:48:35.802041Z","iopub.execute_input":"2023-08-05T00:48:35.802426Z","iopub.status.idle":"2023-08-05T00:48:36.416726Z","shell.execute_reply.started":"2023-08-05T00:48:35.802396Z","shell.execute_reply":"2023-08-05T00:48:36.415283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_grouped.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:48:11.719520Z","iopub.execute_input":"2023-08-05T00:48:11.719943Z","iopub.status.idle":"2023-08-05T00:48:11.732531Z","shell.execute_reply.started":"2023-08-05T00:48:11.719907Z","shell.execute_reply":"2023-08-05T00:48:11.731453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_grouped2.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-05T00:48:45.362056Z","iopub.execute_input":"2023-08-05T00:48:45.362563Z","iopub.status.idle":"2023-08-05T00:48:45.379296Z","shell.execute_reply.started":"2023-08-05T00:48:45.362521Z","shell.execute_reply":"2023-08-05T00:48:45.377844Z"},"trusted":true},"execution_count":null,"outputs":[]}]}