{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Effect of Different Feature Scaling Technique on Random Forest\n\n##### In this notebook I... \n     1. Use following Feature Scaling Technique\n        a. Base (No Feature Scaling)\n        b. Standard Scalar\n        c. Normalization\n        d. Min_Max Scalar\n    \n    2. All Technique has been imported from sklearn Lib\n    3. My WandB Plot has been attached for reference\n\n##### I hope this notebook will help you analyse the Data and would prompt you to reuse my work. Please Upvote if it does. Thanks and Happy Kaggling.","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nsns.set()\n\nimport dask.dataframe as dd\n#import polars as pl\n\nimport datetime \nfrom tqdm import tqdm\n\nimport plotly.express as px\nfrom plotly.subplots import make_subplots\nimport plotly.graph_objects as go\n\nfrom metric import score # Import event detection ap score function\n\n# These are variables to be used by the score function\ncolumn_names = {\n    'series_id_column_name': 'series_id',\n    'time_column_name': 'step',\n    'event_column_name': 'event',\n    'score_column_name': 'score',\n}\n\ntolerances = {\n    'onset': [12, 36, 60, 90, 120, 150, 180, 240, 300, 360], \n    'wakeup': [12, 36, 60, 90, 120, 150, 180, 240, 300, 360]\n}","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-11-07T02:20:13.090352Z","iopub.execute_input":"2023-11-07T02:20:13.090846Z","iopub.status.idle":"2023-11-07T02:20:16.256702Z","shell.execute_reply.started":"2023-11-07T02:20:13.090805Z","shell.execute_reply":"2023-11-07T02:20:16.255238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Importing data","metadata":{}},{"cell_type":"code","source":"train_data = dd.read_parquet(\"/kaggle/input/cmi-baseline-v1/train_data_baseline.parquet\")\ntrain_data.awake = train_data.awake.astype(np.uint8)","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:16.259645Z","iopub.execute_input":"2023-11-07T02:20:16.260405Z","iopub.status.idle":"2023-11-07T02:20:16.639696Z","shell.execute_reply.started":"2023-11-07T02:20:16.260363Z","shell.execute_reply":"2023-11-07T02:20:16.638273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Taking Sub Sample from training set","metadata":{}},{"cell_type":"code","source":"sub_sample_train = train_data[train_data.id_map.isin([0,1,2,3,4,5])]","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:16.641364Z","iopub.execute_input":"2023-11-07T02:20:16.641738Z","iopub.status.idle":"2023-11-07T02:20:16.654804Z","shell.execute_reply.started":"2023-11-07T02:20:16.641708Z","shell.execute_reply":"2023-11-07T02:20:16.653399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Clearing Memory\ndel train_data;","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:16.657940Z","iopub.execute_input":"2023-11-07T02:20:16.658313Z","iopub.status.idle":"2023-11-07T02:20:16.669346Z","shell.execute_reply.started":"2023-11-07T02:20:16.658284Z","shell.execute_reply":"2023-11-07T02:20:16.667957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Feature Engineering","metadata":{}},{"cell_type":"code","source":"#Very basic FE Technique","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:16.671203Z","iopub.execute_input":"2023-11-07T02:20:16.671600Z","iopub.status.idle":"2023-11-07T02:20:16.680928Z","shell.execute_reply.started":"2023-11-07T02:20:16.671564Z","shell.execute_reply":"2023-11-07T02:20:16.679311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Dask to Pandas Conversion\nsub_sample_train = sub_sample_train.compute()","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:16.682792Z","iopub.execute_input":"2023-11-07T02:20:16.683779Z","iopub.status.idle":"2023-11-07T02:20:27.775863Z","shell.execute_reply.started":"2023-11-07T02:20:16.683718Z","shell.execute_reply":"2023-11-07T02:20:27.774898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_sample_train[\"month\"] = sub_sample_train.timestamp.dt.month\n\nsub_sample_train[\"day\"] = sub_sample_train.timestamp.dt.day\n\nsub_sample_train[\"hour\"] = sub_sample_train.timestamp.dt.hour\n\nsub_sample_train[\"hour_multi_min\"] = sub_sample_train.timestamp.dt.hour * sub_sample_train.timestamp.dt.minute","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:27.777016Z","iopub.execute_input":"2023-11-07T02:20:27.777358Z","iopub.status.idle":"2023-11-07T02:20:28.954541Z","shell.execute_reply.started":"2023-11-07T02:20:27.777330Z","shell.execute_reply":"2023-11-07T02:20:28.952823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"feature_names = ['step', 'anglez', 'enmo','month','day', 'hour', 'hour_multi_min']\n\ntarget = 'awake'\n\nlabels = sub_sample_train[target].unique()","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:28.956429Z","iopub.execute_input":"2023-11-07T02:20:28.956838Z","iopub.status.idle":"2023-11-07T02:20:28.982559Z","shell.execute_reply.started":"2023-11-07T02:20:28.956808Z","shell.execute_reply":"2023-11-07T02:20:28.980943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train Test Split","metadata":{}},{"cell_type":"markdown","source":"### Feature Scaling","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import StandardScaler\nfrom sklearn.preprocessing import Normalizer\nfrom sklearn.preprocessing import MinMaxScaler\n\nscaler = StandardScaler()\nsub_sample_train_ss = scaler.fit_transform(sub_sample_train[feature_names])\n\nnorm = Normalizer()\nsub_sample_train_norm = norm.fit_transform(sub_sample_train[feature_names])\n\nmin_max = MinMaxScaler()\nsub_sample_train_mm = min_max.fit_transform(sub_sample_train[feature_names])","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:28.984715Z","iopub.execute_input":"2023-11-07T02:20:28.986163Z","iopub.status.idle":"2023-11-07T02:20:30.241890Z","shell.execute_reply.started":"2023-11-07T02:20:28.986109Z","shell.execute_reply":"2023-11-07T02:20:30.240562Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This script needs these libraries to be installed: \n#   numpy, sklearn\n\nimport wandb\nfrom wandb.sklearn import plot_precision_recall, plot_feature_importances\nfrom wandb.sklearn import plot_class_proportions, plot_learning_curve, plot_roc\n\nimport numpy as np\nfrom sklearn import datasets\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2023-11-07T02:20:30.244965Z","iopub.execute_input":"2023-11-07T02:20:30.245606Z","iopub.status.idle":"2023-11-07T02:20:31.998759Z","shell.execute_reply.started":"2023-11-07T02:20:30.245570Z","shell.execute_reply":"2023-11-07T02:20:31.997225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualization","metadata":{}},{"cell_type":"markdown","source":"## 1. Confusion Matrix","metadata":{}},{"cell_type":"markdown","source":"![](https://github.com/GAURAV2567/Kaggle_CMI/blob/main/CM1.png?raw=true)","metadata":{}},{"cell_type":"markdown","source":"![](https://github.com/GAURAV2567/Kaggle_CMI/blob/main/CM2.png?raw=true)","metadata":{}},{"cell_type":"markdown","source":"**Findings**\n\nTheoratically there should be no change in RF model Performance due to different Feature Scaling Technique. Because RF split the decision tree node based on Individual Features.\n\nBut As per above Fig:-\n* We can clearly see an Outlier from all the FS Technique, which is **Normalization**\n    * As *FN* is significantly low\n    * *Accuracy* is Higher","metadata":{}},{"cell_type":"markdown","source":"## 2. Feature Importance","metadata":{}},{"cell_type":"markdown","source":"![](https://github.com/GAURAV2567/Kaggle_CMI/blob/main/FI1.png?raw=true)","metadata":{"execution":{"iopub.status.busy":"2023-11-06T07:28:35.489335Z","iopub.execute_input":"2023-11-06T07:28:35.490316Z","iopub.status.idle":"2023-11-06T07:28:35.499069Z","shell.execute_reply.started":"2023-11-06T07:28:35.490279Z","shell.execute_reply":"2023-11-06T07:28:35.497171Z"}}},{"cell_type":"markdown","source":"![](https://github.com/GAURAV2567/Kaggle_CMI/blob/main/FI2.png?raw=true)","metadata":{}},{"cell_type":"markdown","source":"**Findings**\n\n* Again we can see that **Normalization** is an Outlier from the rest\n* We can also see that **Normalization** have a very differenct way of assigning weightage.\n\n    * As ENMO is an important feature but its assigning it low weightage. *(Need to investigate further on why?)*\n\n##### Although the *Theory* is not wrong as the difference is not that significantly large but nonetheless there is an *minor difference*. ","metadata":{}},{"cell_type":"markdown","source":"# THE END","metadata":{}},{"cell_type":"markdown","source":"> **You can run the below cell and perform the Experiment yourself on your data. Thanks**","metadata":{"execution":{"iopub.status.busy":"2023-11-06T07:08:53.881729Z","iopub.execute_input":"2023-11-06T07:08:53.882097Z","iopub.status.idle":"2023-11-06T07:08:53.887501Z","shell.execute_reply.started":"2023-11-06T07:08:53.882073Z","shell.execute_reply":"2023-11-06T07:08:53.885893Z"}}},{"cell_type":"code","source":"Exp_type = [\"Base\",\"Standard Scalar\",\"Normalization\",\"Min Max Scaler\"]\ncount = 0\nfor i in sub_sample_train[feature_names],sub_sample_train_ss,sub_sample_train_norm,sub_sample_train_mm:\n    print(Exp_type[count])\n\n    # load and process data\n    #wbcd = datasets.load_breast_cancer()\n    #feature_names = wbcd.feature_names\n    #labels = wbcd.target_names\n\n    test_size = 0.2\n    X_train, X_test, y_train, y_test = train_test_split(i,sub_sample_train[target].to_numpy().ravel(), test_size=test_size)\n\n    # Train model\n\n    model = RandomForestClassifier(n_estimators=500,min_samples_leaf=25,random_state=42,n_jobs=-1)\n    model.fit(X_train, y_train)\n    model_params = model.get_params()\n\n    #Saving Model\n    #import pickle\n    #with open('rf_classifier_g_v1_sub_sample', 'wb') as f:\n    #    pickle.dump(model, f)\n\n    #with open('/kaggle/input/rf-classifier-g-v1-sub-sample/rf_classifier_g_v1_sub_sample', 'rb') as f:\n        #model = pickle.load(f)\n\n    # get predictions\n    y_pred = model.predict(X_test)\n    y_probas = model.predict_proba(X_test)\n    #importances = model.feature_importances_\n    #indices = np.argsort(importances)[::-1]\n\n    # Initializaing W&B\n\n    from kaggle_secrets import UserSecretsClient\n    user_secrets = UserSecretsClient()\n    key = user_secrets.get_secret(\"wandb\")\n    wandb.login(key=key)\n\n    # start a new wandb run and add your model hyperparameters\n    wandb.init(project='CMI_sub_sample_Feature_Scaling_v2',name=f\"Experiment_{Exp_type[count]}\", config=model_params)\n\n    # Add additional configs to wandb\n    wandb.config.update({\"test_size\" : test_size,\n                        \"train_len\" : len(X_train),\n                        \"test_len\" : len(X_test)})\n\n    # log additional visualisations to wandb\n    #plot_class_proportions(y_train, y_test, labels)\n    #plot_learning_curve(model, X_train, y_train)\n    #plot_roc(y_test, y_probas, labels)\n    #plot_precision_recall(y_test, y_probas, labels)\n    #plot_feature_importances(model)\n\n    # Plotting feature importances\n    fig = px.bar(x=feature_names, \n           y=model.feature_importances_,\n           title='Random forest feature importances'\n                )\n    wandb.log({\"plot-Random forest feature importances\": fig})\n\n    fig\n\n    from sklearn.metrics import accuracy_score,confusion_matrix,classification_report\n\n    cf2=confusion_matrix(y_test,y_pred,labels=[1,0])\n    cf2\n\n    import plotly.figure_factory as ff\n\n    group_names = ['True Pos', 'False Pos', 'False Neg', 'True Neu']\n\n    confusion_matrix_values = confusion_matrix(y_test, y_pred, labels=[1, 0]).flatten()\n    group_counts = ['{0:0.0f}'.format(value) for value in confusion_matrix_values]\n\n    group_percentages = ['{0:.2%}'.format(value) for value in confusion_matrix_values / np.sum(confusion_matrix_values)]\n\n    labels = [f'{v1}<br>{v2}<br>{v3}' for v1, v2, v3 in zip(group_names, group_counts, group_percentages)]\n    labels = np.array(labels).reshape(2, 2)\n\n    z = confusion_matrix(y_test, y_pred, labels=[1, 0])\n\n    fig = ff.create_annotated_heatmap(z, x=[0,1], y=[1, 0], annotation_text=labels, colorscale='RdYlGn',font_colors=[\"black\"],showscale=True)\n\n    # Set custom tick values for x and y axes\n    fig.update_xaxes(tickvals=[0, 1], ticktext=['1', '0'])\n    fig.update_yaxes(tickvals=[0, 1], ticktext=[f'<b>{np.unique(y_pred,return_counts=True)[1][0]}</b> \\t 0', f'<b>{np.unique(y_pred,return_counts=True)[1][1]}</b> \\t 1'])\n\n    fig.update_layout(\n        title=f'RandomForest Classifier<br>Accuracy: {accuracy_score(y_test, y_pred)}',\n        title_x=0.5,  # Center the title horizontally\n        title_y=0.05,  # Position the title at the bottom\n        xaxis_title='Predicted label',\n        yaxis_title='True label',\n\n        # Change the figure size\n        width=500,  # Adjust the width as desired\n        height=500  # Adjust the height as desired\n    )\n\n    # To display the Plotly figure in Jupyter Notebook or another environment, you can simply use:\n    # fig.show()\n\n    # To save the figure to an HTML file:\n    # fig.write_html('confusion_matrix_plotly.html')\n    wandb.log({\"plot-Confusion Matrix\": fig})\n    fig\n\n    clf_report2=classification_report(y_test,y_pred,output_dict=True)\n    print(classification_report(y_test,y_pred))\n\n    wandb.summary[\"classification_report\"] = classification_report(y_test,y_pred)\n\n    # [optional] finish the wandb run, necessary in notebooks\n    wandb.finish()\n    count +=1","metadata":{"execution":{"iopub.status.busy":"2023-11-01T05:16:45.185528Z","iopub.execute_input":"2023-11-01T05:16:45.185916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}