marcotcr / lime

Lime: Explaining the predictions of any machine learning classifier
BSD 2-Clause "Simplified" License
11.64k stars 1.81k forks source link

Getting error when my predict_fn is actually a method from a class #736

Open ShahrinNakkhatra-optimizely opened 10 months ago

ShahrinNakkhatra-optimizely commented 10 months ago

Getting this error when my predict_fn is actually a function within a class.

lime_exp = lime_explainer.explain_instance(data_row=instance, predict_fn=self.explain_pipe)

This is how my methods looks like:

    def explain_pipe(self):
        temp_df = pd.DataFrame(self.selected_df, columns=self.cols)
        selected_df_ = temp_df.copy()
        dp = DataProcessingPrediction(selected_df_, self.local_directory, self.product)

        selected_df_ = dp.scale_df(
            scaler_path=os.path.join(self.local_directory, "scaler_objects.pkl"),
            col_names_path=os.path.join(self.local_directory, "scaled_col_names.pkl"),
        )
        selected_df_ = dp.clean_column_names()
        selected_df_ = dp.load_and_reorder(
            os.path.join(self.local_directory, "column_order.pkl")
        )

        selected_df_.drop(columns="is_churned", inplace=True)
        # selected_df_.to_csv('../train_pipe_outputs_/selected_df.csv')
        output = self.model.predict_proba(selected_df_)  # [ :,1]
        return output

    def explain_row(self, X_train, X_pred, row_number: int):
        lime_explainer = lime_tabular.LimeTabularExplainer(
            training_data=np.array(X_train),
            training_labels=self.training_labels,
            feature_names=X_train.columns,
            class_names=["not churn", "churn"],
            mode="classification",
        )

        instance = X_pred.iloc[row_number]
        lime_exp = lime_explainer.explain_instance(
            data_row=instance, predict_fn=self.explain_pipe
        )
        return lime_exp

The error I get is: yss = predict_fn(inverse) TypeError: Explanation.explain_pipe() takes 1 positional argument but 2 were given

This works totally fine if I use the predict_fn = explain_pipe without using any class.

ShahrinNakkhatra-optimizely commented 10 months ago

Update: It got fixed when I used some default arguments with explain_pipe:

def explain_pipe(self, selected_df=None, cols=None):
        if selected_df is None:
            selected_df = self.selected_df

        if cols is None:
            cols = self.cols

        temp_df = pd.DataFrame(selected_df, columns=cols)
        selected_df_ = temp_df.copy()
        dp = DataProcessingPrediction(selected_df_, self.local_directory, self.product)

        selected_df_ = dp.scale_df(
            scaler_path=os.path.join(self.local_directory, "scaler_objects.pkl"),
            col_names_path=os.path.join(self.local_directory, "scaled_col_names.pkl"),
        )

        selected_df_ = dp.clean_column_names()

        selected_df_ = dp.load_and_reorder(
            os.path.join(self.local_directory, "column_order.pkl")
        )

        selected_df_.drop(columns="is_churned", inplace=True)
        # selected_df_.to_csv('../train_pipe_outputs_/selected_df.csv')
        output = self.model.predict_proba(selected_df_)  # [ :,1]
        return output