Q- Here i will walk you throught my working process so far in my note book oky 



train_path = "data/raw/test.csv"
test_path = "data/raw/test.csv"


# Read the train and test datasets
train_df = pd.read_csv(train_path)
test_df = pd.read_csv(test_path)


# Merge the datasets
df = pd.concat([train_df, test_df], axis=0, ignore_index=True)


# Display the first 5 lines
df.head()




"""
Q- now we need to check the table describtion of the data


"""
df.describe()

"""
Q- check some information about the data ?
"""
df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 128748 entries, 0 to 128747
Data columns (total 12 columns):
 #   Column             Non-Null Count   Dtype 
---  ------             --------------   ----- 
 0   CustomerID         128748 non-null  int64 
 1   Age                128748 non-null  int64 
 2   Gender             128748 non-null  object
 3   Tenure             128748 non-null  int64 
 4   Usage Frequency    128748 non-null  int64 
 5   Support Calls      128748 non-null  int64 
 6   Payment Delay      128748 non-null  int64 
 7   Subscription Type  128748 non-null  object
 8   Contract Length    128748 non-null  object
 9   Total Spend        128748 non-null  int64 
 10  Last Interaction   128748 non-null  int64 
 11  Churn              128748 non-null  int64 
dtypes: int64(9), object(3)
memory usage: 11.8+ MB



"""
Q- let's Rename the columns and remove the empty space oky


"""


df.columns = [col.lower().replace(' ','_') for col in df.columns]
df.columns




"""
Q- let's remove the columns with unncessry information
A- it's the CustomerID column oky


"""
df.drop(columns='customerid',inplace=True)
df.shape


(128748, 11)


from typing import Callable, List
import pandas as pd


def compute_null_percentage(column: pd.Series) -> float:
    """
    Compute the percentage of null values in a given column.


    Args:
        column (pd.Series): The input column to analyze.


    Returns:
        float: The percentage of null values in the column.
    """
    null_count: int = column.isnull().sum()
    total_count: int = len(column)


    return (null_count / total_count) * 100 if total_count > 0 else 0.0


def analyze_null_percentages(df: pd.DataFrame) -> pd.Series:
    """
    Analyze null percentages for all columns in a DataFrame.


    Args:
        df (pd.DataFrame): The input DataFrame to analyze.


    Returns:
        pd.Series: A series of null percentages for each column.
    """
    return df.isnull().mean() * 100


# Call the analyze_null_percentages function
null_percentages = analyze_null_percentages(df)


# Print the results
for column, percentage in null_percentages.items():
    print(f"{column}: {percentage:.2f}% null values")


from typing import Callable, List
import pandas as pd

def compute_null_percentage(column: pd.Series) -> float:
    """
    Compute the percentage of null values in a given column.

    Args:
        column (pd.Series): The input column to analyze.

    Returns:
        float: The percentage of null values in the column.
    """
    null_count: int = column.isnull().sum()
    total_count: int = len(column)

    return (null_count / total_count) * 100 if total_count > 0 else 0.0

def analyze_null_percentages(df: pd.DataFrame) -> pd.Series:
    """
    Analyze null percentages for all columns in a DataFrame.

    Args:
        df (pd.DataFrame): The input DataFrame to analyze.

    Returns:
        pd.Series: A series of null percentages for each column.
    """
    return df.isnull().mean() * 100

# Call the analyze_null_percentages function
null_percentages = analyze_null_percentages(df)

# Print the results
for column, percentage in null_percentages.items():
    print(f"{column}: {percentage:.2f}% null values")

df.dropna(inplace=True) # Remov

df.isnull().sum()

"""
Q- next we have some categorical features that we need to encode.
Q- before starting the ml modeling oky


Q- the featuers are
- gender
-subscription_type
-contract_length
Q- so we use the OneHotEncoder to encode the categorical features
Q- how to logic is done ?
- firtst we need to call the packge to do this wich is "OneHotEncoder"
- then we make an instance of it as encoder varible
- then we fit the encoder to the data
Q- so give the full code here without removing the """ """ comments oky


"""
from sklearn.preprocessing import OneHotEncoder


# List of categorical columns to encode
categorical_features = ['gender', 'subscription_type', 'contract_length']


# Create an instance of OneHotEncoder
encoder = OneHotEncoder(sparse_output=False)


# Fit the encoder to the data and transform the categorical columns
encoded_features = encoder.fit_transform(df[categorical_features])


# Create a DataFrame from the encoded features
encoded_df = pd.DataFrame(encoded_features, columns=encoder.get_feature_names_out(categorical_features))


# Drop the original categorical columns from the DataFrame
df.drop(columns=categorical_features, inplace=True)


# Concatenate the encoded features with the original DataFrame
df = pd.concat([df, encoded_df], axis=1)


# Display the first 5 lines of the updated DataFrame
df.head()

df.dropna(inplace=True)


# Verify that all null values have been dropped
print(df.isnull().sum())

"""
Q- now we have clean the data , encoding it
Q- it's time to prepare the train and test data
Q- first think we need to import the needed libraries like train_test_split from sklearn.model_selection
Q- and StandardScaler from sklearn.preprocessing
Q- then due this problem is a supervised learning problem and the target is "churn" we need to remove it from the data
Q- and then we need to split the data into train and test data
Q- and then we need to scale the data
"""
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler


X=df.drop("churn",axis=1)
y=df["churn"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# identify numerical columns
numerical_cols = X_train.select_dtypes(include=['int64', 'float64']).columns
# intialize the scaler
scaler = StandardScaler()
# fit and transform the numerical columns
X_train[numerical_cols] = scaler.fit_transform(X_train[numerical_cols])
# transform the test set
X_test[numerical_cols] = scaler.transform(X_test[numerical_cols])


# print the result
print("Training set shape :" , X_train.shape)
print("Test set shape :" , X_test.shape)

Training set shape : (102998, 15)
Test set shape : (25750, 15)

import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
from tabulate import tabulate


def train_and_validate_model(X_train, X_test, y_train, y_test, model=LogisticRegression()):
    """
    Train a model and validate its performance using various metrics.


    Input:
    - X_train: Training features
    - X_test: Testing features
    - y_train: Training labels
    - y_test: Testing labels
    - model: Machine learning model (default: LogisticRegression)


    Output:
    - accuracy: Accuracy score
    - precision: Precision score
    - recall: Recall score
    - f1: F1 score
    - roc_auc: ROC AUC score
    """
    # Train the model
    model.fit(X_train, y_train)


    # Make predictions
    y_pred = model.predict(X_test)
    y_pred_proba = model.predict_proba(X_test)[:, 1]


    # Calculate performance metrics
    accuracy = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred)
    recall = recall_score(y_test, y_pred)
    f1 = f1_score(y_test, y_pred)
    roc_auc = roc_auc_score(y_test, y_pred_proba)
   
    return accuracy, precision, recall, f1, roc_auc
"""
Q- now just print the result after calling the method
Q- give the code to it
"""
result = train_and_validate_model(X_train, X_test, y_train, y_test)
metrics = ['Accuracy', 'Precision', 'Recall', 'F1 Score', 'ROC AUC']
for metric, value in zip(metrics, result):
    print(f"{metric}: {value:.4f}")


Q- my first question i learned that mlflow is an important open source ml framework , that you installed it using pip command and integrate it in many part of your notebook project 

Q- my first question is true this ? if yes using only the context my project where i can use it exactly oky