Modify sklearn model threshold 'DIRECTLY' in model object loaded from Pickle file

Viewed 33

I am working on a 2-class classification problem. I trained a XGBoost model whose threshold needs to be tuned (from default 0.5 to 0.7) to get a better performance on train/test set.

I knew we can do something like this:

with open("XGBoost_model.pkl", "rb") as fr:
    model = pickle.load(fr)
Y_pred_1 = (model.predict_proba(X_test)[:, 1] >= 0.7).astype(int)

However, is there any way that I can make 0.7 as default threshold value so that the pickle-loaded model can make predicition directly with threshold 0.7 instead of 0.5?

with open("XGBoost_model.pkl", "rb") as fr:
    model = pickle.load(fr)
Y_pred_2 = model.predict(X)
\\ *** find a way to make Y_pred_1 == Y_pred_2***

This is my try: Override the loaded model instance (XGBClassifier object), I've tried 3 ways of doing it, but it ended up with runtime error shown below:

// This method is derived by modifying the model.predict method in *\lib\site-packages\xgboost\sklearn.py
// I changed the threshold from 0.5 to 0.7
def new_predict(
    self,
    X,
    output_margin=False,
    ntree_limit=None,
    validate_features=True,
    base_margin=None,
    iteration_range=None,
) -> np.ndarray:
    class_probs = super().predict(
        X=X,
        output_margin=output_margin,
        ntree_limit=ntree_limit,
        validate_features=validate_features,
        base_margin=base_margin,
        iteration_range=iteration_range,
    )
    if output_margin:
        # If output_margin is active, simply return the scores
        return class_probs

    if len(class_probs.shape) > 1 and self.n_classes_ != 2:
        # multi-class, turns softprob into softmax
        column_indexes: np.ndarray = np.argmax(class_probs, axis=1)  # type: ignore
    elif len(class_probs.shape) > 1 and class_probs.shape[1] != 1:
        # multi-label
        column_indexes = np.zeros(class_probs.shape)
        column_indexes[class_probs > 0.7] = 1
    elif self.objective == "multi:softmax":
        return class_probs.astype(np.int32)
    else:
        # turns soft logit into class label
        column_indexes = np.repeat(0, class_probs.shape[0])
        column_indexes[class_probs > 0.7] = 1

    if hasattr(self, "_le"):
        return self._le.inverse_transform(column_indexes)
    return column_indexes

And then, I tried 3 different ways to modify the instance method:

model.predict = new_predict
model.predict = functools.partial(new_predict, model)
model.predict = types.MethodType(new_predict, model)`

Get a runtime error:

model.predict(model, valid_X) //RuntimeError: super(): __class__ cell not found

Anyone can help me with this?

0 Answers
Related