美文网首页
sklearn2pmml安装使用

sklearn2pmml安装使用

作者: 曦宝 | 来源:发表于2018-09-21 11:51 被阅读231次

我们的公司代码是Java,但是做算法部分用的是python的sklearn库,因此考虑用sklearn2pmml出一个pmml文件,文件里保存的是模型文件的详情,再交给Java用,实现跨平台使用,下面是使用跑通的方法:

1.在网站下载文件

https://pypi.org/project/sklearn2pmml/#files

image.png
我这里下载的是最新版的。(20180921)

2.下载的是一个压缩包,任意指定一个文件夹将文件解压缩。

image.png

解压后文件内容(360解压就可以了)

3.安装sklearn2pmml

1.在cmd里,切换到之前解压缩的目录里(setup.py文件所在的位置)
2.在命令行输入
python setup.py build
python setup.py install


image.png

多了一个build文件夹

4.查看是否安装成功

image.png

如上图,引入sklearn2pmml库不提示错误了,运行一下看看


image.png

上面是训练模型的代码,这里使用了最简单的参数,仅指定了pmml文件的路径。


image.png
运行报错,缺少sklearn_pandas 库。

5.安装sklearn_pandas库

https://pypi.org/project/sklearn-pandas/

image.png
安装这个.whl文件,其实安装在哪里都可以,但是为了方便找,一般都安装在Scripts文件夹下
image.png
我使用的是anaconda,如果没有使用anaconda就安装在python的script文件夹下。
在cmd里,cd到该文件夹下,输入命令:pip install sklearn_pandas-1.7.0-py2.py3-none-any.whl
这个比较简单,出现successed证明成功安装。

6.python输入测试代码

image.png
运行报错
image.png
下载java端的jar包,jpmml-sklearn-executable
https://github.com/jpmml/jpmml-sklearn/releases
image.png

7.先保存成sklearn模型的自带格式

image.png

修改程序加两句话


image.png

生成了自带格式的模型
在将自带格式的模型文件转换成pmml文件

8.将pkl文件转换成pmml文件

在CMD中输入下面的命令


image.png

出现下面的场景证明转换成功。


image.png

9.这个pmml文件只支持java8,不支持java7,因此要先在电脑上安装java8

https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

image.png
上图显示出了依赖包,以及java8版本,下面是java代码
package javaTopython;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
 
import org.dmg.pmml.FieldName;
import org.dmg.pmml.PMML;
import org.jpmml.evaluator.Evaluator;
import org.jpmml.evaluator.FieldValue;
import org.jpmml.evaluator.InputField;
import org.jpmml.evaluator.ModelEvaluator;
import org.jpmml.evaluator.ModelEvaluatorFactory;
import org.jpmml.evaluator.TargetField;

public class PmmlFile {
    public static void main(String[] args) throws Exception {
        String  pathxml="D:\\pmml-model\\demo.pmml";
        Map<String, Double>  map=new HashMap<String, Double>();
        map.put("sepal_length", 5.1);
        map.put("sepal_width", 3.5);
        map.put("petal_length", 1.4);
        map.put("petal_width", 0.2);    
        predictLrHeart(map, pathxml);
    }
    
    public static void predictLrHeart(Map<String, Double> irismap,String  pathxml)throws Exception {
 
        PMML pmml;
        // 模型导入
        File file = new File(pathxml);
        InputStream inputStream = new FileInputStream(file);
        try (InputStream is = inputStream) {
            pmml = org.jpmml.model.PMMLUtil.unmarshal(is);
 
            ModelEvaluatorFactory modelEvaluatorFactory = ModelEvaluatorFactory
                    .newInstance();
            ModelEvaluator<?> modelEvaluator = modelEvaluatorFactory
                    .newModelEvaluator(pmml);
            Evaluator evaluator = (Evaluator) modelEvaluator;
 
            List<InputField> inputFields = evaluator.getInputFields();
            // 过模型的原始特征,从画像中获取数据,作为模型输入
            Map<FieldName, FieldValue> arguments = new LinkedHashMap<>();
            for (InputField inputField : inputFields) {
                FieldName inputFieldName = inputField.getName();
                Object rawValue = irismap
                        .get(inputFieldName.getValue());
                FieldValue inputFieldValue = inputField.prepare(rawValue);
                arguments.put(inputFieldName, inputFieldValue);
            }
 
            Map<FieldName, ?> results = evaluator.evaluate(arguments);
            List<TargetField> targetFields = evaluator.getTargetFields();
            //对于分类问题等有多个输出。
            for (TargetField targetField : targetFields) {
                FieldName targetFieldName = targetField.getName();
                Object targetFieldValue = results.get(targetFieldName);
                System.err.println("target: " + targetFieldName.getValue()
                        + " value: " + targetFieldValue);
            }
        }
    }
}

给出一组feature值


image.png

可以看出他的label值,应该是0,但是我的运行结果


image.png
不知道问题出现在哪里,回头我再检查一下是否是模型的问题。

10.首先从源头开始检查

所谓的源头就是python代码和生成的模型文件。

1,首先在网上百度了python端的代码,越简单出错的可能性越小

发现其实python端的代码都比较简单,主要有两种形式,上面已经展示了一种,就是含有feature_name的,下面我用的这种更加简单,是不含有feature_name的,但其实本质上并没有差别,是一样的,随便挑一种都可以。

from sklearn2pmml import PMMLPipeline
from sklearn.datasets import load_iris
from sklearn import tree
from sklearn.externals import joblib
from sklearn.linear_model import LogisticRegression

iris = load_iris()
clf = LogisticRegression()
pipeline = PMMLPipeline([("classifier", clf)])
pipeline.fit(iris.data, iris.target)

joblib.dump(pipeline, "pipeline.pkl", compress=9)

因为是跑通代码的demo,所以算法为默认参数,没有进行调参等处理。可以看到上面引用了tree,是因为一开始我在网上搜到的代码,别人用的是决策树。
这里提到是因为我踩了一个坑,对于零基础第一次做的人来说,可能并不容易察觉。
当我检查转换成的pmml文件的时候,发现


image.png

下图中的
DataField name,只有x1,x3,x4,并没有x2,也就是说生成的模型文件其实是不正确的。
因为python端的代码选择了最简单的代码,不可能出错,本着算法工作者的直觉,考虑换成了较为“安全”的逻辑回归。
再次生成模型文件,转换文件格式,发现模型文件正确了。

2,注意算法和参数的选择对模型正确性的影响

更正:这里出现了错误

其实出现特征缺失是因为这项特征前面的系数为0,所以模型文件做了简化处理,并不影响结果。我后来又用手写数字识别的数据做了实现,发现不论如何更换算法,x1,x40,x41这几个特征总是缺失,于是意识到了,这与算法无关,只不过是特征前面的系数为0。模型文件可以处理这样的缺失,类似于libsvm类型的数据一样,缺失值当做0处理,因此在java端赋值的时候可以正常赋值,并不影响正确结果

赋值
结果

以上是我在理解上的错误,更正一下,至于上次出错的原因,猜测是因为决策树算法有一些不可或缺的参数,我没有赋值导致的结果总是null,跟算法的选择无关。

特此更正

11.java端的代码

网上java端的代码也有两种版本,经过尝试,上面给出的版本是可以跑通的,另一种在我这里不能用,不知道什么原因,因为在python代码中没有调用feature_name,所以在仅需在上面的java代码中将主函数的map.put()传参数的部分的key值做一下修改就可以了。


image.png

运行结果

target: y value: ProbabilityDistribution{result=2, probability_entries=[0=1.6171914035182245E-4, 1=0.427941843129312, 2=0.5718964377303362]}
image.png

运行结果中,target:y因为没有给target也就是label命名,因此默认y。后面value给出的是概率分布,result给出的是可能性最大的分类。后面是每一个类别的概率。

因为水平不行,所以就这么一个简单的东西折腾了好久。不知道这么做的人是不是比较少,网上的资料搜来搜去就那么几个,而且都是python部分和Java部分分开的。我这里算是一个小总结,省的自己将来再踩坑。

相关文章

网友评论

      本文标题:sklearn2pmml安装使用

      本文链接:https://www.haomeiwen.com/subject/bilanftx.html