import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras


from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error
url = "https://raw.githubusercontent.com/plotly/datasets/master/diabetes.csv"
print(f"Loading dataset from: {url}")
df = pd.read_csv(url)
df.head()
# Separate features (X) and target (y - assuming last column)
X = df.drop(['Outcome'], axis=1)
y = df['Outcome']
# Split data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Standardize features 
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test) # Use transform only on test set
# 2. Build the Regularized FNN Model
model = keras.Sequential([
    # Example for L1 REGULARIZATION
    keras.layers.Dense(64, activation='relu',
                 kernel_regularizer=keras.regularizers.l1(0.01),
                 input_shape=(X_train.shape[1],)), 

    # Example for DROPOUT
    keras.layers.Dropout(0.3),

    # Example for L2 REGULARIZATION
    keras.layers.Dense(32, activation='relu',
                 kernel_regularizer=keras.regularizers.l2(0.01)),
                 
    keras.layers.Dropout(0.3),
    keras.layers.Dense(1)
])

# 3. Compile the Model
model.compile(optimizer='adam',  loss='mse', metrics=['mae'])   
# 4. Train the Model
# Use EarlyStopping callback to prevent overfitting and save time 
# Example for EARLY STOPPING
early_stopping = keras.callbacks.EarlyStopping(monitor='val_loss',  # Monitor validation loss
                              patience=10,         # Stop after 10 epochs with no improvement
                               restore_best_weights=True) # Keep the best model weights


# Verbose: Set to 0 for silent training, 1 for progress bar
history = model.fit(X_train, y_train,
                    validation_data=(X_test, y_test),
                    epochs=100,          
                    batch_size=16,       
                    callbacks=[early_stopping])
# 5. Evaluate the Model
y_pred = model.predict(X_test)

# Calculate performance metrics 
mse = mean_squared_error(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)

mae, mse
# 6. Plot Training History
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Model Loss During Training (MSE)')

plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()

plt.grid(True)
plt.show()