2

我有一个从 SAS Miner 生成的 PMML,我无法使用 JPMML 1.1.4 进行正确评估。JPMML 1.1.4 说它支持 PMML 4.2,而 PMML 说它是 PMML 4.2 版。

以下函数“SAS-EM-String-Normalize”中的 FMTWIDTH 是正确的 PMML 语法吗?

任何想法为什么我不能使用 JPMML 评估这个函数?

我的 TransformationDictionary 中的函数看起来像,

<TransformationDictionary>
    <DefineFunction name="SAS-EM-String-Normalize" optype="categorical" dataType="string">
        <ParameterField name="FMTWIDTH" optype="continuous"/>
        <ParameterField name="AnyCInput" optype="categorical"/>
        <Apply function="trimBlanks">
          <Apply function="uppercase">
            <Apply function="substring">
              <FieldRef field="AnyCInput"/>
              <Constant>1</Constant>
              <Constant>FMTWIDTH</Constant>
            </Apply>
          </Apply>
        </Apply>   
    </DefineFunction>
</TransformationDictionary>

我得到以下异常,

线程“主”org.jpmml.evaluator.TypeCheckException 中的异常:应为 INTEGER,但在 org.jpmml.evaluator.FieldValue.asInteger(FieldValue.java:125) 的 org.jpmml.evaluator.FunctionRegistry$36 处获得了 STRING (FMTWIDTH)。在 org.jpmml.evaluator.ExpressionUtil.evaluateApply(ExpressionUtil.java:203) 在 org.jpmml.evaluator.ExpressionUtil 的 org.jpmml.evaluator.FunctionUtil.evaluate(FunctionUtil.java:38) 评估(FunctionRegistry.java:463) .evaluate(ExpressionUtil.java:91) 在 org.jpmml.evaluator.FunctionUtil.evaluate(FunctionUtil.java:76) 在 org.jpmml.evaluator.FunctionUtil.evaluate(FunctionUtil.java:43) 在 org.jpmml.evaluator。 ExpressionUtil.evaluateApply(ExpressionUtil.java:203) 在 org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:91) 在 org.jpmml.evaluator.ExpressionUtil。evaluateApply(ExpressionUtil.java:188) at org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:91) at org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:58) at org.jpmml.evaluator.ExpressionUtil .evaluate(ExpressionUtil.java:45) 在 org.jpmml.evaluator.ExpressionUtil.evaluateMapValues(ExpressionUtil.java:169) 在 org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:87) 在 org.jpmml.evaluator。 ExpressionUtil.evaluate(ExpressionUtil.java:58) at org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:45) at org.jpmml.evaluator.RegressionModelEvaluator.evaluateRegressionTable(RegressionModelEvaluator.java:150) at org.jpmml.evaluator .RegressionModelEvaluator.evaluateClassification(RegressionModelEvaluator.java:107) 在 org.jpmml.evaluator。RegressionModelEvaluator.evaluate(RegressionModelEvaluator.java:57) at org.jpmml.evaluator.ModelEvaluator.evaluate(ModelEvaluator.java:65) at ValidPMMLTesterRandomScores.randomEvaluation(ValidPMMLTesterRandomScores.java:116) at ValidPMMLTesterRandomScores.printModelInformation(ValidPMMLTesterRandomScores.java:94) at ValidPMMLTesterRandomScores.readModelFromFile(ValidPMMLTesterRandomScores.java:142) 在 ValidPMMLTesterRandomScores.main(ValidPMMLTesterRandomScores.java:160)readModelFromFile(ValidPMMLTesterRandomScores.java:142) 在 ValidPMMLTesterRandomScores.main(ValidPMMLTesterRandomScores.java:160)readModelFromFile(ValidPMMLTesterRandomScores.java:142) 在 ValidPMMLTesterRandomScores.main(ValidPMMLTesterRandomScores.java:160)

4

2 回答 2

3

根据PMML 内置函数“substring”的正式定义,它需要一个字符串参数和两个整数参数。SAS EM 生成的 PMML 代码尝试使用字符串参数、整数参数和另一个字符串参数调用此函数substring($AnyCInput, 1, "FMTWIDTH")

可以通过使用以下元素访问“FMTWIDTH”参数的值来修复此 PMML 片段FieldRef

<Apply function="substring">
  <FieldRef field="AnyCInput"/>
  <Constant>1</Constant>
  <FieldRef field="FMTWIDTH"/>
</Apply>

总之,JPMML 是正确的,SAS EM 是错误的。

于 2015-10-09T15:35:32.480 回答
0

通过重新排列 PMML 类模型对象,可以即时更正无效的 PMML 文档。JPMML-Model 库的访问者 API正是为此目的而设计的:

PMML pmml = loadSasEmPMML()

Visitor invalidSubstringCorrector = new AbstractVisitor(){

    @Override
    public VisitorAction visit(Apply apply){
        if(isInvalidSubstring(apply)){
            List<Expression> expressions = apply.getExpressions();

            expressions.set(2, new FieldRef(new FieldName("FMTWIDTH")));
        }
        return super.visit(apply);
    }

    private boolean isInvalidSubstring(Apply apply){
        if(("substring").equals(apply.getFunction())){
            List<Expression> expressions = apply.getExpressions();

            Expression lengthArgument = expressions.get(2);
            if(lengthArgument instanceof Constant){
                Constant constant = (Constant)lengthArgument;
                return ("FMTWIDTH").equals(constant.getValue());
            }
        }
        return false;
    }
};

invalidSubstringCorrector.applyTo(pmml);

目前,该方法isInvalidSubstring(Apply)通过仅检查第三个表达式元素是否为字符串常量“FMTWIDTH”来识别有问题的 Apply 元素。如果需要更加确定,那么添加关于第一个和第二个表达式元素的正确断言也许是一个好主意。

于 2015-10-15T20:24:05.360 回答