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 2018/02/12 19:30:38 UTC
ignite git commit: IGNITE-7451: Make Linear SVM for
multi-classification
Repository: ignite
Updated Branches:
refs/heads/master 6f6f8dd3e -> c66196378
IGNITE-7451: Make Linear SVM for multi-classification
this closes #3484
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c6619637
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c6619637
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c6619637
Branch: refs/heads/master
Commit: c661963784fe3a15b9404e10da37df015acc95ab
Parents: 6f6f8dd
Author: zaleslaw <za...@gmail.com>
Authored: Mon Feb 12 22:30:22 2018 +0300
Committer: YuriBabak <y....@gmail.com>
Committed: Mon Feb 12 22:30:22 2018 +0300
----------------------------------------------------------------------
.../ml/svm/SVMBinaryClassificationExample.java | 11 +-
.../ignite/ml/structures/LabeledDataset.java | 12 +-
.../svm/SVMLinearBinaryClassificationModel.java | 184 +++++++++++++++++++
.../SVMLinearBinaryClassificationTrainer.java | 6 +-
.../ml/svm/SVMLinearClassificationModel.java | 176 ------------------
.../SVMLinearMultiClassClassificationModel.java | 89 +++++++++
...VMLinearMultiClassClassificationTrainer.java | 160 ++++++++++++++++
.../org/apache/ignite/ml/LocalModelsTest.java | 39 +++-
...dLinearSVMClassificationSCDATrainerTest.java | 34 ----
.../ml/svm/GenericLinearSVMTrainerTest.java | 139 --------------
...lLinearSVMClassificationSCDATrainerTest.java | 37 ----
.../org/apache/ignite/ml/svm/SVMModelTest.java | 24 ++-
.../org/apache/ignite/ml/svm/SVMTestSuite.java | 10 +-
...inearSVMBinaryClassificationTrainerTest.java | 35 ++++
...inearSVMBinaryClassificationTrainerTest.java | 141 ++++++++++++++
...inearSVMBinaryClassificationTrainerTest.java | 38 ++++
...rSVMMultiClassClassificationTrainerTest.java | 35 ++++
...rSVMMultiClassClassificationTrainerTest.java | 76 ++++++++
...rSVMMultiClassClassificationTrainerTest.java | 38 ++++
19 files changed, 876 insertions(+), 408 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/examples/src/main/java/org/apache/ignite/examples/ml/svm/SVMBinaryClassificationExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/ignite/examples/ml/svm/SVMBinaryClassificationExample.java b/examples/src/main/java/org/apache/ignite/examples/ml/svm/SVMBinaryClassificationExample.java
index 979afe2..e256276 100644
--- a/examples/src/main/java/org/apache/ignite/examples/ml/svm/SVMBinaryClassificationExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/ml/svm/SVMBinaryClassificationExample.java
@@ -19,10 +19,7 @@ package org.apache.ignite.examples.ml.svm;
import java.io.File;
import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
import java.nio.file.Path;
-import java.nio.file.Paths;
import org.apache.ignite.Ignite;
import org.apache.ignite.Ignition;
import org.apache.ignite.examples.ExampleNodeStartup;
@@ -33,13 +30,13 @@ import org.apache.ignite.ml.structures.LabeledDatasetTestTrainPair;
import org.apache.ignite.ml.structures.preprocessing.LabeledDatasetLoader;
import org.apache.ignite.ml.structures.preprocessing.LabellingMachine;
import org.apache.ignite.ml.structures.preprocessing.Normalizer;
+import org.apache.ignite.ml.svm.SVMLinearBinaryClassificationModel;
import org.apache.ignite.ml.svm.SVMLinearBinaryClassificationTrainer;
-import org.apache.ignite.ml.svm.SVMLinearClassificationModel;
import org.apache.ignite.thread.IgniteThread;
/**
* <p>
- * Example of using {@link org.apache.ignite.ml.svm.SVMLinearClassificationModel} with Titanic dataset.</p>
+ * Example of using {@link org.apache.ignite.ml.svm.SVMLinearBinaryClassificationModel} with Titanic dataset.</p>
* <p>
* Note that in this example we cannot guarantee order in which nodes return results of intermediate
* computations and therefore algorithm can return different results.</p>
@@ -95,10 +92,10 @@ public class SVMBinaryClassificationExample {
LabeledDataset train = split.train();
System.out.println("\n>>> Create new linear binary SVM trainer object.");
- Trainer<SVMLinearClassificationModel, LabeledDataset> trainer = new SVMLinearBinaryClassificationTrainer();
+ Trainer<SVMLinearBinaryClassificationModel, LabeledDataset> trainer = new SVMLinearBinaryClassificationTrainer();
System.out.println("\n>>> Perform the training to get the model.");
- SVMLinearClassificationModel mdl = trainer.train(train);
+ SVMLinearBinaryClassificationModel mdl = trainer.train(train);
System.out.println("\n>>> SVM classification model: " + mdl);
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/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
index 15e8c40..0028a16 100644
--- 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
@@ -191,10 +191,20 @@ public class LabeledDataset<L, Row extends LabeledVector> extends Dataset<Row> {
/** */
public static Vector emptyVector(int size, boolean isDistributed) {
-
if(isDistributed)
return new SparseDistributedVector(size);
else
return new DenseLocalOnHeapVector(size);
}
+
+ /** Makes copy with new Label objects and old features and Metadata objects. */
+ public LabeledDataset copy(){
+ LabeledDataset res = new LabeledDataset(this.data, this.colSize);
+ res.isDistributed = this.isDistributed;
+ res.meta = this.meta;
+ for (int i = 0; i < rowSize; i++)
+ res.setLabel(i, this.label(i));
+
+ return res;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationModel.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationModel.java b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationModel.java
new file mode 100644
index 0000000..6d93402
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationModel.java
@@ -0,0 +1,184 @@
+/*
+ * 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.svm;
+
+import java.io.Serializable;
+import java.util.Objects;
+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;
+
+/**
+ * Base class for SVM linear classification model.
+ */
+public class SVMLinearBinaryClassificationModel implements Model<Vector, Double>, Exportable<SVMLinearBinaryClassificationModel>, Serializable {
+ /** Output label format. -1 and +1 for false value and raw distances from the separating hyperplane otherwise. */
+ private boolean isKeepingRawLabels = false;
+
+ /** Threshold to assign +1 label to the observation if raw value more than this threshold. */
+ private double threshold = 0.0;
+
+ /** Multiplier of the objects's vector required to make prediction. */
+ private Vector weights;
+
+ /** Intercept of the linear regression model. */
+ private double intercept;
+
+ /** */
+ public SVMLinearBinaryClassificationModel(Vector weights, double intercept) {
+ this.weights = weights;
+ this.intercept = intercept;
+ }
+
+ /**
+ * Set up the output label format.
+ *
+ * @param isKeepingRawLabels The parameter value.
+ * @return Model with new isKeepingRawLabels parameter value.
+ */
+ public SVMLinearBinaryClassificationModel withRawLabels(boolean isKeepingRawLabels) {
+ this.isKeepingRawLabels = isKeepingRawLabels;
+ return this;
+ }
+
+ /**
+ * Set up the threshold.
+ *
+ * @param threshold The parameter value.
+ * @return Model with new threshold parameter value.
+ */
+ public SVMLinearBinaryClassificationModel withThreshold(double threshold) {
+ this.threshold = threshold;
+ return this;
+ }
+
+ /**
+ * Set up the weights.
+ *
+ * @param weights The parameter value.
+ * @return Model with new weights parameter value.
+ */
+ public SVMLinearBinaryClassificationModel withWeights(Vector weights) {
+ this.weights = weights;
+ return this;
+ }
+
+ /**
+ * Set up the intercept.
+ *
+ * @param intercept The parameter value.
+ * @return Model with new intercept parameter value.
+ */
+ public SVMLinearBinaryClassificationModel withIntercept(double intercept) {
+ this.intercept = intercept;
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Double apply(Vector input) {
+ final double res = input.dot(weights) + intercept;
+ if (isKeepingRawLabels)
+ return res;
+ else
+ return res - threshold > 0 ? 1.0 : -1.0;
+ }
+
+ /**
+ * Gets the output label format mode.
+ *
+ * @return The parameter value.
+ */
+ public boolean isKeepingRawLabels() {
+ return isKeepingRawLabels;
+ }
+
+ /**
+ * Gets the threshold.
+ *
+ * @return The parameter value.
+ */
+ public double threshold() {
+ return threshold;
+ }
+
+ /**
+ * Gets the weights.
+ *
+ * @return The parameter value.
+ */
+ public Vector weights() {
+ return weights;
+ }
+
+ /**
+ * Gets the intercept.
+ *
+ * @return The parameter value.
+ */
+ public double intercept() {
+ return intercept;
+ }
+
+ /** {@inheritDoc} */
+ @Override public <P> void saveModel(Exporter<SVMLinearBinaryClassificationModel, P> exporter, P path) {
+ exporter.save(this, path);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ SVMLinearBinaryClassificationModel mdl = (SVMLinearBinaryClassificationModel)o;
+ return Double.compare(mdl.intercept, intercept) == 0
+ && Double.compare(mdl.threshold, threshold) == 0
+ && Boolean.compare(mdl.isKeepingRawLabels, isKeepingRawLabels) == 0
+ && Objects.equals(weights, mdl.weights);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return Objects.hash(weights, intercept, isKeepingRawLabels, threshold);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ if (weights.size() < 10) {
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < weights.size(); i++) {
+ double nextItem = i == weights.size() - 1 ? intercept : weights.get(i + 1);
+
+ builder.append(String.format("%.4f", Math.abs(weights.get(i))))
+ .append("*x")
+ .append(i)
+ .append(nextItem > 0 ? " + " : " - ");
+ }
+
+ builder.append(String.format("%.4f", Math.abs(intercept)));
+ return builder.toString();
+ }
+
+ return "LinearRegressionModel{" +
+ "weights=" + weights +
+ ", intercept=" + intercept +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationTrainer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationTrainer.java b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationTrainer.java
index a14694b..ee3b6e8 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationTrainer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearBinaryClassificationTrainer.java
@@ -32,7 +32,7 @@ import org.jetbrains.annotations.NotNull;
* and +1 labels for two classes and makes binary classification. </p> The paper about this algorithm could be found
* here https://arxiv.org/abs/1409.1458.
*/
-public class SVMLinearBinaryClassificationTrainer implements Trainer<SVMLinearClassificationModel, LabeledDataset> {
+public class SVMLinearBinaryClassificationTrainer implements Trainer<SVMLinearBinaryClassificationModel, LabeledDataset> {
/** Amount of outer SDCA algorithm iterations. */
private int amountOfIterations = 20;
@@ -51,7 +51,7 @@ public class SVMLinearBinaryClassificationTrainer implements Trainer<SVMLinearCl
* @param data data to build model
* @return model
*/
- @Override public SVMLinearClassificationModel train(LabeledDataset data) {
+ @Override public SVMLinearBinaryClassificationModel train(LabeledDataset data) {
isDistributed = data.isDistributed();
final int weightVectorSizeWithIntercept = data.colSize() + 1;
@@ -62,7 +62,7 @@ public class SVMLinearBinaryClassificationTrainer implements Trainer<SVMLinearCl
weights = weights.plus(deltaWeights); // creates new vector
}
- return new SVMLinearClassificationModel(weights.viewPart(1, weights.size() - 1), weights.get(0));
+ return new SVMLinearBinaryClassificationModel(weights.viewPart(1, weights.size() - 1), weights.get(0));
}
/** */
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearClassificationModel.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearClassificationModel.java b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearClassificationModel.java
deleted file mode 100644
index e807128..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearClassificationModel.java
+++ /dev/null
@@ -1,176 +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.svm;
-
-import java.io.Serializable;
-import java.util.Objects;
-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;
-
-/**
- * Base class for SVM linear classification model.
- */
-public class SVMLinearClassificationModel implements Model<Vector, Double>, Exportable<SVMLinearClassificationModel>, Serializable {
- /** Output label format. -1 and +1 for false value and raw distances from the separating hyperplane otherwise. */
- private boolean isKeepingRawLabels = false;
-
- /** Threshold to assign +1 label to the observation if raw value more than this threshold. */
- private double threshold = 0.0;
-
- /** Multiplier of the objects's vector required to make prediction. */
- private Vector weights;
-
- /** Intercept of the linear regression model. */
- private double intercept;
-
- /** */
- public SVMLinearClassificationModel(Vector weights, double intercept) {
- this.weights = weights;
- this.intercept = intercept;
- }
-
- /**
- * Set up the output label format.
- * @param isKeepingRawLabels The parameter value.
- * @return Model with new isKeepingRawLabels parameter value.
- */
- public SVMLinearClassificationModel withRawLabels(boolean isKeepingRawLabels) {
- this.isKeepingRawLabels = isKeepingRawLabels;
- return this;
- }
-
- /**
- * Set up the threshold.
- * @param threshold The parameter value.
- * @return Model with new threshold parameter value.
- */
- public SVMLinearClassificationModel withThreshold(double threshold) {
- this.threshold = threshold;
- return this;
- }
-
- /**
- * Set up the weights.
- * @param weights The parameter value.
- * @return Model with new weights parameter value.
- */
- public SVMLinearClassificationModel withWeights(Vector weights) {
- this.weights = weights;
- return this;
- }
-
- /**
- * Set up the intercept.
- * @param intercept The parameter value.
- * @return Model with new intercept parameter value.
- */
- public SVMLinearClassificationModel withIntercept(double intercept) {
- this.intercept = intercept;
- return this;
- }
-
- /** {@inheritDoc} */
- @Override public Double apply(Vector input) {
- final double res = input.dot(weights) + intercept;
- if (isKeepingRawLabels)
- return res;
- else
- return res - threshold > 0 ? 1.0 : -1.0;
- }
-
- /**
- * Gets the output label format mode.
- * @return The parameter value.
- */
- public boolean isKeepingRawLabels() {
- return isKeepingRawLabels;
- }
-
- /**
- * Gets the threshold.
- * @return The parameter value.
- */
- public double threshold() {
- return threshold;
- }
-
- /**
- * Gets the weights.
- * @return The parameter value.
- */
- public Vector weights() {
- return weights;
- }
-
- /**
- * Gets the intercept.
- * @return The parameter value.
- */
- public double intercept() {
- return intercept;
- }
-
- /** {@inheritDoc} */
- @Override public <P> void saveModel(Exporter<SVMLinearClassificationModel, P> exporter, P path) {
- exporter.save(this, path);
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(Object o) {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
- SVMLinearClassificationModel mdl = (SVMLinearClassificationModel)o;
- return Double.compare(mdl.intercept, intercept) == 0
- && Double.compare(mdl.threshold, threshold) == 0
- && Boolean.compare(mdl.isKeepingRawLabels, isKeepingRawLabels) == 0
- && Objects.equals(weights, mdl.weights);
- }
-
- /** {@inheritDoc} */
- @Override public int hashCode() {
- return Objects.hash(weights, intercept, isKeepingRawLabels, threshold);
- }
-
- /** {@inheritDoc} */
- @Override public String toString() {
- if (weights.size() < 10) {
- StringBuilder builder = new StringBuilder();
-
- for (int i = 0; i < weights.size(); i++) {
- double nextItem = i == weights.size() - 1 ? intercept : weights.get(i + 1);
-
- builder.append(String.format("%.4f", Math.abs(weights.get(i))))
- .append("*x")
- .append(i)
- .append(nextItem > 0 ? " + " : " - ");
- }
-
- builder.append(String.format("%.4f", Math.abs(intercept)));
- return builder.toString();
- }
-
- return "LinearRegressionModel{" +
- "weights=" + weights +
- ", intercept=" + intercept +
- '}';
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationModel.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationModel.java b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationModel.java
new file mode 100644
index 0000000..fd91595
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationModel.java
@@ -0,0 +1,89 @@
+/*
+ * 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.svm;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+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;
+
+/** Base class for multi-classification model for set of SVM classifiers. */
+public class SVMLinearMultiClassClassificationModel implements Model<Vector, Double>, Exportable<SVMLinearMultiClassClassificationModel>, Serializable {
+ /** List of models associated with each class. */
+ private Map<Double, SVMLinearBinaryClassificationModel> models;
+
+ /** */
+ public SVMLinearMultiClassClassificationModel() {
+ this.models = new HashMap<>();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Double apply(Vector input) {
+ TreeMap<Double, Double> maxMargins = new TreeMap<>();
+
+ models.forEach((k, v) -> maxMargins.put(input.dot(v.weights()) + v.intercept(), k));
+
+ return maxMargins.lastEntry().getValue();
+ }
+
+ /** {@inheritDoc} */
+ @Override public <P> void saveModel(Exporter<SVMLinearMultiClassClassificationModel, P> exporter, P path) {
+ exporter.save(this, path);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ SVMLinearMultiClassClassificationModel mdl = (SVMLinearMultiClassClassificationModel)o;
+ return Objects.equals(models, mdl.models);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return Objects.hash(models);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ StringBuilder wholeStr = new StringBuilder();
+
+ models.forEach((clsLb, mdl) -> {
+ wholeStr.append("The class with label " + clsLb + " has classifier: " + mdl.toString() + System.lineSeparator());
+ });
+
+ return wholeStr.toString();
+ }
+
+ /**
+ * Adds a specific SVM binary classifier to the bunch of same classifiers.
+ *
+ * @param clsLb The class label for the added model.
+ * @param mdl The model.
+ */
+ public void add(double clsLb, SVMLinearBinaryClassificationModel mdl) {
+ models.put(clsLb, mdl);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationTrainer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationTrainer.java b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationTrainer.java
new file mode 100644
index 0000000..669e2e3
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/svm/SVMLinearMultiClassClassificationTrainer.java
@@ -0,0 +1,160 @@
+/*
+ * 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.svm;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.ignite.ml.Trainer;
+import org.apache.ignite.ml.structures.LabeledDataset;
+
+/**
+ * Base class for a soft-margin SVM linear multiclass-classification trainer based on the communication-efficient
+ * distributed dual coordinate ascent algorithm (CoCoA) with hinge-loss function.
+ *
+ * All common parameters are shared with bunch of binary classification trainers.
+ */
+public class SVMLinearMultiClassClassificationTrainer implements Trainer<SVMLinearMultiClassClassificationModel, LabeledDataset> {
+ /** Amount of outer SDCA algorithm iterations. */
+ private int amountOfIterations = 20;
+
+ /** Amount of local SDCA algorithm iterations. */
+ private int amountOfLocIterations = 50;
+
+ /** Regularization parameter. */
+ private double lambda = 0.2;
+
+ /**
+ * Returns model based on data.
+ *
+ * @param data data to build model.
+ * @return model.
+ */
+ @Override public SVMLinearMultiClassClassificationModel train(LabeledDataset data) {
+ List<Double> classes = getClassLabels(data);
+
+ SVMLinearMultiClassClassificationModel multiClsMdl = new SVMLinearMultiClassClassificationModel();
+
+ classes.forEach(clsLb -> {
+ LabeledDataset binarizedDataset = binarizeLabels(data, clsLb);
+
+ SVMLinearBinaryClassificationTrainer trainer = new SVMLinearBinaryClassificationTrainer()
+ .withAmountOfIterations(this.amountOfIterations())
+ .withAmountOfLocIterations(this.amountOfLocIterations())
+ .withLambda(this.lambda());
+
+ multiClsMdl.add(clsLb, trainer.train(binarizedDataset));
+ });
+
+ return multiClsMdl;
+ }
+
+ /**
+ * Copies the given data and changes class labels in +1 for chosen class and in -1 for the rest classes.
+ *
+ * @param data Data to transform.
+ * @param clsLb Chosen class in schema One-vs-Rest.
+ * @return Copy of dataset with new labels.
+ */
+ private LabeledDataset binarizeLabels(LabeledDataset data, double clsLb) {
+ final LabeledDataset ds = data.copy();
+
+ for (int i = 0; i < ds.rowSize(); i++)
+ ds.setLabel(i, ds.label(i) == clsLb ? 1.0 : -1.0);
+
+ return ds;
+ }
+
+ /** Iterates among dataset and collects class labels. */
+ private List<Double> getClassLabels(LabeledDataset data) {
+ final Set<Double> clsLabels = new HashSet<>();
+
+ for (int i = 0; i < data.rowSize(); i++)
+ clsLabels.add(data.label(i));
+
+ List<Double> res = new ArrayList<>();
+ res.addAll(clsLabels);
+
+ return res;
+ }
+
+ /**
+ * Set up the regularization parameter.
+ *
+ * @param lambda The regularization parameter. Should be more than 0.0.
+ * @return Trainer with new lambda parameter value.
+ */
+ public SVMLinearMultiClassClassificationTrainer withLambda(double lambda) {
+ assert lambda > 0.0;
+ this.lambda = lambda;
+ return this;
+ }
+
+ /**
+ * Gets the regularization lambda.
+ *
+ * @return The parameter value.
+ */
+ public double lambda() {
+ return lambda;
+ }
+
+ /**
+ * Gets the amount of outer iterations of SCDA algorithm.
+ *
+ * @return The parameter value.
+ */
+ public int amountOfIterations() {
+ return amountOfIterations;
+ }
+
+ /**
+ * Set up the amount of outer iterations of SCDA algorithm.
+ *
+ * @param amountOfIterations The parameter value.
+ * @return Trainer with new amountOfIterations parameter value.
+ */
+ public SVMLinearMultiClassClassificationTrainer withAmountOfIterations(int amountOfIterations) {
+ this.amountOfIterations = amountOfIterations;
+ return this;
+ }
+
+ /**
+ * Gets the amount of local iterations of SCDA algorithm.
+ *
+ * @return The parameter value.
+ */
+ public int amountOfLocIterations() {
+ return amountOfLocIterations;
+ }
+
+ /**
+ * Set up the amount of local iterations of SCDA algorithm.
+ *
+ * @param amountOfLocIterations The parameter value.
+ * @return Trainer with new amountOfLocIterations parameter value.
+ */
+ public SVMLinearMultiClassClassificationTrainer withAmountOfLocIterations(int amountOfLocIterations) {
+ this.amountOfLocIterations = amountOfLocIterations;
+ return this;
+ }
+}
+
+
+
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/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 bcbc1fc..57d93d6 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
@@ -31,7 +31,8 @@ import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
import org.apache.ignite.ml.regressions.linear.LinearRegressionModel;
import org.apache.ignite.ml.structures.LabeledDataset;
-import org.apache.ignite.ml.svm.SVMLinearClassificationModel;
+import org.apache.ignite.ml.svm.SVMLinearBinaryClassificationModel;
+import org.apache.ignite.ml.svm.SVMLinearMultiClassClassificationModel;
import org.junit.Assert;
import org.junit.Test;
@@ -80,13 +81,41 @@ public class LocalModelsTest {
/** */
@Test
- public void importExportSVMClassificationModelTest() throws IOException {
+ public void importExportSVMBinaryClassificationModelTest() throws IOException {
executeModelTest(mdlFilePath -> {
- SVMLinearClassificationModel mdl = new SVMLinearClassificationModel(new DenseLocalOnHeapVector(new double[]{1, 2}), 3);
- Exporter<SVMLinearClassificationModel, String> exporter = new FileExporter<>();
+ SVMLinearBinaryClassificationModel mdl = new SVMLinearBinaryClassificationModel(new DenseLocalOnHeapVector(new double[]{1, 2}), 3);
+ Exporter<SVMLinearBinaryClassificationModel, String> exporter = new FileExporter<>();
mdl.saveModel(exporter, mdlFilePath);
- SVMLinearClassificationModel load = exporter.load(mdlFilePath);
+ SVMLinearBinaryClassificationModel load = exporter.load(mdlFilePath);
+
+ Assert.assertNotNull(load);
+ Assert.assertEquals("", mdl, load);
+
+ return null;
+ });
+ }
+
+
+ /** */
+ @Test
+ public void importExportSVMMulticlassClassificationModelTest() throws IOException {
+ executeModelTest(mdlFilePath -> {
+
+
+ SVMLinearBinaryClassificationModel binaryMdl1 = new SVMLinearBinaryClassificationModel(new DenseLocalOnHeapVector(new double[]{1, 2}), 3);
+ SVMLinearBinaryClassificationModel binaryMdl2 = new SVMLinearBinaryClassificationModel(new DenseLocalOnHeapVector(new double[]{2, 3}), 4);
+ SVMLinearBinaryClassificationModel binaryMdl3 = new SVMLinearBinaryClassificationModel(new DenseLocalOnHeapVector(new double[]{3, 4}), 5);
+
+ SVMLinearMultiClassClassificationModel mdl = new SVMLinearMultiClassClassificationModel();
+ mdl.add(1, binaryMdl1);
+ mdl.add(2, binaryMdl2);
+ mdl.add(3, binaryMdl3);
+
+ Exporter<SVMLinearMultiClassClassificationModel, String> exporter = new FileExporter<>();
+ mdl.saveModel(exporter, mdlFilePath);
+
+ SVMLinearMultiClassClassificationModel load = exporter.load(mdlFilePath);
Assert.assertNotNull(load);
Assert.assertEquals("", mdl, load);
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/DistributedLinearSVMClassificationSCDATrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/DistributedLinearSVMClassificationSCDATrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/DistributedLinearSVMClassificationSCDATrainerTest.java
deleted file mode 100644
index a4a91a4..0000000
--- a/modules/ml/src/test/java/org/apache/ignite/ml/svm/DistributedLinearSVMClassificationSCDATrainerTest.java
+++ /dev/null
@@ -1,34 +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.svm;
-
-import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
-import org.apache.ignite.ml.regressions.linear.LinearRegressionSGDTrainer;
-
-/**
- * Tests for {@link LinearRegressionSGDTrainer} on {@link DenseLocalOnHeapMatrix}.
- */
-public class DistributedLinearSVMClassificationSCDATrainerTest extends GenericLinearSVMTrainerTest {
- /** */
- public DistributedLinearSVMClassificationSCDATrainerTest() {
- super(
- new SVMLinearBinaryClassificationTrainer(),
- true,
- 1e-2);
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/GenericLinearSVMTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/GenericLinearSVMTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/GenericLinearSVMTrainerTest.java
deleted file mode 100644
index 1cd2a50..0000000
--- a/modules/ml/src/test/java/org/apache/ignite/ml/svm/GenericLinearSVMTrainerTest.java
+++ /dev/null
@@ -1,139 +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.svm;
-
-import java.util.concurrent.ThreadLocalRandom;
-import org.apache.ignite.internal.util.IgniteUtils;
-import org.apache.ignite.ml.TestUtils;
-import org.apache.ignite.ml.Trainer;
-import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
-import org.apache.ignite.ml.structures.LabeledDataset;
-import org.apache.ignite.ml.structures.LabeledVector;
-import org.junit.Test;
-
-/**
- * Base class for all linear regression trainers.
- */
-public class GenericLinearSVMTrainerTest extends BaseSVMTest {
- /** Fixed size of Dataset. */
- private static final int AMOUNT_OF_OBSERVATIONS = 100;
-
- /** Fixed size of columns in Dataset. */
- private static final int AMOUNT_OF_FEATURES = 2;
-
- /** */
- private final Trainer<SVMLinearClassificationModel, LabeledDataset> trainer;
-
- /** */
- private boolean isDistributed;
-
- /** */
- private final double precision;
-
- /** */
- GenericLinearSVMTrainerTest(
- Trainer<SVMLinearClassificationModel, LabeledDataset> trainer,
- boolean isDistributed,
- double precision) {
- super();
- this.trainer = trainer;
- this.precision = precision;
- this.isDistributed = isDistributed;
- }
-
- /**
- * Test trainer on classification model y = x.
- */
- @Test
- public void testTrainWithTheLinearlySeparableCase() {
- if (isDistributed)
- IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
-
- LabeledDataset dataset = new LabeledDataset<Double, LabeledVector>(AMOUNT_OF_OBSERVATIONS, AMOUNT_OF_FEATURES, isDistributed);
-
- ThreadLocalRandom rndX = ThreadLocalRandom.current();
- ThreadLocalRandom rndY = ThreadLocalRandom.current();
- for (int i = 0; i < AMOUNT_OF_OBSERVATIONS; i++) {
- double x = rndX.nextDouble(-1000, 1000);
- double y = rndY.nextDouble(-1000, 1000);
- dataset.features(i).set(0, x);
- dataset.features(i).set(1, y);
- double lb = y - x > 0 ? 1 : -1;
- dataset.setLabel(i, lb);
- }
-
- SVMLinearClassificationModel mdl = trainer.train(dataset);
-
- TestUtils.assertEquals(-1, mdl.apply(new DenseLocalOnHeapVector(new double[] {100, 10})), precision);
- TestUtils.assertEquals(1, mdl.apply(new DenseLocalOnHeapVector(new double[] {10, 100})), precision);
- }
-
- /**
- * Test trainer on classification model y = x. Amount of generated points is increased 10 times.
- */
- @Test
- public void testTrainWithTheLinearlySeparableCase10() {
- if (isDistributed)
- IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
-
- LabeledDataset dataset = new LabeledDataset<Double, LabeledVector>(AMOUNT_OF_OBSERVATIONS * 10, AMOUNT_OF_FEATURES, isDistributed);
-
- ThreadLocalRandom rndX = ThreadLocalRandom.current();
- ThreadLocalRandom rndY = ThreadLocalRandom.current();
- for (int i = 0; i < AMOUNT_OF_OBSERVATIONS * 10; i++) {
- double x = rndX.nextDouble(-1000, 1000);
- double y = rndY.nextDouble(-1000, 1000);
- dataset.features(i).set(0, x);
- dataset.features(i).set(1, y);
- double lb = y - x > 0 ? 1 : -1;
- dataset.setLabel(i, lb);
- }
-
- SVMLinearClassificationModel mdl = trainer.train(dataset);
-
- TestUtils.assertEquals(-1, mdl.apply(new DenseLocalOnHeapVector(new double[] {100, 10})), precision);
- TestUtils.assertEquals(1, mdl.apply(new DenseLocalOnHeapVector(new double[] {10, 100})), precision);
- }
-
- /**
- * Test trainer on classification model y = x. Amount of generated points is increased 100 times.
- */
- @Test
- public void testTrainWithTheLinearlySeparableCase100() {
- if (isDistributed)
- IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
-
- LabeledDataset dataset = new LabeledDataset<Double, LabeledVector>(AMOUNT_OF_OBSERVATIONS * 100, AMOUNT_OF_FEATURES, isDistributed);
-
- ThreadLocalRandom rndX = ThreadLocalRandom.current();
- ThreadLocalRandom rndY = ThreadLocalRandom.current();
- for (int i = 0; i < AMOUNT_OF_OBSERVATIONS * 100; i++) {
- double x = rndX.nextDouble(-1000, 1000);
- double y = rndY.nextDouble(-1000, 1000);
- dataset.features(i).set(0, x);
- dataset.features(i).set(1, y);
- double lb = y - x > 0 ? 1 : -1;
- dataset.setLabel(i, lb);
- }
-
- SVMLinearClassificationModel mdl = trainer.train(dataset);
-
- TestUtils.assertEquals(-1, mdl.apply(new DenseLocalOnHeapVector(new double[] {100, 10})), precision);
- TestUtils.assertEquals(1, mdl.apply(new DenseLocalOnHeapVector(new double[] {10, 100})), precision);
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/LocalLinearSVMClassificationSCDATrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/LocalLinearSVMClassificationSCDATrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/LocalLinearSVMClassificationSCDATrainerTest.java
deleted file mode 100644
index 68860d2..0000000
--- a/modules/ml/src/test/java/org/apache/ignite/ml/svm/LocalLinearSVMClassificationSCDATrainerTest.java
+++ /dev/null
@@ -1,37 +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.svm;
-
-import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
-import org.apache.ignite.ml.regressions.linear.LinearRegressionSGDTrainer;
-
-/**
- * Tests for {@link LinearRegressionSGDTrainer} on {@link DenseLocalOnHeapMatrix}.
- */
-public class LocalLinearSVMClassificationSCDATrainerTest extends GenericLinearSVMTrainerTest {
- /** */
- public LocalLinearSVMClassificationSCDATrainerTest() {
- super(
- new SVMLinearBinaryClassificationTrainer()
- .withLambda(0.2)
- .withAmountOfIterations(10)
- .withAmountOfLocIterations(20),
- false,
- 1e-2);
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMModelTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMModelTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMModelTest.java
index 1742593..35b6644 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMModelTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMModelTest.java
@@ -36,7 +36,7 @@ public class SVMModelTest {
@Test
public void testPredictWithRawLabels() {
Vector weights = new DenseLocalOnHeapVector(new double[]{2.0, 3.0});
- SVMLinearClassificationModel mdl = new SVMLinearClassificationModel(weights, 1.0).withRawLabels(true);
+ SVMLinearBinaryClassificationModel mdl = new SVMLinearBinaryClassificationModel(weights, 1.0).withRawLabels(true);
Vector observation = new DenseLocalOnHeapVector(new double[]{1.0, 1.0});
TestUtils.assertEquals(1.0 + 2.0 * 1.0 + 3.0 * 1.0, mdl.apply(observation), PRECISION);
@@ -56,11 +56,27 @@ public class SVMModelTest {
Assert.assertEquals(true, mdl.isKeepingRawLabels());
}
+
+ /** */
+ @Test
+ public void testPredictWithMultiClasses() {
+ Vector weights1 = new DenseLocalOnHeapVector(new double[]{10.0, 0.0});
+ Vector weights2 = new DenseLocalOnHeapVector(new double[]{0.0, 10.0});
+ Vector weights3 = new DenseLocalOnHeapVector(new double[]{-1.0, -1.0});
+ SVMLinearMultiClassClassificationModel mdl = new SVMLinearMultiClassClassificationModel();
+ mdl.add(1, new SVMLinearBinaryClassificationModel(weights1, 0.0).withRawLabels(true));
+ mdl.add(2, new SVMLinearBinaryClassificationModel(weights2, 0.0).withRawLabels(true));
+ mdl.add(2, new SVMLinearBinaryClassificationModel(weights3, 0.0).withRawLabels(true));
+
+ Vector observation = new DenseLocalOnHeapVector(new double[]{1.0, 1.0});
+ TestUtils.assertEquals( 1.0, mdl.apply(observation), PRECISION);
+ }
+
/** */
@Test
public void testPredictWithErasedLabels() {
Vector weights = new DenseLocalOnHeapVector(new double[]{1.0, 1.0});
- SVMLinearClassificationModel mdl = new SVMLinearClassificationModel(weights, 1.0);
+ SVMLinearBinaryClassificationModel mdl = new SVMLinearBinaryClassificationModel(weights, 1.0);
Vector observation = new DenseLocalOnHeapVector(new double[]{1.0, 1.0});
TestUtils.assertEquals(1.0, mdl.apply(observation), PRECISION);
@@ -87,7 +103,7 @@ public class SVMModelTest {
@Test
public void testPredictWithErasedLabelsAndChangedThreshold() {
Vector weights = new DenseLocalOnHeapVector(new double[]{1.0, 1.0});
- SVMLinearClassificationModel mdl = new SVMLinearClassificationModel(weights, 1.0).withThreshold(5);
+ SVMLinearBinaryClassificationModel mdl = new SVMLinearBinaryClassificationModel(weights, 1.0).withThreshold(5);
Vector observation = new DenseLocalOnHeapVector(new double[]{1.0, 1.0});
TestUtils.assertEquals(-1.0, mdl.apply(observation), PRECISION);
@@ -103,7 +119,7 @@ public class SVMModelTest {
public void testPredictOnAnObservationWithWrongCardinality() {
Vector weights = new DenseLocalOnHeapVector(new double[]{2.0, 3.0});
- SVMLinearClassificationModel mdl = new SVMLinearClassificationModel(weights, 1.0);
+ SVMLinearBinaryClassificationModel mdl = new SVMLinearBinaryClassificationModel(weights, 1.0);
Vector observation = new DenseLocalOnHeapVector(new double[]{1.0});
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMTestSuite.java
index bfc341c..853a43f 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMTestSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/SVMTestSuite.java
@@ -17,6 +17,10 @@
package org.apache.ignite.ml.svm;
+import org.apache.ignite.ml.svm.binary.DistributedLinearSVMBinaryClassificationTrainerTest;
+import org.apache.ignite.ml.svm.binary.LocalLinearSVMBinaryClassificationTrainerTest;
+import org.apache.ignite.ml.svm.multi.DistributedLinearSVMMultiClassClassificationTrainerTest;
+import org.apache.ignite.ml.svm.multi.LocalLinearSVMMultiClassClassificationTrainerTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -25,8 +29,10 @@ import org.junit.runners.Suite;
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({
- LocalLinearSVMClassificationSCDATrainerTest.class,
- DistributedLinearSVMClassificationSCDATrainerTest.class,
+ LocalLinearSVMBinaryClassificationTrainerTest.class,
+ DistributedLinearSVMBinaryClassificationTrainerTest.class,
+ LocalLinearSVMMultiClassClassificationTrainerTest.class,
+ DistributedLinearSVMMultiClassClassificationTrainerTest.class,
SVMModelTest.class
})
public class SVMTestSuite {
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/DistributedLinearSVMBinaryClassificationTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/DistributedLinearSVMBinaryClassificationTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/DistributedLinearSVMBinaryClassificationTrainerTest.java
new file mode 100644
index 0000000..1be1d1c
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/DistributedLinearSVMBinaryClassificationTrainerTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.svm.binary;
+
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.regressions.linear.LinearRegressionSGDTrainer;
+import org.apache.ignite.ml.svm.SVMLinearBinaryClassificationTrainer;
+
+/**
+ * Tests for {@link LinearRegressionSGDTrainer} on {@link DenseLocalOnHeapMatrix}.
+ */
+public class DistributedLinearSVMBinaryClassificationTrainerTest extends GenericLinearSVMBinaryClassificationTrainerTest {
+ /** */
+ public DistributedLinearSVMBinaryClassificationTrainerTest() {
+ super(
+ new SVMLinearBinaryClassificationTrainer(),
+ true,
+ 1e-2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/GenericLinearSVMBinaryClassificationTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/GenericLinearSVMBinaryClassificationTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/GenericLinearSVMBinaryClassificationTrainerTest.java
new file mode 100644
index 0000000..f390557
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/GenericLinearSVMBinaryClassificationTrainerTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.svm.binary;
+
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.TestUtils;
+import org.apache.ignite.ml.Trainer;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.structures.LabeledDataset;
+import org.apache.ignite.ml.structures.LabeledVector;
+import org.apache.ignite.ml.svm.BaseSVMTest;
+import org.apache.ignite.ml.svm.SVMLinearBinaryClassificationModel;
+import org.junit.Test;
+
+/**
+ * Base class for all linear regression trainers.
+ */
+public class GenericLinearSVMBinaryClassificationTrainerTest extends BaseSVMTest {
+ /** Fixed size of Dataset. */
+ private static final int AMOUNT_OF_OBSERVATIONS = 100;
+
+ /** Fixed size of columns in Dataset. */
+ private static final int AMOUNT_OF_FEATURES = 2;
+
+ /** */
+ private final Trainer<SVMLinearBinaryClassificationModel, LabeledDataset> trainer;
+
+ /** */
+ private boolean isDistributed;
+
+ /** */
+ private final double precision;
+
+ /** */
+ GenericLinearSVMBinaryClassificationTrainerTest(
+ Trainer<SVMLinearBinaryClassificationModel, LabeledDataset> trainer,
+ boolean isDistributed,
+ double precision) {
+ super();
+ this.trainer = trainer;
+ this.precision = precision;
+ this.isDistributed = isDistributed;
+ }
+
+ /**
+ * Test trainer on classification model y = x.
+ */
+ @Test
+ public void testTrainWithTheLinearlySeparableCase() {
+ if (isDistributed)
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ LabeledDataset dataset = new LabeledDataset<Double, LabeledVector>(AMOUNT_OF_OBSERVATIONS, AMOUNT_OF_FEATURES, isDistributed);
+
+ ThreadLocalRandom rndX = ThreadLocalRandom.current();
+ ThreadLocalRandom rndY = ThreadLocalRandom.current();
+ for (int i = 0; i < AMOUNT_OF_OBSERVATIONS; i++) {
+ double x = rndX.nextDouble(-1000, 1000);
+ double y = rndY.nextDouble(-1000, 1000);
+ dataset.features(i).set(0, x);
+ dataset.features(i).set(1, y);
+ double lb = y - x > 0 ? 1 : -1;
+ dataset.setLabel(i, lb);
+ }
+
+ SVMLinearBinaryClassificationModel mdl = trainer.train(dataset);
+
+ TestUtils.assertEquals(-1, mdl.apply(new DenseLocalOnHeapVector(new double[] {100, 10})), precision);
+ TestUtils.assertEquals(1, mdl.apply(new DenseLocalOnHeapVector(new double[] {10, 100})), precision);
+ }
+
+ /**
+ * Test trainer on classification model y = x. Amount of generated points is increased 10 times.
+ */
+ @Test
+ public void testTrainWithTheLinearlySeparableCase10() {
+ if (isDistributed)
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ LabeledDataset dataset = new LabeledDataset<Double, LabeledVector>(AMOUNT_OF_OBSERVATIONS * 10, AMOUNT_OF_FEATURES, isDistributed);
+
+ ThreadLocalRandom rndX = ThreadLocalRandom.current();
+ ThreadLocalRandom rndY = ThreadLocalRandom.current();
+ for (int i = 0; i < AMOUNT_OF_OBSERVATIONS * 10; i++) {
+ double x = rndX.nextDouble(-1000, 1000);
+ double y = rndY.nextDouble(-1000, 1000);
+ dataset.features(i).set(0, x);
+ dataset.features(i).set(1, y);
+ double lb = y - x > 0 ? 1 : -1;
+ dataset.setLabel(i, lb);
+ }
+
+ SVMLinearBinaryClassificationModel mdl = trainer.train(dataset);
+
+ TestUtils.assertEquals(-1, mdl.apply(new DenseLocalOnHeapVector(new double[] {100, 10})), precision);
+ TestUtils.assertEquals(1, mdl.apply(new DenseLocalOnHeapVector(new double[] {10, 100})), precision);
+ }
+
+ /**
+ * Test trainer on classification model y = x. Amount of generated points is increased 100 times.
+ */
+ @Test
+ public void testTrainWithTheLinearlySeparableCase100() {
+ if (isDistributed)
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+ LabeledDataset dataset = new LabeledDataset<Double, LabeledVector>(AMOUNT_OF_OBSERVATIONS * 100, AMOUNT_OF_FEATURES, isDistributed);
+
+ ThreadLocalRandom rndX = ThreadLocalRandom.current();
+ ThreadLocalRandom rndY = ThreadLocalRandom.current();
+ for (int i = 0; i < AMOUNT_OF_OBSERVATIONS * 100; i++) {
+ double x = rndX.nextDouble(-1000, 1000);
+ double y = rndY.nextDouble(-1000, 1000);
+ dataset.features(i).set(0, x);
+ dataset.features(i).set(1, y);
+ double lb = y - x > 0 ? 1 : -1;
+ dataset.setLabel(i, lb);
+ }
+
+ SVMLinearBinaryClassificationModel mdl = trainer.train(dataset);
+
+ TestUtils.assertEquals(-1, mdl.apply(new DenseLocalOnHeapVector(new double[] {100, 10})), precision);
+ TestUtils.assertEquals(1, mdl.apply(new DenseLocalOnHeapVector(new double[] {10, 100})), precision);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/LocalLinearSVMBinaryClassificationTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/LocalLinearSVMBinaryClassificationTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/LocalLinearSVMBinaryClassificationTrainerTest.java
new file mode 100644
index 0000000..a9cb54c
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/binary/LocalLinearSVMBinaryClassificationTrainerTest.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.svm.binary;
+
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.regressions.linear.LinearRegressionSGDTrainer;
+import org.apache.ignite.ml.svm.SVMLinearBinaryClassificationTrainer;
+
+/**
+ * Tests for {@link LinearRegressionSGDTrainer} on {@link DenseLocalOnHeapMatrix}.
+ */
+public class LocalLinearSVMBinaryClassificationTrainerTest extends GenericLinearSVMBinaryClassificationTrainerTest {
+ /** */
+ public LocalLinearSVMBinaryClassificationTrainerTest() {
+ super(
+ new SVMLinearBinaryClassificationTrainer()
+ .withLambda(0.2)
+ .withAmountOfIterations(10)
+ .withAmountOfLocIterations(20),
+ false,
+ 1e-2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/DistributedLinearSVMMultiClassClassificationTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/DistributedLinearSVMMultiClassClassificationTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/DistributedLinearSVMMultiClassClassificationTrainerTest.java
new file mode 100644
index 0000000..6806e0b
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/DistributedLinearSVMMultiClassClassificationTrainerTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.svm.multi;
+
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.regressions.linear.LinearRegressionSGDTrainer;
+import org.apache.ignite.ml.svm.SVMLinearMultiClassClassificationTrainer;
+
+/**
+ * Tests for {@link LinearRegressionSGDTrainer} on {@link DenseLocalOnHeapMatrix}.
+ */
+public class DistributedLinearSVMMultiClassClassificationTrainerTest extends GenericLinearSVMMultiClassClassificationTrainerTest {
+ /** */
+ public DistributedLinearSVMMultiClassClassificationTrainerTest() {
+ super(
+ new SVMLinearMultiClassClassificationTrainer(),
+ true,
+ 1e-2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/GenericLinearSVMMultiClassClassificationTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/GenericLinearSVMMultiClassClassificationTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/GenericLinearSVMMultiClassClassificationTrainerTest.java
new file mode 100644
index 0000000..8c6083d
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/GenericLinearSVMMultiClassClassificationTrainerTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.svm.multi;
+
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.TestUtils;
+import org.apache.ignite.ml.Trainer;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.structures.LabeledDataset;
+import org.apache.ignite.ml.svm.BaseSVMTest;
+import org.apache.ignite.ml.svm.SVMLinearMultiClassClassificationModel;
+import org.junit.Test;
+
+/**
+ * Base class for all linear regression trainers.
+ */
+public class GenericLinearSVMMultiClassClassificationTrainerTest extends BaseSVMTest {
+ /** */
+ private final Trainer<SVMLinearMultiClassClassificationModel, LabeledDataset> trainer;
+
+ /** */
+ private boolean isDistributed;
+
+ /** */
+ private final double precision;
+
+ /** */
+ GenericLinearSVMMultiClassClassificationTrainerTest(
+ Trainer<SVMLinearMultiClassClassificationModel, LabeledDataset> trainer,
+ boolean isDistributed,
+ double precision) {
+ super();
+ this.trainer = trainer;
+ this.precision = precision;
+ this.isDistributed = isDistributed;
+ }
+
+ /**
+ * Test trainer on classification model y = x.
+ */
+ @Test
+ public void testTrainWithTheLinearlySeparableCase() {
+ if (isDistributed)
+ IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+ double[][] mtx =
+ new double[][] {
+ {-10.0, 12.0},
+ {-5.0, 14.0},
+ {-3.0, 18.0},
+ {13.0, -1.0},
+ {10.0, -2.0},
+ {15.0, -3.0}};
+ double[] lbs = new double[] {1.0, 1.0, 1.0, 2.0, 2.0, 2.0};
+ LabeledDataset dataset = new LabeledDataset(mtx, lbs, null, isDistributed);
+
+
+ SVMLinearMultiClassClassificationModel mdl = trainer.train(dataset);
+ TestUtils.assertEquals(1.0, mdl.apply(new DenseLocalOnHeapVector(new double[] {-2.0, 15})), precision);
+ TestUtils.assertEquals(2.0, mdl.apply(new DenseLocalOnHeapVector(new double[] {12, -5})), precision);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/c6619637/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/LocalLinearSVMMultiClassClassificationTrainerTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/LocalLinearSVMMultiClassClassificationTrainerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/LocalLinearSVMMultiClassClassificationTrainerTest.java
new file mode 100644
index 0000000..a239c95
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/svm/multi/LocalLinearSVMMultiClassClassificationTrainerTest.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.svm.multi;
+
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.regressions.linear.LinearRegressionSGDTrainer;
+import org.apache.ignite.ml.svm.SVMLinearMultiClassClassificationTrainer;
+
+/**
+ * Tests for {@link LinearRegressionSGDTrainer} on {@link DenseLocalOnHeapMatrix}.
+ */
+public class LocalLinearSVMMultiClassClassificationTrainerTest extends GenericLinearSVMMultiClassClassificationTrainerTest {
+ /** */
+ public LocalLinearSVMMultiClassClassificationTrainerTest() {
+ super(
+ new SVMLinearMultiClassClassificationTrainer()
+ .withLambda(0.2)
+ .withAmountOfIterations(10)
+ .withAmountOfLocIterations(20),
+ false,
+ 1e-2);
+ }
+}