jpmml / jpmml-lightgbm

Java library and command-line application for converting LightGBM models to PMML
GNU Affero General Public License v3.0
174 stars 58 forks source link

Converting LightGBM models with custom objective functions to PMML #65

Closed mk2424-cyber closed 1 month ago

mk2424-cyber commented 1 month ago

My model file: it is a ightgbm model, v4 and has custom objective function using asymmetric focal loss.

cat lgbm.ml | grep objective
[objective: custom]
[objective: 5]

What I’ve tried: Using 1.5.4 jar file (also attempted 1.4.7) and unable to create pmml file for my lightgbm v4 model.

Command:

java -jar pmml-lightgbm-example/target/pmml-lightgbm-example-executable-1.5-SNAPSHOT.jar --lgbm-input lgb_model.txt --pmml-output lightgbm_model.pmml

Error:

INFO: Loading GBDT..
Aug 01, 2024 11:09:52
Aug 01, 2024 11:09:55 PM org. jpmml. lightgbm. example.Main run
INFO: Loaded GBDT in 3621 ms.
Aug 01, 2024 11:09:55 PM org. jpmml. lightgbm. example.Main run
INFO: Converting GBDT to PMML..
Aug 01, 2024 11:09:55 PM org- jpmml. lightgbm. example.Main run
SEVERE: Failed to convert GBDT to PMML java. lang. IllegalStateException
at org. jpmml. lightgbm.GBDT. encodeSchema (GBDT. java: 175)
at org. jpmml. lightgbm.GBDT. encodePMML (GBDT. java: 409)
at org-jpmml. lightgbm. example.Main. run (Main.java:175)
at org. jpmml. lightgbm.example.Main.main (Main-java:136)

How do I solve this issue?

vruusmann commented 1 month ago

My model file: it is a ightgbm model, v4 and has custom objective function using asymmetric focal loss.

There are three ways to approach this. I'm not familiar with the implementation of your custom objective function (OF), so I cannot suggest which way is the most appropriate here. But give them a try, and then tell me what worked for you.

First, is your custom OF compatible with some LightGBM's built-in OF? If it is, then simply edit your LightGBM model file and replace the contents of the [objective: ...] attribute.

For example, if your OF is compatible with the most common regression target, insert the following into your LightGBM model file:

[objective: regression]

Second, the JPMML-LightGBM command-line application accepts a --objective option. This way, you don't need to edit the LightGBM model file, and can make a "in-memory edit" to the file being converted:

$ java  -jar pmml-lightgbm-example-executable-1.5-SNAPSHOT.jar --lgbm-input mymodel.txt --pmml-output mymodel.pmml --objective <your objective function's specification>

This command-line option was added based on some user's request a while ago. There should be a GitHub issue (in "closed" state) about its usage. Find it yourself.

Third, if your OF is performing actual computations during prediction time (such as applying some transformation to the interim LightGBM booster score), then you need to implement your own subclass of org.jpmml.lightgbm.ObjectiveFunction, and register with the JPMML-LightGBM runtime.

You can browse the implementations of built-in OF classes for inspiration. For example, PoissonRegression and BinomialLogisticRegression

vruusmann commented 1 month ago

See https://github.com/jpmml/jpmml-lightgbm/issues/55

vruusmann commented 1 month ago

the JPMML-LightGBM command-line application accepts a --objective option

The Java code for parsing this command-line argument is here: https://github.com/jpmml/jpmml-lightgbm/blob/1.5.4/pmml-lightgbm/src/main/java/org/jpmml/lightgbm/LightGBMUtil.java#L97-L132

So, the syntax appears to be "Java OF class name, followed by a whitespace-separated list of OF config entries"

For example:

java  -jar pmml-lightgbm-example-executable-1.5-SNAPSHOT.jar --objective "org.jpmml.lightgbm.Regression(metric:l2)" --lgbm-file <path> --pmml-file <path>
vruusmann commented 1 month ago

I simplified the format of command-line OF strings somewhat in the latest 1.5.5 version. Specifically, the "config section" is now optional.

Earlier:

java -jar pmml-lightgbm-example-executable-1.5.4.jar --objective "org.jpmml.lightgbm.Regression(regression metric:l2)" ...

Now:

java -jar pmml-lightgbm-example-executable-1.5.5.jar --objective org.jpmml.lightgbm.Regression ...
vruusmann commented 1 month ago

Some more command-line OF string examples: https://github.com/jpmml/jpmml-lightgbm/blob/1.5.5/pmml-lightgbm/src/test/java/org/jpmml/lightgbm/LightGBMUtilTest.java#L29-L58

mk2424-cyber commented 1 month ago

Thank you very much! I went with option 1, it was the simplest for my use case. I added the objective in the model file and it worked like a charm. Cheers!