{ "cells": [ { "cell_type": "markdown", "id": "61c88034-1243-4ab7-9d20-96398b0d9efd", "metadata": {}, "source": [ "# Case Study: Predictive Analytics for E-commerce\n", "\n", "## Business Context:\n", "- You are hired as a Data Science and AI for an e-commerce company named \"Terra Store.\" Terra Store is looking to enhance its marketing strategy by predicting customer purchase behavior based on historical data. The company wants to build an AI-powered application that can provide insights into which products a customer is likely to purchase next.\n", "\n", "## Problem Statement:\n", "- Terra Store has provided you with a dataset containing information about customer interactions, purchases, and product details. Your task is to develop a web-based AI application that predicts the next product a customer is likely to buy. The application should be user-friendly, allowing marketing teams to target customers more effectively." ] }, { "cell_type": "markdown", "id": "f4f2378e-150a-4caa-9de0-6d4034bded4b", "metadata": {}, "source": [ "## Data Description:\n", "- The dataset includes the following information:\n", "- Customer Interactions:\n", " - Customer ID\n", " - Page views\n", " - Time spent on the website\n", "- Purchase History:\n", " - Customer ID\n", " - Product ID\n", " - Purchase date\n", "- Product Details:\n", " - Product ID\n", " - Category\n", " - Price\n", " - Ratings" ] }, { "cell_type": "markdown", "id": "270ab428-5a85-4b96-8fc2-0b5b803c625d", "metadata": {}, "source": [ "## Step by Step\n", "1. Data exploration\n", "2. Data preprocessing\n", "3. Model Development\n", "4. Web Application Development" ] }, { "cell_type": "markdown", "id": "0730d462-87a6-4b07-af77-ab4e02e77f9f", "metadata": {}, "source": [ "## Data exploration" ] }, { "cell_type": "code", "execution_count": 444, "id": "2c8130e6-7add-4d51-8e5a-aeab1a3bec09", "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "import random\n", "import warnings\n", "import joblib\n", "import gradio as gr\n", "\n", "from faker import Faker\n", "\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "from surprise import KNNWithMeans\n", "from surprise.model_selection import train_test_split\n", "from surprise.accuracy import rmse\n", "\n", "from surprise import Dataset\n", "from surprise import Reader\n", "\n", "fake = Faker()\n", "warnings.filterwarnings('ignore')\n", "pd.set_option(\"display.max_columns\", 100)" ] }, { "cell_type": "code", "execution_count": 11, "id": "b4100a7e-59e3-4fe6-a0ac-b3c3e3c69621", "metadata": {}, "outputs": [], "source": [ "df_ci = pd.read_csv(\"/Users/Ruangguru/Documents/Project/skilvul/customer_interactions.csv\")\n", "df_pd = pd.read_csv(\"/Users/Ruangguru/Documents/Project/skilvul/product_details.csv\", delimiter=';')\n", "df_ph = pd.read_csv(\"/Users/Ruangguru/Documents/Project/skilvul/purchase_history.csv\", delimiter=';')" ] }, { "cell_type": "markdown", "id": "c01b2fbc-683a-4169-8096-d5c2f61564ed", "metadata": {}, "source": [ "- because the data is very small, so i decided to create syntetics data " ] }, { "cell_type": "markdown", "id": "3036a93f-129e-4a08-a446-441e2dcacfbf", "metadata": {}, "source": [ "### data customer interactions" ] }, { "cell_type": "code", "execution_count": 12, "id": "365d1c9c-069a-476e-84e2-a6cd872ecaca", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
customer_idpage_viewstime_spent
0125120
122090
2330150
341580
4522110
\n", "
" ], "text/plain": [ " customer_id page_views time_spent\n", "0 1 25 120\n", "1 2 20 90\n", "2 3 30 150\n", "3 4 15 80\n", "4 5 22 110" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ci" ] }, { "cell_type": "code", "execution_count": 169, "id": "9d770909-3e13-4e5f-b18b-f6db1438dfb7", "metadata": {}, "outputs": [], "source": [ "len_fake_data_ci = 95\n", "df_fake_ci = pd.DataFrame()\n", "df_fake_ci = df_fake_ci.assign(page_views = pd.Series(fake.random.randint(1, 35) for i in range(len_fake_data_ci)),\n", " time_spent = pd.Series(fake.random.randint(50, 300) for i in range(len_fake_data_ci)))" ] }, { "cell_type": "code", "execution_count": 170, "id": "d4944ac3-326b-4339-ab4b-e5c0ac555a61", "metadata": {}, "outputs": [], "source": [ "df_fake_ci = df_fake_ci.reset_index().rename(columns={\n", " 'index' : 'customer_id'\n", "})\n", "\n", "df_fake_ci['customer_id'] = df_fake_ci['customer_id'] + 6" ] }, { "cell_type": "code", "execution_count": 173, "id": "4370a491-b716-41ce-9be6-941fc7aa16a3", "metadata": {}, "outputs": [], "source": [ "df_ci_full = pd.concat([df_ci, df_fake_ci], ignore_index=True)" ] }, { "cell_type": "markdown", "id": "4b43983c-1c6a-4bc5-8d86-0744fed3fed1", "metadata": {}, "source": [ "### product details" ] }, { "cell_type": "code", "execution_count": 13, "id": "ea1710f6-b1cc-485e-8e71-de9462cd9b13", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
product_idcategorypriceratingsUnnamed: 4Unnamed: 5Unnamed: 6
0101Electronics5004.5NaNNaNNaN
1102Clothing503.8NaNNaNNaN
2103Home & Kitchen2004.2NaNNaNNaN
3104Beauty304.0NaNNaNNaN
4105Electronics8004.8NaNNaNNaN
\n", "
" ], "text/plain": [ " product_id category price ratings Unnamed: 4 Unnamed: 5 \\\n", "0 101 Electronics 500 4.5 NaN NaN \n", "1 102 Clothing 50 3.8 NaN NaN \n", "2 103 Home & Kitchen 200 4.2 NaN NaN \n", "3 104 Beauty 30 4.0 NaN NaN \n", "4 105 Electronics 800 4.8 NaN NaN \n", "\n", " Unnamed: 6 \n", "0 NaN \n", "1 NaN \n", "2 NaN \n", "3 NaN \n", "4 NaN " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_pd" ] }, { "cell_type": "code", "execution_count": 196, "id": "5af8face-680b-443f-91c3-bafe78e322a8", "metadata": {}, "outputs": [], "source": [ "len_fake_data_pd = 20\n", "df_fake_pd = pd.DataFrame()\n", "df_fake_pd = df_fake_pd.assign(category = pd.Series(random.choice(['Electronics', 'Clothing', 'Home & Kitchen', 'Beauty']) for i in range(len_fake_data_pd)),\n", " price = pd.Series(fake.random.randint(30, 1000) for i in range(len_fake_data_ci)),\n", " ratings = pd.Series(round(fake.random.uniform(1, 5), 2) for i in range(len_fake_data_ci)))" ] }, { "cell_type": "code", "execution_count": 197, "id": "c2d9c9cf-096f-4eeb-a5b1-30c02d43655b", "metadata": {}, "outputs": [], "source": [ "df_fake_pd = df_fake_pd.reset_index().rename(columns={\n", " 'index' : 'product_id'\n", "})\n", "\n", "df_fake_pd['product_id'] = df_fake_pd['product_id'] + 106" ] }, { "cell_type": "code", "execution_count": 199, "id": "8915489e-fab3-4582-9c4f-2d9e5d5037f8", "metadata": {}, "outputs": [], "source": [ "df_pd_full = pd.concat([df_pd, df_fake_pd], ignore_index=True)" ] }, { "cell_type": "markdown", "id": "9d5c54e3-a9fb-46ce-8614-b33093075196", "metadata": {}, "source": [ "### purchase history" ] }, { "cell_type": "code", "execution_count": 246, "id": "3e8adc2c-12f4-4de1-a329-e6e6500577ae", "metadata": {}, "outputs": [], "source": [ "len_fake_data_ph = 994\n", "df_fake_ph = pd.DataFrame()\n", "df_fake_ph = df_fake_ph.assign(customer_id = pd.Series(fake.random.randint(1, 100) for i in range(len_fake_data_ph)),\n", " product_id = pd.Series(fake.random.randint(101, 125) for i in range(len_fake_data_ph)),\n", " purchase_date = pd.Series(fake.date_between_dates(pd.to_datetime('2023-01-01'), pd.to_datetime('2023-01-06')) for i in range(len_fake_data_ph)))" ] }, { "cell_type": "code", "execution_count": 247, "id": "5e6089c9-16c9-4f72-b722-fb9f96f55af4", "metadata": {}, "outputs": [], "source": [ "df_ph_full = pd.concat([df_ph, df_fake_ph], ignore_index=True)" ] }, { "cell_type": "markdown", "id": "632e3b2b-f489-43f4-8b08-4853745bd259", "metadata": {}, "source": [ "### final data" ] }, { "cell_type": "code", "execution_count": 248, "id": "fb959b97-8ddf-4b99-a985-65096de6e019", "metadata": {}, "outputs": [], "source": [ "df_ph_full = pd.merge(df_ph_full, df_ci_full, on=['customer_id']).drop(columns=['Unnamed: 3', 'Unnamed: 4', 'Unnamed: 5', 'Unnamed: 6'])\n", "df_ph_final = pd.merge(df_ph_full, df_pd_full, on=['product_id']).drop(columns=['Unnamed: 4', 'Unnamed: 5', 'Unnamed: 6'])" ] }, { "cell_type": "code", "execution_count": 249, "id": "be4f2ee4-4dfa-4feb-959c-700861e4725d", "metadata": {}, "outputs": [], "source": [ "df_ph_final['purchase_date'] = pd.to_datetime(df_ph_final['purchase_date'])" ] }, { "cell_type": "code", "execution_count": 250, "id": "3e2980ea-13c3-45db-a862-2b6b0dd2793e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
customer_idproduct_idpurchase_datepage_viewstime_spentcategorypriceratings
011012023-01-0125120Electronics5004.5
131012023-01-0130150Electronics5004.5
231012023-01-0330150Electronics5004.5
341012023-01-021580Electronics5004.5
451012023-01-0522110Electronics5004.5
\n", "
" ], "text/plain": [ " customer_id product_id purchase_date page_views time_spent category \\\n", "0 1 101 2023-01-01 25 120 Electronics \n", "1 3 101 2023-01-01 30 150 Electronics \n", "2 3 101 2023-01-03 30 150 Electronics \n", "3 4 101 2023-01-02 15 80 Electronics \n", "4 5 101 2023-01-05 22 110 Electronics \n", "\n", " price ratings \n", "0 500 4.5 \n", "1 500 4.5 \n", "2 500 4.5 \n", "3 500 4.5 \n", "4 500 4.5 " ] }, "execution_count": 250, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final.head()" ] }, { "cell_type": "markdown", "id": "f7a3bd03-0cc0-4436-9c38-83f773955fa8", "metadata": {}, "source": [ "- the final data that i will used to build the model" ] }, { "cell_type": "code", "execution_count": 251, "id": "ead8f76e-0c6b-48d1-a1d4-8516da1d0bb4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1000, 8)" ] }, "execution_count": 251, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final.shape" ] }, { "cell_type": "markdown", "id": "9bd56d0f-8cc3-4019-b538-b53b6b595b6a", "metadata": {}, "source": [ "- total data 1000 with 8 columns" ] }, { "cell_type": "code", "execution_count": 252, "id": "57449465-a0e0-4cff-9bd1-ee0f4de35087", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
customer_idproduct_idpurchase_datepage_viewstime_spentpriceratings
count1000.0000001000.0000010001000.0000001000.0000001000.0000001000.00000
mean49.077000112.732002023-01-02 22:45:07.20000019.996000163.470000469.8280003.03613
min1.000000101.000002023-01-01 00:00:002.00000050.00000030.0000001.06000
25%24.000000106.000002023-01-02 00:00:0011.00000098.000000146.0000001.48000
50%49.000000113.000002023-01-03 00:00:0022.000000158.000000480.0000003.23500
75%74.000000119.000002023-01-04 00:00:0028.000000226.000000774.0000004.20000
max100.000000125.000002023-01-05 00:00:0035.000000298.000000962.0000004.92000
std29.2024637.37296NaN9.90646973.424575296.9600881.36245
\n", "
" ], "text/plain": [ " customer_id product_id purchase_date page_views \\\n", "count 1000.000000 1000.00000 1000 1000.000000 \n", "mean 49.077000 112.73200 2023-01-02 22:45:07.200000 19.996000 \n", "min 1.000000 101.00000 2023-01-01 00:00:00 2.000000 \n", "25% 24.000000 106.00000 2023-01-02 00:00:00 11.000000 \n", "50% 49.000000 113.00000 2023-01-03 00:00:00 22.000000 \n", "75% 74.000000 119.00000 2023-01-04 00:00:00 28.000000 \n", "max 100.000000 125.00000 2023-01-05 00:00:00 35.000000 \n", "std 29.202463 7.37296 NaN 9.906469 \n", "\n", " time_spent price ratings \n", "count 1000.000000 1000.000000 1000.00000 \n", "mean 163.470000 469.828000 3.03613 \n", "min 50.000000 30.000000 1.06000 \n", "25% 98.000000 146.000000 1.48000 \n", "50% 158.000000 480.000000 3.23500 \n", "75% 226.000000 774.000000 4.20000 \n", "max 298.000000 962.000000 4.92000 \n", "std 73.424575 296.960088 1.36245 " ] }, "execution_count": 252, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final.describe()" ] }, { "cell_type": "code", "execution_count": 253, "id": "04bb7bda-847d-41db-8b2b-490d62401368", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "customer_id\n", "3 21\n", "49 17\n", "70 16\n", "38 15\n", "16 15\n", "82 15\n", "84 14\n", "23 14\n", "18 14\n", "63 14\n", "Name: count, dtype: int64" ] }, "execution_count": 253, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final['customer_id'].value_counts().head(10)" ] }, { "cell_type": "code", "execution_count": 254, "id": "071c9a8b-dd76-46f7-9ace-4af99b5bdc51", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "product_id\n", "103 50\n", "105 49\n", "102 48\n", "121 46\n", "101 44\n", "118 43\n", "108 43\n", "117 42\n", "115 42\n", "107 41\n", "Name: count, dtype: int64" ] }, "execution_count": 254, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final['product_id'].value_counts().head(10)" ] }, { "cell_type": "code", "execution_count": 255, "id": "7f278206-cc47-4760-bef2-2f510df2ef4b", "metadata": {}, "outputs": [ { "data": { "image/png": "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UMW4NBP52GOP6U9/+pPmzp1bYv2UKVN08803l0txAAAAqJpcmonMyMjQyJEjS6wfMWKEdu3adcVFAQAAoGpzaSYyMDBQ6enpioiIcFqfnp6uxo0bl0thqD7Wzh4iPz8/d5cBAADKkUshctSoUXrggQf03Xff6cYbb5QkpaWl6amnntLEiRPLtUAAAABUPTbLsizTjSzL0vPPP6958+bp8OHDkqTQ0FA98sgjGj9+vGw2W7kXiqtPXl6e/P39lZuby0wkAABXibJ+f7sUIn8tPz9fkuTr63slu0E1RIgEAODqU9bvb5d/J/ICwiMAAEDN41KI7Ny5c6mXrG02m7y8vNSyZUsNHz5cffr0ueICAQAAUPW49BM/sbGx+u6771SvXj316dNHffr0kY+PjzIzM9WtWzdlZ2crJiZGK1asKO96AQAAUAW4NBN5/PhxTZo0SdOmTXNaP3v2bH3//ff67LPPNGPGDP31r39VXFxcuRQKAACAqsOlB2v8/f21ZcsWtWzZ0mn9vn371LVrV+Xm5urbb79Vt27dHA/eoObhwRoAAK4+Zf3+dulytpeXl9avX19i/fr16+Xl5SVJKi4udvwNAACA6sWly9njxo3TQw89pC1btqhbt26SpM2bN2vx4sV6/PHHJUmffvqprrvuunIrFAAAAFWHy78T+eabb2rBggXavXu3JKl169YaN26c7r33XknSL7/84nhaGzUTl7MBALj6VNqPjQMXQ4gEAODqU6H3RErSyZMnHZevT5w4IUnaunWrfvjhB1d3CQAAgKuES/dE7tixQzExMfL399f+/ft1//33q0GDBlq2bJkOHDigpUuXlnedAAAAqEJcmomcOHGihg8frr179zrd8zhw4ECtXbu23IoDAABA1eRSiNy8ebMefPDBEuuvueYa5eTkXHFRAAAAqNpcCpF2u115eXkl1u/Zs0eBgYFXXBQAAACqNpfuifx//+//6YknntB7770nSbLZbDpw4ICmTJmiwYMHl2uBuPr1/MvbqmX3dncZAAAY2/L0MHeXUGW5NBM5b948FRQUqHHjxvrll1/Uq1cvtWzZUr6+vnryySfLu0YAAABUMS7NRPr7+2vVqlVKS0vT9u3bVVBQoC5duigmJqa86wMAAEAV5FKIXLp0qeLj49WjRw/16NHDsf7MmTN65513NGwYU78AAADVmUuXs++7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7eu0v1deeUUBAQFKTU0t02XxWrVqqUGDBpKkxo0bKyAgwNF27733asmSJbrrrrskSW+88YaaNGmi3r17X3R/c+bM0axZs0yGAAAAXKWYiXSjPn36KD09Xenp6dq0aZP69++vAQMG6Pvvv9f27du1b98++fr6ysfHRz4+PmrQoIFOnTqlzMxMSdKRI0c0atQoRUREyN/fX35+fiooKNCBAweuuLZRo0bps88+0w8//CBJSkpKcjwMdDFTp05Vbm6uYzl48OAV1wEAAKomZiLdqF69emrZsqXj9eLFi+Xv769XX31VBQUF6tq1q958880S2wUGBkqSEhMT9eOPP+qFF15Q06ZNZbfbFRUV5bjc7eFx/v8RLMtybHv27Nky1da5c2d16tRJS5cuVb9+/fTNN9/o448/vuQ2drtddru9TPsHAABXN0JkFWKz2eTh4aFffvlFXbp00bvvvqvGjRvLz8+v1P5paWl66aWXNHDgQEnnH8Q5fvy4o/1C2MzOzlbnzp0lyekhG0ny9PSUJBUVFZXY//3336/nn39eP/zwg2JiYhQWFnbF5wgAAKoHLme70enTp5WTk6OcnBxlZGRo3LhxKigo0G233aaEhAQ1atRIcXFxWrdunbKyspSSkqLx48fr0KFDkqSIiAi9/vrrysjI0JdffqmEhAR5e3s79u/t7a3f/e53mjt3rjIyMpSamqq//OUvTjU0bdpUNptNycnJOnbsmAoKChxt9957rw4dOqRXX331kg/UAACAmocQ6UYrV65USEiIQkJC1L17d23evFnvv/++evfurbp162rt2rVq0qSJ7rjjDrVt21YjR47UqVOnHDOT//znP/XTTz+pS5cuGjp0qMaPH6/GjRs7HeNf//qXzp07p65du2rChAmaPXu2U/s111yjWbNm6bHHHlNQUJDGjh3raPP399fgwYPl4+OjQYMGVfh4AACAq4fN+vUNc8BvREdHq3379po/f77xtnl5efL391encYtUy+59+Q2ACrbl6WHuLgEAqrwL39+5ubkXvaVO4p5IXMRPP/2klJQUpaSk6KWXXnJ3OQAAoIohRKJUnTt31k8//aSnnnpKrVu3dnc5AACgiiFEolS//ucVAQAAfosHawAAAGCMEAkAAABjhEgAAAAYI0QCAADAGCESAAAAxgiRAAAAMEaIBAAAgDFCJAAAAIwRIgEAAGCMEAkAAABjhEgAAAAYI0QCAADAGCESAAAAxgiRAAAAMEaIBAAAgDFCJAAAAIwRIgEAAGCMEAkAAABjhEgAAAAYI0QCAADAGCESAAAAxgiRAAAAMEaIBAAAgDFCJAAAAIwRIgEAAGCMEAkAAABjtd1dAKq/tbOHyM/Pz91lAACAcsRMJAAAAIwRIgEAAGCMEAkAAABjhEgAAAAYI0QCAADAGCESAAAAxgiRAAAAMEaIBAAAgDF+bBwVxrIsSVJeXp6bKwEAAGV14Xv7wvf4xRAiUWF+/PFHSVJYWJibKwEAAKby8/Pl7+9/0XZCJCpMgwYNJEkHDhy45JsQ5+Xl5SksLEwHDx7kn4ksA8ar7BgrM4yXGcbLzNUwXpZlKT8/X6GhoZfsR4hEhfHwOH/Lrb+/f5X9oFRFfn5+jJcBxqvsGCszjJcZxstMVR+vskz+8GANAAAAjBEiAQAAYIwQiQpjt9s1Y8YM2e12d5dyVWC8zDBeZcdYmWG8zDBeZqrTeNmsyz2/DQAAAPwGM5EAAAAwRogEAACAMUIkAAAAjBEiAQAAYIwQiQrx4osvKjw8XF5eXurevbs2bdrk7pKqhJkzZ8pmszktbdq0cbSfOnVKY8aMUcOGDeXj46PBgwfryJEjbqy4cq1du1a33XabQkNDZbPZtHz5cqd2y7I0ffp0hYSEyNvbWzExMdq7d69TnxMnTighIUF+fn4KCAjQyJEjVVBQUIlnUXkuN17Dhw8v8X6LjY116lNTxmvOnDnq1q2bfH191bhxYw0aNEi7d+926lOWz9+BAwd0yy23qG7dumrcuLEeeeQRnTt3rjJPpVKUZbx69+5d4v310EMPOfWpKeO1cOFCRUZGOn5APCoqSp988omjvbq+twiRKHfvvvuuJk6cqBkzZmjr1q3q1KmT+vfvr6NHj7q7tCqhffv2ys7OdixffPGFo+1Pf/qT/vOf/+j9999XamqqDh8+rDvuuMON1VauwsJCderUSS+++GKp7X//+981f/58LVq0SF9++aXq1aun/v3769SpU44+CQkJ+uabb7Rq1SolJydr7dq1euCBByrrFCrV5cZLkmJjY53eb2+//bZTe00Zr9TUVI0ZM0YbN27UqlWrdPbsWfXr10+FhYWOPpf7/BUVFemWW27RmTNntH79er322mtKSkrS9OnT3XFKFaos4yVJo0aNcnp//f3vf3e01aTxuvbaazV37lxt2bJFX331lfr27au4uDh98803kqrxe8sCytkNN9xgjRkzxvG6qKjICg0NtebMmePGqqqGGTNmWJ06dSq17eTJk1adOnWs999/37EuIyPDkmRt2LChkiqsOiRZH374oeN1cXGxFRwcbD399NOOdSdPnrTsdrv19ttvW5ZlWbt27bIkWZs3b3b0+eSTTyybzWb98MMPlVa7O/x2vCzLshITE624uLiLblOTx+vo0aOWJCs1NdWyrLJ9/v773/9aHh4eVk5OjqPPwoULLT8/P+v06dOVewKV7LfjZVmW1atXL+uPf/zjRbepyeNlWZZVv359a/HixdX6vcVMJMrVmTNntGXLFsXExDjWeXh4KCYmRhs2bHBjZVXH3r17FRoaqubNmyshIUEHDhyQJG3ZskVnz551Grs2bdqoSZMmjJ2krKws5eTkOI2Pv7+/unfv7hifDRs2KCAgQNdff72jT0xMjDw8PPTll19Wes1VQUpKiho3bqzWrVvr4Ycf1o8//uhoq8njlZubK0lq0KCBpLJ9/jZs2KCOHTsqKCjI0ad///7Ky8tzzDhVV78drwvefPNNNWrUSB06dNDUqVP1888/O9pq6ngVFRXpnXfeUWFhoaKioqr1e6u2uwtA9XL8+HEVFRU5fRAkKSgoSN9++62bqqo6unfvrqSkJLVu3VrZ2dmaNWuWbrrpJn399dfKycmRp6enAgICnLYJCgpSTk6OewquQi6MQWnvrQttOTk5aty4sVN77dq11aBBgxo5hrGxsbrjjjvUrFkzZWZm6vHHH9eAAQO0YcMG1apVq8aOV3FxsSZMmKAePXqoQ4cOklSmz19OTk6p778LbdVVaeMlSffee6+aNm2q0NBQ7dixQ1OmTNHu3bu1bNkySTVvvHbu3KmoqCidOnVKPj4++vDDD9WuXTulp6dX2/cWIRKoRAMGDHD8HRkZqe7du6tp06Z677335O3t7cbKUB3dc889jr87duyoyMhItWjRQikpKYqOjnZjZe41ZswYff311073I+PiLjZev753tmPHjgoJCVF0dLQyMzPVokWLyi7T7Vq3bq309HTl5ubq3//+txITE5WamurusioUl7NRrho1aqRatWqVeOrsyJEjCg4OdlNVVVdAQIBatWqlffv2KTg4WGfOnNHJkyed+jB2510Y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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sns.countplot(df_ph_final['category']);" ] }, { "cell_type": "code", "execution_count": 256, "id": "c34e8603-d749-4a84-8d68-8712d0824a3f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 256, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAGxCAYAAAB4AFyyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8WgzjOAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAxUklEQVR4nO3df1RU9b7/8deo/DKdQUT5kSBkCmpZph2kH6dSjugtlx653eroTdO0DDW1n9xvaroqrHtT81y07BraPZnlWWm/rcQfHRNJSVNKSTsYHmXwYMGo4ICwv3+c5dwziQk0sGfj87HWXovZnz1v3vNZI73a85m9bYZhGAIAALCgNmY3AAAA0FQEGQAAYFkEGQAAYFkEGQAAYFkEGQAAYFkEGQAAYFkEGQAAYFkEGQAAYFntzG6gudXV1enYsWPq2LGjbDab2e0AAIAGMAxDJ0+eVHR0tNq0ufB5l1YfZI4dO6aYmBiz2wAAAE1w5MgRdevW7YLjrT7IdOzYUdI/JsJut5vcDQAAaAiXy6WYmBjPf8cvpNUHmXMfJ9ntdoIMAAAWc7FlISz2BQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAltXO7AYA+I/i4mKVlZX5vG54eLhiY2N9XhcACDIAJP0jxCQm9lZVVaXPa4eEtNeBA/sJMwB8jiADQJJUVlamqqpKJU2YK3tUnM/qukoOK++1eSorKyPIAPA5ggwAL/aoOIXFJpjdBgA0CIt9AQCAZRFkAACAZRFkAACAZRFkAACAZbHYF5bA9U0AAPUxNcjU1tbq6aef1p/+9Cc5nU5FR0dr/Pjxeuqpp2Sz2SRJhmFo7ty5evXVV1VeXq4bb7xRy5YtU8+ePc1sHS2I65sAAC7E1CDz/PPPa9myZVq1apX69u2rXbt26b777pPD4dD06dMlSS+88IKWLFmiVatWKT4+XrNnz1Zqaqq+/fZbBQcHm9k+WgjXNwEAXIipQWb79u0aOXKkbr/9dklSXFyc3nzzTX355ZeS/nE2ZvHixXrqqac0cuRISdLrr7+uiIgIrV+/XnfffbdpvaPlcX0TAMDPmbrY94YbblBOTo6+++47SdLXX3+tbdu2afjw4ZKkoqIiOZ1OpaSkeJ7jcDiUlJSk3Nzcemu63W65XC6vDQAAtE6mnpF58skn5XK5lJiYqLZt26q2tlbPPvusxowZI0lyOp2SpIiICK/nRUREeMZ+LjMzU/PmzWvexgEAgF8w9YzM22+/rTfeeEOrV6/WV199pVWrVum//uu/tGrVqibXzMjIUEVFhWc7cuSIDzsGAAD+xNQzMo899piefPJJz1qXq6++Wj/88IMyMzM1btw4RUZGSpJKS0sVFRXleV5paamuvfbaemsGBQUpKCio2XsHAADmM/WMTGVlpdq08W6hbdu2qqurkyTFx8crMjJSOTk5nnGXy6W8vDwlJye3aK8AAMD/mHpGZsSIEXr22WcVGxurvn37avfu3Vq4cKEmTJggSbLZbJoxY4aeeeYZ9ezZ0/P16+joaI0aNcrM1gEAgB8wNcj88Y9/1OzZs/XQQw/p+PHjio6O1gMPPKA5c+Z4jnn88cd1+vRpTZ48WeXl5brpppu0YcMGriEDAADMDTIdO3bU4sWLtXjx4gseY7PZNH/+fM2fP7/lGgMAAJbATSMBAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBlmRpk4uLiZLPZztvS09MlSWfOnFF6ero6d+6sDh06KC0tTaWlpWa2DAAA/IipQWbnzp0qKSnxbJ999pkk6c4775QkzZw5U++//77Wrl2rrVu36tixYxo9erSZLQMAAD/Szsxf3qVLF6/HCxYsUI8ePXTLLbeooqJCK1as0OrVqzV48GBJUnZ2tnr37q0dO3Zo0KBBZrQMAAD8iN+skamurtaf/vQnTZgwQTabTfn5+aqpqVFKSornmMTERMXGxio3N9fETgEAgL8w9YzMP1u/fr3Ky8s1fvx4SZLT6VRgYKBCQ0O9jouIiJDT6bxgHbfbLbfb7Xnscrmao10AAOAH/OaMzIoVKzR8+HBFR0f/qjqZmZlyOByeLSYmxkcdAgAAf+MXQeaHH37Qxo0bdf/993v2RUZGqrq6WuXl5V7HlpaWKjIy8oK1MjIyVFFR4dmOHDnSXG0DAACT+UWQyc7OVteuXXX77bd79g0YMEABAQHKycnx7CssLFRxcbGSk5MvWCsoKEh2u91rAwAArZPpa2Tq6uqUnZ2tcePGqV27/2vH4XBo4sSJmjVrlsLCwmS32zVt2jQlJydfEt9YKi4uVllZWbPUDg8PV2xsrM/rNlfP+/fv93lNAEDrYHqQ2bhxo4qLizVhwoTzxhYtWqQ2bdooLS1NbrdbqampWrp0qQldtqzi4mIlJvZWVVVls9QPCWmvAwf2+zTMNHfPklTjrm622gAAazI9yAwdOlSGYdQ7FhwcrKysLGVlZbVwV+YqKytTVVWlkibMlT0qzqe1XSWHlffaPJWVlfk0yDRnzyX7clXw3nKdPXvWp3UBANZnepDBhdmj4hQWm2B2G43SHD27Sg77tB4AoPXwi8W+AAAATUGQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAlkWQAQAAltXO7AYAALCa4uJilZWV+bxueHi4YmNjfV63NSPIAADQCMXFxUpM7K2qqkqf1w4Jaa8DB/YTZhqBIAMAQCOUlZWpqqpSSRPmyh4V57O6rpLDynttnsrKyggyjUCQAQCgCexRcQqLTTC7jUsei30BAIBlEWQAAIBlEWQAAIBlEWQAAIBlEWQAAIBl8a2lS9T+/fv9uh4AAA1BkLnEVFWckGTT2LFjm6V+jbu6WeoCAFAfgswlpqbypCRD1/7hCXWJT/RZ3ZJ9uSp4b7nOnj3rs5oAAFwMQeYS1aFrrE8v5OQqOeyzWgAANBRBBgAAP9Jcaw5b6w0pTQ8yR48e1RNPPKGPP/5YlZWVuvLKK5Wdna2BAwdKkgzD0Ny5c/Xqq6+qvLxcN954o5YtW6aePXua3DkAAL7T3GsYW+sNKU0NMj/99JNuvPFG3Xbbbfr444/VpUsXHTx4UJ06dfIc88ILL2jJkiVatWqV4uPjNXv2bKWmpurbb79VcHCwid0DAOA7zbWGUWrdN6Q0Ncg8//zziomJUXZ2tmdffHy852fDMLR48WI99dRTGjlypCTp9ddfV0REhNavX6+77767xXsGAKA5+XoNY2tn6gXx3nvvPQ0cOFB33nmnunbtqv79++vVV1/1jBcVFcnpdColJcWzz+FwKCkpSbm5ufXWdLvdcrlcXhsAAGidTA0yf/3rXz3rXT755BNNmTJF06dP16pVqyRJTqdTkhQREeH1vIiICM/Yz2VmZsrhcHi2mJiY5n0RAADANKYGmbq6Ol133XV67rnn1L9/f02ePFmTJk3Syy+/3OSaGRkZqqio8GxHjhzxYccAAMCfmBpkoqKi1KdPH699vXv3VnFxsSQpMjJSklRaWup1TGlpqWfs54KCgmS32702AADQOpm62PfGG29UYWGh177vvvtO3bt3l/SPhb+RkZHKycnRtddeK0lyuVzKy8vTlClTWrrd8xQXF6usrMzndblvEQAADWNqkJk5c6ZuuOEGPffcc/q3f/s3ffnll1q+fLmWL18uSbLZbJoxY4aeeeYZ9ezZ0/P16+joaI0aNcrM1lVcXKzExN6qqqpstt/BfYsAAPhlpgaZ66+/XuvWrVNGRobmz5+v+Ph4LV68WGPGjPEc8/jjj+v06dOaPHmyysvLddNNN2nDhg2mX0OmrKxMVVWVSpowV/aoOJ/W5r5FAAA0jOlX9r3jjjt0xx13XHDcZrNp/vz5mj9/fgt21XD2qDiff9+f+xYBANAwpi72BQAA+DVMPyMDAL9Gcy26b6032ANaG4IMAMtqzkX3rfUGe0BrQ5ABYFnNtei+Nd9gD2htCDIALK85Ft0DsAYW+wIAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMvi7tcA0IoUFxerrKzM53XDw8MVGxvr87rAr0WQAYBWori4WImJvVVVVenz2iEh7XXgwH7CDPwOQQYAWomysjJVVVUqacJc2aPifFbXVXJYea/NU1lZGUEGfocgAwCtjD0qTmGxCWa3AbQIFvsCAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLMjXIPP3007LZbF5bYmKiZ/zMmTNKT09X586d1aFDB6Wlpam0tNTEjgEAgD8x/YxM3759VVJS4tm2bdvmGZs5c6bef/99rV27Vlu3btWxY8c0evRoE7sFAAD+xPR7LbVr106RkZHn7a+oqNCKFSu0evVqDR48WJKUnZ2t3r17a8eOHRo0aFBLtwoAAPyM6WdkDh48qOjoaF1xxRUaM2aMiouLJUn5+fmqqalRSkqK59jExETFxsYqNzfXrHYBAIAfMfWMTFJSklauXKmEhASVlJRo3rx5uvnmm1VQUCCn06nAwECFhoZ6PSciIkJOp/OCNd1ut9xut+exy+VqrvYBAIDJTA0yw4cP9/zcr18/JSUlqXv37nr77bcVEhLSpJqZmZmaN2+er1oEAAB+zPSPlv5ZaGioevXqpUOHDikyMlLV1dUqLy/3Oqa0tLTeNTXnZGRkqKKiwrMdOXKkmbsGAABm8asgc+rUKX3//feKiorSgAEDFBAQoJycHM94YWGhiouLlZycfMEaQUFBstvtXhsAAGidTP1o6dFHH9WIESPUvXt3HTt2THPnzlXbtm11zz33yOFwaOLEiZo1a5bCwsJkt9s1bdo0JScn840lAAAgyeQg87e//U333HOPTpw4oS5duuimm27Sjh071KVLF0nSokWL1KZNG6Wlpcntdis1NVVLly41s2UAAOBHTA0ya9as+cXx4OBgZWVlKSsrq4U6AgAAVuJXa2QAAAAaw/Qr+wIALm3FxcUqKyvzed3w8HDFxsb6vC78S5OCzBVXXKGdO3eqc+fOXvvLy8t13XXX6a9//atPmgMAtG7FxcVKTOytqqpKn9cOCWmvAwf2E2ZauSYFmcOHD6u2tva8/W63W0ePHv3VTQEALg1lZWWqqqpU0oS5skfF+ayuq+Sw8l6bp7KyMoJMK9eoIPPee+95fv7kk0/kcDg8j2tra5WTk6O4uDifNQcAuDTYo+IUFptgdhuwoEYFmVGjRkmSbDabxo0b5zUWEBCguLg4vfjiiz5rDmgJ+/fvb5a6fD6PC2muNSHN9V4G/FmjgkxdXZ0kKT4+Xjt37lR4eHizNAW0hKqKE5JsGjt2bLPU5/N51Kc514ScU+OubrbagL9p0hqZoqIiX/cBtLiaypOSDF37hyfUJT7Rp7X5fB4X0lxrQiSpZF+uCt5brrNnz/q0LuDPmvz165ycHOXk5Oj48eOeMzXnvPbaa7+6MaCldOgay2fzaHHNsSbEVXLYp/UAK2hSkJk3b57mz5+vgQMHKioqSjabzdd9AQAAXFSTgszLL7+slStX6t///d993Q8AAECDNekWBdXV1brhhht83QsAAECjNCnI3H///Vq9erWvewEAAGiUJn20dObMGS1fvlwbN25Uv379FBAQ4DW+cOFCnzQHAADwS5oUZPbu3atrr71WklRQUOA1xsJfAADQUpoUZDZv3uzrPgAAABqtSWtkAAAA/EGTzsjcdtttv/gR0qZNm5rcEAAAQEM1KcicWx9zTk1Njfbs2aOCgoLzbiYJAADQXJoUZBYtWlTv/qefflqnTp36VQ0BAAA0lE/XyIwdO5b7LAEAgBbj0yCTm5ur4OBgX5YEAAC4oCZ9tDR69Givx4ZhqKSkRLt27dLs2bN90hgAAMDFNCnIOBwOr8dt2rRRQkKC5s+fr6FDh/qkMQAAgItpUpDJzs72dR8AAACN1qQgc05+fr72798vSerbt6/69+/vk6YAAAAaoklB5vjx47r77ru1ZcsWhYaGSpLKy8t12223ac2aNerSpYsvewQAAKhXk761NG3aNJ08eVLffPONfvzxR/34448qKCiQy+XS9OnTfd0jAABAvZp0RmbDhg3auHGjevfu7dnXp08fZWVlsdgXAAC0mCadkamrq1NAQMB5+wMCAlRXV/ermwIAAGiIJgWZwYMH6+GHH9axY8c8+44ePaqZM2dqyJAhPmsOAADglzQpyPz3f/+3XC6X4uLi1KNHD/Xo0UPx8fFyuVz64x//2KRGFixYIJvNphkzZnj2nTlzRunp6ercubM6dOigtLQ0lZaWNqk+AABofZq0RiYmJkZfffWVNm7cqAMHDkiSevfurZSUlCY1sXPnTr3yyivq16+f1/6ZM2fqww8/1Nq1a+VwODR16lSNHj1aX3zxRZN+DwAAaF0adUZm06ZN6tOnj1wul2w2m373u99p2rRpmjZtmq6//nr17dtXf/nLXxrVwKlTpzRmzBi9+uqr6tSpk2d/RUWFVqxYoYULF2rw4MEaMGCAsrOztX37du3YsaNRvwMAALROjQoyixcv1qRJk2S3288bczgceuCBB7Rw4cJGNZCenq7bb7/9vLM5+fn5qqmp8dqfmJio2NhY5ebmNup3AACA1qlRQebrr7/WsGHDLjg+dOhQ5efnN7jemjVr9NVXXykzM/O8MafTqcDAQM8F986JiIiQ0+m8YE232y2Xy+W1AQCA1qlRQaa0tLTer12f065dO/39739vUK0jR47o4Ycf1htvvKHg4ODGtPGLMjMz5XA4PFtMTIzPagMAAP/SqCBz+eWXq6Cg4ILje/fuVVRUVINq5efn6/jx47ruuuvUrl07tWvXTlu3btWSJUvUrl07RUREqLq6WuXl5V7PKy0tVWRk5AXrZmRkqKKiwrMdOXKkQf0AAADraVSQ+Zd/+RfNnj1bZ86cOW+sqqpKc+fO1R133NGgWkOGDNG+ffu0Z88ezzZw4ECNGTPG83NAQIBycnI8zyksLFRxcbGSk5MvWDcoKEh2u91rAwAArVOjvn791FNP6Z133lGvXr00depUJSQkSJIOHDigrKws1dbW6v/9v//XoFodO3bUVVdd5bXvsssuU+fOnT37J06cqFmzZiksLEx2u13Tpk1TcnKyBg0a1Ji2AQBAK9WoIBMREaHt27drypQpysjIkGEYkiSbzabU1FRlZWUpIiLCZ80tWrRIbdq0UVpamtxut1JTU7V06VKf1QcAANbW6Avide/eXR999JF++uknHTp0SIZhqGfPnl7XgGmqLVu2eD0ODg5WVlaWsrKyfnVtAADQ+jTpyr6S1KlTJ11//fW+7AUAAKBRmnSvJQAAAH9AkAEAAJZFkAEAAJZFkAEAAJZFkAEAAJbV5G8tAbi4/fv3+7xmeHi4YmNjfV4XuJjmeD83R01cWggyQDOoqjghyaaxY8f6vHZISHsdOLCfMIMW05zv53Nq3NXNVhutG0EGaAY1lSclGbr2D0+oS3yiz+q6Sg4r77V5KisrI8igxTTX+1mSSvblquC95Tp79qxP6+LSQZABmlGHrrEKi00wuw3AJ5rj/ewqOezTerj0sNgXAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYVjuzGwAAAC1j//79Pq8ZHh6u2NhYn9dtKFODzLJly7Rs2TIdPnxYktS3b1/NmTNHw4cPlySdOXNGjzzyiNasWSO3263U1FQtXbpUERERJnYNAIC1VFWckGTT2LFjfV47JKS9DhzYb1qYMTXIdOvWTQsWLFDPnj1lGIZWrVqlkSNHavfu3erbt69mzpypDz/8UGvXrpXD4dDUqVM1evRoffHFF2a2DQCApdRUnpRk6No/PKEu8Yk+q+sqOay81+aprKzs0gwyI0aM8Hr87LPPatmyZdqxY4e6deumFStWaPXq1Ro8eLAkKTs7W71799aOHTs0aNAgM1oGAMCyOnSNVVhsgtlt+JTfLPatra3VmjVrdPr0aSUnJys/P181NTVKSUnxHJOYmKjY2Fjl5uZesI7b7ZbL5fLaAABA62R6kNm3b586dOigoKAgPfjgg1q3bp369Okjp9OpwMBAhYaGeh0fEREhp9N5wXqZmZlyOByeLSYmpplfAQAAMIvpQSYhIUF79uxRXl6epkyZonHjxunbb79tcr2MjAxVVFR4tiNHjviwWwAA4E9M//p1YGCgrrzySknSgAEDtHPnTr300ku66667VF1drfLycq+zMqWlpYqMjLxgvaCgIAUFBTV32wAAwA+Yfkbm5+rq6uR2uzVgwAAFBAQoJyfHM1ZYWKji4mIlJyeb2CEAAPAXpp6RycjI0PDhwxUbG6uTJ09q9erV2rJliz755BM5HA5NnDhRs2bNUlhYmOx2u6ZNm6bk5GS+sQSgRTTHxcOaoyZwKTM1yBw/flz33nuvSkpK5HA41K9fP33yySf63e9+J0latGiR2rRpo7S0NK8L4gFAc2rOi4edU+OubrbawKXE1CCzYsWKXxwPDg5WVlaWsrKyWqgjAGi+i4dJUsm+XBW8t1xnz571aV3gUmX6Yl8A8FfNcfEwV8lhn9YDLnV+t9gXAACgoQgyAADAsggyAADAsggyAADAsggyAADAsggyAADAsggyAADAsggyAADAsrggHoAWwX2LADQHggyAZsV9iwA0J4IMgGbFfYsANCeCDIAWwX2LADQHFvsCAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLIsgAAADLMjXIZGZm6vrrr1fHjh3VtWtXjRo1SoWFhV7HnDlzRunp6ercubM6dOigtLQ0lZaWmtQxAADwJ6YGma1btyo9PV07duzQZ599ppqaGg0dOlSnT5/2HDNz5ky9//77Wrt2rbZu3apjx45p9OjRJnYNAAD8RTszf/mGDRu8Hq9cuVJdu3ZVfn6+fvvb36qiokIrVqzQ6tWrNXjwYElSdna2evfurR07dmjQoEFmtA0AAPyEX62RqaiokCSFhYVJkvLz81VTU6OUlBTPMYmJiYqNjVVubq4pPQIAAP9h6hmZf1ZXV6cZM2boxhtv1FVXXSVJcjqdCgwMVGhoqNexERERcjqd9dZxu91yu92exy6Xq9l6BgAA5vKbMzLp6ekqKCjQmjVrflWdzMxMORwOzxYTE+OjDgEAgL/xiyAzdepUffDBB9q8ebO6devm2R8ZGanq6mqVl5d7HV9aWqrIyMh6a2VkZKiiosKzHTlypDlbBwAAJjI1yBiGoalTp2rdunXatGmT4uPjvcYHDBiggIAA5eTkePYVFhaquLhYycnJ9dYMCgqS3W732gAAQOtk6hqZ9PR0rV69Wu+++646duzoWfficDgUEhIih8OhiRMnatasWQoLC5Pdbte0adOUnJzMN5ZwSdu/f78lagJm499K62dqkFm2bJkk6dZbb/Xan52drfHjx0uSFi1apDZt2igtLU1ut1upqalaunRpC3cK+IeqihOSbBo7dmyz/Y4ad3Wz1QZaCv9WLh2mBhnDMC56THBwsLKyspSVldUCHQH+rabypCRD1/7hCXWJT/Rp7ZJ9uSp4b7nOnj3r07qAGfi3cunwm69fA2i4Dl1jFRab4NOarpLDPq0H+AP+rbR+fvGtJQAAgKYgyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsiyAAAAMsyNch8/vnnGjFihKKjo2Wz2bR+/XqvccMwNGfOHEVFRSkkJEQpKSk6ePCgOc0CAAC/Y2qQOX36tK655hplZWXVO/7CCy9oyZIlevnll5WXl6fLLrtMqampOnPmTAt3CgAA/FE7M3/58OHDNXz48HrHDMPQ4sWL9dRTT2nkyJGSpNdff10RERFav3697r777pZsFQAA+CG/XSNTVFQkp9OplJQUzz6Hw6GkpCTl5uZe8Hlut1sul8trAwAArZPfBhmn0ylJioiI8NofERHhGatPZmamHA6HZ4uJiWnWPgEAgHn8Nsg0VUZGhioqKjzbkSNHzG4JAAA0E78NMpGRkZKk0tJSr/2lpaWesfoEBQXJbrd7bQAAoHXy2yATHx+vyMhI5eTkePa5XC7l5eUpOTnZxM4AAIC/MPVbS6dOndKhQ4c8j4uKirRnzx6FhYUpNjZWM2bM0DPPPKOePXsqPj5es2fPVnR0tEaNGmVe0wAAwG+YGmR27dql2267zfN41qxZkqRx48Zp5cqVevzxx3X69GlNnjxZ5eXluummm7RhwwYFBweb1TIAAPAjpgaZW2+9VYZhXHDcZrNp/vz5mj9/fgt2BQAArMJv18gAAABcDEEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYFkEGAABYliWCTFZWluLi4hQcHKykpCR9+eWXZrcEAAD8gN8HmbfeekuzZs3S3Llz9dVXX+maa65Ramqqjh8/bnZrAADAZH4fZBYuXKhJkybpvvvuU58+ffTyyy+rffv2eu2118xuDQAAmMyvg0x1dbXy8/OVkpLi2demTRulpKQoNzfXxM4AAIA/aGd2A7+krKxMtbW1ioiI8NofERGhAwcO1Psct9stt9vteVxRUSFJcrlcPu3t1KlTkqQffyjUWXeVT2u7Sn6QJFUcPaiAdjZL1KbnlqlNzy1T24o9N2dtem6Z2pbs2Vks6R//TfT1f2fP1TMM45cPNPzY0aNHDUnG9u3bvfY/9thjxm9+85t6nzN37lxDEhsbGxsbG1sr2I4cOfKLWcGvz8iEh4erbdu2Ki0t9dpfWlqqyMjIep+TkZGhWbNmeR7X1dXpxx9/VOfOnWWz+TCFulyKiYnRkSNHZLfbfVYX52OuWw5z3XKY65bDXLccX861YRg6efKkoqOjf/E4vw4ygYGBGjBggHJycjRq1ChJ/wgmOTk5mjp1ar3PCQoKUlBQkNe+0NDQZuvRbrfzD6OFMNcth7luOcx1y2GuW46v5trhcFz0GL8OMpI0a9YsjRs3TgMHDtRvfvMbLV68WKdPn9Z9991ndmsAAMBkfh9k7rrrLv3973/XnDlz5HQ6de2112rDhg3nLQAGAACXHr8PMpI0derUC36UZJagoCDNnTv3vI+x4HvMdcthrlsOc91ymOuWY8Zc2wzjYt9rAgAA8E9+fUE8AACAX0KQAQAAlkWQAQAAlkWQuYinn35aNpvNa0tMTPSMnzlzRunp6ercubM6dOigtLS08y7gh/p9/vnnGjFihKKjo2Wz2bR+/XqvccMwNGfOHEVFRSkkJEQpKSk6ePCg1zE//vijxowZI7vdrtDQUE2cONFz+wj8n4vN9fjx4897nw8bNszrGOb64jIzM3X99derY8eO6tq1q0aNGqXCwkKvYxryN6O4uFi333672rdvr65du+qxxx7T2bNnW/Kl+L2GzPWtt9563vv6wQcf9DqGub64ZcuWqV+/fp5rwyQnJ+vjjz/2jJv9nibINEDfvn1VUlLi2bZt2+YZmzlzpt5//32tXbtWW7du1bFjxzR69GgTu7WO06dP65prrlFWVla94y+88IKWLFmil19+WXl5ebrsssuUmpqqM2fOeI4ZM2aMvvnmG3322Wf64IMP9Pnnn2vy5Mkt9RIs42JzLUnDhg3zep+/+eabXuPM9cVt3bpV6enp2rFjhz777DPV1NRo6NChOn36tOeYi/3NqK2t1e23367q6mpt375dq1at0sqVKzVnzhwzXpLfashcS9KkSZO83tcvvPCCZ4y5bphu3bppwYIFys/P165duzR48GCNHDlS33zzjSQ/eE/75KZIrdjcuXONa665pt6x8vJyIyAgwFi7dq1n3/79+w1JRm5ubgt12DpIMtatW+d5XFdXZ0RGRhr/+Z//6dlXXl5uBAUFGW+++aZhGIbx7bffGpKMnTt3eo75+OOPDZvNZhw9erTFerean8+1YRjGuHHjjJEjR17wOcx10xw/ftyQZGzdutUwjIb9zfjoo4+MNm3aGE6n03PMsmXLDLvdbrjd7pZ9ARby87k2DMO45ZZbjIcffviCz2Gum65Tp07G//zP//jFe5ozMg1w8OBBRUdH64orrtCYMWNUXPyPu33m5+erpqZGKSkpnmMTExMVGxur3Nxcs9ptFYqKiuR0Or3m1uFwKCkpyTO3ubm5Cg0N1cCBAz3HpKSkqE2bNsrLy2vxnq1uy5Yt6tq1qxISEjRlyhSdOHHCM8ZcN01FRYUkKSwsTFLD/mbk5ubq6quv9rroZ2pqqlwul+f/gHG+n8/1OW+88YbCw8N11VVXKSMjQ5WVlZ4x5rrxamtrtWbNGp0+fVrJycl+8Z62xAXxzJSUlKSVK1cqISFBJSUlmjdvnm6++WYVFBTI6XQqMDDwvHs5RUREyOl0mtNwK3Fu/n5+Bed/nlun06muXbt6jbdr105hYWHMfyMNGzZMo0ePVnx8vL7//nv9x3/8h4YPH67c3Fy1bduWuW6Curo6zZgxQzfeeKOuuuoqSWrQ3wyn01nv+/7cGM5X31xL0h/+8Ad1795d0dHR2rt3r5544gkVFhbqnXfekcRcN8a+ffuUnJysM2fOqEOHDlq3bp369OmjPXv2mP6eJshcxPDhwz0/9+vXT0lJSerevbvefvtthYSEmNgZ4Dt333235+err75a/fr1U48ePbRlyxYNGTLExM6sKz09XQUFBV5r6tA8LjTX/7yG6+qrr1ZUVJSGDBmi77//Xj169GjpNi0tISFBe/bsUUVFhf785z9r3Lhx2rp1q9ltSWKxb6OFhoaqV69eOnTokCIjI1VdXa3y8nKvY0pLSxUZGWlOg63Eufn7+cr3f57byMhIHT9+3Gv87Nmz+vHHH5n/X+mKK65QeHi4Dh06JIm5bqypU6fqgw8+0ObNm9WtWzfP/ob8zYiMjKz3fX9uDN4uNNf1SUpKkiSv9zVz3TCBgYG68sorNWDAAGVmZuqaa67RSy+95BfvaYJMI506dUrff/+9oqKiNGDAAAUEBCgnJ8czXlhYqOLiYiUnJ5vYpfXFx8crMjLSa25dLpfy8vI8c5ucnKzy8nLl5+d7jtm0aZPq6uo8f7DQNH/729904sQJRUVFSWKuG8owDE2dOlXr1q3Tpk2bFB8f7zXekL8ZycnJ2rdvn1dw/Oyzz2S329WnT5+WeSEWcLG5rs+ePXskyet9zVw3TV1dndxut3+8p3/1cuFW7pFHHjG2bNliFBUVGV988YWRkpJihIeHG8ePHzcMwzAefPBBIzY21ti0aZOxa9cuIzk52UhOTja5a2s4efKksXv3bmP37t2GJGPhwoXG7t27jR9++MEwDMNYsGCBERoaarz77rvG3r17jZEjRxrx8fFGVVWVp8awYcOM/v37G3l5eca2bduMnj17Gvfcc49ZL8lv/dJcnzx50nj00UeN3Nxco6ioyNi4caNx3XXXGT179jTOnDnjqcFcX9yUKVMMh8NhbNmyxSgpKfFslZWVnmMu9jfj7NmzxlVXXWUMHTrU2LNnj7FhwwajS5cuRkZGhhkvyW9dbK4PHTpkzJ8/39i1a5dRVFRkvPvuu8YVV1xh/Pa3v/XUYK4b5sknnzS2bt1qFBUVGXv37jWefPJJw2azGZ9++qlhGOa/pwkyF3HXXXcZUVFRRmBgoHH55Zcbd911l3Ho0CHPeFVVlfHQQw8ZnTp1Mtq3b2/8/ve/N0pKSkzs2Do2b95sSDpvGzdunGEY//gK9uzZs42IiAgjKCjIGDJkiFFYWOhV48SJE8Y999xjdOjQwbDb7cZ9991nnDx50oRX499+aa4rKyuNoUOHGl26dDECAgKM7t27G5MmTfL6qqRhMNcNUd8cSzKys7M9xzTkb8bhw4eN4cOHGyEhIUZ4eLjxyCOPGDU1NS38avzbxea6uLjY+O1vf2uEhYUZQUFBxpVXXmk89thjRkVFhVcd5vriJkyYYHTv3t0IDAw0unTpYgwZMsQTYgzD/Pc0d78GAACWxRoZAABgWQQZAABgWQQZAABgWQQZAABgWQQZAABgWQQZAABgWQQZAABgWQQZAABgWQQZAE22ZcsW2Wy2824YBwAthSADoMFuvfVWzZgxw/P4hhtuUElJiRwOh3lN+YHDhw/LZrN5bkoIoOW0M7sBANYVGBioyMhIs9sAcAnjjAyABhk/fry2bt2ql156STabTTabTStXrvT6aGnlypUKDQ3VBx98oISEBLVv317/+q//qsrKSq1atUpxcXHq1KmTpk+frtraWk9tt9utRx99VJdffrkuu+wyJSUlacuWLQ3q64cfftCIESPUqVMnXXbZZerbt68++ugjSf/30deHH36ofv36KTg4WIMGDVJBQYFXjW3btunmm29WSEiIYmJiNH36dJ0+fdozHhcXp+eee04TJkxQx44dFRsbq+XLl3vG4+PjJUn9+/eXzWbTrbfe2oQZBtAUBBkADfLSSy8pOTlZkyZNUklJiUpKShQTE3PecZWVlVqyZInWrFmjDRs2aMuWLfr973+vjz76SB999JH+93//V6+88or+/Oc/e54zdepU5ebmas2aNdq7d6/uvPNODRs2TAcPHrxoX+np6XK73fr888+1b98+Pf/88+rQoYPXMY899phefPFF7dy5U126dNGIESNUU1MjSfr+++81bNgwpaWlae/evXrrrbe0bds2TZ061avGiy++qIEDB2r37t166KGHNGXKFBUWFkqSvvzyS0nSxo0bVVJSonfeeadxkwug6XxyD20Al4RbbrnFePjhhz2PN2/ebEgyfvrpJ8MwDCM7O9uQZBw6dMhzzAMPPGC0b9/eOHnypGdfamqq8cADDxiGYRg//PCD0bZtW+Po0aNev2vIkCFGRkbGRXu6+uqrjaeffrresXP9rVmzxrPvxIkTRkhIiPHWW28ZhmEYEydONCZPnuz1vL/85S9GmzZtjKqqKsMwDKN79+7G2LFjPeN1dXVG165djWXLlhmGYRhFRUWGJGP37t0X7ReAb7FGBoBPtW/fXj169PA8joiIUFxcnNdZkoiICB0/flyStG/fPtXW1qpXr15eddxutzp37nzR3zd9+nRNmTJFn376qVJSUpSWlqZ+/fp5HZOcnOz5OSwsTAkJCdq/f78k6euvv9bevXv1xhtveI4xDEN1dXUqKipS7969Jcmrps1mU2RkpOc1ADAPQQaATwUEBHg9ttls9e6rq6uTJJ06dUpt27ZVfn6+2rZt63Xczz8iqs/999+v1NRUffjhh/r000+VmZmpF198UdOmTWtQv6dOndIDDzyg6dOnnzcWGxv7i6/r3GsAYB6CDIAGCwwM9Fqk6wv9+/dXbW2tjh8/rptvvrlJNWJiYvTggw/qwQcfVEZGhl599VWvILNjxw5PKPnpp5/03Xffec60XHfddfr222915ZVXNvk1BAYGSpLP5wbAxbHYF0CDxcXFKS8vT4cPH1ZZWZlPzkj06tVLY8aM0b333qt33nlHRUVF+vLLL5WZmakPP/zwos+fMWOGPvnkExUVFemrr77S5s2bPSHlnPnz5ysnJ0cFBQUaP368wsPDNWrUKEnSE088oe3bt2vq1Knas2ePDh48qHffffe8xb6/pGvXrgoJCdGGDRtUWlqqioqKRs0BgKYjyABosEcffVRt27ZVnz591KVLFxUXF/ukbnZ2tu6991498sgjSkhI0KhRo7Rz506vj3YupLa2Vunp6erdu7eGDRumXr16aenSpV7HLFiwQA8//LAGDBggp9Op999/33MWpV+/ftq6dau+++473Xzzzerfv7/mzJmj6OjoBvffrl07LVmyRK+88oqio6M1cuTIxk0AgCazGYZhmN0EADSHLVu26LbbbtNPP/2k0NBQs9sB0Aw4IwMAACyLIAPArw0fPlwdOnSod3vuuefMbg+AyfhoCYBfO3r0qKqqquodCwsLU1hYWAt3BMCfEGQAAIBl8dESAACwLIIMAACwLIIMAACwLIIMAACwLIIMAACwLIIMAACwLIIMAACwLIIMAACwrP8PWuPJAkRvTjcAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sns.histplot(df_ph_final['time_spent'], bins=20)" ] }, { "cell_type": "code", "execution_count": 257, "id": "82aa5fbf-4ca3-44e7-8e95-672a361652eb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 257, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAGxCAYAAACEFXd4AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8WgzjOAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAsLUlEQVR4nO3df1RVdb7/8RcmIiaghPLDOEJpgJk6pRFZaYmhTS0dnXs1dZalo02JP5tyqIwkHcq6RZrprRl/3SVazaRZM9kUJuVIaJiZBaSOznEUcI4FRwWRZH//8Hbu96Sk4jmcw4fnY629Fmfvfd68+azd8tX+8dkBlmVZAgAAMFQrXzcAAADgTYQdAABgNMIOAAAwGmEHAAAYjbADAACMRtgBAABGI+wAAACjEXYAAIDRWvu6AX9QX1+vw4cPKyQkRAEBAb5uBwAAXADLsnTs2DHFxMSoVauGz98QdiQdPnxYsbGxvm4DAAA0wsGDB3XllVc2uJ2wIykkJETSmcEKDQ31cTcAAOBCOJ1OxcbGuv4dbwhhR3JdugoNDSXsAADQzJzvFhRuUAYAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwWmtfNwAAaDp2u10Oh8MrtSMiImSz2bxSG7gUhB0AaCHsdrsSE5NUU1PtlfrBwe1UUlJM4IHfIewAQAvhcDhUU1Ot5AmZCo2O82htZ9kBFS6bK4fDQdiB3yHsAEALExodp3Bbgq/bAJoMNygDAACjEXYAAIDRCDsAAMBohB0AAGA0wg4AADAaYQcAABiNsAMAAIxG2AEAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwWmtf/vKPP/5Yzz33nIqKilRWVqZ169Zp+PDhru2WZSkzM1OvvfaaKisr1b9/fy1ZskTdu3d37fPtt99q6tSpeuedd9SqVSuNHDlSL730ktq3b++DvwgAgObLbrfL4XB4vG5ERIRsNpvH614on4adEydOqHfv3powYYJGjBhx1vYFCxZo4cKFWrlypeLj4zVnzhylpaXp66+/Vtu2bSVJY8eOVVlZmT744APV1dXp/vvv1+TJk5Wbm9vUfw4AAM2W3W5XYmKSamqqPV47OLidSkqKfRZ4fBp2hg4dqqFDh55zm2VZysnJ0RNPPKFhw4ZJklatWqXIyEitX79eo0ePVnFxsTZu3Kjt27erb9++kqRFixbprrvu0vPPP6+YmJgm+1sAAGjOHA6HamqqlTwhU6HRcR6r6yw7oMJlc+VwOFpm2Pkp+/fvV3l5uVJTU13rwsLClJycrIKCAo0ePVoFBQXq0KGDK+hIUmpqqlq1aqXCwkL94he/8EXrAAA0W6HRcQq3Jfi6DY/y27BTXl4uSYqMjHRbHxkZ6dpWXl6uzp07u21v3bq1wsPDXfucS21trWpra12fnU6np9oGAAB+pkU+jZWdna2wsDDXEhsb6+uWAACAl/ht2ImKipIkVVRUuK2vqKhwbYuKitKRI0fctn///ff69ttvXfucS0ZGhqqqqlzLwYMHPdw9AADwF34bduLj4xUVFaW8vDzXOqfTqcLCQqWkpEiSUlJSVFlZqaKiItc+mzZtUn19vZKTkxusHRQUpNDQULcFAACYyaf37Bw/flx79+51fd6/f7927typ8PBw2Ww2zZgxQ/PmzVP37t1dj57HxMS45uJJSkrSkCFDNGnSJC1dulR1dXVKT0/X6NGjeRILAABI8nHY+eyzz3T77be7Ps+aNUuSNH78eK1YsUKPPvqoTpw4ocmTJ6uyslK33HKLNm7c6JpjR5JWr16t9PR0DRo0yDWp4MKFC5v8bwEAAP7Jp2Fn4MCBsiyrwe0BAQHKyspSVlZWg/uEh4czgSAAAGiQ396zAwAA4AmEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwGmEHAAAYjbADAACMRtgBAABGI+wAAACjEXYAAIDRCDsAAMBohB0AAGA0wg4AADAaYQcAABiNsAMAAIxG2AEAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwGmEHAAAYjbADAACMRtgBAABGa+3rBgAA+Cl2u10Oh8MrtSMiImSz2bxSG/6DsAMA8Ft2u12JiUmqqan2Sv3g4HYqKSkm8BiOsAMA8FsOh0M1NdVKnpCp0Og4j9Z2lh1Q4bK5cjgchB3DEXYAAH4vNDpO4bYEX7eBZooblAEAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwml+HndOnT2vOnDmKj49XcHCwrr76aj399NOyLMu1j2VZevLJJxUdHa3g4GClpqZqz549PuwaAAD4E78OO88++6yWLFmil19+WcXFxXr22We1YMECLVq0yLXPggULtHDhQi1dulSFhYW6/PLLlZaWppMnT/qwcwAA4C9a+7qBn7J161YNGzZMP//5zyVJcXFxWrNmjbZt2ybpzFmdnJwcPfHEExo2bJgkadWqVYqMjNT69es1evRon/UOAAD8g1+f2bn55puVl5enb775RpL0xRdfaMuWLRo6dKgkaf/+/SovL1dqaqrrO2FhYUpOTlZBQUGDdWtra+V0Ot0WAABgJr8+s/O73/1OTqdTiYmJuuyyy3T69GnNnz9fY8eOlSSVl5dLkiIjI92+FxkZ6dp2LtnZ2Zo7d673GgcAAH7Dr8/svPHGG1q9erVyc3O1Y8cOrVy5Us8//7xWrlx5SXUzMjJUVVXlWg4ePOihjgEAgL/x6zM7jzzyiH73u9+57r257rrr9M9//lPZ2dkaP368oqKiJEkVFRWKjo52fa+iokJ9+vRpsG5QUJCCgoK82jsAAPAPfn1mp7q6Wq1aubd42WWXqb6+XpIUHx+vqKgo5eXlubY7nU4VFhYqJSWlSXsFAAD+ya/P7Nxzzz2aP3++bDabrr32Wn3++ed64YUXNGHCBElSQECAZsyYoXnz5ql79+6Kj4/XnDlzFBMTo+HDh/u2eQAA4Bf8OuwsWrRIc+bM0UMPPaQjR44oJiZGDzzwgJ588knXPo8++qhOnDihyZMnq7KyUrfccos2btyotm3b+rBzAADgL/w67ISEhCgnJ0c5OTkN7hMQEKCsrCxlZWU1XWMAAKDZ8Ot7dgAAAC4VYQcAABiNsAMAAIxG2AEAAEYj7AAAAKP59dNYAAB4W3FxscdrRkREyGazebwuGoewAwBokWqqjkoK0Lhx4zxeOzi4nUpKigk8foKwAwBokeqqj0my1GfMbHWKT/RYXWfZARUumyuHw0HY8ROEHQBAi9a+s03htgRftwEv4gZlAABgNMIOAAAwGmEHAAAYjbADAACMRtgBAABGI+wAAACjEXYAAIDRCDsAAMBohB0AAGA0wg4AADAaYQcAABiNsAMAAIxG2AEAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgtNa+bgAti91ul8Ph8HjdiIgI2Ww2j9cFADR/hB00GbvdrsTEJNXUVHu8dnBwO5WUFBN4AABnIeygyTgcDtXUVCt5QqZCo+M8VtdZdkCFy+bK4XAQdgAAZyHsoMmFRscp3Jbg6zYAAC0ENygDAACjEXYAAIDRCDsAAMBohB0AAGA0wg4AADAaYQcAABiNsAMAAIxG2AEAAEYj7AAAAKMRdgAAgNEaFXauuuoqHT169Kz1lZWVuuqqqy65KQAAAE9pVNg5cOCATp8+fdb62tpaHTp06JKbAgAA8JSLehHohg0bXD+///77CgsLc30+ffq08vLyFBcX57HmgItRXFzslboRERG8TR0AmrGLCjvDhw+XJAUEBGj8+PFu2wIDAxUXF6f/+q//8lhzwIWoqToqKUDjxo3zSv3g4HYqKSkm8ABAM3VRYae+vl6SFB8fr+3btysiIsIrTQEXo676mCRLfcbMVqf4RI/WdpYdUOGyuXI4HIQdAGimLirs/GD//v2e7qNBhw4d0uzZs/Xee++purpa3bp10/Lly9W3b19JkmVZyszM1GuvvabKykr1799fS5YsUffu3ZusR/iH9p1tCrcl+LoNAICfaVTYkaS8vDzl5eXpyJEjrjM+P1i2bNklNyZJ3333nfr376/bb79d7733njp16qQ9e/aoY8eOrn0WLFighQsXauXKlYqPj9ecOXOUlpamr7/+Wm3btvVIHwAAoPlqVNiZO3eusrKy1LdvX0VHRysgIMDTfUmSnn32WcXGxmr58uWudfHx8a6fLctSTk6OnnjiCQ0bNkyStGrVKkVGRmr9+vUaPXq0V/oCAADNR6PCztKlS7VixQr96le/8nQ/bjZs2KC0tDT9x3/8h/Lz89WlSxc99NBDmjRpkqQzl9PKy8uVmprq+k5YWJiSk5NVUFBA2AEAAI2bZ+fUqVO6+eabPd3LWf7xj3+47r95//339eCDD2ratGlauXKlJKm8vFySFBkZ6fa9yMhI17Zzqa2tldPpdFsAAICZGhV2fv3rXys3N9fTvZylvr5e119/vX7/+9/rZz/7mSZPnqxJkyZp6dKll1Q3OztbYWFhriU2NtZDHQMAAH/TqMtYJ0+e1KuvvqoPP/xQvXr1UmBgoNv2F154wSPNRUdHq0ePHm7rkpKS9Oc//1mSFBUVJUmqqKhQdHS0a5+Kigr16dOnwboZGRmaNWuW67PT6STwAABgqEaFnV27drnCxO7du922efJm5f79+6u0tNRt3TfffKOuXbtKOnOzclRUlPLy8lz9OJ1OFRYW6sEHH2ywblBQkIKCgjzWJwAA8F+NCjsfffSRp/s4p5kzZ+rmm2/W73//e/3nf/6ntm3bpldffVWvvvqqpDPBasaMGZo3b566d+/uevQ8JibGNdszAABo2Ro9z05T6Nevn9atW6eMjAxlZWUpPj5eOTk5Gjt2rGufRx99VCdOnNDkyZNVWVmpW265RRs3bmSOHQAAIKmRYef222//yctVmzZtanRDP3b33Xfr7rvvbnB7QECAsrKylJWV5bHfCQAAzNGosPPjm3/r6uq0c+dO7d69+6wXhAIAAPhSo8LOiy++eM71Tz31lI4fP35JDQEAAHhSo+bZaci4ceM89l4sAAAAT/Bo2CkoKODGYAAA4FcadRlrxIgRbp8ty1JZWZk+++wzzZkzxyONAQAAeEKjwk5YWJjb51atWikhIUFZWVm68847PdIYAACAJzQq7CxfvtzTfQAAAHjFJU0qWFRUpOLiYknStddeq5/97GceaQoAAMBTGhV2jhw5otGjR2vz5s3q0KGDJKmyslK333671q5dq06dOnmyRwAAgEZrVNiZOnWqjh07pq+++kpJSUmSpK+//lrjx4/XtGnTtGbNGo82CZjIbrfL4XB4pXZERIRsNptXagNAc9OosLNx40Z9+OGHrqAjST169NDixYu5QRm4AHa7XYmJSaqpqfZK/eDgdiopKSbwAIAaGXbq6+sVGBh41vrAwEDV19dfclOA6RwOh2pqqpU8IVOh0XEere0sO6DCZXPlcDgIOwCgRoadO+64Q9OnT9eaNWsUExMjSTp06JBmzpypQYMGebRBwGSh0XEKtyX4ug0AMFqjZlB++eWX5XQ6FRcXp6uvvlpXX3214uPj5XQ6tWjRIk/3CAAA0GiNOrMTGxurHTt26MMPP1RJSYkkKSkpSampqR5tDgAA4FJd1JmdTZs2qUePHnI6nQoICNDgwYM1depUTZ06Vf369dO1116rTz75xFu9AgAAXLSLCjs5OTmaNGmSQkNDz9oWFhamBx54QC+88ILHmgMAALhUFxV2vvjiCw0ZMqTB7XfeeaeKioouuSkAAABPuaiwU1FRcc5Hzn/QunVr/fvf/77kpgAAADzlosJOly5dtHv37ga379q1S9HR0ZfcFAAAgKdcVNi56667NGfOHJ08efKsbTU1NcrMzNTdd9/tseYAAAAu1UU9ev7EE0/orbfe0jXXXKP09HQlJJyZDK2kpESLFy/W6dOn9fjjj3ulUQAAgMa4qLATGRmprVu36sEHH1RGRoYsy5IkBQQEKC0tTYsXL1ZkZKRXGgUAAGiMi55UsGvXrvrrX/+q7777Tnv37pVlWerevbs6duzojf4AAAAuSaNmUJakjh07ql+/fp7sBQAAwOMa9W4sAACA5oKwAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgtEbPswPfs9vtcjgcHq8bEREhm83m8boAAPgCYaeZstvtSkxMUk1NtcdrBwe3U0lJMYEHAGAEwk4z5XA4VFNTreQJmQqNjvNYXWfZARUumyuHw0HYAQAYgbDTzIVGxyncluDrNgC/xiVfoGUj7AAwGpd8ARB2ABiNS74ACDsAWgQu+QItF/PsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwGmEHAAAYjbADAACMRtgBAABGI+wAAACjMYMyAPghb7y8tLi42KP1gOaCsAMAfsabLy+VpLraU16pC/grwg4A+Blvvby07MsC7d7wqr7//nuP1QSaA8IOAPgpT7+81Fl2wGO1gOaEG5QBAIDRCDsAAMBozeoy1jPPPKOMjAxNnz5dOTk5kqSTJ0/q4Ycf1tq1a1VbW6u0tDS98sorioyM9G2z/8sbT1RIPFUBAMCFajZhZ/v27frv//5v9erVy239zJkz9Ze//EVvvvmmwsLClJ6erhEjRujvf/+7jzr9P95+okLiqQoAAM6nWYSd48ePa+zYsXrttdc0b9481/qqqir98Y9/VG5uru644w5J0vLly5WUlKRPP/1UN910k69aluS9JyoknqoAAOBCNYuwM2XKFP385z9XamqqW9gpKipSXV2dUlNTXesSExNls9lUUFDQYNipra1VbW2t67PT6fRe8/L8ExUST1UA8E+evsTOJXt4gt+HnbVr12rHjh3avn37WdvKy8vVpk0bdejQwW19ZGSkysvLG6yZnZ2tuXPnerpVAGixaqqOSgrQuHHjvFKfS/a4FH4ddg4ePKjp06frgw8+UNu2bT1WNyMjQ7NmzXJ9djqdio2N9Vh9AGhp6qqPSbLUZ8xsdYpP9FhdLtnDE/w67BQVFenIkSO6/vrrXetOnz6tjz/+WC+//LLef/99nTp1SpWVlW5ndyoqKhQVFdVg3aCgIAUFBXmzdQBokdp3tjERIvyOX4edQYMG6csvv3Rbd//99ysxMVGzZ89WbGysAgMDlZeXp5EjR0qSSktLZbfblZKS4ouWAQCAn/HrsBMSEqKePXu6rbv88st1xRVXuNZPnDhRs2bNUnh4uEJDQzV16lSlpKT4/EksAADgH/w67FyIF198Ua1atdLIkSPdJhUEAACQmmHY2bx5s9vntm3bavHixVq8eLFvGgIAAH6Nd2MBAACjEXYAAIDRCDsAAMBohB0AAGA0wg4AADAaYQcAABiNsAMAAIxG2AEAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjNba1w0AQHNWXFzcLGoCLRlhBwAaoabqqKQAjRs3zmu/o672lNdqAy0JYQcAGqGu+pgkS33GzFan+ESP1i77skC7N7yq77//3qN1gZaKsAMAl6B9Z5vCbQkereksO+DRevANb12OjIiIkM1m80ptUxF2AADwIG9f4gwObqeSkmICz0Ug7AAA4EHevMTpLDugwmVz5XA4CDsXgbADAIAXeOMSJxqHeXYAAIDRCDsAAMBohB0AAGA07tkBLoCnHyFlhlwAl4KZuy8OYQf4Cd5+hJQZcgFcDGbubhzCDvATvPUIKTPkAmgMZu5uHMIOcAE8/QgpM+QCuBTM3H1xuEEZAAAYjbADAACMRtgBAABGI+wAAACjEXYAAIDReBoLwEWx2+1yOBwerxsREcFbnAF4BWEHwAWz2+1KTExSTU21x2sHB7dTSUkxgQeAxxF2AFwwh8OhmppqJU/IVGh0nMfqOssOqHDZXDkcDsIOAI8j7AC4aKHRcR6f0AwAvIWwAxiKFwUCwBmEHcAwvCgQANwRdgDD8KJAAHBH2ME5cQmk+eNFgQBwBmEHbrgEAgAwDWEHbrgEAgAwDWEH58QlEACAKXg3FgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Xj0HIDfYOZuAN5A2AHgc8zcDcCbCDsAfI6ZuwF4k1+HnezsbL311lsqKSlRcHCwbr75Zj377LNKSPi/mX1Pnjyphx9+WGvXrlVtba3S0tL0yiuvKDIy0oedA2gMZu4G4A1+fYNyfn6+pkyZok8//VQffPCB6urqdOedd+rEiROufWbOnKl33nlHb775pvLz83X48GGNGDHCh10DAAB/4tdndjZu3Oj2ecWKFercubOKiop02223qaqqSn/84x+Vm5urO+64Q5K0fPlyJSUl6dNPP9VNN93ki7YBAIAf8eszOz9WVVUlSQoPD5ckFRUVqa6uTqmpqa59EhMTZbPZVFBQ0GCd2tpaOZ1OtwUAAJip2YSd+vp6zZgxQ/3791fPnj0lSeXl5WrTpo06dOjgtm9kZKTKy8sbrJWdna2wsDDXEhsb683WAQCADzWbsDNlyhTt3r1ba9euveRaGRkZqqqqci0HDx70QIcAAMAf+fU9Oz9IT0/Xu+++q48//lhXXnmla31UVJROnTqlyspKt7M7FRUVioqKarBeUFCQgoKCvNkyAADwE359ZseyLKWnp2vdunXatGmT4uPj3bbfcMMNCgwMVF5enmtdaWmp7Ha7UlJSmrpdAADgh/z6zM6UKVOUm5urt99+WyEhIa77cMLCwhQcHKywsDBNnDhRs2bNUnh4uEJDQzV16lSlpKTwJBYAAJDk52FnyZIlkqSBAwe6rV++fLnuu+8+SdKLL76oVq1aaeTIkW6TCgIAAEh+HnYsyzrvPm3bttXixYu1ePHiJugIAAA0N359zw4AAMClIuwAAACjEXYAAIDRCDsAAMBohB0AAGA0wg4AADAaYQcAABiNsAMAAIxG2AEAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwGmEHAAAYjbADAACMRtgBAABGI+wAAACjEXYAAIDRCDsAAMBohB0AAGA0wg4AADAaYQcAABiNsAMAAIxG2AEAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAwGmEHAAAYjbADAACMRtgBAABGI+wAAACjEXYAAIDRCDsAAMBohB0AAGA0Y8LO4sWLFRcXp7Zt2yo5OVnbtm3zdUsAAMAPGBF2Xn/9dc2aNUuZmZnasWOHevfurbS0NB05csTXrQEAAB8zIuy88MILmjRpku6//3716NFDS5cuVbt27bRs2TJftwYAAHys2YedU6dOqaioSKmpqa51rVq1UmpqqgoKCnzYGQAA8Aetfd3ApXI4HDp9+rQiIyPd1kdGRqqkpOSc36mtrVVtba3rc1VVlSTJ6XR6tLfjx49Lkr79Z6m+r63xaG1n2T8lSVWH9iiwdYDf1/VmbXpu/rXpuWlq03PT1G6OPXuztrPcLunMv4me/nf2h3qWZf30jlYzd+jQIUuStXXrVrf1jzzyiHXjjTee8zuZmZmWJBYWFhYWFhYDloMHD/5kVmj2Z3YiIiJ02WWXqaKiwm19RUWFoqKizvmdjIwMzZo1y/W5vr5e3377ra644goFBHg2Kfs7p9Op2NhYHTx4UKGhob5uxy8wJu4YD3eMhzvG42yMiTtvjodlWTp27JhiYmJ+cr9mH3batGmjG264QXl5eRo+fLikM+ElLy9P6enp5/xOUFCQgoKC3NZ16NDBy536t9DQUP6j/BHGxB3j4Y7xcMd4nI0xceet8QgLCzvvPs0+7EjSrFmzNH78ePXt21c33nijcnJydOLECd1///2+bg0AAPiYEWFn1KhR+ve//60nn3xS5eXl6tOnjzZu3HjWTcsAAKDlMSLsSFJ6enqDl63QsKCgIGVmZp51Wa8lY0zcMR7uGA93jMfZGBN3/jAeAZZ1vue1AAAAmq9mP6kgAADATyHsAAAAoxF2AACA0Qg7LdRTTz2lgIAAtyUxMdHXbTWZjz/+WPfcc49iYmIUEBCg9evXu223LEtPPvmkoqOjFRwcrNTUVO3Zs8c3zTaR843Jfffdd9YxM2TIEN8062XZ2dnq16+fQkJC1LlzZw0fPlylpaVu+5w8eVJTpkzRFVdcofbt22vkyJFnTW5qkgsZk4EDB551jPzmN7/xUcfetWTJEvXq1cs1d0xKSoree+891/aWdnycbzx8fWwQdlqwa6+9VmVlZa5ly5Ytvm6pyZw4cUK9e/fW4sWLz7l9wYIFWrhwoZYuXarCwkJdfvnlSktL08mTJ5u406ZzvjGRpCFDhrgdM2vWrGnCDptOfn6+pkyZok8//VQffPCB6urqdOedd+rEiROufWbOnKl33nlHb775pvLz83X48GGNGDHCh11714WMiSRNmjTJ7RhZsGCBjzr2riuvvFLPPPOMioqK9Nlnn+mOO+7QsGHD9NVXX0lqecfH+cZD8vGx4ZEXVKHZyczMtHr37u3rNvyCJGvdunWuz/X19VZUVJT13HPPudZVVlZaQUFB1po1a3zQYdP78ZhYlmWNHz/eGjZsmE/68bUjR45Ykqz8/HzLss4cD4GBgdabb77p2qe4uNiSZBUUFPiqzSb14zGxLMsaMGCANX36dN815WMdO3a0/vCHP3B8/K8fxsOyfH9scGanBduzZ49iYmJ01VVXaezYsbLb7b5uyS/s379f5eXlSk1Nda0LCwtTcnKyCgoKfNiZ723evFmdO3dWQkKCHnzwQR09etTXLTWJqqoqSVJ4eLgkqaioSHV1dW7HSGJiomw2W4s5Rn48Jj9YvXq1IiIi1LNnT2VkZKi6utoX7TWp06dPa+3atTpx4oRSUlJa/PHx4/H4gS+PDWMmFcTFSU5O1ooVK5SQkKCysjLNnTtXt956q3bv3q2QkBBft+dT5eXlknTWDNyRkZGubS3RkCFDNGLECMXHx2vfvn167LHHNHToUBUUFOiyyy7zdXteU19frxkzZqh///7q2bOnpDPHSJs2bc56p15LOUbONSaSNGbMGHXt2lUxMTHatWuXZs+erdLSUr311ls+7NZ7vvzyS6WkpOjkyZNq37691q1bpx49emjnzp0t8vhoaDwk3x8bhJ0WaujQoa6fe/XqpeTkZHXt2lVvvPGGJk6c6MPO4K9Gjx7t+vm6665Tr169dPXVV2vz5s0aNGiQDzvzrilTpmj37t0t6p6282loTCZPnuz6+brrrlN0dLQGDRqkffv26eqrr27qNr0uISFBO3fuVFVVlf70pz9p/Pjxys/P93VbPtPQePTo0cPnxwaXsSDpzFvfr7nmGu3du9fXrfhcVFSUJJ315ERFRYVrG6SrrrpKERERRh8z6enpevfdd/XRRx/pyiuvdK2PiorSqVOnVFlZ6bZ/SzhGGhqTc0lOTpYkY4+RNm3aqFu3brrhhhuUnZ2t3r1766WXXmqxx0dD43EuTX1sEHYgSTp+/Lj27dun6OhoX7fic/Hx8YqKilJeXp5rndPpVGFhodv155buX//6l44ePWrkMWNZltLT07Vu3Tpt2rRJ8fHxbttvuOEGBQYGuh0jpaWlstvtxh4j5xuTc9m5c6ckGXmMnEt9fb1qa2tb5PFxLj+Mx7k09bHBZawW6re//a3uuecede3aVYcPH1ZmZqYuu+wy3Xvvvb5urUkcP37c7f8o9u/fr507dyo8PFw2m00zZszQvHnz1L17d8XHx2vOnDmKiYnR8OHDfde0l/3UmISHh2vu3LkaOXKkoqKitG/fPj366KPq1q2b0tLSfNi1d0yZMkW5ubl6++23FRIS4rrPIiwsTMHBwQoLC9PEiRM1a9YshYeHKzQ0VFOnTlVKSopuuukmH3fvHecbk3379ik3N1d33XWXrrjiCu3atUszZ87Ubbfdpl69evm4e8/LyMjQ0KFDZbPZdOzYMeXm5mrz5s16//33W+Tx8VPj4RfHhs+eA4NPjRo1yoqOjrbatGljdenSxRo1apS1d+9eX7fVZD766CNL0lnL+PHjLcs68/j5nDlzrMjISCsoKMgaNGiQVVpa6tumveynxqS6utq68847rU6dOlmBgYFW165drUmTJlnl5eW+btsrzjUOkqzly5e79qmpqbEeeughq2PHjla7du2sX/ziF1ZZWZnvmvay842J3W63brvtNis8PNwKCgqyunXrZj3yyCNWVVWVbxv3kgkTJlhdu3a12rRpY3Xq1MkaNGiQ9be//c21vaUdHz81Hv5wbPDWcwAAYDTu2QEAAEYj7AAAAKMRdgAAgNEIOwAAwGiEHQAAYDTCDgAAMBphBwAAGI2wAwAAjEbYAQBJ9913n9GvAwFaMmZQBgBJVVVVsixLHTp08HUrADyMsAMAAIzGZSwAl2zgwIFKT09Xenq6wsLCFBERoTlz5uiH/5f6n//5H/Xt21chISGKiorSmDFjdOTIEbcaGzZsUPfu3dW2bVvdfvvtWrlypQICAlRZWenaZ8uWLbr11lsVHBys2NhYTZs2TSdOnDhvf4899piSk5PPWt+7d29lZWVJOvsyVn19vbKzsxUfH6/g4GD17t1bf/rTn1zb+/btq+eff971efjw4QoMDNTx48clSf/6178UEBDgepP8K6+84vr7IiMj9ctf/vK8fQPwDMIOAI9YuXKlWrdurW3btumll17SCy+8oD/84Q+SpLq6Oj399NP64osvtH79eh04cED33Xef67v79+/XL3/5Sw0fPlxffPGFHnjgAT3++ONu9fft26chQ4Zo5MiR2rVrl15//XVt2bJF6enp5+1t7Nix2rZtm/bt2+da99VXX2nXrl0aM2bMOb+TnZ2tVatWaenSpfrqq680c+ZMjRs3Tvn5+ZKkAQMGaPPmzZIky7L0ySefqEOHDtqyZYskKT8/X126dFG3bt302Wefadq0acrKylJpaak2btyo22677YLHFsAlarL3qwMw1oABA6ykpCSrvr7etW727NlWUlLSOfffvn27Jck6duyYa9+ePXu67fP4449bkqzvvvvOsizLmjhxojV58mS3fT755BOrVatWVk1NzXl77N27t5WVleX6nJGRYSUnJ7s+jx8/3ho2bJhlWZZ18uRJq127dtbWrVvdakycONG69957LcuyrA0bNlhhYWHW999/b+3cudOKioqypk+fbs2ePduyLMv69a9/bY0ZM8ayLMv685//bIWGhlpOp/O8fQLwPM7sAPCIm266SQEBAa7PKSkp2rNnj06fPq2ioiLdc889stlsCgkJ0YABAyRJdrtdklRaWqp+/fq51bvxxhvdPn/xxRdasWKF2rdv71rS0tJUX1+v/fv3n7e/sWPHKjc3V9KZMzFr1qzR2LFjz7nv3r17VV1drcGDB7v9vlWrVrnODt166606duyYPv/8c+Xn52vAgAEaOHCg62xPfn6+Bg4cKEkaPHiwunbtqquuukq/+tWvtHr1alVXV5+3ZwCe0drXDQAw28mTJ5WWlqa0tDStXr1anTp1kt1uV1pamk6dOnXBdY4fP64HHnhA06ZNO2ubzWY77/fvvfdezZ49Wzt27FBNTY0OHjyoUaNGNfi7JOkvf/mLunTp4rYtKChIktShQwf17t1bmzdvVkFBgQYPHqzbbrtNo0aN0jfffKM9e/a4Ql1ISIh27NihzZs3629/+5uefPJJPfXUU9q+fTtPfwFNgLADwCMKCwvdPn/66afq3r27SkpKdPToUT3zzDOKjY2VJH322Wdu+yYkJOivf/2r27rt27e7fb7++uv19ddfq1u3bo3q78orr9SAAQO0evVq1dTUaPDgwercufM59+3Ro4eCgoJkt9tdgeVcBgwYoI8++kjbtm3T/PnzFR4erqSkJM2fP1/R0dG65pprXPu2bt1aqampSk1NVWZmpjp06KBNmzZpxIgRjfp7AFw4LmMB8Ai73a5Zs2aptLRUa9as0aJFizR9+nTZbDa1adNGixYt0j/+8Q9t2LBBTz/9tNt3H3jgAZWUlGj27Nn65ptv9MYbb2jFihWS5Lo0Nnv2bG3dulXp6enauXOn9uzZo7fffvuCblD+wdixY7V27Vq9+eabDV7Cks6cifntb3+rmTNnauXKldq3b5927NihRYsWaeXKla79Bg4cqPfff1+tW7dWYmKia93q1avdQtK7776rhQsXaufOnfrnP/+pVatWqb6+XgkJCRfcO4BL4OubhgA0fwMGDLAeeugh6ze/+Y0VGhpqdezY0XrsscdcNyzn5uZacXFxVlBQkJWSkmJt2LDBkmR9/vnnrhpvv/221a1bNysoKMgaOHCgtWTJEkuS283H27ZtswYPHmy1b9/euvzyy61evXpZ8+fPv+A+v/vuOysoKMhq166d6+boH/z/NyhblmXV19dbOTk5VkJCghUYGGh16tTJSktLs/Lz8137HD161AoICLBGjRrlWrdu3TpLkrV06VLXuk8++cQaMGCA1bFjRys4ONjq1auX9frrr19w3wAuDZMKArhkAwcOVJ8+fZSTk+OxmvPnz9fSpUt18OBBj9UE0DJxzw4Av/DKK6+oX79+uuKKK/T3v/9dzz333EVdogKAhhB2APiFPXv2aN68efr2229ls9n08MMPKyMj44K++8knn2jo0KENbv/h6SoALROXsQA0ezU1NTp06FCD2xv7BBcAMxB2AACA0Xj0HAAAGI2wAwAAjEbYAQAARiPsAAAAoxF2AACA0Qg7AADAaIQdAABgNMIOAAAw2v8DKyInDBmx7uoAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "sns.histplot(df_ph_final['page_views'], bins=20)" ] }, { "cell_type": "markdown", "id": "6cfe0417-c13e-4a7d-889d-39e9bc50e75c", "metadata": {}, "source": [ "- distribution of category, time spent and page views variables" ] }, { "cell_type": "code", "execution_count": 258, "id": "ae2bcbc4-853b-4098-af03-27a171ea1da2", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pricepage_viewstime_spent
summeansummeansummean
customer_id
16756519.69230832525.01560120.0
24098372.54545522020.099090.0
311587551.76190563030.03150150.0
44542324.42857121015.0112080.0
55715519.54545524222.01210110.0
.....................
965888490.66666714412.03360280.0
97988197.60000012525.0680136.0
984879443.54545524222.057252.0
993547394.11111111713.01629181.0
1005552504.72727331929.01133103.0
\n", "

100 rows × 6 columns

\n", "
" ], "text/plain": [ " price page_views time_spent \n", " sum mean sum mean sum mean\n", "customer_id \n", "1 6756 519.692308 325 25.0 1560 120.0\n", "2 4098 372.545455 220 20.0 990 90.0\n", "3 11587 551.761905 630 30.0 3150 150.0\n", "4 4542 324.428571 210 15.0 1120 80.0\n", "5 5715 519.545455 242 22.0 1210 110.0\n", "... ... ... ... ... ... ...\n", "96 5888 490.666667 144 12.0 3360 280.0\n", "97 988 197.600000 125 25.0 680 136.0\n", "98 4879 443.545455 242 22.0 572 52.0\n", "99 3547 394.111111 117 13.0 1629 181.0\n", "100 5552 504.727273 319 29.0 1133 103.0\n", "\n", "[100 rows x 6 columns]" ] }, "execution_count": 258, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final.groupby(['customer_id']).agg({\n", " 'price' : ['sum', 'mean'],\n", " 'page_views' : ['sum', 'mean'],\n", " 'time_spent': ['sum', 'mean']\n", "})" ] }, { "cell_type": "code", "execution_count": 259, "id": "0e0db145-c718-4d9d-8034-5519f1756c1b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "purchase_date\n", "2023-01-02 220\n", "2023-01-03 208\n", "2023-01-01 199\n", "2023-01-05 193\n", "2023-01-04 180\n", "Name: count, dtype: int64" ] }, "execution_count": 259, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final['purchase_date'].value_counts()" ] }, { "cell_type": "markdown", "id": "db2d93bb-ae4c-47a9-82ad-d43bf81f85ed", "metadata": {}, "source": [ "## Data Preprocessing" ] }, { "cell_type": "code", "execution_count": 260, "id": "7b4c2115-bcfd-4b3f-919c-cc3a95471326", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
customer_idproduct_idpurchase_datepage_viewstime_spentcategorypriceratings
011012023-01-0125120Electronics5004.50
131012023-01-0130150Electronics5004.50
231012023-01-0330150Electronics5004.50
341012023-01-021580Electronics5004.50
451012023-01-0522110Electronics5004.50
...........................
995211062023-01-0526100Home & Kitchen6782.74
996171062023-01-0116280Home & Kitchen6782.74
997431062023-01-056217Home & Kitchen6782.74
998911062023-01-0129234Home & Kitchen6782.74
999901062023-01-0411213Home & Kitchen6782.74
\n", "

1000 rows × 8 columns

\n", "
" ], "text/plain": [ " customer_id product_id purchase_date page_views time_spent \\\n", "0 1 101 2023-01-01 25 120 \n", "1 3 101 2023-01-01 30 150 \n", "2 3 101 2023-01-03 30 150 \n", "3 4 101 2023-01-02 15 80 \n", "4 5 101 2023-01-05 22 110 \n", ".. ... ... ... ... ... \n", "995 21 106 2023-01-05 26 100 \n", "996 17 106 2023-01-01 16 280 \n", "997 43 106 2023-01-05 6 217 \n", "998 91 106 2023-01-01 29 234 \n", "999 90 106 2023-01-04 11 213 \n", "\n", " category price ratings \n", "0 Electronics 500 4.50 \n", "1 Electronics 500 4.50 \n", "2 Electronics 500 4.50 \n", "3 Electronics 500 4.50 \n", "4 Electronics 500 4.50 \n", ".. ... ... ... \n", "995 Home & Kitchen 678 2.74 \n", "996 Home & Kitchen 678 2.74 \n", "997 Home & Kitchen 678 2.74 \n", "998 Home & Kitchen 678 2.74 \n", "999 Home & Kitchen 678 2.74 \n", "\n", "[1000 rows x 8 columns]" ] }, "execution_count": 260, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final" ] }, { "cell_type": "markdown", "id": "ba9ccc12-53fd-465b-8f29-e4bd9d3be185", "metadata": {}, "source": [ "- the data seems good and no need for data preprocessing" ] }, { "cell_type": "markdown", "id": "c446b5de-46b1-4ccf-91ce-417fe350b48e", "metadata": {}, "source": [ "## Model Development\n", "- using KNNwithMeans from scikit surprise\n", "- this model capables to find nearest neighbors and predict the ratings (to indicate user preference)\n", "- our goal is to predict top 5 product with highest ratings related to customers\n", "- my hipothesis is higher ratings mean higher probability customers will buy the products" ] }, { "cell_type": "code", "execution_count": 373, "id": "cfbffc6d-7c44-4449-9d95-cad2db7104a4", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
customer_idproduct_idpurchase_datepage_viewstime_spentcategorypriceratings
011012023-01-0125120Electronics5004.5
131012023-01-0130150Electronics5004.5
231012023-01-0330150Electronics5004.5
341012023-01-021580Electronics5004.5
451012023-01-0522110Electronics5004.5
\n", "
" ], "text/plain": [ " customer_id product_id purchase_date page_views time_spent category \\\n", "0 1 101 2023-01-01 25 120 Electronics \n", "1 3 101 2023-01-01 30 150 Electronics \n", "2 3 101 2023-01-03 30 150 Electronics \n", "3 4 101 2023-01-02 15 80 Electronics \n", "4 5 101 2023-01-05 22 110 Electronics \n", "\n", " price ratings \n", "0 500 4.5 \n", "1 500 4.5 \n", "2 500 4.5 \n", "3 500 4.5 \n", "4 500 4.5 " ] }, "execution_count": 373, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final.head()" ] }, { "cell_type": "code", "execution_count": 414, "id": "8734beed-20df-49e9-ac21-754adfc1639c", "metadata": {}, "outputs": [], "source": [ "reader = Reader(rating_scale=(1, 5))\n", "\n", "# Loads Pandas dataframe\n", "data = Dataset.load_from_df(df_ph_final[[\"customer_id\", \"product_id\", \"ratings\"]], reader)" ] }, { "cell_type": "markdown", "id": "3727fb26-8d6d-4438-a9e9-eff23df5220c", "metadata": {}, "source": [ "- create datasets" ] }, { "cell_type": "code", "execution_count": 415, "id": "6c266fed-6d16-4633-b002-ca1f13bda70a", "metadata": {}, "outputs": [], "source": [ "sim_options = {\n", " \"name\": \"cosine\",\n", " \"user_based\": True,\n", "}\n", "algo = KNNWithMeans(sim_options=sim_options)" ] }, { "cell_type": "markdown", "id": "d3d689ac-1d96-4a7c-8889-9592c6ef1a13", "metadata": {}, "source": [ "- define models" ] }, { "cell_type": "code", "execution_count": 416, "id": "f1f15533-473d-4571-80e6-f54a51ccd85c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Computing the cosine similarity matrix...\n", "Done computing similarity matrix.\n" ] } ], "source": [ "trainset, testset = train_test_split(data, test_size=0.25)\n", "algo.fit(trainset)\n", "predictions = algo.test(testset)" ] }, { "cell_type": "markdown", "id": "61942c65-fefc-4cb2-9532-714058513884", "metadata": {}, "source": [ "- training for the models" ] }, { "cell_type": "code", "execution_count": 417, "id": "a7b4cf3e-d850-4dc8-b5bf-7841586b0816", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RMSE: 0.4993\n" ] }, { "data": { "text/plain": [ "0.4992596085741228" ] }, "execution_count": 417, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rmse(predictions)" ] }, { "cell_type": "markdown", "id": "65e3d046-f24d-4adb-8a91-8d90c18e4b94", "metadata": {}, "source": [ "- using RMSE to evaluate the models and the RMSE seems good around 0.4993" ] }, { "cell_type": "code", "execution_count": 418, "id": "80bd5e5e-1945-4f81-8fe5-9d2d65c189c2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['KNN_Model.joblib']" ] }, "execution_count": 418, "metadata": {}, "output_type": "execute_result" } ], "source": [ "joblib.dump(algo, \"KNN_Model.joblib\")" ] }, { "cell_type": "markdown", "id": "3fbf727c-ebd9-4476-afbc-f5a7c5a14aaa", "metadata": {}, "source": [ "- save model " ] }, { "cell_type": "markdown", "id": "8b5c8a49-fce3-42a3-a342-7d3ef3df3954", "metadata": {}, "source": [ "### testing" ] }, { "cell_type": "code", "execution_count": 420, "id": "b390e5a6-01ae-46c4-8df0-493f75fe2b02", "metadata": {}, "outputs": [], "source": [ "list_predicted = []\n", "\n", "for id in df_ph_final['product_id'].unique():\n", " preds = list(algo.predict(1, id))\n", " product_id = preds[1]\n", " product_score = preds[3]\n", "\n", " list_predicted.append((product_id, product_score))" ] }, { "cell_type": "code", "execution_count": 425, "id": "423ab39c-9232-4ca5-a395-1d5366e6096b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([101, 105, 120, 110, 102, 115, 103, 103, 122, 114, 114, 124, 121])" ] }, "execution_count": 425, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_ph_final[df_ph_final['customer_id']==1]['product_id'].values" ] }, { "cell_type": "code", "execution_count": 430, "id": "c3e97249-37b0-4f43-9849-aa30df423169", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[105, 121, 118, 114, 101]" ] }, "execution_count": 430, "metadata": {}, "output_type": "execute_result" } ], "source": [ "top_5_products = sorted(list_predicted, key=lambda x:x[1], reverse=True)[:5]\n", "top_5_products = [product[0] for product in top_5_products]\n", "top_5_products" ] }, { "cell_type": "markdown", "id": "0159ed80-6adc-4238-af18-fc1701da965c", "metadata": {}, "source": [ "- so from the historical data, the models predict that\n", "- the most likely products that the user will buy are 105, 121, 118, 114, 101" ] }, { "cell_type": "markdown", "id": "de0860a0-47ed-432b-ba09-26bd41e85d7c", "metadata": {}, "source": [ "## Web Apps Development\n", "- will use gradio and will hosting to huggingface" ] }, { "cell_type": "code", "execution_count": 447, "id": "f73f026e-8692-48b6-af28-411439bac649", "metadata": {}, "outputs": [], "source": [ "df_ph_final.to_csv(\"data_final.csv\", index=False)" ] }, { "cell_type": "code", "execution_count": 437, "id": "f9db4891-7e9c-406f-9487-faf2ccd8c1b8", "metadata": {}, "outputs": [], "source": [ "def product_recommender(customer_id):\n", " list_predicted = []\n", " \n", " for id in df_ph_final['product_id'].unique():\n", " preds = list(algo.predict(customer_id, id))\n", " product_id = preds[1]\n", " product_score = preds[3]\n", " \n", " list_predicted.append((product_id, product_score))\n", " \n", " top_5_products_raw = sorted(list_predicted, key=lambda x:x[1], reverse=True)[:5]\n", " top_5_products = [product[0] for product in top_5_products_raw]\n", "\n", " product_1_category = df_ph_final[df_ph_final['product_id']==top_5_products[0]]['category'].values[0]\n", " product_2_category = df_ph_final[df_ph_final['product_id']==top_5_products[1]]['category'].values[0]\n", " product_3_category = df_ph_final[df_ph_final['product_id']==top_5_products[2]]['category'].values[0]\n", " product_4_category = df_ph_final[df_ph_final['product_id']==top_5_products[3]]['category'].values[0]\n", " product_5_category = df_ph_final[df_ph_final['product_id']==top_5_products[4]]['category'].values[0]\n", "\n", " result_1 = f\"Recommendation Product ID {top_5_products[0]} with Category {product_1_category}\"\n", " result_2 = f\"Recommendation Product ID {top_5_products[1]} with Category {product_2_category}\"\n", " result_3 = f\"Recommendation Product ID {top_5_products[2]} with Category {product_3_category}\"\n", " result_4 = f\"Recommendation Product ID {top_5_products[3]} with Category {product_4_category}\"\n", " result_5 = f\"Recommendation Product ID {top_5_products[4]} with Category {product_5_category}\"\n", "\n", " return result_1, result_2, result_3, result_4, result_5" ] }, { "cell_type": "code", "execution_count": 442, "id": "1ea72b31-8ca8-46f1-9833-d33cb4cc8ae7", "metadata": {}, "outputs": [], "source": [ "demo = gr.Interface(\n", " title=\"Product Recommendation System\",\n", " description=\"\"\"This User Interface is Powered by Machine Learning to\n", " Predict the Top 5 of Product that customer likely to buy in the next purchase.\n", " All you need is to Input Customer ID and then the Recommendation will be appear.\"\"\",\n", " fn=product_recommender,\n", " inputs=[\n", " gr.Number(label=\"Input Customer ID\")\n", " ],\n", " outputs=[\n", " gr.Textbox(label=\"Recommendation Product 1\"),\n", " gr.Textbox(label=\"Recommendation Product 2\"),\n", " gr.Textbox(label=\"Recommendation Product 3\"),\n", " gr.Textbox(label=\"Recommendation Product 4\"),\n", " gr.Textbox(label=\"Recommendation Product 5\")\n", " ]\n", ")" ] }, { "cell_type": "code", "execution_count": 443, "id": "3d5921b0-816f-4d59-acc2-63e0be081f9f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running on local URL: http://127.0.0.1:7862\n", "\n", "To create a public link, set `share=True` in `launch()`.\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [] }, "execution_count": 443, "metadata": {}, "output_type": "execute_result" } ], "source": [ "demo.launch()" ] }, { "cell_type": "markdown", "id": "192d7c24-be73-48a7-8bc0-eb1bc49d3e54", "metadata": {}, "source": [ "## Scripts for Deployment in Huggingface" ] }, { "cell_type": "code", "execution_count": 445, "id": "3d4df15e-88f4-4854-bc2c-8267211cd6eb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Writing requirements.txt\n" ] } ], "source": [ "%%writefile requirements.txt\n", "gradio\n", "pandas\n", "numpy\n", "faker\n", "scikit-surprise" ] }, { "cell_type": "code", "execution_count": 449, "id": "408aac2a-9b5c-4797-bd00-7706007f81c1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Writing app.py\n" ] } ], "source": [ "%%writefile app.py\n", "import gradio as gr\n", "import pandas as pd\n", "import joblib\n", "\n", "data = pd.read_csv(r\"data_final.csv\")\n", "\n", "def product_recommender(customer_id):\n", " list_predicted = []\n", " \n", " for id in data['product_id'].unique():\n", " preds = list(algo.predict(customer_id, id))\n", " product_id = preds[1]\n", " product_score = preds[3]\n", " \n", " list_predicted.append((product_id, product_score))\n", " \n", " top_5_products_raw = sorted(list_predicted, key=lambda x:x[1], reverse=True)[:5]\n", " top_5_products = [product[0] for product in top_5_products_raw]\n", "\n", " product_1_category = data[data['product_id']==top_5_products[0]]['category'].values[0]\n", " product_2_category = data[data['product_id']==top_5_products[1]]['category'].values[0]\n", " product_3_category = data[data['product_id']==top_5_products[2]]['category'].values[0]\n", " product_4_category = data[data['product_id']==top_5_products[3]]['category'].values[0]\n", " product_5_category = data[data['product_id']==top_5_products[4]]['category'].values[0]\n", "\n", " result_1 = f\"Recommendation Product ID {top_5_products[0]} with Category {product_1_category}\"\n", " result_2 = f\"Recommendation Product ID {top_5_products[1]} with Category {product_2_category}\"\n", " result_3 = f\"Recommendation Product ID {top_5_products[2]} with Category {product_3_category}\"\n", " result_4 = f\"Recommendation Product ID {top_5_products[3]} with Category {product_4_category}\"\n", " result_5 = f\"Recommendation Product ID {top_5_products[4]} with Category {product_5_category}\"\n", "\n", " return result_1, result_2, result_3, result_4, result_5\n", "\n", "demo = gr.Interface(\n", " title=\"Product Recommendation System\",\n", " description=\"\"\"This User Interface is Powered by Machine Learning to\n", " Predict the Top 5 of Product that customer likely to buy in the next purchase.\n", " All you need is to Input Customer ID and then the Recommendation will be appear.\"\"\",\n", " fn=product_recommender,\n", " inputs=[\n", " gr.Number(label=\"Input Customer ID\")\n", " ],\n", " outputs=[\n", " gr.Textbox(label=\"Recommendation Product 1\"),\n", " gr.Textbox(label=\"Recommendation Product 2\"),\n", " gr.Textbox(label=\"Recommendation Product 3\"),\n", " gr.Textbox(label=\"Recommendation Product 4\"),\n", " gr.Textbox(label=\"Recommendation Product 5\")\n", " ]\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()" ] }, { "cell_type": "markdown", "id": "50dee250-e65d-4ae3-9263-cfacc09ac6ff", "metadata": {}, "source": [ "- link web apps --> https://huggingface.co/spaces/Adipta/product-recommender\n", "- link repository --> https://huggingface.co/spaces/Adipta/product-recommender/tree/main" ] }, { "cell_type": "code", "execution_count": null, "id": "61ac0db1-1c8e-447f-8cb2-70f679d61a59", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.18" } }, "nbformat": 4, "nbformat_minor": 5 }