You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ch...@apache.org on 2019/02/11 11:53:41 UTC
[ignite] branch master updated: IGNITE-11244: [ML] Improve model
loading from directory instead full path to file with model
This is an automated email from the ASF dual-hosted git repository.
chief pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 816f435 IGNITE-11244: [ML] Improve model loading from directory instead full path to file with model
816f435 is described below
commit 816f435df98a7f407b07f37d2cb9d69ab8ed8941
Author: zaleslaw <za...@gmail.com>
AuthorDate: Mon Feb 11 14:53:18 2019 +0300
IGNITE-11244: [ML] Improve model loading from directory instead
full path to file with model
This closes #6065
---
.../modelparser/DecisionTreeFromSparkExample.java | 3 +-
.../DecisionTreeRegressionFromSparkExample.java | 3 +-
.../spark/modelparser/GBTFromSparkExample.java | 11 +-
.../modelparser/GBTRegressionFromSparkExample.java | 11 +-
.../spark/modelparser/KMeansFromSparkExample.java | 3 +-
.../LinearRegressionFromSparkExample.java | 3 +-
.../spark/modelparser/LogRegFromSparkExample.java | 3 +-
.../modelparser/RandomForestFromSparkExample.java | 3 +-
.../RandomForestRegressionFromSparkExample.java | 3 +-
.../spark/modelparser/SVMFromSparkExample.java | 3 +-
.../ml/sparkmodelparser/SparkModelParser.java | 148 ++++++++++----
.../IgniteMLSparkModelParserTestSuite.java | 30 +++
.../ml/sparkmodelparser/SparkModelParserTest.java | 218 +++++++++++++++++++++
.../test/resources/models/gbt/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc | Bin 0 -> 288 bytes
.../src/test/resources/models/gbt/data/_SUCCESS | 0
...6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet | Bin 0 -> 35369 bytes
.../resources/models/gbt/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../resources/models/gbt/metadata/.part-00000.crc | Bin 0 -> 16 bytes
.../test/resources/models/gbt/metadata/_SUCCESS | 0
.../test/resources/models/gbt/metadata/part-00000 | 1 +
.../models/gbt/treesMetadata/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4d24-9900-be8a4396710b-c000.snappy.parquet.crc | Bin 0 -> 36 bytes
.../resources/models/gbt/treesMetadata/_SUCCESS | 0
...e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet | Bin 0 -> 3370 bytes
.../resources/models/linreg/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc | Bin 0 -> 24 bytes
.../src/test/resources/models/linreg/data/_SUCCESS | 0
...6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet | Bin 0 -> 1570 bytes
.../resources/models/linreg/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../models/linreg/metadata/.part-00000.crc | Bin 0 -> 12 bytes
.../test/resources/models/linreg/metadata/_SUCCESS | 0
.../resources/models/linreg/metadata/part-00000 | 1 +
.../models/nodatafolder/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../models/nodatafolder/metadata/.part-00000.crc | Bin 0 -> 12 bytes
.../models/nodatafolder/metadata/_SUCCESS | 0
.../models/nodatafolder/metadata/part-00000 | 1 +
.../models/nometadatafilefolder/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc | Bin 0 -> 24 bytes
.../models/nometadatafilefolder/data/_SUCCESS | 0
...6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet | Bin 0 -> 1570 bytes
.../nometadatafilefolder/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../nometadatafilefolder/metadata/.part-00000.crc | Bin 0 -> 12 bytes
.../models/nometadatafilefolder/metadata/_SUCCESS | 0
.../models/nometadatafolder/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc | Bin 0 -> 24 bytes
.../models/nometadatafolder/data/_SUCCESS | 0
...6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet | Bin 0 -> 1570 bytes
.../models/nomodelfilefolder/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc | Bin 0 -> 24 bytes
.../models/nomodelfilefolder/data/_SUCCESS | 0
.../nomodelfilefolder/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../nomodelfilefolder/metadata/.part-00000.crc | Bin 0 -> 12 bytes
.../models/nomodelfilefolder/metadata/_SUCCESS | 0
.../models/nomodelfilefolder/metadata/part-00000 | 1 +
.../models/notreesmetadatafile/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc | Bin 0 -> 288 bytes
.../models/notreesmetadatafile/data/_SUCCESS | 0
...6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet | Bin 0 -> 35369 bytes
.../notreesmetadatafile/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../notreesmetadatafile/metadata/.part-00000.crc | Bin 0 -> 16 bytes
.../models/notreesmetadatafile/metadata/_SUCCESS | 0
.../models/notreesmetadatafile/metadata/part-00000 | 1 +
.../treesMetadata/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4d24-9900-be8a4396710b-c000.snappy.parquet.crc | Bin 0 -> 36 bytes
.../notreesmetadatafile/treesMetadata/_SUCCESS | 0
.../notreesmetadatafolder/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc | Bin 0 -> 288 bytes
.../models/notreesmetadatafolder/data/_SUCCESS | 0
...6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet | Bin 0 -> 35369 bytes
.../notreesmetadatafolder/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../notreesmetadatafolder/metadata/.part-00000.crc | Bin 0 -> 16 bytes
.../models/notreesmetadatafolder/metadata/_SUCCESS | 0
.../notreesmetadatafolder/metadata/part-00000 | 1 +
.../models/twomodelfilefolder/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc | Bin 0 -> 24 bytes
.../models/twomodelfilefolder/data/_SUCCESS | 0
...6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet | Bin 0 -> 1570 bytes
...6cdf-4ad3-bddd-7cad8378429d-c001.snappy.parquet | Bin 0 -> 1570 bytes
.../twomodelfilefolder/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../twomodelfilefolder/metadata/.part-00000.crc | Bin 0 -> 12 bytes
.../models/twomodelfilefolder/metadata/_SUCCESS | 0
.../models/twomodelfilefolder/metadata/part-00000 | 1 +
.../twotreesmetadatafiles/data/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc | Bin 0 -> 288 bytes
.../models/twotreesmetadatafiles/data/_SUCCESS | 0
...6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet | Bin 0 -> 35369 bytes
.../twotreesmetadatafiles/metadata/._SUCCESS.crc | Bin 0 -> 8 bytes
.../twotreesmetadatafiles/metadata/.part-00000.crc | Bin 0 -> 16 bytes
.../models/twotreesmetadatafiles/metadata/_SUCCESS | 0
.../twotreesmetadatafiles/metadata/part-00000 | 1 +
.../treesMetadata/._SUCCESS.crc | Bin 0 -> 8 bytes
...-4d24-9900-be8a4396710b-c000.snappy.parquet.crc | Bin 0 -> 36 bytes
.../twotreesmetadatafiles/treesMetadata/_SUCCESS | 0
...e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet | Bin 0 -> 3370 bytes
...e1e6-4d24-9900-be8a4396710b-c001.snappy.parquet | Bin 0 -> 3370 bytes
96 files changed, 385 insertions(+), 65 deletions(-)
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeFromSparkExample.java
index f220271..4e8a2d3 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeFromSparkExample.java
@@ -39,8 +39,7 @@ import org.apache.ignite.ml.tree.DecisionTreeNode;
*/
public class DecisionTreeFromSparkExample {
/** Path to Spark DT model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/dt/data" +
- "/part-00000-86bc0f70-df49-48b3-8356-9a26f9a6eb0f-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/dt";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeRegressionFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeRegressionFromSparkExample.java
index f09cc0c..0dbfd2a 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeRegressionFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/DecisionTreeRegressionFromSparkExample.java
@@ -40,8 +40,7 @@ import org.apache.ignite.ml.tree.DecisionTreeNode;
*/
public class DecisionTreeRegressionFromSparkExample {
/** Path to Spark Decision tree regression model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/dtreg/data" +
- "/part-00000-366f6ff2-698b-4bdd-8b1c-de87e11b3d1b-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/dtreg";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTFromSparkExample.java
index c62e839..b85129d 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTFromSparkExample.java
@@ -39,12 +39,7 @@ import org.apache.ignite.ml.sparkmodelparser.SupportedSparkModels;
*/
public class GBTFromSparkExample {
/** Path to Spark LogReg model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/gbt/data" +
- "/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet";
-
- /** Spark model metadata path. */
- private static final String SPARK_MDL_METADATA_PATH = "examples/src/main/resources/models/spark/serialized/gbt/treesMetadata" +
- "/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/gbt";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
@@ -67,8 +62,8 @@ public class GBTFromSparkExample {
IgniteBiFunction<Integer, Object[], Double> lbExtractor = (k, v) -> (double)v[1];
- ModelsComposition mdl = (ModelsComposition)SparkModelParser.parseWithMetadata(
- SPARK_MDL_PATH, SPARK_MDL_METADATA_PATH,
+ ModelsComposition mdl = (ModelsComposition)SparkModelParser.parse(
+ SPARK_MDL_PATH,
SupportedSparkModels.GRADIENT_BOOSTED_TREES
);
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTRegressionFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTRegressionFromSparkExample.java
index 4c2837c..d0b2548 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTRegressionFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/GBTRegressionFromSparkExample.java
@@ -40,12 +40,7 @@ import org.apache.ignite.ml.sparkmodelparser.SupportedSparkModels;
*/
public class GBTRegressionFromSparkExample {
/** Path to Spark GBT Regression model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/gbtreg/data" +
- "/part-00000-db4215b8-888b-4944-b933-7897869a29d3-c000.snappy.parquet";
-
- /** Spark model metadata path. */
- private static final String SPARK_MDL_METADATA_PATH = "examples/src/main/resources/models/spark/serialized/gbtreg/treesMetadata" +
- "/part-00000-999806a9-1326-48b3-bad7-07c343405928-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/gbtreg";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
@@ -68,8 +63,8 @@ public class GBTRegressionFromSparkExample {
IgniteBiFunction<Integer, Object[], Double> lbExtractor = (k, v) -> (double)v[4];
- ModelsComposition mdl = (ModelsComposition)SparkModelParser.parseWithMetadata(
- SPARK_MDL_PATH, SPARK_MDL_METADATA_PATH,
+ ModelsComposition mdl = (ModelsComposition)SparkModelParser.parse(
+ SPARK_MDL_PATH,
SupportedSparkModels.GRADIENT_BOOSTED_TREES_REGRESSION
);
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/KMeansFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/KMeansFromSparkExample.java
index 693c3d7..d76b158 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/KMeansFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/KMeansFromSparkExample.java
@@ -40,8 +40,7 @@ import org.apache.ignite.ml.sparkmodelparser.SupportedSparkModels;
*/
public class KMeansFromSparkExample {
/** Path to Spark KMeans model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/kmeans/data" +
- "/part-00000-e1f2c475-c65a-4b9e-879e-de4afd4f65bc-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/kmeans";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LinearRegressionFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LinearRegressionFromSparkExample.java
index 41aaa88..8902c72 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LinearRegressionFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LinearRegressionFromSparkExample.java
@@ -40,8 +40,7 @@ import org.apache.ignite.ml.sparkmodelparser.SupportedSparkModels;
*/
public class LinearRegressionFromSparkExample {
/** Path to Spark linear regression model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/linreg/data" +
- "/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/linreg";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LogRegFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LogRegFromSparkExample.java
index bd2f801..2a416da 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LogRegFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/LogRegFromSparkExample.java
@@ -39,8 +39,7 @@ import org.apache.ignite.ml.sparkmodelparser.SupportedSparkModels;
*/
public class LogRegFromSparkExample {
/** Path to Spark LogReg model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/logreg/data" +
- "/part-00000-7551081d-c0a8-4ed7-afe4-a464aabc7f80-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/logreg";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestFromSparkExample.java
index 07f2512..4c040b3 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestFromSparkExample.java
@@ -39,8 +39,7 @@ import org.apache.ignite.ml.sparkmodelparser.SupportedSparkModels;
*/
public class RandomForestFromSparkExample {
/** Path to Spark Random Forest model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/rf/data" +
- "/part-00000-290bdb9d-bc1b-411c-8811-c3205434f5fc-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/rf";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestRegressionFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestRegressionFromSparkExample.java
index 8c4a737..42c6699 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestRegressionFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/RandomForestRegressionFromSparkExample.java
@@ -40,8 +40,7 @@ import org.apache.ignite.ml.sparkmodelparser.SupportedSparkModels;
*/
public class RandomForestRegressionFromSparkExample {
/** Path to Spark Random Forest regression model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/rfreg/data" +
- "/part-00000-06273895-4b81-4a77-823e-dfd32d1560eb-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/rfreg";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/SVMFromSparkExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/SVMFromSparkExample.java
index 86aacf1..5ce177d 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/SVMFromSparkExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/inference/spark/modelparser/SVMFromSparkExample.java
@@ -39,8 +39,7 @@ import org.apache.ignite.ml.svm.SVMLinearClassificationModel;
*/
public class SVMFromSparkExample {
/** Path to Spark SVM model. */
- public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/svm/data" +
- "/part-00000-b3d800e2-a36c-4948-8e65-29c9f5c9c5b2-c000.snappy.parquet";
+ public static final String SPARK_MDL_PATH = "examples/src/main/resources/models/spark/serialized/svm";
/** Run example. */
public static void main(String[] args) throws FileNotFoundException {
diff --git a/modules/ml/spark-model-parser/src/main/java/org/apache/ignite/ml/sparkmodelparser/SparkModelParser.java b/modules/ml/spark-model-parser/src/main/java/org/apache/ignite/ml/sparkmodelparser/SparkModelParser.java
index db10814..82a86a8 100644
--- a/modules/ml/spark-model-parser/src/main/java/org/apache/ignite/ml/sparkmodelparser/SparkModelParser.java
+++ b/modules/ml/spark-model-parser/src/main/java/org/apache/ignite/ml/sparkmodelparser/SparkModelParser.java
@@ -20,6 +20,7 @@ package org.apache.ignite.ml.sparkmodelparser;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -63,13 +64,93 @@ import org.jetbrains.annotations.Nullable;
/** Parser of Spark models. */
public class SparkModelParser {
/**
+ * Load model from parquet (presented as a directory).
+ *
+ * @param pathToMdl Path to directory with saved model.
+ * @param parsedSparkMdl Parsed spark model.
+ */
+ public static Model parse(String pathToMdl, SupportedSparkModels parsedSparkMdl) throws IllegalArgumentException {
+ File mdlDir = IgniteUtils.resolveIgnitePath(pathToMdl);
+
+ if (mdlDir == null)
+ throw new IllegalArgumentException("Directory not found or empty [directory_path=" + pathToMdl + "]");
+
+ if (!mdlDir.isDirectory())
+ throw new IllegalArgumentException("Spark Model Parser supports loading from directory only. " +
+ "The specified path " + pathToMdl + " is not the path to directory.");
+
+ String[] files = mdlDir.list();
+ if (files.length == 0) throw new IllegalArgumentException("Directory contain 0 files and sub-directories [directory_path=" + pathToMdl + "]");
+
+ if (Arrays.stream(files).noneMatch("data"::equals))
+ throw new IllegalArgumentException("Directory should contain data sub-directory [directory_path=" + pathToMdl + "]");
+
+ if (Arrays.stream(files).noneMatch("metadata"::equals))
+ throw new IllegalArgumentException("Directory should contain metadata sub-directory [directory_path=" + pathToMdl + "]");
+
+ String pathToData = pathToMdl + File.separator + "data";
+ File dataDir = IgniteUtils.resolveIgnitePath(pathToData);
+
+ File[] dataParquetFiles = dataDir.listFiles((dir, name) -> name.matches("^part-.*\\.snappy\\.parquet$"));
+ if (dataParquetFiles.length == 0)
+ throw new IllegalArgumentException("Directory should contain parquet file " +
+ "with model [directory_path=" + pathToData + "]");
+
+ if (dataParquetFiles.length > 1)
+ throw new IllegalArgumentException("Directory should contain only one parquet file " +
+ "with model [directory_path=" + pathToData + "]");
+
+ String pathToMdlFile = dataParquetFiles[0].getPath();
+
+ String pathToMetadata = pathToMdl + File.separator + "metadata";
+ File metadataDir = IgniteUtils.resolveIgnitePath(pathToMetadata);
+ String[] metadataFiles = metadataDir.list();
+
+ if (Arrays.stream(metadataFiles).noneMatch("part-00000"::equals))
+ throw new IllegalArgumentException("Directory should contain json file with model metadata " +
+ "with name part-00000 [directory_path=" + pathToMetadata + "]");
+
+ if (shouldContainTreeMetadataSubDirectory(parsedSparkMdl)) {
+ if (Arrays.stream(files).noneMatch("treesMetadata"::equals))
+ throw new IllegalArgumentException("Directory should contain treeMetadata sub-directory [directory_path=" + pathToMdl + "]");
+
+ String pathToTreesMetadata = pathToMdl + File.separator + "treesMetadata";
+ File treesMetadataDir = IgniteUtils.resolveIgnitePath(pathToTreesMetadata);
+
+ File[] treesMetadataParquetFiles = treesMetadataDir.listFiles((dir, name) -> name.matches("^part-.*\\.snappy\\.parquet$"));
+ if (treesMetadataParquetFiles.length == 0)
+ throw new IllegalArgumentException("Directory should contain parquet file " +
+ "with model treesMetadata [directory_path=" + pathToTreesMetadata + "]");
+
+ if (treesMetadataParquetFiles.length > 1)
+ throw new IllegalArgumentException("Directory should contain only one parquet file " +
+ "with model [directory_path=" + pathToTreesMetadata + "]");
+
+ String pathToTreesMetadataFile = treesMetadataParquetFiles[0].getPath();
+
+ return parseDataWithMetadata(pathToMdlFile, pathToTreesMetadataFile, parsedSparkMdl);
+ } else
+ return parseData(pathToMdlFile, parsedSparkMdl);
+
+ }
+
+ /**
+ * @param parsedSparkMdl Parsed spark model.
+ */
+ private static boolean shouldContainTreeMetadataSubDirectory(SupportedSparkModels parsedSparkMdl) {
+ return parsedSparkMdl == SupportedSparkModels.GRADIENT_BOOSTED_TREES
+ || parsedSparkMdl == SupportedSparkModels.GRADIENT_BOOSTED_TREES_REGRESSION;
+ }
+
+
+ /**
* Load model from parquet file.
*
* @param pathToMdl Hadoop path to model saved from Spark.
* @param parsedSparkMdl One of supported Spark models to parse it.
* @return Instance of parsedSparkMdl model.
*/
- public static Model parse(String pathToMdl, SupportedSparkModels parsedSparkMdl) {
+ private static Model parseData(String pathToMdl, SupportedSparkModels parsedSparkMdl) {
File mdlRsrc = IgniteUtils.resolveIgnitePath(pathToMdl);
if (mdlRsrc == null)
throw new IllegalArgumentException("Resource not found [resource_path=" + pathToMdl + "]");
@@ -98,6 +179,39 @@ public class SparkModelParser {
}
}
+
+ /**
+ * Load model and its metadata from parquet files.
+ *
+ * @param pathToMdl Hadoop path to model saved from Spark.
+ * @param pathToMetaData Hadoop path to metadata saved from Spark.
+ * @param parsedSparkMdl One of supported Spark models to parse it.
+ * @return Instance of parsedSparkMdl model.
+ */
+ private static Model parseDataWithMetadata(String pathToMdl, String pathToMetaData,
+ SupportedSparkModels parsedSparkMdl) {
+ File mdlRsrc1 = IgniteUtils.resolveIgnitePath(pathToMdl);
+ if (mdlRsrc1 == null)
+ throw new IllegalArgumentException("Resource not found [resource_path=" + pathToMdl + "]");
+
+ String ignitePathToMdl = mdlRsrc1.getPath();
+
+ File mdlRsrc2 = IgniteUtils.resolveIgnitePath(pathToMetaData);
+ if (mdlRsrc2 == null)
+ throw new IllegalArgumentException("Resource not found [resource_path=" + pathToMetaData + "]");
+
+ String ignitePathToMdlMetaData = mdlRsrc2.getPath();
+
+ switch (parsedSparkMdl) {
+ case GRADIENT_BOOSTED_TREES:
+ return loadGBTClassifierModel(ignitePathToMdl, ignitePathToMdlMetaData);
+ case GRADIENT_BOOSTED_TREES_REGRESSION:
+ return loadGBTRegressionModel(ignitePathToMdl, ignitePathToMdlMetaData);
+ default:
+ throw new UnsupportedSparkModelException(ignitePathToMdl);
+ }
+ }
+
/**
* Load Random Forest Regression model.
*
@@ -164,38 +278,6 @@ public class SparkModelParser {
}
/**
- * Load model and its metadata from parquet files.
- *
- * @param pathToMdl Hadoop path to model saved from Spark.
- * @param pathToMetaData Hadoop path to metadata saved from Spark.
- * @param parsedSparkMdl One of supported Spark models to parse it.
- * @return Instance of parsedSparkMdl model.
- */
- public static Model parseWithMetadata(String pathToMdl, String pathToMetaData,
- SupportedSparkModels parsedSparkMdl) {
- File mdlRsrc1 = IgniteUtils.resolveIgnitePath(pathToMdl);
- if (mdlRsrc1 == null)
- throw new IllegalArgumentException("Resource not found [resource_path=" + pathToMdl + "]");
-
- String ignitePathToMdl = mdlRsrc1.getPath();
-
- File mdlRsrc2 = IgniteUtils.resolveIgnitePath(pathToMetaData);
- if (mdlRsrc2 == null)
- throw new IllegalArgumentException("Resource not found [resource_path=" + pathToMetaData + "]");
-
- String ignitePathToMdlMetaData = mdlRsrc2.getPath();
-
- switch (parsedSparkMdl) {
- case GRADIENT_BOOSTED_TREES:
- return loadGBTClassifierModel(ignitePathToMdl, ignitePathToMdlMetaData);
- case GRADIENT_BOOSTED_TREES_REGRESSION:
- return loadGBTRegressionModel(ignitePathToMdl, ignitePathToMdlMetaData);
- default:
- throw new UnsupportedSparkModelException(ignitePathToMdl);
- }
- }
-
- /**
* Load GDB Regression model.
*
* @param pathToMdl Path to model.
diff --git a/modules/ml/spark-model-parser/src/test/java/org/apache/ignite/ml/sparkmodelparser/IgniteMLSparkModelParserTestSuite.java b/modules/ml/spark-model-parser/src/test/java/org/apache/ignite/ml/sparkmodelparser/IgniteMLSparkModelParserTestSuite.java
new file mode 100644
index 0000000..5f715c3
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/java/org/apache/ignite/ml/sparkmodelparser/IgniteMLSparkModelParserTestSuite.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.sparkmodelparser;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/** Test suite for all module tests. */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ SparkModelParserTest.class
+})
+public class IgniteMLSparkModelParserTestSuite {
+ // No-op.
+}
diff --git a/modules/ml/spark-model-parser/src/test/java/org/apache/ignite/ml/sparkmodelparser/SparkModelParserTest.java b/modules/ml/spark-model-parser/src/test/java/org/apache/ignite/ml/sparkmodelparser/SparkModelParserTest.java
new file mode 100644
index 0000000..5bc3544
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/java/org/apache/ignite/ml/sparkmodelparser/SparkModelParserTest.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.sparkmodelparser;
+
+import java.io.File;
+import java.net.URL;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static junit.framework.TestCase.fail;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link SparkModelParser}.
+ */
+public class SparkModelParserTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ /** Path to empty directory. */
+ public static final String SPARK_MDL_PATH = "models";
+
+ /**
+ * Fails on null directory.
+ */
+ @Test
+ public void failOnNullDirectory() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ "incorrectPath", SupportedSparkModels.LINEAR_REGRESSION
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory not found or empty"));
+ }
+ }
+
+ /**
+ * Fails on empty directory.
+ */
+ @Test
+ public void failOnEmptyDirectory() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + "empty", SupportedSparkModels.LINEAR_REGRESSION
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory not found or empty"));
+ }
+ }
+
+ /**
+ * Fails on empty directory with empty subfolder.
+ */
+ @Test
+ public void failOnEmptyOrNonExistingDataDirectory() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "nodatafolder", SupportedSparkModels.LINEAR_REGRESSION
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain data sub-directory"));
+ }
+ }
+
+ /**
+ * Fails on empty directory with empty subfolder.
+ */
+ @Test
+ public void failOnEmptyOrNonExistingMetadataDirectory() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "nometadatafolder", SupportedSparkModels.LINEAR_REGRESSION
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain metadata sub-directory"));
+ }
+ }
+
+ /**
+ * Fails on non-existing model parquet file.
+ */
+ @Test
+ public void failOnNonExistingModelParquetFile() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "nomodelfilefolder", SupportedSparkModels.LINEAR_REGRESSION
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain parquet file"));
+ }
+ }
+
+ /**
+ * Fails on two existing model parquet file.
+ */
+ @Test
+ public void failOnTwoExistingModelParquetFile() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "twomodelfilefolder", SupportedSparkModels.LINEAR_REGRESSION
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain only one parquet file"));
+ }
+ }
+
+ /**
+ * Fails on two existing model parquet file.
+ */
+ @Test
+ public void failOnNonExistingMetadataFile() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "nometadatafilefolder", SupportedSparkModels.LINEAR_REGRESSION
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain json file with model metadata"));
+ }
+ }
+
+ /**
+ * Fails on non-existing treesMetadataFolder for GBT models.
+ */
+ @Test
+ public void failOnNonExistingTreeMetadataFolder() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "notreesmetadatafolder", SupportedSparkModels.GRADIENT_BOOSTED_TREES
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain treeMetadata sub-directory"));
+ }
+ }
+
+ /**
+ * Fails on non-existing treesMetadata parquet file for GBT models.
+ */
+ @Test
+ public void failOnNonExistingTreeMetadataFile() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "notreesmetadatafile", SupportedSparkModels.GRADIENT_BOOSTED_TREES
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain parquet file"));
+ }
+ }
+
+ /**
+ * Fails on two existing treesMetadata parquet file for GBT models.
+ */
+ @Test
+ public void failOnTwoExistingTreeMetadataFile() {
+ URL url = getClass().getClassLoader().getResource(SPARK_MDL_PATH);
+
+ try {
+ SparkModelParser.parse(
+ url.getPath() + File.separator + "twotreesmetadatafiles", SupportedSparkModels.GRADIENT_BOOSTED_TREES
+ );
+ fail("Expected IllegalArgumentException exception");
+ }
+ catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("Directory should contain only one parquet file"));
+ }
+ }
+}
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..ee329e9
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet
new file mode 100644
index 0000000..9fb2aa0
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/.part-00000.crc
new file mode 100644
index 0000000..b30ab3d
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/part-00000
new file mode 100644
index 0000000..097b5d9
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/gbt/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.classification.GBTClassificationModel","timestamp":1548233686134,"sparkVersion":"2.2.0","uid":"gbtc_bc5b0cce5380","paramMap":{"maxDepth":7,"impurity":"gini","subsamplingRate":1.0,"maxMemoryInMB":256,"seed":-1287390502,"cacheNodeIds":false,"labelCol":"survived","maxIter":10,"minInstancesPerNode":1,"predictionCol":"prediction","stepSize":0.1,"probabilityCol":"probability","featuresCol":"features","lossType":"logistic","rawPredictionCol":"rawPrediction","maxBin [...]
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc
new file mode 100644
index 0000000..1f162ed
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet
new file mode 100644
index 0000000..35e68c5
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/gbt/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..933dc33
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet
new file mode 100644
index 0000000..df367c6
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/linreg/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/.part-00000.crc
new file mode 100644
index 0000000..2560e39
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/part-00000
new file mode 100644
index 0000000..93c10ee
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/linreg/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.regression.LinearRegressionModel","timestamp":1548077038088,"sparkVersion":"2.2.0","uid":"linReg_e029f9195938","paramMap":{"solver":"auto","standardization":true,"aggregationDepth":2,"fitIntercept":true,"elasticNetParam":0.1,"tol":1.0E-6,"maxIter":100,"labelCol":"age","predictionCol":"prediction","featuresCol":"features","regParam":0.1}}
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/.part-00000.crc
new file mode 100644
index 0000000..2560e39
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/part-00000
new file mode 100644
index 0000000..93c10ee
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/nodatafolder/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.regression.LinearRegressionModel","timestamp":1548077038088,"sparkVersion":"2.2.0","uid":"linReg_e029f9195938","paramMap":{"solver":"auto","standardization":true,"aggregationDepth":2,"fitIntercept":true,"elasticNetParam":0.1,"tol":1.0E-6,"maxIter":100,"labelCol":"age","predictionCol":"prediction","featuresCol":"features","regParam":0.1}}
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..933dc33
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet
new file mode 100644
index 0000000..df367c6
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/.part-00000.crc
new file mode 100644
index 0000000..2560e39
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafilefolder/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..933dc33
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet
new file mode 100644
index 0000000..df367c6
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nometadatafolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..933dc33
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/.part-00000.crc
new file mode 100644
index 0000000..2560e39
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/part-00000
new file mode 100644
index 0000000..93c10ee
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/nomodelfilefolder/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.regression.LinearRegressionModel","timestamp":1548077038088,"sparkVersion":"2.2.0","uid":"linReg_e029f9195938","paramMap":{"solver":"auto","standardization":true,"aggregationDepth":2,"fitIntercept":true,"elasticNetParam":0.1,"tol":1.0E-6,"maxIter":100,"labelCol":"age","predictionCol":"prediction","featuresCol":"features","regParam":0.1}}
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..ee329e9
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet
new file mode 100644
index 0000000..9fb2aa0
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/.part-00000.crc
new file mode 100644
index 0000000..b30ab3d
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/part-00000
new file mode 100644
index 0000000..097b5d9
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.classification.GBTClassificationModel","timestamp":1548233686134,"sparkVersion":"2.2.0","uid":"gbtc_bc5b0cce5380","paramMap":{"maxDepth":7,"impurity":"gini","subsamplingRate":1.0,"maxMemoryInMB":256,"seed":-1287390502,"cacheNodeIds":false,"labelCol":"survived","maxIter":10,"minInstancesPerNode":1,"predictionCol":"prediction","stepSize":0.1,"probabilityCol":"probability","featuresCol":"features","lossType":"logistic","rawPredictionCol":"rawPrediction","maxBin [...]
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc
new file mode 100644
index 0000000..1f162ed
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafile/treesMetadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..ee329e9
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet
new file mode 100644
index 0000000..9fb2aa0
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/.part-00000.crc
new file mode 100644
index 0000000..b30ab3d
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/part-00000
new file mode 100644
index 0000000..097b5d9
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/notreesmetadatafolder/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.classification.GBTClassificationModel","timestamp":1548233686134,"sparkVersion":"2.2.0","uid":"gbtc_bc5b0cce5380","paramMap":{"maxDepth":7,"impurity":"gini","subsamplingRate":1.0,"maxMemoryInMB":256,"seed":-1287390502,"cacheNodeIds":false,"labelCol":"survived","maxIter":10,"minInstancesPerNode":1,"predictionCol":"prediction","stepSize":0.1,"probabilityCol":"probability","featuresCol":"features","lossType":"logistic","rawPredictionCol":"rawPrediction","maxBin [...]
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..933dc33
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/.part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet
new file mode 100644
index 0000000..df367c6
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c001.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c001.snappy.parquet
new file mode 100644
index 0000000..df367c6
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/data/part-00000-1ff2d09d-6cdf-4ad3-bddd-7cad8378429d-c001.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/.part-00000.crc
new file mode 100644
index 0000000..2560e39
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/part-00000
new file mode 100644
index 0000000..93c10ee
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/twomodelfilefolder/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.regression.LinearRegressionModel","timestamp":1548077038088,"sparkVersion":"2.2.0","uid":"linReg_e029f9195938","paramMap":{"solver":"auto","standardization":true,"aggregationDepth":2,"fitIntercept":true,"elasticNetParam":0.1,"tol":1.0E-6,"maxIter":100,"labelCol":"age","predictionCol":"prediction","featuresCol":"features","regParam":0.1}}
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc
new file mode 100644
index 0000000..ee329e9
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/.part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet
new file mode 100644
index 0000000..9fb2aa0
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/data/part-00000-ea23dcda-6344-4b1f-9716-fbedf7caba2d-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/.part-00000.crc b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/.part-00000.crc
new file mode 100644
index 0000000..b30ab3d
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/.part-00000.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/part-00000 b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/part-00000
new file mode 100644
index 0000000..097b5d9
--- /dev/null
+++ b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/metadata/part-00000
@@ -0,0 +1 @@
+{"class":"org.apache.spark.ml.classification.GBTClassificationModel","timestamp":1548233686134,"sparkVersion":"2.2.0","uid":"gbtc_bc5b0cce5380","paramMap":{"maxDepth":7,"impurity":"gini","subsamplingRate":1.0,"maxMemoryInMB":256,"seed":-1287390502,"cacheNodeIds":false,"labelCol":"survived","maxIter":10,"minInstancesPerNode":1,"predictionCol":"prediction","stepSize":0.1,"probabilityCol":"probability","featuresCol":"features","lossType":"logistic","rawPredictionCol":"rawPrediction","maxBin [...]
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/._SUCCESS.crc b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/._SUCCESS.crc
new file mode 100644
index 0000000..3b7b044
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/._SUCCESS.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc
new file mode 100644
index 0000000..1f162ed
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/.part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet.crc differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/_SUCCESS b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/_SUCCESS
new file mode 100644
index 0000000..e69de29
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet
new file mode 100644
index 0000000..35e68c5
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c000.snappy.parquet differ
diff --git a/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c001.snappy.parquet b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c001.snappy.parquet
new file mode 100644
index 0000000..35e68c5
Binary files /dev/null and b/modules/ml/spark-model-parser/src/test/resources/models/twotreesmetadatafiles/treesMetadata/part-00000-9033203a-e1e6-4d24-9900-be8a4396710b-c001.snappy.parquet differ