onnx / onnxmltools

ONNXMLTools enables conversion of models to ONNX
https://onnx.ai
Apache License 2.0
1.03k stars 188 forks source link

use custom objective function #502

Open RenEjima opened 3 years ago

RenEjima commented 3 years ago

I have a question. Can't we use custom objective function in onnx?

I difined "focal_loss" as a objective function.

ONNX couldn't save following LightGBM model,

model = lgb.LGBMClassifier(objective=focal_loss, learning_rate=0.1, num_boost_round=10)
model.fit(
        X_train,
        y_train,
        eval_set=[(X_eval, y_eval)],
        eval_metric=eval_error)

but ONNX could save following LightGBM model.

model = lgb.LGBMClassifier(objective='binary', learning_rate=0.1, num_boost_round=10)
model.fit(
        X_train,
        y_train,
        eval_set=[(X_eval, y_eval)],
        eval_metric=eval_error)

If there is any way to use custom objective function, please let me know.

xadupre commented 3 years ago

onnxmltools only saves the final tree and does not need to know which cost function was used to trained the tree. It is possible to add any custom information in the metadata after the conversion if you need to save some information about the training:

meta = {'pA': 'one', 'pB': 'two'}
onnx.helper.set_model_props(model_onnx, meta)
RenEjima commented 3 years ago

Thank you for you reply! I don't need information about history of training and I need only the final tree now. When I want to do so, how can I save LGBMClassifier with custom cost function using onnxmltools?

xadupre commented 3 years ago

The converter for lightgbm works the same way. It does not store the cost function but it can be added to the metadata as well after the conversion.

RenEjima commented 3 years ago

This is my code and I wrote this with reference to http://onnx.ai/sklearn-onnx/auto_examples/plot_pipeline_lightgbm.html

def registerConvONNX_lightGBM():

    update_registered_converter(
        LGBMClassifier, 'LightGbmLGBMClassifier',
        calculate_linear_classifier_output_shapes, convert_lightgbm,
        options={'nocl': [True, False]}
    )

def buildONNXModel_lightGBM(model):
    registerConvONNX_lightGBM()
    return convert_sklearn(model, 'lightgbm',[('input', FloatTensorType([None, colExpVarDim]))],target_opset=12)

def saveONNXModel(model_onnx,model_name):
    with open(model_name, "wb") as f:
        f.write(model_onnx.SerializeToString())

model = LGBMClassifier(boosting_type='gbdt',objective=get_focal_loss,n_estimators=150,metric="custom")
        print("training is starting")
model.fit(
            X_train,
            y_train,
            eval_set=[(X_eval, y_eval)],
            eval_metric=get_focal_error,
            early_stopping_rounds=30,)

model_onnx = buildONNXModel_lightGBM(model) 
saveONNXModel(model_onnx,'lightGBM.onnx')

Then, I can't save model because I use custom objective... but I can save model if I use objective='binary'... How can I save only final tree?

xadupre commented 3 years ago

I'll see what I can do. The objective is used to guess the type of outputs (regressor, classifier) the converted model should have. I need to see how to retrieve that information in some other way.

RenEjima commented 3 years ago

The objective is used to guess the type of outputs (regressor, classifier) the converted model should have.

I think it is better to add new input(it describe the model type such as classifier, regressor,or Ranker) when saving onnx model.

RenEjima commented 2 years ago

Hi @xadupre , is this issue still unresolved? I think custom objective function(for example, Focal loss, IBloss, and so on) is one of the strong way against unbalance data and many realistic case is unbalance. So I hope this issue will be solved soon.

xadupre commented 2 years ago
ogencoglu commented 2 months ago

It would be really useful to fix this.

lightgbm models trained with a custom objective function can not be converted to onnx currently. This is weird because why should inference care about the training objective.