# Apply Regression Techniques for Imbalanced Dataset
import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import SGDClassifier, LogisticRegression
from sklearn.multiclass import OneVsOneClassifier
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.metrics import classification_report
# 1. Load dataset
columns = [
    "duration", "protocol_type", "service", "flag", "src_bytes", "dst_bytes",
    "land", "wrong_fragment", "urgent", "hot", "num_failed_logins",
    "logged_in", "num_compromised", "root_shell", "su_attempted", "num_root",
    "num_file_creations", "num_shells", "num_access_files",
    "num_outbound_cmds", "is_host_login", "is_guest_login", "count",
    "srv_count", "serror_rate", "srv_serror_rate", "rerror_rate",
    "srv_rerror_rate", "same_srv_rate", "diff_srv_rate",
    "srv_diff_host_rate", "dst_host_count", "dst_host_srv_count",
    "dst_host_same_srv_rate", "dst_host_diff_srv_rate",
    "dst_host_same_src_port_rate", "dst_host_srv_diff_host_rate",
    "dst_host_serror_rate", "dst_host_srv_serror_rate",
    "dst_host_rerror_rate", "dst_host_srv_rerror_rate", "outcome"
]
dataset = pd.read_csv("./kdd/kddcup.data", names=columns, nrows=1000000)
print(dataset.head())
print("Dataset Shape:", dataset.shape)
# 2. Encode target label
print("Unique outcomes:")
print(sorted(dataset["outcome"].unique()))
labels_enc = LabelEncoder()
labels = labels_enc.fit_transform(dataset["outcome"])
labels_map = labels_enc.classes_
print("Labels:")
print(labels_map)
# 3. Convert categorical data
dataset.drop("outcome", axis=1, inplace=True)
observations = pd.get_dummies(dataset, sparse=True)
del dataset
print("Observation Shape:")
print(observations.shape)
# 4. Train test split
x_train, x_test, y_train, y_test = train_test_split(
    observations, labels, train_size=0.5, random_state=101)
del observations
# 5. Normalized confusion matrix
def plot_normalised_confusion_matrix(
    cm, labels, title="Matrix", cmap=plt.cm.Blues):
    plt.figure(figsize=(6, 6))
    cm_normalized = cm.astype("float") / cm.sum(axis=1)[:, np.newaxis]
    plt.imshow(cm_normalized, cmap=cmap)
    plt.title(title)
    plt.xlabel("Predicted Label")
    plt.ylabel("True Label")
    plt.show()
# 6. SGD classifier
clf = SGDClassifier(loss="log_loss", random_state=101)
clf.fit(x_train, y_train)
y_train_pred = clf.predict(x_train)
y_test_pred = clf.predict(x_test)
print("\nTRAIN ACCURACY:")
print(accuracy_score(y_train, y_train_pred))
print("\nTRAIN CONFUSION MATRIX:")
print(confusion_matrix(y_train, y_train_pred))
print("\nTRAIN CLASSIFICATION REPORT:")
print(classification_report(y_train, y_train_pred))
print("\nTEST ACCURACY:")
print(accuracy_score(y_test, y_test_pred))
print("\nTEST CONFUSION MATRIX:")
print(confusion_matrix(y_test, y_test_pred))
print("\nTEST CLASSIFICATION REPORT:")
print(classification_report(y_test, y_test_pred))
# 7. Balance classes
random.seed(101)
def sample_class(y, label, min_samples=500,
                 max_samples=20000):
    rows = np.where(y == label)[0]
    n = min(max(len(rows), min_samples), max_samples)
    return [random.choice(rows) for _ in range(n)]
train_idx = []
for label in np.unique(y_train):
    train_idx.extend(sample_class(y_train, label))
x_train_balanced = x_train.iloc[train_idx]
y_train_balanced = y_train[train_idx]
print("Balanced Training Shape:", x_train_balanced.shape)
# 8. Grid search
parameters = {
    "estimator__loss": ["log_loss", "hinge"],
    "estimator__alpha": [1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001]
}
clfgs = GridSearchCV(
    OneVsOneClassifier(SGDClassifier(random_state=101, n_jobs=1)),
    param_grid=parameters, cv=3, n_jobs=1,
    scoring="accuracy"
)
clfgs.fit(x_train_balanced, y_train_balanced)
clf = clfgs.best_estimator_
print("\nBest Parameters:", clfgs.best_params_)
# 9. Prediction after grid search
y_train_pred = clf.predict(x_train_balanced)
y_test_pred = clf.predict(x_test)
print("\nGRID SEARCH TRAIN ACCURACY:")
print(accuracy_score(y_train_balanced, y_train_pred))
print("\nGRID SEARCH TEST ACCURACY:")
print(accuracy_score(y_test, y_test_pred))
# 10. Logistic regression
clf = OneVsOneClassifier(
    LogisticRegression(max_iter=1000, n_jobs=1))
clf.fit(x_train_balanced, y_train_balanced)
y_train_pred = clf.predict(x_train_balanced)
y_test_pred = clf.predict(x_test)
print("\nLOGISTIC REGRESSION TRAIN ACCURACY:")
print(accuracy_score(y_train_balanced, y_train_pred))
print("\nTRAIN CONFUSION MATRIX:")
print(confusion_matrix(y_train_balanced, y_train_pred))
print("\nTRAIN CLASSIFICATION REPORT:")
print(classification_report(y_train_balanced, y_train_pred))
print("\nTEST ACCURACY:")
print(accuracy_score(y_test, y_test_pred))
print("\nTEST CLASSIFICATION REPORT:")
print(classification_report(y_test, y_test_pred))
