tutorial java python jython scikit-learn

tutorial - ¿Cómo puedo llamar clasificadores scikit-learn desde Java?



processing tutorial (5)

Aquí hay algo de código para la solución JPMML:

--Parte de piña--

# helper function to determine the string columns which have to be one-hot-encoded in order to apply an estimator. def determine_categorical_columns(df): categorical_columns = [] x = 0 for col in df.dtypes: if col == ''object'': val = df[df.columns[x]].iloc[0] if not isinstance(val,Decimal): categorical_columns.append(df.columns[x]) x += 1 return categorical_columns categorical_columns = determine_categorical_columns(df) other_columns = list(set(df.columns).difference(categorical_columns)) #construction of transformators for our example labelBinarizers = [(d, LabelBinarizer()) for d in categorical_columns] nones = [(d, None) for d in other_columns] transformators = labelBinarizers+nones mapper = DataFrameMapper(transformators,df_out=True) gbc = GradientBoostingClassifier() #construction of the pipeline lm = PMMLPipeline([ ("mapper", mapper), ("estimator", gbc) ])

--JAVA PART -

//Initialisation. String pmmlFile = "ScikitLearnNew.pmml"; PMML pmml = org.jpmml.model.PMMLUtil.unmarshal(new FileInputStream(pmmlFile)); ModelEvaluatorFactory modelEvaluatorFactory = ModelEvaluatorFactory.newInstance(); MiningModelEvaluator evaluator = (MiningModelEvaluator) modelEvaluatorFactory.newModelEvaluator(pmml); //Determine which features are required as input HashMap<String, Field>() inputFieldMap = new HashMap<String, Field>(); for (int i = 0; i < evaluator.getInputFields().size();i++) { InputField curInputField = evaluator.getInputFields().get(i); String fieldName = curInputField.getName().getValue(); inputFieldMap.put(fieldName.toLowerCase(),curInputField.getField()); } //prediction HashMap<String,String> argsMap = new HashMap<String,String>(); //... fill argsMap with input Map<FieldName, ?> res; // here we keep only features that are required by the model Map<FieldName,String> args = new HashMap<FieldName, String>(); Iterator<String> iter = argsMap.keySet().iterator(); while (iter.hasNext()) { String key = iter.next(); Field f = inputFieldMap.get(key); if (f != null) { FieldName name =f.getName(); String value = argsMap.get(key); args.put(name, value); } } //the model is applied to input, a probability distribution is obtained res = evaluator.evaluate(args); SegmentResult segmentResult = (SegmentResult) res; Object targetValue = segmentResult.getTargetValue(); ProbabilityDistribution probabilityDistribution = (ProbabilityDistribution) targetValue;

Tengo un clasificador que entrené usando Python scikit-learn. ¿Cómo puedo usar el clasificador de un programa Java? ¿Puedo usar Jython? ¿Hay alguna manera de guardar el clasificador en Python y cargarlo en Java? ¿Hay alguna otra manera de usarlo?


Hay JPMML proyecto JPMML para este propósito.

Primero, puede serializar el modelo scikit-learn a PMML (que es XML internamente) usando la biblioteca sklearn2pmml directamente desde python o sklearn2pmml en python primero y convertir usando jpmml-sklearn en java o desde una línea de comando proporcionada por esta biblioteca. A continuación, puede cargar el archivo pmml, deserializar y ejecutar el modelo cargado utilizando jpmml-evaluator en su código Java.

De esta manera no funciona con todos los modelos de scikit-learn, sino con many de ellos.


Me encontré en una situación similar. Recomiendo tallar un microservicio clasificador. Podría tener un microservicio clasificador que se ejecute en Python y luego exponga las llamadas a ese servicio a través de alguna API RESTFul que produzca el formato de intercambio de datos JSON / XML. Creo que este es un enfoque más limpio.


No se puede usar jython, ya que scikit-learn se basa en gran medida en numpy y scipy que tienen muchas extensiones compiladas de C y Fortran, por lo que no pueden funcionar en jython.

Las formas más fáciles de usar scikit-learn en un entorno java serían:

  • exponga el clasificador como un servicio HTTP / Json, por ejemplo, utilizando un microframo como un flask o bottle o cornice y llámelo desde java utilizando una biblioteca de cliente HTTP

  • escriba una aplicación de envoltorio de línea de comandos en python que lea datos en stdin y produzca predicciones en stdout usando algún formato como CSV o JSON (o alguna representación binaria de nivel inferior) y llame al programa python desde java, por ejemplo, utilizando Apache Commons Exec .

  • haga que el programa python produzca los parámetros numéricos sin procesar aprendidos en el momento del ajuste (típicamente como una matriz de valores de punto flotante) y vuelva a implementar la función de predicción en java (esto es típicamente fácil para los modelos lineales predictivos donde la predicción es a menudo solo un producto puntual con umbral) .

El último enfoque será mucho más trabajo si también necesita volver a implementar la extracción de características en Java.

Finalmente, puede usar una biblioteca de Java como Weka o Mahout que implementa los algoritmos que necesita en lugar de intentar usar scikit-learn desde Java.


Puede utilizar un cargador, he probado el sklearn-porter ( https://github.com/nok/sklearn-porter ) y funciona bien para Java.

Mi código es el siguiente:

import pandas as pd from sklearn import tree from sklearn_porter import Porter train_dataset = pd.read_csv(''./result2.csv'').as_matrix() X_train = train_dataset[:90, :8] Y_train = train_dataset[:90, 8:] X_test = train_dataset[90:, :8] Y_test = train_dataset[90:, 8:] print X_train.shape print Y_train.shape clf = tree.DecisionTreeClassifier() clf = clf.fit(X_train, Y_train) porter = Porter(clf, language=''java'') output = porter.export(embed_data=True) print(output)

En mi caso, estoy usando un DecisionTreeClassifier, y la salida de

imprimir (salida)

Es el siguiente código como texto en la consola:

class DecisionTreeClassifier { private static int findMax(int[] nums) { int index = 0; for (int i = 0; i < nums.length; i++) { index = nums[i] > nums[index] ? i : index; } return index; } public static int predict(double[] features) { int[] classes = new int[2]; if (features[5] <= 51.5) { if (features[6] <= 21.0) { // HUGE amount of ifs.......... } } return findMax(classes); } public static void main(String[] args) { if (args.length == 8) { // Features: double[] features = new double[args.length]; for (int i = 0, l = args.length; i < l; i++) { features[i] = Double.parseDouble(args[i]); } // Prediction: int prediction = DecisionTreeClassifier.predict(features); System.out.println(prediction); } } }