【问题标题】:evaluate method takes long time - PMML models using Jpmml评估方法需要很长时间 - 使用 Jpmml 的 PMML 模型
【发布时间】:2017-06-23 18:58:32
【问题描述】:

今天我使用 Jpmml 来在我的代码中加载 pmml 模型。但是“评估”方法需要很长时间。 这是今天的工作代码:

    String modelPath = "....";
    ModelEvaluatorFactory factory = ModelEvaluatorFactory.newInstance();
    InputStream in = new   ByteArrayInputStream(modelPath.getBytes("UTF-8"));

    PMML pmmlModel = JAXBUtil.unmarshalPMML(new StreamSource(in)); 
    ModelEvaluator<?> evaluator = factory.newModelManager(pmmlModel);
    List<FieldName> activeFields = evaluator.getActiveFields();

    Map<FieldName, FieldValue> defaultFeatures = new HashMap<>();

    //after filling the 'defaultFeatures' the line below takes long time
    Map<FieldName, ?> results = evaluator.evaluate(defaultFeatures);

PMML 示例:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <PMML xmlns="http://www.dmg.org/PMML-4_2" version="4.2">
    <Header>
        <Application name="JPMML-SkLearn" version="1.0-SNAPSHOT"/>
        <Timestamp>2017-01-22T14:18:05Z</Timestamp>
    </Header>
    <DataDictionary>
        <DataField name="GENDER" optype="categorical" dataType="string">
            <Value value="0"/>
            <Value value="1"/>
        </DataField>
        <DataField name="1GA_" optype="continuous" dataType="double"/>
    //67000 rows of datafield
    </DataDictionary>
    <TransformationDictionary>
        <DefineFunction name="logit" optype="continuous" dataType="double">
            <ParameterField name="value" optype="continuous" dataType="double"/>
            <Apply function="/">
                <Constant dataType="double">1</Constant>
                <Apply function="+">
                    <Constant dataType="double">1</Constant>
                    <Apply function="exp">
                        <Apply function="*">
                            <Constant dataType="double">-1</Constant>
                            <FieldRef field="value"/>
                        </Apply>
                    </Apply>
                </Apply>
            </Apply>
        </DefineFunction>
    </TransformationDictionary>
     <MiningModel functionName="classification">
        <MiningSchema>
            <MiningField name="GENDER" usageType="target"/>
            <MiningField name="1GA_"/>
      //67000 rows of MiningField
       </MiningSchema>
        <Output>
            <OutputField name="probability_0" feature="probability" value="0"/>
            <OutputField name="probability_1" feature="probability" value="1"/>
        </Output>
        <LocalTransformations>
            <DerivedField name="x1" optype="continuous" dataType="double">
                <FieldRef field="1GA_"/>
            </DerivedField>
       //100000 rows
        </LocalTransformations>
         <Segmentation multipleModelMethod="modelChain">
            <Segment id="1">
                <True/>
                <RegressionModel functionName="regression">
                    <MiningSchema>
                        <MiningField name="1GA_"/>
                  </MiningSchema>
                    <Output>
                        <OutputField name="decisionFunction_1"    feature="predictedValue"/>
                        <OutputField name="logitDecisionFunction_1" optype="continuous" dataType="double" feature="transformedValue">
                            <Apply function="logit">
<FieldRef field="decisionFunction_1"/>
                            </Apply>
                        </OutputField>
                    </Output>
                    <RegressionTable intercept="-5.303370169392045">
           <NumericPredictor name="x1" coefficient="0.18476274186559316"/>
          //100000 rows of NumericPredictor

      </RegressionTable>
                 </RegressionModel>
              </Segment>
              <Segment id="2">
                  <True/>
                <RegressionModel functionName="regression">
                    <MiningSchema>
                        <MiningField name="logitDecisionFunction_1"/>
                    </MiningSchema>
                    <Output>
                        <OutputField name="logitDecisionFunction_0"  
     feature="predictedValue"/>
                    </Output>
                    <RegressionTable intercept="1.0">
            <NumericPredictor name="logitDecisionFunction_1" 

           coefficient="-1.0"/>
                        </RegressionTable>
                    </RegressionModel>
                </Segment>
                <Segment id="3">
                    <True/>
                    <RegressionModel functionName="classification">
                        <MiningSchema>
                            <MiningField name="GENDER" usageType="target"/>
                            <MiningField name="logitDecisionFunction_1"/>
                            <MiningField name="logitDecisionFunction_0"/>
                        </MiningSchema>
                        <RegressionTable intercept="0.0" targetCategory="1">
                            <NumericPredictor name="logitDecisionFunction_1" 


     coefficient="1.0"/>
                    </RegressionTable>
                <RegressionTable intercept="0.0" targetCategory="0">
                        <NumericPredictor name="logitDecisionFunction_0"   


       coefficient="1.0"/>
                        </RegressionTable>
                    </RegressionModel>
                </Segment>
         </Segmentation>
        </MiningModel>
        </PMML>

有一个想法是尝试使用 MLlib 代替 Jpmml。 有任何想法吗? 谢谢

【问题讨论】:

    标签: java performance apache-spark-mllib pmml


    【解决方案1】:

    “负载”是什么意思?是“将 PMML 文档解析为内存数据结构”还是“执行 PMML 文档”?

    您的代码似乎是针对后者的。但它肯定会失败,因为 JAXBUtil#unmarshalPMML(Source) 方法是用一个字节数组调用的,它不包含有效的 PMML 文档(没有 XML 解析器会接受 "....".getBytes("UTF-8"))。

    另外,“需要很长时间”是什么意思? JAXB 框架的一次性初始化成本约为 1 秒。之后,它每秒可以解组约 200 到 500 MB(即兆字节)的 PMML 内容。你还需要多少?

    【讨论】:

    • 嗨,代码正在运行。需要很长时间的是评估方法。因此我想使用 MLlib 文件夹。
    • 所以,“加载”实际上是指“执行”。 JPMML 正在根据存储在您的 PMML 文档中的执行计划执行模型。执行速度很慢,因为您的 PMML 文档包含无效的执行计划。您使用什么软件来生成这个 PMML 文档? Was 是 Apache Spark 自己的 PMMLExportable 接口,众所周知,它会生成低效的执行计划(例如,可以将单个分类数据列扩展到数千个连续数据列)。
    • 我添加了 pmml 架构。感谢您的帮助
    • 这就是你的性能问题的根源://67000 rows of datafield。基本上,JPMML 预计会执行一个需要 67'000(“六十七千”)参数的函数,而您对它的性能不满意?您需要重构存储在 PMML 文档中的执行计划。在这种情况下,您需要弄清楚这 67'000 个 DataField 元素真正代表什么。例如,也许它们代表 67 个分类特征,每个分类特征都有 1000 个“深度”类别级别?重构后,这个 67 个参数的函数的计算速度将提高 1000 倍。
    • 您的代码示例表明您在转换和评估方面都使用了过时的 JPMML 库。您绝对应该升级到 JPMML-SkLearn 1.2(.6) 和 JPMML-Evaluator 1.3(.4)。性能提升应该很明显,但很自然地不足以让 67'000 个参数的函数飞起来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    相关资源
    最近更新 更多