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?