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 2017/12/11 16:02:20 UTC

[1/2] ignite git commit: IGNITE-6880: KNN(k nearest neighbor) algorithm

Repository: ignite
Updated Branches:
  refs/heads/master e3d70a824 -> 8ba773bfe


http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/IgniteMLTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/IgniteMLTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/IgniteMLTestSuite.java
index 7a61bad..05c91bd 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/IgniteMLTestSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/IgniteMLTestSuite.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.ml;
 
 import org.apache.ignite.ml.clustering.ClusteringTestSuite;
+import org.apache.ignite.ml.knn.KNNTestSuite;
 import org.apache.ignite.ml.math.MathImplMainTestSuite;
 import org.apache.ignite.ml.regressions.RegressionsTestSuite;
 import org.apache.ignite.ml.trees.DecisionTreesTestSuite;
@@ -33,6 +34,7 @@ import org.junit.runners.Suite;
     RegressionsTestSuite.class,
     ClusteringTestSuite.class,
     DecisionTreesTestSuite.class,
+    KNNTestSuite.class,
     LocalModelsTest.class
 })
 public class IgniteMLTestSuite {

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/LocalModelsTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/LocalModelsTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/LocalModelsTest.java
index d0d1247..37dec77 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/LocalModelsTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/LocalModelsTest.java
@@ -23,11 +23,15 @@ import java.nio.file.Path;
 import java.util.function.Function;
 import org.apache.ignite.ml.clustering.KMeansLocalClusterer;
 import org.apache.ignite.ml.clustering.KMeansModel;
-import org.apache.ignite.ml.math.EuclideanDistance;
+import org.apache.ignite.ml.knn.models.KNNModel;
+import org.apache.ignite.ml.knn.models.KNNModelFormat;
+import org.apache.ignite.ml.knn.models.KNNStrategy;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
 import org.apache.ignite.ml.regressions.OLSMultipleLinearRegressionModel;
 import org.apache.ignite.ml.regressions.OLSMultipleLinearRegressionModelFormat;
 import org.apache.ignite.ml.regressions.OLSMultipleLinearRegressionTrainer;
+import org.apache.ignite.ml.structures.LabeledDataset;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -126,4 +130,37 @@ public class LocalModelsTest {
 
         return trainer.train(data);
     }
+
+    /** */
+    @Test
+    public void importExportKNNModelTest() throws IOException {
+        executeModelTest(mdlFilePath -> {
+            double[][] mtx =
+                new double[][] {
+                    {1.0, 1.0},
+                    {1.0, 2.0},
+                    {2.0, 1.0},
+                    {-1.0, -1.0},
+                    {-1.0, -2.0},
+                    {-2.0, -1.0}};
+            double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+
+            LabeledDataset training = new LabeledDataset(mtx, lbs);
+
+            KNNModel mdl = new KNNModel(3, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+
+            Exporter<KNNModelFormat, String> exporter = new FileExporter<>();
+            mdl.saveModel(exporter, mdlFilePath);
+
+            KNNModelFormat load = exporter.load(mdlFilePath);
+
+            Assert.assertNotNull(load);
+
+            KNNModel importedMdl = new KNNModel(load.getK(), load.getDistanceMeasure(), load.getStgy(), load.getTraining());
+
+            Assert.assertTrue("", mdl.equals(importedMdl));
+
+            return null;
+        });
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClustererTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClustererTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClustererTest.java
index 0cfa7b8..0aa8f83 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClustererTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClustererTest.java
@@ -22,10 +22,10 @@ import java.util.Comparator;
 import java.util.Random;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.ml.math.DistanceMeasure;
-import org.apache.ignite.ml.math.EuclideanDistance;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClustererTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClustererTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClustererTest.java
index c58ffc7..2af94aa 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClustererTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClustererTest.java
@@ -21,10 +21,10 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
-import org.apache.ignite.ml.math.DistanceMeasure;
-import org.apache.ignite.ml.math.EuclideanDistance;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
 import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestMultiNode.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestMultiNode.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestMultiNode.java
index 1f71dee..71be8be 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestMultiNode.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestMultiNode.java
@@ -27,9 +27,9 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.ml.math.EuclideanDistance;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestSingleNode.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestSingleNode.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestSingleNode.java
index 19c328a..705db7a 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestSingleNode.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTestSingleNode.java
@@ -30,11 +30,11 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.ml.math.DistanceMeasure;
-import org.apache.ignite.ml.math.EuclideanDistance;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.VectorUtils;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.functions.Functions;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansLocalClustererTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansLocalClustererTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansLocalClustererTest.java
index b396f5b..cd9b2ed 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansLocalClustererTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansLocalClustererTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.ml.clustering;
 
-import org.apache.ignite.ml.math.EuclideanDistance;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
 import org.junit.Assert;
 import org.junit.Test;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/knn/BaseKNNTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/BaseKNNTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/BaseKNNTest.java
new file mode 100644
index 0000000..9075978
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/BaseKNNTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.knn;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.ml.structures.LabeledDataset;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Base class for decision trees test.
+ */
+public class BaseKNNTest extends GridCommonAbstractTest {
+    /** Count of nodes. */
+    private static final int NODE_COUNT = 4;
+
+    /** Separator. */
+    private static final String SEPARATOR = "\t";
+
+    /** Path to the Iris dataset. */
+    static final String KNN_IRIS_TXT = "datasets/knn/iris.txt";
+
+    /** Grid instance. */
+    protected Ignite ignite;
+
+    /**
+     * Default constructor.
+     */
+    public BaseKNNTest() {
+        super(false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override protected void beforeTest() throws Exception {
+        ignite = grid(NODE_COUNT);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        for (int i = 1; i <= NODE_COUNT; i++)
+            startGrid(i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * Loads labeled dataset from file with .txt extension.
+     *
+     * @param rsrcPath path to dataset.
+     * @return null if path is incorrect.
+     */
+    LabeledDataset loadDatasetFromTxt(String rsrcPath, boolean isFallOnBadData) {
+        try {
+            Path path = Paths.get(this.getClass().getClassLoader().getResource(rsrcPath).toURI());
+            try {
+                return LabeledDataset.loadTxt(path, SEPARATOR, false, isFallOnBadData);
+            }
+            catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        catch (URISyntaxException e) {
+            e.printStackTrace();
+            return null;
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java
new file mode 100644
index 0000000..e010553
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNClassificationTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.knn;
+
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.knn.models.KNNModel;
+import org.apache.ignite.ml.knn.models.KNNStrategy;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
+import org.apache.ignite.ml.math.exceptions.knn.SmallTrainingDatasetSizeException;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.structures.LabeledDataset;
+
+/** Tests behaviour of KNNClassificationTest. */
+public class KNNClassificationTest extends BaseKNNTest {
+    /** */
+    public void testBinaryClassificationTest() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {1.0, 1.0},
+                {1.0, 2.0},
+                {2.0, 1.0},
+                {-1.0, -1.0},
+                {-1.0, -2.0},
+                {-2.0, -1.0}};
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+
+        LabeledDataset training = new LabeledDataset(mtx, lbs);
+
+        KNNModel knnMdl = new KNNModel(3, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+        Vector firstVector = new DenseLocalOnHeapVector(new double[] {2.0, 2.0});
+        assertEquals(knnMdl.predict(firstVector), 1.0);
+        Vector secondVector = new DenseLocalOnHeapVector(new double[] {-2.0, -2.0});
+        assertEquals(knnMdl.predict(secondVector), 2.0);
+    }
+
+    /** */
+    public void testBinaryClassificationWithSmallestKTest() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {1.0, 1.0},
+                {1.0, 2.0},
+                {2.0, 1.0},
+                {-1.0, -1.0},
+                {-1.0, -2.0},
+                {-2.0, -1.0}};
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+
+        LabeledDataset training = new LabeledDataset(mtx, lbs);
+
+        KNNModel knnMdl = new KNNModel(1, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+        Vector firstVector = new DenseLocalOnHeapVector(new double[] {2.0, 2.0});
+        assertEquals(knnMdl.predict(firstVector), 1.0);
+        Vector secondVector = new DenseLocalOnHeapVector(new double[] {-2.0, -2.0});
+        assertEquals(knnMdl.predict(secondVector), 2.0);
+    }
+
+    /** */
+    public void testBinaryClassificationFarPointsWithSimpleStrategy() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {10.0, 10.0},
+                {10.0, 20.0},
+                {-1, -1},
+                {-2, -2},
+                {-1.0, -2.0},
+                {-2.0, -1.0}};
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+        LabeledDataset training = new LabeledDataset(mtx, lbs);
+
+        KNNModel knnMdl = new KNNModel(3, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+        Vector vector = new DenseLocalOnHeapVector(new double[] {-1.01, -1.01});
+        assertEquals(knnMdl.predict(vector), 2.0);
+    }
+
+    /** */
+    public void testBinaryClassificationFarPointsWithWeightedStrategy() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {10.0, 10.0},
+                {10.0, 20.0},
+                {-1, -1},
+                {-2, -2},
+                {-1.0, -2.0},
+                {-2.0, -1.0}
+            };
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+        LabeledDataset training = new LabeledDataset(mtx, lbs);
+
+        KNNModel knnMdl = new KNNModel(3, new EuclideanDistance(), KNNStrategy.WEIGHTED, training);
+        Vector vector = new DenseLocalOnHeapVector(new double[] {-1.01, -1.01});
+        assertEquals(knnMdl.predict(vector), 1.0);
+    }
+
+    /** */
+    public void testPredictOnIrisDataset() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        LabeledDataset training = loadDatasetFromTxt(KNN_IRIS_TXT, false);
+
+        KNNModel knnMdl = new KNNModel(7, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+        Vector vector = new DenseLocalOnHeapVector(new double[] {5.15, 3.55, 1.45, 0.25});
+        assertEquals(knnMdl.predict(vector), 1.0);
+    }
+
+    /** */
+    public void testLargeKValue() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {10.0, 10.0},
+                {10.0, 20.0},
+                {-1, -1},
+                {-2, -2},
+                {-1.0, -2.0},
+                {-2.0, -1.0}
+            };
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+        LabeledDataset training = new LabeledDataset(mtx, lbs);
+
+        try {
+            new KNNModel(7, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+            fail("SmallTrainingDatasetSizeException");
+        }
+        catch (SmallTrainingDatasetSizeException e) {
+            return;
+        }
+        fail("SmallTrainingDatasetSizeException");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNMultipleLinearRegressionTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNMultipleLinearRegressionTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNMultipleLinearRegressionTest.java
new file mode 100644
index 0000000..9a918b6
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNMultipleLinearRegressionTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.knn;
+
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.knn.models.KNNStrategy;
+import org.apache.ignite.ml.knn.models.Normalization;
+import org.apache.ignite.ml.knn.regression.KNNMultipleLinearRegression;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+import org.apache.ignite.ml.structures.LabeledDataset;
+import org.junit.Assert;
+
+/**
+ * Tests for {@link KNNMultipleLinearRegression}.
+ */
+public class KNNMultipleLinearRegressionTest extends BaseKNNTest {
+    /** */
+    private double[] y;
+
+    /** */
+    private double[][] x;
+
+    /** */
+    public void testSimpleRegressionWithOneNeighbour() {
+
+        y = new double[] {11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
+        x = new double[6][];
+        x[0] = new double[] {0, 0, 0, 0, 0};
+        x[1] = new double[] {2.0, 0, 0, 0, 0};
+        x[2] = new double[] {0, 3.0, 0, 0, 0};
+        x[3] = new double[] {0, 0, 4.0, 0, 0};
+        x[4] = new double[] {0, 0, 0, 5.0, 0};
+        x[5] = new double[] {0, 0, 0, 0, 6.0};
+
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        LabeledDataset training = new LabeledDataset(x, y);
+
+        KNNMultipleLinearRegression knnMdl = new KNNMultipleLinearRegression(1, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+        Vector vector = new SparseBlockDistributedVector(new double[] {0, 0, 0, 5.0, 0.0});
+        System.out.println(knnMdl.predict(vector));
+        Assert.assertEquals(15, knnMdl.predict(vector), 1E-12);
+    }
+
+    /** */
+    public void testLongly() {
+
+        y = new double[] {60323, 61122, 60171, 61187, 63221, 63639, 64989, 63761, 66019, 68169, 66513, 68655, 69564, 69331, 70551};
+        x = new double[15][];
+        x[0] = new double[] {83.0, 234289, 2356, 1590, 107608, 1947};
+        x[1] = new double[] {88.5, 259426, 2325, 1456, 108632, 1948};
+        x[2] = new double[] {88.2, 258054, 3682, 1616, 109773, 1949};
+        x[3] = new double[] {89.5, 284599, 3351, 1650, 110929, 1950};
+        x[4] = new double[] {96.2, 328975, 2099, 3099, 112075, 1951};
+        x[5] = new double[] {98.1, 346999, 1932, 3594, 113270, 1952};
+        x[6] = new double[] {99.0, 365385, 1870, 3547, 115094, 1953};
+        x[7] = new double[] {100.0, 363112, 3578, 3350, 116219, 1954};
+        x[8] = new double[] {101.2, 397469, 2904, 3048, 117388, 1955};
+        x[9] = new double[] {108.4, 442769, 2936, 2798, 120445, 1957};
+        x[10] = new double[] {110.8, 444546, 4681, 2637, 121950, 1958};
+        x[11] = new double[] {112.6, 482704, 3813, 2552, 123366, 1959};
+        x[12] = new double[] {114.2, 502601, 3931, 2514, 125368, 1960};
+        x[13] = new double[] {115.7, 518173, 4806, 2572, 127852, 1961};
+        x[14] = new double[] {116.9, 554894, 4007, 2827, 130081, 1962};
+
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        LabeledDataset training = new LabeledDataset(x, y);
+
+        KNNMultipleLinearRegression knnMdl = new KNNMultipleLinearRegression(3, new EuclideanDistance(), KNNStrategy.SIMPLE, training);
+        Vector vector = new DenseLocalOnHeapVector(new double[] {104.6, 419180, 2822, 2857, 118734, 1956});
+        System.out.println(knnMdl.predict(vector));
+        Assert.assertEquals(67857, knnMdl.predict(vector), 2000);
+    }
+
+    /** */
+    public void testLonglyWithNormalization() {
+        y = new double[] {60323, 61122, 60171, 61187, 63221, 63639, 64989, 63761, 66019, 68169, 66513, 68655, 69564, 69331, 70551};
+        x = new double[15][];
+        x[0] = new double[] {83.0, 234289, 2356, 1590, 107608, 1947};
+        x[1] = new double[] {88.5, 259426, 2325, 1456, 108632, 1948};
+        x[2] = new double[] {88.2, 258054, 3682, 1616, 109773, 1949};
+        x[3] = new double[] {89.5, 284599, 3351, 1650, 110929, 1950};
+        x[4] = new double[] {96.2, 328975, 2099, 3099, 112075, 1951};
+        x[5] = new double[] {98.1, 346999, 1932, 3594, 113270, 1952};
+        x[6] = new double[] {99.0, 365385, 1870, 3547, 115094, 1953};
+        x[7] = new double[] {100.0, 363112, 3578, 3350, 116219, 1954};
+        x[8] = new double[] {101.2, 397469, 2904, 3048, 117388, 1955};
+        x[9] = new double[] {108.4, 442769, 2936, 2798, 120445, 1957};
+        x[10] = new double[] {110.8, 444546, 4681, 2637, 121950, 1958};
+        x[11] = new double[] {112.6, 482704, 3813, 2552, 123366, 1959};
+        x[12] = new double[] {114.2, 502601, 3931, 2514, 125368, 1960};
+        x[13] = new double[] {115.7, 518173, 4806, 2572, 127852, 1961};
+        x[14] = new double[] {116.9, 554894, 4007, 2827, 130081, 1962};
+
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        LabeledDataset training = new LabeledDataset(x, y);
+
+        final LabeledDataset normalizedTrainingDataset = training.normalizeWith(Normalization.MINIMAX);
+
+        KNNMultipleLinearRegression knnMdl = new KNNMultipleLinearRegression(5, new EuclideanDistance(), KNNStrategy.SIMPLE, normalizedTrainingDataset);
+        Vector vector = new DenseLocalOnHeapVector(new double[] {104.6, 419180, 2822, 2857, 118734, 1956});
+        System.out.println(knnMdl.predict(vector));
+        Assert.assertEquals(67857, knnMdl.predict(vector), 2000);
+    }
+
+    /** */
+    public void testLonglyWithWeightedStrategyAndNormalization() {
+        y = new double[] {60323, 61122, 60171, 61187, 63221, 63639, 64989, 63761, 66019, 68169, 66513, 68655, 69564, 69331, 70551};
+        x = new double[15][];
+        x[0] = new double[] {83.0, 234289, 2356, 1590, 107608, 1947};
+        x[1] = new double[] {88.5, 259426, 2325, 1456, 108632, 1948};
+        x[2] = new double[] {88.2, 258054, 3682, 1616, 109773, 1949};
+        x[3] = new double[] {89.5, 284599, 3351, 1650, 110929, 1950};
+        x[4] = new double[] {96.2, 328975, 2099, 3099, 112075, 1951};
+        x[5] = new double[] {98.1, 346999, 1932, 3594, 113270, 1952};
+        x[6] = new double[] {99.0, 365385, 1870, 3547, 115094, 1953};
+        x[7] = new double[] {100.0, 363112, 3578, 3350, 116219, 1954};
+        x[8] = new double[] {101.2, 397469, 2904, 3048, 117388, 1955};
+        x[9] = new double[] {108.4, 442769, 2936, 2798, 120445, 1957};
+        x[10] = new double[] {110.8, 444546, 4681, 2637, 121950, 1958};
+        x[11] = new double[] {112.6, 482704, 3813, 2552, 123366, 1959};
+        x[12] = new double[] {114.2, 502601, 3931, 2514, 125368, 1960};
+        x[13] = new double[] {115.7, 518173, 4806, 2572, 127852, 1961};
+        x[14] = new double[] {116.9, 554894, 4007, 2827, 130081, 1962};
+
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        LabeledDataset training = new LabeledDataset(x, y);
+
+        final LabeledDataset normalizedTrainingDataset = training.normalizeWith(Normalization.MINIMAX);
+
+        KNNMultipleLinearRegression knnMdl = new KNNMultipleLinearRegression(5, new EuclideanDistance(), KNNStrategy.WEIGHTED, normalizedTrainingDataset);
+        Vector vector = new DenseLocalOnHeapVector(new double[] {104.6, 419180, 2822, 2857, 118734, 1956});
+        System.out.println(knnMdl.predict(vector));
+        Assert.assertEquals(67857, knnMdl.predict(vector), 2000);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNTestSuite.java
new file mode 100644
index 0000000..8b47e0a
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/KNNTestSuite.java
@@ -0,0 +1,33 @@
+/*
+ * 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.knn;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Test suite for all tests located in org.apache.ignite.ml.trees package.
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    KNNClassificationTest.class,
+    KNNMultipleLinearRegressionTest.class,
+    LabeledDatasetTest.class
+})
+public class KNNTestSuite {
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledDatasetTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledDatasetTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledDatasetTest.java
new file mode 100644
index 0000000..32bd37b
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/knn/LabeledDatasetTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.knn;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.exceptions.NoDataException;
+import org.apache.ignite.ml.math.exceptions.knn.EmptyFileException;
+import org.apache.ignite.ml.math.exceptions.knn.FileParsingException;
+import org.apache.ignite.ml.structures.LabeledDataset;
+import org.apache.ignite.ml.structures.LabeledVector;
+
+/** Tests behaviour of KNNClassificationTest. */
+public class LabeledDatasetTest extends BaseKNNTest {
+    /** */
+    private static final String KNN_IRIS_TXT = "datasets/knn/iris.txt";
+
+    /** */
+    private static final String NO_DATA_TXT = "datasets/knn/no_data.txt";
+
+    /** */
+    private static final String EMPTY_TXT = "datasets/knn/empty.txt";
+
+    /** */
+    private static final String IRIS_INCORRECT_TXT = "datasets/knn/iris_incorrect.txt";
+
+    /** */
+    private static final String IRIS_MISSED_DATA = "datasets/knn/missed_data.txt";
+
+
+    /** */
+    public void testFeatureNames() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {1.0, 1.0},
+                {1.0, 2.0},
+                {2.0, 1.0},
+                {-1.0, -1.0},
+                {-1.0, -2.0},
+                {-2.0, -1.0}};
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+
+        String[] featureNames = new String[] {"x", "y"};
+        final LabeledDataset dataset = new LabeledDataset(mtx, lbs, featureNames, false);
+
+        assertEquals(dataset.getFeatureName(0), "x");
+    }
+
+    /** */
+    public void testAccessMethods() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {1.0, 1.0},
+                {1.0, 2.0},
+                {2.0, 1.0},
+                {-1.0, -1.0},
+                {-1.0, -2.0},
+                {-2.0, -1.0}};
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+
+        final LabeledDataset dataset = new LabeledDataset(mtx, lbs, null, false);
+
+        assertEquals(dataset.colSize(), 2);
+        assertEquals(dataset.rowSize(), 6);
+
+        final LabeledVector<Vector, Double> row = dataset.getRow(0);
+
+        assertEquals(row.features().get(0), 1.0);
+        assertEquals(row.label(), 1.0);
+        dataset.setLabel(0, 2.0);
+        assertEquals(row.label(), 2.0);
+    }
+
+    /** */
+    public void testFailOnYNull() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {
+                {1.0, 1.0},
+                {1.0, 2.0},
+                {2.0, 1.0},
+                {-1.0, -1.0},
+                {-1.0, -2.0},
+                {-2.0, -1.0}};
+        double[] lbs = new double[] {};
+
+        try {
+            new LabeledDataset(mtx, lbs);
+            fail("CardinalityException");
+        }
+        catch (CardinalityException e) {
+            return;
+        }
+        fail("CardinalityException");
+    }
+
+    /** */
+    public void testFailOnXNull() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[][] mtx =
+            new double[][] {};
+        double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+
+        try {
+            new LabeledDataset(mtx, lbs);
+            fail("CardinalityException");
+        }
+        catch (CardinalityException e) {
+            return;
+        }
+        fail("CardinalityException");
+    }
+
+    /** */
+    public void testLoadingCorrectTxtFile() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        LabeledDataset training = loadDatasetFromTxt(KNN_IRIS_TXT, false);
+        assertEquals(training.rowSize(), 150);
+    }
+
+    /** */
+    public void testLoadingEmptyFile() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        try {
+            loadDatasetFromTxt(EMPTY_TXT, false);
+            fail("EmptyFileException");
+        }
+        catch (EmptyFileException e) {
+            return;
+        }
+        fail("EmptyFileException");
+    }
+
+    /** */
+    public void testLoadingFileWithFirstEmptyRow() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        try {
+            loadDatasetFromTxt(NO_DATA_TXT, false);
+            fail("NoDataException");
+        }
+        catch (NoDataException e) {
+            return;
+        }
+        fail("NoDataException");
+    }
+
+    /** */
+    public void testLoadingFileWithIncorrectData() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        LabeledDataset training = loadDatasetFromTxt(IRIS_INCORRECT_TXT, false);
+        assertEquals(149, training.rowSize());
+    }
+
+    /** */
+    public void testFailOnLoadingFileWithIncorrectData() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        try {
+            loadDatasetFromTxt(IRIS_INCORRECT_TXT, true);
+            fail("FileParsingException");
+        }
+        catch (FileParsingException e) {
+            return;
+        }
+        fail("FileParsingException");
+
+    }
+
+    /** */
+    public void testLoadingFileWithMissedData() throws URISyntaxException, IOException {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        Path path = Paths.get(this.getClass().getClassLoader().getResource(IRIS_MISSED_DATA).toURI());
+
+        LabeledDataset training = LabeledDataset.loadTxt(path, ",", false, false);
+
+        assertEquals(training.features(2).get(1), 0.0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java
index af2154e..bb41239 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java
@@ -23,6 +23,7 @@ import org.apache.ignite.ml.math.decompositions.LUDecompositionTest;
 import org.apache.ignite.ml.math.decompositions.QRDSolverTest;
 import org.apache.ignite.ml.math.decompositions.QRDecompositionTest;
 import org.apache.ignite.ml.math.decompositions.SingularValueDecompositionTest;
+import org.apache.ignite.ml.math.distances.DistanceTest;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOffHeapMatrixConstructorTest;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrixConstructorTest;
 import org.apache.ignite.ml.math.impls.matrix.DiagonalMatrixTest;
@@ -117,8 +118,9 @@ import org.junit.runners.Suite;
     EigenDecompositionTest.class,
     CholeskyDecompositionTest.class,
     QRDecompositionTest.class,
+    SingularValueDecompositionTest.class,
     QRDSolverTest.class,
-    SingularValueDecompositionTest.class
+    DistanceTest.class
 })
 public class MathImplLocalTestSuite {
     // No-op.

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/math/distances/DistanceTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/distances/DistanceTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/distances/DistanceTest.java
new file mode 100644
index 0000000..022b86a
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/distances/DistanceTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.math.distances;
+
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/** */
+public class DistanceTest {
+    /** Precision. */
+    private static final double PRECISION = 0.0;
+
+    /** */
+    private Vector v1;
+
+    /** */
+    private Vector v2;
+
+    /** */
+    @Before
+    public void setup() {
+        v1 = new DenseLocalOnHeapVector(new double[] {0.0, 0.0, 0.0});
+        v2 = new DenseLocalOnHeapVector(new double[] {2.0, 1.0, 0.0});
+    }
+
+    /** */
+    @Test
+    public void euclideanDistance() throws Exception {
+
+        double expRes = Math.pow(5, 0.5);
+
+        DistanceMeasure distanceMeasure = new EuclideanDistance();
+
+        Assert.assertEquals(expRes, distanceMeasure.compute(v1, v2), PRECISION);
+    }
+
+    /** */
+    @Test
+    public void manhattanDistance() throws Exception {
+        double expRes = 3;
+
+        DistanceMeasure distanceMeasure = new ManhattanDistance();
+
+        Assert.assertEquals(expRes, distanceMeasure.compute(v1, v2), PRECISION);
+    }
+
+    /** */
+    @Test
+    public void hammingDistance() throws Exception {
+        double expRes = 2;
+
+        DistanceMeasure distanceMeasure = new HammingDistance();
+
+        Assert.assertEquals(expRes, distanceMeasure.compute(v1, v2), PRECISION);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
index 4be7336..2774028 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
@@ -418,6 +418,7 @@ public class OLSMultipleLinearRegressionTest extends AbstractMultipleLinearRegre
 
         Matrix hat = mdl.calculateHat();
 
+
         // Reference data is upper half of symmetric hat matrix
         double[] refData = new double[] {
             .418, -.002, .079, -.274, -.046, .181, .128, .222, .050, .242,

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/trees/ColumnDecisionTreeTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/trees/ColumnDecisionTreeTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/trees/ColumnDecisionTreeTrainerTest.java
index 929ded9..9e81bea 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/trees/ColumnDecisionTreeTrainerTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/trees/ColumnDecisionTreeTrainerTest.java
@@ -183,9 +183,9 @@ public class ColumnDecisionTreeTrainerTest extends BaseDecisionTreeTest {
 
         byRegion.keySet().forEach(k -> {
             LabeledVectorDouble sp = byRegion.get(k).get(0);
-            Tracer.showAscii(sp.vector());
-            X.println("Actual and predicted vectors [act=" + sp.label() + " " + ", pred=" + mdl.predict(sp.vector()) + "]");
-            assert mdl.predict(sp.vector()) == sp.doubleLabel();
+            Tracer.showAscii(sp.features());
+            X.println("Actual and predicted vectors [act=" + sp.label() + " " + ", pred=" + mdl.predict(sp.features()) + "]");
+            assert mdl.predict(sp.features()) == sp.doubleLabel();
         });
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/java/org/apache/ignite/ml/trees/performance/ColumnDecisionTreeTrainerBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/trees/performance/ColumnDecisionTreeTrainerBenchmark.java b/modules/ml/src/test/java/org/apache/ignite/ml/trees/performance/ColumnDecisionTreeTrainerBenchmark.java
index 7ca5d38..524a8ad 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/trees/performance/ColumnDecisionTreeTrainerBenchmark.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/trees/performance/ColumnDecisionTreeTrainerBenchmark.java
@@ -273,9 +273,9 @@ public class ColumnDecisionTreeTrainerBenchmark extends BaseDecisionTreeTest {
 
         byRegion.keySet().forEach(k -> {
             LabeledVectorDouble sp = byRegion.get(k).get(0);
-            Tracer.showAscii(sp.vector());
-            X.println("Predicted value and label [pred=" + mdl.predict(sp.vector()) + ", label=" + sp.doubleLabel() + "]");
-            assert mdl.predict(sp.vector()) == sp.doubleLabel();
+            Tracer.showAscii(sp.features());
+            X.println("Predicted value and label [pred=" + mdl.predict(sp.features()) + ", label=" + sp.doubleLabel() + "]");
+            assert mdl.predict(sp.features()) == sp.doubleLabel();
         });
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/README.md
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/README.md b/modules/ml/src/test/resources/datasets/README.md
new file mode 100644
index 0000000..2f9c5ec
--- /dev/null
+++ b/modules/ml/src/test/resources/datasets/README.md
@@ -0,0 +1,2 @@
+iris.txt and cleared_machines are from Lichman, M. (2013). UCI Machine Learning Repository [http://archive.ics.uci.edu/ml]. Irvine, CA: University of California, School of Information and Computer Science.
+Read more about machine dataset http://archive.ics.uci.edu/ml/machine-learning-databases/cpu-performance/machine.names
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/knn/cleared_machines.txt
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/knn/cleared_machines.txt b/modules/ml/src/test/resources/datasets/knn/cleared_machines.txt
new file mode 100644
index 0000000..cf8b6b0
--- /dev/null
+++ b/modules/ml/src/test/resources/datasets/knn/cleared_machines.txt
@@ -0,0 +1,209 @@
+199,125,256,6000,256,16,128
+253,29,8000,32000,32,8,32
+253,29,8000,32000,32,8,32
+253,29,8000,32000,32,8,32
+132,29,8000,16000,32,8,16
+290,26,8000,32000,64,8,32
+381,23,16000,32000,64,16,32
+381,23,16000,32000,64,16,32
+749,23,16000,64000,64,16,32
+1238,23,32000,64000,128,32,64
+23,400,1000,3000,0,1,2
+24,400,512,3500,4,1,6
+70,60,2000,8000,65,1,8
+117,50,4000,16000,65,1,8
+15,350,64,64,0,1,4
+64,200,512,16000,0,4,32
+23,167,524,2000,8,4,15
+29,143,512,5000,0,7,32
+22,143,1000,2000,0,5,16
+124,110,5000,5000,142,8,64
+35,143,1500,6300,0,5,32
+39,143,3100,6200,0,5,20
+40,143,2300,6200,0,6,64
+45,110,3100,6200,0,6,64
+28,320,128,6000,0,1,12
+21,320,512,2000,4,1,3
+28,320,256,6000,0,1,6
+22,320,256,3000,4,1,3
+28,320,512,5000,4,1,5
+27,320,256,5000,4,1,6
+102,25,1310,2620,131,12,24
+102,25,1310,2620,131,12,24
+74,50,2620,10480,30,12,24
+74,50,2620,10480,30,12,24
+138,56,5240,20970,30,12,24
+136,64,5240,20970,30,12,24
+23,50,500,2000,8,1,4
+29,50,1000,4000,8,1,5
+44,50,2000,8000,8,1,5
+30,50,1000,4000,8,3,5
+41,50,1000,8000,8,3,5
+74,50,2000,16000,8,3,5
+74,50,2000,16000,8,3,6
+74,50,2000,16000,8,3,6
+54,133,1000,12000,9,3,12
+41,133,1000,8000,9,3,12
+18,810,512,512,8,1,1
+28,810,1000,5000,0,1,1
+36,320,512,8000,4,1,5
+38,200,512,8000,8,1,8
+34,700,384,8000,0,1,1
+19,700,256,2000,0,1,1
+72,140,1000,16000,16,1,3
+36,200,1000,8000,0,1,2
+30,110,1000,4000,16,1,2
+56,110,1000,12000,16,1,2
+42,220,1000,8000,16,1,2
+34,800,256,8000,0,1,4
+34,800,256,8000,0,1,4
+34,800,256,8000,0,1,4
+34,800,256,8000,0,1,4
+34,800,256,8000,0,1,4
+19,125,512,1000,0,8,20
+75,75,2000,8000,64,1,38
+113,75,2000,16000,64,1,38
+157,75,2000,16000,128,1,38
+18,90,256,1000,0,3,10
+20,105,256,2000,0,3,10
+28,105,1000,4000,0,3,24
+33,105,2000,4000,8,3,19
+47,75,2000,8000,8,3,24
+54,75,3000,8000,8,3,48
+20,175,256,2000,0,3,24
+23,300,768,3000,0,6,24
+25,300,768,3000,6,6,24
+52,300,768,12000,6,6,24
+27,300,768,4500,0,1,24
+50,300,384,12000,6,1,24
+18,300,192,768,6,6,24
+53,180,768,12000,6,1,31
+23,330,1000,3000,0,2,4
+30,300,1000,4000,8,3,64
+73,300,1000,16000,8,2,112
+20,330,1000,2000,0,1,2
+25,330,1000,4000,0,3,6
+28,140,2000,4000,0,3,6
+29,140,2000,4000,0,4,8
+32,140,2000,4000,8,1,20
+175,140,2000,32000,32,1,20
+57,140,2000,8000,32,1,54
+181,140,2000,32000,32,1,54
+181,140,2000,32000,32,1,54
+32,140,2000,4000,8,1,20
+82,57,4000,16000,1,6,12
+171,57,4000,24000,64,12,16
+361,26,16000,32000,64,16,24
+350,26,16000,32000,64,8,24
+220,26,8000,32000,0,8,24
+113,26,8000,16000,0,8,16
+15,480,96,512,0,1,1
+21,203,1000,2000,0,1,5
+35,115,512,6000,16,1,6
+18,1100,512,1500,0,1,1
+20,1100,768,2000,0,1,1
+20,600,768,2000,0,1,1
+28,400,2000,4000,0,1,1
+45,400,4000,8000,0,1,1
+18,900,1000,1000,0,1,2
+17,900,512,1000,0,1,2
+26,900,1000,4000,4,1,2
+28,900,1000,4000,8,1,2
+28,900,2000,4000,0,3,6
+31,225,2000,4000,8,3,6
+31,225,2000,4000,8,3,6
+42,180,2000,8000,8,1,6
+76,185,2000,16000,16,1,6
+76,180,2000,16000,16,1,6
+26,225,1000,4000,2,3,6
+59,25,2000,12000,8,1,4
+65,25,2000,12000,16,3,5
+101,17,4000,16000,8,6,12
+116,17,4000,16000,32,6,12
+18,1500,768,1000,0,0,0
+20,1500,768,2000,0,0,0
+20,800,768,2000,0,0,0
+30,50,2000,4000,0,3,6
+44,50,2000,8000,8,3,6
+44,50,2000,8000,8,1,6
+82,50,2000,16000,24,1,6
+82,50,2000,16000,24,1,6
+128,50,8000,16000,48,1,10
+37,100,1000,8000,0,2,6
+46,100,1000,8000,24,2,6
+46,100,1000,8000,24,3,6
+80,50,2000,16000,12,3,16
+88,50,2000,16000,24,6,16
+88,50,2000,16000,24,6,16
+33,150,512,4000,0,8,128
+46,115,2000,8000,16,1,3
+29,115,2000,4000,2,1,5
+53,92,2000,8000,32,1,6
+53,92,2000,8000,32,1,6
+41,92,2000,8000,4,1,6
+86,75,4000,16000,16,1,6
+95,60,4000,16000,32,1,6
+107,60,2000,16000,64,5,8
+117,60,4000,16000,64,5,8
+119,50,4000,16000,64,5,10
+120,72,4000,16000,64,8,16
+48,72,2000,8000,16,6,8
+126,40,8000,16000,32,8,16
+266,40,8000,32000,64,8,24
+270,35,8000,32000,64,8,24
+426,38,16000,32000,128,16,32
+151,48,4000,24000,32,8,24
+267,38,8000,32000,64,8,24
+603,30,16000,32000,256,16,24
+19,112,1000,1000,0,1,4
+21,84,1000,2000,0,1,6
+26,56,1000,4000,0,1,6
+35,56,2000,6000,0,1,8
+41,56,2000,8000,0,1,8
+47,56,4000,8000,0,1,8
+62,56,4000,12000,0,1,8
+78,56,4000,16000,0,1,8
+80,38,4000,8000,32,16,32
+80,38,4000,8000,32,16,32
+142,38,8000,16000,64,4,8
+281,38,8000,24000,160,4,8
+190,38,4000,16000,128,16,32
+21,200,1000,2000,0,1,2
+25,200,1000,4000,0,1,4
+67,200,2000,8000,64,1,5
+24,250,512,4000,0,1,7
+24,250,512,4000,0,4,7
+64,250,1000,16000,1,1,8
+25,160,512,4000,2,1,5
+20,160,512,2000,2,3,8
+29,160,1000,4000,8,1,14
+43,160,1000,8000,16,1,14
+53,160,2000,8000,32,1,13
+19,240,512,1000,8,1,3
+22,240,512,2000,8,1,5
+31,105,2000,4000,8,3,8
+41,105,2000,6000,16,6,16
+47,105,2000,8000,16,4,14
+99,52,4000,16000,32,4,12
+67,70,4000,12000,8,6,8
+81,59,4000,12000,32,6,12
+149,59,8000,16000,64,12,24
+183,26,8000,24000,32,8,16
+275,26,8000,32000,64,12,16
+382,26,8000,32000,128,24,32
+56,116,2000,8000,32,5,28
+182,50,2000,32000,24,6,26
+227,50,2000,32000,48,26,52
+341,50,2000,32000,112,52,104
+360,50,4000,32000,112,52,104
+919,30,8000,64000,96,12,176
+978,30,8000,64000,128,12,176
+24,180,262,4000,0,1,3
+24,180,512,4000,0,1,3
+24,180,262,4000,0,1,3
+24,180,512,4000,0,1,3
+37,124,1000,8000,0,1,8
+50,98,1000,8000,32,2,8
+41,125,2000,8000,0,2,14
+47,480,512,8000,32,0,0
+25,480,1000,4000,0,0,0

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/knn/empty.txt
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/knn/empty.txt b/modules/ml/src/test/resources/datasets/knn/empty.txt
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/knn/iris.txt
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/knn/iris.txt b/modules/ml/src/test/resources/datasets/knn/iris.txt
new file mode 100644
index 0000000..18f5f7c
--- /dev/null
+++ b/modules/ml/src/test/resources/datasets/knn/iris.txt
@@ -0,0 +1,150 @@
+1.0	5.1	3.5	1.4	0.2
+1.0	4.9	3.0	1.4	0.2
+1.0	4.7	3.2	1.3	0.2
+1.0	4.6	3.1	1.5	0.2
+1.0	5.0	3.6	1.4	0.2
+1.0	5.4	3.9	1.7	0.4
+1.0	4.6	3.4	1.4	0.3
+1.0	5.0	3.4	1.5	0.2
+1.0	4.4	2.9	1.4	0.2
+1.0	4.9	3.1	1.5	0.1
+1.0	5.4	3.7	1.5	0.2
+1.0	4.8	3.4	1.6	0.2
+1.0	4.8	3.0	1.4	0.1
+1.0	4.3	3.0	1.1	0.1
+1.0	5.8	4.0	1.2	0.2
+1.0	5.7	4.4	1.5	0.4
+1.0	5.4	3.9	1.3	0.4
+1.0	5.1	3.5	1.4	0.3
+1.0	5.7	3.8	1.7	0.3
+1.0	5.1	3.8	1.5	0.3
+1.0	5.4	3.4	1.7	0.2
+1.0	5.1	3.7	1.5	0.4
+1.0	4.6	3.6	1.0	0.2
+1.0	5.1	3.3	1.7	0.5
+1.0	4.8	3.4	1.9	0.2
+1.0	5.0	3.0	1.6	0.2
+1.0	5.0	3.4	1.6	0.4
+1.0	5.2	3.5	1.5	0.2
+1.0	5.2	3.4	1.4	0.2
+1.0	4.7	3.2	1.6	0.2
+1.0	4.8	3.1	1.6	0.2
+1.0	5.4	3.4	1.5	0.4
+1.0	5.2	4.1	1.5	0.1
+1.0	5.5	4.2	1.4	0.2
+1.0	4.9	3.1	1.5	0.1
+1.0	5.0	3.2	1.2	0.2
+1.0	5.5	3.5	1.3	0.2
+1.0	4.9	3.1	1.5	0.1
+1.0	4.4	3.0	1.3	0.2
+1.0	5.1	3.4	1.5	0.2
+1.0	5.0	3.5	1.3	0.3
+1.0	4.5	2.3	1.3	0.3
+1.0	4.4	3.2	1.3	0.2
+1.0	5.0	3.5	1.6	0.6
+1.0	5.1	3.8	1.9	0.4
+1.0	4.8	3.0	1.4	0.3
+1.0	5.1	3.8	1.6	0.2
+1.0	4.6	3.2	1.4	0.2
+1.0	5.3	3.7	1.5	0.2
+1.0	5.0	3.3	1.4	0.2
+2.0	7.0	3.2	4.7	1.4
+2.0	6.4	3.2	4.5	1.5
+2.0	6.9	3.1	4.9	1.5
+2.0	5.5	2.3	4.0	1.3
+2.0	6.5	2.8	4.6	1.5
+2.0	5.7	2.8	4.5	1.3
+2.0	6.3	3.3	4.7	1.6
+2.0	4.9	2.4	3.3	1.0
+2.0	6.6	2.9	4.6	1.3
+2.0	5.2	2.7	3.9	1.4
+2.0	5.0	2.0	3.5	1.0
+2.0	5.9	3.0	4.2	1.5
+2.0	6.0	2.2	4.0	1.0
+2.0	6.1	2.9	4.7	1.4
+2.0	5.6	2.9	3.6	1.3
+2.0	6.7	3.1	4.4	1.4
+2.0	5.6	3.0	4.5	1.5
+2.0	5.8	2.7	4.1	1.0
+2.0	6.2	2.2	4.5	1.5
+2.0	5.6	2.5	3.9	1.1
+2.0	5.9	3.2	4.8	1.8
+2.0	6.1	2.8	4.0	1.3
+2.0	6.3	2.5	4.9	1.5
+2.0	6.1	2.8	4.7	1.2
+2.0	6.4	2.9	4.3	1.3
+2.0	6.6	3.0	4.4	1.4
+2.0	6.8	2.8	4.8	1.4
+2.0	6.7	3.0	5.0	1.7
+2.0	6.0	2.9	4.5	1.5
+2.0	5.7	2.6	3.5	1.0
+2.0	5.5	2.4	3.8	1.1
+2.0	5.5	2.4	3.7	1.0
+2.0	5.8	2.7	3.9	1.2
+2.0	6.0	2.7	5.1	1.6
+2.0	5.4	3.0	4.5	1.5
+2.0	6.0	3.4	4.5	1.6
+2.0	6.7	3.1	4.7	1.5
+2.0	6.3	2.3	4.4	1.3
+2.0	5.6	3.0	4.1	1.3
+2.0	5.5	2.5	4.0	1.3
+2.0	5.5	2.6	4.4	1.2
+2.0	6.1	3.0	4.6	1.4
+2.0	5.8	2.6	4.0	1.2
+2.0	5.0	2.3	3.3	1.0
+2.0	5.6	2.7	4.2	1.3
+2.0	5.7	3.0	4.2	1.2
+2.0	5.7	2.9	4.2	1.3
+2.0	6.2	2.9	4.3	1.3
+2.0	5.1	2.5	3.0	1.1
+2.0	5.7	2.8	4.1	1.3
+3.0	6.3	3.3	6.0	2.5
+3.0	5.8	2.7	5.1	1.9
+3.0	7.1	3.0	5.9	2.1
+3.0	6.3	2.9	5.6	1.8
+3.0	6.5	3.0	5.8	2.2
+3.0	7.6	3.0	6.6	2.1
+3.0	4.9	2.5	4.5	1.7
+3.0	7.3	2.9	6.3	1.8
+3.0	6.7	2.5	5.8	1.8
+3.0	7.2	3.6	6.1	2.5
+3.0	6.5	3.2	5.1	2.0
+3.0	6.4	2.7	5.3	1.9
+3.0	6.8	3.0	5.5	2.1
+3.0	5.7	2.5	5.0	2.0
+3.0	5.8	2.8	5.1	2.4
+3.0	6.4	3.2	5.3	2.3
+3.0	6.5	3.0	5.5	1.8
+3.0	7.7	3.8	6.7	2.2
+3.0	7.7	2.6	6.9	2.3
+3.0	6.0	2.2	5.0	1.5
+3.0	6.9	3.2	5.7	2.3
+3.0	5.6	2.8	4.9	2.0
+3.0	7.7	2.8	6.7	2.0
+3.0	6.3	2.7	4.9	1.8
+3.0	6.7	3.3	5.7	2.1
+3.0	7.2	3.2	6.0	1.8
+3.0	6.2	2.8	4.8	1.8
+3.0	6.1	3.0	4.9	1.8
+3.0	6.4	2.8	5.6	2.1
+3.0	7.2	3.0	5.8	1.6
+3.0	7.4	2.8	6.1	1.9
+3.0	7.9	3.8	6.4	2.0
+3.0	6.4	2.8	5.6	2.2
+3.0	6.3	2.8	5.1	1.5
+3.0	6.1	2.6	5.6	1.4
+3.0	7.7	3.0	6.1	2.3
+3.0	6.3	3.4	5.6	2.4
+3.0	6.4	3.1	5.5	1.8
+3.0	6.0	3.0	4.8	1.8
+3.0	6.9	3.1	5.4	2.1
+3.0	6.7	3.1	5.6	2.4
+3.0	6.9	3.1	5.1	2.3
+3.0	5.8	2.7	5.1	1.9
+3.0	6.8	3.2	5.9	2.3
+3.0	6.7	3.3	5.7	2.5
+3.0	6.7	3.0	5.2	2.3
+3.0	6.3	2.5	5.0	1.9
+3.0	6.5	3.0	5.2	2.0
+3.0	6.2	3.4	5.4	2.3
+3.0	5.9	3.0	5.1	1.8

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/knn/iris_incorrect.txt
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/knn/iris_incorrect.txt b/modules/ml/src/test/resources/datasets/knn/iris_incorrect.txt
new file mode 100644
index 0000000..7bb42c6
--- /dev/null
+++ b/modules/ml/src/test/resources/datasets/knn/iris_incorrect.txt
@@ -0,0 +1,150 @@
+1.0	5.1	3.5	1.4	13ls
+ss	4.9	3.0	1.4	0.2
+1.0	4.7	3.2	1.3	0.2
+1.0	4.6	3.1	1.5	0.2
+1.0	5.0	3.6	1.4	0.2
+1.0	5.4	3.9	1.7	0.4
+1.0	4.6	3.4	1.4	0.3
+1.0	5.0	3.4	1.5	0.2
+1.0	4.4	2.9	1.4	0.2
+1.0	4.9	3.1	1.5	0.1
+1.0	5.4	3.7	1.5	0.2
+1.0	4.8	3.4	1.6	0.2
+1.0	4.8	3.0	1.4	0.1
+1.0	4.3	3.0	1.1	0.1
+1.0	5.8	4.0	1.2	0.2
+1.0	5.7	4.4	1.5	0.4
+1.0	5.4	3.9	1.3	0.4
+1.0	5.1	3.5	1.4	0.3
+1.0	5.7	3.8	1.7	0.3
+1.0	5.1	3.8	1.5	0.3
+1.0	5.4	3.4	1.7	0.2
+1.0	5.1	3.7	1.5	0.4
+1.0	4.6	3.6	1.0	0.2
+1.0	5.1	3.3	1.7	0.5
+1.0	4.8	3.4	1.9	0.2
+1.0	5.0	3.0	1.6	0.2
+1.0	5.0	3.4	1.6	0.4
+1.0	5.2	3.5	1.5	0.2
+1.0	5.2	3.4	1.4	0.2
+1.0	4.7	3.2	1.6	0.2
+1.0	4.8	3.1	1.6	0.2
+1.0	5.4	3.4	1.5	0.4
+1.0	5.2	4.1	1.5	0.1
+1.0	5.5	4.2	1.4	0.2
+1.0	4.9	3.1	1.5	0.1
+1.0	5.0	3.2	1.2	0.2
+1.0	5.5	3.5	1.3	0.2
+1.0	4.9	3.1	1.5	0.1
+1.0	4.4	3.0	1.3	0.2
+1.0	5.1	3.4	1.5	0.2
+1.0	5.0	3.5	1.3	0.3
+1.0	4.5	2.3	1.3	0.3
+1.0	4.4	3.2	1.3	0.2
+1.0	5.0	3.5	1.6	0.6
+1.0	5.1	3.8	1.9	0.4
+1.0	4.8	3.0	1.4	0.3
+1.0	5.1	3.8	1.6	0.2
+1.0	4.6	3.2	1.4	0.2
+1.0	5.3	3.7	1.5	0.2
+1.0	5.0	3.3	1.4	0.2
+2.0	7.0	3.2	4.7	1.4
+2.0	6.4	3.2	4.5	1.5
+2.0	6.9	3.1	4.9	1.5
+2.0	5.5	2.3	4.0	1.3
+2.0	6.5	2.8	4.6	1.5
+2.0	5.7	2.8	4.5	1.3
+2.0	6.3	3.3	4.7	1.6
+2.0	4.9	2.4	3.3	1.0
+2.0	6.6	2.9	4.6	1.3
+2.0	5.2	2.7	3.9	1.4
+2.0	5.0	2.0	3.5	1.0
+2.0	5.9	3.0	4.2	1.5
+2.0	6.0	2.2	4.0	1.0
+2.0	6.1	2.9	4.7	1.4
+2.0	5.6	2.9	3.6	1.3
+2.0	6.7	3.1	4.4	1.4
+2.0	5.6	3.0	4.5	1.5
+2.0	5.8	2.7	4.1	1.0
+2.0	6.2	2.2	4.5	1.5
+2.0	5.6	2.5	3.9	1.1
+2.0	5.9	3.2	4.8	1.8
+2.0	6.1	2.8	4.0	1.3
+2.0	6.3	2.5	4.9	1.5
+2.0	6.1	2.8	4.7	1.2
+2.0	6.4	2.9	4.3	1.3
+2.0	6.6	3.0	4.4	1.4
+2.0	6.8	2.8	4.8	1.4
+2.0	6.7	3.0	5.0	1.7
+2.0	6.0	2.9	4.5	1.5
+2.0	5.7	2.6	3.5	1.0
+2.0	5.5	2.4	3.8	1.1
+2.0	5.5	2.4	3.7	1.0
+2.0	5.8	2.7	3.9	1.2
+2.0	6.0	2.7	5.1	1.6
+2.0	5.4	3.0	4.5	1.5
+2.0	6.0	3.4	4.5	1.6
+2.0	6.7	3.1	4.7	1.5
+2.0	6.3	2.3	4.4	1.3
+2.0	5.6	3.0	4.1	1.3
+2.0	5.5	2.5	4.0	1.3
+2.0	5.5	2.6	4.4	1.2
+2.0	6.1	3.0	4.6	1.4
+2.0	5.8	2.6	4.0	1.2
+2.0	5.0	2.3	3.3	1.0
+2.0	5.6	2.7	4.2	1.3
+2.0	5.7	3.0	4.2	1.2
+2.0	5.7	2.9	4.2	1.3
+2.0	6.2	2.9	4.3	1.3
+2.0	5.1	2.5	3.0	1.1
+2.0	5.7	2.8	4.1	1.3
+3.0	6.3	3.3	6.0	2.5
+3.0	5.8	2.7	5.1	1.9
+3.0	7.1	3.0	5.9	2.1
+3.0	6.3	2.9	5.6	1.8
+3.0	6.5	3.0	5.8	2.2
+3.0	7.6	3.0	6.6	2.1
+3.0	4.9	2.5	4.5	1.7
+3.0	7.3	2.9	6.3	1.8
+3.0	6.7	2.5	5.8	1.8
+3.0	7.2	3.6	6.1	2.5
+3.0	6.5	3.2	5.1	2.0
+3.0	6.4	2.7	5.3	1.9
+3.0	6.8	3.0	5.5	2.1
+3.0	5.7	2.5	5.0	2.0
+3.0	5.8	2.8	5.1	2.4
+3.0	6.4	3.2	5.3	2.3
+3.0	6.5	3.0	5.5	1.8
+3.0	7.7	3.8	6.7	2.2
+3.0	7.7	2.6	6.9	2.3
+3.0	6.0	2.2	5.0	1.5
+3.0	6.9	3.2	5.7	2.3
+3.0	5.6	2.8	4.9	2.0
+3.0	7.7	2.8	6.7	2.0
+3.0	6.3	2.7	4.9	1.8
+3.0	6.7	3.3	5.7	2.1
+3.0	7.2	3.2	6.0	1.8
+3.0	6.2	2.8	4.8	1.8
+3.0	6.1	3.0	4.9	1.8
+3.0	6.4	2.8	5.6	2.1
+3.0	7.2	3.0	5.8	1.6
+3.0	7.4	2.8	6.1	1.9
+3.0	7.9	3.8	6.4	2.0
+3.0	6.4	2.8	5.6	2.2
+3.0	6.3	2.8	5.1	1.5
+3.0	6.1	2.6	5.6	1.4
+3.0	7.7	3.0	6.1	2.3
+3.0	6.3	3.4	5.6	2.4
+3.0	6.4	3.1	5.5	1.8
+3.0	6.0	3.0	4.8	1.8
+3.0	6.9	3.1	5.4	2.1
+3.0	6.7	3.1	5.6	2.4
+3.0	6.9	3.1	5.1	2.3
+3.0	5.8	2.7	5.1	1.9
+3.0	6.8	3.2	5.9	2.3
+3.0	6.7	3.3	5.7	2.5
+3.0	6.7	3.0	5.2	2.3
+3.0	6.3	2.5	5.0	1.9
+3.0	6.5	3.0	5.2	2.0
+3.0	6.2	3.4	5.4	2.3
+3.0	5.9	3.0	5.1	1.8

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/knn/machine.data.txt
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/knn/machine.data.txt b/modules/ml/src/test/resources/datasets/knn/machine.data.txt
new file mode 100644
index 0000000..656ed8c
--- /dev/null
+++ b/modules/ml/src/test/resources/datasets/knn/machine.data.txt
@@ -0,0 +1,209 @@
+adviser,32/60,125,256,6000,256,16,128,198,199
+amdahl,470v/7,29,8000,32000,32,8,32,269,253
+amdahl,470v/7a,29,8000,32000,32,8,32,220,253
+amdahl,470v/7b,29,8000,32000,32,8,32,172,253
+amdahl,470v/7c,29,8000,16000,32,8,16,132,132
+amdahl,470v/b,26,8000,32000,64,8,32,318,290
+amdahl,580-5840,23,16000,32000,64,16,32,367,381
+amdahl,580-5850,23,16000,32000,64,16,32,489,381
+amdahl,580-5860,23,16000,64000,64,16,32,636,749
+amdahl,580-5880,23,32000,64000,128,32,64,1144,1238
+apollo,dn320,400,1000,3000,0,1,2,38,23
+apollo,dn420,400,512,3500,4,1,6,40,24
+basf,7/65,60,2000,8000,65,1,8,92,70
+basf,7/68,50,4000,16000,65,1,8,138,117
+bti,5000,350,64,64,0,1,4,10,15
+bti,8000,200,512,16000,0,4,32,35,64
+burroughs,b1955,167,524,2000,8,4,15,19,23
+burroughs,b2900,143,512,5000,0,7,32,28,29
+burroughs,b2925,143,1000,2000,0,5,16,31,22
+burroughs,b4955,110,5000,5000,142,8,64,120,124
+burroughs,b5900,143,1500,6300,0,5,32,30,35
+burroughs,b5920,143,3100,6200,0,5,20,33,39
+burroughs,b6900,143,2300,6200,0,6,64,61,40
+burroughs,b6925,110,3100,6200,0,6,64,76,45
+c.r.d,68/10-80,320,128,6000,0,1,12,23,28
+c.r.d,universe:2203t,320,512,2000,4,1,3,69,21
+c.r.d,universe:68,320,256,6000,0,1,6,33,28
+c.r.d,universe:68/05,320,256,3000,4,1,3,27,22
+c.r.d,universe:68/137,320,512,5000,4,1,5,77,28
+c.r.d,universe:68/37,320,256,5000,4,1,6,27,27
+cdc,cyber:170/750,25,1310,2620,131,12,24,274,102
+cdc,cyber:170/760,25,1310,2620,131,12,24,368,102
+cdc,cyber:170/815,50,2620,10480,30,12,24,32,74
+cdc,cyber:170/825,50,2620,10480,30,12,24,63,74
+cdc,cyber:170/835,56,5240,20970,30,12,24,106,138
+cdc,cyber:170/845,64,5240,20970,30,12,24,208,136
+cdc,omega:480-i,50,500,2000,8,1,4,20,23
+cdc,omega:480-ii,50,1000,4000,8,1,5,29,29
+cdc,omega:480-iii,50,2000,8000,8,1,5,71,44
+cambex,1636-1,50,1000,4000,8,3,5,26,30
+cambex,1636-10,50,1000,8000,8,3,5,36,41
+cambex,1641-1,50,2000,16000,8,3,5,40,74
+cambex,1641-11,50,2000,16000,8,3,6,52,74
+cambex,1651-1,50,2000,16000,8,3,6,60,74
+dec,decsys:10:1091,133,1000,12000,9,3,12,72,54
+dec,decsys:20:2060,133,1000,8000,9,3,12,72,41
+dec,microvax-1,810,512,512,8,1,1,18,18
+dec,vax:11/730,810,1000,5000,0,1,1,20,28
+dec,vax:11/750,320,512,8000,4,1,5,40,36
+dec,vax:11/780,200,512,8000,8,1,8,62,38
+dg,eclipse:c/350,700,384,8000,0,1,1,24,34
+dg,eclipse:m/600,700,256,2000,0,1,1,24,19
+dg,eclipse:mv/10000,140,1000,16000,16,1,3,138,72
+dg,eclipse:mv/4000,200,1000,8000,0,1,2,36,36
+dg,eclipse:mv/6000,110,1000,4000,16,1,2,26,30
+dg,eclipse:mv/8000,110,1000,12000,16,1,2,60,56
+dg,eclipse:mv/8000-ii,220,1000,8000,16,1,2,71,42
+formation,f4000/100,800,256,8000,0,1,4,12,34
+formation,f4000/200,800,256,8000,0,1,4,14,34
+formation,f4000/200ap,800,256,8000,0,1,4,20,34
+formation,f4000/300,800,256,8000,0,1,4,16,34
+formation,f4000/300ap,800,256,8000,0,1,4,22,34
+four-phase,2000/260,125,512,1000,0,8,20,36,19
+gould,concept:32/8705,75,2000,8000,64,1,38,144,75
+gould,concept:32/8750,75,2000,16000,64,1,38,144,113
+gould,concept:32/8780,75,2000,16000,128,1,38,259,157
+hp,3000/30,90,256,1000,0,3,10,17,18
+hp,3000/40,105,256,2000,0,3,10,26,20
+hp,3000/44,105,1000,4000,0,3,24,32,28
+hp,3000/48,105,2000,4000,8,3,19,32,33
+hp,3000/64,75,2000,8000,8,3,24,62,47
+hp,3000/88,75,3000,8000,8,3,48,64,54
+hp,3000/iii,175,256,2000,0,3,24,22,20
+harris,100,300,768,3000,0,6,24,36,23
+harris,300,300,768,3000,6,6,24,44,25
+harris,500,300,768,12000,6,6,24,50,52
+harris,600,300,768,4500,0,1,24,45,27
+harris,700,300,384,12000,6,1,24,53,50
+harris,80,300,192,768,6,6,24,36,18
+harris,800,180,768,12000,6,1,31,84,53
+honeywell,dps:6/35,330,1000,3000,0,2,4,16,23
+honeywell,dps:6/92,300,1000,4000,8,3,64,38,30
+honeywell,dps:6/96,300,1000,16000,8,2,112,38,73
+honeywell,dps:7/35,330,1000,2000,0,1,2,16,20
+honeywell,dps:7/45,330,1000,4000,0,3,6,22,25
+honeywell,dps:7/55,140,2000,4000,0,3,6,29,28
+honeywell,dps:7/65,140,2000,4000,0,4,8,40,29
+honeywell,dps:8/44,140,2000,4000,8,1,20,35,32
+honeywell,dps:8/49,140,2000,32000,32,1,20,134,175
+honeywell,dps:8/50,140,2000,8000,32,1,54,66,57
+honeywell,dps:8/52,140,2000,32000,32,1,54,141,181
+honeywell,dps:8/62,140,2000,32000,32,1,54,189,181
+honeywell,dps:8/20,140,2000,4000,8,1,20,22,32
+ibm,3033:s,57,4000,16000,1,6,12,132,82
+ibm,3033:u,57,4000,24000,64,12,16,237,171
+ibm,3081,26,16000,32000,64,16,24,465,361
+ibm,3081:d,26,16000,32000,64,8,24,465,350
+ibm,3083:b,26,8000,32000,0,8,24,277,220
+ibm,3083:e,26,8000,16000,0,8,16,185,113
+ibm,370/125-2,480,96,512,0,1,1,6,15
+ibm,370/148,203,1000,2000,0,1,5,24,21
+ibm,370/158-3,115,512,6000,16,1,6,45,35
+ibm,38/3,1100,512,1500,0,1,1,7,18
+ibm,38/4,1100,768,2000,0,1,1,13,20
+ibm,38/5,600,768,2000,0,1,1,16,20
+ibm,38/7,400,2000,4000,0,1,1,32,28
+ibm,38/8,400,4000,8000,0,1,1,32,45
+ibm,4321,900,1000,1000,0,1,2,11,18
+ibm,4331-1,900,512,1000,0,1,2,11,17
+ibm,4331-11,900,1000,4000,4,1,2,18,26
+ibm,4331-2,900,1000,4000,8,1,2,22,28
+ibm,4341,900,2000,4000,0,3,6,37,28
+ibm,4341-1,225,2000,4000,8,3,6,40,31
+ibm,4341-10,225,2000,4000,8,3,6,34,31
+ibm,4341-11,180,2000,8000,8,1,6,50,42
+ibm,4341-12,185,2000,16000,16,1,6,76,76
+ibm,4341-2,180,2000,16000,16,1,6,66,76
+ibm,4341-9,225,1000,4000,2,3,6,24,26
+ibm,4361-4,25,2000,12000,8,1,4,49,59
+ibm,4361-5,25,2000,12000,16,3,5,66,65
+ibm,4381-1,17,4000,16000,8,6,12,100,101
+ibm,4381-2,17,4000,16000,32,6,12,133,116
+ibm,8130-a,1500,768,1000,0,0,0,12,18
+ibm,8130-b,1500,768,2000,0,0,0,18,20
+ibm,8140,800,768,2000,0,0,0,20,20
+ipl,4436,50,2000,4000,0,3,6,27,30
+ipl,4443,50,2000,8000,8,3,6,45,44
+ipl,4445,50,2000,8000,8,1,6,56,44
+ipl,4446,50,2000,16000,24,1,6,70,82
+ipl,4460,50,2000,16000,24,1,6,80,82
+ipl,4480,50,8000,16000,48,1,10,136,128
+magnuson,m80/30,100,1000,8000,0,2,6,16,37
+magnuson,m80/31,100,1000,8000,24,2,6,26,46
+magnuson,m80/32,100,1000,8000,24,3,6,32,46
+magnuson,m80/42,50,2000,16000,12,3,16,45,80
+magnuson,m80/43,50,2000,16000,24,6,16,54,88
+magnuson,m80/44,50,2000,16000,24,6,16,65,88
+microdata,seq.ms/3200,150,512,4000,0,8,128,30,33
+nas,as/3000,115,2000,8000,16,1,3,50,46
+nas,as/3000-n,115,2000,4000,2,1,5,40,29
+nas,as/5000,92,2000,8000,32,1,6,62,53
+nas,as/5000-e,92,2000,8000,32,1,6,60,53
+nas,as/5000-n,92,2000,8000,4,1,6,50,41
+nas,as/6130,75,4000,16000,16,1,6,66,86
+nas,as/6150,60,4000,16000,32,1,6,86,95
+nas,as/6620,60,2000,16000,64,5,8,74,107
+nas,as/6630,60,4000,16000,64,5,8,93,117
+nas,as/6650,50,4000,16000,64,5,10,111,119
+nas,as/7000,72,4000,16000,64,8,16,143,120
+nas,as/7000-n,72,2000,8000,16,6,8,105,48
+nas,as/8040,40,8000,16000,32,8,16,214,126
+nas,as/8050,40,8000,32000,64,8,24,277,266
+nas,as/8060,35,8000,32000,64,8,24,370,270
+nas,as/9000-dpc,38,16000,32000,128,16,32,510,426
+nas,as/9000-n,48,4000,24000,32,8,24,214,151
+nas,as/9040,38,8000,32000,64,8,24,326,267
+nas,as/9060,30,16000,32000,256,16,24,510,603
+ncr,v8535:ii,112,1000,1000,0,1,4,8,19
+ncr,v8545:ii,84,1000,2000,0,1,6,12,21
+ncr,v8555:ii,56,1000,4000,0,1,6,17,26
+ncr,v8565:ii,56,2000,6000,0,1,8,21,35
+ncr,v8565:ii-e,56,2000,8000,0,1,8,24,41
+ncr,v8575:ii,56,4000,8000,0,1,8,34,47
+ncr,v8585:ii,56,4000,12000,0,1,8,42,62
+ncr,v8595:ii,56,4000,16000,0,1,8,46,78
+ncr,v8635,38,4000,8000,32,16,32,51,80
+ncr,v8650,38,4000,8000,32,16,32,116,80
+ncr,v8655,38,8000,16000,64,4,8,100,142
+ncr,v8665,38,8000,24000,160,4,8,140,281
+ncr,v8670,38,4000,16000,128,16,32,212,190
+nixdorf,8890/30,200,1000,2000,0,1,2,25,21
+nixdorf,8890/50,200,1000,4000,0,1,4,30,25
+nixdorf,8890/70,200,2000,8000,64,1,5,41,67
+perkin-elmer,3205,250,512,4000,0,1,7,25,24
+perkin-elmer,3210,250,512,4000,0,4,7,50,24
+perkin-elmer,3230,250,1000,16000,1,1,8,50,64
+prime,50-2250,160,512,4000,2,1,5,30,25
+prime,50-250-ii,160,512,2000,2,3,8,32,20
+prime,50-550-ii,160,1000,4000,8,1,14,38,29
+prime,50-750-ii,160,1000,8000,16,1,14,60,43
+prime,50-850-ii,160,2000,8000,32,1,13,109,53
+siemens,7.521,240,512,1000,8,1,3,6,19
+siemens,7.531,240,512,2000,8,1,5,11,22
+siemens,7.536,105,2000,4000,8,3,8,22,31
+siemens,7.541,105,2000,6000,16,6,16,33,41
+siemens,7.551,105,2000,8000,16,4,14,58,47
+siemens,7.561,52,4000,16000,32,4,12,130,99
+siemens,7.865-2,70,4000,12000,8,6,8,75,67
+siemens,7.870-2,59,4000,12000,32,6,12,113,81
+siemens,7.872-2,59,8000,16000,64,12,24,188,149
+siemens,7.875-2,26,8000,24000,32,8,16,173,183
+siemens,7.880-2,26,8000,32000,64,12,16,248,275
+siemens,7.881-2,26,8000,32000,128,24,32,405,382
+sperry,1100/61-h1,116,2000,8000,32,5,28,70,56
+sperry,1100/81,50,2000,32000,24,6,26,114,182
+sperry,1100/82,50,2000,32000,48,26,52,208,227
+sperry,1100/83,50,2000,32000,112,52,104,307,341
+sperry,1100/84,50,4000,32000,112,52,104,397,360
+sperry,1100/93,30,8000,64000,96,12,176,915,919
+sperry,1100/94,30,8000,64000,128,12,176,1150,978
+sperry,80/3,180,262,4000,0,1,3,12,24
+sperry,80/4,180,512,4000,0,1,3,14,24
+sperry,80/5,180,262,4000,0,1,3,18,24
+sperry,80/6,180,512,4000,0,1,3,21,24
+sperry,80/8,124,1000,8000,0,1,8,42,37
+sperry,90/80-model-3,98,1000,8000,32,2,8,46,50
+sratus,32,125,2000,8000,0,2,14,52,41
+wang,vs-100,480,512,8000,32,0,0,67,47
+wang,vs-90,480,1000,4000,0,0,0,45,25

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/knn/missed_data.txt
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/knn/missed_data.txt b/modules/ml/src/test/resources/datasets/knn/missed_data.txt
new file mode 100644
index 0000000..83ce9a5
--- /dev/null
+++ b/modules/ml/src/test/resources/datasets/knn/missed_data.txt
@@ -0,0 +1,3 @@
+1.0,5.1,3.5,1.4,0.2
+1.0,4.9,3.0,1.4,0.2
+1.0,4.7,,1.3,0.2

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/test/resources/datasets/knn/no_data.txt
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/resources/datasets/knn/no_data.txt b/modules/ml/src/test/resources/datasets/knn/no_data.txt
new file mode 100644
index 0000000..d1d4c7b
--- /dev/null
+++ b/modules/ml/src/test/resources/datasets/knn/no_data.txt
@@ -0,0 +1,6 @@
+
+
+2
+
+
+323

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index cb335d12..97983dd 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -838,6 +838,7 @@
                                         <exclude>src/main/java/org/apache/ignite/examples/streaming/wordcount/*.txt</exclude><!--books examples-->
                                         <exclude>examples/src/main/java/org/apache/ignite/examples/streaming/wordcount/*.txt</exclude><!--books examples-->
                                         <exclude>src/main/resources/person.csv</exclude><!--CacheLoadOnlyStoreExample csv-->
+                                        <exclude>**/resources/datasets/knn/*</exclude><!--Dataset examples in ml module-->
                                         <exclude>examples/src/main/resources/person.csv</exclude><!--CacheLoadOnlyStoreExample csv-->
                                         <exclude>src/main/java/org/jetbrains/annotations/*.java</exclude><!--copyright-->
                                         <exclude>dev-tools/IGNITE-*.patch</exclude>


[2/2] ignite git commit: IGNITE-6880: KNN(k nearest neighbor) algorithm

Posted by ch...@apache.org.
IGNITE-6880: KNN(k nearest neighbor) algorithm

this closes #3117


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/8ba773bf
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/8ba773bf
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/8ba773bf

Branch: refs/heads/master
Commit: 8ba773bfe580ab3e0822283e7581115242303962
Parents: e3d70a8
Author: zaleslaw <za...@gmail.com>
Authored: Mon Dec 11 19:02:08 2017 +0300
Committer: Yury Babak <yb...@gridgain.com>
Committed: Mon Dec 11 19:02:08 2017 +0300

----------------------------------------------------------------------
 .../ml/clustering/FuzzyCMeansExample.java       |   4 +-
 .../KMeansDistributedClustererExample.java      |   2 +-
 .../clustering/KMeansLocalClustererExample.java |   4 +-
 .../ignite/ml/FuzzyCMeansModelFormat.java       |   2 +-
 .../org/apache/ignite/ml/KMeansModelFormat.java |   2 +-
 .../ml/clustering/BaseFuzzyCMeansClusterer.java |   2 +-
 .../ml/clustering/BaseKMeansClusterer.java      |   2 +-
 .../FuzzyCMeansDistributedClusterer.java        |   2 +-
 .../clustering/FuzzyCMeansLocalClusterer.java   |   2 +-
 .../ignite/ml/clustering/FuzzyCMeansModel.java  |   2 +-
 .../clustering/KMeansDistributedClusterer.java  |   2 +-
 .../ml/clustering/KMeansLocalClusterer.java     |   2 +-
 .../ignite/ml/clustering/KMeansModel.java       |   2 +-
 .../apache/ignite/ml/knn/models/KNNModel.java   | 233 ++++++++++
 .../ignite/ml/knn/models/KNNModelFormat.java    |  92 ++++
 .../ignite/ml/knn/models/KNNStrategy.java       |  27 ++
 .../ignite/ml/knn/models/Normalization.java     |  32 ++
 .../ignite/ml/knn/models/package-info.java      |  22 +
 .../org/apache/ignite/ml/knn/package-info.java  |  22 +
 .../regression/KNNMultipleLinearRegression.java |  83 ++++
 .../ignite/ml/knn/regression/package-info.java  |  22 +
 .../apache/ignite/ml/math/DistanceMeasure.java  |  38 --
 .../ignite/ml/math/EuclideanDistance.java       |  58 ---
 .../ml/math/distances/DistanceMeasure.java      |  39 ++
 .../ml/math/distances/EuclideanDistance.java    |  59 +++
 .../ml/math/distances/HammingDistance.java      |  65 +++
 .../ml/math/distances/ManhattanDistance.java    |  59 +++
 .../ignite/ml/math/distances/package-info.java  |  22 +
 .../ignite/ml/math/distributed/CacheUtils.java  |   2 +-
 .../distributed/keys/impl/SparseMatrixKey.java  |   1 +
 .../math/exceptions/knn/EmptyFileException.java |  37 ++
 .../exceptions/knn/FileParsingException.java    |  39 ++
 .../exceptions/knn/NoLabelVectorException.java  |  37 ++
 .../knn/SmallTrainingDatasetSizeException.java  |  38 ++
 .../ml/math/exceptions/knn/package-info.java    |  22 +
 .../ignite/ml/structures/LabeledDataset.java    | 457 +++++++++++++++++++
 .../ignite/ml/structures/LabeledVector.java     |  37 +-
 .../org/apache/ignite/ml/IgniteMLTestSuite.java |   2 +
 .../org/apache/ignite/ml/LocalModelsTest.java   |  39 +-
 .../FuzzyCMeansDistributedClustererTest.java    |   4 +-
 .../FuzzyCMeansLocalClustererTest.java          |   4 +-
 ...KMeansDistributedClustererTestMultiNode.java |   2 +-
 ...MeansDistributedClustererTestSingleNode.java |   4 +-
 .../ml/clustering/KMeansLocalClustererTest.java |   2 +-
 .../org/apache/ignite/ml/knn/BaseKNNTest.java   |  91 ++++
 .../ignite/ml/knn/KNNClassificationTest.java    | 153 +++++++
 .../ml/knn/KNNMultipleLinearRegressionTest.java | 157 +++++++
 .../org/apache/ignite/ml/knn/KNNTestSuite.java  |  33 ++
 .../ignite/ml/knn/LabeledDatasetTest.java       | 208 +++++++++
 .../ignite/ml/math/MathImplLocalTestSuite.java  |   4 +-
 .../ignite/ml/math/distances/DistanceTest.java  |  75 +++
 .../OLSMultipleLinearRegressionTest.java        |   1 +
 .../ml/trees/ColumnDecisionTreeTrainerTest.java |   6 +-
 .../ColumnDecisionTreeTrainerBenchmark.java     |   6 +-
 .../ml/src/test/resources/datasets/README.md    |   2 +
 .../resources/datasets/knn/cleared_machines.txt | 209 +++++++++
 .../src/test/resources/datasets/knn/empty.txt   |   0
 .../ml/src/test/resources/datasets/knn/iris.txt | 150 ++++++
 .../resources/datasets/knn/iris_incorrect.txt   | 150 ++++++
 .../resources/datasets/knn/machine.data.txt     | 209 +++++++++
 .../test/resources/datasets/knn/missed_data.txt |   3 +
 .../src/test/resources/datasets/knn/no_data.txt |   6 +
 parent/pom.xml                                  |   1 +
 63 files changed, 2963 insertions(+), 131 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/FuzzyCMeansExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/FuzzyCMeansExample.java b/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/FuzzyCMeansExample.java
index 9c47186..3fce624 100644
--- a/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/FuzzyCMeansExample.java
+++ b/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/FuzzyCMeansExample.java
@@ -22,10 +22,10 @@ import org.apache.ignite.Ignition;
 import org.apache.ignite.ml.clustering.BaseFuzzyCMeansClusterer;
 import org.apache.ignite.ml.clustering.FuzzyCMeansDistributedClusterer;
 import org.apache.ignite.ml.clustering.FuzzyCMeansModel;
-import org.apache.ignite.ml.math.DistanceMeasure;
-import org.apache.ignite.ml.math.EuclideanDistance;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 import org.apache.ignite.thread.IgniteThread;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansDistributedClustererExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansDistributedClustererExample.java b/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansDistributedClustererExample.java
index 456e915..09f35d2 100644
--- a/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansDistributedClustererExample.java
+++ b/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansDistributedClustererExample.java
@@ -24,10 +24,10 @@ import org.apache.ignite.Ignition;
 import org.apache.ignite.examples.ExampleNodeStartup;
 import org.apache.ignite.examples.ml.math.matrix.SparseDistributedMatrixExample;
 import org.apache.ignite.ml.clustering.KMeansDistributedClusterer;
-import org.apache.ignite.ml.math.EuclideanDistance;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Tracer;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 import org.apache.ignite.thread.IgniteThread;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansLocalClustererExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansLocalClustererExample.java b/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansLocalClustererExample.java
index 970931e..28ca9d9 100644
--- a/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansLocalClustererExample.java
+++ b/examples/src/main/ml/org/apache/ignite/examples/ml/clustering/KMeansLocalClustererExample.java
@@ -22,10 +22,10 @@ import java.util.Comparator;
 import java.util.List;
 import org.apache.ignite.ml.clustering.KMeansLocalClusterer;
 import org.apache.ignite.ml.clustering.KMeansModel;
-import org.apache.ignite.ml.math.DistanceMeasure;
-import org.apache.ignite.ml.math.EuclideanDistance;
 import org.apache.ignite.ml.math.Tracer;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.math.distances.EuclideanDistance;
 import org.apache.ignite.ml.math.functions.Functions;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/FuzzyCMeansModelFormat.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/FuzzyCMeansModelFormat.java b/modules/ml/src/main/java/org/apache/ignite/ml/FuzzyCMeansModelFormat.java
index 2b27e86..cc3d9b3 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/FuzzyCMeansModelFormat.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/FuzzyCMeansModelFormat.java
@@ -19,8 +19,8 @@ package org.apache.ignite.ml;
 
 import java.io.Serializable;
 import java.util.Arrays;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 
 /** Fuzzy C-Means model representation. */
 public class FuzzyCMeansModelFormat implements Serializable {

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/KMeansModelFormat.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/KMeansModelFormat.java b/modules/ml/src/main/java/org/apache/ignite/ml/KMeansModelFormat.java
index 4f5b143..c013198 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/KMeansModelFormat.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/KMeansModelFormat.java
@@ -19,8 +19,8 @@ package org.apache.ignite.ml;
 
 import java.io.Serializable;
 import java.util.Arrays;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 
 /**
  * K-means model representation.

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseFuzzyCMeansClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseFuzzyCMeansClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseFuzzyCMeansClusterer.java
index 65aaeee..2b2febf 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseFuzzyCMeansClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseFuzzyCMeansClusterer.java
@@ -17,9 +17,9 @@
 
 package org.apache.ignite.ml.clustering;
 
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 import org.apache.ignite.ml.math.exceptions.ConvergenceException;
 import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseKMeansClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseKMeansClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseKMeansClusterer.java
index 570ea7e..521437c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseKMeansClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/BaseKMeansClusterer.java
@@ -19,9 +19,9 @@ package org.apache.ignite.ml.clustering;
 
 import java.util.List;
 import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 import org.apache.ignite.ml.math.exceptions.ConvergenceException;
 import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClusterer.java
index a5cd871..8823c10 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansDistributedClusterer.java
@@ -26,9 +26,9 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 import javax.cache.Cache;
 import org.apache.ignite.internal.util.GridArgumentCheck;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.VectorUtils;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 import org.apache.ignite.ml.math.distributed.CacheUtils;
 import org.apache.ignite.ml.math.distributed.keys.impl.SparseMatrixKey;
 import org.apache.ignite.ml.math.exceptions.ConvergenceException;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClusterer.java
index 1724da3..a1b6d3f 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansLocalClusterer.java
@@ -22,9 +22,9 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Random;
 import org.apache.ignite.internal.util.GridArgumentCheck;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 import org.apache.ignite.ml.math.exceptions.ConvergenceException;
 import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansModel.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansModel.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansModel.java
index 41267b9..83fbf1f 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansModel.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/FuzzyCMeansModel.java
@@ -21,8 +21,8 @@ import java.util.Arrays;
 import org.apache.ignite.ml.Exportable;
 import org.apache.ignite.ml.Exporter;
 import org.apache.ignite.ml.FuzzyCMeansModelFormat;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 
 /** This class incapsulates result of clusterization. */
 public class FuzzyCMeansModel implements ClusterizationModel<Vector, Integer>, Exportable<FuzzyCMeansModelFormat> {

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
index 24938bc..5595b4c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
@@ -26,9 +26,9 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 import javax.cache.Cache;
 import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.VectorUtils;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 import org.apache.ignite.ml.math.distributed.CacheUtils;
 import org.apache.ignite.ml.math.distributed.keys.impl.SparseMatrixKey;
 import org.apache.ignite.ml.math.exceptions.ConvergenceException;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansLocalClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansLocalClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansLocalClusterer.java
index 3d005b4..8a50e65 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansLocalClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansLocalClusterer.java
@@ -23,10 +23,10 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Random;
 import org.apache.ignite.internal.util.GridArgumentCheck;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.VectorUtils;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 import org.apache.ignite.ml.math.exceptions.ConvergenceException;
 import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
 import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansModel.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansModel.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansModel.java
index c449b8b..381f976 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansModel.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansModel.java
@@ -21,8 +21,8 @@ import java.util.Arrays;
 import org.apache.ignite.ml.Exportable;
 import org.apache.ignite.ml.Exporter;
 import org.apache.ignite.ml.KMeansModelFormat;
-import org.apache.ignite.ml.math.DistanceMeasure;
 import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
 
 /**
  * This class encapsulates result of clusterization.

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModel.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModel.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModel.java
new file mode 100644
index 0000000..44955c8
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModel.java
@@ -0,0 +1,233 @@
+/*
+ * 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.knn.models;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import org.apache.ignite.ml.Exportable;
+import org.apache.ignite.ml.Exporter;
+import org.apache.ignite.ml.Model;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.math.exceptions.knn.SmallTrainingDatasetSizeException;
+import org.apache.ignite.ml.structures.LabeledDataset;
+import org.apache.ignite.ml.structures.LabeledVector;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * kNN algorithm is a classification algorithm.
+ */
+public class KNNModel implements Model<Vector, Double>, Exportable<KNNModelFormat> {
+    /** Amount of nearest neighbors. */
+    protected final int k;
+
+    /** Distance measure. */
+    protected final DistanceMeasure distanceMeasure;
+
+    /** Training dataset. */
+    protected final LabeledDataset training;
+
+    /** kNN strategy. */
+    protected final KNNStrategy stgy;
+
+    /** Cached distances for k-nearest neighbors. */
+    protected double[] cachedDistances;
+
+    /**
+     * Creates the kNN model with the given parameters.
+     *
+     * @param k Amount of nearest neighbors.
+     * @param distanceMeasure Distance measure.
+     * @param stgy Strategy of calculations.
+     * @param training Training dataset.
+     */
+    public KNNModel(int k, DistanceMeasure distanceMeasure, KNNStrategy stgy, LabeledDataset training) {
+        assert training != null;
+
+        if (training.rowSize() < k)
+            throw new SmallTrainingDatasetSizeException(k, training.rowSize());
+
+        this.k = k;
+        this.distanceMeasure = distanceMeasure;
+        this.training = training;
+        this.stgy = stgy;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Double predict(Vector v) {
+        LabeledVector[] neighbors = findKNearestNeighbors(v, true);
+
+        return classify(neighbors, v, stgy);
+    }
+
+    /** */
+    @Override public <P> void saveModel(Exporter<KNNModelFormat, P> exporter, P path) {
+        KNNModelFormat mdlData = new KNNModelFormat(k, distanceMeasure, training, stgy);
+
+        exporter.save(mdlData, path);
+    }
+
+    /**
+     * The main idea is calculation all distance pairs between given vector and all vectors in training set, sorting
+     * them and finding k vectors with min distance with the given vector.
+     *
+     * @param v The given vector.
+     * @return K-nearest neighbors.
+     */
+    protected LabeledVector[] findKNearestNeighbors(Vector v, boolean isCashedDistance) {
+        LabeledVector[] trainingData = training.data();
+
+        TreeMap<Double, Set<Integer>> distanceIdxPairs = getDistances(v, trainingData);
+
+        return getKClosestVectors(trainingData, distanceIdxPairs, isCashedDistance);
+    }
+
+    /**
+     * Iterates along entries in distance map and fill the resulting k-element array.
+     *
+     * @param trainingData The training data.
+     * @param distanceIdxPairs The distance map.
+     * @param isCashedDistances Cache distances if true.
+     * @return K-nearest neighbors.
+     */
+    @NotNull private LabeledVector[] getKClosestVectors(LabeledVector[] trainingData,
+        TreeMap<Double, Set<Integer>> distanceIdxPairs, boolean isCashedDistances) {
+        LabeledVector[] res = new LabeledVector[k];
+        int i = 0;
+        final Iterator<Double> iter = distanceIdxPairs.keySet().iterator();
+        while (i < k) {
+            double key = iter.next();
+            Set<Integer> idxs = distanceIdxPairs.get(key);
+            for (Integer idx : idxs) {
+                res[i] = trainingData[idx];
+                if (isCashedDistances) {
+                    if (cachedDistances == null)
+                        cachedDistances = new double[k];
+                    cachedDistances[i] = key;
+                }
+                i++;
+                if (i >= k)
+                    break; // go to next while-loop iteration
+            }
+        }
+        return res;
+    }
+
+    /**
+     * Computes distances between given vector and each vector in training dataset.
+     *
+     * @param v The given vector.
+     * @param trainingData The training dataset.
+     * @return Key - distanceMeasure from given features before features with idx stored in value. Value is presented
+     * with Set because there can be a few vectors with the same distance.
+     */
+    @NotNull private TreeMap<Double, Set<Integer>> getDistances(Vector v, LabeledVector[] trainingData) {
+        TreeMap<Double, Set<Integer>> distanceIdxPairs = new TreeMap<>();
+
+        for (int i = 0; i < trainingData.length; i++) {
+
+            LabeledVector labeledVector = trainingData[i];
+            if (labeledVector != null) {
+                double distance = distanceMeasure.compute(v, labeledVector.features());
+                putDistanceIdxPair(distanceIdxPairs, i, distance);
+            }
+        }
+        return distanceIdxPairs;
+    }
+
+    /** */
+    private void putDistanceIdxPair(Map<Double, Set<Integer>> distanceIdxPairs, int i, double distance) {
+        if (distanceIdxPairs.containsKey(distance)) {
+            Set<Integer> idxs = distanceIdxPairs.get(distance);
+            idxs.add(i);
+        }
+        else {
+            Set<Integer> idxs = new HashSet<>();
+            idxs.add(i);
+            distanceIdxPairs.put(distance, idxs);
+        }
+    }
+
+    /** */
+    private double classify(LabeledVector[] neighbors, Vector v, KNNStrategy stgy) {
+        Map<Double, Double> clsVotes = new HashMap<>();
+
+        for (int i = 0; i < neighbors.length; i++) {
+            LabeledVector neighbor = neighbors[i];
+            double clsLb = (double)neighbor.label();
+
+            double distance = cachedDistances != null ? cachedDistances[i] : distanceMeasure.compute(v, neighbor.features());
+
+            if (clsVotes.containsKey(clsLb)) {
+                double clsVote = clsVotes.get(clsLb);
+                clsVote += getClassVoteForVector(stgy, distance);
+                clsVotes.put(clsLb, clsVote);
+            }
+            else {
+                final double val = getClassVoteForVector(stgy, distance);
+                clsVotes.put(clsLb, val);
+            }
+        }
+        return getClassWithMaxVotes(clsVotes);
+    }
+
+    /** */
+    private double getClassWithMaxVotes(Map<Double, Double> clsVotes) {
+        return Collections.max(clsVotes.entrySet(), Map.Entry.comparingByValue()).getKey();
+    }
+
+    /** */
+    private double getClassVoteForVector(KNNStrategy stgy, double distance) {
+        if (stgy.equals(KNNStrategy.WEIGHTED))
+            return 1 / distance; // strategy.WEIGHTED
+        else
+            return 1.0; // strategy.SIMPLE
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + k;
+        res = res * 37 + distanceMeasure.hashCode();
+        res = res * 37 + stgy.hashCode();
+        res = res * 37 + Arrays.hashCode(training.data());
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        KNNModel that = (KNNModel)obj;
+
+        return k == that.k && distanceMeasure.equals(that.distanceMeasure) && stgy.equals(that.stgy)
+            && Arrays.deepEquals(training.data(), that.training.data());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModelFormat.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModelFormat.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModelFormat.java
new file mode 100644
index 0000000..17d9842
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNModelFormat.java
@@ -0,0 +1,92 @@
+/*
+ * 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.knn.models;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.structures.LabeledDataset;
+
+/** */
+public class KNNModelFormat implements Serializable {
+    /** Amount of nearest neighbors. */
+    private int k;
+
+    /** Distance measure. */
+    private DistanceMeasure distanceMeasure;
+
+    /** Training dataset */
+    private LabeledDataset training;
+
+    /** kNN strategy. */
+    private KNNStrategy stgy;
+
+    /** */
+    public int getK() {
+        return k;
+    }
+
+    /** */
+    public DistanceMeasure getDistanceMeasure() {
+        return distanceMeasure;
+    }
+
+    /** */
+    public LabeledDataset getTraining() {
+        return training;
+    }
+
+    /** */
+    public KNNStrategy getStgy() {
+        return stgy;
+    }
+
+    /** */
+    public KNNModelFormat(int k, DistanceMeasure measure, LabeledDataset training, KNNStrategy stgy) {
+        this.k = k;
+        this.distanceMeasure = measure;
+        this.training = training;
+        this.stgy = stgy;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + k;
+        res = res * 37 + distanceMeasure.hashCode();
+        res = res * 37 + stgy.hashCode();
+        res = res * 37 + Arrays.hashCode(training.data());
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        KNNModelFormat that = (KNNModelFormat)obj;
+
+        return k == that.k && distanceMeasure.equals(that.distanceMeasure) && stgy.equals(that.stgy)
+            && Arrays.deepEquals(training.data(), that.training.data());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNStrategy.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNStrategy.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNStrategy.java
new file mode 100644
index 0000000..d524773
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/KNNStrategy.java
@@ -0,0 +1,27 @@
+/*
+ * 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.knn.models;
+
+/** This enum contains settings for kNN algorithm. */
+public enum KNNStrategy {
+    /** */
+    SIMPLE,
+
+    /** */
+    WEIGHTED
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/Normalization.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/Normalization.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/Normalization.java
new file mode 100644
index 0000000..aa4b291
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/Normalization.java
@@ -0,0 +1,32 @@
+/*
+ * 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.knn.models;
+
+/** This enum contains names of different normalization approaches. */
+public enum Normalization {
+    /** Minimax.
+     *
+     * x'=(x-MIN[X])/(MAX[X]-MIN[X])
+     */
+    MINIMAX,
+    /** Z normalization.
+     *
+     * x'=(x-M[X])/\sigma [X]
+     */
+    Z_NORMALIZATION
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/package-info.java
new file mode 100644
index 0000000..7b6e678
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/models/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains main APIs for kNN classification algorithms.
+ */
+package org.apache.ignite.ml.knn.models;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/package-info.java
new file mode 100644
index 0000000..0854015
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains main APIs for kNN algorithms.
+ */
+package org.apache.ignite.ml.knn;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/KNNMultipleLinearRegression.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/KNNMultipleLinearRegression.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/KNNMultipleLinearRegression.java
new file mode 100644
index 0000000..2db8a9f
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/KNNMultipleLinearRegression.java
@@ -0,0 +1,83 @@
+/*
+ * 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.knn.regression;
+
+import org.apache.ignite.ml.knn.models.KNNModel;
+import org.apache.ignite.ml.knn.models.KNNStrategy;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distances.DistanceMeasure;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.structures.LabeledDataset;
+import org.apache.ignite.ml.structures.LabeledVector;
+
+/**
+ * This class provides kNN Multiple Linear Regression or Locally [weighted] regression (Simple and Weighted versions).
+ *
+ * <p> This is an instance-based learning method. </p>
+ *
+ * <ul>
+ *     <li>Local means using nearby points (i.e. a nearest neighbors approach).</li>
+ *     <li>Weighted means we value points based upon how far away they are.</li>
+ *     <li>Regression means approximating a function.</li>
+ * </ul>
+ */
+public class KNNMultipleLinearRegression extends KNNModel {
+    /** {@inheritDoc} */
+    public KNNMultipleLinearRegression(int k, DistanceMeasure distanceMeasure, KNNStrategy stgy,
+        LabeledDataset training) {
+        super(k, distanceMeasure, stgy, training);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Double predict(Vector v) {
+        LabeledVector[] neighbors = findKNearestNeighbors(v, true);
+
+        return predictYBasedOn(neighbors, v);
+    }
+
+    /** */
+    private double predictYBasedOn(LabeledVector[] neighbors, Vector v) {
+        switch (stgy) {
+            case SIMPLE:
+                return simpleRegression(neighbors);
+            case WEIGHTED:
+                return weightedRegression(neighbors, v);
+            default:
+                throw new UnsupportedOperationException("Strategy " + stgy.name() + " is not supported");
+        }
+    }
+
+    /** */
+    private double weightedRegression(LabeledVector<Vector, Double>[] neighbors, Vector v) {
+        double sum = 0.0;
+        double div = 0.0;
+        for (int i = 0; i < neighbors.length; i++) {
+            double distance = cachedDistances != null ? cachedDistances[i] : distanceMeasure.compute(v, neighbors[i].features());
+            sum += neighbors[i].label() * distance;
+            div += distance;
+        }
+        return sum / div;
+    }
+
+    /** */
+    private double simpleRegression(LabeledVector<Vector, Double>[] neighbors) {
+        double sum = 0.0;
+        for (LabeledVector<Vector, Double> neighbor : neighbors)
+            sum += neighbor.label();
+        return sum / (double)k;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/package-info.java
new file mode 100644
index 0000000..30023a1
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/knn/regression/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains main APIs for kNN regression algorithms.
+ */
+package org.apache.ignite.ml.knn.regression;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/DistanceMeasure.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/DistanceMeasure.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/DistanceMeasure.java
deleted file mode 100644
index df235a7..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/DistanceMeasure.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.math;
-
-import java.io.Externalizable;
-import org.apache.ignite.ml.math.exceptions.CardinalityException;
-
-/**
- * This class is based on the corresponding class from Apache Common Math lib.
- * Interface for distance measures of n-dimensional vectors.
- */
-public interface DistanceMeasure extends Externalizable {
-    /**
-     * Compute the distance between two n-dimensional vectors.
-     * <p>
-     * The two vectors are required to have the same dimension.
-     *
-     * @param a the first vector
-     * @param b the second vector
-     * @return the distance between the two vectors
-     * @throws CardinalityException if the array lengths differ.
-     */
-    public double compute(Vector a, Vector b) throws CardinalityException;
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/EuclideanDistance.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/EuclideanDistance.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/EuclideanDistance.java
deleted file mode 100644
index 5d5a64e..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/EuclideanDistance.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.math;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.apache.ignite.ml.math.exceptions.CardinalityException;
-import org.apache.ignite.ml.math.util.MatrixUtil;
-
-/**
- * Calculates the L<sub>2</sub> (Euclidean) distance between two points.
- */
-public class EuclideanDistance implements DistanceMeasure {
-    /** Serializable version identifier. */
-    private static final long serialVersionUID = 1717556319784040040L;
-
-    /** {@inheritDoc} */
-    @Override public double compute(Vector a, Vector b)
-        throws CardinalityException {
-        return MatrixUtil.localCopyOf(a).minus(b).kNorm(2.0);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeExternal(ObjectOutput out) throws IOException {
-        // No-op
-    }
-
-    /** {@inheritDoc} */
-    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        // No-op
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-
-        if (obj == null || getClass() != obj.getClass())
-            return false;
-
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/DistanceMeasure.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/DistanceMeasure.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/DistanceMeasure.java
new file mode 100644
index 0000000..3fa2ec7
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/DistanceMeasure.java
@@ -0,0 +1,39 @@
+/*
+ * 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.math.distances;
+
+import java.io.Externalizable;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+
+/**
+ * This class is based on the corresponding class from Apache Common Math lib.
+ * Interface for distance measures of n-dimensional vectors.
+ */
+public interface DistanceMeasure extends Externalizable {
+    /**
+     * Compute the distance between two n-dimensional vectors.
+     * <p>
+     * The two vectors are required to have the same dimension.
+     *
+     * @param a The first vector.
+     * @param b The second vector.
+     * @return The distance between the two vectors.
+     * @throws CardinalityException if the array lengths differ.
+     */
+    public double compute(Vector a, Vector b) throws CardinalityException;
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/EuclideanDistance.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/EuclideanDistance.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/EuclideanDistance.java
new file mode 100644
index 0000000..a0c95d2
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/EuclideanDistance.java
@@ -0,0 +1,59 @@
+/*
+ * 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.math.distances;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.util.MatrixUtil;
+
+/**
+ * Calculates the L<sub>2</sub> (Euclidean) distance between two points.
+ */
+public class EuclideanDistance implements DistanceMeasure {
+    /** Serializable version identifier. */
+    private static final long serialVersionUID = 1717556319784040040L;
+
+    /** {@inheritDoc} */
+    @Override public double compute(Vector a, Vector b)
+        throws CardinalityException {
+        return MatrixUtil.localCopyOf(a).minus(b).kNorm(2.0);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        // No-op
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        // No-op
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/HammingDistance.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/HammingDistance.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/HammingDistance.java
new file mode 100644
index 0000000..dec2d73
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/HammingDistance.java
@@ -0,0 +1,65 @@
+/*
+ * 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.math.distances;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.functions.Functions;
+import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.util.MatrixUtil;
+
+/**
+ * Calculates the Hamming distance between two points.
+ */
+public class HammingDistance implements DistanceMeasure {
+    /** Serializable version identifier. */
+    private static final long serialVersionUID = 1771556549784040098L;
+
+    /** {@inheritDoc} */
+    @Override public double compute(Vector a, Vector b)
+        throws CardinalityException {
+        IgniteDoubleFunction<Double> fun = (value -> {
+            if (value == 0) return 0.0;
+            else return 1.0;
+        });
+        return MatrixUtil.localCopyOf(a).minus(b).foldMap(Functions.PLUS, fun, 0d);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        // No-op
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        // No-op
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/ManhattanDistance.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/ManhattanDistance.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/ManhattanDistance.java
new file mode 100644
index 0000000..66394f1
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/ManhattanDistance.java
@@ -0,0 +1,59 @@
+/*
+ * 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.math.distances;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.util.MatrixUtil;
+
+/**
+ * Calculates the L<sub>1</sub> (sum of abs) distance between two points.
+ */
+public class ManhattanDistance implements DistanceMeasure {
+    /** Serializable version identifier. */
+    private static final long serialVersionUID = 8989556319784040040L;
+
+    /** {@inheritDoc} */
+    @Override public double compute(Vector a, Vector b)
+        throws CardinalityException {
+        return MatrixUtil.localCopyOf(a).minus(b).kNorm(1.0);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        // No-op
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        // No-op
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/package-info.java
new file mode 100644
index 0000000..9d799b7
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distances/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains main APIs for distances.
+ */
+package org.apache.ignite.ml.math.distances;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
index 9ca167c..3256f8a 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
@@ -374,7 +374,7 @@ public class CacheUtils {
             else if (key instanceof VectorBlockKey)
                 return ((VectorBlockKey)key).dataStructureId().equals(matrixUuid);
             else
-                throw new UnsupportedOperationException(); // TODO: handle my poor doubles
+                throw new UnsupportedOperationException();
         };
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
index cbd5208..3669d19 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
@@ -28,6 +28,7 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 
+
 /**
  * Key implementation for {@link SparseDistributedMatrix}.
  */

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/EmptyFileException.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/EmptyFileException.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/EmptyFileException.java
new file mode 100644
index 0000000..065776a
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/EmptyFileException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.math.exceptions.knn;
+
+import org.apache.ignite.IgniteException;
+
+/**
+ * Shows empty filename.
+ */
+public class EmptyFileException extends IgniteException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * Creates new exception.
+     *
+     * @param filename Name of the file without content.
+     */
+    public EmptyFileException(String filename) {
+        super("Empty file with filename " +  filename);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/FileParsingException.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/FileParsingException.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/FileParsingException.java
new file mode 100644
index 0000000..12c8fe3
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/FileParsingException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.math.exceptions.knn;
+
+import java.nio.file.Path;
+import org.apache.ignite.IgniteException;
+
+/**
+ * Shows non-parsed data in specific row by given file path.
+ */
+public class FileParsingException extends IgniteException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * Creates new exception.
+     * @param parsedData Data to parse.
+     * @param rowIdx Index of row in file.
+     * @param file File path
+     */
+    public FileParsingException(String parsedData, int rowIdx, Path file) {
+        super("Data " + parsedData + " in row # " + rowIdx + " in file " + file + " can not be parsed to appropriate format");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/NoLabelVectorException.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/NoLabelVectorException.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/NoLabelVectorException.java
new file mode 100644
index 0000000..7815e0f
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/NoLabelVectorException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.math.exceptions.knn;
+
+import org.apache.ignite.IgniteException;
+
+/**
+ * Shows Labeled Dataset index with non-existing Labeled Vector.
+ */
+public class NoLabelVectorException extends IgniteException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * Creates new exception.
+     *
+     * @param idx index of missed Labeled vector.
+     */
+    public NoLabelVectorException(int idx) {
+        super("No vector in position" + idx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/SmallTrainingDatasetSizeException.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/SmallTrainingDatasetSizeException.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/SmallTrainingDatasetSizeException.java
new file mode 100644
index 0000000..5eb3f7a
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/SmallTrainingDatasetSizeException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.math.exceptions.knn;
+
+import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
+
+/**
+ * Indicates a small training dataset size in ML algorithms.
+ */
+public class SmallTrainingDatasetSizeException extends MathIllegalArgumentException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * Creates new small training dataset size exception.
+     *
+     * @param exp Expected dataset size.
+     * @param act Actual dataset size.
+     */
+    public SmallTrainingDatasetSizeException(int exp, int act) {
+        super("Small training dataset size [expected=%d, actual=%d]", exp, act);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/package-info.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/package-info.java
new file mode 100644
index 0000000..e55b7b9
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/knn/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains exceptions for kNN algorithms.
+ */
+package org.apache.ignite.ml.math.exceptions.knn;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledDataset.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledDataset.java b/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledDataset.java
new file mode 100644
index 0000000..81f7607
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledDataset.java
@@ -0,0 +1,457 @@
+/*
+ * 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.structures;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.ignite.ml.knn.models.Normalization;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.exceptions.NoDataException;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.exceptions.knn.EmptyFileException;
+import org.apache.ignite.ml.math.exceptions.knn.FileParsingException;
+import org.apache.ignite.ml.math.exceptions.knn.NoLabelVectorException;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Class for set of labeled vectors.
+ */
+public class LabeledDataset implements Serializable {
+    /** Data to keep. */
+    private final LabeledVector[] data;
+
+    /** Feature names (one name for each attribute in vector). */
+    private String[] featureNames;
+
+    /** Amount of instances. */
+    private int rowSize;
+
+    /** Amount of attributes in each vector. */
+    private int colSize;
+
+    /**
+     * Creates new Labeled Dataset by given data.
+     *
+     * @param data Should be initialized with one vector at least.
+     * @param colSize Amount of observed attributes in each vector.
+     */
+    public LabeledDataset(LabeledVector[] data, int colSize) {
+        this(data, null, colSize);
+    }
+
+    /**
+     * Creates new Labeled Dataset by given data.
+     *
+     * @param data Given data. Should be initialized with one vector at least.
+     * @param featureNames Column names.
+     * @param colSize Amount of observed attributes in each vector.
+     */
+    public LabeledDataset(LabeledVector[] data, String[] featureNames, int colSize) {
+        assert data != null;
+        assert data.length > 0;
+
+        this.data = data;
+        this.rowSize = data.length;
+        this.colSize = colSize;
+
+        if(featureNames == null) generateFeatureNames();
+        else {
+            assert colSize == featureNames.length;
+            this.featureNames = featureNames;
+        }
+
+    }
+
+    /**
+     * Creates new Labeled Dataset and initialized with empty data structure.
+     *
+     * @param rowSize Amount of instances. Should be > 0.
+     * @param colSize Amount of attributes. Should be > 0.
+     * @param isDistributed Use distributed data structures to keep data.
+     */
+    public LabeledDataset(int rowSize, int colSize,  boolean isDistributed){
+        this(rowSize, colSize, null, isDistributed);
+    }
+
+    /**
+     * Creates new local Labeled Dataset and initialized with empty data structure.
+     *
+     * @param rowSize Amount of instances. Should be > 0.
+     * @param colSize Amount of attributes. Should be > 0.
+     */
+    public LabeledDataset(int rowSize, int colSize){
+        this(rowSize, colSize, null, false);
+    }
+
+    /**
+     * Creates new Labeled Dataset and initialized with empty data structure.
+     *
+     * @param rowSize Amount of instances. Should be > 0.
+     * @param colSize Amount of attributes. Should be > 0
+     * @param featureNames Column names.
+     * @param isDistributed Use distributed data structures to keep data.
+     */
+    public LabeledDataset(int rowSize, int colSize, String[] featureNames, boolean isDistributed){
+        assert rowSize > 0;
+        assert colSize > 0;
+
+        if(featureNames == null) generateFeatureNames();
+        else {
+            assert colSize == featureNames.length;
+            this.featureNames = featureNames;
+        }
+
+        this.rowSize = rowSize;
+        this.colSize = colSize;
+
+        data = new LabeledVector[rowSize];
+        for (int i = 0; i < rowSize; i++)
+            data[i] = new LabeledVector(getVector(colSize, isDistributed), null);
+
+    }
+
+
+    /**
+     * Creates new local Labeled Dataset by matrix and vector of labels.
+     *
+     * @param mtx Given matrix with rows as observations.
+     * @param lbs Labels of observations.
+     */
+    public LabeledDataset(double[][] mtx, double[] lbs) {
+       this(mtx, lbs, null, false);
+    }
+
+    /**
+     * Creates new Labeled Dataset by matrix and vector of labels.
+     *
+     * @param mtx Given matrix with rows as observations.
+     * @param lbs Labels of observations.
+     * @param featureNames Column names.
+     * @param isDistributed Use distributed data structures to keep data.
+     */
+    public LabeledDataset(double[][] mtx, double[] lbs, String[] featureNames, boolean isDistributed) {
+        assert mtx != null;
+        assert lbs != null;
+
+        if(mtx.length != lbs.length)
+            throw new CardinalityException(lbs.length, mtx.length);
+
+        if(mtx[0] == null)
+            throw new NoDataException("Pass filled array, the first vector is empty");
+
+        this.rowSize = lbs.length;
+        this.colSize = mtx[0].length;
+
+        if(featureNames == null) generateFeatureNames();
+        else this.featureNames = featureNames;
+
+
+        data = new LabeledVector[rowSize];
+        for (int i = 0; i < rowSize; i++){
+
+            data[i] = new LabeledVector(getVector(colSize, isDistributed), lbs[i]);
+            for (int j = 0; j < colSize; j++) {
+                try {
+                    data[i].features().set(j, mtx[i][j]);
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    throw new NoDataException("No data in given matrix by coordinates (" + i + "," + j + ")");
+                }
+            }
+        }
+    }
+
+    /** */
+    private void generateFeatureNames() {
+        featureNames = new String[colSize];
+
+        for (int i = 0; i < colSize; i++)
+            featureNames[i] = "f_" + i;
+    }
+
+
+    /**
+     * Get vectors and their labels.
+     *
+     * @return Array of Label Vector instances.
+     */
+    public LabeledVector[] data() {
+        return data;
+    }
+
+    /**
+     * Gets amount of observation.
+     *
+     * @return Amount of rows in dataset.
+     */
+    public int rowSize(){
+        return rowSize;
+    }
+
+    /**
+     * Returns feature name for column with given index.
+     *
+     * @param i The given index.
+     * @return Feature name.
+     */
+    public String getFeatureName(int i){
+        return featureNames[i];
+    }
+
+    /**
+     * Gets amount of attributes.
+     *
+     * @return Amount of attributes in each Labeled Vector.
+     */
+    public int colSize(){
+        return colSize;
+    }
+
+    /**
+     * Retrieves Labeled Vector by given index.
+     *
+     * @param idx Index of observation.
+     * @return Labeled features.
+     */
+    public LabeledVector getRow(int idx){
+        return data[idx];
+    }
+
+    /**
+     * Get the features.
+     *
+     * @param idx Index of observation.
+     * @return Vector with features.
+     */
+    public Vector features(int idx){
+        assert idx < rowSize;
+        assert data != null;
+        assert data[idx] != null;
+
+        return data[idx].features();
+    }
+
+    /**
+     * Returns label if label is attached or null if label is missed.
+     *
+     * @param idx Index of observation.
+     * @return Label.
+     */
+    public double label(int idx) {
+        LabeledVector labeledVector = data[idx];
+
+        if(labeledVector!=null)
+            return (double)labeledVector.label();
+        else
+            return Double.NaN;
+    }
+
+    /**
+     * Fill the label with given value.
+     *
+     * @param idx Index of observation.
+     * @param lb The given label.
+     */
+    public void setLabel(int idx, double lb) {
+        LabeledVector labeledVector = data[idx];
+
+        if(labeledVector != null)
+            labeledVector.setLabel(lb);
+        else
+            throw new NoLabelVectorException(idx);
+    }
+
+    /**
+     * Datafile should keep class labels in the first column.
+     *
+     * @param pathToFile Path to file.
+     * @param separator Element to tokenize row on separate tokens.
+     * @param isDistributed Generates distributed dataset if true.
+     * @param isFallOnBadData Fall on incorrect data if true.
+     * @return Labeled Dataset parsed from file.
+     */
+    public static LabeledDataset loadTxt(Path pathToFile, String separator, boolean isDistributed, boolean isFallOnBadData) throws IOException {
+        Stream<String> stream = Files.lines(pathToFile);
+        List<String> list = new ArrayList<>();
+        stream.forEach(list::add);
+
+        final int rowSize = list.size();
+
+        List<Double> labels = new ArrayList<>();
+        List<Vector> vectors = new ArrayList<>();
+
+        if (rowSize > 0) {
+
+            final int colSize = getColumnSize(separator, list) - 1;
+
+            if (colSize > 0) {
+
+                for (int i = 0; i < rowSize; i++) {
+                    Double clsLb;
+
+                    String[] rowData = list.get(i).split(separator);
+
+                    try {
+                        clsLb = Double.parseDouble(rowData[0]);
+                        Vector vec = parseFeatures(pathToFile, isDistributed, isFallOnBadData, colSize, i, rowData);
+                        labels.add(clsLb);
+                        vectors.add(vec);
+                    }
+                    catch (NumberFormatException e) {
+                        if(isFallOnBadData)
+                            throw new FileParsingException(rowData[0], i, pathToFile);
+                    }
+                }
+
+                LabeledVector[] data = new LabeledVector[vectors.size()];
+                for (int i = 0; i < vectors.size(); i++)
+                    data[i] = new LabeledVector(vectors.get(i), labels.get(i));
+
+                return new LabeledDataset(data, colSize);
+            }
+            else
+                throw new NoDataException("File should contain first row with data");
+        }
+        else
+            throw new EmptyFileException(pathToFile.toString());
+    }
+
+    /** */
+    @NotNull private static Vector parseFeatures(Path pathToFile, boolean isDistributed, boolean isFallOnBadData,
+        int colSize, int rowIdx, String[] rowData) {
+        final Vector vec = getVector(colSize, isDistributed);
+
+        for (int j = 0; j < colSize; j++) {
+
+            if (rowData.length == colSize + 1) {
+                double val = fillMissedData();
+
+                try {
+                    val = Double.parseDouble(rowData[j + 1]);
+                    vec.set(j, val);
+                }
+                catch (NumberFormatException e) {
+                    if(isFallOnBadData)
+                        throw new FileParsingException(rowData[j + 1], rowIdx, pathToFile);
+                    else
+                        vec.set(j,val);
+                }
+            }
+            else throw new CardinalityException(colSize + 1, rowData.length);
+        }
+        return vec;
+    }
+
+    // TODO: IGNITE-7025 add filling with mean, mode, ignoring and so on
+    /** */
+    private static double fillMissedData() {
+            return 0.0;
+    }
+
+    /** */
+    @NotNull private static Vector getVector(int size, boolean isDistributed) {
+
+        if(isDistributed) return new SparseBlockDistributedVector(size);
+        else return new DenseLocalOnHeapVector(size);
+    }
+
+    /** */
+    private static int getColumnSize(String separator, List<String> list) {
+        String[] rowData = list.get(0).split(separator, -1); // assume that all observation has the same length as a first row
+
+        return rowData.length;
+    }
+
+    /**
+     * Scales features in dataset.
+     *
+     * @param normalization normalization approach
+     * @return Labeled dataset
+     */
+    public LabeledDataset normalizeWith(Normalization normalization) {
+        switch (normalization){
+            case MINIMAX: minMaxFeatures();
+                break;
+            case Z_NORMALIZATION: throw new UnsupportedOperationException("Z-normalization is not supported yet");
+        }
+
+        return this;
+    }
+
+    /**
+     * Complexity 2*N^2. Try to optimize.
+     */
+    private void minMaxFeatures() {
+        double[] mins = new double[colSize];
+        double[] maxs = new double[colSize];
+
+        for (int j = 0; j < colSize; j++) {
+            double maxInCurrCol = Double.MIN_VALUE;
+            double minInCurrCol = Double.MAX_VALUE;
+
+            for (int i = 0; i < rowSize; i++) {
+                double e = data[i].features().get(j);
+                maxInCurrCol = Math.max(e, maxInCurrCol);
+                minInCurrCol = Math.min(e, minInCurrCol);
+            }
+
+            mins[j] = minInCurrCol;
+            maxs[j] = maxInCurrCol;
+        }
+
+        for (int j = 0; j < colSize; j++) {
+            double div = maxs[j] - mins[j];
+
+            for (int i = 0; i < rowSize; i++) {
+                double oldVal = data[i].features().get(j);
+                double newVal = (oldVal - mins[j])/div;
+                // x'=(x-MIN[X])/(MAX[X]-MIN[X])
+                data[i].features().set(j, newVal);
+            }
+        }
+    }
+
+    /** */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        LabeledDataset that = (LabeledDataset)o;
+
+        return rowSize == that.rowSize && colSize == that.colSize && Arrays.equals(data, that.data) && Arrays.equals(featureNames, that.featureNames);
+    }
+
+    /** */
+    @Override public int hashCode() {
+        int res = Arrays.hashCode(data);
+        res = 31 * res + Arrays.hashCode(featureNames);
+        res = 31 * res + rowSize;
+        res = 31 * res + colSize;
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ba773bf/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledVector.java
index 51b973a..a4e218b 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/structures/LabeledVector.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.ml.structures;
 
+import java.io.Serializable;
 import org.apache.ignite.ml.math.Vector;
 
 /**
@@ -25,12 +26,12 @@ import org.apache.ignite.ml.math.Vector;
  * @param <V> Some class extending {@link Vector}.
  * @param <T> Type of label.
  */
-public class LabeledVector<V extends Vector, T> {
+public class LabeledVector<V extends Vector, T> implements Serializable {
     /** Vector. */
     private final V vector;
 
     /** Label. */
-    private final T lb;
+    private T lb;
 
     /**
      * Construct labeled vector.
@@ -48,7 +49,7 @@ public class LabeledVector<V extends Vector, T> {
      *
      * @return Vector.
      */
-    public V vector() {
+    public V features() {
         return vector;
     }
 
@@ -60,4 +61,34 @@ public class LabeledVector<V extends Vector, T> {
     public T label() {
         return lb;
     }
+
+    /**
+     * Set the label
+     *
+     * @param lb Label.
+     */
+    public void setLabel(T lb) {
+        this.lb = lb;
+    }
+
+    /** */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        LabeledVector vector1 = (LabeledVector)o;
+
+        if (vector != null ? !vector.equals(vector1.vector) : vector1.vector != null)
+            return false;
+        return lb != null ? lb.equals(vector1.lb) : vector1.lb == null;
+    }
+
+    /** */
+    @Override public int hashCode() {
+        int res = vector != null ? vector.hashCode() : 0;
+        res = 31 * res + (lb != null ? lb.hashCode() : 0);
+        return res;
+    }
 }