Wednesday, September 2, 2026

TYBCS- DS & DA Assignment 5

 Assignment 5
Supervised Machine Learning Models for Classification (KNN, Random Forest)

 Lab Assignment
SET A:
1. Implement the K-Nearest Neighbors (KNN) algorithm on the Wine dataset. Perform data preprocessing, model training, testing, and performance evaluation. Compare the results for different values of K.

pip install pandas numpy matplotlib seaborn scikit-learn

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import (
    accuracy_score,
    precision_score,
    recall_score,
    f1_score,
    confusion_matrix,
    classification_report
)

# =========================================================
# STEP 1: LOAD WINE DATASET
# =========================================================

wine = load_wine()

# Convert dataset into DataFrame
df = pd.DataFrame(
    wine.data,
    columns=wine.feature_names
)

# Add target column
df["Target"] = wine.target

print("========== WINE DATASET ==========")
print(df.head())

# =========================================================
# STEP 2: DATASET INFORMATION
# =========================================================

print("\n========== DATASET INFORMATION ==========")
df.info()

print("\n========== DATASET SHAPE ==========")
print(df.shape)

print("\n========== STATISTICAL DESCRIPTION ==========")
print(df.describe())

print("\n========== MISSING VALUES ==========")
print(df.isnull().sum())

print("\n========== CLASS DISTRIBUTION ==========")
print(df["Target"].value_counts())

# =========================================================
# STEP 3: DEFINE FEATURES AND TARGET
# =========================================================

X = df.drop("Target", axis=1)
y = df["Target"]

print("\nNumber of Features:", X.shape[1])
print("Number of Classes:", len(np.unique(y)))

# =========================================================
# STEP 4: SPLIT DATA INTO TRAINING AND TESTING
# =========================================================

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42,
    stratify=y
)

print("\n========== DATA SPLIT ==========")
print("Training Records:", len(X_train))
print("Testing Records :", len(X_test))

# =========================================================
# STEP 5: FEATURE SCALING
# =========================================================

scaler = StandardScaler()

X_train_scaled = scaler.fit_transform(X_train)

X_test_scaled = scaler.transform(X_test)

print("\nFeature scaling completed.")

# =========================================================
# STEP 6: APPLY KNN FOR DIFFERENT VALUES OF K
# =========================================================

k_values = [1, 3, 5, 7, 9, 11, 13, 15]

results = []

print("\n========== KNN PERFORMANCE ==========")

for k in k_values:

    # Create KNN model
    knn = KNeighborsClassifier(
        n_neighbors=k
    )

    # Train model
    knn.fit(
        X_train_scaled,
        y_train
    )

    # Predict test data
    y_pred = knn.predict(
        X_test_scaled
    )

    # Calculate metrics
    accuracy = accuracy_score(
        y_test,
        y_pred
    )

    precision = precision_score(
        y_test,
        y_pred,
        average="weighted",
        zero_division=0
    )

    recall = recall_score(
        y_test,
        y_pred,
        average="weighted",
        zero_division=0
    )

    f1 = f1_score(
        y_test,
        y_pred,
        average="weighted",
        zero_division=0
    )

    results.append({
        "K": k,
        "Accuracy": accuracy,
        "Precision": precision,
        "Recall": recall,
        "F1-Score": f1
    })

    print(
        "K =", k,
        "| Accuracy =", round(accuracy, 4),
        "| Precision =", round(precision, 4),
        "| Recall =", round(recall, 4),
        "| F1 =", round(f1, 4)
    )

# =========================================================
# STEP 7: CREATE COMPARISON TABLE
# =========================================================

results_df = pd.DataFrame(results)

print("\n========== K VALUE COMPARISON ==========")
print(
    results_df.round(4)
)

# =========================================================
# STEP 8: IDENTIFY BEST K
# =========================================================

best_index = results_df["Accuracy"].idxmax()

best_k = results_df.loc[
    best_index,
    "K"
]

best_accuracy = results_df.loc[
    best_index,
    "Accuracy"
]

print("\n========== BEST K VALUE ==========")

print(
    "Best K:",
    int(best_k)
)

print(
    "Best Accuracy:",
    round(best_accuracy, 4)
)

# =========================================================
# STEP 9: PLOT K VS ACCURACY
# =========================================================

plt.figure(figsize=(9, 6))

plt.plot(
    results_df["K"],
    results_df["Accuracy"],
    marker="o",
    linewidth=2
)

plt.xlabel("Value of K")
plt.ylabel("Accuracy")

plt.title(
    "KNN Accuracy for Different Values of K"
)

plt.xticks(k_values)

plt.grid(
    True,
    linestyle="--",
    alpha=0.5
)

plt.tight_layout()
plt.show()

# =========================================================
# STEP 10: TRAIN FINAL MODEL USING BEST K
# =========================================================

final_model = KNeighborsClassifier(
    n_neighbors=int(best_k)
)

final_model.fit(
    X_train_scaled,
    y_train
)

final_pred = final_model.predict(
    X_test_scaled
)

# =========================================================
# STEP 11: CONFUSION MATRIX
# =========================================================

cm = confusion_matrix(
    y_test,
    final_pred
)

print("\n========== CONFUSION MATRIX ==========")
print(cm)

plt.figure(figsize=(7, 5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    xticklabels=wine.target_names,
    yticklabels=wine.target_names
)

plt.xlabel("Predicted Class")
plt.ylabel("Actual Class")

plt.title(
    "KNN Confusion Matrix"
)

plt.tight_layout()
plt.show()

# =========================================================
# STEP 12: CLASSIFICATION REPORT
# =========================================================

print("\n========== CLASSIFICATION REPORT ==========")

print(
    classification_report(
        y_test,
        final_pred,
        target_names=wine.target_names,
        zero_division=0
    )
)

# =========================================================
# STEP 13: PREDICT A NEW WINE SAMPLE
# =========================================================

# Example wine sample
new_wine = [[
    13.2,     # alcohol
    2.7,      # malic acid
    2.4,      # ash
    18.5,     # alcalinity of ash
    100,      # magnesium
    2.5,      # total phenols
    2.3,      # flavanoids
    0.3,      # nonflavanoid phenols
    1.7,      # proanthocyanins
    4.0,      # color intensity
    1.0,      # hue
    3.0,      # od280/od315
    800       # proline
]]

new_wine_scaled = scaler.transform(
    new_wine
)

prediction = final_model.predict(
    new_wine_scaled
)

print("\n========== NEW WINE PREDICTION ==========")

print(
    "Predicted Wine Class:",
    prediction[0]
)

print(
    "Wine Type:",
    wine.target_names[prediction[0]]
)


2. Apply the Random Forest algorithm on the Heart Disease dataset to predict the presence of heart disease. Preprocess the data, evaluate the model using accuracy and confusion matrix, and identify important features affecting the prediction.

 
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report

# ------------------------------------------------------------
# Step 1: Load the Heart Disease Dataset
# ------------------------------------------------------------

df = pd.read_csv("heart.csv")

print("========== FIRST 5 RECORDS ==========")
print(df.head())

print("\n========== DATASET INFORMATION ==========")
df.info()

print("\n========== DATASET SHAPE ==========")
print(df.shape)

print("\n========== STATISTICAL DESCRIPTION ==========")
print(df.describe())

# ------------------------------------------------------------
# Step 2: Check Missing Values
# ------------------------------------------------------------

print("\n========== MISSING VALUES ==========")
print(df.isnull().sum())

# Remove missing records if present
df = df.dropna()

# ------------------------------------------------------------
# Step 3: Separate Features and Target
# ------------------------------------------------------------

X = df.drop("target", axis=1)
y = df["target"]

print("\n========== FEATURES ==========")
print(X.columns.tolist())

print("\n========== TARGET DISTRIBUTION ==========")
print(y.value_counts())

# ------------------------------------------------------------
# Step 4: Split Dataset into Training and Testing Data
# ------------------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42,
    stratify=y
)

print("\nTraining samples:", X_train.shape[0])
print("Testing samples :", X_test.shape[0])

# ------------------------------------------------------------
# Step 5: Create Random Forest Model
# ------------------------------------------------------------

model = RandomForestClassifier(
    n_estimators=100,
    random_state=42
)

# ------------------------------------------------------------
# Step 6: Train the Model
# ------------------------------------------------------------

model.fit(X_train, y_train)

print("\nRandom Forest model trained successfully.")

# ------------------------------------------------------------
# Step 7: Make Predictions
# ------------------------------------------------------------

y_pred = model.predict(X_test)

print("\n========== PREDICTIONS ==========")
print(y_pred)

# ------------------------------------------------------------
# Step 8: Calculate Accuracy
# ------------------------------------------------------------

accuracy = accuracy_score(y_test, y_pred)

print("\n========== MODEL ACCURACY ==========")
print("Accuracy:", round(accuracy, 4))
print("Accuracy (%):", round(accuracy * 100, 2), "%")

# ------------------------------------------------------------
# Step 9: Confusion Matrix
# ------------------------------------------------------------

cm = confusion_matrix(y_test, y_pred)

print("\n========== CONFUSION MATRIX ==========")
print(cm)

plt.figure(figsize=(7, 5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    cmap="Blues",
    xticklabels=["No Disease", "Disease"],
    yticklabels=["No Disease", "Disease"]
)

plt.xlabel("Predicted Class")
plt.ylabel("Actual Class")
plt.title("Random Forest - Confusion Matrix")

plt.tight_layout()
plt.show()

# ------------------------------------------------------------
# Step 10: Classification Report
# ------------------------------------------------------------

print("\n========== CLASSIFICATION REPORT ==========")

print(
    classification_report(
        y_test,
        y_pred,
        target_names=["No Disease", "Disease"],
        zero_division=0
    )
)

# ------------------------------------------------------------
# Step 11: Calculate Feature Importance
# ------------------------------------------------------------

feature_importance = pd.DataFrame({
    "Feature": X.columns,
    "Importance": model.feature_importances_
})

feature_importance = feature_importance.sort_values(
    by="Importance",
    ascending=False
)

print("\n========== FEATURE IMPORTANCE ==========")
print(feature_importance)

# ------------------------------------------------------------
# Step 12: Visualize Important Features
# ------------------------------------------------------------

plt.figure(figsize=(10, 6))

sns.barplot(
    data=feature_importance,
    x="Importance",
    y="Feature"
)

plt.xlabel("Importance Score")
plt.ylabel("Features")
plt.title("Important Features for Heart Disease Prediction")

plt.tight_layout()
plt.show()

# ------------------------------------------------------------
# Step 13: Display Top 5 Important Features
# ------------------------------------------------------------

print("\n========== TOP 5 IMPORTANT FEATURES ==========")

print(feature_importance.head(5))

# ------------------------------------------------------------
# Step 14: Predict a New Patient
# ------------------------------------------------------------

new_patient = [[
    55,     # age
    1,      # sex
    1,      # cp
    130,    # trestbps
    250,    # chol
    0,      # fbs
    1,      # restecg
    150,    # thalach
    0,      # exang
    1.2,    # oldpeak
    1,      # slope
    0,      # ca
    2       # thal
]]

prediction = model.predict(new_patient)

print("\n========== NEW PATIENT PREDICTION ==========")

if prediction[0] == 1:
    print("Prediction: Presence of Heart Disease")
else:
    print("Prediction: Absence of Heart Disease")

heart.csv

age,sex,cp,trestbps,chol,fbs,restecg,thalach,exang,oldpeak,slope,ca,thal,target
67,0,2,130,309,0,0,124,0,3.4,1,2,1,1
57,1,3,113,310,1,0,176,0,1.7,2,0,1,1
43,1,0,161,216,0,0,182,0,1.1,2,1,2,0
71,1,2,113,277,1,2,196,1,0.9,2,1,2,1
36,0,1,114,167,0,2,164,1,1.1,0,3,2,1
49,0,0,165,174,1,0,107,1,1.2,2,1,3,1
67,0,0,146,203,0,2,200,1,0.9,0,0,1,0
47,0,0,127,207,0,0,165,1,4.0,1,2,3,1
51,1,2,134,216,0,0,98,1,3.4,2,1,3,1
39,0,1,133,253,1,1,163,1,0.2,0,3,2,1
39,0,0,176,323,0,2,147,1,1.2,0,1,2,1
52,0,3,95,173,0,0,197,1,0.1,2,0,0,0
64,0,0,105,263,1,0,106,0,2.2,1,3,0,1
68,0,0,151,181,1,2,191,1,2.1,1,1,3,1
52,1,2,144,324,0,1,96,1,3.7,1,3,1,1
31,0,2,117,235,0,1,135,1,1.4,0,0,2,1
50,1,1,125,300,1,0,102,1,3.7,0,2,2,1
30,0,3,136,343,1,2,129,1,4.4,0,0,3,1
52,1,2,101,276,1,1,131,1,0.4,0,0,0,1
72,0,0,110,304,1,2,98,1,3.6,1,0,1,1
58,0,1,154,279,1,2,139,1,2.7,2,0,0,1
66,1,0,96,166,0,0,116,1,2.2,0,2,0,0
30,1,0,95,253,1,1,155,1,1.9,0,2,0,1
49,1,2,142,310,0,0,94,1,3.5,1,3,0,1
61,0,1,106,286,0,1,118,0,2.9,2,1,2,1
40,1,3,163,192,0,1,126,0,3.6,2,2,2,1
50,0,3,131,325,1,1,127,1,4.1,1,2,0,1
72,0,2,126,188,0,1,172,1,2.8,1,1,1,1
53,1,2,103,319,0,1,97,0,4.4,2,2,3,1
77,1,1,113,175,1,2,198,1,2.7,0,0,1,1
55,0,3,142,248,0,0,154,0,2.9,2,0,1,1
70,0,3,174,199,0,2,175,0,2.5,1,1,1,1
56,1,3,97,302,1,1,106,0,0.4,0,3,0,1
44,1,0,114,301,0,0,160,0,3.3,0,3,2,1
43,1,3,118,162,0,1,178,0,2.5,1,1,1,1
75,0,0,148,209,0,0,134,1,2.0,1,1,0,1
72,0,1,127,284,1,2,93,0,4.1,1,0,1,1
31,0,0,118,206,1,0,125,1,1.3,2,3,1,1
65,0,1,169,185,1,0,159,1,2.4,2,2,0,1
35,0,3,166,322,0,0,120,0,3.1,0,0,2,1
49,0,3,130,169,0,0,108,0,3.6,1,1,2,1
37,1,1,132,214,1,0,150,1,2.1,0,3,3,1
67,0,2,178,157,0,1,197,0,3.8,0,2,0,1
46,0,1,119,293,0,0,143,0,3.5,0,2,3,1
32,0,2,112,291,1,0,128,1,0.3,0,0,3,1
53,1,0,176,264,1,2,180,1,0.2,1,3,3,1
42,0,0,160,292,0,0,163,0,2.8,0,3,2,1
37,0,0,148,241,0,2,179,1,1.6,1,1,0,0
54,1,3,129,247,0,1,108,0,0.9,1,3,3,1
30,0,0,174,215,1,0,128,0,2.6,2,3,0,1
48,0,2,155,181,1,2,156,0,1.5,1,0,0,1
56,0,0,135,340,1,2,134,1,2.4,2,3,2,1
75,0,1,127,235,1,1,102,1,2.1,1,2,3,1
35,0,1,162,200,0,0,181,1,2.6,1,0,3,1
72,1,3,127,302,1,0,147,1,1.8,1,0,0,1
36,1,1,108,335,1,2,109,1,3.1,2,1,1,1
75,1,2,115,212,1,0,181,0,0.8,2,3,2,1
63,0,0,142,339,1,2,161,0,3.1,0,1,2,1
42,0,3,114,274,1,0,150,0,1.9,2,2,2,1
45,0,0,102,299,0,2,194,0,3.9,2,0,2,0
64,1,0,101,207,0,0,128,1,2.3,2,0,3,1
68,0,2,161,207,1,1,90,0,4.4,2,0,3,1
32,0,1,111,235,0,0,92,1,2.7,0,2,1,1
30,1,1,127,198,1,0,166,0,1.0,2,2,2,0
34,0,0,142,329,1,1,181,1,3.7,1,1,2,1
70,1,3,170,319,0,0,151,1,1.6,1,1,0,1
32,1,1,153,219,0,1,152,0,1.6,2,1,3,0
57,1,3,180,164,1,0,114,0,0.1,2,3,2,1
46,0,1,116,203,1,2,145,0,2.5,1,0,1,0
54,0,3,124,337,1,2,122,0,2.4,1,0,1,1
72,0,2,132,250,0,0,127,1,1.6,0,1,3,1
62,0,3,145,157,1,0,95,0,4.0,1,0,1,1
38,0,2,148,202,1,0,147,0,0.6,1,1,1,1
64,0,2,102,209,1,2,133,1,1.5,2,3,3,1
42,0,3,121,257,0,0,134,0,1.4,1,3,2,1
59,1,2,121,154,1,2,121,0,0.4,0,2,2,1
76,0,0,115,252,1,1,134,0,2.2,1,3,1,1
43,1,2,124,345,0,2,150,0,3.1,2,1,1,1
36,0,1,122,155,1,2,136,0,2.3,2,3,2,1
42,0,3,158,258,1,1,110,1,0.7,1,2,3,1
51,0,0,163,265,0,2,169,0,1.7,2,0,1,0
68,1,3,155,243,1,0,174,0,0.0,0,1,0,1
49,1,1,142,196,0,0,164,0,3.9,0,0,3,1
44,1,1,113,248,0,2,190,0,0.4,1,2,1,1
73,1,1,98,204,1,0,125,0,2.7,1,2,1,1
46,0,2,129,317,1,2,188,1,4.4,1,2,0,1
75,1,2,158,201,1,0,108,0,2.4,2,0,0,1
52,0,3,143,293,1,0,109,1,4.2,0,0,2,1
54,0,3,111,162,0,2,146,1,1.1,0,0,3,1
53,1,0,138,263,1,0,107,0,3.4,2,0,3,1
73,1,0,124,273,0,2,136,0,2.4,0,2,2,1
69,1,3,140,255,1,0,194,0,3.2,1,2,3,1
57,1,2,100,307,1,0,138,0,0.3,1,1,3,1
43,1,1,131,296,1,1,103,1,0.7,1,1,3,1
73,1,3,118,294,0,1,104,0,0.6,0,0,3,1
29,1,0,140,269,1,2,120,0,3.1,1,3,3,1
53,1,2,147,212,1,1,90,0,3.8,2,3,0,1
35,0,3,154,168,1,2,143,0,3.4,2,2,3,1
37,1,3,157,241,1,1,92,0,0.1,0,2,0,1
52,1,2,179,207,0,0,105,0,3.9,2,2,3,1


3. Use the KNN algorithm to classify emails as spam or non-spam based on selected features. Evaluate the classifier using suitable performance metrics. 
Attributes: [ World_Counr, Links_Count, Special_Characters, Sender_Reputation, Spam]


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import (
    accuracy_score,
    precision_score,
    recall_score,
    f1_score,
    confusion_matrix,
    classification_report
)

# ------------------------------------------------------------
# Step 1: Load Dataset
# ------------------------------------------------------------

df = pd.read_csv("email_spam.csv")

print("========== FIRST 5 RECORDS ==========")
print(df.head())

print("\n========== DATASET INFORMATION ==========")
df.info()

print("\n========== DATASET SHAPE ==========")
print(df.shape)

print("\n========== MISSING VALUES ==========")
print(df.isnull().sum())

# ------------------------------------------------------------
# Step 2: Data Preprocessing
# ------------------------------------------------------------

# Remove missing values
df = df.dropna()

# Convert categorical World_Counr into numerical values
df = pd.get_dummies(
    df,
    columns=["World_Counr"],
    drop_first=True
)

print("\n========== PREPROCESSED DATA ==========")
print(df.head())

# ------------------------------------------------------------
# Step 3: Separate Features and Target
# ------------------------------------------------------------

X = df.drop("Spam", axis=1)
y = df["Spam"]

print("\n========== FEATURES ==========")
print(X.columns.tolist())

print("\n========== TARGET DISTRIBUTION ==========")
print(y.value_counts())

# ------------------------------------------------------------
# Step 4: Split Dataset
# ------------------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42,
    stratify=y
)

print("\nTraining records:", X_train.shape[0])
print("Testing records :", X_test.shape[0])

# ------------------------------------------------------------
# Step 5: Feature Scaling
# ------------------------------------------------------------

scaler = StandardScaler()

X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# ------------------------------------------------------------
# Step 6: Train KNN Classifier
# ------------------------------------------------------------

k = 5

model = KNeighborsClassifier(n_neighbors=k)

model.fit(X_train_scaled, y_train)

print("\nKNN model trained successfully.")
print("Value of K:", k)

# ------------------------------------------------------------
# Step 7: Make Predictions
# ------------------------------------------------------------

y_pred = model.predict(X_test_scaled)

print("\n========== PREDICTIONS ==========")
print(y_pred)

# ------------------------------------------------------------
# Step 8: Performance Evaluation
# ------------------------------------------------------------

accuracy = accuracy_score(y_test, y_pred)

precision = precision_score(
    y_test,
    y_pred,
    zero_division=0
)

recall = recall_score(
    y_test,
    y_pred,
    zero_division=0
)

f1 = f1_score(
    y_test,
    y_pred,
    zero_division=0
)

print("\n========== PERFORMANCE METRICS ==========")
print("Accuracy  :", round(accuracy, 4))
print("Precision :", round(precision, 4))
print("Recall    :", round(recall, 4))
print("F1-Score  :", round(f1, 4))

# ------------------------------------------------------------
# Step 9: Classification Report
# ------------------------------------------------------------

print("\n========== CLASSIFICATION REPORT ==========")

print(
    classification_report(
        y_test,
        y_pred,
        target_names=["Non-Spam", "Spam"],
        zero_division=0
    )
)

# ------------------------------------------------------------
# Step 10: Confusion Matrix
# ------------------------------------------------------------

cm = confusion_matrix(y_test, y_pred)

print("\n========== CONFUSION MATRIX ==========")
print(cm)

plt.figure(figsize=(7, 5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    cmap="Blues",
    xticklabels=["Non-Spam", "Spam"],
    yticklabels=["Non-Spam", "Spam"]
)

plt.xlabel("Predicted Class")
plt.ylabel("Actual Class")
plt.title("KNN Email Spam Classification - Confusion Matrix")

plt.tight_layout()
plt.show()

# ------------------------------------------------------------
# Step 11: Compare Different Values of K
# ------------------------------------------------------------

k_values = [1, 3, 5, 7, 9, 11, 13]

accuracy_values = []

print("\n========== K VALUE COMPARISON ==========")

for k in k_values:

    knn = KNeighborsClassifier(n_neighbors=k)

    knn.fit(X_train_scaled, y_train)

    prediction = knn.predict(X_test_scaled)

    acc = accuracy_score(y_test, prediction)

    accuracy_values.append(acc)

    print(
        "K =", k,
        "| Accuracy =", round(acc, 4)
    )

# ------------------------------------------------------------
# Step 12: Plot K vs Accuracy
# ------------------------------------------------------------

plt.figure(figsize=(8, 5))

plt.plot(
    k_values,
    accuracy_values,
    marker="o",
    linewidth=2
)

plt.xlabel("Value of K")
plt.ylabel("Accuracy")
plt.title("KNN: K Value vs Accuracy")
plt.xticks(k_values)
plt.grid(True)

plt.tight_layout()
plt.show()

# ------------------------------------------------------------
# Step 13: Find Best K
# ------------------------------------------------------------

best_index = np.argmax(accuracy_values)

best_k = k_values[best_index]
best_accuracy = accuracy_values[best_index]

print("\n========== BEST K ==========")
print("Best K:", best_k)
print("Best Accuracy:", round(best_accuracy, 4))
print("Best Accuracy (%):", round(best_accuracy * 100, 2), "%")

Sample email_spam.csv

If you need a dataset for the program, use this format:

World_Counr,Links_Count,Special_Characters,Sender_Reputation,Spam
USA,2,5,92,0
India,1,3,88,0
UK,3,6,85,0
Canada,2,4,90,0
Australia,1,2,95,0
Germany,2,5,87,0
France,1,3,91,0
Japan,2,4,93,0
India,8,18,25,1
USA,12,22,18,1
UK,10,20,30,1
Canada,9,17,35,1
Australia,11,25,15,1
Germany,7,16,40,1
France,13,28,12,1
Japan,9,21,32,1
India,3,7,82,0
USA,4,8,78,0
UK,2,5,89,0
Canada,1,4,94,0
Australia,10,19,22,1
Germany,8,15,38,1
France,12,24,20,1
Japan,7,18,42,1
India,2,6,86,0
USA,3,5,90,0
UK,1,3,96,0
Canada,4,7,80,0
Australia,9,20,28,1
Germany,11,23,17,1
France,8,19,33,1
Japan,10,22,24,1
India,1,2,93,0
USA,2,4,91,0
UK,3,6,84,0
Canada,2,5,88,0
Australia,12,26,14,1
Germany,9,18,31,1
France,11,21,19,1
Japan,8,17,36,1


4. Apply the Random Forest algorithm to predict house prices based on property attributes. Evaluate the model performance and analyze the importance of features influencing the prediction.

# Import required libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# ----------------------------------------------------
# 1. Load California Housing Dataset
# ----------------------------------------------------

housing = fetch_california_housing()

# Create DataFrame
X = pd.DataFrame(housing.data, columns=housing.feature_names)
y = pd.Series(housing.target, name="HousePrice")

print("First 5 records:")
print(X.head())

print("\nDataset Shape:", X.shape)

# ----------------------------------------------------
# 2. Display Dataset Information
# ----------------------------------------------------

print("\nDataset Information:")
print(X.info())

print("\nStatistical Summary:")
print(X.describe())

# ----------------------------------------------------
# 3. Check Missing Values
# ----------------------------------------------------

print("\nMissing Values:")
print(X.isnull().sum())

# ----------------------------------------------------
# 4. Split Dataset into Training and Testing Sets
# ----------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.20,
    random_state=42
)

print("\nTraining Data Shape:", X_train.shape)
print("Testing Data Shape:", X_test.shape)

# ----------------------------------------------------
# 5. Create Random Forest Regression Model
# ----------------------------------------------------

model = RandomForestRegressor(
    n_estimators=100,
    random_state=42,
    max_depth=None,
    n_jobs=-1
)

# ----------------------------------------------------
# 6. Train the Model
# ----------------------------------------------------

model.fit(X_train, y_train)

# ----------------------------------------------------
# 7. Make Predictions
# ----------------------------------------------------

y_pred = model.predict(X_test)

print("\nFirst 10 Actual Prices:")
print(y_test.head(10).values)

print("\nFirst 10 Predicted Prices:")
print(y_pred[:10])

# ----------------------------------------------------
# 8. Evaluate Model Performance
# ----------------------------------------------------

mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)

print("\n----- Model Performance -----")
print("Mean Absolute Error (MAE):", mae)
print("Mean Squared Error (MSE):", mse)
print("Root Mean Squared Error (RMSE):", rmse)
print("R² Score:", r2)

# ----------------------------------------------------
# 9. Feature Importance
# ----------------------------------------------------

feature_importance = pd.DataFrame({
    "Feature": X.columns,
    "Importance": model.feature_importances_
})

feature_importance = feature_importance.sort_values(
    by="Importance",
    ascending=False
)

print("\n----- Feature Importance -----")
print(feature_importance)

# ----------------------------------------------------
# 10. Plot Feature Importance
# ----------------------------------------------------

plt.figure(figsize=(10, 6))

plt.bar(
    feature_importance["Feature"],
    feature_importance["Importance"]
)

plt.xlabel("Features")
plt.ylabel("Importance")
plt.title("Feature Importance - Random Forest")
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

# ----------------------------------------------------
# 11. Actual vs Predicted Prices
# ----------------------------------------------------

plt.figure(figsize=(8, 6))

plt.scatter(y_test, y_pred, alpha=0.5)

plt.xlabel("Actual House Price")
plt.ylabel("Predicted House Price")
plt.title("Actual vs Predicted House Prices")

plt.tight_layout()
plt.show()


SET B:
1. Implement a KNN classifier on a Movie dataset. Preprocess the data, evaluate the model usingaccuracy and confusion matrix.

# --------------------------------------------------
# 1. Import Libraries
# --------------------------------------------------

import pandas as pd
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, ConfusionMatrixDisplay


# --------------------------------------------------
# 2. Create Movie Dataset
# --------------------------------------------------

data = {
    'Action': [8, 7, 9, 2, 3, 1, 8, 6, 2, 9, 4, 1],
    'Comedy': [2, 3, 1, 8, 9, 7, 2, 4, 8, 1, 6, 9],
    'Drama':  [3, 4, 2, 7, 8, 9, 4, 5, 7, 2, 6, 8],
    'Rating': [8.5, 8.0, 8.7, 7.5, 8.2, 7.8,
               8.8, 7.9, 7.4, 8.9, 7.6, 8.1],
    'Genre': [
        'Action',
        'Action',
        'Action',
        'Comedy',
        'Comedy',
        'Drama',
        'Action',
        'Comedy',
        'Drama',
        'Action',
        'Drama',
        'Comedy'
    ]
}

df = pd.DataFrame(data)

print("Movie Dataset:")
print(df)


# --------------------------------------------------
# 3. Check Missing Values
# --------------------------------------------------

print("\nMissing Values:")
print(df.isnull().sum())


# --------------------------------------------------
# 4. Separate Features and Target
# --------------------------------------------------

X = df[['Action', 'Comedy', 'Drama', 'Rating']]
y = df['Genre']


# --------------------------------------------------
# 5. Split Dataset
# --------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.25,
    random_state=42,
    stratify=y
)


# --------------------------------------------------
# 6. Feature Scaling
# --------------------------------------------------

scaler = StandardScaler()

X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)


# --------------------------------------------------
# 7. Create KNN Classifier
# --------------------------------------------------

knn = KNeighborsClassifier(n_neighbors=3)


# --------------------------------------------------
# 8. Train the Model
# --------------------------------------------------

knn.fit(X_train, y_train)


# --------------------------------------------------
# 9. Make Predictions
# --------------------------------------------------

y_pred = knn.predict(X_test)

print("\nActual Values:")
print(y_test.values)

print("\nPredicted Values:")
print(y_pred)


# --------------------------------------------------
# 10. Calculate Accuracy
# --------------------------------------------------

accuracy = accuracy_score(y_test, y_pred)

print("\nAccuracy:", accuracy)
print("Accuracy Percentage:", accuracy * 100, "%")


# --------------------------------------------------
# 11. Confusion Matrix
# --------------------------------------------------

cm = confusion_matrix(y_test, y_pred)

print("\nConfusion Matrix:")
print(cm)


# --------------------------------------------------
# 12. Display Confusion Matrix Graphically
# --------------------------------------------------

disp = ConfusionMatrixDisplay(
    confusion_matrix=cm,
    display_labels=knn.classes_
)

disp.plot()

plt.title("KNN - Confusion Matrix")
plt.show()

 

 2. Develop a Random Forest model to classify mobile phones into different price ranges based on their specifications. Evaluate the classifier and identify the most influential features.

# --------------------------------------------------
# 1. Import Libraries
# --------------------------------------------------

import pandas as pd
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import (
    accuracy_score,
    classification_report,
    confusion_matrix,
    ConfusionMatrixDisplay
)


# --------------------------------------------------
# 2. Load Dataset
# --------------------------------------------------

df = pd.read_csv("mobile_price.csv")

print("First 5 records:")
print(df.head())

print("\nDataset Shape:")
print(df.shape)


# --------------------------------------------------
# 3. Dataset Information
# --------------------------------------------------

print("\nDataset Information:")
df.info()

print("\nStatistical Summary:")
print(df.describe())


# --------------------------------------------------
# 4. Check Missing Values
# --------------------------------------------------

print("\nMissing Values:")
print(df.isnull().sum())


# --------------------------------------------------
# 5. Separate Features and Target
# --------------------------------------------------

X = df.drop("price_range", axis=1)

y = df["price_range"]

print("\nFeatures:")
print(X.columns)

print("\nTarget Classes:")
print(y.unique())


# --------------------------------------------------
# 6. Split Dataset into Training and Testing
# --------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42,
    stratify=y
)

print("\nTraining Data:", X_train.shape)
print("Testing Data:", X_test.shape)


# --------------------------------------------------
# 7. Create Random Forest Classifier
# --------------------------------------------------

rf_model = RandomForestClassifier(
    n_estimators=100,
    random_state=42,
    n_jobs=-1
)


# --------------------------------------------------
# 8. Train the Model
# --------------------------------------------------

rf_model.fit(X_train, y_train)


# --------------------------------------------------
# 9. Make Predictions
# --------------------------------------------------

y_pred = rf_model.predict(X_test)

print("\nActual Values:")
print(y_test.values[:20])

print("\nPredicted Values:")
print(y_pred[:20])


# --------------------------------------------------
# 10. Calculate Accuracy
# --------------------------------------------------

accuracy = accuracy_score(y_test, y_pred)

print("\n----- Model Accuracy -----")
print("Accuracy:", accuracy)
print("Accuracy Percentage:", accuracy * 100, "%")


# --------------------------------------------------
# 11. Classification Report
# --------------------------------------------------

print("\n----- Classification Report -----")

print(
    classification_report(
        y_test,
        y_pred,
        target_names=[
            "Low",
            "Medium",
            "High",
            "Very High"
        ]
    )
)


# --------------------------------------------------
# 12. Confusion Matrix
# --------------------------------------------------

cm = confusion_matrix(y_test, y_pred)

print("\n----- Confusion Matrix -----")
print(cm)


# --------------------------------------------------
# 13. Display Confusion Matrix
# --------------------------------------------------

disp = ConfusionMatrixDisplay(
    confusion_matrix=cm,
    display_labels=[
        "Low",
        "Medium",
        "High",
        "Very High"
    ]
)

disp.plot()

plt.title("Random Forest - Mobile Price Classification")

plt.show()


# --------------------------------------------------
# 14. Calculate Feature Importance
# --------------------------------------------------

feature_importance = pd.DataFrame({
    "Feature": X.columns,
    "Importance": rf_model.feature_importances_
})

feature_importance = feature_importance.sort_values(
    by="Importance",
    ascending=False
)


# --------------------------------------------------
# 15. Display Feature Importance
# --------------------------------------------------

print("\n----- Feature Importance -----")
print(feature_importance)


# --------------------------------------------------
# 16. Plot Feature Importance
# --------------------------------------------------

plt.figure(figsize=(12, 6))

plt.bar(
    feature_importance["Feature"],
    feature_importance["Importance"]
)

plt.xlabel("Features")
plt.ylabel("Importance")
plt.title("Feature Importance in Random Forest")

plt.xticks(rotation=90)

plt.tight_layout()

plt.show() 

 
SET C:
1. Apply KNN and Random Forest algorithms to classify Instagram influencers into different engagement categories based on followers, likes, comments, and posts. Compare the performance of both classifiers.

# --------------------------------------------------
# 1. Import Libraries
# --------------------------------------------------

import pandas as pd
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import (
    accuracy_score,
    confusion_matrix,
    ConfusionMatrixDisplay,
    classification_report
)


# --------------------------------------------------
# 2. Create Instagram Influencer Dataset
# --------------------------------------------------

data = {
    'Followers': [
        5000, 8000, 12000, 15000,
        20000, 25000, 30000, 35000,
        45000, 50000, 60000, 70000,
        80000, 90000, 100000, 120000,
        150000, 180000, 200000, 250000
    ],

    'Likes': [
        300, 500, 800, 1000,
        1500, 2000, 2500, 3000,
        4000, 5000, 6000, 7000,
        8500, 10000, 12000, 15000,
        18000, 22000, 26000, 32000
    ],

    'Comments': [
        20, 30, 50, 70,
        90, 120, 150, 180,
        220, 250, 300, 350,
        400, 450, 500, 600,
        750, 900, 1100, 1300
    ],

    'Posts': [
        10, 15, 20, 25,
        30, 35, 40, 45,
        50, 55, 60, 65,
        70, 75, 80, 85,
        90, 95, 100, 110
    ],

    'Engagement': [
        'Low', 'Low', 'Low', 'Low',
        'Medium', 'Medium', 'Medium', 'Medium',
        'Medium', 'Medium', 'Medium', 'Medium',
        'High', 'High', 'High', 'High',
        'High', 'High', 'High', 'High'
    ]
}

df = pd.DataFrame(data)


# --------------------------------------------------
# 3. Display Dataset
# --------------------------------------------------

print("Instagram Influencer Dataset:")
print(df)

print("\nDataset Shape:")
print(df.shape)


# --------------------------------------------------
# 4. Check Missing Values
# --------------------------------------------------

print("\nMissing Values:")
print(df.isnull().sum())


# --------------------------------------------------
# 5. Separate Features and Target
# --------------------------------------------------

X = df[['Followers', 'Likes', 'Comments', 'Posts']]

y = df['Engagement']


# --------------------------------------------------
# 6. Split Dataset
# --------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.30,
    random_state=42,
    stratify=y
)


# --------------------------------------------------
# 7. Feature Scaling for KNN
# --------------------------------------------------

scaler = StandardScaler()

X_train_scaled = scaler.fit_transform(X_train)

X_test_scaled = scaler.transform(X_test)


# ==================================================
# 8. KNN CLASSIFIER
# ==================================================

knn = KNeighborsClassifier(n_neighbors=3)

knn.fit(X_train_scaled, y_train)

y_pred_knn = knn.predict(X_test_scaled)


# --------------------------------------------------
# 9. KNN Accuracy
# --------------------------------------------------

knn_accuracy = accuracy_score(y_test, y_pred_knn)

print("\n========== KNN CLASSIFIER ==========")

print("KNN Accuracy:", knn_accuracy)

print("KNN Accuracy Percentage:",
      knn_accuracy * 100, "%")


# --------------------------------------------------
# 10. KNN Classification Report
# --------------------------------------------------

print("\nKNN Classification Report:")

print(
    classification_report(
        y_test,
        y_pred_knn,
        zero_division=0
    )
)


# --------------------------------------------------
# 11. KNN Confusion Matrix
# --------------------------------------------------

cm_knn = confusion_matrix(
    y_test,
    y_pred_knn,
    labels=['Low', 'Medium', 'High']
)

print("\nKNN Confusion Matrix:")
print(cm_knn)


# ==================================================
# 12. RANDOM FOREST CLASSIFIER
# ==================================================

rf = RandomForestClassifier(
    n_estimators=100,
    random_state=42
)

rf.fit(X_train, y_train)

y_pred_rf = rf.predict(X_test)


# --------------------------------------------------
# 13. Random Forest Accuracy
# --------------------------------------------------

rf_accuracy = accuracy_score(y_test, y_pred_rf)

print("\n========== RANDOM FOREST ==========")

print("Random Forest Accuracy:",
      rf_accuracy)

print("Random Forest Accuracy Percentage:",
      rf_accuracy * 100, "%")


# --------------------------------------------------
# 14. Random Forest Classification Report
# --------------------------------------------------

print("\nRandom Forest Classification Report:")

print(
    classification_report(
        y_test,
        y_pred_rf,
        zero_division=0
    )
)


# --------------------------------------------------
# 15. Random Forest Confusion Matrix
# --------------------------------------------------

cm_rf = confusion_matrix(
    y_test,
    y_pred_rf,
    labels=['Low', 'Medium', 'High']
)

print("\nRandom Forest Confusion Matrix:")
print(cm_rf)


# ==================================================
# 16. Compare Accuracy
# ==================================================

print("\n========== PERFORMANCE COMPARISON ==========")

print("KNN Accuracy:",
      knn_accuracy * 100, "%")

print("Random Forest Accuracy:",
      rf_accuracy * 100, "%")


if knn_accuracy > rf_accuracy:
    print("\nKNN performed better.")

elif rf_accuracy > knn_accuracy:
    print("\nRandom Forest performed better.")

else:
    print("\nBoth classifiers have the same accuracy.")


# ==================================================
# 17. Plot Confusion Matrix - KNN
# ==================================================

disp1 = ConfusionMatrixDisplay(
    confusion_matrix=cm_knn,
    display_labels=['Low', 'Medium', 'High']
)

disp1.plot()

plt.title("KNN - Instagram Engagement Classification")

plt.show()


# ==================================================
# 18. Plot Confusion Matrix - Random Forest
# ==================================================

disp2 = ConfusionMatrixDisplay(
    confusion_matrix=cm_rf,
    display_labels=['Low', 'Medium', 'High']
)

disp2.plot()

plt.title("Random Forest - Instagram Engagement Classification")

plt.show()


# ==================================================
# 19. Feature Importance - Random Forest
# ==================================================

importance = pd.DataFrame({
    'Feature': X.columns,
    'Importance': rf.feature_importances_
})

importance = importance.sort_values(
    by='Importance',
    ascending=False
)

print("\n========== FEATURE IMPORTANCE ==========")

print(importance)


# --------------------------------------------------
# 20. Plot Feature Importance
# --------------------------------------------------

plt.figure(figsize=(8, 5))

plt.bar(
    importance['Feature'],
    importance['Importance']
)

plt.xlabel("Features")
plt.ylabel("Importance")

plt.title(
    "Random Forest Feature Importance"
)

plt.xticks(rotation=45)

plt.tight_layout()

plt.show()


2. Implement KNN and Random Forest algorithms to predict product rating categories based on customer reviews, purchase history, and product features. Compare the effectiveness of both classifiers.

 # --------------------------------------------------
# 1. Import Libraries
# --------------------------------------------------

import pandas as pd
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import (
    accuracy_score,
    confusion_matrix,
    ConfusionMatrixDisplay,
    classification_report
)


# --------------------------------------------------
# 2. Create Product Dataset
# --------------------------------------------------

data = {
    'Review_Score': [
        1, 2, 2, 3, 3,
        4, 4, 5, 5, 4,
        2, 3, 3, 4, 5,
        1, 2, 4, 5, 5,
        2, 3, 4, 4, 5
    ],

    'Purchase_Frequency': [
        1, 1, 2, 2, 3,
        3, 4, 5, 5, 4,
        1, 2, 3, 4, 5,
        1, 2, 4, 5, 5,
        2, 3, 4, 4, 5
    ],

    'Product_Quality': [
        2, 2, 3, 3, 3,
        4, 4, 5, 5, 4,
        2, 3, 3, 4, 5,
        1, 2, 4, 5, 5,
        2, 3, 4, 4, 5
    ],

    'Price': [
        500, 600, 700, 800, 900,
        1000, 1100, 1200, 1300, 1250,
        650, 750, 850, 1050, 1400,
        450, 550, 1150, 1350, 1500,
        600, 800, 1100, 1250, 1450
    ],

    'Rating_Category': [
        'Low', 'Low', 'Low', 'Medium', 'Medium',
        'High', 'High', 'High', 'High', 'High',
        'Low', 'Medium', 'Medium', 'High', 'High',
        'Low', 'Low', 'High', 'High', 'High',
        'Low', 'Medium', 'High', 'High', 'High'
    ]
}

df = pd.DataFrame(data)


# --------------------------------------------------
# 3. Display Dataset
# --------------------------------------------------

print("Product Dataset:")
print(df)

print("\nDataset Shape:")
print(df.shape)


# --------------------------------------------------
# 4. Check Missing Values
# --------------------------------------------------

print("\nMissing Values:")
print(df.isnull().sum())


# --------------------------------------------------
# 5. Separate Features and Target
# --------------------------------------------------

X = df[
    [
        'Review_Score',
        'Purchase_Frequency',
        'Product_Quality',
        'Price'
    ]
]

y = df['Rating_Category']


# --------------------------------------------------
# 6. Split Dataset
# --------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.30,
    random_state=42,
    stratify=y
)


# ==================================================
# 7. FEATURE SCALING FOR KNN
# ==================================================

scaler = StandardScaler()

X_train_scaled = scaler.fit_transform(X_train)

X_test_scaled = scaler.transform(X_test)


# ==================================================
# 8. KNN CLASSIFIER
# ==================================================

knn = KNeighborsClassifier(n_neighbors=3)

knn.fit(X_train_scaled, y_train)

y_pred_knn = knn.predict(X_test_scaled)


# --------------------------------------------------
# 9. KNN Accuracy
# --------------------------------------------------

knn_accuracy = accuracy_score(
    y_test,
    y_pred_knn
)

print("\n========== KNN CLASSIFIER ==========")

print("KNN Accuracy:",
      knn_accuracy)

print("KNN Accuracy Percentage:",
      knn_accuracy * 100, "%")


# --------------------------------------------------
# 10. KNN Classification Report
# --------------------------------------------------

print("\nKNN Classification Report:")

print(
    classification_report(
        y_test,
        y_pred_knn,
        zero_division=0
    )
)


# --------------------------------------------------
# 11. KNN Confusion Matrix
# --------------------------------------------------

labels = ['Low', 'Medium', 'High']

cm_knn = confusion_matrix(
    y_test,
    y_pred_knn,
    labels=labels
)

print("\nKNN Confusion Matrix:")
print(cm_knn)


# ==================================================
# 12. RANDOM FOREST CLASSIFIER
# ==================================================

rf = RandomForestClassifier(
    n_estimators=100,
    random_state=42
)

rf.fit(X_train, y_train)

y_pred_rf = rf.predict(X_test)


# --------------------------------------------------
# 13. Random Forest Accuracy
# --------------------------------------------------

rf_accuracy = accuracy_score(
    y_test,
    y_pred_rf
)

print("\n========== RANDOM FOREST ==========")

print("Random Forest Accuracy:",
      rf_accuracy)

print("Random Forest Accuracy Percentage:",
      rf_accuracy * 100, "%")


# --------------------------------------------------
# 14. Random Forest Classification Report
# --------------------------------------------------

print("\nRandom Forest Classification Report:")

print(
    classification_report(
        y_test,
        y_pred_rf,
        zero_division=0
    )
)


# --------------------------------------------------
# 15. Random Forest Confusion Matrix
# --------------------------------------------------

cm_rf = confusion_matrix(
    y_test,
    y_pred_rf,
    labels=labels
)

print("\nRandom Forest Confusion Matrix:")
print(cm_rf)


# ==================================================
# 16. Compare Both Models
# ==================================================

print("\n========== PERFORMANCE COMPARISON ==========")

print("KNN Accuracy:",
      knn_accuracy * 100, "%")

print("Random Forest Accuracy:",
      rf_accuracy * 100, "%")


if knn_accuracy > rf_accuracy:

    print("\nKNN performed better.")

elif rf_accuracy > knn_accuracy:

    print("\nRandom Forest performed better.")

else:

    print("\nBoth models have the same accuracy.")


# ==================================================
# 17. Plot KNN Confusion Matrix
# ==================================================

disp1 = ConfusionMatrixDisplay(
    confusion_matrix=cm_knn,
    display_labels=labels
)

disp1.plot()

plt.title(
    "KNN - Product Rating Classification"
)

plt.show()


# ==================================================
# 18. Plot Random Forest Confusion Matrix
# ==================================================

disp2 = ConfusionMatrixDisplay(
    confusion_matrix=cm_rf,
    display_labels=labels
)

disp2.plot()

plt.title(
    "Random Forest - Product Rating Classification"
)

plt.show()


# ==================================================
# 19. Random Forest Feature Importance
# ==================================================

importance = pd.DataFrame({
    'Feature': X.columns,
    'Importance': rf.feature_importances_
})

importance = importance.sort_values(
    by='Importance',
    ascending=False
)

print("\n========== FEATURE IMPORTANCE ==========")

print(importance)


# ==================================================
# 20. Plot Feature Importance
# ==================================================

plt.figure(figsize=(8, 5))

plt.bar(
    importance['Feature'],
    importance['Importance']
)

plt.xlabel("Features")
plt.ylabel("Importance")

plt.title(
    "Random Forest Feature Importance"
)

plt.xticks(rotation=45)

plt.tight_layout()

plt.show()

 

TYBCS DS & DA Assignment 4

 Assignment 4
Supervised Machine Learning Models for Regression
(Linear Regression, Polynomial Regression, Logistic Regression)

Lab Assignment
SET A
1. Apply Linear Regression on a YouTube Video dataset to predict video views using relevant video attributes. Visualize the relationship between the predictor and target variable using a scatter plot and regression line.

 import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

# Create YouTube video dataset
data = {
    "Video": [
        "Video 1", "Video 2", "Video 3", "Video 4", "Video 5",
        "Video 6", "Video 7", "Video 8", "Video 9", "Video 10",
        "Video 11", "Video 12", "Video 13", "Video 14", "Video 15"
    ],
    "Likes": [
        1200, 2500, 3200, 4500, 5200,
        6800, 7500, 8200, 9500, 11000,
        12500, 14000, 15500, 17000, 19000
    ],
    "Views": [
        15000, 28000, 35000, 50000, 62000,
        75000, 82000, 95000, 110000, 125000,
        145000, 160000, 180000, 195000, 220000
    ]
}

df = pd.DataFrame(data)

print("YouTube Dataset:")
print(df)

# Save dataset
df.to_csv("youtube_videos.csv", index=False)

# Independent variable (Predictor)
X = df[["Likes"]]

# Dependent variable (Target)
y = df["Views"]

# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Create Linear Regression model
model = LinearRegression()

# Train the model
model.fit(X_train, y_train)

# Predict views
y_pred = model.predict(X_test)

# Display model parameters
print("\nLinear Regression Equation:")
print("Views =", model.intercept_, "+", model.coef_[0], "* Likes")

# Display predictions
result = pd.DataFrame({
    "Actual Views": y_test,
    "Predicted Views": y_pred
})

print("\nActual vs Predicted Views:")
print(result)

# Model evaluation
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print("\nMean Squared Error:", mse)
print("R2 Score:", r2)

# Predict views for a new video
new_likes = [[10000]]
predicted_views = model.predict(new_likes)

print("\nPredicted views for 10,000 likes:",
      round(predicted_views[0], 2))

# Scatter plot with regression line
plt.figure(figsize=(9, 6))

plt.scatter(
    df["Likes"],
    df["Views"],
    label="Actual Data"
)

plt.plot(
    df["Likes"],
    model.predict(df[["Likes"]]),
    linewidth=2,
    label="Regression Line"
)

plt.xlabel("Number of Likes")
plt.ylabel("Number of Views")
plt.title("YouTube Likes vs Video Views - Linear Regression")
plt.legend()
plt.grid(True, linestyle="--", alpha=0.5)

plt.tight_layout()
plt.show()

 

2. Apply Logistic Regression on an Online Gaming dataset to classify players as Casual or Professional gamers based on features such as daily play time, achievements unlocked, in-game purchases, and gaming level. Evaluate the model using Accuracy, Precision, Recall, F1-Score, and Confusion Matrix.

 import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (
    accuracy_score,
    precision_score,
    recall_score,
    f1_score,
    confusion_matrix,
    classification_report
)

# --------------------------------------------------
# Step 1: Create Online Gaming Dataset
# --------------------------------------------------

data = {
    "Player": [
        "P1", "P2", "P3", "P4", "P5",
        "P6", "P7", "P8", "P9", "P10",
        "P11", "P12", "P13", "P14", "P15",
        "P16", "P17", "P18", "P19", "P20"
    ],

    "Daily_Play_Time": [
        1.0, 1.5, 2.0, 2.5, 3.0,
        3.5, 4.0, 4.5, 5.0, 5.5,
        6.0, 6.5, 7.0, 7.5, 8.0,
        8.5, 9.0, 9.5, 10.0, 10.5
    ],

    "Achievements_Unlocked": [
        5, 8, 12, 15, 20,
        25, 30, 35, 40, 45,
        50, 55, 60, 65, 70,
        75, 80, 85, 90, 95
    ],

    "In_Game_Purchases": [
        200, 300, 500, 600, 700,
        900, 1000, 1200, 1500, 1700,
        2000, 2200, 2500, 2800, 3000,
        3200, 3500, 3800, 4000, 4500
    ],

    "Gaming_Level": [
        3, 5, 7, 9, 12,
        15, 18, 21, 24, 27,
        30, 33, 36, 39, 42,
        45, 48, 51, 54, 57
    ],

    # 0 = Casual, 1 = Professional
    "Player_Type": [
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        1, 1, 1, 1, 1,
        1, 1, 1, 1, 1
    ]
}

df = pd.DataFrame(data)

print("Online Gaming Dataset:")
print(df)

# Save dataset
df.to_csv("online_gaming.csv", index=False)

# --------------------------------------------------
# Step 2: Select Features and Target
# --------------------------------------------------

features = [
    "Daily_Play_Time",
    "Achievements_Unlocked",
    "In_Game_Purchases",
    "Gaming_Level"
]

X = df[features]
y = df["Player_Type"]

# --------------------------------------------------
# Step 3: Split Dataset
# --------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.30,
    random_state=42,
    stratify=y
)

# --------------------------------------------------
# Step 4: Create and Train Logistic Regression Model
# --------------------------------------------------

model = LogisticRegression(max_iter=1000)

model.fit(X_train, y_train)

# --------------------------------------------------
# Step 5: Make Predictions
# --------------------------------------------------

y_pred = model.predict(X_test)

print("\nActual Values:")
print(y_test.values)

print("\nPredicted Values:")
print(y_pred)

# --------------------------------------------------
# Step 6: Evaluate Model
# --------------------------------------------------

accuracy = accuracy_score(y_test, y_pred)

precision = precision_score(
    y_test,
    y_pred,
    zero_division=0
)

recall = recall_score(
    y_test,
    y_pred,
    zero_division=0
)

f1 = f1_score(
    y_test,
    y_pred,
    zero_division=0
)

print("\n----- Model Evaluation -----")
print("Accuracy  :", round(accuracy, 4))
print("Precision :", round(precision, 4))
print("Recall    :", round(recall, 4))
print("F1-Score  :", round(f1, 4))

# --------------------------------------------------
# Step 7: Classification Report
# --------------------------------------------------

print("\nClassification Report:")
print(
    classification_report(
        y_test,
        y_pred,
        target_names=["Casual", "Professional"],
        zero_division=0
    )
)

# --------------------------------------------------
# Step 8: Confusion Matrix
# --------------------------------------------------

cm = confusion_matrix(y_test, y_pred)

print("\nConfusion Matrix:")
print(cm)

plt.figure(figsize=(6, 5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    xticklabels=["Casual", "Professional"],
    yticklabels=["Casual", "Professional"]
)

plt.xlabel("Predicted Class")
plt.ylabel("Actual Class")
plt.title("Confusion Matrix - Online Gaming Classification")

plt.tight_layout()
plt.show()

# --------------------------------------------------
# Step 9: Predict a New Player
# --------------------------------------------------

new_player = [[6.5, 55, 2300, 34]]

prediction = model.predict(new_player)

if prediction[0] == 0:
    print("\nNew Player Classification: Casual Gamer")
else:
    print("\nNew Player Classification: Professional Gamer")

 
3. Download the Salary Dataset. Write a Python program to read the dataset and display its information. Preprocess the data if required and split it into training and testing sets. Apply Simple Linear Regression to predict salary based on years of experience. Plot the regression line and evaluate the model using appropriate metrics such as Mean Squared Error.
Apply Polynomial Regression to predict song popularity using audio features such as danceability, energy, and tempo. Evaluate the model using MAE, RMSE, and R² Score, and visualize the fitted curve.

pip install pandas matplotlib scikit-learn

 import pandas as pd
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

# --------------------------------------------------
# Step 1: Read the Salary Dataset
# --------------------------------------------------

df = pd.read_csv("Salary.csv")

print("First 5 records:")
print(df.head())

# --------------------------------------------------
# Step 2: Display Dataset Information
# --------------------------------------------------

print("\nDataset Information:")
print(df.info())

print("\nDataset Description:")
print(df.describe())

print("\nMissing Values:")
print(df.isnull().sum())

# --------------------------------------------------
# Step 3: Preprocess the Data
# --------------------------------------------------

# Remove missing values
df = df.dropna()

# Convert columns to numeric if required
df["YearsExperience"] = pd.to_numeric(
    df["YearsExperience"], errors="coerce"
)

df["Salary"] = pd.to_numeric(
    df["Salary"], errors="coerce"
)

# Remove rows containing invalid values
df = df.dropna()

print("\nCleaned Dataset:")
print(df.head())

# --------------------------------------------------
# Step 4: Select Independent and Dependent Variables
# --------------------------------------------------

X = df[["YearsExperience"]]
y = df["Salary"]

# --------------------------------------------------
# Step 5: Split Dataset into Training and Testing Sets
# --------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.2,
    random_state=42
)

print("\nTraining Records:", len(X_train))
print("Testing Records:", len(X_test))

# --------------------------------------------------
# Step 6: Create Linear Regression Model
# --------------------------------------------------

model = LinearRegression()

# Train the model
model.fit(X_train, y_train)

# --------------------------------------------------
# Step 7: Predict Salary
# --------------------------------------------------

y_pred = model.predict(X_test)

print("\nActual and Predicted Salaries:")

result = pd.DataFrame({
    "YearsExperience": X_test["YearsExperience"].values,
    "Actual Salary": y_test.values,
    "Predicted Salary": y_pred
})

print(result)

# --------------------------------------------------
# Step 8: Display Regression Equation
# --------------------------------------------------

print("\nRegression Equation:")
print(
    "Salary =",
    round(model.intercept_, 2),
    "+",
    round(model.coef_[0], 2),
    "* YearsExperience"
)

# --------------------------------------------------
# Step 9: Evaluate the Model
# --------------------------------------------------

mse = mean_squared_error(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print("\n----- Model Evaluation -----")
print("Mean Squared Error (MSE):", round(mse, 2))
print("Mean Absolute Error (MAE):", round(mae, 2))
print("R2 Score:", round(r2, 4))

# --------------------------------------------------
# Step 10: Plot Regression Line
# --------------------------------------------------

plt.figure(figsize=(9, 6))

# Actual data
plt.scatter(
    X,
    y,
    label="Actual Salary"
)

# Regression line
plt.plot(
    X,
    model.predict(X),
    linewidth=2,
    label="Regression Line"
)

plt.xlabel("Years of Experience")
plt.ylabel("Salary")
plt.title("Salary Prediction using Simple Linear Regression")

plt.legend()
plt.grid(True, linestyle="--", alpha=0.5)

plt.tight_layout()
plt.show()

# --------------------------------------------------
# Step 11: Predict Salary for New Experience
# --------------------------------------------------

years = [[7]]

predicted_salary = model.predict(years)

print(
    "\nPredicted salary for 7 years of experience:",
    round(predicted_salary[0], 2)
)

 

Part B: Polynomial Regression for Song Popularity 

 Part B: Polynomial Regression for Song Popularity

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# --------------------------------------------------
# Step 1: Create / Read Song Dataset
# --------------------------------------------------

data = {
    "Song": [
        "Song 1", "Song 2", "Song 3", "Song 4", "Song 5",
        "Song 6", "Song 7", "Song 8", "Song 9", "Song 10",
        "Song 11", "Song 12", "Song 13", "Song 14", "Song 15",
        "Song 16", "Song 17", "Song 18", "Song 19", "Song 20"
    ],

    "Danceability": [
        0.40, 0.45, 0.50, 0.55, 0.60,
        0.62, 0.65, 0.68, 0.70, 0.72,
        0.74, 0.76, 0.78, 0.80, 0.82,
        0.84, 0.86, 0.88, 0.90, 0.92
    ],

    "Energy": [
        0.30, 0.35, 0.40, 0.42, 0.45,
        0.50, 0.52, 0.55, 0.58, 0.60,
        0.62, 0.65, 0.68, 0.70, 0.72,
        0.75, 0.78, 0.80, 0.83, 0.85
    ],

    "Tempo": [
        80, 85, 90, 95, 100,
        105, 110, 115, 120, 125,
        128, 130, 135, 140, 145,
        150, 155, 160, 165, 170
    ],

    "Popularity": [
        35, 38, 42, 45, 48,
        52, 55, 58, 61, 64,
        66, 69, 72, 75, 78,
        80, 83, 86, 89, 92
    ]
}

df = pd.DataFrame(data)

print("Song Dataset:")
print(df)

# Save dataset
df.to_csv("song_popularity.csv", index=False)

# --------------------------------------------------
# Step 2: Check Dataset Information
# --------------------------------------------------

print("\nDataset Information:")
df.info()

print("\nMissing Values:")
print(df.isnull().sum())

# --------------------------------------------------
# Step 3: Preprocess Dataset
# --------------------------------------------------

features = [
    "Danceability",
    "Energy",
    "Tempo"
]

target = "Popularity"

# Convert features to numeric
for column in features + [target]:
    df[column] = pd.to_numeric(
        df[column],
        errors="coerce"
    )

# Remove missing values
df = df.dropna()

# --------------------------------------------------
# Step 4: Select Features and Target
# --------------------------------------------------

X = df[features]
y = df[target]

# --------------------------------------------------
# Step 5: Split Dataset
# --------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.2,
    random_state=42
)

# --------------------------------------------------
# Step 6: Create Polynomial Regression Model
# --------------------------------------------------

degree = 2

model = make_pipeline(
    PolynomialFeatures(degree=degree),
    LinearRegression()
)

# Train model
model.fit(X_train, y_train)

# --------------------------------------------------
# Step 7: Predict Popularity
# --------------------------------------------------

y_pred = model.predict(X_test)

result = pd.DataFrame({
    "Actual Popularity": y_test.values,
    "Predicted Popularity": y_pred
})

print("\nActual vs Predicted Popularity:")
print(result)

# --------------------------------------------------
# Step 8: Evaluate Model
# --------------------------------------------------

mae = mean_absolute_error(y_test, y_pred)

mse = mean_squared_error(y_test, y_pred)

rmse = np.sqrt(mse)

r2 = r2_score(y_test, y_pred)

print("\n----- Polynomial Regression Evaluation -----")

print("Mean Absolute Error (MAE):", round(mae, 2))

print("Root Mean Squared Error (RMSE):", round(rmse, 2))

print("R2 Score:", round(r2, 4))

# --------------------------------------------------
# Step 9: Visualize Fitted Polynomial Curve
# --------------------------------------------------

# For visualization, use Danceability as the
# main predictor while keeping the other features
# fixed at their mean values.

danceability_range = np.linspace(
    df["Danceability"].min(),
    df["Danceability"].max(),
    100
)

visual_data = pd.DataFrame({
    "Danceability": danceability_range,
    "Energy": df["Energy"].mean(),
    "Tempo": df["Tempo"].mean()
})

predicted_curve = model.predict(visual_data)

plt.figure(figsize=(9, 6))

# Actual observations
plt.scatter(
    df["Danceability"],
    df["Popularity"],
    label="Actual Songs"
)

# Polynomial fitted curve
plt.plot(
    danceability_range,
    predicted_curve,
    linewidth=2,
    label="Polynomial Regression Curve"
)

plt.xlabel("Danceability")
plt.ylabel("Song Popularity")
plt.title(
    "Polynomial Regression: Danceability vs Song Popularity"
)

plt.legend()
plt.grid(True, linestyle="--", alpha=0.5)

plt.tight_layout()
plt.show() 

 
SET B
1. Apply Logistic Regression to classify smartphones into different price categories using specifications such as RAM, storage, battery capacity, and camera resolution. Assess the model using Accuracy, F1-Score, and Confusion Matrix. 

pip install pandas matplotlib seaborn scikit-learn

 

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix, classification_report

# ---------------------------------------------------------
# Step 1: Create Smartphone Dataset
# ---------------------------------------------------------

data = {
    "Smartphone": [
        "Phone1", "Phone2", "Phone3", "Phone4", "Phone5",
        "Phone6", "Phone7", "Phone8", "Phone9", "Phone10",
        "Phone11", "Phone12", "Phone13", "Phone14", "Phone15",
        "Phone16", "Phone17", "Phone18", "Phone19", "Phone20",
        "Phone21", "Phone22", "Phone23", "Phone24", "Phone25",
        "Phone26", "Phone27", "Phone28", "Phone29", "Phone30"
    ],

    "RAM_GB": [
        2, 3, 3, 4, 4, 4, 6, 6, 6, 8,
        8, 8, 8, 12, 12, 12, 12, 16, 16, 16,
        2, 3, 4, 6, 8, 12, 16, 4, 8, 12
    ],

    "Storage_GB": [
        32, 32, 64, 64, 128, 128, 128, 128, 256, 256,
        256, 128, 256, 256, 256, 512, 512, 512, 512, 512,
        32, 64, 64, 128, 256, 256, 512, 128, 256, 512
    ],

    "Battery_mAh": [
        3000, 3500, 4000, 4000, 4500, 4500, 5000, 5000, 4800, 5000,
        5000, 4500, 5000, 5000, 5200, 5000, 5500, 5000, 5200, 5500,
        3200, 3800, 4200, 4500, 5000, 5200, 5500, 4500, 5000, 5200
    ],

    "Camera_MP": [
        8, 12, 13, 16, 16, 20, 24, 32, 32, 48,
        48, 50, 50, 64, 64, 64, 108, 108, 200, 200,
        12, 16, 20, 32, 48, 64, 108, 32, 50, 108
    ],

    # 0 = Budget, 1 = Mid-Range, 2 = Premium
    "Price_Category": [
        0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
        1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
        0, 0, 1, 1, 1, 2, 2, 1, 1, 2
    ]
}

df = pd.DataFrame(data)

print("----- Smartphone Dataset -----")
print(df)

# Save dataset
df.to_csv("smartphone_price.csv", index=False)

# ---------------------------------------------------------
# Step 2: Display Dataset Information
# ---------------------------------------------------------

print("\n----- Dataset Information -----")
df.info()

print("\n----- Missing Values -----")
print(df.isnull().sum())

# ---------------------------------------------------------
# Step 3: Prepare Features and Target
# ---------------------------------------------------------

features = [
    "RAM_GB",
    "Storage_GB",
    "Battery_mAh",
    "Camera_MP"
]

X = df[features]
y = df["Price_Category"]

# ---------------------------------------------------------
# Step 4: Split Data into Training and Testing Sets
# ---------------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.30,
    random_state=42,
    stratify=y
)

print("\nTraining Records:", len(X_train))
print("Testing Records:", len(X_test))

# ---------------------------------------------------------
# Step 5: Apply Logistic Regression
# ---------------------------------------------------------

model = LogisticRegression(
    max_iter=1000,
    multi_class="auto"
)

model.fit(X_train, y_train)

# Predict test data
y_pred = model.predict(X_test)

print("\nActual Price Categories:")
print(y_test.values)

print("\nPredicted Price Categories:")
print(y_pred)

# ---------------------------------------------------------
# Step 6: Evaluate the Model
# ---------------------------------------------------------

accuracy = accuracy_score(y_test, y_pred)

f1 = f1_score(
    y_test,
    y_pred,
    average="weighted"
)

print("\n----- Model Evaluation -----")
print("Accuracy :", round(accuracy, 4))
print("F1-Score :", round(f1, 4))

print("\n----- Classification Report -----")

print(
    classification_report(
        y_test,
        y_pred,
        target_names=["Budget", "Mid-Range", "Premium"],
        zero_division=0
    )
)

# ---------------------------------------------------------
# Step 7: Confusion Matrix
# ---------------------------------------------------------

cm = confusion_matrix(y_test, y_pred)

print("\n----- Confusion Matrix -----")
print(cm)

plt.figure(figsize=(7, 5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    xticklabels=["Budget", "Mid-Range", "Premium"],
    yticklabels=["Budget", "Mid-Range", "Premium"]
)

plt.xlabel("Predicted Category")
plt.ylabel("Actual Category")
plt.title("Confusion Matrix - Smartphone Price Classification")

plt.tight_layout()
plt.show()

# ---------------------------------------------------------
# Step 8: Predict Price Category for a New Smartphone
# ---------------------------------------------------------

new_phone = [[
    8,       # RAM in GB
    256,     # Storage in GB
    5000,    # Battery in mAh
    64       # Camera in MP
]]

prediction = model.predict(new_phone)

categories = {
    0: "Budget",
    1: "Mid-Range",
    2: "Premium"
}

print("\n----- New Smartphone Prediction -----")
print("RAM          :", new_phone[0][0], "GB")
print("Storage      :", new_phone[0][1], "GB")
print("Battery      :", new_phone[0][2], "mAh")
print("Camera       :", new_phone[0][3], "MP")
print("Predicted Price Category:", categories[prediction[0]]) 


2. Use a Gaming Dataset containing gameplay hours, achievements unlocked, in-game purchases, and friend count. Develop a Multiple Linear Regression model to predict player engagement score. Evaluate the model using MAE, MSE, RMSE, and R² Score.

pip install pandas numpy matplotlib scikit-learn

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import (
    mean_absolute_error,
    mean_squared_error,
    r2_score
)

# ---------------------------------------------------------
# Step 1: Create Gaming Dataset
# ---------------------------------------------------------

data = {
    "Player": [
        "P1", "P2", "P3", "P4", "P5",
        "P6", "P7", "P8", "P9", "P10",
        "P11", "P12", "P13", "P14", "P15",
        "P16", "P17", "P18", "P19", "P20",
        "P21", "P22", "P23", "P24", "P25"
    ],

    "Gameplay_Hours": [
        5, 8, 10, 12, 15,
        18, 20, 22, 25, 28,
        30, 32, 35, 38, 40,
        42, 45, 48, 50, 52,
        55, 58, 60, 65, 70
    ],

    "Achievements_Unlocked": [
        5, 8, 12, 15, 20,
        25, 28, 32, 36, 40,
        45, 48, 52, 55, 60,
        65, 68, 72, 76, 80,
        84, 88, 92, 96, 100
    ],

    "In_Game_Purchases": [
        100, 200, 300, 250, 500,
        600, 700, 800, 900, 1000,
        1200, 1300, 1500, 1600, 1800,
        2000, 2200, 2400, 2600, 2800,
        3000, 3200, 3500, 3800, 4000
    ],

    "Friend_Count": [
        5, 8, 10, 12, 15,
        18, 20, 22, 25, 28,
        30, 32, 35, 38, 40,
        42, 45, 48, 50, 55,
        58, 60, 65, 70, 75
    ],

    "Engagement_Score": [
        18, 24, 29, 33, 38,
        44, 47, 51, 56, 60,
        64, 67, 72, 76, 79,
        82, 85, 88, 91, 94,
        96, 97, 98, 99, 100
    ]
}

df = pd.DataFrame(data)

print("----- Gaming Dataset -----")
print(df)

# Save dataset
df.to_csv("gaming_dataset.csv", index=False)

# ---------------------------------------------------------
# Step 2: Display Dataset Information
# ---------------------------------------------------------

print("\n----- Dataset Information -----")
df.info()

print("\n----- Statistical Description -----")
print(df.describe())

print("\n----- Missing Values -----")
print(df.isnull().sum())

# ---------------------------------------------------------
# Step 3: Define Features and Target
# ---------------------------------------------------------

features = [
    "Gameplay_Hours",
    "Achievements_Unlocked",
    "In_Game_Purchases",
    "Friend_Count"
]

X = df[features]
y = df["Engagement_Score"]

# ---------------------------------------------------------
# Step 4: Split Dataset
# ---------------------------------------------------------

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42
)

print("\nTraining Records:", len(X_train))
print("Testing Records:", len(X_test))

# ---------------------------------------------------------
# Step 5: Apply Multiple Linear Regression
# ---------------------------------------------------------

model = LinearRegression()

model.fit(X_train, y_train)

# Predict test data
y_pred = model.predict(X_test)

# ---------------------------------------------------------
# Step 6: Display Actual and Predicted Values
# ---------------------------------------------------------

result = pd.DataFrame({
    "Actual Engagement Score": y_test.values,
    "Predicted Engagement Score": y_pred
})

print("\n----- Actual vs Predicted Values -----")
print(result)

# ---------------------------------------------------------
# Step 7: Regression Coefficients
# ---------------------------------------------------------

print("\n----- Regression Coefficients -----")

for feature, coefficient in zip(features, model.coef_):
    print(feature, ":", round(coefficient, 4))

print("\nIntercept:", round(model.intercept_, 4))

# ---------------------------------------------------------
# Step 8: Model Evaluation
# ---------------------------------------------------------

mae = mean_absolute_error(y_test, y_pred)

mse = mean_squared_error(y_test, y_pred)

rmse = np.sqrt(mse)

r2 = r2_score(y_test, y_pred)

print("\n----- Model Evaluation -----")
print("Mean Absolute Error (MAE) :", round(mae, 4))
print("Mean Squared Error (MSE)  :", round(mse, 4))
print("Root Mean Squared Error (RMSE) :", round(rmse, 4))
print("R2 Score                  :", round(r2, 4))

# ---------------------------------------------------------
# Step 9: Actual vs Predicted Plot
# ---------------------------------------------------------

plt.figure(figsize=(8, 6))

plt.scatter(
    y_test,
    y_pred,
    s=70
)

plt.xlabel("Actual Engagement Score")
plt.ylabel("Predicted Engagement Score")

plt.title(
    "Actual vs Predicted Player Engagement Score"
)

plt.grid(True, linestyle="--", alpha=0.5)

plt.tight_layout()
plt.show()

# ---------------------------------------------------------
# Step 10: Predict Engagement for a New Player
# ---------------------------------------------------------

new_player = [[
    35,      # Gameplay Hours
    55,      # Achievements
    1500,    # In-Game Purchases
    40       # Friend Count
]]

predicted_score = model.predict(new_player)

print("\n----- New Player Prediction -----")

print("Gameplay Hours       :", new_player[0][0])
print("Achievements         :", new_player[0][1])
print("In-Game Purchases    :", new_player[0][2])
print("Friend Count         :", new_player[0][3])

print(
    "Predicted Engagement Score:",
    round(predicted_score[0], 2)
)


3. Use a Sports Performance dataset containing attributes such as practice hours, fitness score, match  experience, and training sessions. Apply Simple Linear Regression and Multiple Linear Regression to predict player performance. Compare the models using MAE, MSE, RMSE, and R² Score, and identify the most suitable regression model.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import (
    mean_absolute_error,
    mean_squared_error,
    r2_score
)

# ---------------------------------------------------------
# Step 1: Create Sports Performance Dataset
# ---------------------------------------------------------

data = {
    "Player": [
        "P1", "P2", "P3", "P4", "P5",
        "P6", "P7", "P8", "P9", "P10",
        "P11", "P12", "P13", "P14", "P15",
        "P16", "P17", "P18", "P19", "P20",
        "P21", "P22", "P23", "P24", "P25",
        "P26", "P27", "P28", "P29", "P30"
    ],

    "Practice_Hours": [
        2, 3, 4, 5, 6,
        7, 8, 9, 10, 11,
        12, 13, 14, 15, 16,
        17, 18, 19, 20, 21,
        22, 23, 24, 25, 26,
        27, 28, 29, 30, 32
    ],

    "Fitness_Score": [
        45, 48, 50, 52, 55,
        57, 60, 62, 64, 66,
        68, 70, 72, 74, 76,
        78, 80, 82, 84, 85,
        87, 88, 89, 91, 92,
        93, 94, 95, 96, 98
    ],

    "Match_Experience": [
        2, 3, 4, 5, 6,
        8, 9, 10, 12, 13,
        15, 16, 18, 20, 22,
        24, 25, 27, 28, 30,
        32, 35, 36, 38, 40,
        42, 45, 48, 50
    ],

    "Training_Sessions": [
        10, 12, 15, 18, 20,
        22, 25, 28, 30, 32,
        35, 38, 40, 42, 45,
        48, 50, 52, 55, 58,
        60, 62, 65, 68, 70,
        72, 75, 78, 80
    ],

    "Performance_Score": [
        42, 45, 48, 51, 54,
        57, 60, 62, 65, 67,
        70, 72, 74, 76, 78,
        80, 82, 84, 86, 87,
        89, 90, 91, 93, 94,
        95, 96, 97, 98, 99
    ]
}

df = pd.DataFrame(data)

print("----- Sports Performance Dataset -----")
print(df)

# Save dataset
df.to_csv("sports_performance.csv", index=False)

# ---------------------------------------------------------
# Step 2: Display Dataset Information
# ---------------------------------------------------------

print("\n----- Dataset Information -----")
df.info()

print("\n----- Statistical Description -----")
print(df.describe())

print("\n----- Missing Values -----")
print(df.isnull().sum())

# ---------------------------------------------------------
# Step 3: Define Variables
# ---------------------------------------------------------

features = [
    "Practice_Hours",
    "Fitness_Score",
    "Match_Experience",
    "Training_Sessions"
]

target = "Performance_Score"

# ---------------------------------------------------------
# Step 4: Split Dataset
# ---------------------------------------------------------

X = df[features]
y = df[target]

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42
)

print("\nTraining Records:", len(X_train))
print("Testing Records:", len(X_test))

# =========================================================
# MODEL 1: SIMPLE LINEAR REGRESSION
# =========================================================

# Use Practice Hours as the single predictor

X_simple = df[["Practice_Hours"]]

X_train_s, X_test_s, y_train_s, y_test_s = train_test_split(
    X_simple,
    y,
    test_size=0.20,
    random_state=42
)

simple_model = LinearRegression()

simple_model.fit(X_train_s, y_train_s)

simple_pred = simple_model.predict(X_test_s)

# ---------------------------------------------------------
# Simple Regression Evaluation
# ---------------------------------------------------------

simple_mae = mean_absolute_error(
    y_test_s,
    simple_pred
)

simple_mse = mean_squared_error(
    y_test_s,
    simple_pred
)

simple_rmse = np.sqrt(simple_mse)

simple_r2 = r2_score(
    y_test_s,
    simple_pred
)

print("\n========================================")
print("SIMPLE LINEAR REGRESSION")
print("========================================")

print("Regression Equation:")
print(
    "Performance =",
    round(simple_model.intercept_, 2),
    "+",
    round(simple_model.coef_[0], 2),
    "* Practice Hours"
)

print("\nMAE  :", round(simple_mae, 4))
print("MSE  :", round(simple_mse, 4))
print("RMSE :", round(simple_rmse, 4))
print("R2   :", round(simple_r2, 4))

# ---------------------------------------------------------
# Simple Regression Plot
# ---------------------------------------------------------

plt.figure(figsize=(8, 6))

plt.scatter(
    X_simple,
    y,
    label="Actual Data"
)

plt.plot(
    X_simple,
    simple_model.predict(X_simple),
    linewidth=2,
    label="Regression Line"
)

plt.xlabel("Practice Hours")
plt.ylabel("Performance Score")
plt.title("Simple Linear Regression")
plt.legend()
plt.grid(True, linestyle="--", alpha=0.5)

plt.tight_layout()
plt.show()

# =========================================================
# MODEL 2: MULTIPLE LINEAR REGRESSION
# =========================================================

multiple_model = LinearRegression()

multiple_model.fit(
    X_train,
    y_train
)

multiple_pred = multiple_model.predict(X_test)

# ---------------------------------------------------------
# Multiple Regression Evaluation
# ---------------------------------------------------------

multiple_mae = mean_absolute_error(
    y_test,
    multiple_pred
)

multiple_mse = mean_squared_error(
    y_test,
    multiple_pred
)

multiple_rmse = np.sqrt(multiple_mse)

multiple_r2 = r2_score(
    y_test,
    multiple_pred
)

print("\n========================================")
print("MULTIPLE LINEAR REGRESSION")
print("========================================")

print("\nRegression Coefficients:")

for feature, coefficient in zip(
    features,
    multiple_model.coef_
):
    print(
        feature,
        ":",
        round(coefficient, 4)
    )

print(
    "\nIntercept:",
    round(multiple_model.intercept_, 4)
)

print("\nMAE  :", round(multiple_mae, 4))
print("MSE  :", round(multiple_mse, 4))
print("RMSE :", round(multiple_rmse, 4))
print("R2   :", round(multiple_r2, 4))

# ---------------------------------------------------------
# Actual vs Predicted Plot
# ---------------------------------------------------------

plt.figure(figsize=(8, 6))

plt.scatter(
    y_test,
    multiple_pred,
    s=70
)

plt.xlabel("Actual Performance Score")
plt.ylabel("Predicted Performance Score")

plt.title(
    "Multiple Linear Regression: "
    "Actual vs Predicted Performance"
)

plt.grid(True, linestyle="--", alpha=0.5)

plt.tight_layout()
plt.show()

# =========================================================
# MODEL COMPARISON
# =========================================================

comparison = pd.DataFrame({
    "Model": [
        "Simple Linear Regression",
        "Multiple Linear Regression"
    ],

    "MAE": [
        simple_mae,
        multiple_mae
    ],

    "MSE": [
        simple_mse,
        multiple_mse
    ],

    "RMSE": [
        simple_rmse,
        multiple_rmse
    ],

    "R2 Score": [
        simple_r2,
        multiple_r2
    ]
})

print("\n========================================")
print("MODEL COMPARISON")
print("========================================")

print(
    comparison.round(4)
)

# ---------------------------------------------------------
# Identify Best Model
# ---------------------------------------------------------

if multiple_r2 > simple_r2:
    best_model = "Multiple Linear Regression"
else:
    best_model = "Simple Linear Regression"

print("\nMost Suitable Model:", best_model)

# ---------------------------------------------------------
# Predict Performance of a New Player
# ---------------------------------------------------------

new_player = [[
    15,     # Practice Hours
    80,     # Fitness Score
    20,     # Match Experience
    45      # Training Sessions
]]

predicted_performance = multiple_model.predict(
    new_player
)

print("\n----- New Player Prediction -----")

print("Practice Hours     :", new_player[0][0])
print("Fitness Score      :", new_player[0][1])
print("Match Experience   :", new_player[0][2])
print("Training Sessions  :", new_player[0][3])

print(
    "Predicted Performance Score:",
    round(predicted_performance[0], 2)
)


SET C
1. Download a Mobile Phone Specifications dataset. Apply Multiple Linear Regression to predict mobile prices using features such as RAM, storage, battery capacity, and camera resolution. Categorize mobiles into Budget and Premium segments and build a Logistic Regression model for  classification. Compare the performance of both models using appropriate regression and classification metrics.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.metrics import (
    mean_absolute_error,
    mean_squared_error,
    r2_score,
    accuracy_score,
    precision_score,
    recall_score,
    f1_score,
    confusion_matrix,
    classification_report
)

# =========================================================
# STEP 1: READ MOBILE PHONE DATASET
# =========================================================

# Downloaded dataset file
df = pd.read_csv("mobile_phone.csv")

print("========== MOBILE PHONE DATASET ==========")
print(df.head())

# =========================================================
# STEP 2: DISPLAY DATASET INFORMATION
# =========================================================

print("\n========== DATASET INFORMATION ==========")
df.info()

print("\n========== STATISTICAL DESCRIPTION ==========")
print(df.describe())

print("\n========== MISSING VALUES ==========")
print(df.isnull().sum())

# =========================================================
# STEP 3: PREPROCESS DATA
# =========================================================

# Change these names if your dataset uses different names
features = [
    "RAM",
    "Storage",
    "Battery",
    "Camera"
]

target = "Price"

# Convert selected columns to numeric
for column in features + [target]:
    df[column] = pd.to_numeric(
        df[column],
        errors="coerce"
    )

# Remove missing values
df = df.dropna()

print("\n========== CLEANED DATASET ==========")
print(df[features + [target]].head())

# =========================================================
# PART A: MULTIPLE LINEAR REGRESSION
# =========================================================

print("\n\n==========================================")
print("MULTIPLE LINEAR REGRESSION")
print("==========================================")

X = df[features]
y = df[target]

# Split dataset
X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42
)

print("\nTraining Records:", len(X_train))
print("Testing Records :", len(X_test))

# Create model
linear_model = LinearRegression()

# Train model
linear_model.fit(X_train, y_train)

# Predict prices
y_pred = linear_model.predict(X_test)

# ---------------------------------------------------------
# Regression Coefficients
# ---------------------------------------------------------

print("\nRegression Coefficients:")

for feature, coefficient in zip(
    features,
    linear_model.coef_
):
    print(
        feature,
        ":",
        round(coefficient, 4)
    )

print(
    "\nIntercept:",
    round(linear_model.intercept_, 4)
)

# ---------------------------------------------------------
# Actual vs Predicted Price
# ---------------------------------------------------------

result = pd.DataFrame({
    "Actual Price": y_test.values,
    "Predicted Price": y_pred
})

print("\n========== ACTUAL VS PREDICTED PRICE ==========")
print(result)

# ---------------------------------------------------------
# Regression Metrics
# ---------------------------------------------------------

mae = mean_absolute_error(
    y_test,
    y_pred
)

mse = mean_squared_error(
    y_test,
    y_pred
)

rmse = np.sqrt(mse)

r2 = r2_score(
    y_test,
    y_pred
)

print("\n========== REGRESSION EVALUATION ==========")
print("MAE  :", round(mae, 2))
print("MSE  :", round(mse, 2))
print("RMSE :", round(rmse, 2))
print("R2 Score :", round(r2, 4))

# ---------------------------------------------------------
# Actual vs Predicted Price Plot
# ---------------------------------------------------------

plt.figure(figsize=(8, 6))

plt.scatter(
    y_test,
    y_pred,
    s=70
)

# Reference line
minimum = min(y_test.min(), y_pred.min())
maximum = max(y_test.max(), y_pred.max())

plt.plot(
    [minimum, maximum],
    [minimum, maximum],
    linewidth=2
)

plt.xlabel("Actual Mobile Price")
plt.ylabel("Predicted Mobile Price")

plt.title(
    "Multiple Linear Regression: "
    "Actual vs Predicted Price"
)

plt.grid(True, linestyle="--", alpha=0.5)

plt.tight_layout()
plt.show()

# =========================================================
# PART B: CREATE BUDGET / PREMIUM CATEGORY
# =========================================================

print("\n\n==========================================")
print("MOBILE PRICE CATEGORIZATION")
print("==========================================")

# Find median price as the classification threshold
threshold = df["Price"].median()

print(
    "Price Classification Threshold:",
    threshold
)

# 0 = Budget
# 1 = Premium
df["Price_Category"] = np.where(
    df["Price"] <= threshold,
    0,
    1
)

print("\nPrice Categories:")
print("0 = Budget")
print("1 = Premium")

print("\nCategory Distribution:")
print(
    df["Price_Category"].value_counts()
)

# =========================================================
# PART C: LOGISTIC REGRESSION
# =========================================================

print("\n\n==========================================")
print("LOGISTIC REGRESSION")
print("==========================================")

X_class = df[features]
y_class = df["Price_Category"]

# Split data
X_train_c, X_test_c, y_train_c, y_test_c = train_test_split(
    X_class,
    y_class,
    test_size=0.20,
    random_state=42,
    stratify=y_class
)

print("\nTraining Records:", len(X_train_c))
print("Testing Records :", len(X_test_c))

# Create Logistic Regression model
logistic_model = LogisticRegression(
    max_iter=2000
)

# Train model
logistic_model.fit(
    X_train_c,
    y_train_c
)

# Predict categories
y_pred_c = logistic_model.predict(X_test_c)

# ---------------------------------------------------------
# Classification Results
# ---------------------------------------------------------

print("\nActual Categories:")
print(y_test_c.values)

print("\nPredicted Categories:")
print(y_pred_c)

# ---------------------------------------------------------
# Classification Metrics
# ---------------------------------------------------------

accuracy = accuracy_score(
    y_test_c,
    y_pred_c
)

precision = precision_score(
    y_test_c,
    y_pred_c,
    zero_division=0
)

recall = recall_score(
    y_test_c,
    y_pred_c,
    zero_division=0
)

f1 = f1_score(
    y_test_c,
    y_pred_c,
    zero_division=0
)

print("\n========== CLASSIFICATION EVALUATION ==========")

print("Accuracy  :", round(accuracy, 4))
print("Precision :", round(precision, 4))
print("Recall    :", round(recall, 4))
print("F1-Score  :", round(f1, 4))

# ---------------------------------------------------------
# Classification Report
# ---------------------------------------------------------

print("\n========== CLASSIFICATION REPORT ==========")

print(
    classification_report(
        y_test_c,
        y_pred_c,
        target_names=[
            "Budget",
            "Premium"
        ],
        zero_division=0
    )
)

# =========================================================
# STEP 4: CONFUSION MATRIX
# =========================================================

cm = confusion_matrix(
    y_test_c,
    y_pred_c
)

print("\n========== CONFUSION MATRIX ==========")
print(cm)

plt.figure(figsize=(7, 5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    xticklabels=[
        "Budget",
        "Premium"
    ],
    yticklabels=[
        "Budget",
        "Premium"
    ]
)

plt.xlabel("Predicted Category")
plt.ylabel("Actual Category")

plt.title(
    "Confusion Matrix - Mobile Price Classification"
)

plt.tight_layout()
plt.show()

# =========================================================
# STEP 5: COMPARE THE MODELS
# =========================================================

print("\n\n==========================================")
print("MODEL COMPARISON")
print("==========================================")

comparison = pd.DataFrame({
    "Model": [
        "Multiple Linear Regression",
        "Logistic Regression"
    ],

    "MAE": [
        mae,
        np.nan
    ],

    "MSE": [
        mse,
        np.nan
    ],

    "RMSE": [
        rmse,
        np.nan
    ],

    "R2 Score": [
        r2,
        np.nan
    ],

    "Accuracy": [
        np.nan,
        accuracy
    ],

    "F1 Score": [
        np.nan,
        f1
    ]
})

print(
    comparison.round(4)
)

# =========================================================
# STEP 6: PREDICT A NEW MOBILE
# =========================================================

print("\n\n==========================================")
print("NEW MOBILE PREDICTION")
print("==========================================")

# Example:
# RAM = 8 GB
# Storage = 256 GB
# Battery = 5000 mAh
# Camera = 64 MP

new_mobile = [[
    8,
    256,
    5000,
    64
]]

# Predict actual price
predicted_price = linear_model.predict(
    new_mobile
)

# Predict category
predicted_category = logistic_model.predict(
    new_mobile
)

print(
    "Predicted Mobile Price:",
    round(predicted_price[0], 2)
)

if predicted_category[0] == 0:
    print("Predicted Category: Budget")
else:
    print("Predicted Category: Premium")


2. Use a YouTube Video Statistics dataset to predict video views using Simple Linear Regression based on the number of likes. Convert the target variable into Popular and Non-Popular categories using a suitable threshold and apply Logistic Regression. Evaluate the regression model using MAE, MSE, RMSE, and R² Score, and evaluate the classification model using Accuracy, Precision, Recall, F1-Score, and Confusion Matrix. 

 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.metrics import (
    mean_absolute_error,
    mean_squared_error,
    r2_score,
    accuracy_score,
    precision_score,
    recall_score,
    f1_score,
    confusion_matrix,
    classification_report
)

# =========================================================
# STEP 1: READ YOUTUBE DATASET
# =========================================================

df = pd.read_csv("youtube_video_statistics.csv")

print("========== FIRST 5 RECORDS ==========")
print(df.head())

print("\n========== DATASET INFORMATION ==========")
df.info()

print("\n========== STATISTICAL DESCRIPTION ==========")
print(df.describe())

print("\n========== MISSING VALUES ==========")
print(df.isnull().sum())

# =========================================================
# STEP 2: PREPROCESSING
# =========================================================

# Change these column names if your dataset uses different names
# Example: views, likes

df["Views"] = pd.to_numeric(
    df["Views"],
    errors="coerce"
)

df["Likes"] = pd.to_numeric(
    df["Likes"],
    errors="coerce"
)

# Remove missing values
df = df.dropna(
    subset=["Views", "Likes"]
)

print("\n========== CLEANED DATA ==========")
print(df[["Likes", "Views"]].head())

# =========================================================
# PART A: SIMPLE LINEAR REGRESSION
# =========================================================

print("\n==========================================")
print("SIMPLE LINEAR REGRESSION")
print("==========================================")

# Independent variable = Likes
# Dependent variable = Views

X = df[["Likes"]]
y = df["Views"]

# Split dataset into training and testing
X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42
)

print("\nTraining Records:", len(X_train))
print("Testing Records :", len(X_test))

# Create Linear Regression model
linear_model = LinearRegression()

# Train model
linear_model.fit(
    X_train,
    y_train
)

# Predict views
y_pred = linear_model.predict(
    X_test
)

# =========================================================
# REGRESSION EQUATION
# =========================================================

print("\nRegression Equation:")

print(
    "Views =",
    round(linear_model.intercept_, 2),
    "+",
    round(linear_model.coef_[0], 2),
    "* Likes"
)

# =========================================================
# ACTUAL VS PREDICTED VALUES
# =========================================================

result = pd.DataFrame({
    "Likes": X_test["Likes"].values,
    "Actual Views": y_test.values,
    "Predicted Views": y_pred
})

print("\n========== ACTUAL VS PREDICTED ==========")
print(result)

# =========================================================
# REGRESSION EVALUATION
# =========================================================

mae = mean_absolute_error(
    y_test,
    y_pred
)

mse = mean_squared_error(
    y_test,
    y_pred
)

rmse = np.sqrt(mse)

r2 = r2_score(
    y_test,
    y_pred
)

print("\n========== REGRESSION EVALUATION ==========")

print("MAE  :", round(mae, 2))
print("MSE  :", round(mse, 2))
print("RMSE :", round(rmse, 2))
print("R2 Score :", round(r2, 4))

# =========================================================
# REGRESSION PLOT
# =========================================================

plt.figure(figsize=(9, 6))

plt.scatter(
    df["Likes"],
    df["Views"],
    label="Actual Data"
)

# Sort values so regression line is displayed correctly
sorted_df = df.sort_values("Likes")

plt.plot(
    sorted_df["Likes"],
    linear_model.predict(
        sorted_df[["Likes"]]
    ),
    linewidth=2,
    label="Regression Line"
)

plt.xlabel("Number of Likes")
plt.ylabel("Number of Views")

plt.title(
    "Simple Linear Regression: "
    "Likes vs Views"
)

plt.legend()
plt.grid(
    True,
    linestyle="--",
    alpha=0.5
)

plt.tight_layout()
plt.show()

# =========================================================
# PART B: CREATE POPULAR / NON-POPULAR CATEGORY
# =========================================================

print("\n==========================================")
print("POPULARITY CLASSIFICATION")
print("==========================================")

# Use median views as the popularity threshold
threshold = df["Views"].median()

print(
    "\nPopularity Threshold:",
    threshold
)

# 0 = Non-Popular
# 1 = Popular

df["Popularity"] = np.where(
    df["Views"] >= threshold,
    1,
    0
)

print("\nCategory Definition:")
print("0 = Non-Popular")
print("1 = Popular")

print("\nPopularity Distribution:")
print(
    df["Popularity"].value_counts()
)

# =========================================================
# PART C: LOGISTIC REGRESSION
# =========================================================

print("\n==========================================")
print("LOGISTIC REGRESSION")
print("==========================================")

# Use Likes to classify popularity
X_class = df[["Likes"]]
y_class = df["Popularity"]

# Split dataset
X_train_c, X_test_c, y_train_c, y_test_c = train_test_split(
    X_class,
    y_class,
    test_size=0.20,
    random_state=42,
    stratify=y_class
)

print("\nTraining Records:", len(X_train_c))
print("Testing Records :", len(X_test_c))

# Create Logistic Regression model
logistic_model = LogisticRegression(
    max_iter=2000
)

# Train model
logistic_model.fit(
    X_train_c,
    y_train_c
)

# Predict popularity
y_pred_c = logistic_model.predict(
    X_test_c
)

# =========================================================
# CLASSIFICATION RESULTS
# =========================================================

print("\nActual Categories:")
print(y_test_c.values)

print("\nPredicted Categories:")
print(y_pred_c)

# =========================================================
# CLASSIFICATION METRICS
# =========================================================

accuracy = accuracy_score(
    y_test_c,
    y_pred_c
)

precision = precision_score(
    y_test_c,
    y_pred_c,
    zero_division=0
)

recall = recall_score(
    y_test_c,
    y_pred_c,
    zero_division=0
)

f1 = f1_score(
    y_test_c,
    y_pred_c,
    zero_division=0
)

print("\n========== CLASSIFICATION EVALUATION ==========")

print("Accuracy  :", round(accuracy, 4))
print("Precision :", round(precision, 4))
print("Recall    :", round(recall, 4))
print("F1-Score  :", round(f1, 4))

# =========================================================
# CLASSIFICATION REPORT
# =========================================================

print("\n========== CLASSIFICATION REPORT ==========")

print(
    classification_report(
        y_test_c,
        y_pred_c,
        target_names=[
            "Non-Popular",
            "Popular"
        ],
        zero_division=0
    )
)

# =========================================================
# CONFUSION MATRIX
# =========================================================

cm = confusion_matrix(
    y_test_c,
    y_pred_c
)

print("\n========== CONFUSION MATRIX ==========")
print(cm)

plt.figure(figsize=(7, 5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    xticklabels=[
        "Non-Popular",
        "Popular"
    ],
    yticklabels=[
        "Non-Popular",
        "Popular"
    ]
)

plt.xlabel("Predicted Category")
plt.ylabel("Actual Category")

plt.title(
    "Confusion Matrix - YouTube Popularity Classification"
)

plt.tight_layout()
plt.show()

# =========================================================
# PART D: PREDICT A NEW VIDEO
# =========================================================

print("\n==========================================")
print("NEW VIDEO PREDICTION")
print("==========================================")

# Example video with 10,000 likes
new_video = [[10000]]

# Predict number of views using Linear Regression
predicted_views = linear_model.predict(
    new_video
)

# Predict popularity using Logistic Regression
predicted_category = logistic_model.predict(
    new_video
)

print(
    "Number of Likes:",
    new_video[0][0]
)

print(
    "Predicted Views:",
    round(predicted_views[0], 2)
)

if predicted_category[0] == 1:
    print("Predicted Category: Popular")
else:
    print("Predicted Category: Non-Popular")