2

I have a sklearn pipeline. One of its step is ExpressionTransformer(f"round(X[0]*{nRoundMin})/{nRoundMin}") (importing ExpressionTransformer from sklearn2pmml.preprocessing). When I try to write this pipeline into a PMML file, I get the following error:

Standard output is empty
Standard error:
Jun 27, 2019 8:39:55 AM org.jpmml.sklearn.Main run
INFO: Parsing PKL..
Jun 27, 2019 8:40:53 AM org.jpmml.sklearn.Main run
INFO: Parsed PKL in 58085 ms.
Jun 27, 2019 8:40:53 AM org.jpmml.sklearn.Main run
INFO: Converting..
Jun 27, 2019 8:41:03 AM org.jpmml.sklearn.Main run
SEVERE: Failed to convert
java.lang.IllegalArgumentException: round
    at org.jpmml.sklearn.ExpressionTranslator.translateFunction(ExpressionTranslator.java:94)
    at org.jpmml.sklearn.ExpressionTranslator.FunctionInvocationExpression(ExpressionTranslator.java:513)
    at org.jpmml.sklearn.ExpressionTranslator.PrimaryExpression(ExpressionTranslator.java:416)
    at org.jpmml.sklearn.ExpressionTranslator.UnaryExpression(ExpressionTranslator.java:374)
    at org.jpmml.sklearn.ExpressionTranslator.MultiplicativeExpression(ExpressionTranslator.java:316)
    at org.jpmml.sklearn.ExpressionTranslator.AdditiveExpression(ExpressionTranslator.java:280)
    at org.jpmml.sklearn.ExpressionTranslator.ComparisonExpression(ExpressionTranslator.java:228)
    at org.jpmml.sklearn.ExpressionTranslator.NegationExpression(ExpressionTranslator.java:217)
    at org.jpmml.sklearn.ExpressionTranslator.LogicalAndExpression(ExpressionTranslator.java:187)
    at org.jpmml.sklearn.ExpressionTranslator.LogicalOrExpression(ExpressionTranslator.java:166)
    at org.jpmml.sklearn.ExpressionTranslator.IfElseExpression(ExpressionTranslator.java:147)
    at org.jpmml.sklearn.ExpressionTranslator.Expression(ExpressionTranslator.java:140)
    at org.jpmml.sklearn.ExpressionTranslator.translateExpressionInternal(ExpressionTranslator.java:134)
    at org.jpmml.sklearn.ExpressionTranslator.translate(ExpressionTranslator.java:33)
    at org.jpmml.sklearn.ExpressionTranslator.translate(ExpressionTranslator.java:22)
    at sklearn2pmml.preprocessing.ExpressionTransformer.encodeFeatures(ExpressionTransformer.java:43)
    at sklearn.pipeline.Pipeline.encodeFeatures(Pipeline.java:81)

though round is in the PMML built-in functions (http://dmg.org/pmml/v4-2-1/BuiltinFunctions.html#math). How should I write this pipeline step to get the round function translated properly ?

If I remove the round function in the above ExpressionTransfomer, the PMML is created without any issue.

I've also tried to replace the above ExpressionTransfomer by

Pipeline([
    ("i", ExpressionTransformer("X[0]*"+str(nRoundMin))),
    ("r", FunctionTransformer(np.round)),
    ("f", ExpressionTransformer("X[0]/"+str(nRoundMin)))
])

and

Pipeline([
    ("i", ExpressionTransformer("X[0]*"+str(nRoundMin))),
    ("r", FunctionTransformer(round)),
    ("f", ExpressionTransformer("X[0]/"+str(nRoundMin)))
])

but it didn't help.

[Edit] Following user1808924's recommendation, I've also tried ExpressionTransformer(f"numpy.rint(X[0]*{nRoundMin})/{nRoundMin}"), which yields to a similar error:

Standard output is empty
Standard error:
Jun 27, 2019 12:38:51 PM org.jpmml.sklearn.Main run
INFO: Parsing PKL..
Jun 27, 2019 12:39:54 PM org.jpmml.sklearn.Main run
INFO: Parsed PKL in 63076 ms.
Jun 27, 2019 12:39:54 PM org.jpmml.sklearn.Main run
INFO: Converting..
Jun 27, 2019 12:40:05 PM org.jpmml.sklearn.Main run
SEVERE: Failed to convert
java.lang.IllegalArgumentException: numpy.rint
    at org.jpmml.sklearn.ExpressionTranslator.translateFunction(ExpressionTranslator.java:94)
    at org.jpmml.sklearn.ExpressionTranslator.FunctionInvocationExpression(ExpressionTranslator.java:513)
    at org.jpmml.sklearn.ExpressionTranslator.PrimaryExpression(ExpressionTranslator.java:416)
    at org.jpmml.sklearn.ExpressionTranslator.UnaryExpression(ExpressionTranslator.java:374)
    at org.jpmml.sklearn.ExpressionTranslator.MultiplicativeExpression(ExpressionTranslator.java:316)
    at org.jpmml.sklearn.ExpressionTranslator.AdditiveExpression(ExpressionTranslator.java:280)
    at org.jpmml.sklearn.ExpressionTranslator.ComparisonExpression(ExpressionTranslator.java:228)
    at org.jpmml.sklearn.ExpressionTranslator.NegationExpression(ExpressionTranslator.java:217)
    at org.jpmml.sklearn.ExpressionTranslator.LogicalAndExpression(ExpressionTranslator.java:187)
    at org.jpmml.sklearn.ExpressionTranslator.LogicalOrExpression(ExpressionTranslator.java:166)
    at org.jpmml.sklearn.ExpressionTranslator.IfElseExpression(ExpressionTranslator.java:147)
    at org.jpmml.sklearn.ExpressionTranslator.Expression(ExpressionTranslator.java:140)
    at org.jpmml.sklearn.ExpressionTranslator.translateExpressionInternal(ExpressionTranslator.java:134)
    at org.jpmml.sklearn.ExpressionTranslator.translate(ExpressionTranslator.java:33)
    at org.jpmml.sklearn.ExpressionTranslator.translate(ExpressionTranslator.java:22)
    at sklearn2pmml.preprocessing.ExpressionTransformer.encodeFeatures(ExpressionTransformer.java:43)

1 Answers1

2

The ExpressionTransformer expects a string argument that is a valid Python expression (evaluatable in your local workspace environment). Therefore, if you want to apply rounding, you need to use some built-in Python function for doing so.

For example, you can use Numpy's rint universal function:

transformer = ExpressionTransformer("numpy.rint(X[0] / X[1])")
user1808924
  • 4,563
  • 2
  • 17
  • 20
  • Thanks, but it also fails in sklearn2pmml. I've edited my question to add the error message. – user11671065 Jun 27 '19 at 12:44
  • What's your SkLearn2PMML package version? The support for Numpy UFuncs was introduced in one of the very latest versions. Try upgrading to SkLearn2PMML 0.47.0 or newer, and re-run the experiment. – user1808924 Jun 27 '19 at 14:17
  • I have sklearn2pmml==0.87.1 version and this worked for me. – Tom Dec 14 '22 at 14:35