{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":7391,"databundleVersionId":44328,"sourceType":"competition"}],"dockerImageVersionId":30822,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Homework 4 - ruslahnq","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport gc\nimport sys\n\nfrom sklearn.base import BaseEstimator, TransformerMixin\nfrom sklearn.compose import ColumnTransformer, TransformedTargetRegressor\nfrom sklearn.preprocessing import OneHotEncoder, LabelEncoder, StandardScaler, OrdinalEncoder\nfrom sklearn.impute import SimpleImputer\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.model_selection import train_test_split, TimeSeriesSplit\nfrom sklearn.metrics import make_scorer\nfrom lightgbm import LGBMRegressor\nfrom catboost import CatBoostRegressor\nfrom sklearn.dummy import DummyRegressor\nfrom sklearn.model_selection import TimeSeriesSplit\nfrom sklearn.model_selection import RandomizedSearchCV\n\nfrom scipy.stats import randint, uniform","metadata":{"_uuid":"c6e7d8ed-bc84-4630-aded-c130bc6afeb1","_cell_guid":"d9d1b886-a95f-436c-95f1-31d5b2920ca4","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:23:37.310030Z","iopub.execute_input":"2025-01-17T12:23:37.310486Z","iopub.status.idle":"2025-01-17T12:23:42.497657Z","shell.execute_reply.started":"2025-01-17T12:23:37.310447Z","shell.execute_reply":"2025-01-17T12:23:42.496509Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\n\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\npaths = []\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n        paths.append(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"effd6f73-fa3f-4856-98db-89d9a19a95b2","_cell_guid":"639bc205-d850-4cbb-b8d1-266d15828de1","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:23:42.498666Z","iopub.execute_input":"2025-01-17T12:23:42.499311Z","iopub.status.idle":"2025-01-17T12:23:42.509996Z","shell.execute_reply.started":"2025-01-17T12:23:42.499280Z","shell.execute_reply":"2025-01-17T12:23:42.508910Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install py7zr --quiet","metadata":{"_uuid":"6e120892-b321-4789-be38-bc84d059c3a7","_cell_guid":"53fe9db7-7e33-438d-aa08-3c9040f6ef5a","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:23:42.511105Z","iopub.execute_input":"2025-01-17T12:23:42.511418Z","iopub.status.idle":"2025-01-17T12:23:47.933572Z","shell.execute_reply.started":"2025-01-17T12:23:42.511392Z","shell.execute_reply":"2025-01-17T12:23:47.932089Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import py7zr\nfor filenames in paths:\n    with py7zr.SevenZipFile(filenames, mode='r') as z_ref:\n        z_ref.extractall(path='/kaggle/working')","metadata":{"_uuid":"d2176299-263d-4c43-acdc-717e4e3a6430","_cell_guid":"372217b9-015a-4d4d-b6fd-bb38c8a2e20b","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:23:47.935116Z","iopub.execute_input":"2025-01-17T12:23:47.935566Z","iopub.status.idle":"2025-01-17T12:25:25.213833Z","shell.execute_reply.started":"2025-01-17T12:23:47.935523Z","shell.execute_reply":"2025-01-17T12:25:25.212464Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Corporación Favorita Grocery Sales Forecasting\n\nPlease read data description: https://www.kaggle.com/c/favorita-grocery-sales-forecasting","metadata":{"_uuid":"fd88e21c-8b8c-4789-a7ba-ea59d4360cd3","_cell_guid":"aaed6701-b9af-46c7-8056-ffa706fd0d64","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"markdown","source":"## Splitting Data into Training and Test Sets\nThe data you are working with splited into **training** and **test** sets and stored in the following files:\n\n- **`/kaggle/working/train_data.csv`** – the training dataset used for model training.\n- **`/kaggle/working/test_data.csv`** – the test dataset used to evaluate the model's performance.","metadata":{"_uuid":"6e28a253-af3f-4b55-b15c-30f2d3c6bd84","_cell_guid":"84db092f-fdf5-4767-85cd-a3458bc52b89","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"%%time\ndata = pd.read_csv(\"/kaggle/working/train.csv\")\ndata[\"date\"] =  pd.to_datetime(data[\"date\"])","metadata":{"_uuid":"a2a9e70b-a16c-4fd2-a4b8-ead3fa64f278","_cell_guid":"fc8819c3-4a00-48e7-9ab9-17402b17a0b5","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:25:25.218033Z","iopub.execute_input":"2025-01-17T12:25:25.218543Z","iopub.status.idle":"2025-01-17T12:27:08.246511Z","shell.execute_reply.started":"2025-01-17T12:25:25.218494Z","shell.execute_reply":"2025-01-17T12:27:08.245129Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"monthly_counts_data = data['date'].dt.to_period('M').value_counts().sort_index()\n\nplt.figure(figsize=(12, 6))\nmonthly_counts_data.plot(kind='bar', color='skyblue')\nplt.title('Count of Data for Each Month for All data', fontsize=14)\nplt.xlabel('Month', fontsize=12)\nplt.ylabel('Count', fontsize=12)\nplt.xticks(rotation=45)\nplt.grid(axis='y', linestyle='--', alpha=0.7)\nplt.show()","metadata":{"_uuid":"0d37cc2f-44bd-4881-9539-be00103f8aa0","_cell_guid":"8b11a6d3-362e-4868-8f2c-487a64df8bb4","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:27:08.248608Z","iopub.execute_input":"2025-01-17T12:27:08.249044Z","iopub.status.idle":"2025-01-17T12:27:15.927228Z","shell.execute_reply.started":"2025-01-17T12:27:08.249008Z","shell.execute_reply":"2025-01-17T12:27:15.925991Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Choosing only one whole year, but selecting all the different months because of RAM usage error from Kaggle. Choosing only the recent year, so model will keep up with the up to date data.","metadata":{}},{"cell_type":"code","source":"%%time\nTHRESHOLD_TRAIN_DATE_FROM = pd.to_datetime(\"2017-01-01\")\nTHRESHOLD_TRAIN_DATE = pd.to_datetime(\"2017-07-01\")\nTHRESHOLD_TEST_DATE = pd.to_datetime(\"2017-08-01\")\n\ndata[(THRESHOLD_TRAIN_DATE_FROM <= data[\"date\"])&(data[\"date\"] < THRESHOLD_TRAIN_DATE)].to_csv(\"/kaggle/working/train_data.csv\")\ndata[(data[\"date\"] >= THRESHOLD_TRAIN_DATE)&(data[\"date\"] < THRESHOLD_TEST_DATE)].to_csv(\"/kaggle/working/test_data.csv\")\n\n%xdel data","metadata":{"_uuid":"c221585d-209d-4383-8447-1163d989482b","_cell_guid":"16faf7d7-411e-4f08-8cd0-0179bb805824","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:27:15.929193Z","iopub.execute_input":"2025-01-17T12:27:15.929570Z","iopub.status.idle":"2025-01-17T12:28:40.402671Z","shell.execute_reply.started":"2025-01-17T12:27:15.929529Z","shell.execute_reply":"2025-01-17T12:28:40.401336Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\ntrain_df = pd.read_csv(\"/kaggle/working/train_data.csv\")\ntest_df = pd.read_csv(\"/kaggle/working/test_data.csv\")","metadata":{"_uuid":"ab8d0532-dabb-4923-8e0f-59eddd615bd3","_cell_guid":"1da1c9a5-8044-4dd9-8647-eed9451ace17","trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:40.403899Z","iopub.execute_input":"2025-01-17T12:28:40.404379Z","iopub.status.idle":"2025-01-17T12:28:55.477418Z","shell.execute_reply.started":"2025-01-17T12:28:40.404338Z","shell.execute_reply":"2025-01-17T12:28:55.475966Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df[\"date\"] = pd.to_datetime(train_df[\"date\"])\ntest_df[\"date\"] = pd.to_datetime(test_df[\"date\"])","metadata":{"_uuid":"b2f36db1-0ee4-4704-a2d6-a8fb7057f406","_cell_guid":"dfbb1285-c07e-41c6-a9bb-b7ccfa70f32c","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:28:55.478615Z","iopub.execute_input":"2025-01-17T12:28:55.479067Z","iopub.status.idle":"2025-01-17T12:28:58.082423Z","shell.execute_reply.started":"2025-01-17T12:28:55.479026Z","shell.execute_reply":"2025-01-17T12:28:58.081009Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import sys\n# import gc\n\n# # Collect garbage to remove unreferenced objects\n# gc.collect()\n\n# # List all objects and their sizes in memory\n# for var_name, var_obj in globals().items():\n#     try:\n#         if sys.getsizeof(var_obj) / (1024 ** 2) > 100:\n#             print(f\"{var_name}: {sys.getsizeof(var_obj) / (1024 ** 2):.2f} MB\")\n#     except TypeError:\n#         pass","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:58.083693Z","iopub.execute_input":"2025-01-17T12:28:58.084096Z","iopub.status.idle":"2025-01-17T12:28:58.088438Z","shell.execute_reply.started":"2025-01-17T12:28:58.084063Z","shell.execute_reply":"2025-01-17T12:28:58.087367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"monthly_counts = train_df['date'].dt.to_period('M').value_counts().sort_index().reset_index()\nmonthly_counts_test = test_df['date'].dt.to_period('M').value_counts().sort_index().reset_index()","metadata":{"_uuid":"e65e7f4d-134f-44b6-9a3b-9ed0cc44c25a","_cell_guid":"c65ade2c-81ae-4dbc-a708-03ce33b80191","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:28:58.089729Z","iopub.execute_input":"2025-01-17T12:28:58.090209Z","iopub.status.idle":"2025-01-17T12:28:59.209542Z","shell.execute_reply.started":"2025-01-17T12:28:58.090165Z","shell.execute_reply":"2025-01-17T12:28:59.208035Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"monthly_counts['type'] = 'Train'\nmonthly_counts_test['type'] = 'Test'\ncombined = pd.concat([monthly_counts, monthly_counts_test])\n\nplt.figure(figsize=(12, 6))\nsns.barplot(data=combined, x='date', y='count', hue='type', palette=['blue', 'red'])\nplt.title('Count of Data for Each Month (Train vs Test)', fontsize=14)\nplt.xlabel('Month', fontsize=12)\nplt.ylabel('Count', fontsize=12)\nplt.xticks(rotation=45)\nplt.legend(title='Dataset')\nplt.grid(axis='y', linestyle='--', alpha=0.7)\nplt.show()","metadata":{"_uuid":"88c2be84-af63-4399-9bab-3c9230d2325d","_cell_guid":"5f86cf41-c34a-4853-ae6f-47927a841a88","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.210900Z","iopub.execute_input":"2025-01-17T12:28:59.211371Z","iopub.status.idle":"2025-01-17T12:28:59.613441Z","shell.execute_reply.started":"2025-01-17T12:28:59.211323Z","shell.execute_reply":"2025-01-17T12:28:59.611735Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.head()","metadata":{"_uuid":"d026d255-6916-4f7b-bafb-b432cd2f7c5b","_cell_guid":"a7ca1ea6-d07f-48ed-9a5e-744af42b777f","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.614789Z","iopub.execute_input":"2025-01-17T12:28:59.615195Z","iopub.status.idle":"2025-01-17T12:28:59.634613Z","shell.execute_reply.started":"2025-01-17T12:28:59.615148Z","shell.execute_reply":"2025-01-17T12:28:59.633393Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Additional Data\n\n\nTo make more effective use of the data, you also have access to several auxiliary datasets containing contextual information:\n\n#### 1. **`holidays_events.csv`**\n   - **Description**:\n     Contains information about holidays and events that may influence sales.\n   - **Useful Columns**:\n     - `date`: The date of the holiday or event.\n     - `type`: The type of event (national, regional, local).\n     - `locale`: The level of impact (national, regional, local).\n     - `description`: A description of the event.\n   - **How to Use**:\n     - Add a flag indicating whether a date is a holiday to the training and test sets.\n     - Categorize holidays by their `type` and consider their impact on sales.\n     - Use the `locale` column to analyze regional effects.","metadata":{"_uuid":"7690d401-b8a6-4c2b-82ec-a1d4c7ea5b15","_cell_guid":"a31ad756-92de-4b0e-894a-d57b6e48d127","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2024-12-22T19:12:02.31896Z","iopub.execute_input":"2024-12-22T19:12:02.319553Z","iopub.status.idle":"2024-12-22T19:12:02.32548Z","shell.execute_reply.started":"2024-12-22T19:12:02.319516Z","shell.execute_reply":"2024-12-22T19:12:02.323891Z"},"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"holiday_events = pd.read_csv(\"/kaggle/working/holidays_events.csv\")\nprint(holiday_events.shape)\nholiday_events.head()","metadata":{"_uuid":"9e1c1d5b-0307-4b1b-8bbc-22bbe9d0dad1","_cell_guid":"b9cecdf1-d100-4300-a9e7-c11fa77cb5a2","trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.636471Z","iopub.execute_input":"2025-01-17T12:28:59.636943Z","iopub.status.idle":"2025-01-17T12:28:59.654489Z","shell.execute_reply.started":"2025-01-17T12:28:59.636896Z","shell.execute_reply":"2025-01-17T12:28:59.652719Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"holiday_events.isna().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.655911Z","iopub.execute_input":"2025-01-17T12:28:59.656246Z","iopub.status.idle":"2025-01-17T12:28:59.665418Z","shell.execute_reply.started":"2025-01-17T12:28:59.656218Z","shell.execute_reply":"2025-01-17T12:28:59.664243Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### 2. **`items.csv`**\n   - **Description**:\n     Contains information about the items being sold.\n   - **Useful Columns**:\n     - `item_nbr`: Unique identifier for each item.\n     - `family`: The category or family the item belongs to (e.g., \"Beverages\").\n     - `class`: A finer categorization of items.\n     - `perishable`: A binary indicator for whether the item is perishable (1 for perishable, 0 otherwise).\n   - **How to Use**:\n     - Use `family` and `class` to group items and analyze trends across categories.\n     - Include the `perishable` indicator to weight predictions for perishable items.","metadata":{"_uuid":"423b5546-8e6a-4dd8-8a5b-8ee0d4e8ad26","_cell_guid":"3f8787d3-2a8d-4d6f-887f-68af249a8fa5","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"items = pd.read_csv(\"/kaggle/working/items.csv\")\nprint(items.shape)\nitems.head()","metadata":{"_uuid":"f296fb77-0b69-4487-bc26-df8621a3edbc","_cell_guid":"6f644363-d8d6-40da-ae77-d4db031dd1b2","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.666677Z","iopub.execute_input":"2025-01-17T12:28:59.667162Z","iopub.status.idle":"2025-01-17T12:28:59.694769Z","shell.execute_reply.started":"2025-01-17T12:28:59.667103Z","shell.execute_reply":"2025-01-17T12:28:59.693561Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"items.isna().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.699998Z","iopub.execute_input":"2025-01-17T12:28:59.700403Z","iopub.status.idle":"2025-01-17T12:28:59.709648Z","shell.execute_reply.started":"2025-01-17T12:28:59.700369Z","shell.execute_reply":"2025-01-17T12:28:59.708215Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### 3. **`oil.csv`**\n   - **Description**:\n     Contains daily oil price data, which can serve as an external economic indicator.\n   - **Useful Columns**:\n     - `date`: The date corresponding to the oil price.\n     - `dcoilwtico`: The daily oil price.\n   - **How to Use**:\n     - Join this dataset with the training and test sets on the `date` column to include oil price as a feature.\n     - Analyze the correlation between oil price fluctuations and sales trends.","metadata":{"_uuid":"4e39ea32-929f-413d-9d6e-0d508e950b75","_cell_guid":"8723b589-ea65-4b05-abe5-7dd16976305b","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"oil = pd.read_csv(\"/kaggle/working/oil.csv\")\nprint(oil.shape)\noil.head()","metadata":{"_uuid":"d5bf5013-26a2-496d-ad57-5b37b540f77d","_cell_guid":"7b21c9f8-df52-4e3b-b7ac-d6da94e298ca","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.712850Z","iopub.execute_input":"2025-01-17T12:28:59.713281Z","iopub.status.idle":"2025-01-17T12:28:59.735754Z","shell.execute_reply.started":"2025-01-17T12:28:59.713236Z","shell.execute_reply":"2025-01-17T12:28:59.734224Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"oil.isna().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.737429Z","iopub.execute_input":"2025-01-17T12:28:59.737895Z","iopub.status.idle":"2025-01-17T12:28:59.747504Z","shell.execute_reply.started":"2025-01-17T12:28:59.737848Z","shell.execute_reply":"2025-01-17T12:28:59.746226Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"oil = oil.dropna(subset=['dcoilwtico'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.748867Z","iopub.execute_input":"2025-01-17T12:28:59.749340Z","iopub.status.idle":"2025-01-17T12:28:59.768692Z","shell.execute_reply.started":"2025-01-17T12:28:59.749294Z","shell.execute_reply":"2025-01-17T12:28:59.767487Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"oil.isna().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.770039Z","iopub.execute_input":"2025-01-17T12:28:59.770453Z","iopub.status.idle":"2025-01-17T12:28:59.790837Z","shell.execute_reply.started":"2025-01-17T12:28:59.770411Z","shell.execute_reply":"2025-01-17T12:28:59.789464Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### 4. **`stores.csv`**\n   - **Description**:\n     Contains information about the stores where items are sold.\n   - **Useful Columns**:\n     - `store_nbr`: Unique identifier for each store.\n     - `city`: The city where the store is located.\n     - `state`: The state where the store is located.\n     - `type`: The store type.\n     - `cluster`: A grouping of similar stores based on sales patterns.\n   - **How to Use**:\n     - Use `city` and `state` for regional analysis of sales trends.\n     - Incorporate `type` and `cluster` to identify patterns and group stores with similar behavior.","metadata":{"_uuid":"fa52abb1-f5ec-4260-84d0-a8c9b40c2ee3","_cell_guid":"01b3300b-2e0b-4003-96b8-a116fbaade0f","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"stores = pd.read_csv(\"/kaggle/working/stores.csv\")\nprint(stores.shape)\nstores.head()","metadata":{"_uuid":"a6991164-c3ca-4332-b2bc-15fe24d0b140","_cell_guid":"f73b105b-cac9-42c8-9112-5f13ea357bdd","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.792201Z","iopub.execute_input":"2025-01-17T12:28:59.792554Z","iopub.status.idle":"2025-01-17T12:28:59.819473Z","shell.execute_reply.started":"2025-01-17T12:28:59.792521Z","shell.execute_reply":"2025-01-17T12:28:59.818089Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"stores.isna().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.820636Z","iopub.execute_input":"2025-01-17T12:28:59.821089Z","iopub.status.idle":"2025-01-17T12:28:59.829470Z","shell.execute_reply.started":"2025-01-17T12:28:59.821051Z","shell.execute_reply":"2025-01-17T12:28:59.828090Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**[READ DATA DESCRIPTION CAREFULY](https://www.kaggle.com/competitions/favorita-grocery-sales-forecasting) !!!!** \n\n## Exploratory Data Analysis and Model Training\n\n### 1. Baseline Model\n- Consider which model would be suitable as `DummyModel` for this task, then create, train, and use its predictions as a baseline.\n\n### 2. Feature Engineering\n- Generate new features by incorporating data from additional datasets to enhance the model's predictive capabilities.\n\n### 3. Model Training and Optimization\n- Utilize advanced regression models, such as **LGBM Regression** or **CatBoost Regression**, to achieve the best results. Focus on hyperparameter tuning and evaluation metrics to optimize performance. **Use foremention Normalized Weighted Root Mean Squared Logarithmic Error**.  \n\n### Thats All :-)","metadata":{"_uuid":"79cb2add-bde1-4ccd-8c7a-912e6f543335","_cell_guid":"bdf1f972-4a03-41ae-8e5f-64c98f8fdd56","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"markdown","source":"### Preparaing our data","metadata":{}},{"cell_type":"code","source":"train_df.dtypes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.830697Z","iopub.execute_input":"2025-01-17T12:28:59.831030Z","iopub.status.idle":"2025-01-17T12:28:59.849573Z","shell.execute_reply.started":"2025-01-17T12:28:59.831000Z","shell.execute_reply":"2025-01-17T12:28:59.848410Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Number of NaN in train_df['unit_sales']:\", train_df['unit_sales'].isna().sum())\nprint(\"Number of NaN in train_df['unit_sales']:\", test_df['unit_sales'].isna().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.851261Z","iopub.execute_input":"2025-01-17T12:28:59.851765Z","iopub.status.idle":"2025-01-17T12:28:59.905087Z","shell.execute_reply.started":"2025-01-17T12:28:59.851718Z","shell.execute_reply":"2025-01-17T12:28:59.903618Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(train_df.shape, test_df.shape)\nprint(\"train/test ratio:\", train_df.shape[0] / test_df.shape[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.906133Z","iopub.execute_input":"2025-01-17T12:28:59.906464Z","iopub.status.idle":"2025-01-17T12:28:59.912884Z","shell.execute_reply.started":"2025-01-17T12:28:59.906436Z","shell.execute_reply":"2025-01-17T12:28:59.911602Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.info()\ntrain_df.isnull().sum()\ntrain_df.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:28:59.914040Z","iopub.execute_input":"2025-01-17T12:28:59.914411Z","iopub.status.idle":"2025-01-17T12:29:03.291689Z","shell.execute_reply.started":"2025-01-17T12:28:59.914381Z","shell.execute_reply":"2025-01-17T12:29:03.290244Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"item_counts = train_df['item_nbr'].value_counts()\nitem_bins = pd.cut(item_counts, bins=10).value_counts().sort_index()\n\nplt.figure(figsize=(12, 6))\nitem_bins.plot(kind='bar', color='skyblue', edgecolor='black')\n\nplt.title('Distribution of Item Sales (Grouped)', fontsize=16)\nplt.xlabel('Number of Sales (Binned)', fontsize=14)\nplt.ylabel('Number of Items', fontsize=14)\nplt.xticks(rotation=45)\nplt.grid(axis='y', linestyle='--', alpha=0.7)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:03.293041Z","iopub.execute_input":"2025-01-17T12:29:03.293458Z","iopub.status.idle":"2025-01-17T12:29:04.407719Z","shell.execute_reply.started":"2025-01-17T12:29:03.293418Z","shell.execute_reply":"2025-01-17T12:29:04.406467Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Here, we can see an interesting distribution. As we can see, number of different items being sold follow the normal distribution e.g those items that were sold ~7644-9555 times are more frequently seen than all the others respectively. However, this information doesn't tell any essential information about the items itself or about any other properties that those items possess.","metadata":{}},{"cell_type":"markdown","source":"# Merging additional data with our data","metadata":{}},{"cell_type":"code","source":"# converting to datetime\nholiday_events['date'] = pd.to_datetime(holiday_events['date'])\noil['date'] = pd.to_datetime(oil['date'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:04.409028Z","iopub.execute_input":"2025-01-17T12:29:04.409383Z","iopub.status.idle":"2025-01-17T12:29:04.417928Z","shell.execute_reply.started":"2025-01-17T12:29:04.409354Z","shell.execute_reply":"2025-01-17T12:29:04.416664Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(holiday_events.dtypes)\nprint(\"-------\")\nprint(oil.dtypes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:04.418917Z","iopub.execute_input":"2025-01-17T12:29:04.419295Z","iopub.status.idle":"2025-01-17T12:29:04.439731Z","shell.execute_reply.started":"2025-01-17T12:29:04.419264Z","shell.execute_reply":"2025-01-17T12:29:04.438272Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Adding items data","metadata":{}},{"cell_type":"code","source":"train_df = train_df.merge(items, on='item_nbr', how='left')\ntest_df = test_df.merge(items, on='item_nbr', how='left')\n\nprint(\"Train shape after merging items:\", train_df.shape)\nprint(\"Test shape after merging items:\", test_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:04.441333Z","iopub.execute_input":"2025-01-17T12:29:04.441833Z","iopub.status.idle":"2025-01-17T12:29:07.805350Z","shell.execute_reply.started":"2025-01-17T12:29:04.441757Z","shell.execute_reply":"2025-01-17T12:29:07.803965Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Adding stores data","metadata":{}},{"cell_type":"code","source":"train_df = train_df.merge(stores, on='store_nbr', how='left')\ntest_df = test_df.merge(stores, on='store_nbr', how='left')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:07.806773Z","iopub.execute_input":"2025-01-17T12:29:07.807191Z","iopub.status.idle":"2025-01-17T12:29:12.401512Z","shell.execute_reply.started":"2025-01-17T12:29:07.807159Z","shell.execute_reply":"2025-01-17T12:29:12.400277Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Adding oil data\n\nHowever, before, we should fill the missing values","metadata":{}},{"cell_type":"code","source":"oil.isnull().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:12.402943Z","iopub.execute_input":"2025-01-17T12:29:12.403409Z","iopub.status.idle":"2025-01-17T12:29:12.412287Z","shell.execute_reply.started":"2025-01-17T12:29:12.403365Z","shell.execute_reply":"2025-01-17T12:29:12.410909Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"oil = oil.sort_values('date').fillna(method='ffill')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:12.413778Z","iopub.execute_input":"2025-01-17T12:29:12.414329Z","iopub.status.idle":"2025-01-17T12:29:12.434857Z","shell.execute_reply.started":"2025-01-17T12:29:12.414281Z","shell.execute_reply":"2025-01-17T12:29:12.433421Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = train_df.merge(oil, on='date', how='left')\ntest_df = test_df.merge(oil, on='date', how='left')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:12.436400Z","iopub.execute_input":"2025-01-17T12:29:12.436864Z","iopub.status.idle":"2025-01-17T12:29:19.355105Z","shell.execute_reply.started":"2025-01-17T12:29:12.436790Z","shell.execute_reply":"2025-01-17T12:29:19.354083Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.isna().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:19.356219Z","iopub.execute_input":"2025-01-17T12:29:19.356518Z","iopub.status.idle":"2025-01-17T12:29:22.967322Z","shell.execute_reply.started":"2025-01-17T12:29:19.356494Z","shell.execute_reply":"2025-01-17T12:29:22.966168Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:22.968384Z","iopub.execute_input":"2025-01-17T12:29:22.968697Z","iopub.status.idle":"2025-01-17T12:29:22.980010Z","shell.execute_reply.started":"2025-01-17T12:29:22.968669Z","shell.execute_reply":"2025-01-17T12:29:22.978716Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Adding holiday days data","metadata":{}},{"cell_type":"code","source":"holiday_events","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:22.981222Z","iopub.execute_input":"2025-01-17T12:29:22.981533Z","iopub.status.idle":"2025-01-17T12:29:23.018445Z","shell.execute_reply.started":"2025-01-17T12:29:22.981507Z","shell.execute_reply":"2025-01-17T12:29:23.017116Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"For now, I'll add only the National holidays because every region of nation would have a holiday on that case. For Regional and Local cases, we should also have to check regions of our data entries so that they will match when joining.\n\nOkay....... You know what? I will add the regional and local cases! Let's achieve the maximum performance!","metadata":{}},{"cell_type":"code","source":"holidays = holiday_events","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:23.019712Z","iopub.execute_input":"2025-01-17T12:29:23.020177Z","iopub.status.idle":"2025-01-17T12:29:23.034649Z","shell.execute_reply.started":"2025-01-17T12:29:23.020134Z","shell.execute_reply":"2025-01-17T12:29:23.033161Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"holiday_counts = holidays['locale'].value_counts()\n\nplt.figure(figsize=(8, 5))\nsns.barplot(x=holiday_counts.index, y=holiday_counts.values, palette=\"viridis\")\n\nplt.title(\"Number of Holidays by Type\", fontsize=16)\nplt.xlabel(\"Holiday Type\", fontsize=14)\nplt.ylabel(\"Count\", fontsize=14)\nplt.xticks(fontsize=12)\nplt.yticks(fontsize=12)\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:23.036064Z","iopub.execute_input":"2025-01-17T12:29:23.036548Z","iopub.status.idle":"2025-01-17T12:29:23.451371Z","shell.execute_reply.started":"2025-01-17T12:29:23.036501Z","shell.execute_reply":"2025-01-17T12:29:23.450249Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"holidays = holiday_events\n\n# national holidays\nholiday_national = holidays[holidays['locale'] == 'National'].copy()\nholiday_national['is_holiday_national'] = 1\nholiday_national = holiday_national[['date', 'is_holiday_national', 'type', 'transferred']]\nholiday_national.rename(columns={'type': 'type_national'}, inplace=True)\n\n# regional holidays\nholiday_regional = holidays[holidays['locale'] == 'Regional'].copy()\nholiday_regional['is_holiday_regional'] = 1\nholiday_regional = holiday_regional[['date', 'locale_name', 'is_holiday_regional', 'type', 'transferred']]\nholiday_regional.rename(columns={'type': 'type_regional'}, inplace=True)\n\n\n# local holidays\nholiday_local = holidays[holidays['locale'] == 'Local'].copy()\nholiday_local['is_holiday_local'] = 1\nholiday_local = holiday_local[['date', 'locale_name', 'is_holiday_local', 'type', 'transferred']]\nholiday_local.rename(columns={'type': 'type_local'}, inplace=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:23.452695Z","iopub.execute_input":"2025-01-17T12:29:23.453178Z","iopub.status.idle":"2025-01-17T12:29:23.469324Z","shell.execute_reply.started":"2025-01-17T12:29:23.453135Z","shell.execute_reply":"2025-01-17T12:29:23.467544Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"holiday_local.rename(columns={'transferred': 'transferred_local'}, inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:23.470698Z","iopub.execute_input":"2025-01-17T12:29:23.471217Z","iopub.status.idle":"2025-01-17T12:29:23.490125Z","shell.execute_reply.started":"2025-01-17T12:29:23.471179Z","shell.execute_reply":"2025-01-17T12:29:23.488856Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"assert(holidays.shape[0] == holiday_national.shape[0] + holiday_regional.shape[0] + holiday_local.shape[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:23.492031Z","iopub.execute_input":"2025-01-17T12:29:23.492523Z","iopub.status.idle":"2025-01-17T12:29:23.509973Z","shell.execute_reply.started":"2025-01-17T12:29:23.492459Z","shell.execute_reply":"2025-01-17T12:29:23.508580Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(holiday_national.dtypes)\nprint(holiday_regional.dtypes)\nprint(holiday_local.dtypes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:23.511098Z","iopub.execute_input":"2025-01-17T12:29:23.511420Z","iopub.status.idle":"2025-01-17T12:29:23.532480Z","shell.execute_reply.started":"2025-01-17T12:29:23.511395Z","shell.execute_reply":"2025-01-17T12:29:23.530947Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# merging local holidays\ntrain_df = train_df.merge(\n    holiday_local, \n    left_on=['date', 'city'],\n    right_on=['date', 'locale_name'],\n    how='left'\n)\ntest_df = test_df.merge(\n    holiday_local, \n    left_on=['date', 'city'],\n    right_on=['date', 'locale_name'],\n    how='left'\n)\ntrain_df['is_holiday_local'] = train_df['is_holiday_local'].fillna(0)\ntest_df['is_holiday_local'] = test_df['is_holiday_local'].fillna(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:23.533731Z","iopub.execute_input":"2025-01-17T12:29:23.534230Z","iopub.status.idle":"2025-01-17T12:29:31.928715Z","shell.execute_reply.started":"2025-01-17T12:29:23.534182Z","shell.execute_reply":"2025-01-17T12:29:31.927393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# merging national holidays\ntrain_df = train_df.merge(holiday_national, on='date', how='left')\ntest_df  = test_df.merge(holiday_national, on='date', how='left')\ntrain_df['is_holiday_national'] = train_df['is_holiday_national'].fillna(0)\ntest_df['is_holiday_national'] = test_df['is_holiday_national'].fillna(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:31.929961Z","iopub.execute_input":"2025-01-17T12:29:31.930301Z","iopub.status.idle":"2025-01-17T12:29:43.721075Z","shell.execute_reply.started":"2025-01-17T12:29:31.930273Z","shell.execute_reply":"2025-01-17T12:29:43.719911Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df[train_df[\"is_holiday_national\"] == 1].shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:43.722082Z","iopub.execute_input":"2025-01-17T12:29:43.722376Z","iopub.status.idle":"2025-01-17T12:29:43.882338Z","shell.execute_reply.started":"2025-01-17T12:29:43.722352Z","shell.execute_reply":"2025-01-17T12:29:43.880992Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# merging regional holidays\ntrain_df = train_df.merge(\n    holiday_regional, \n    left_on=['date', 'state'],\n    right_on=['date', 'locale_name'],\n    how='left'\n)\ntest_df = test_df.merge(\n    holiday_regional, \n    left_on=['date', 'state'],\n    right_on=['date', 'locale_name'],\n    how='left'\n)\n\ntrain_df['is_holiday_regional'] = train_df['is_holiday_regional'].fillna(0)\ntest_df['is_holiday_regional'] = test_df['is_holiday_regional'].fillna(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:29:43.883593Z","iopub.execute_input":"2025-01-17T12:29:43.884064Z","iopub.status.idle":"2025-01-17T12:30:00.591510Z","shell.execute_reply.started":"2025-01-17T12:29:43.884023Z","shell.execute_reply":"2025-01-17T12:30:00.590201Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.dtypes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:00.592742Z","iopub.execute_input":"2025-01-17T12:30:00.593226Z","iopub.status.idle":"2025-01-17T12:30:00.602156Z","shell.execute_reply.started":"2025-01-17T12:30:00.593183Z","shell.execute_reply":"2025-01-17T12:30:00.601114Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# EDA","metadata":{}},{"cell_type":"code","source":"# Average unit sales by state\nstate_sales = train_df.groupby('state')['unit_sales'].mean().reset_index().sort_values(by='unit_sales', ascending=False)\n\nplt.figure(figsize=(10, 6))\nsns.barplot(data=state_sales, x='state', y='unit_sales', palette='coolwarm')\nplt.title('Average Unit Sales by State')\nplt.xlabel('State')\nplt.ylabel('Average Unit Sales')\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:00.603359Z","iopub.execute_input":"2025-01-17T12:30:00.603706Z","iopub.status.idle":"2025-01-17T12:30:02.282198Z","shell.execute_reply.started":"2025-01-17T12:30:00.603671Z","shell.execute_reply":"2025-01-17T12:30:02.280982Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Looking at the chart, I want to classify the states by 3 classes: 0 - Pichincha, 1 - Every other except Pastaza, 2 - Pastaza, because the Pichincha and Pastaza looks like an outliers among all the others. This way I will get more usefull information and also save the memory becaues I don't have to classify each state, but only group them to 3 different classes.","metadata":{}},{"cell_type":"code","source":"# Average unit sales by city\ncity_sales = train_df.groupby('city')['unit_sales'].mean().reset_index().sort_values(by='unit_sales', ascending=False)\n\nplt.figure(figsize=(10, 6))\nsns.barplot(data=city_sales, x='city', y='unit_sales', palette='coolwarm')\nplt.title('Average Unit Sales by City')\nplt.xlabel('City')\nplt.ylabel('Average Unit Sales')\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:02.283614Z","iopub.execute_input":"2025-01-17T12:30:02.284140Z","iopub.status.idle":"2025-01-17T12:30:04.042278Z","shell.execute_reply.started":"2025-01-17T12:30:02.284093Z","shell.execute_reply":"2025-01-17T12:30:04.040974Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Looking at these values, I want to classify the cities again: 0 - Quito, Cayambe, 1 - All the others except Riobamba, Salinas, Santa Dormingo, Ibarra, Playas, Latacunga, Puyo, 2 - Riobamba, Salinas, Santa Dormingo, Ibarra, Playas, Latacunga, Puyo.","metadata":{}},{"cell_type":"code","source":"state_mapping = {\n    'Pichincha': 0,\n    'Pastaza': 2\n}\n\ncity_mapping = {\n    'Quito': 0,\n    'Cayambe': 0,\n    'Riobamba': 2,\n    'Salinas': 2,\n    'Santa Dormingo': 2,\n    'Ibarra': 2,\n    'Playas': 2,\n    'Latacunga': 2,\n    'Puyo': 2\n}\n\ntrain_df['state'] = train_df['state'].astype('category')\ntest_df['state'] = test_df['state'].astype('category')\n\ntrain_df['city'] = train_df['city'].astype('category')\ntest_df['city'] = test_df['city'].astype('category')\n\ntrain_df['state_class'] = train_df['state'].map(state_mapping).fillna(1).astype('uint8')\ntest_df['state_class'] = test_df['state'].map(state_mapping).fillna(1).astype('uint8')\n\ntrain_df['city_class'] = train_df['city'].map(city_mapping).fillna(1).astype('uint8')\ntest_df['city_class'] = test_df['city'].map(city_mapping).fillna(1).astype('uint8')\n\ntrain_df.drop(columns=['state', 'city'], inplace=True)\ntest_df.drop(columns=['state', 'city'], inplace=True)\n\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:04.043617Z","iopub.execute_input":"2025-01-17T12:30:04.043987Z","iopub.status.idle":"2025-01-17T12:30:11.433394Z","shell.execute_reply.started":"2025-01-17T12:30:04.043956Z","shell.execute_reply":"2025-01-17T12:30:11.432167Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Feature Engineering","metadata":{}},{"cell_type":"markdown","source":"Creating a single class which will useful information from date field such as year, month, day etc. and also whether it is working or weekend days.","metadata":{}},{"cell_type":"code","source":"train_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:11.440440Z","iopub.execute_input":"2025-01-17T12:30:11.440901Z","iopub.status.idle":"2025-01-17T12:30:11.466690Z","shell.execute_reply.started":"2025-01-17T12:30:11.440862Z","shell.execute_reply":"2025-01-17T12:30:11.465406Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"But before, I want to delete some non-useful columns!","metadata":{}},{"cell_type":"code","source":"drop_columns = ['locale_name_x', 'locale_name_y', 'transferred_local', 'transferred_x', 'transferred_y', 'type_local', 'type_national', 'type_regional', 'id', 'Unnamed: 0']\n\ntrain_df.drop(columns=drop_columns, inplace=True)\ntest_df.drop(columns=drop_columns, inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:11.469110Z","iopub.execute_input":"2025-01-17T12:30:11.469441Z","iopub.status.idle":"2025-01-17T12:30:12.944598Z","shell.execute_reply.started":"2025-01-17T12:30:11.469412Z","shell.execute_reply":"2025-01-17T12:30:12.943317Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:12.945916Z","iopub.execute_input":"2025-01-17T12:30:12.946356Z","iopub.status.idle":"2025-01-17T12:30:13.080666Z","shell.execute_reply.started":"2025-01-17T12:30:12.946320Z","shell.execute_reply":"2025-01-17T12:30:13.079327Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:13.081914Z","iopub.execute_input":"2025-01-17T12:30:13.082376Z","iopub.status.idle":"2025-01-17T12:30:13.112510Z","shell.execute_reply.started":"2025-01-17T12:30:13.082332Z","shell.execute_reply":"2025-01-17T12:30:13.111391Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Defining our own class to extract useful date information","metadata":{}},{"cell_type":"code","source":"class DateFeatureExtractor(BaseEstimator, TransformerMixin):\n    def __init__(self, date_col='date'):\n        self.date_col = date_col\n\n    def fit(self, X, y=None):\n        return self\n\n    def transform(self, X):\n        X = X.copy()\n        X[self.date_col] = pd.to_datetime(X[self.date_col])\n        X['year'] = X[self.date_col].dt.year\n        X['month'] = X[self.date_col].dt.month\n        X['day'] = X[self.date_col].dt.day\n        X['day_of_week'] = X[self.date_col].dt.dayofweek\n        X['day_of_year'] = X[self.date_col].dt.dayofyear\n        X['is_weekend'] = (X[self.date_col].dt.dayofweek >= 5).astype('uint8')\n        X.drop(columns=[self.date_col], inplace=True)\n        return X\n\n    def get_feature_names_out(self, input_features=None):\n        return ['year', 'month', 'day', 'day_of_week', 'day_of_year', 'is_weekend']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:13.113580Z","iopub.execute_input":"2025-01-17T12:30:13.113900Z","iopub.status.idle":"2025-01-17T12:30:13.133714Z","shell.execute_reply.started":"2025-01-17T12:30:13.113872Z","shell.execute_reply":"2025-01-17T12:30:13.132457Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Preparing our data","metadata":{}},{"cell_type":"code","source":"X_train = train_df.drop(columns=['unit_sales'])\ny_train = train_df['unit_sales']\n\nX_val = test_df.drop(columns=['unit_sales'])\ny_val = test_df['unit_sales']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:13.135344Z","iopub.execute_input":"2025-01-17T12:30:13.135775Z","iopub.status.idle":"2025-01-17T12:30:14.572923Z","shell.execute_reply.started":"2025-01-17T12:30:13.135730Z","shell.execute_reply":"2025-01-17T12:30:14.571567Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train.dtypes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:14.574146Z","iopub.execute_input":"2025-01-17T12:30:14.574480Z","iopub.status.idle":"2025-01-17T12:30:14.582544Z","shell.execute_reply.started":"2025-01-17T12:30:14.574450Z","shell.execute_reply":"2025-01-17T12:30:14.581198Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def convert_categorical_features(df: pd.DataFrame, cat_cols: list) -> pd.DataFrame:\n    for col in cat_cols:\n        if pd.api.types.is_numeric_dtype(df[col]):\n            df[col] = df[col].fillna(-1)\n        else:\n            df[col] = df[col].fillna(\"missing\")\n        \n        if pd.api.types.is_integer_dtype(df[col]) or pd.api.types.is_string_dtype(df[col]):\n            continue\n        \n        if pd.api.types.is_float_dtype(df[col]):\n            all_integers = df[col].apply(lambda x: x.is_integer() if not pd.isna(x) else True).all()\n            if all_integers:\n                df[col] = df[col].astype('uint16')\n            else:\n                df[col] = df[col].astype(str)\n        else:\n            df[col] = df[col].astype(str)\n    \n    return df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:14.583732Z","iopub.execute_input":"2025-01-17T12:30:14.584285Z","iopub.status.idle":"2025-01-17T12:30:14.600580Z","shell.execute_reply.started":"2025-01-17T12:30:14.584248Z","shell.execute_reply":"2025-01-17T12:30:14.599196Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# dropping train and test data becaues I have no memory...\ndel train_df\ndel test_df\n\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:14.601971Z","iopub.execute_input":"2025-01-17T12:30:14.602337Z","iopub.status.idle":"2025-01-17T12:30:14.839461Z","shell.execute_reply.started":"2025-01-17T12:30:14.602297Z","shell.execute_reply":"2025-01-17T12:30:14.837707Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"numerical_features = [\n    'store_nbr', 'item_nbr', 'dcoilwtico', \n    'year','month','day','day_of_week','day_of_year' \n    # these ones will be added after date extracting in pipeline\n]\n\ncategorical_features = [\n    'onpromotion', 'family', 'class', 'state_class', 'city_class', 'type',\n    'is_holiday_local', 'is_holiday_national', 'is_holiday_regional',\n    'cluster', 'perishable',\n    'is_weekend' # this one will be added after date extracting in pipeline\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:14.840962Z","iopub.execute_input":"2025-01-17T12:30:14.841427Z","iopub.status.idle":"2025-01-17T12:30:14.856848Z","shell.execute_reply.started":"2025-01-17T12:30:14.841373Z","shell.execute_reply":"2025-01-17T12:30:14.855575Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train = convert_categorical_features(X_train, categorical_features[:-1])\nX_val = convert_categorical_features(X_val, categorical_features[:-1])\n\ngc.collect()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:30:14.858216Z","iopub.execute_input":"2025-01-17T12:30:14.858540Z","iopub.status.idle":"2025-01-17T12:31:11.901689Z","shell.execute_reply.started":"2025-01-17T12:30:14.858512Z","shell.execute_reply":"2025-01-17T12:31:11.900406Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Creating a pipeline for data preprocessing and model fitting","metadata":{}},{"cell_type":"code","source":"numeric_transformer = Pipeline(\n    steps=[\n        ('imputer', SimpleImputer(strategy='constant', fill_value=0)),\n        ('scaler', StandardScaler())\n    ]\n)\n\ncategorical_transformer = Pipeline(\n    steps=[\n        ('imputer', SimpleImputer(strategy='constant', fill_value='missing')),\n        ('encoder', OneHotEncoder(handle_unknown='ignore'))\n    ]\n)\n\npreprocessor = ColumnTransformer(\n    transformers=[\n        ('num', numeric_transformer, numerical_features),\n        ('cat', categorical_transformer, categorical_features)\n    ],\n    remainder='drop'\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:11.902914Z","iopub.execute_input":"2025-01-17T12:31:11.903251Z","iopub.status.idle":"2025-01-17T12:31:11.909478Z","shell.execute_reply.started":"2025-01-17T12:31:11.903221Z","shell.execute_reply":"2025-01-17T12:31:11.908035Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Creating a pipeline for Dummy Regressor","metadata":{}},{"cell_type":"code","source":"model_dummy = DummyRegressor(strategy='mean')\n\npipeline_dummy = Pipeline([\n    ('date_feats', DateFeatureExtractor(date_col='date')),\n    ('preprocessor', preprocessor),\n    ('regressor', model_dummy)\n])\n\n# handling cases where log function takes negative or zero values\ndef safe_log1p(x):\n    return np.log1p(np.clip(x, 1e-15, None))\n\ndef safe_expm1(x):\n    return np.expm1(np.clip(x, None, 709))\n\n# wrapping with log transform\npipeline_dummy = TransformedTargetRegressor(\n    regressor=pipeline_dummy,\n    func=safe_log1p,\n    inverse_func=safe_expm1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:11.910761Z","iopub.execute_input":"2025-01-17T12:31:11.911286Z","iopub.status.idle":"2025-01-17T12:31:11.930710Z","shell.execute_reply.started":"2025-01-17T12:31:11.911241Z","shell.execute_reply":"2025-01-17T12:31:11.929426Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Creating a pipeline for LGB Regressor","metadata":{}},{"cell_type":"code","source":"model_lgb = LGBMRegressor(\n    n_estimators=200,\n    learning_rate=0.1,\n    num_leaves=31,\n    random_state=42\n)\n\npipeline_lgb = Pipeline([\n    ('date_feats', DateFeatureExtractor(date_col='date')),\n    ('preprocessor', preprocessor),\n    ('regressor', model_lgb)\n])\n\n# wrapping with log transformer on target field\npipeline_lgb = TransformedTargetRegressor(\n    regressor=pipeline_lgb,\n    func=safe_log1p,\n    inverse_func=safe_expm1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:11.932206Z","iopub.execute_input":"2025-01-17T12:31:11.932971Z","iopub.status.idle":"2025-01-17T12:31:11.955565Z","shell.execute_reply.started":"2025-01-17T12:31:11.932918Z","shell.execute_reply":"2025-01-17T12:31:11.954142Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Creating a pipeline for CatBoostRegression","metadata":{}},{"cell_type":"code","source":"preprocessor_cat = ColumnTransformer(\n    transformers=[\n        ('num', numeric_transformer, numerical_features)\n    ],\n    remainder='passthrough'\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:11.956908Z","iopub.execute_input":"2025-01-17T12:31:11.957327Z","iopub.status.idle":"2025-01-17T12:31:11.981600Z","shell.execute_reply.started":"2025-01-17T12:31:11.957285Z","shell.execute_reply":"2025-01-17T12:31:11.980393Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"feature_extraction_pipeline = Pipeline([\n    ('date_feats', DateFeatureExtractor(date_col='date')),\n    ('preprocessor', preprocessor_cat)\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:11.982731Z","iopub.execute_input":"2025-01-17T12:31:11.983147Z","iopub.status.idle":"2025-01-17T12:31:12.000098Z","shell.execute_reply.started":"2025-01-17T12:31:11.983117Z","shell.execute_reply":"2025-01-17T12:31:11.998896Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_temp = feature_extraction_pipeline.named_steps['date_feats'].transform(X_train.head())\nfeature_extraction_pipeline.named_steps['preprocessor'].fit(X_temp)\ncol_names_for_preprocessor = X_temp.columns\nfeature_names = feature_extraction_pipeline.named_steps['preprocessor'].get_feature_names_out(col_names_for_preprocessor)\n\ncategorical_indices = [i for i, feature in enumerate(feature_names) \n                      if any(cat_feat in feature for cat_feat in categorical_features)]\n\nprint(\"Categorical feature indices:\", categorical_indices)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:12.001434Z","iopub.execute_input":"2025-01-17T12:31:12.001851Z","iopub.status.idle":"2025-01-17T12:31:12.038742Z","shell.execute_reply.started":"2025-01-17T12:31:12.001789Z","shell.execute_reply":"2025-01-17T12:31:12.037290Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_cat = CatBoostRegressor(\n    iterations=250,\n    learning_rate=0.1,\n    random_seed=42,\n    cat_features=categorical_indices,\n    verbose=False\n)\n\npipeline_cat = Pipeline([\n    ('date_feats', DateFeatureExtractor(date_col='date')),\n    ('preprocessor', preprocessor_cat),\n    ('regressor', model_cat)\n])\n\npipeline_cat = TransformedTargetRegressor(\n    regressor=pipeline_cat,\n    func=safe_log1p,\n    inverse_func=safe_expm1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:12.040049Z","iopub.execute_input":"2025-01-17T12:31:12.040470Z","iopub.status.idle":"2025-01-17T12:31:12.062177Z","shell.execute_reply.started":"2025-01-17T12:31:12.040434Z","shell.execute_reply":"2025-01-17T12:31:12.060776Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Fitting our Dummy Pipeline","metadata":{}},{"cell_type":"code","source":"pipeline_dummy.fit(X_train, y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T12:31:12.063649Z","iopub.execute_input":"2025-01-17T12:31:12.064146Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Fitting our LGB Pipeline","metadata":{}},{"cell_type":"code","source":"pipeline_lgb.fit(X_train, y_train)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Fitting our Cat Pipeline","metadata":{}},{"cell_type":"markdown","source":"#### Was unable to fit the Cat model because of memory insufficiency.","metadata":{}},{"cell_type":"code","source":"# pipeline_cat.fit(X_train, y_train)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Predicting on DummyRegressor","metadata":{}},{"cell_type":"code","source":"dummy_val_preds = pipeline_dummy.predict(X_val)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Predicting on LGBMRegressor","metadata":{}},{"cell_type":"code","source":"lgb_val_preds = pipeline_lgb.predict(X_val)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Predicting on CatRegressor (Again, was unable to train)","metadata":{}},{"cell_type":"code","source":"# cat_val_preds = pipeline_cat.predict(X_val)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Scoring","metadata":{}},{"cell_type":"code","source":"def nwrmsle(y_true, y_pred, weights):\n    # ensuring no negative predictions are seen\n    y_pred = np.clip(y_pred, a_min=0, a_max=None)\n    y_true = np.clip(y_true, a_min=0, a_max=None)\n    \n    log_diff = np.log1p(y_pred) - np.log1p(y_true)\n    weighted_squared_log_diff = weights * (log_diff ** 2)\n    score = np.sqrt(np.sum(weighted_squared_log_diff) / np.sum(weights))\n    \n    return score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T09:50:11.929616Z","iopub.execute_input":"2025-01-17T09:50:11.930316Z","iopub.status.idle":"2025-01-17T09:50:11.940112Z","shell.execute_reply.started":"2025-01-17T09:50:11.930254Z","shell.execute_reply":"2025-01-17T09:50:11.938398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"perishable_weights_val = np.where(X_val['perishable'] == 1, 1.25, 1.00)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T09:50:13.257330Z","iopub.execute_input":"2025-01-17T09:50:13.257927Z","iopub.status.idle":"2025-01-17T09:50:13.285046Z","shell.execute_reply.started":"2025-01-17T09:50:13.257873Z","shell.execute_reply":"2025-01-17T09:50:13.283035Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### DummyRegressor Scoring","metadata":{}},{"cell_type":"code","source":"dummy_val_score = nwrmsle(y_val.values, dummy_val_preds, perishable_weights_val)\nprint(\"Dummy NWRMSLE Score:\", dummy_val_score)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T09:50:15.129311Z","iopub.execute_input":"2025-01-17T09:50:15.129863Z","iopub.status.idle":"2025-01-17T09:50:15.323506Z","shell.execute_reply.started":"2025-01-17T09:50:15.129811Z","shell.execute_reply":"2025-01-17T09:50:15.321670Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### LGBMRegressor Scoring","metadata":{}},{"cell_type":"code","source":"lgb_val_score = nwrmsle(y_val.values, lgb_val_preds, perishable_weights_val)\nprint(\"LGB NWRMSLE Score:\", lgb_val_score)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T09:50:17.601332Z","iopub.execute_input":"2025-01-17T09:50:17.601920Z","iopub.status.idle":"2025-01-17T09:50:17.777078Z","shell.execute_reply.started":"2025-01-17T09:50:17.601867Z","shell.execute_reply":"2025-01-17T09:50:17.775366Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Conclusion","metadata":{}},{"cell_type":"markdown","source":"Overall, the experience while doing this assignment was not the best one becaues of memory issues. I wasn't able to train the models on whole dataset and even so, the memory usage was on its peak and near reaching its limits and crashing. CatRegression used too much memory to fit the model, while regular dummy regressor and LGB regressor used not too much memory and their training was successful (lgb one because its efficient memory usage). \n\nOverall, I was unable to do \"proper\" hyper parameter tuning on LGBM becuase of again memory issues, however when restarting my sessions I tried differet parameters and the ones you can see on the final model are the \"best\" ones I was able to find using my own hands and repetitions.\n\nI've achieved nwrmsle scoring of ~0.88 on Dummy Regressor and of ~0.71 on LGB Regressor. So, the performance boost of using the LGB one we can see clearly compared to Dummy one.","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}