diff --git a/Groundwater Arsenic Content Detection/README.md b/Groundwater Arsenic Content Detection/README.md new file mode 100644 index 000000000..095d5e710 --- /dev/null +++ b/Groundwater Arsenic Content Detection/README.md @@ -0,0 +1,131 @@ +Groundwater Arsenic Content Detection + +🎯 Goal +To develop an accurate prediction model for arsenic contamination in groundwater using a hybrid approach that combines Artificial Neural Networks (ANN) with the Whale Optimization Algorithm (WOA) and also using third method random forest classifier. This project aims to help water management authorities and public health officials identify potential arsenic contamination risks before they pose a threat to human health. + +🧵 Dataset +The dataset contains groundwater quality parameters collected from various locations, including: + +Arsenic concentration levels +Environmental parameters +Geological factors +Chemical composition indicators + +🧾 Description +This project addresses the critical issue of arsenic contamination in groundwater through advanced machine learning techniques. By combining the predictive power of Backpropagation Neural Networks (BPNN) with the optimization capabilities of the Whale Optimization Algorithm (WOA), we create a robust system for predicting arsenic levels in groundwater. This hybrid approach allows for better understanding of the complex relationships between environmental factors and arsenic contamination. + +🧮 What I had done! + +Data Collection and Preprocessing + +Gathered groundwater quality parameters from various locations +Performed data cleaning and handled missing values +Normalized the data for better model performance +Split the dataset into training and testing sets + + +Model Development + +Implemented BPNN architecture +Integrated WOA for neural network optimization +Fine-tuned hyperparameters for both algorithms +Implemented random forest classifier + + +Model Evaluation + +Conducted performance analysis using multiple metrics +Compared BPNN and WOA-optimized results +Analyzed feature importance + + +Visualization and Reporting + +Created visualizations for data analysis +Generated performance comparison charts +Documented findings and recommendations + + + +🚀 Models Implemented + +Backpropagation Neural Network (BPNN) + +Chosen for its ability to learn complex patterns in data +Effective for regression problems +Capable of handling multiple input parameters + + +Whale Optimization Algorithm (WOA) + +Selected for its proven optimization capabilities +Helps avoid local optima problems +Efficient in optimizing neural network weights and biases + + +Hybrid BPNN-WOA Model + +Combines the strengths of both algorithms +Improves prediction accuracy +Reduces overfitting risks + +Random Forest Classifier +Another algorith with good accuracy to check the groundwater quality. + +📚 Libraries Needed + +TensorFlow/Keras (Neural Network Implementation) +NumPy (Numerical Computations) +Pandas (Data Manipulation) +Scikit-learn (Model Evaluation) +Matplotlib (Visualization) +SciPy (Scientific Computing) + +📊 Exploratory Data Analysis Results +![RMSE Graph](https://github.com/user-attachments/assets/00e3cecb-af37-428b-b00d-6d6b4c3e5b19) +![Loss and accuracy](https://github.com/user-attachments/assets/ffc4b37e-f58d-4d20-b1a9-b0a213514d61) + + +Correlation matrix of features +Distribution of arsenic levels +Geographical distribution of sampling points +Feature importance plots +Model performance comparisons + +📈 Performance of the Models based on the Accuracy Scores + +ANN Model: + +Mean Squared Error (MSE): 0.14 +Accuracy:72.97 +Root Mean Squared Error (RMSE): 0.38 + + +WOA-Optimized ANN: + +Mean Squared Error (MSE): 0.12 +Accuracy: 83.78 +Root Mean Squared Error (RMSE): 0.32 + +Rainforest Classifier: + +Mean Squared Error (MSE): 0.20 +Root Mean Squared Error (RMSE): 0.50 + + +📢 Conclusion +The hybrid BPNN-WOA approach demonstrates superior performance in predicting groundwater arsenic levels compared to traditional methods. Key findings include: + +Improved prediction accuracy by 13% using the hybrid approach +Identification of key environmental factors influencing arsenic levels +Potential for real-world application in water quality monitoring +Recommendation for implementation in groundwater management systems + +✒️ Your Signature +Stuti Sharma + +GitHub: https://github.com/Stuti333 + +LinkedIn: https://www.linkedin.com/in/stuti-sharma-94057122b/ + +Email: stutiemailbox@gmail.com diff --git a/Groundwater Arsenic Content Detection/data/Ground Water .csv b/Groundwater Arsenic Content Detection/data/Ground Water .csv new file mode 100644 index 000000000..2bd5fc86c --- /dev/null +++ b/Groundwater Arsenic Content Detection/data/Ground Water .csv @@ -0,0 +1,134 @@ +Station Code,Station Name,STATE,Temperature Min,Temperature Max,pH Min,pH Max,Conductivity (µmhos/cm) Min,Conductivity (µmhos/cm) Max,BOD min(mg/L),BOD max(mg/L),Nitrate N min(mg/L),NitrateN max(mg/L) ,Faecal Coliform min (MPN/100ml),Faecal Coliform max(MPN/100ml),Total Coliformmin (MPN/100ml),Total Coliform max (MPN/100ml),Total Dissolved Solidsmin (mg/L),Total Dissolved Solids max(mg/L),Fluoride min(mg/L),Fluoride max (mg/L),Arsenic min (mg/L),Arsenic max (mg/L),Average arsenic(mg/L) +3093,"BORE WELL AT ALLADAPALEM +VILLAGE, PYDIBHIMAVARAM",ANDHRA PRADESH,29,30,7.3,7.4,840,1481,2,2.1,0.9,16.75,2,4,64,75,584,980,0.4,0.8,0.001,0.001,0.001 +3092,"BORE WELL AT ARINAMA +AKKIVALASA, SRIKAKULAM",ANDHRA PRADESH,28,31,7.4,8.1,712,1139,2,2.4,0.9,7.95,3,4,64,75,492,754,1,1.1,0.001,0.001,0.001 +4360,"BORE WELL AT IDA, +RAMANAYYAPETA, KKAINADA",ANDHRA PRADESH,27,29,7.7,7.8,990,1280,1.8,2,1,3.48,2,7,75,93,660,868,0.4,0.4,0.007,0.009,0.005 +3091,"BORE WELL AT KAPULUPPADA +DUMPSITE, VISHAKHAPATNAM",ANDHRA PRADESH,26,26,7,7.1,3340,4260,2.2,3.6,4.9,41.6,4,7,93,93,2320,2832,0.8,1.1,0.001,0.001,0.004 +4353,"BORE WELL AT MANGARAJU +HOUSE, GAJAPATHINAGARAM +VILLAGE, PAYAKARAOPETA (M)",ANDHRA PRADESH,25,27,7.9,8.1,2660,3940,1.4,2.7,3,46.25,3,4,63,93,1844,2640,0.4,0.5,0.001,0.001,0.001 +3087,"BORE WELL NEAR VILLAGE +SECRETARIAT, PATHAPADU (V)",ANDHRA PRADESH,24,27,7.5,7.8,2031,2050,1.4,1.8,0.97,7.1,3,3,21,28,1210,1218,0.4,1,0.001,0.001,0.001 +4355,"BORE WELL, CHIPPADA VILLAGE, +BHEEMUNIPATNAM (M)",ANDHRA PRADESH,25,27,7.9,8,660,1482,2.2,2.2,2.05,3.6,4,7,43,120,442,980,0.4,1.4,0.001,0.001,0.001 +4354,"BORE WELL, SRI NOOKATATA +TEMPLE RAJAYYAPETA VILLAGE, +NAKKAPALLI (M)",ANDHRA PRADESH,25,27,7.4,7.6,11120,11420,2.2,2.5,2.2,15.4,7,9,120,150,7340,7968,0.3,0.7,0.001,0.001,0.001 +4394,"BOREWELL AT APLLC OFFICE +INDUSTRIAL ESTATE GROWTH +CENTRE, THUMAKUNTA, +HINDUPUR (M)",ANDHRA PRADESH,26,28,6.9,7.1,1584,3239,1,1,5.8,7.9,2,4,2,21,901,1764,0.6,1.3,0.001,0.001,0.001 +4395,"BOREWELL AT APLLC OFFICE +INDUSTRIAL ESTATE, +ANANTAPURAM (M)",ANDHRA PRADESH,26,28,7,7.1,3558,3780,1,1,10.4,11.4,2,6,2,33,1868,2144,0.5,1.5,0.001,0.001,0.001 +4377,"BOREWELL AT IMITATION +JEWELLARY PARK, +MACHILIPTNAM",ANDHRA PRADESH,27,27,8.1,8.1,1896,1920,1.4,1.8,0.3,2.8,3,3,14,21,1158,1170,0.8,0.9,0.001,0.001,0.001 +1519,BOREWELL AT NAGIRI,ANDHRA PRADESH,28,29,7.1,7.3,1872,2741,1,1,5.2,6.8,2,4,2,16,1061,1361,0.5,0.5,0.001,0.001,0.001 +1518,"BOREWELL AT NANDYAL +(KUNDU)",ANDHRA PRADESH,23,27,7.2,7.3,6619,7770,1,1,5.8,6.2,2,2,2,14,4068,4413,1,1.1,0.001,0.001,0.001 +4364,"BOREWELL AT RAJIV GRUHA +KA;PA, NEAR AP PAPER MAILLS +WORKERS COLONY,",ANDHRA PRADESH,28,28,7.6,7.6,1048,1048,1.5,1.5,3.22,3.22,3,3,93,93,680,680,0.7,0.7,0.001,0.001,0.001 +,"MALLAYAPETA, KATHERU, +RAJAMAHENDRAVARAM",,,,,,,,2.4,2.4,8,8,4,4,93,93,746,746,0.8,0.8,0.002,0.003,0.002 +4350,"BOREWELL AT ZP HIGH SCHOOL, +UDDANAM REGION, +AMALAPADU (V) +VAJRAPUKOTTURU",ANDHRA PRADESH,24,24,7.1,7.1,1140,1140,2,2.2,5.2,7.41,3,3,23,28,5634,6600,1.4,1.7,0.001,0.001,0.0015 +4384,"BOREWELL IN FRONT OF M/S +BHAGEERADHA CHEMICALS & +INDUSTRIES LTD, +CHERUVUKOMMUPALEM (V) +ONGOLE (M)",ANDHRA PRADESH,22,23,7.2,7.3,9090,10500,1.4,1.8,0.3,0.7,3,3,21,39,1120,1160,0.3,0.3,0.001,0.001,0.001 +1513,"BOREWELL KRISHNA MURTHY, +D.NO. 48-16-43 AUTONAGAR +VIJJAYAWADA",ANDHRA PRADESH,25,25,7.1,7.8,1877,1970,2,2,0.79,1.1,4,7,75,93,212,988,0.2,1.1,0.001,0.001,0.001 +1523,"BOREWELL NEAR M/S ANDHRA +SUGARS LTD. , KOVVUR",ANDHRA PRADESH,24,26,7,7.6,310,1447,1,1,1.4,2.6,2,3,2,12,714,784,0.6,1.1,0.001,0.001,0.001 +4392,"BOREWELL NEAR SRI +GOVINDARAJA SWAMY TEMPLE, +TIRUPATI TOWN",ANDHRA PRADESH,27,27,6.9,7.5,1380,1414,1,1,2.2,2.4,2,2,2,11,582,642,0.4,0.5,0.002,0.002,0.0015 +1520,"BOREWELL NEAR +SWARNAMUKHI RIVER AT +SRIKALAHASTI",ANDHRA PRADESH,28,29,7.3,7.3,1027,1266,1,1,6.7,10.1,2,3,2,29,2568,3370,1.3,1.8,0.001,0.001,0.0015 +1517,"BOREWELL NEAR TUNGBHADRA +RIVER KURNOOL",ANDHRA PRADESH,23,26,7.8,7.9,4520,5663,1.2,1.4,1.1,1.18,3,3,15,21,630,658,0.4,0.5,0.001,0.001,0.001 +1516,"BOREWELL OF NAVLOK +GARDENS, NELLORE",ANDHRA PRADESH,20,21,8.1,8.1,1080,1100,1.4,1.8,0.3,0.6,3,3,20,23,1050,1220,0.2,0.5,0.001,0.001,0.001 +1514,"BOREWELL VIJAY KUMAR +AUTONAGAR VIJAYAWADA",ANDHRA PRADESH,25,25,7.2,7.9,1780,2080,2,2.2,2.47,3.8,3,3,20,21,2310,2348,0.8,1,0.001,0.001,0.001 +4376,"BOREWELL WATER , APIIC +OFFICE, IDA KONDAPALLI, +IBRAHIMPATNAM (M)",ANDHRA PRADESH,26,26,7.1,7.6,3850,3860,1,1.8,0.3,1.5,3,3,14,15,508,550,0.5,0.6,0.001,0.001,0.001 +4380,"BOREWELL WATER , SRI +VENKATESWARA SWAMY +TEMPLE, VENKATAPALEM (V), +TULLUR (M)",ANDHRA PRADESH,22,22,7.1,7.5,860,899,1,1.8,0.3,1.5,3,3,14,15,508,550,0.5,0.6,0.001,0.001,0.001 +4382,"BOREWELL WATER POLICE +STATION, AUTONAGAR, +PEDAKAKANI, GUNTUR",ANDHRA PRADESH,21,22,7.1,8.1,4450,4580,2,2.2,3.5,3.86,3,3,28,28,2790,2840,0.2,0.8,0.001,0.001,0.001 +4393,"CLOSED MSW DUMPSITE, +UKKAYAPALLI (V), KADAPA (M)",ANDHRA PRADESH,24,25,7.3,7.4,2810,3352,1,1,10.4,13.1,2,9,2,71,1589,1785,0.6,1.2,0.004,0.004,0.0025 +3090,"HAND PUMP AT +PITTAVANIPALEM, +VISHAKHAPATNAM",ANDHRA PRADESH,27,27,6.7,7.6,1610,1983,2.2,2.2,2.5,18.8,3,4,75,75,1120,1312,0.3,0.5,0.001,0.001,0.0025 +3089,"HAND PUMP AT TANAM VILL., +VISHAKHAPATNAM",ANDHRA PRADESH,27,28,7.2,7.9,2180,2180,2.1,2.2,1.6,13.1,4,4,75,93,1480,1524,1.1,1.3,0.001,0.001,0.001 +1524,"OPEN WELL NEAR PARTAP +NAGAR BRIDGE -KAKINADA",ANDHRA PRADESH,27,30,7.3,7.7,1147,1295,2.1,2.1,0.9,4.78,4,4,75,75,784,848,0.3,1,0.001,0.001,0.001 +1521,"OPEN WELL NEAR RAMA +TEMPLE , WARD NO.2 , MINDI , +VISAKHAPATNAM",ANDHRA PRADESH,26,27,6.8,7.5,1977,2580,1.8,4,1.5,12.4,7,7,93,120,1296,1812,0.8,0.8,0.001,0.001,0.001 +1522,OPEN WELL PEDDANUVVI -VIZIANAGARAM,ANDHRA PRADESH,27,28,7.4,7.9,1120,1190,1.6,2.1,1.5,2.87,3,9,75,75,780,792,0.5,0.8,0.001,0.001,0.001 +26,"WELL AT GRAM PANCHAYAT +OFFICE, KAANURU, VIJAYWADA",ANDHRA PRADESH,25,25,7,8.1,1597,2160,1,2.2,0.7,1.89,3,3,20,23,942,1314,0.4,0.7,0.001,0.001,0.001 +1537,"GROUND WATER AT (JORHAT, +ASSAM)",ASSAM,25,26,7,7.2,276,278,2.3,2.3,0.7,0.8,2,2,2,2,156,224,0.3,0.3,0.01,0.01,0.0055 +1539,"GROUND WATER AT BARPETA, +ASSAM",ASSAM,30,31,7.4,7.5,304,329,2,2.1,0.8,0.8,2,2,2,2,172,180,0.3,0.3,0.01,0.01,0.01 +1540,"GROUND WATER AT +BONAIGAON, ASSAM",ASSAM,27,29,7.2,7.6,366,390,2,2.6,0.7,1,2,2,2,2,202,218,0.3,0.3,0.01,0.01,0.01 +1533,"GROUND WATER AT DIGBOI, +TINSUKIA DISTT., ASSAM",ASSAM,24,26,6.8,7.1,328,332,2.3,2.5,1.1,1.4,2,2,2,2,184,218,0.2,0.3,0.01,0.01,0.01 +1534,"GROUND WATER AT KARBI +ANGLONG DISTT., ASSAM",ASSAM,25,25,7.2,7.2,308,308,2.3,2.3,0.8,0.8,-,-,-,-,176,176,0.3,0.3,-,-,0.01 +1541,"GROUND WATER AT NOONMATI +GUWAHATI, ASSAM",ASSAM,27,29,7.3,7.6,401,408,2.3,2.5,0.8,1,2,2,2,2,218,224,0.3,0.3,0.01,0.01,0.01 +1535,"GROUND WATER AT SIBSAGAR +GOVT ME SCHOOL WARD 6, RED +CROSS ROAD , ASSAM",ASSAM,25,26,6.8,7.3,284,288,2.2,2.6,0.7,0.8,2,2,2,2,160,166,0.3,0.3,0.01,0.01,0.01 +1542,"GROUND WATER AT SIJUBARI +MAZAR, NATBOMA HATIGAON",ASSAM,27,28,7.8,7.8,352,354,2,2.6,0.8,1,2,2,2,2,194,200,0.3,0.4,0.01,0.01,0.01 +2599,"GROUND WATER BUS STAND +SASARAM, ROHTAS",BIHAR,20,20,7.9,7.9,735,735,,,0.88,0.88,7,7,9,9,482,482,0.2,0.2,0.001,0.001,0.01 +2044,"GROUND WATER FROM DADU +MAJRA, CHANDIGARH",CHANDIGARH,24.9,26.4,7.1,7.2,714,804,1,1.2,4.9,8.4,2,2,33,41,390,518,0.3,0.7,0.001,0.001,0.01 +2043,"GROUND WATER FROM +PALSORA VILLAGE, +CHANDIGARH",CHANDIGARH,25,26.4,7.2,7.4,836,909,1,1.5,2.2,3.8,2,5,49,49,430,570,0.3,0.3,0.001,0.001,0.01 +2039,"GROUND WATER FROM SECTOR +15, CHANDIGARH",CHANDIGARH,25,26.3,7.2,7.3,505,550,1,1,4.1,7.2,2,2,26,49,306,380,0.2,0.2,0.001,0.001,0.01 +2448,"GROUND WATER FROM VILLAGE +BHIMPORE, DAMAN","DAMAN AND DIU, +DADRA AND +NAGAR HAVELI",27.2,29.2,7.1,7.2,437,443,1,1,3.54,3.8,22,23,48,52,279,294,0.2,0.2,0.01,0.01,0.01 +1440,"WELL AT SOMNATH INDUSTRIAL +ESTATE, DAMAN","DAMAN AND DIU, +DADRA AND +NAGAR HAVELI",28.1,28.3,6.7,7.1,814,835,1,1,3.67,3.9,2,2,2,10,570,590,0.3,0.4,0.01,0.01,0.01 +2451,"WELL AT VILLAGE DABHEL, +DAMAN","DAMAN AND DIU, +DADRA AND +NAGAR HAVELI",28.4,29.1,7,7.1,1120,1324,1,1,1.67,1.78,2,2,6,8,790,823,0.3,0.4,0.01,0.01,0.01 +3194,"BORE WELL AT BETHORA +INDUSTRIAL ESTATE",GOA,29,29,7.1,7.1,118,118,1.8,1.8,0.5,0.5,2,2,2,2,77,77,0.2,0.2,0.001,0.001,0.01 +3195,"BORE WELL AT MADKAIM +INDUSTRIAL ESTATE",GOA,28,28,7.9,7.9,101,101,1.9,1.9,0.5,0.5,2,2,2,2,64,64,0.2,0.2,0.001,0.001,0.01 +2281,WELL AT CORLIM INDL. ESTATE,GOA,29,29,5,5,91,91,1.2,1.2,0.3,0.3,2,2,2,2,54,54,0.2,0.2,0.001,0.001,0.01 +2280,"WELL AT KUDAI INDL. +ESTATE(M/S CADILA +HEALTHCARE LIMITED)",GOA,28,28,5.6,5.6,122,122,4.2,4.2,0.3,0.3,2,2,2,2,77,77,0.2,0.2,0.001,0.001,0.01 diff --git a/Groundwater Arsenic Content Detection/images/Loss and accuracy.png b/Groundwater Arsenic Content Detection/images/Loss and accuracy.png new file mode 100644 index 000000000..7da4b86b2 Binary files /dev/null and b/Groundwater Arsenic Content Detection/images/Loss and accuracy.png differ diff --git a/Groundwater Arsenic Content Detection/images/RMSE Graph.png b/Groundwater Arsenic Content Detection/images/RMSE Graph.png new file mode 100644 index 000000000..4dadc8f4c Binary files /dev/null and b/Groundwater Arsenic Content Detection/images/RMSE Graph.png differ diff --git a/Groundwater Arsenic Content Detection/models/ann+woa.ipynb b/Groundwater Arsenic Content Detection/models/ann+woa.ipynb new file mode 100644 index 000000000..0a2f6212b --- /dev/null +++ b/Groundwater Arsenic Content Detection/models/ann+woa.ipynb @@ -0,0 +1,1318 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.model_selection import train_test_split\n", + "import numpy as np\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import accuracy_score\n", + "from sklearn.metrics import average_precision_score\n", + "from sklearn.metrics import mean_squared_error\n", + "from flask import Flask, request, jsonify, render_template\n", + "import pandas as pd\n", + "from sklearn.preprocessing import StandardScaler\n", + "import numpy as np\n", + "data = pd.read_csv('../data/Ground Water .csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Station Code pH Min pH Max Conductivity (µmhos/cm) Min \\\n", + "0 0.338985 0.208298 -0.143048 -0.431640 \n", + "1 0.338154 0.413193 1.213569 -0.494694 \n", + "2 1.391339 1.027880 0.632161 -0.357749 \n", + "3 0.337324 -0.406389 -0.724455 0.799876 \n", + "4 1.385525 1.437671 1.213569 0.464903 \n", + "5 0.334002 0.618089 0.632161 0.155054 \n", + "6 1.387186 1.437671 1.019766 -0.520309 \n", + "7 1.386355 0.413193 0.244557 4.112358 \n", + "8 1.419579 -0.611285 -0.724455 -0.065141 \n", + "9 1.419977 -0.406389 -0.724455 0.907264 \n", + "10 1.405459 1.847462 1.213569 0.088552 \n", + "11 -0.968359 -0.201494 -0.336850 0.076729 \n", + "12 -0.969189 0.003402 -0.336850 2.415132 \n", + "13 1.394661 0.822984 0.244557 -0.329178 \n", + "14 -0.266097 0.003402 0.050754 -0.321296 \n", + "15 1.383033 -0.201494 -0.724455 -0.283858 \n", + "16 1.411273 0.003402 -0.336850 3.632362 \n", + "17 -0.973342 -0.201494 0.632161 0.079193 \n", + "18 -0.965036 -0.406389 0.244557 -0.692722 \n", + "19 1.417917 -0.611285 0.050754 -0.165633 \n", + "20 -0.967528 0.208298 -0.336850 -0.339523 \n", + "21 -0.970020 1.232776 0.825964 1.381151 \n", + "22 -0.970850 1.847462 1.213569 -0.313415 \n", + "23 -0.972512 0.003402 0.825964 0.031410 \n", + "24 1.404628 -0.201494 0.244557 1.051105 \n", + "25 1.407950 -0.201494 0.050754 -0.421788 \n", + "26 1.409612 -0.201494 1.213569 1.346669 \n", + "27 1.418748 0.208298 -0.143048 0.538794 \n", + "28 0.336493 -1.021076 0.244557 -0.052333 \n", + "29 0.335663 0.003402 0.825964 0.228452 \n", + "30 -0.964206 0.208298 0.438359 -0.280410 \n", + "31 -0.966698 -0.816180 0.050754 0.128453 \n", + "32 -0.965867 0.413193 0.825964 -0.293711 \n", + "33 -1.597711 -0.406389 1.213569 -0.058737 \n", + "34 -0.953408 -0.406389 -0.530653 -0.709470 \n", + "35 -0.951747 0.413193 0.050754 -0.695677 \n", + "36 -0.950916 0.003402 0.244557 -0.665136 \n", + "37 -0.956730 -0.816180 -0.724455 -0.683855 \n", + "38 -0.955900 0.003402 -0.530653 -0.693707 \n", + "39 -0.950086 0.208298 0.244557 -0.647895 \n", + "40 -0.955069 -0.816180 -0.336850 -0.705529 \n", + "41 -0.949255 1.232776 0.632161 -0.672032 \n", + "42 -0.071325 1.437671 0.825964 -0.483364 \n", + "43 -0.532301 -0.201494 -0.530653 -0.493709 \n", + "44 -0.533131 0.003402 -0.143048 -0.433611 \n", + "45 -0.536454 0.003402 -0.336850 -0.596663 \n", + "46 -0.196743 -0.201494 -0.530653 -0.630161 \n", + "47 -1.033975 -1.021076 -0.724455 -0.444448 \n", + "48 -0.194252 -0.406389 -0.724455 -0.293711 \n", + "49 0.422874 -0.201494 -0.724455 -0.787302 \n", + "50 0.423705 1.437671 0.825964 -0.795676 \n", + "51 -0.335451 -3.865027 -4.189642 -0.798041 \n", + "52 -0.336282 -3.274927 -3.631491 -0.785332 \n", + "\n", + " Conductivity (µmhos/cm) Max BOD min(mg/L) BOD max(mg/L) \\\n", + "0 -0.239813 0.669106 0.235279 \n", + "1 -0.388427 0.669106 0.646191 \n", + "2 -0.327156 0.304189 0.098309 \n", + "3 0.967783 1.034023 2.289838 \n", + "4 0.828729 -0.425644 1.057103 \n", + "5 0.007442 -0.425644 -0.175632 \n", + "6 -0.239378 1.034023 0.372250 \n", + "7 3.871226 1.034023 0.783162 \n", + "8 0.524114 -1.155478 -1.271397 \n", + "9 0.759202 -1.155478 -1.271397 \n", + "10 -0.049048 -0.425644 -0.175632 \n", + "11 0.307712 -1.155478 -1.271397 \n", + "12 2.493029 -1.155478 -1.271397 \n", + "13 -0.427970 -0.243186 -0.586544 \n", + "14 -0.323897 1.398940 0.646191 \n", + "15 -0.387992 0.669106 0.372250 \n", + "16 3.679332 -0.425644 -0.175632 \n", + "17 -0.027321 0.669106 0.098309 \n", + "18 -0.254587 -1.155478 -1.271397 \n", + "19 -0.268927 -1.155478 -1.271397 \n", + "20 -0.333240 -1.155478 -1.271397 \n", + "21 1.577447 -0.790561 -0.723515 \n", + "22 -0.405374 -0.425644 -0.175632 \n", + "23 0.020478 0.669106 0.372250 \n", + "24 0.793965 -1.155478 -0.175632 \n", + "25 -0.492717 -1.155478 -0.175632 \n", + "26 1.106836 0.669106 0.372250 \n", + "27 0.573217 -1.155478 -1.271397 \n", + "28 -0.021672 1.034023 0.372250 \n", + "29 0.063933 0.851564 0.372250 \n", + "30 -0.320638 0.851564 0.235279 \n", + "31 0.237750 0.304189 2.837720 \n", + "32 -0.366265 -0.060728 0.235279 \n", + "33 0.055242 -1.155478 0.372250 \n", + "34 -0.762568 1.216481 0.509220 \n", + "35 -0.740407 0.669106 0.235279 \n", + "36 -0.713900 0.669106 0.920132 \n", + "37 -0.739103 1.216481 0.783162 \n", + "38 -0.749532 1.216481 0.509220 \n", + "39 -0.706078 1.216481 0.783162 \n", + "40 -0.758223 1.034023 0.920132 \n", + "41 -0.729543 0.669106 0.920132 \n", + "42 -0.563982 0.121731 0.098309 \n", + "43 -0.533999 -1.155478 -0.997456 \n", + "44 -0.488372 -1.155478 -0.586544 \n", + "45 -0.644373 -1.155478 -1.271397 \n", + "46 -0.690869 -1.155478 -1.271397 \n", + "47 -0.520528 -1.155478 -1.271397 \n", + "48 -0.308036 -1.155478 -1.271397 \n", + "49 -0.832095 0.304189 -0.175632 \n", + "50 -0.839483 0.486648 -0.038662 \n", + "51 -0.841568 -0.790561 -0.997456 \n", + "52 -0.830357 2.975380 2.969212 \n", + "\n", + " Nitrate N min(mg/L) NitrateN max(mg/L) \\\n", + "0 -0.610752 1.229754 \n", + "1 -0.610752 0.203837 \n", + "2 -0.570066 -0.317282 \n", + "3 1.016692 4.126803 \n", + "4 0.243656 4.387013 \n", + "5 -0.582272 0.104743 \n", + "6 -0.142862 -0.303292 \n", + "7 -0.081833 1.072369 \n", + "8 1.382866 0.198008 \n", + "9 3.254426 0.606043 \n", + "10 -0.854868 -0.396557 \n", + "11 1.138750 0.069769 \n", + "12 1.382866 -0.000180 \n", + "13 0.333165 -0.347593 \n", + "14 2.277960 0.209666 \n", + "15 1.138750 0.140883 \n", + "16 -0.854868 -0.641378 \n", + "17 -0.655507 -0.594746 \n", + "18 -0.407321 -0.419874 \n", + "19 -0.081833 -0.443190 \n", + "20 1.749041 0.454487 \n", + "21 -0.529380 -0.585419 \n", + "22 -0.854868 -0.653037 \n", + "23 0.028020 -0.279976 \n", + "24 -0.854868 -0.548113 \n", + "25 -0.854868 -0.548113 \n", + "26 0.447086 -0.272981 \n", + "27 3.254426 0.804232 \n", + "28 0.040225 1.468746 \n", + "29 -0.325949 0.804232 \n", + "30 -0.610752 -0.165726 \n", + "31 -0.366635 0.722625 \n", + "32 -0.366635 -0.388397 \n", + "33 -0.692124 -0.502646 \n", + "34 -0.692124 -0.629720 \n", + "35 -0.651438 -0.629720 \n", + "36 -0.692124 -0.606404 \n", + "37 -0.529380 -0.559771 \n", + "38 -0.651438 -0.629720 \n", + "39 -0.651438 -0.606404 \n", + "40 -0.692124 -0.629720 \n", + "41 -0.651438 -0.606404 \n", + "42 -0.618889 -0.620394 \n", + "43 1.016692 0.256299 \n", + "44 -0.081833 -0.279976 \n", + "45 0.691203 0.116401 \n", + "46 0.463361 -0.279976 \n", + "47 0.516253 -0.268318 \n", + "48 -0.297469 -0.515470 \n", + "49 -0.773496 -0.664695 \n", + "50 -0.773496 -0.664695 \n", + "51 -0.854868 -0.688011 \n", + "52 -0.854868 -0.688011 \n", + "\n", + " Total Dissolved Solidsmin (mg/L) ... Arsenic min (mg/L)_- \\\n", + "0 -0.373573 ... False \n", + "1 -0.446035 ... False \n", + "2 -0.313714 ... False \n", + "3 0.993744 ... False \n", + "4 0.618834 ... False \n", + "5 0.119480 ... False \n", + "6 -0.485416 ... False \n", + "7 4.248903 ... False \n", + "8 -0.123896 ... False \n", + "9 0.637737 ... False \n", + "10 0.078524 ... False \n", + "11 0.002124 ... False \n", + "12 2.370512 ... False \n", + "13 -0.297961 ... False \n", + "14 -0.245978 ... False \n", + "15 3.603933 ... False \n", + "16 0.048594 ... False \n", + "17 -0.666570 ... False \n", + "18 -0.271182 ... False \n", + "19 -0.375148 ... False \n", + "20 1.189075 ... False \n", + "21 -0.337342 ... False \n", + "22 -0.006540 ... False \n", + "23 0.985868 ... False \n", + "24 -0.433433 ... False \n", + "25 -0.433433 ... False \n", + "26 1.363928 ... False \n", + "27 0.417990 ... False \n", + "28 0.048594 ... False \n", + "29 0.332139 ... False \n", + "30 -0.216048 ... False \n", + "31 0.187216 ... False \n", + "32 -0.219199 ... False \n", + "33 -0.091603 ... False \n", + "34 -0.710677 ... False \n", + "35 -0.698075 ... False \n", + "36 -0.674446 ... False \n", + "37 -0.688623 ... False \n", + "38 -0.694924 ... True \n", + "39 -0.661844 ... False \n", + "40 -0.707526 ... False \n", + "41 -0.680747 ... False \n", + "42 -0.453911 ... False \n", + "43 -0.526372 ... False \n", + "44 -0.494867 ... False \n", + "45 -0.592533 ... False \n", + "46 -0.613799 ... False \n", + "47 -0.384600 ... False \n", + "48 -0.211322 ... False \n", + "49 -0.772899 ... False \n", + "50 -0.783138 ... False \n", + "51 -0.786919 ... False \n", + "52 -0.772899 ... False \n", + "\n", + " Arsenic min (mg/L)_0.001 Arsenic min (mg/L)_0.002 \\\n", + "0 True False \n", + "1 True False \n", + "2 False False \n", + "3 True False \n", + "4 True False \n", + "5 True False \n", + "6 True False \n", + "7 True False \n", + "8 True False \n", + "9 True False \n", + "10 True False \n", + "11 True False \n", + "12 True False \n", + "13 True False \n", + "14 False True \n", + "15 True False \n", + "16 True False \n", + "17 True False \n", + "18 True False \n", + "19 False True \n", + "20 True False \n", + "21 True False \n", + "22 True False \n", + "23 True False \n", + "24 True False \n", + "25 True False \n", + "26 True False \n", + "27 False False \n", + "28 True False \n", + "29 True False \n", + "30 True False \n", + "31 True False \n", + "32 True False \n", + "33 True False \n", + "34 False False \n", + "35 False False \n", + "36 False False \n", + "37 False False \n", + "38 False False \n", + "39 False False \n", + "40 False False \n", + "41 False False \n", + "42 True False \n", + "43 True False \n", + "44 True False \n", + "45 True False \n", + "46 False False \n", + "47 False False \n", + "48 False False \n", + "49 True False \n", + "50 True False \n", + "51 True False \n", + "52 True False \n", + "\n", + " Arsenic min (mg/L)_0.004 Arsenic min (mg/L)_0.007 \\\n", + "0 False False \n", + "1 False False \n", + "2 False True \n", + "3 False False \n", + "4 False False \n", + "5 False False \n", + "6 False False \n", + "7 False False \n", + "8 False False \n", + "9 False False \n", + "10 False False \n", + "11 False False \n", + "12 False False \n", + "13 False False \n", + "14 False False \n", + "15 False False \n", + "16 False False \n", + "17 False False \n", + "18 False False \n", + "19 False False \n", + "20 False False \n", + "21 False False \n", + "22 False False \n", + "23 False False \n", + "24 False False \n", + "25 False False \n", + "26 False False \n", + "27 True False \n", + "28 False False \n", + "29 False False \n", + "30 False False \n", + "31 False False \n", + "32 False False \n", + "33 False False \n", + "34 False False \n", + "35 False False \n", + "36 False False \n", + "37 False False \n", + "38 False False \n", + "39 False False \n", + "40 False False \n", + "41 False False \n", + "42 False False \n", + "43 False False \n", + "44 False False \n", + "45 False False \n", + "46 False False \n", + "47 False False \n", + "48 False False \n", + "49 False False \n", + "50 False False \n", + "51 False False \n", + "52 False False \n", + "\n", + " Arsenic min (mg/L)_0.01 Arsenic max (mg/L)_- Arsenic max (mg/L)_0.001 \\\n", + "0 False False True \n", + "1 False False True \n", + "2 False False False \n", + "3 False False True \n", + "4 False False True \n", + "5 False False True \n", + "6 False False True \n", + "7 False False True \n", + "8 False False True \n", + "9 False False True \n", + "10 False False True \n", + "11 False False True \n", + "12 False False True \n", + "13 False False True \n", + "14 False False False \n", + "15 False False True \n", + "16 False False True \n", + "17 False False True \n", + "18 False False True \n", + "19 False False False \n", + "20 False False True \n", + "21 False False True \n", + "22 False False True \n", + "23 False False True \n", + "24 False False True \n", + "25 False False True \n", + "26 False False True \n", + "27 False False False \n", + "28 False False True \n", + "29 False False True \n", + "30 False False True \n", + "31 False False True \n", + "32 False False True \n", + "33 False False True \n", + "34 True False False \n", + "35 True False False \n", + "36 True False False \n", + "37 True False False \n", + "38 False True False \n", + "39 True False False \n", + "40 True False False \n", + "41 True False False \n", + "42 False False True \n", + "43 False False True \n", + "44 False False True \n", + "45 False False True \n", + "46 True False False \n", + "47 True False False \n", + "48 True False False \n", + "49 False False True \n", + "50 False False True \n", + "51 False False True \n", + "52 False False True \n", + "\n", + " Arsenic max (mg/L)_0.002 Arsenic max (mg/L)_0.003 \n", + "0 False False \n", + "1 False False \n", + "2 False False \n", + "3 False False \n", + "4 False False \n", + "5 False False \n", + "6 False False \n", + "7 False False \n", + "8 False False \n", + "9 False False \n", + "10 False False \n", + "11 False False \n", + "12 False False \n", + "13 False False \n", + "14 False True \n", + "15 False False \n", + "16 False False \n", + "17 False False \n", + "18 False False \n", + "19 True False \n", + "20 False False \n", + "21 False False \n", + "22 False False \n", + "23 False False \n", + "24 False False \n", + "25 False False \n", + "26 False False \n", + "27 False False \n", + "28 False False \n", + "29 False False \n", + "30 False False \n", + "31 False False \n", + "32 False False \n", + "33 False False \n", + "34 False False \n", + "35 False False \n", + "36 False False \n", + "37 False False \n", + "38 False False \n", + "39 False False \n", + "40 False False \n", + "41 False False \n", + "42 False False \n", + "43 False False \n", + "44 False False \n", + "45 False False \n", + "46 False False \n", + "47 False False \n", + "48 False False \n", + "49 False False \n", + "50 False False \n", + "51 False False \n", + "52 False False \n", + "\n", + "[53 rows x 142 columns]\n" + ] + } + ], + "source": [ + "numeric_columns = data.select_dtypes(include='number').columns\n", + "data[numeric_columns] = data[numeric_columns].fillna(data[numeric_columns].median())\n", + "\n", + "\n", + "# Select only numeric columns for quantile calculations\n", + "numeric_data = data.select_dtypes(include=[np.number])\n", + "data[numeric_data.columns] = numeric_data.clip(lower=numeric_data.quantile(0.01), upper=numeric_data.quantile(0.99), axis=1)\n", + "\n", + "\n", + "# Encode categorical variables\n", + "data = pd.get_dummies(data)\n", + "\n", + "# Scale numerical variables\n", + "scaler = StandardScaler()\n", + "data[data.select_dtypes(include=['float64']).columns] = scaler.fit_transform(data.select_dtypes(include=['float64']))\n", + "\n", + "\n", + "data = data.drop(data.columns[[1, 2]], axis=1)\n", + "X = data.iloc[:,:-3]\n", + "y = data.iloc[:, -1]\n", + "#print(\"\\nX\")\n", + "print(X)\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "x: Station Code pH Min pH Max Conductivity (µmhos/cm) Min \\\n", + "22 -0.970850 1.847462 1.213569 -0.313415 \n", + "7 1.386355 0.413193 0.244557 4.112358 \n", + "14 -0.266097 0.003402 0.050754 -0.321296 \n", + "34 -0.953408 -0.406389 -0.530653 -0.709470 \n", + "48 -0.194252 -0.406389 -0.724455 -0.293711 \n", + "18 -0.965036 -0.406389 0.244557 -0.692722 \n", + "50 0.423705 1.437671 0.825964 -0.795676 \n", + "35 -0.951747 0.413193 0.050754 -0.695677 \n", + "15 1.383033 -0.201494 -0.724455 -0.283858 \n", + "5 0.334002 0.618089 0.632161 0.155054 \n", + "28 0.336493 -1.021076 0.244557 -0.052333 \n", + "16 1.411273 0.003402 -0.336850 3.632362 \n", + "45 -0.536454 0.003402 -0.336850 -0.596663 \n", + "20 -0.967528 0.208298 -0.336850 -0.339523 \n", + "46 -0.196743 -0.201494 -0.530653 -0.630161 \n", + "8 1.419579 -0.611285 -0.724455 -0.065141 \n", + "13 1.394661 0.822984 0.244557 -0.329178 \n", + "25 1.407950 -0.201494 0.050754 -0.421788 \n", + "17 -0.973342 -0.201494 0.632161 0.079193 \n", + "51 -0.335451 -3.865027 -4.189642 -0.798041 \n", + "42 -0.071325 1.437671 0.825964 -0.483364 \n", + "1 0.338154 0.413193 1.213569 -0.494694 \n", + "12 -0.969189 0.003402 -0.336850 2.415132 \n", + "40 -0.955069 -0.816180 -0.336850 -0.705529 \n", + "24 1.404628 -0.201494 0.244557 1.051105 \n", + "6 1.387186 1.437671 1.019766 -0.520309 \n", + "23 -0.972512 0.003402 0.825964 0.031410 \n", + "36 -0.950916 0.003402 0.244557 -0.665136 \n", + "21 -0.970020 1.232776 0.825964 1.381151 \n", + "19 1.417917 -0.611285 0.050754 -0.165633 \n", + "9 1.419977 -0.406389 -0.724455 0.907264 \n", + "39 -0.950086 0.208298 0.244557 -0.647895 \n", + "49 0.422874 -0.201494 -0.724455 -0.787302 \n", + "3 0.337324 -0.406389 -0.724455 0.799876 \n", + "0 0.338985 0.208298 -0.143048 -0.431640 \n", + "47 -1.033975 -1.021076 -0.724455 -0.444448 \n", + "44 -0.533131 0.003402 -0.143048 -0.433611 \n", + "\n", + " Conductivity (µmhos/cm) Max BOD min(mg/L) BOD max(mg/L) \\\n", + "22 -0.405374 -0.425644 -0.175632 \n", + "7 3.871226 1.034023 0.783162 \n", + "14 -0.323897 1.398940 0.646191 \n", + "34 -0.762568 1.216481 0.509220 \n", + "48 -0.308036 -1.155478 -1.271397 \n", + "18 -0.254587 -1.155478 -1.271397 \n", + "50 -0.839483 0.486648 -0.038662 \n", + "35 -0.740407 0.669106 0.235279 \n", + "15 -0.387992 0.669106 0.372250 \n", + "5 0.007442 -0.425644 -0.175632 \n", + "28 -0.021672 1.034023 0.372250 \n", + "16 3.679332 -0.425644 -0.175632 \n", + "45 -0.644373 -1.155478 -1.271397 \n", + "20 -0.333240 -1.155478 -1.271397 \n", + "46 -0.690869 -1.155478 -1.271397 \n", + "8 0.524114 -1.155478 -1.271397 \n", + "13 -0.427970 -0.243186 -0.586544 \n", + "25 -0.492717 -1.155478 -0.175632 \n", + "17 -0.027321 0.669106 0.098309 \n", + "51 -0.841568 -0.790561 -0.997456 \n", + "42 -0.563982 0.121731 0.098309 \n", + "1 -0.388427 0.669106 0.646191 \n", + "12 2.493029 -1.155478 -1.271397 \n", + "40 -0.758223 1.034023 0.920132 \n", + "24 0.793965 -1.155478 -0.175632 \n", + "6 -0.239378 1.034023 0.372250 \n", + "23 0.020478 0.669106 0.372250 \n", + "36 -0.713900 0.669106 0.920132 \n", + "21 1.577447 -0.790561 -0.723515 \n", + "19 -0.268927 -1.155478 -1.271397 \n", + "9 0.759202 -1.155478 -1.271397 \n", + "39 -0.706078 1.216481 0.783162 \n", + "49 -0.832095 0.304189 -0.175632 \n", + "3 0.967783 1.034023 2.289838 \n", + "0 -0.239813 0.669106 0.235279 \n", + "47 -0.520528 -1.155478 -1.271397 \n", + "44 -0.488372 -1.155478 -0.586544 \n", + "\n", + " Nitrate N min(mg/L) NitrateN max(mg/L) \\\n", + "22 -0.854868 -0.653037 \n", + "7 -0.081833 1.072369 \n", + "14 2.277960 0.209666 \n", + "34 -0.692124 -0.629720 \n", + "48 -0.297469 -0.515470 \n", + "18 -0.407321 -0.419874 \n", + "50 -0.773496 -0.664695 \n", + "35 -0.651438 -0.629720 \n", + "15 1.138750 0.140883 \n", + "5 -0.582272 0.104743 \n", + "28 0.040225 1.468746 \n", + "16 -0.854868 -0.641378 \n", + "45 0.691203 0.116401 \n", + "20 1.749041 0.454487 \n", + "46 0.463361 -0.279976 \n", + "8 1.382866 0.198008 \n", + "13 0.333165 -0.347593 \n", + "25 -0.854868 -0.548113 \n", + "17 -0.655507 -0.594746 \n", + "51 -0.854868 -0.688011 \n", + "42 -0.618889 -0.620394 \n", + "1 -0.610752 0.203837 \n", + "12 1.382866 -0.000180 \n", + "40 -0.692124 -0.629720 \n", + "24 -0.854868 -0.548113 \n", + "6 -0.142862 -0.303292 \n", + "23 0.028020 -0.279976 \n", + "36 -0.692124 -0.606404 \n", + "21 -0.529380 -0.585419 \n", + "19 -0.081833 -0.443190 \n", + "9 3.254426 0.606043 \n", + "39 -0.651438 -0.606404 \n", + "49 -0.773496 -0.664695 \n", + "3 1.016692 4.126803 \n", + "0 -0.610752 1.229754 \n", + "47 0.516253 -0.268318 \n", + "44 -0.081833 -0.279976 \n", + "\n", + " Total Dissolved Solidsmin (mg/L) ... Arsenic min (mg/L)_- \\\n", + "22 -0.006540 ... False \n", + "7 4.248903 ... False \n", + "14 -0.245978 ... False \n", + "34 -0.710677 ... False \n", + "48 -0.211322 ... False \n", + "18 -0.271182 ... False \n", + "50 -0.783138 ... False \n", + "35 -0.698075 ... False \n", + "15 3.603933 ... False \n", + "5 0.119480 ... False \n", + "28 0.048594 ... False \n", + "16 0.048594 ... False \n", + "45 -0.592533 ... False \n", + "20 1.189075 ... False \n", + "46 -0.613799 ... False \n", + "8 -0.123896 ... False \n", + "13 -0.297961 ... False \n", + "25 -0.433433 ... False \n", + "17 -0.666570 ... False \n", + "51 -0.786919 ... False \n", + "42 -0.453911 ... False \n", + "1 -0.446035 ... False \n", + "12 2.370512 ... False \n", + "40 -0.707526 ... False \n", + "24 -0.433433 ... False \n", + "6 -0.485416 ... False \n", + "23 0.985868 ... False \n", + "36 -0.674446 ... False \n", + "21 -0.337342 ... False \n", + "19 -0.375148 ... False \n", + "9 0.637737 ... False \n", + "39 -0.661844 ... False \n", + "49 -0.772899 ... False \n", + "3 0.993744 ... False \n", + "0 -0.373573 ... False \n", + "47 -0.384600 ... False \n", + "44 -0.494867 ... False \n", + "\n", + " Arsenic min (mg/L)_0.001 Arsenic min (mg/L)_0.002 \\\n", + "22 True False \n", + "7 True False \n", + "14 False True \n", + "34 False False \n", + "48 False False \n", + "18 True False \n", + "50 True False \n", + "35 False False \n", + "15 True False \n", + "5 True False \n", + "28 True False \n", + "16 True False \n", + "45 True False \n", + "20 True False \n", + "46 False False \n", + "8 True False \n", + "13 True False \n", + "25 True False \n", + "17 True False \n", + "51 True False \n", + "42 True False \n", + "1 True False \n", + "12 True False \n", + "40 False False \n", + "24 True False \n", + "6 True False \n", + "23 True False \n", + "36 False False \n", + "21 True False \n", + "19 False True \n", + "9 True False \n", + "39 False False \n", + "49 True False \n", + "3 True False \n", + "0 True False \n", + "47 False False \n", + "44 True False \n", + "\n", + " Arsenic min (mg/L)_0.004 Arsenic min (mg/L)_0.007 \\\n", + "22 False False \n", + "7 False False \n", + "14 False False \n", + "34 False False \n", + "48 False False \n", + "18 False False \n", + "50 False False \n", + "35 False False \n", + "15 False False \n", + "5 False False \n", + "28 False False \n", + "16 False False \n", + "45 False False \n", + "20 False False \n", + "46 False False \n", + "8 False False \n", + "13 False False \n", + "25 False False \n", + "17 False False \n", + "51 False False \n", + "42 False False \n", + "1 False False \n", + "12 False False \n", + "40 False False \n", + "24 False False \n", + "6 False False \n", + "23 False False \n", + "36 False False \n", + "21 False False \n", + "19 False False \n", + "9 False False \n", + "39 False False \n", + "49 False False \n", + "3 False False \n", + "0 False False \n", + "47 False False \n", + "44 False False \n", + "\n", + " Arsenic min (mg/L)_0.01 Arsenic max (mg/L)_- Arsenic max (mg/L)_0.001 \\\n", + "22 False False True \n", + "7 False False True \n", + "14 False False False \n", + "34 True False False \n", + "48 True False False \n", + "18 False False True \n", + "50 False False True \n", + "35 True False False \n", + "15 False False True \n", + "5 False False True \n", + "28 False False True \n", + "16 False False True \n", + "45 False False True \n", + "20 False False True \n", + "46 True False False \n", + "8 False False True \n", + "13 False False True \n", + "25 False False True \n", + "17 False False True \n", + "51 False False True \n", + "42 False False True \n", + "1 False False True \n", + "12 False False True \n", + "40 True False False \n", + "24 False False True \n", + "6 False False True \n", + "23 False False True \n", + "36 True False False \n", + "21 False False True \n", + "19 False False False \n", + "9 False False True \n", + "39 True False False \n", + "49 False False True \n", + "3 False False True \n", + "0 False False True \n", + "47 True False False \n", + "44 False False True \n", + "\n", + " Arsenic max (mg/L)_0.002 Arsenic max (mg/L)_0.003 \n", + "22 False False \n", + "7 False False \n", + "14 False True \n", + "34 False False \n", + "48 False False \n", + "18 False False \n", + "50 False False \n", + "35 False False \n", + "15 False False \n", + "5 False False \n", + "28 False False \n", + "16 False False \n", + "45 False False \n", + "20 False False \n", + "46 False False \n", + "8 False False \n", + "13 False False \n", + "25 False False \n", + "17 False False \n", + "51 False False \n", + "42 False False \n", + "1 False False \n", + "12 False False \n", + "40 False False \n", + "24 False False \n", + "6 False False \n", + "23 False False \n", + "36 False False \n", + "21 False False \n", + "19 True False \n", + "9 False False \n", + "39 False False \n", + "49 False False \n", + "3 False False \n", + "0 False False \n", + "47 False False \n", + "44 False False \n", + "\n", + "[37 rows x 142 columns]\n", + "\n", + "y: \n" + ] + } + ], + "source": [ + "print(\"\\nx:\",X_train)\n", + "\n", + "print(\"\\ny: \")\n", + "from sklearn.model_selection import KFold\n", + "from sklearn.linear_model import LinearRegression\n", + "from sklearn.metrics import mean_squared_error\n", + "\n", + "# Choose a model to use\n", + "model = LinearRegression()\n", + "\n", + "# Split the dataset into k-folds\n", + "kf = KFold(n_splits=5, shuffle=True)\n", + "\n", + "# Perform cross-validation\n", + "mse_scores = []\n", + "for train_index, test_index in kf.split(X_train):\n", + " # Split the data into training and testing sets for this fold\n", + " X_train_fold, X_test_fold = X_train.iloc[train_index], X_train.iloc[test_index]\n", + " y_train_fold, y_test_fold = y_train.iloc[train_index], y_train.iloc[test_index]\n", + " # Train the model on the training set and test it on the testing set\n", + " model.fit(X_train_fold, y_train_fold)\n", + " y_pred = model.predict(X_test_fold)\n", + " mse = mean_squared_error(y_test_fold, y_pred)\n", + " mse_scores.append(mse)\n", + " \n", + "# Compute the average mean squared error across all folds\n", + "avg_mse = sum(mse_scores) / len(mse_scores)\n", + "#print(\"\\navgmse: \",avg_mse)\n", + "\n", + "\n", + "\n", + "Y_train=np.unique(y_train_fold)\n", + "#y_train=y_train.reshape(-1,1)\n", + "#print(\"\\nunique: \",y_train)\n", + "#print(\"\\nunique shape: \",y_train.shape)\n", + "#print(\"\\nlength unique shape: \",len(y_train))\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.pyplot as plt1\n", + "from functools import partial\n", + "import numpy as np\n", + "\n", + "\n", + "def f(X):\n", + " A = 10\n", + " sol = []\n", + " for ind in X:\n", + " sol.append(A*len(ind) + sum([(i**2 - A * np.cos(2 * np.pi * i)) for i in ind]) )#output-Y\n", + "\n", + " return np.array(sol)\n", + "x_lb=y_lb=-500\n", + "x_ub=y_ub=500\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "class WOA:\n", + " def __init__(self, obj_func, n_whale, spiral_constant, n_iter,lb, ub,W):\n", + " self.obj_func = obj_func\n", + " self.n_whale = n_whale\n", + " self.spiral_constant = spiral_constant\n", + " self.n_iter = n_iter\n", + " #print('--------------------')\n", + " self.whale = {}\n", + " self.prey = {}\n", + " self.W=W\n", + " #print('----------------------------')\n", + " self.lb = np.array([x_lb, y_lb])\n", + "\n", + " self.ub = np.array([x_ub, y_ub])\n", + "\n", + " def init_whale(self):\n", + " tmp = [np.random.uniform(self.lb, self.ub, size=(len(self.lb),))\n", + " for i in range(self.n_whale)]\n", + " print(\"\\n temp:\",tmp)\n", + " self.whale['position'] = np.array(tmp)\n", + " self.whale['fitness'] = self.obj_func(self.whale['position'])\n", + "\n", + " def init_prey(self):\n", + " \n", + " tmp = [np.random.uniform(self.lb, self.ub, size=(len(self.lb),))]\n", + " \n", + " self.prey['position'] = np.array(tmp)\n", + " self.prey['fitness'] = self.obj_func(self.prey['position'])\n", + "\n", + " \n", + " def update_prey(self):\n", + " if self.whale['fitness'].min() < self.prey['fitness'][0]:\n", + " self.prey['position'][0] = self.whale['position'][self.whale['fitness'].argmin()]\n", + " self.prey['fitness'][0] = self.whale['fitness'].min()\n", + "\n", + " def search(self, idx, A, C):\n", + " random_whale = self.whale['position'][np.random.randint(low=0, high=self.n_whale,\n", + " size=len(idx[0]))]\n", + " d = np.abs(C[..., np.newaxis] * random_whale - self.whale['position'][idx])\n", + " self.whale['position'][idx] = np.clip(random_whale - A[..., np.newaxis] * d, self.lb, self.ub)\n", + "\n", + " def encircle(self, idx, A, C):\n", + " #d = np.abs(C[..., np.newaxis] * self.prey['position'].reshape(1, -1) - self.whale['position'][idx])\n", + " d = np.abs(np.reshape(C, (-1, 1)) * self.prey['position'].reshape(1, -1) - self.whale['position'][idx])\n", + "\n", + " self.whale['position'][idx] = np.clip(self.prey['position'][0] - A[..., np.newaxis] * d, self.lb, self.ub)\n", + "\n", + " def bubble_net(self, idx):\n", + " d_prime = np.abs(self.prey['position'] - self.whale['position'][idx])\n", + " l = np.random.uniform(-1, 1, size=len(idx[0]))\n", + " self.whale[\"position\"][idx] = np.clip(\n", + " d_prime * np.exp(self.spiral_constant * l)[..., np.newaxis] * np.cos(2 * np.pi * l)[..., np.newaxis]\n", + " + self.prey[\"position\"],\n", + " self.lb,\n", + " self.ub,\n", + " )\n", + "\n", + " def optimize(self, a):\n", + "\n", + " p = np.random.random(self.n_whale)\n", + " r1 = np.random.random(self.n_whale)\n", + " r2 = np.random.random(self.n_whale)\n", + " A = 2 * a * r1 - a\n", + " C = 2 * r2\n", + " search_idx = np.where((p < 0.5) & (abs(A) > 1))\n", + " encircle_idx = np.where((p < 0.5) & (abs(A) <= 1))\n", + " bubbleNet_idx = np.where(p >= 0.5)\n", + " self.search(search_idx, A[search_idx], C[search_idx])\n", + " self.encircle(encircle_idx, A[encircle_idx], C[encircle_idx])\n", + " self.bubble_net(bubbleNet_idx)\n", + " self.whale['fitness'] = self.obj_func(self.whale['position'])\n", + "\n", + " def run(self):\n", + " self.init_whale()\n", + " self.init_prey()\n", + " f_values = [self.prey['fitness'][0]]\n", + " #print(\"\\n\\n\\n\\n\\noptimal sol: \",self.prey['position'][0])\n", + " for n in range(self.n_iter):\n", + " #print(\"Iteration = \", n, \" f(x) = \", self.prey['fitness'][0])\n", + " a = 2 - n * (2 / self.n_iter)\n", + " self.optimize(a)\n", + " self.update_prey()\n", + " #l.append((self.loss(out, y_wt)))\n", + " #acc.append(abs((1-(sum(l)/len(x)))*10))\n", + " f_values.append(self.prey['fitness'][0])\n", + " \n", + " optimal_x = self.prey['position'].squeeze()\n", + " #print(\"\\n f_val: \",f_values)\n", + " #print(\"\\n optimal: \",optimal_x)\n", + " return f_values, optimal_x\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "ils: (37, 142)\n" + ] + } + ], + "source": [ + "#neural Network\n", + "input_layer_size = X_train.shape[1]\n", + "print(\"\\nils: \",X_train.shape)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "import numpy as np\n", + "\n", + "class NeuralNetwork:\n", + " def __init__(self, input_layer_size, hidden_layer_size, output_layer_size, X):\n", + " self.input_layer_size = input_layer_size\n", + " self.hidden_layer_size = hidden_layer_size\n", + " self.output_layer_size = output_layer_size\n", + "\n", + " # Initialize the weights with random values\n", + " self.W1 = np.random.randn(input_layer_size, hidden_layer_size)\n", + " self.W2 = np.random.randn(hidden_layer_size, output_layer_size)\n", + "\n", + " # Initialize the biases with zeros\n", + " self.b1 = np.zeros((1, hidden_layer_size))\n", + " self.b2 = np.zeros((1, output_layer_size))\n", + "\n", + " def sigmoid(self, x):\n", + " x = np.array(x, dtype=float) \n", + " return 1 / (1 + np.exp(-x))\n", + "\n", + " def forward_propagation(self, X):\n", + " # Calculate the hidden layer activations\n", + " self.Z1 = np.dot(X, self.W1) + self.b1\n", + " self.A1 = self.sigmoid(self.Z1)\n", + "\n", + " # Calculate the output layer activations\n", + " self.Z2 = np.dot(self.A1, self.W2) + self.b2\n", + " self.A2 = self.sigmoid(self.Z2)\n", + "\n", + " return self.A2\n", + "\n", + " def backward_propagation(self, X, Y, output, learning_rate):\n", + " # Reshape Y to match the shape of output\n", + " Y = Y.values.reshape(-1, 1)\n", + "\n", + " # Calculate the error in the output layer\n", + " dZ2 = output - Y\n", + " dW2 = np.dot(self.A1.T, dZ2)\n", + " db2 = np.sum(dZ2, axis=0, keepdims=True)\n", + "\n", + " # Calculate the error in the hidden layer\n", + " dZ1 = np.dot(dZ2, self.W2.T) * (self.A1 * (1 - self.A1))\n", + " dW1 = np.dot(X.T, dZ1)\n", + " db1 = np.sum(dZ1, axis=0, keepdims=True)\n", + " self.W1 = self.W1.astype('float64')\n", + " dW1 = dW1.astype('float64')\n", + " # Update the weights and biases\n", + " self.W1 -= learning_rate * dW1\n", + " self.b1 -= learning_rate * db1\n", + " self.W2 -= learning_rate * dW2\n", + " self.b2 -= learning_rate * db2\n", + " def loss(self, y_pred, y_true):\n", + " y_true = y_true.values.reshape(-1, 1)\n", + " y_pred_binary = (y_pred >= 0.5).astype(int)\n", + " y_true_binary = (y_true >= 0.5).astype(int)\n", + " mse = np.mean((y_pred - y_true_binary)**2)\n", + " return mse\n", + "\n", + " def accuracy(self, y_pred, y_true):\n", + " y_true = y_true.values.reshape(-1, 1)\n", + " y_pred_binary = (y_pred >= 0.5).astype(int)\n", + " y_true_binary = (y_true >= 0.5).astype(int)\n", + " return (y_pred_binary == y_true_binary).mean() * 100\n", + "\n", + " def rmsee(self, y_pred, y_train):\n", + " mse = mean_squared_error(y_train, y_pred)\n", + " rmse = mean_squared_error(y_train, y_pred, squared=False)\n", + " return rmse\n", + "\n", + " def train(self, X, Y, epoch=10, alpha=0.01):\n", + " acc = []\n", + " losss = []\n", + " rm = []\n", + " for j in range(epoch):\n", + " out = self.forward_propagation(X)\n", + " self.backward_propagation(X, Y, out, alpha)\n", + " acc.append(self.accuracy(out, Y))\n", + " losss.append(self.loss(out, Y))\n", + " rm.append(self.rmsee(out, Y))\n", + "\n", + " return acc, losss, rm\n", + "\n", + " def predict(self, X):\n", + " # Forward propagation to get the output\n", + " output = self.forward_propagation(X)\n", + "\n", + " # Apply the threshold to classify the output\n", + " predictions = (output >= 0.5).astype(int)\n", + "\n", + " return predictions\n", + "\n", + "\n", + "# Define your ANN architecture\n", + "input_layer_size = X_train.shape[1]\n", + "\n", + "hidden_layer_size = 10\n", + "output_layer_size = 1\n", + "\n", + "weights = np.random.rand(input_layer_size*hidden_layer_size + hidden_layer_size*output_layer_size)\n", + "\n", + "def fitness_function(weights):\n", + " \n", + " nn=NeuralNetwork(input_layer_size,hidden_layer_size,output_layer_size,X_train)\n", + " return nn\n", + " \n", + "\n", + " \n", + "\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy: 83.78378378378379\n", + "Loss: 0.10386266491656121\n", + "Predictions: [[0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [1]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]\n", + " [0]]\n", + "Test Accuracy: 93.75\n", + "Sample 1: Groundwater is not harmful.\n", + "Sample 2: Groundwater is not harmful.\n", + "Sample 3: Groundwater is not harmful.\n", + "Sample 4: Groundwater is not harmful.\n", + "Sample 5: Groundwater is not harmful.\n", + "Sample 6: Groundwater is not harmful.\n", + "Sample 7: Groundwater is not harmful.\n", + "Sample 8: Groundwater is harmful.\n", + "Sample 9: Groundwater is not harmful.\n", + "Sample 10: Groundwater is not harmful.\n", + "Sample 11: Groundwater is not harmful.\n", + "Sample 12: Groundwater is not harmful.\n", + "Sample 13: Groundwater is not harmful.\n", + "Sample 14: Groundwater is not harmful.\n", + "Sample 15: Groundwater is not harmful.\n", + "Sample 16: Groundwater is not harmful.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n", + "c:\\Users\\stuti\\anaconda3\\envs\\deep-learning\\lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "ff=fitness_function(weights)\n", + "val=ff.forward_propagation( X_train)\n", + "\n", + "\n", + "acc,losss,rm=ff.train(X_train,y_train,10,0.01)\n", + "\n", + "\n", + "max_accuracy = acc[0]\n", + "\n", + "for i in range(1, len(acc)):\n", + " if acc[i] > max_accuracy:\n", + " max_accuracy = acc[i]\n", + "\n", + "print(\"Accuracy:\", max_accuracy)\n", + "print(\"Loss:\",losss[len(losss)-1])\n", + "#print(\"\\ntrain: \",acc,losss)\n", + "#print(ff.predict(X_train))\n", + "predictions = ff.predict(X_test)\n", + "\n", + "# Print the predictions\n", + "print(\"Predictions:\", predictions)\n", + "accuracy = ff.accuracy(predictions, y_test)\n", + "print(\"Test Accuracy:\", accuracy)\n", + "\n", + "# Print messages for groundwater quality\n", + "for i, prediction in enumerate(predictions):\n", + " if prediction == 1:\n", + " print(f\"Sample {i+1}: Groundwater is harmful.\")\n", + " else:\n", + " print(f\"Sample {i+1}: Groundwater is not harmful.\")\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plotting accuracy\n", + "plt.subplot(1, 3, 3)\n", + "plt.plot(rm)\n", + "plt.ylabel('RMSE value')\n", + "plt.xlabel(\"Epochs:\")\n", + "plt.show()\n", + "\n", + "# Plotting Loss\n", + "plt.subplot(1, 2, 1)\n", + "plt.plot(losss)\n", + "plt.title(\"Loss over Time\")\n", + "plt.xlabel(\"Epoch\")\n", + "plt.ylabel(\"Loss\")\n", + "\n", + "plt.subplot(1, 2, 2)\n", + "plt.plot(acc)\n", + "plt.title(\"Accuracy over Time\")\n", + "plt.xlabel(\"Epoch\")\n", + "plt.ylabel(\"Accuracy\")\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "deep-learning", + "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.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Groundwater Arsenic Content Detection/models/ann.ipynb b/Groundwater Arsenic Content Detection/models/ann.ipynb new file mode 100644 index 000000000..e69de29bb diff --git a/Groundwater Arsenic Content Detection/models/random_forest.ipynb b/Groundwater Arsenic Content Detection/models/random_forest.ipynb new file mode 100644 index 000000000..a285413eb --- /dev/null +++ b/Groundwater Arsenic Content Detection/models/random_forest.ipynb @@ -0,0 +1,152 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.model_selection import train_test_split, KFold\n", + "from sklearn.ensemble import RandomForestRegressor\n", + "from sklearn.metrics import mean_squared_error, accuracy_score\n", + "import matplotlib.pyplot as plt\n", + "\n", + "data = pd.read_csv('../data/Ground Water .csv')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Fold 1:\n", + "MSE: 0.0105\n", + "RMSE: 0.1022\n", + "\n", + "Fold 2:\n", + "MSE: 0.0006\n", + "RMSE: 0.0245\n", + "\n", + "Fold 3:\n", + "MSE: 0.0000\n", + "RMSE: 0.0053\n", + "\n", + "Fold 4:\n", + "MSE: 0.0076\n", + "RMSE: 0.0871\n", + "\n", + "Fold 5:\n", + "MSE: 0.0009\n", + "RMSE: 0.0305\n" + ] + } + ], + "source": [ + "\n", + "# Fill NaN values in numeric columns with median\n", + "numeric_columns = data.select_dtypes(include='number').columns\n", + "data[numeric_columns] = data[numeric_columns].fillna(data[numeric_columns].median())\n", + "\n", + "# Handle outliers using quantile clipping\n", + "numeric_data = data.select_dtypes(include=[np.number])\n", + "data[numeric_data.columns] = numeric_data.clip(\n", + " lower=numeric_data.quantile(0.01), \n", + " upper=numeric_data.quantile(0.99), \n", + " axis=1\n", + ")\n", + "\n", + "# Convert categorical variables to dummy variables\n", + "data = pd.get_dummies(data)\n", + "\n", + "# Scale the features\n", + "scaler = StandardScaler()\n", + "data[data.select_dtypes(include=['float64']).columns] = scaler.fit_transform(\n", + " data.select_dtypes(include=['float64'])\n", + ")\n", + "\n", + "# Drop specified columns and split features/target\n", + "data = data.drop(data.columns[[1, 2]], axis=1)\n", + "X = data.iloc[:,:-3]\n", + "y = data.iloc[:, -1]\n", + "\n", + "# Split the data\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)\n", + "\n", + "# Initialize Random Forest model\n", + "rf_model = RandomForestRegressor(\n", + " n_estimators=100,\n", + " max_depth=10,\n", + " random_state=42,\n", + " n_jobs=-1\n", + ")\n", + "\n", + "# Perform K-fold cross-validation\n", + "kf = KFold(n_splits=5, shuffle=True, random_state=42)\n", + "mse_scores = []\n", + "accuracy_scores = []\n", + "rmse_scores = []\n", + "\n", + "for fold, (train_index, val_index) in enumerate(kf.split(X_train), 1):\n", + " # Split data for this fold\n", + " X_train_fold = X_train.iloc[train_index]\n", + " X_val_fold = X_train.iloc[val_index]\n", + " y_train_fold = y_train.iloc[train_index]\n", + " y_val_fold = y_train.iloc[val_index]\n", + " \n", + " # Train the model\n", + " rf_model.fit(X_train_fold, y_train_fold)\n", + " \n", + " # Make predictions\n", + " y_pred = rf_model.predict(X_val_fold)\n", + " \n", + " # Calculate metrics\n", + " mse = mean_squared_error(y_val_fold, y_pred)\n", + " rmse = np.sqrt(mse)\n", + " \n", + " # Convert predictions to binary for accuracy calculation\n", + " y_pred_binary = (y_pred >= 0.5).astype(int)\n", + " y_val_binary = (y_val_fold >= 0.5).astype(int)\n", + " acc = accuracy_score(y_val_binary, y_pred_binary) * 100\n", + " \n", + " # Store scores\n", + " mse_scores.append(mse)\n", + " accuracy_scores.append(acc)\n", + " rmse_scores.append(rmse)\n", + " \n", + " print(f\"\\nFold {fold}:\")\n", + " print(f\"MSE: {mse:.4f}\")\n", + " print(f\"RMSE: {rmse:.4f}\")\n", + " " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "deep-learning", + "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.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}