<jupyter_start><jupyter_text>Stability of the Grid System> we’ll build a binary classification model to predict if a grid is stable or unstable using the UCI Electrical Grid Stability Simulated dataset.- author: <NAME>- toc: true- comments: true- categories: [machine-learning, classification]- image: images/sgs-shield.png  Libraries<jupyter_code>import warnings
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
plt.style.use("ggplot")

from sklearn.model_selection import (train_test_split, 
                                     RandomizedSearchCV)
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import ExtraTreeClassifier
from sklearn.metrics import accuracy_score

from lightgbm import LGBMClassifier<jupyter_output><empty_output><jupyter_text>Libraries Settings<jupyter_code>pd.set_option("display.max_columns", None)
pd.set_option("display.max_colwidth", None)<jupyter_output><empty_output><jupyter_text>Overview Electrical grids require a balance between electricity supply and demand in order to be stable. Conventional systems achieve this balance through demand-driven electricity production. For future grids with a high share of inflexible (i.e., renewable) energy source, the concept of demand response is a promising solution. This implies changes in electricity consumption in relation to electricity price changes. In this work, we’ll build a binary classification model to predict if a grid is stable or unstable using the UCI Electrical Grid Stability Simulated dataset {% fn 1 %}.  Data Importation<jupyter_code>elec = pd.read_csv("datasets/Data_for_UCI_named.csv")
elec.head()<jupyter_output><empty_output><jupyter_text>It has 12 primary predictive features and two dependent variables.  Predictive features: - `'tau1'` to `'tau4'`: the reaction time of each network participant, a real value within the range 0.5 to 10 (`'tau1'` corresponds to the supplier node, `'tau2'` to `'tau4'` to the consumer nodes);- `'p1'` to `'p4'`: nominal power produced (positive) or consumed (negative) by each network participant, a real value within the range -2.0 to -0.5 for consumers (`'p2'` to `'p4'`). As the total power consumed equals the total power generated, $p1 (supplier node) = - (p2 + p3 + p4)$;- `'g1'` to `'g4'`: price elasticity coefficient for each network participant, a real value within the range 0.05 to 1.00 (`'g1'` corresponds to the supplier node, `'g2'` to `'g4'` to the consumer nodes; `'g'` stands for `'gamma'`);  Dependent variables:- `'stab'`: the maximum real part of the characteristic differential equation root (if positive, the system is linearly unstable; if negative, linearly stable);- `'stabf'`: a categorical (binary) label (`'stable'` or `'unstable'`).  Data Cleaning<jupyter_code>elec.info()
elec.isnull().sum()<jupyter_output><empty_output><jupyter_text>There is no missing value in the dataset. The dataset has 10000 rows and 14 columns. Because of the direct relationship between 'stab' and 'stabf' ('stabf' = 'stable' if 'stab' <= 0, 'unstable' otherwise), 'stab' should be dropped and 'stabf' will remain as the sole dependent variable (binary classification).<jupyter_code>elec.stabf.value_counts()
elec[(elec.stab<=0) & (elec.stabf!='stable')]
elec[(elec.stab>0) & (elec.stabf!='unstable')]<jupyter_output><empty_output><jupyter_text>All the rows are observing the direct relationship of stab and stabf<jupyter_code>elec.drop(columns=['stab'], inplace=True)
elec.head()
X = elec.drop(columns='stabf')
X.head()
y = elec.stabf
y.head()<jupyter_output><empty_output><jupyter_text>Data modeling We will split the data into an 80-20 train-test split with a random state of “1”. And use the standard scaler to transform the train set (x_train, y_train) and the test set (x_test). We will use scikit learn to train a random forest and extra trees classifier. We'll also use xgboost and lightgbm to train an extreme boosting model and a light gradient boosting model. random_state = 1 for training all models and evaluate on the test set will be used. Also, to improve the Extra Trees Classifier, we will use the following parameters (number of estimators, minimum number of samples, minimum number of samples for leaf node and the number of features to consider when looking for the best split) for the hyperparameter grid needed to run a Randomized Cross Validation Search (RandomizedSearchCV).<jupyter_code>n_estimators = [50, 100, 300, 500, 1000]

min_samples_split = [2, 3, 5, 7, 9]

min_samples_leaf = [1, 2, 4, 6, 8]

max_features = ['auto', 'sqrt', 'log2', None] 

hyperparameter_grid = {'n_estimators': n_estimators,
                       'min_samples_leaf': min_samples_leaf,
                       'min_samples_split': min_samples_split,
                       'max_features': max_features}
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=1)
X_train_scaled = StandardScaler().fit_transform(X_train)
X_test_scaled = StandardScaler().fit_transform(X_test)
rf = RandomForestClassifier(random_state=1)
rf.fit(X_train_scaled, y_train)
rf_pred = rf.predict(X_test_scaled)
rf_pred[:5]
et = ExtraTreeClassifier(random_state=1)
et.fit(X_train_scaled, y_train)
et_pred = et.predict(X_test_scaled)
et_pred[:5]
y_test[:5]
rs = RandomizedSearchCV(rf, param_distributions=hyperparameter_grid, cv=5)
rs.fit(X_train_scaled, y_train)
print(f"Best Score: {round(rs.best_score_, 2)}\nBest Params: {rs.best_params_}")
rf_rs = RandomForestClassifier(n_estimators=500, min_samples_split=3, min_samples_leaf=2, max_features='sqrt')
rf_rs.fit(X_train_scaled, y_train)
rf_rs_pred = rf_rs.predict(X_test_scaled)
rf_rs_pred[:5]
hyperparameter_grid_2 = {'min_samples_leaf': min_samples_leaf,
                       'min_samples_split': min_samples_split,
                       'max_features': max_features}
rs_2 = RandomizedSearchCV(et, param_distributions=hyperparameter_grid_2, cv=5)
rs_2.fit(X_train_scaled, y_train)
print(f"Best Score: {round(rs_2.best_score_, 2)}\nBest Params: {rs_2.best_params_}")
et_rs = ExtraTreeClassifier(min_samples_split=3, min_samples_leaf=8, max_features=None)
et_rs.fit(X_train_scaled, y_train)
et_rs_pred = et_rs.predict(X_test_scaled)
et_rs_pred[:5]
lgbc = LGBMClassifier()
lgbc.fit(X_train_scaled, y_train)
lgbc_pred = lgbc.predict(X_test_scaled)
lgbc_pred[:5]
accuracy_score(y_test, rf_pred)
accuracy_score(y_test, lgbc_pred)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09928430028932542, 'fraction_numerical': 0.01583675955535252, 'mean_word_length': 5.8062176165803105, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '543389', 'license': 'MIT', 'n_tokens_mistral': 2202, 'n_tokens_neox': 2084, 'n_words': 663, 'path': 'Stability of the Grid System.ipynb', 'repo_name': 'VictorOmondi1997/Stability-of-the-Grid-System', 'size': '6574'}