{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.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":9994,"databundleVersionId":752467,"sourceType":"competition"}],"dockerImageVersionId":31234,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"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\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\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\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(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":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:45:56.550203Z","iopub.execute_input":"2025-12-20T23:45:56.550562Z","iopub.status.idle":"2025-12-20T23:45:58.236099Z","shell.execute_reply.started":"2025-12-20T23:45:56.550522Z","shell.execute_reply":"2025-12-20T23:45:58.234982Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom sklearn.ensemble import IsolationForest\nDATA_PATH = \"/kaggle/input/ashrae-energy-prediction/\"\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:45:58.237354Z","iopub.execute_input":"2025-12-20T23:45:58.237893Z","iopub.status.idle":"2025-12-20T23:46:01.174613Z","shell.execute_reply.started":"2025-12-20T23:45:58.237850Z","shell.execute_reply":"2025-12-20T23:46:01.173369Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"building = pd.read_csv(DATA_PATH + \"building_metadata.csv\")\nweather = pd.read_csv(DATA_PATH + \"weather_train.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:01.176879Z","iopub.execute_input":"2025-12-20T23:46:01.177518Z","iopub.status.idle":"2025-12-20T23:46:01.469494Z","shell.execute_reply.started":"2025-12-20T23:46:01.177486Z","shell.execute_reply":"2025-12-20T23:46:01.468428Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"chunksize = 1_000_000\ntrain_chunks = pd.read_csv(\n    DATA_PATH + \"train.csv\",\n    chunksize=chunksize\n)\n\nsample_list = []\n\nfor chunk in train_chunks:\n    # Électricité uniquement\n    chunk = chunk[chunk[\"meter\"] == 0]\n\n    # Jointure pour filtrer Office\n    chunk = chunk.merge(\n        building[[\"building_id\", \"primary_use\"]],\n        on=\"building_id\",\n        how=\"left\"\n    )\n    chunk = chunk[chunk[\"primary_use\"] == \"Office\"]\n\n    # Échantillon 1 %\n    if len(chunk) > 0:\n        chunk = chunk.sample(frac=0.01, random_state=42)\n        sample_list.append(chunk)\n\ntrain = pd.concat(sample_list, ignore_index=True)\nprint(\"Dataset après échantillonnage :\", train.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:01.470731Z","iopub.execute_input":"2025-12-20T23:46:01.471068Z","iopub.status.idle":"2025-12-20T23:46:18.479714Z","shell.execute_reply.started":"2025-12-20T23:46:01.471033Z","shell.execute_reply":"2025-12-20T23:46:18.478502Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"chunksize = 1_000_000\ntrain_chunks = pd.read_csv(\n    DATA_PATH + \"train.csv\",\n    chunksize=chunksize\n)\n\nsample_list = []\n\nfor chunk in train_chunks:\n    # Électricité uniquement\n    chunk = chunk[chunk[\"meter\"] == 0]\n\n    # Merge CORRIGÉ avec site_id\n    chunk = chunk.merge(\n        building[[\"building_id\", \"site_id\", \"primary_use\"]],\n        on=\"building_id\",\n        how=\"left\"\n    )\n\n    # Filtrer bureaux\n    chunk = chunk[chunk[\"primary_use\"] == \"Office\"]\n\n    # Échantillon 1 %\n    if len(chunk) > 0:\n        chunk = chunk.sample(frac=0.01, random_state=42)\n        sample_list.append(chunk)\n\ntrain = pd.concat(sample_list, ignore_index=True)\nprint(\"Colonnes disponibles :\", train.columns)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:18.481634Z","iopub.execute_input":"2025-12-20T23:46:18.482139Z","iopub.status.idle":"2025-12-20T23:46:30.172642Z","shell.execute_reply.started":"2025-12-20T23:46:18.482099Z","shell.execute_reply":"2025-12-20T23:46:30.171462Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = train.merge(\n    weather,\n    on=[\"site_id\", \"timestamp\"],\n    how=\"left\"\n)\n\nprint(\"Colonnes après merge météo :\")\nprint(train.columns)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:30.173996Z","iopub.execute_input":"2025-12-20T23:46:30.174361Z","iopub.status.idle":"2025-12-20T23:46:30.229748Z","shell.execute_reply.started":"2025-12-20T23:46:30.174332Z","shell.execute_reply":"2025-12-20T23:46:30.228798Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"weather[\"timestamp\"] = pd.to_datetime(weather[\"timestamp\"])\ntrain[\"timestamp\"] = pd.to_datetime(train[\"timestamp\"])\n\ntrain[\"hour\"] = train[\"timestamp\"].dt.hour\ntrain[\"weekday\"] = train[\"timestamp\"].dt.weekday\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:30.231009Z","iopub.execute_input":"2025-12-20T23:46:30.231368Z","iopub.status.idle":"2025-12-20T23:46:30.299541Z","shell.execute_reply.started":"2025-12-20T23:46:30.231340Z","shell.execute_reply":"2025-12-20T23:46:30.298443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Simulation occupancy\ndef simulate_occupancy(row):\n    if row[\"weekday\"] >= 5:  # week-end\n        return 0\n    elif 8 <= row[\"hour\"] < 12 or 13 <= row[\"hour\"] < 18:\n        return 1\n    else:\n        return 0\n\ntrain[\"occupancy\"] = train.apply(simulate_occupancy, axis=1)\n\n# Bruit capteur (10%)\nnoise = np.random.choice([0, 1], size=len(train), p=[0.1, 0.9])\ntrain[\"occupancy\"] = train[\"occupancy\"] * noise\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:30.300878Z","iopub.execute_input":"2025-12-20T23:46:30.301140Z","iopub.status.idle":"2025-12-20T23:46:30.519095Z","shell.execute_reply.started":"2025-12-20T23:46:30.301117Z","shell.execute_reply":"2025-12-20T23:46:30.518040Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[\"air_temperature\"] = train[\"air_temperature\"].fillna(\n    train[\"air_temperature\"].mean()\n)\n\ntrain[\"meter_reading\"] = train[\"meter_reading\"].fillna(0)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:30.522365Z","iopub.execute_input":"2025-12-20T23:46:30.522698Z","iopub.status.idle":"2025-12-20T23:46:30.531381Z","shell.execute_reply.started":"2025-12-20T23:46:30.522669Z","shell.execute_reply":"2025-12-20T23:46:30.530251Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = train[\n    [\"meter_reading\", \"air_temperature\", \"hour\"]\n]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:30.532680Z","iopub.execute_input":"2025-12-20T23:46:30.533022Z","iopub.status.idle":"2025-12-20T23:46:30.552872Z","shell.execute_reply.started":"2025-12-20T23:46:30.532995Z","shell.execute_reply":"2025-12-20T23:46:30.551625Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"features = [\"meter_reading\", \"air_temperature\", \"hour\"]\nX = train[features]\n\nfrom sklearn.preprocessing import StandardScaler\n\nscaler = StandardScaler()\nX_scaled = pd.DataFrame(\n    scaler.fit_transform(X),\n    columns=features,\n    index=train.index\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:30.554579Z","iopub.execute_input":"2025-12-20T23:46:30.555050Z","iopub.status.idle":"2025-12-20T23:46:30.579692Z","shell.execute_reply.started":"2025-12-20T23:46:30.555011Z","shell.execute_reply":"2025-12-20T23:46:30.578562Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings(\"ignore\", category=UserWarning)\n\n\nfrom sklearn.ensemble import IsolationForest\nfrom sklearn.preprocessing import StandardScaler\n\nfeatures = [\"meter_reading\", \"air_temperature\", \"hour\"]\n\n# Sélection features\nX = train[features]\n\n# Normalisation\nscaler = StandardScaler()\nX_scaled = pd.DataFrame(\n    scaler.fit_transform(X),\n    columns=features,\n    index=train.index\n)\n\n# Modèle non supervisé\niso = IsolationForest(\n    n_estimators=100,\n    contamination=0.05,\n    random_state=42\n)\n\n# FIT + PREDICT ENSEMBLE (clé pour éviter le warning)\ntrain[\"anomaly\"] = iso.fit_predict(X_scaled)\n\n# Conversion labels\ntrain[\"anomaly\"] = train[\"anomaly\"].map({1: 0, -1: 1})\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:30.580848Z","iopub.execute_input":"2025-12-20T23:46:30.581118Z","iopub.status.idle":"2025-12-20T23:46:31.155447Z","shell.execute_reply.started":"2025-12-20T23:46:30.581085Z","shell.execute_reply":"2025-12-20T23:46:31.154385Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[\"anomaly\"].value_counts(normalize=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:31.156821Z","iopub.execute_input":"2025-12-20T23:46:31.157421Z","iopub.status.idle":"2025-12-20T23:46:31.171845Z","shell.execute_reply.started":"2025-12-20T23:46:31.157225Z","shell.execute_reply":"2025-12-20T23:46:31.170756Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[\"waste\"] = (\n    (train[\"anomaly\"] == 1) & \n    (train[\"occupancy\"] == 0)\n).astype(int)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:31.173554Z","iopub.execute_input":"2025-12-20T23:46:31.173964Z","iopub.status.idle":"2025-12-20T23:46:31.191703Z","shell.execute_reply.started":"2025-12-20T23:46:31.173881Z","shell.execute_reply":"2025-12-20T23:46:31.190437Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"total_kwh = train[\"meter_reading\"].sum()\nwasted_kwh = train.loc[train[\"waste\"] == 1, \"meter_reading\"].sum()\nsaving_pct = (wasted_kwh / total_kwh) * 100\n\nprint(f\"Consommation totale : {total_kwh:.2f} kWh\")\nprint(f\"Gaspillage détecté : {wasted_kwh:.2f} kWh\")\nprint(f\"Économie potentielle : {saving_pct:.2f} %\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:31.193096Z","iopub.execute_input":"2025-12-20T23:46:31.193568Z","iopub.status.idle":"2025-12-20T23:46:31.211883Z","shell.execute_reply.started":"2025-12-20T23:46:31.193537Z","shell.execute_reply":"2025-12-20T23:46:31.210736Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# -------------------------------\n# 🔹 1️⃣ Copier la consommation actuelle\n# -------------------------------\ntrain[\"optimized_reading\"] = train[\"meter_reading\"].copy()\n\n# -------------------------------\n# 🔹 2️⃣ Règle 1 : éteindre clim/lumière si salle vide\n# -------------------------------\ntrain.loc[train[\"occupancy\"]==0, \"optimized_reading\"] *= 0.5\n# On simule qu’on économise 50% si salle vide\n\n# -------------------------------\n# 🔹 3️⃣ Règle 2 : réduire consommation si température confortable\n# Température confortable : 20°C à 24°C\n# -------------------------------\nmask_comfort = (train[\"air_temperature\"] >= 20) & (train[\"air_temperature\"] <= 24)\ntrain.loc[mask_comfort, \"optimized_reading\"] *= 0.8\n# On simule 20% économie si température confortable\n\n# -------------------------------\n# 🔹 4️⃣ Calcul KPI consommation optimisée\n# -------------------------------\noptimized_total = train[\"optimized_reading\"].sum()\noptimized_saving = total_kwh - optimized_total\noptimized_saving_pct = (optimized_saving / total_kwh) * 100\n\nprint(f\"Consommation totale avant optimisation : {total_kwh:.2f} kWh\")\nprint(f\"Consommation totale après optimisation : {optimized_total:.2f} kWh\")\nprint(f\"Économie potentielle : {optimized_saving_pct:.2f} %\")\n\n# -------------------------------\n# 🔹 5️⃣ Visualisation comparaison\n# -------------------------------\nplt.figure(figsize=(12,5))\nplt.plot(train[\"timestamp\"], train[\"meter_reading\"], label=\"Consommation réelle\")\nplt.plot(train[\"timestamp\"], train[\"optimized_reading\"], label=\"Consommation optimisée\", alpha=0.8)\nplt.scatter(\n    train.loc[train[\"waste\"]==1, \"timestamp\"],\n    train.loc[train[\"waste\"]==1, \"meter_reading\"],\n    color=\"red\", s=10, label=\"Gaspillage détecté\"\n)\nplt.legend()\nplt.title(\"Optimisation automatique de la consommation énergétique\")\nplt.xlabel(\"Temps\")\nplt.ylabel(\"kWh\")\nplt.show()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:31.213766Z","iopub.execute_input":"2025-12-20T23:46:31.214160Z","iopub.status.idle":"2025-12-20T23:46:32.002486Z","shell.execute_reply.started":"2025-12-20T23:46:31.214105Z","shell.execute_reply":"2025-12-20T23:46:32.001285Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Sauvegarder le DataFrame préparé pour le dashboard\ntrain.to_csv(\"/kaggle/working/train_prepared.csv\", index=False)\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:46:32.004664Z","iopub.execute_input":"2025-12-20T23:46:32.004982Z","iopub.status.idle":"2025-12-20T23:46:32.300733Z","shell.execute_reply.started":"2025-12-20T23:46:32.004951Z","shell.execute_reply":"2025-12-20T23:46:32.299582Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import joblib\n\n# Sauvegarder\njoblib.dump(iso, \"energy_model.pkl\")\n\n# Recharger\nenergy_model = joblib.load(\"energy_model.pkl\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T23:48:07.201883Z","iopub.execute_input":"2025-12-20T23:48:07.202328Z","iopub.status.idle":"2025-12-20T23:48:07.290811Z","shell.execute_reply.started":"2025-12-20T23:48:07.202282Z","shell.execute_reply":"2025-12-20T23:48:07.289798Z"}},"outputs":[],"execution_count":null}]}