Q- given i use Titanic DataSet to develope 
Machine learning model , than test it 
For later make it as backend service using fast api like

So the code for the Feature_engineering 
And Logistic_regression 
IS LIKE this 

“# Feature_engineering.py


import pandas as pd
import numpy as np


def status(feature_name: str) -> None:
    """
    Prints the status of the processed feature.


    Parameters:
    - feature_name (str): Name of the feature that has been processed.
    """
    print(f"Processed feature: {feature_name}")


def get_combined_data(train_path: str = './data/train.csv',
                      test_path: str = './data/test.csv') -> tuple:
    """
    Loads and combines the training and testing datasets.


    Parameters:
    - train_path (str): Path to the training data CSV file.
    - test_path (str): Path to the testing data CSV file.


    Returns:
    - combined (pd.DataFrame): Combined DataFrame of train and test data.
    - targets (pd.Series): Target variable from the training data.
    """
    train = pd.read_csv(train_path)
    test = pd.read_csv(test_path)


    targets = train['Survived']
    train = train.drop(['Survived'], axis=1)


    combined = pd.concat([train, test], ignore_index=True)
    combined = combined.drop(['PassengerId'], axis=1)


    return combined, targets


def extract_titles(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Extracts and maps titles from the 'Name' column to a new 'Title' feature
    and drops the 'Name' column.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with the new 'Title' feature and without the 'Name' column.
    """
    title_dictionary = {
        "Mr": "Mr",
        "Mrs": "Mrs",
        "Miss": "Miss",
        "Master": "Master",
        "Dr": "Officer",
        "Rev": "Officer",
        "Col": "Officer",
        "Major": "Officer",
        "Mlle": "Miss",
        "Countess": "Royalty",
        "Ms": "Miss",
        "Lady": "Royalty",
        "Jonkheer": "Royalty",
        "Don": "Royalty",
        "Dona": "Royalty",
        "Mme": "Mrs",
        "Capt": "Officer",
        "Sir": "Royalty"
    }


    combined['Title'] = combined['Name'].apply(
        lambda name: name.split(',')[1].split('.')[0].strip()
    )
    combined['Title'] = combined['Title'].map(title_dictionary)
    combined['Title'] = combined['Title'].fillna('Other')


    # Drop the 'Name' column as it's no longer needed
    combined = combined.drop('Name', axis=1)


    status('Title')
    return combined


def fill_missing_ages(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Fills missing values in the 'Age' column using the median age
    grouped by 'Sex', 'Pclass', and 'Title'.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with missing 'Age' values filled.
    """
    grouped_median = combined.groupby(['Sex', 'Pclass', 'Title'])['Age'].median().reset_index()


    def fill_age(row):
        condition = (
            (grouped_median['Sex'] == row['Sex']) &
            (grouped_median['Title'] == row['Title']) &
            (grouped_median['Pclass'] == row['Pclass'])
        )
        age = grouped_median[condition]['Age'].values
        if len(age) > 0 and not np.isnan(age[0]):
            return age[0]
        else:
            return combined['Age'].median()  # Fallback


    combined['Age'] = combined.apply(
        lambda row: fill_age(row) if pd.isnull(row['Age']) else row['Age'], axis=1
    )
    status('Age')
    return combined


def fill_missing_fares(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Fills missing values in the 'Fare' column with the mean fare from the training set.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with missing 'Fare' values filled.
    """
    mean_fare = combined.loc[:890, 'Fare'].mean()
    combined['Fare'] = combined['Fare'].fillna(mean_fare)
    status('Fare')
    return combined


def encode_sex(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Encodes the 'Sex' column into numerical values.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with encoded 'Sex' column.
    """
    combined['Sex'] = combined['Sex'].map({'male': 1, 'female': 0})
    status('Sex')
    return combined


def encode_pclass(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Encodes the 'Pclass' column using dummy variables.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with dummy variables for 'Pclass'.
    """
    pclass_dummies = pd.get_dummies(combined['Pclass'], prefix="Pclass")
    combined = pd.concat([combined, pclass_dummies], axis=1)
    combined.drop('Pclass', axis=1, inplace=True)
    status('Pclass')
    return combined


def clean_ticket(ticket: str) -> str:
    """
    Cleans the 'Ticket' string by removing certain characters and extracting the prefix.


    Parameters:
    - ticket (str): The ticket string.


    Returns:
    - str: The cleaned ticket prefix or 'XXX' if no prefix exists.
    """
    ticket = ticket.replace('.', '').replace('/', '').split()
    ticket = list(map(str.strip, ticket))
    ticket = list(filter(lambda t: not t.isdigit(), ticket))
    return ticket[0] if len(ticket) > 0 else 'XXX'


def encode_ticket(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Encodes the 'Ticket' column by extracting prefixes and creating dummy variables.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with dummy variables for 'Ticket'.
    """
    combined['Ticket'] = combined['Ticket'].map(clean_ticket)
    tickets_dummies = pd.get_dummies(combined['Ticket'], prefix='Ticket')
    combined = pd.concat([combined, tickets_dummies], axis=1)
    combined.drop('Ticket', axis=1, inplace=True)
    status('Ticket')
    return combined


def process_family(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Creates family-related features based on 'SibSp' and 'Parch'.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with new family-related features.
    """
    combined['FamilySize'] = combined['Parch'] + combined['SibSp'] + 1
    combined['Singleton'] = combined['FamilySize'].apply(lambda s: 1 if s == 1 else 0)
    combined['SmallFamily'] = combined['FamilySize'].apply(lambda s: 1 if 2 <= s <= 4 else 0)
    combined['LargeFamily'] = combined['FamilySize'].apply(lambda s: 1 if s >= 5 else 0)
    status('Family')
    return combined


def encode_cabin(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Encodes the 'Cabin' column by extracting the first letter and creating dummy variables.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with dummy variables for 'Cabin'.
    """
    combined['Cabin'] = combined['Cabin'].fillna('Unknown')
    combined['Cabin'] = combined['Cabin'].map(lambda x: x[0] if x != 'Unknown' else 'U')
    cabin_dummies = pd.get_dummies(combined['Cabin'], prefix='Cabin')
    combined = pd.concat([combined, cabin_dummies], axis=1)
    combined.drop('Cabin', axis=1, inplace=True)
    status('Cabin')
    return combined


def encode_embarked(combined: pd.DataFrame) -> pd.DataFrame:
    """
    Encodes the 'Embarked' column using dummy variables.


    Parameters:
    - combined (pd.DataFrame): The combined DataFrame.


    Returns:
    - combined (pd.DataFrame): DataFrame with dummy variables for 'Embarked'.
    """
    combined['Embarked'] = combined['Embarked'].fillna('S')  # Assuming 'S' is the most common
    embarked_dummies = pd.get_dummies(combined['Embarked'], prefix='Embarked')
    combined = pd.concat([combined, embarked_dummies], axis=1)
    combined.drop('Embarked', axis=1, inplace=True)
    status('Embarked')
    return combined


def feature_engineering(train_path: str = './data/train.csv',
                       test_path: str = './data/test.csv') -> tuple:
    """
    Executes the complete feature engineering pipeline.


    Parameters:
    - train_path (str): Path to the training data CSV file.
    - test_path (str): Path to the testing data CSV file.


    Returns:
    - combined (pd.DataFrame): Feature-engineered DataFrame.
    - targets (pd.Series): Target variable from the training data.
    """
    # Step 1: Combine Data
    combined, targets = get_combined_data(train_path, test_path)


    # Step 2: Extract Titles
    combined = extract_titles(combined)


    # Continue with other feature engineering steps
    combined = fill_missing_ages(combined)
    combined = fill_missing_fares(combined)
    combined = encode_sex(combined)
    combined = encode_pclass(combined)
    combined = encode_ticket(combined)
    combined = encode_cabin(combined)
    combined = encode_embarked(combined)
    combined = process_family(combined)


    # Debug: Check for non-numeric columns
    non_numeric = combined.select_dtypes(include=['object']).columns
    if len(non_numeric) > 0:
        print(f"Non-numeric columns remaining: {non_numeric.tolist()}")
    else:
        print("All columns are numeric.")


    return combined, targets


if __name__ == "__main__":
    # Example usage
    combined_data, target = feature_engineering()


    print(f"Combined Data Shape: {combined_data.shape}")
    print(combined_data.head())
“
“import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectFromModel
from Feature_engineering import feature_engineering


def compute_score(clf, X, y, scoring='accuracy'):
    """
    Computes the cross-validation score for a given classifier.


    Parameters:
    - clf: The classifier to evaluate.
    - X (pd.DataFrame): Feature matrix.
    - y (pd.Series or np.ndarray): Target vector.
    - scoring (str): Scoring metric.


    Returns:
    - float: Mean cross-validation score.
    """
    scores = cross_val_score(clf, X, y, cv=5, scoring=scoring)
    return np.mean(scores)


def recover_train_test(combined: pd.DataFrame, targets: pd.Series) -> tuple:
    """
    Splits the combined dataset back into training and testing sets.


    Parameters:
    - combined (pd.DataFrame): Combined feature-engineered DataFrame.
    - targets (pd.Series): Target variable.


    Returns:
    - tuple: (train_features, test_features, targets)
    """
    train = combined.iloc[:len(targets)]
    test = combined.iloc[len(targets):]
    return train, test, targets


def main():
    # Step 1: Feature Engineering
    combined, targets = feature_engineering()


    # Step 2: Split into Train and Test
    train, test, targets = recover_train_test(combined, targets)


    # Step 3: Feature Selection using Random Forest
    from sklearn.ensemble import RandomForestClassifier
    rf_clf = RandomForestClassifier(n_estimators=50, max_features='sqrt', random_state=42)
    rf_clf.fit(train, targets)


    selector = SelectFromModel(rf_clf, prefit=True)
    train_reduced = selector.transform(train)
    test_reduced = selector.transform(test)


    print(f"Reduced Train Shape: {train_reduced.shape}")
    print(f"Reduced Test Shape: {test_reduced.shape}")


    # Step 4: Initialize Logistic Regression
    logreg = LogisticRegression(max_iter=1000, random_state=42)


    # Step 5: Evaluate Model with Cross-Validation
    cv_score = compute_score(logreg, train_reduced, targets, scoring='accuracy')
    print(f"Logistic Regression CV Accuracy: {cv_score:.4f}")


    # Step 6: Train the Model on Entire Training Set
    logreg.fit(train_reduced, targets)


    # Step 7: Make Predictions on Test Set
    predictions = logreg.predict(test_reduced)


    # Step 8: Prepare Submission
    submission = pd.read_csv('./data/test.csv')[['PassengerId']].copy()
    submission['Survived'] = predictions
    submission.to_csv('submission_logistic_regression.csv', index=False)
    print("Submission file 'submission_logistic_regression.csv' created successfully.")


if __name__ == "__main__":
    main()
“
Q- next want to give with file called save_model.py that implemnt a function to save the model in the other file using joblib oky