24 KiB
Executable File
24 KiB
Executable File
In [21]:
# Standard Library Imports
import os
import importlib.util
import nbformat
from tempfile import NamedTemporaryFile
from typing import Tuple, Dict
# Third-Party Library Imports
import numpy as np
import pandas as pd
from nbconvert import PythonExporter
# Scikit-Learn Imports
from sklearn.preprocessing import MinMaxScaler, StandardScaler, PolynomialFeatures, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.metrics import (accuracy_score, precision_score, recall_score, f1_score,
mean_squared_error, mean_absolute_error, r2_score)
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
In [22]:
def task1_linear_regression() -> Dict[str, float]:
"""
Performs linear regression on a predefined dataset and returns performance metrics.
**Dataset Assumption:**
- The dataset is located at `"datasets/task1_data.csv"`.
- It should contain the following columns:
- `"X_train"`: Training feature values (numerical).
- `"y_train"`: Training target values.
- `"X_test"`: Testing feature values (numerical).
- `"y_test"`: Testing target values.
**Process:**
1. Load the dataset from `"datasets/task1_data.csv"`.
2. Extract training and testing data.
3. Train a linear regression model on `X_train, y_train`.
4. Use the trained model to predict `y_test` values.
5. Compute evaluation metrics: **MSE, RMSE, MAE, R² Score**.
**Output (Dictionary with Regression Metrics):**
```python
{
"MSE": <Mean Squared Error>,
"RMSE": <Root Mean Squared Error>,
"MAE": <Mean Absolute Error>,
"R2": <R² Score>
}
```
"""
df = pd.read_csv('datasets/task1_data.csv')
X_train, y_train, X_test, y_test = df['X_train'].to_numpy().reshape((-1, 1)), df['y_train'], df['X_test'].to_numpy().reshape((-1, 1)), df['y_test']
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
return {
'MSE': mean_squared_error(y_test, y_pred),
'RMSE': mean_squared_error(y_test, y_pred) ** 0.5,
'MAE': mean_absolute_error(y_test, y_pred),
'R2': r2_score(y_test, y_pred),
}In [23]:
def task1_polynomial_regression() -> Dict[str, float]:
"""
Performs polynomial regression using GridSearchCV to find the best polynomial degree.
**Process:**
1. Load the dataset and extract `X_train, y_train, X_test, y_test`.
2. Define a **pipeline** with polynomial feature transformation and linear regression.
3. Use **GridSearchCV** (with 8-fold cross-validation) to determine the best polynomial degree (range: **2 to 10**).
4. Train the best polynomial regression model and evaluate its performance.
5. Compute and return:
- **Best polynomial degree (`best_degree`)**
- **Mean Squared Error (MSE)**
**Expected Output:**
```
{
"best_degree": <Optimal Polynomial Degree>,
"MSE": <Mean Squared Error>
}
```
"""
df = pd.read_csv('datasets/task1_data.csv')
X_train, y_train, X_test, y_test = df['X_train'].to_numpy().reshape((-1, 1)), df['y_train'], df['X_test'].to_numpy().reshape((-1, 1)), df['y_test']
pipeline = Pipeline([
('polynomial', PolynomialFeatures()),
('linear', LinearRegression())
])
grid_search = GridSearchCV(pipeline, {
'polynomial__degree': range(2, 11)
}, cv=8)
grid_search.fit(X_train, y_train)
return {
'best_degree': grid_search.best_params_['polynomial__degree'],
'MSE': mean_squared_error(y_test, grid_search.best_estimator_.predict(X_test)),
}In [24]:
def task2_preprocessing() -> Tuple[pd.DataFrame, pd.DataFrame, pd.Series, pd.Series]:
"""
Preprocesses the Pokémon dataset by handling missing values, encoding categorical data,
and applying feature scaling before returning train-test splits, ensuring class balance.
**Dataset Assumption:**
- The dataset is located at `"datasets/pokemon_modified.csv"`.
**Process:**
1. Load the dataset and remove redundant columns.
2. Handle missing values:
- Mean imputation for **"height_m"** and **"weight_kg"**.
- Median imputation for **"percentage_male"**.
3. Perform **one-hot encoding** on `"type1"`.
4. Ensure **"is_legendary"** is present as the target variable.
5. Split the dataset into **80% training, 20% testing** using **stratification** to maintain class balance.
6. Apply feature scaling (**StandardScaler**).
7. Return the preprocessed train-test splits.
"""
df2 = pd.read_csv('datasets/pokemon_modified.csv')
y = df2.is_legendary
df2 = df2.drop(['is_legendary', 'name', 'classification'], axis=1)
mean_imputation = SimpleImputer(strategy='mean')
mean_imputation.fit(df2[['height_m', 'weight_kg']])
df2[['height_m', 'weight_kg']] = mean_imputation.transform(df2[['height_m', 'weight_kg']])
median_imputation = SimpleImputer(strategy='median')
median_imputation.fit(df2[['percentage_male']])
df2[['percentage_male']] = median_imputation.transform(df2[['percentage_male']])
ohe = OneHotEncoder(sparse_output=False, drop='first')
ohe.fit(df2[['type1']])
df2 = np.concatenate([df2.drop('type1', axis=1), ohe.transform(df2[['type1']])], axis=1)
X_train, X_test, y_train, y_test = train_test_split(df2, y, test_size=0.2, stratify=y)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
return pd.DataFrame(X_train), pd.DataFrame(X_test), y_train, y_testIn [25]:
def task2_model_comparison() -> Dict[str, Dict[str, float]]:
"""
Trains and evaluates three classification models using GridSearchCV for hyperparameter tuning.
**Dataset Assumption:**
- The preprocessed dataset is obtained from `task2_preprocessing()`, which returns:
- `X_train`: Training features (scaled)
- `X_test`: Testing features (scaled)
- `y_train`: Training labels
- `y_test`: Testing labels
**Process:**
1. Load the preprocessed dataset from `task2_preprocessing()`.
2. Train the following models:
- **Logistic Regression** (Hyperparameters: `C`, `penalty`, `solver`).
- **K-Nearest Neighbors (KNN)** (Hyperparameters: `n_neighbors`, `weights`, `metric`).
- **Gaussian Naive Bayes** (No hyperparameter tuning required).
3. Evaluate the models using the following metrics:
- **Accuracy**
- **Precision**
- **Recall**
- **F1 Score**
4. Return a dictionary with model names as keys and evaluation metrics as values.
**Expected Output:**
```python
{
"Logistic Regression": {"accuracy": <float>, "precision": <float>, "recall": <float>, "f1_score": <float>},
"KNN": {"accuracy": <float>, "precision": <float>, "recall": <float>, "f1_score": <float>},
"Naive Bayes": {"accuracy": <float>, "precision": <float>, "recall": <float>, "f1_score": <float>}
}
```
"""
X_train, X_test, y_train, y_test = task2_preprocessing()
log_reg = GridSearchCV(LogisticRegression(), {
'C': [10 ** i for i in range(-10, 11)],
'penalty': ['l1', 'l2'],
'solver': ['liblinear'],
# 'solver': ['lbfgs', 'liblinear', 'newton-cg', 'newton-cholesky', 'sag', 'saga']
})
log_reg.fit(X_train, y_train)
knn = GridSearchCV(KNeighborsClassifier(), {
'n_neighbors': range(1, 15),
'weights': ['uniform', 'distance'],
'metric': ['minkowski', 'euclidean', 'manhattan', 'cosine', 'chebyshev']
})
knn.fit(X_train, y_train)
gnb = GaussianNB()
gnb.fit(X_train, y_train)
return {
"Logistic Regression": {"accuracy": accuracy_score(y_test, log_reg.predict(X_test)), "precision": precision_score(y_test, log_reg.predict(X_test)), "recall": recall_score(y_test, log_reg.predict(X_test)), "f1_score": f1_score(y_test, log_reg.predict(X_test))},
"KNN": {"accuracy": accuracy_score(y_test, knn.predict(X_test)), "precision": precision_score(y_test, knn.predict(X_test)), "recall": recall_score(y_test, knn.predict(X_test)), "f1_score": f1_score(y_test, knn.predict(X_test))},
"Naive Bayes": {"accuracy": accuracy_score(y_test, gnb.predict(X_test)), "precision": precision_score(y_test, gnb.predict(X_test)), "recall": recall_score(y_test, gnb.predict(X_test)), "f1_score": f1_score(y_test, gnb.predict(X_test))}
}
task2_model_comparison()Out [25]:
{'Logistic Regression': {'accuracy': 0.9937888198757764,
'precision': 1.0,
'recall': 0.9285714285714286,
'f1_score': 0.9629629629629629},
'KNN': {'accuracy': 0.9813664596273292,
'precision': 0.9230769230769231,
'recall': 0.8571428571428571,
'f1_score': 0.8888888888888888},
'Naive Bayes': {'accuracy': 0.8385093167701864,
'precision': 0.34210526315789475,
'recall': 0.9285714285714286,
'f1_score': 0.5}}