[Python] Pipeline FutureWarning: This Pipeline instance is not fitted yet

Discussão em 'Python' iniciado por Stack, Fevereiro 28, 2025.

  1. Stack

    Stack Membro Participativo

    I am working on a fairly simple machine learning problem in the form of a practicum. I am using the following code to preprocess the data:

    from preprocess.date_converter import DateConverter
    from sklearn.pipeline import Pipeline
    from preprocess.nan_fixer import CustomImputer
    import pandas as pd
    from preprocess.encoding import FrecuencyEncoding
    from sklearn.model_selection import train_test_split
    from sklearn.decomposition import PCA
    from preprocess.scaler import CustomScaler



    def basic_preprocess(df, target : str):

    important_features = ['amt', 'category', 'merchant', 'trans_date_trans_time', 'unix_time', 'dob', 'street', 'merch_lat', 'merch_long', 'city', 'merch_zipcode', 'city_pop', 'job', 'last', 'first', 'cc_num', 'long', 'zip', "is_fraud"]

    df = df.drop(["trans_num", "Unnamed: 0"], axis=1)
    df = df[important_features]
    df = df.copy()

    # df, df_ = train_test_split(df, test_size=0.5, shuffle=True, random_state=42, stratify=df[target])

    df_train, unseen_df = train_test_split(df, test_size=0.2, shuffle=True, random_state=42, stratify=df[target])
    df_val, df_test = train_test_split(unseen_df, test_size=0.5, shuffle=True, random_state=42, stratify=unseen_df[target])

    pipeline = Pipeline([
    ("date_converter", DateConverter("trans_date_trans_time")),
    ("imputer", CustomImputer(strategy="most_frequent")),
    ("encoding", FrecuencyEncoding()),
    ("scaler", CustomScaler(df.drop(target, axis=1).columns.tolist())),
    ])



    pipeline.fit(df_train.drop(target, axis=1), df_train[target])
    X_train = pd.DataFrame(pipeline.transform(df_train.drop(target, axis=1)), index=df_train.index)
    X_test = pd.DataFrame(pipeline.transform(df_test.drop(target, axis=1)), index=df_test.index)
    X_val = pd.DataFrame(pipeline.transform(df_val.drop(target, axis=1)), index=df_val.index)


    df_train = pd.concat([X_train, df_train[target]], axis=1)
    df_test = pd.concat([X_test, df_test[target]], axis=1)
    df_val = pd.concat([X_val, df_val[target]], axis=1)


    return [df_train, df_test, df_val]


    Note: preprocess is a personal library that I created to make some transformers of my own. Here is the code for each of the transformers:

    class CustomScaler(BaseEstimator, TransformerMixin):
    """
    Receives the numeric columns from the dataframe. Scales their values using RobustScaler.
    """
    def __init__(self, attributes):
    self.attributes = attributes
    self.scaler = RobustScaler() # Inicializa el escalador

    def fit(self, X, y=None):
    # Ajusta el escalador solo con los datos de entrenamiento
    scale_cols = X[self.attributes]
    self.scaler.fit(scale_cols)
    return self

    def transform(self, X, y=None):
    X_copy = X.copy()
    scale_attrs = X_copy[self.attributes]
    # Usa el escalador ya ajustado para transformar los datos
    X_scaled = self.scaler.transform(scale_attrs)
    X_scaled = pd.DataFrame(X_scaled, columns=self.attributes, index=X_copy.index)
    for attr in self.attributes:
    X_copy[attr] = X_scaled[attr]
    return X_copy


    class CustomImputer(BaseEstimator, TransformerMixin):
    """
    It implements SimpleImputer but, unlike SimpleImputer, it returns
    dataframes and not numpy arrays.
    """
    def __init__(self, strategy : str) -\> None:
    self._imputer = SimpleImputer(strategy=strategy)

    def fit(self, X, y=None):
    self._imputer.fit(X, y)
    return self

    def transform(self, X, y=None):
    transformed_data = self._imputer.transform(X)
    return pd.DataFrame(transformed_data, columns=X.columns)


    class FrecuencyEncoding(BaseEstimator, TransformerMixin):
    """
    Searches for categorical columns and replaces them
    using Frequency Encoding
    """
    def __init__(self):
    self._frequencies = {}

    def fit(self, X, y=None):
    for col in X.select_dtypes(['object']).columns:
    self._frequencies[col] = X[col].value_counts().to_dict()
    return self

    def transform(self, X, y=None):
    df_encoded = X.copy()
    for col in df_encoded.select_dtypes(['object']).columns:
    df_encoded[col] = df_encoded[col].map(self._frequencies[col])
    df_encoded[col] = df_encoded[col].fillna(0)
    return df_encoded


    class DateConverter(BaseEstimator, TransformerMixin):
    """
    Transformer created to convert all date columns to float.

    It receives the list of date columns in the constructor.

    Consider that in order to convert all elements (including nan) to float,
    it was necessary to convert nans to 0 and then convert 0 to nans again.
    """
    def __init__(self, attributes):
    self.attributes = attributes
    def fit(self, X, y=None):
    return self
    def transform(self, X, y=None):
    X = X.copy()
    def converter(col):
    return pd.to_datetime(col, errors='coerce').apply(lambda x: x.timestamp() if pd.notna(x) else 0).astype(float).replace(0, np.nan) if col.name in self.attributes else col
    return X.apply(converter)


    The problem is that, running basic_preprocess I get the following error message:

    /home/santiago/.local/lib/python3.10/site-packages/sklearn/pipeline.py:62: FutureWarning: This Pipeline instance is not fitted yet. Call 'fit' with appropriate arguments before using other methods such as transform, predict, etc. This will raise an error in 1.8 instead of the current warning.
    warnings.warn(
    /home/santiago/.local/lib/python3.10/site-packages/sklearn/pipeline.py:62: FutureWarning: This Pipeline instance is not fitted yet. Call 'fit' with appropriate arguments before using other methods such as transform, predict, etc. This will raise an error in 1.8 instead of the current warning.
    warnings.warn(


    This is no longer the case if I use PCA at the end of the pipeline:

    pipeline = Pipeline([
    ("date_converter", DateConverter("trans_date_trans_time")),
    ("imputer", CustomImputer(strategy="most_frequent")),
    ("encoding", FrecuencyEncoding()),
    ("scaler", CustomScaler(df.drop(target, axis=1).columns.tolist())),
    ("PCA", PCA(n_components=0.999))

    ])


    How to resolve it?

    I ran the transformers separately expecting to get some unexpected behavior, but they all worked perfectly.

    Continue reading...

Compartilhe esta Página