使用JPMML评估SAS生成的PMML文件时出现FMTWIDTH错误

时间:2015-10-07 22:17:58

标签: java sas pmml

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

FMTWIDTH是否在以下功能" SAS-EM-String-Normalize"适当的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>

我得到以下异常,

  

线程中的异常&#34; main&#34; org.jpmml.evaluator.TypeCheckException:   期待INTEGER,但得到了STRING(FMTWIDTH)   org.jpmml.evaluator.FieldValue.asInteger(FieldValue.java:125)at   org.jpmml.evaluator.FunctionRegistry $ 36.evaluate(FunctionRegistry.java:463)     在org.jpmml.evaluator.FunctionUtil.evaluate(FunctionUtil.java:38)     在   org.jpmml.evaluator.ExpressionUtil.evaluateApply(ExpressionUtil.java:203)     在   org.jpmml.evaluator.ExpressionUtil.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)     在   org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:91)     在   org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:58)     在   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)     在   org.jpmml.evaluator.ExpressionUtil.evaluate(ExpressionUtil.java:45)     在   org.jpmml.evaluator.RegressionModelEvaluator.evaluateRegressionTable(RegressionModelEvaluator.java:150)     在   org.jpmml.evaluator.RegressionModelEvaluator.evaluateClassification(RegressionModelEvaluator.java:107)     在   org.jpmml.evaluator.RegressionModelEvaluator.evaluate(RegressionModelEvaluator.java:57)     在   org.jpmml.evaluator.ModelEvaluator.evaluate(ModelEvaluator.java:65)     在   ValidPMMLTesterRandomScores.randomEvaluation(ValidPMMLTesterRandomScores.java:116)     在   ValidPMMLTesterRandomScores.printModelInformation(ValidPMMLTesterRandomScores.java:94)     在   ValidPMMLTesterRandomScores.readModelFromFile(ValidPMMLTesterRandomScores.java:142)     在   ValidPMMLTesterRandomScores.main(ValidPMMLTesterRandomScores.java:160)

2 个答案:

答案 0 :(得分:3)

根据formal definition of the PMML built-in function "substring",它需要一个字符串参数和两个整数参数。 SAS EM生成的PMML代码尝试使用字符串参数,整数参数和另一个字符串参数substring($AnyCInput, 1, "FMTWIDTH")来调用此函数。

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

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

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

答案 1 :(得分:0)

通过重新排列PMML类模型对象,可以动态更正无效的PMML文档。 JPMML-Model library的访问者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元素。如果需要更加确定,那么对于第一个和第二个表达式元素添加适当的断言也许是一个好主意。