diff --git a/samoa-api/src/main/java/org/apache/samoa/evaluation/EvaluatorProcessor.java b/samoa-api/src/main/java/org/apache/samoa/evaluation/EvaluatorProcessor.java index d174dea6..6301b18d 100644 --- a/samoa-api/src/main/java/org/apache/samoa/evaluation/EvaluatorProcessor.java +++ b/samoa-api/src/main/java/org/apache/samoa/evaluation/EvaluatorProcessor.java @@ -31,7 +31,7 @@ import org.apache.samoa.core.ContentEvent; import org.apache.samoa.core.Processor; -import org.apache.samoa.learners.ModelContentEvent; +import org.apache.samoa.learners.ClassificationModelContentEvent; import org.apache.samoa.learners.ResultContentEvent; import org.apache.samoa.moa.core.Measurement; import org.apache.samoa.moa.evaluation.LearningCurve; @@ -74,7 +74,7 @@ private EvaluatorProcessor(Builder builder) { @Override public boolean process(ContentEvent event) { // for serialize - if (event instanceof ModelContentEvent) { + if (event instanceof ClassificationModelContentEvent) { return false; } diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/ModelContentEvent.java b/samoa-api/src/main/java/org/apache/samoa/learners/ClassificationModelContentEvent.java similarity index 79% rename from samoa-api/src/main/java/org/apache/samoa/learners/ModelContentEvent.java rename to samoa-api/src/main/java/org/apache/samoa/learners/ClassificationModelContentEvent.java index bdf5d0d6..c125f941 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/ModelContentEvent.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/ClassificationModelContentEvent.java @@ -21,25 +21,26 @@ */ import org.apache.samoa.core.ContentEvent; +import org.apache.samoa.learners.classifiers.ClassificationModel; -final public class ModelContentEvent implements ContentEvent { +final public class ClassificationModelContentEvent implements ContentEvent { final private boolean isLast; - private Model model; + private ClassificationModel model; private long modelIndex; private long instanceIndex; private int classifierIndex; private int evaluationIndex; - public ModelContentEvent() { + public ClassificationModelContentEvent() { this.isLast = false; } - public ModelContentEvent(boolean isLast) { + public ClassificationModelContentEvent(boolean isLast) { this.isLast = isLast; } - public ModelContentEvent(boolean isLast, Model model, long modelIndex, long instanceIndex, - int classifierIndex, int evaluationIndex) { + public ClassificationModelContentEvent(boolean isLast, ClassificationModel model, long modelIndex, long instanceIndex, + int classifierIndex, int evaluationIndex) { this.isLast = isLast; this.model = model; this.modelIndex = modelIndex; @@ -71,11 +72,11 @@ public void setModelIndex(long modelIndex) { this.modelIndex = modelIndex; } - public Model getModel() { + public ClassificationModel getModel() { return model; } - public void setModel(Model model) { + public void setModel(ClassificationModel model) { this.model = model; } diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/InstanceUtils.java b/samoa-api/src/main/java/org/apache/samoa/learners/InstanceUtils.java new file mode 100644 index 00000000..ab0faea9 --- /dev/null +++ b/samoa-api/src/main/java/org/apache/samoa/learners/InstanceUtils.java @@ -0,0 +1,142 @@ +package org.apache.samoa.learners; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2016 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import org.apache.samoa.instances.*; +import org.apache.samoa.learners.classifiers.ClassificationDataInstance; +import org.apache.samoa.learners.clusterers.ClusterDataInstance; +import org.apache.samoa.moa.core.DataPoint; +import org.apache.samoa.moa.core.FastVector; + +import java.util.ArrayList; +import java.util.Arrays; + +public class InstanceUtils { + + private static InstancesHeader getClusterInstanceHeader(ClusterDataInstance dataInstance) { + ArrayList attributes = new ArrayList<>(); + + for (int i = 0; i < dataInstance.getNumberFeatures(); i++) { + attributes.add(new Attribute("att" + (i + 1))); + } + + // attributes.add(new Attribute("class", null)); + + InstancesHeader instancesHeader = new InstancesHeader( + new Instances(null, attributes, 0)); + instancesHeader.setClassIndex(instancesHeader.numAttributes() - 1); + + return instancesHeader; + } + + private static InstancesHeader getClassificationInstanceHeader(ClassificationDataInstance dataInstance) { + FastVector attributes = new FastVector<>(); + + for (int i = 0; i < dataInstance.getNumberNominalFeatures(); i++) { + FastVector nominalAttVals = new FastVector<>(); + for (int j = 0; j < dataInstance.getNumberValsPerNominalFeature()[i]; j++) { + nominalAttVals.addElement("value" + (j + 1)); + } + attributes.addElement(new Attribute("nominal" + (i + 1), + nominalAttVals)); + } + + for (int i = 0; i < dataInstance.getNumberNumericFeatures(); i++) { + attributes.addElement(new Attribute("numeric" + (i + 1))); + } + + FastVector classLabels = new FastVector<>(); + for (int i = 0; i < dataInstance.getNumberLabels(); i++) { + classLabels.addElement("class" + (i + 1)); + } + attributes.addElement(new Attribute("class", classLabels)); + + InstancesHeader instancesHeader = new InstancesHeader( + new Instances(null, attributes, 0)); + instancesHeader.setClassIndex(instancesHeader.numAttributes() - 1); + + return instancesHeader; + } + + /** + * convert ClassificationDataInstance to SAMOA Instance + */ + public static Instance convertClassificationDataInstance(ClassificationDataInstance dataInstance) { + InstancesHeader header = InstanceUtils.getClassificationInstanceHeader(dataInstance); + Instance inst = new DenseInstance(header.numAttributes()); + + int numNomFeatures = dataInstance.getNumberNominalFeatures(); + int numNumFeatures = dataInstance.getNumberNumericFeatures(); + + for (int i = 0; i < numNomFeatures + numNumFeatures; i++) { + if (i < numNomFeatures) { + inst.setValue(i, dataInstance.getNominalData()[i]); + } else { + inst.setValue(i, dataInstance.getNumericData()[i - numNomFeatures]); + } + } + + inst.setDataset(header); + inst.setClassValue(dataInstance.getTrueLabel()); + + return inst; + } + + /** + * convert SAMOA Instance to ClassificationDataInstance + */ + public static ClassificationDataInstance reConvertClassificationDataInstance( + Instance inst, int numberNominalFeatures, int numberNumericFeatures) { + double[] nominalDataTmp = Arrays.copyOfRange(inst.toDoubleArray(), 0, numberNominalFeatures); + int[] nominalData = new int[nominalDataTmp.length]; + for (int j = 0; j < nominalData.length; j++) { + nominalData[j] = (int) nominalDataTmp[j]; + } + + double[] numericData = Arrays.copyOfRange( + inst.toDoubleArray(), numberNominalFeatures, + inst.toDoubleArray().length - 1); + + int[] numValsPerNominal = new int[nominalData.length]; + Arrays.fill(numValsPerNominal, inst.attribute(0).numValues()); + + return new ClassificationDataInstance( + numberNumericFeatures, numericData, numberNominalFeatures, + numValsPerNominal, nominalData, inst.numClasses(), (int) inst.classValue()); + } + + /** + * convert ClusterDataInstance to SAMOA Instance + */ + public static Instance convertClusterDataInstance(ClusterDataInstance dataInstance) { + Instance inst = new DenseInstance(1.0, dataInstance.getData()); + inst.setDataset(InstanceUtils.getClusterInstanceHeader(dataInstance)); + return new DataPoint(inst, dataInstance.getTimeStamp()); + } + + /** + * convert SAMOA Instance to ClusterDataInstance + */ + public static ClusterDataInstance reConvertClusterDataInstance(DataPoint point) { + double[] data = point.toDoubleArray(); + return new ClusterDataInstance(data.length, point.getTimestamp(), data); + } +} diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ClassificationDataInstance.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ClassificationDataInstance.java new file mode 100644 index 00000000..d2427acb --- /dev/null +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ClassificationDataInstance.java @@ -0,0 +1,80 @@ +package org.apache.samoa.learners.classifiers; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2016 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import java.io.Serializable; + +/** + * DataInstance for classification problem + * There may be tow types of feature in feature vector: numeric feature and nominal feature + */ +public class ClassificationDataInstance implements Serializable { + private int numberNumericFeatures; + private double[] numericData; + + private int numberNominalFeatures; + private int[] numberValsPerNominalFeature; + private int[] nominalData; + + private int numberLabels; + private int trueLabel; + + public ClassificationDataInstance(int numberNumericFeatures, + double[] numericData, int numberNominalFeatures, + int[] numberValsPerNominalFeature, int[] nominalData, + int numberLabels, int trueLabel) { + this.numberNumericFeatures = numberNumericFeatures; + this.numericData = numericData; + this.numberNominalFeatures = numberNominalFeatures; + this.numberValsPerNominalFeature = numberValsPerNominalFeature; + this.nominalData = nominalData; + this.numberLabels = numberLabels; + this.trueLabel = trueLabel; + } + + public int getNumberNumericFeatures() { + return numberNumericFeatures; + } + + public double[] getNumericData() { + return numericData; + } + + public int getNumberNominalFeatures() { + return numberNominalFeatures; + } + + public int[] getNumberValsPerNominalFeature() { + return numberValsPerNominalFeature; + } + + public int[] getNominalData() { + return nominalData; + } + + public int getNumberLabels() { + return numberLabels; + } + + public int getTrueLabel() { + return trueLabel; + } +} diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ClassificationModel.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ClassificationModel.java new file mode 100644 index 00000000..eb37dd5c --- /dev/null +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ClassificationModel.java @@ -0,0 +1,30 @@ +package org.apache.samoa.learners.classifiers; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2016 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import java.io.Serializable; + +/** + * Model for classification problem + */ +public interface ClassificationModel extends Serializable { + double[] predict(ClassificationDataInstance dataInstance); +} diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/BoostingPredictionCombinerProcessor.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/BoostingPredictionCombinerProcessor.java index b7bc995b..58e8c4b7 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/BoostingPredictionCombinerProcessor.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/BoostingPredictionCombinerProcessor.java @@ -30,7 +30,7 @@ import org.apache.samoa.core.ContentEvent; import org.apache.samoa.instances.Instance; import org.apache.samoa.learners.InstanceContentEvent; -import org.apache.samoa.learners.ModelContentEvent; +import org.apache.samoa.learners.ClassificationModelContentEvent; import org.apache.samoa.learners.ResultContentEvent; import org.apache.samoa.moa.core.DoubleVector; import org.apache.samoa.moa.core.Utils; @@ -59,8 +59,8 @@ public class BoostingPredictionCombinerProcessor extends PredictionCombinerProce @Override public boolean process(ContentEvent event) { // for serialize - if (event instanceof ModelContentEvent) { - return this.processModel((ModelContentEvent) event); + if (event instanceof ClassificationModelContentEvent) { + return this.processModel((ClassificationModelContentEvent) event); } ResultContentEvent inEvent = (ResultContentEvent) event; diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/EnsembleModel.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/EnsembleModel.java index 00dd126a..bf6e15c1 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/EnsembleModel.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/EnsembleModel.java @@ -2,12 +2,12 @@ import org.apache.samoa.instances.Instance; import org.apache.samoa.instances.Utils; -import org.apache.samoa.learners.Model; +import org.apache.samoa.learners.InstanceUtils; +import org.apache.samoa.learners.classifiers.ClassificationDataInstance; +import org.apache.samoa.learners.classifiers.ClassificationModel; import org.apache.samoa.moa.core.DoubleVector; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; /* * #%L @@ -29,23 +29,21 @@ * #L% */ -public class EnsembleModel implements Model { - private ArrayList modelList; +public class EnsembleModel implements ClassificationModel { + private ArrayList modelList; private ArrayList modelWeightList; - public EnsembleModel() { - } - - public EnsembleModel(ArrayList modelList, ArrayList modelWeightList) { + public EnsembleModel(ArrayList modelList, + ArrayList modelWeightList) { this.modelList = modelList; this.modelWeightList = modelWeightList; } @Override - public double[] predict(Instance inst) { + public double[] predict(ClassificationDataInstance dataInstance) { DoubleVector combinedVote = new DoubleVector(); for (int i = 0; i < modelList.size(); i++) { - double[] prediction = modelList.get(i).predict(inst); + double[] prediction = modelList.get(i).predict(dataInstance); DoubleVector vote = new DoubleVector(prediction); if (vote.sumOfValues() > 0.0) { vote.normalize(); @@ -56,9 +54,13 @@ public double[] predict(Instance inst) { return combinedVote.getArrayCopy(); } - public boolean evaluate(Instance inst) { + /** + * Predict the class of an input data instance, and evaluate if it is the true class. + */ + public boolean evaluate(ClassificationDataInstance dataInstance) { + Instance inst = InstanceUtils.convertClassificationDataInstance(dataInstance); int trueClass = (int) inst.classValue(); - double[] prediction = this.predict(inst); + double[] prediction = this.predict(dataInstance); int predictedClass = Utils.maxIndex(prediction); return trueClass == predictedClass; } diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/PredictionCombinerProcessor.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/PredictionCombinerProcessor.java index 0d9d22a4..fa9d7507 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/PredictionCombinerProcessor.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/ensemble/PredictionCombinerProcessor.java @@ -29,9 +29,9 @@ import org.apache.samoa.core.ContentEvent; import org.apache.samoa.core.Processor; -import org.apache.samoa.learners.Model; -import org.apache.samoa.learners.ModelContentEvent; +import org.apache.samoa.learners.ClassificationModelContentEvent; import org.apache.samoa.learners.ResultContentEvent; +import org.apache.samoa.learners.classifiers.ClassificationModel; import org.apache.samoa.moa.core.DoubleVector; import org.apache.samoa.moa.core.SerializeUtils; import org.apache.samoa.topology.Stream; @@ -97,7 +97,7 @@ public void setEnsembleSize(int ensembleSize) { protected Map mapCountsforModelReceived; // for serialize - protected Map> mapModelListforModelReceived; // for serialize + protected Map> mapModelListforModelReceived; // for serialize protected Map> mapModelWeightListforModelReceived; // for serialize /** @@ -109,8 +109,8 @@ public void setEnsembleSize(int ensembleSize) { */ public boolean process(ContentEvent event) { // for serialize - if (event instanceof ModelContentEvent) { - return this.processModel((ModelContentEvent) event); + if (event instanceof ClassificationModelContentEvent) { + return this.processModel((ClassificationModelContentEvent) event); } ResultContentEvent inEvent = (ResultContentEvent) event; @@ -135,8 +135,8 @@ public boolean process(ContentEvent event) { } // for serialize - protected boolean processModel(ModelContentEvent event) { - Model model = event.getModel(); + protected boolean processModel(ClassificationModelContentEvent event) { + ClassificationModel model = event.getModel(); long modelIndex = event.getModelIndex(); long instanceIndex = event.getInstanceIndex(); int classifierIndex = event.getClassifierIndex(); @@ -213,13 +213,13 @@ protected void addStatisticsForInstanceReceived(int instanceIndex, int classifie } //for serialize - protected void addStatisticsForModelReceived(long modelIndex, int classifierIndex, Model model, int add) { + protected void addStatisticsForModelReceived(long modelIndex, int classifierIndex, ClassificationModel model, int add) { if (this.mapCountsforModelReceived == null) { this.mapCountsforModelReceived = new HashMap<>(); this.mapModelListforModelReceived = new HashMap<>(); this.mapModelWeightListforModelReceived = new HashMap<>(); } - ArrayList modelList = this.mapModelListforModelReceived.get(modelIndex); + ArrayList modelList = this.mapModelListforModelReceived.get(modelIndex); if (modelList == null) { modelList = new ArrayList<>(); } diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/rules/AMRulesModel.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/rules/AMRulesModel.java index 5565ea7d..389d74d2 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/rules/AMRulesModel.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/rules/AMRulesModel.java @@ -21,22 +21,21 @@ */ import org.apache.samoa.instances.Instance; -import org.apache.samoa.learners.Model; +import org.apache.samoa.learners.InstanceUtils; +import org.apache.samoa.learners.classifiers.ClassificationDataInstance; +import org.apache.samoa.learners.classifiers.ClassificationModel; import org.apache.samoa.learners.classifiers.rules.common.ActiveRule; import org.apache.samoa.learners.classifiers.rules.common.PassiveRule; import org.apache.samoa.moa.classifiers.rules.core.voting.ErrorWeightedVote; import java.util.List; -public class AMRulesModel implements Model { +public class AMRulesModel implements ClassificationModel { private List ruleSet; private ActiveRule defaultRule; private ErrorWeightedVote errorWeightedVote; private boolean unorderedRules; - public AMRulesModel() { - } - public AMRulesModel(ActiveRule defaultRule, List ruleSet, ErrorWeightedVote errorWeightedVote, boolean unorderedRules) { this.defaultRule = defaultRule; @@ -46,7 +45,8 @@ public AMRulesModel(ActiveRule defaultRule, List ruleSet, } @Override - public double[] predict(Instance inst) { + public double[] predict(ClassificationDataInstance dataInstance) { + Instance inst = InstanceUtils.convertClassificationDataInstance(dataInstance); double[] prediction; boolean predictionCovered = false; diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/HoeffdingTreeModel.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/HoeffdingTreeModel.java index 4b856795..aa935570 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/HoeffdingTreeModel.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/HoeffdingTreeModel.java @@ -24,9 +24,11 @@ import org.apache.samoa.instances.Instance; import org.apache.samoa.instances.Instances; import org.apache.samoa.instances.Utils; -import org.apache.samoa.learners.Model; +import org.apache.samoa.learners.InstanceUtils; +import org.apache.samoa.learners.classifiers.ClassificationDataInstance; +import org.apache.samoa.learners.classifiers.ClassificationModel; -public class HoeffdingTreeModel implements Model { +public class HoeffdingTreeModel implements ClassificationModel { private Instances dataset; private Node treeRoot; @@ -35,12 +37,10 @@ public HoeffdingTreeModel(Instances dataset, Node treeRoot) { this.treeRoot = treeRoot; } - public HoeffdingTreeModel() { - } - @Override - public double[] predict(Instance inst) { + public double[] predict(ClassificationDataInstance dataInstance) { double[] prediction; + Instance inst = InstanceUtils.convertClassificationDataInstance(dataInstance); // inst.setDataset(dataset); FoundNode foundNode; @@ -55,13 +55,19 @@ public double[] predict(Instance inst) { int numClasses = dataset.numClasses(); prediction = new double[numClasses]; } + return prediction; } - public boolean evaluate(Instance inst) { + /** + * Predict the class of an input data instance, and evaluate if it is the true class. + */ + public boolean evaluate(ClassificationDataInstance dataInstance) { + Instance inst = InstanceUtils.convertClassificationDataInstance(dataInstance); int trueClass = (int) inst.classValue(); - double[] prediction = this.predict(inst); + double[] prediction = this.predict(dataInstance); int predictedClass = Utils.maxIndex(prediction); + return trueClass == predictedClass; } diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/ModelAggregatorProcessor.java b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/ModelAggregatorProcessor.java index 9aabdbd3..06f479b9 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/ModelAggregatorProcessor.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/classifiers/trees/ModelAggregatorProcessor.java @@ -41,7 +41,7 @@ import org.apache.samoa.instances.InstancesHeader; import org.apache.samoa.learners.InstanceContent; import org.apache.samoa.learners.InstancesContentEvent; -import org.apache.samoa.learners.ModelContentEvent; +import org.apache.samoa.learners.ClassificationModelContentEvent; import org.apache.samoa.learners.ResultContentEvent; import org.apache.samoa.moa.classifiers.core.AttributeSplitSuggestion; import org.apache.samoa.moa.classifiers.core.driftdetection.ChangeDetector; @@ -321,7 +321,7 @@ private void processInstances(InstancesContentEvent instContentEvent) { e.printStackTrace(); } - this.modelStream.put(new ModelContentEvent( + this.modelStream.put(new ClassificationModelContentEvent( instContent.isLastEvent(), hoeffdingTreeModel, modelIndex, instContent.getInstanceIndex(), processorId, instContent.getEvaluationIndex())); // for serialize diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/CluStreamModel.java b/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/CluStreamModel.java index dd153cd6..ee8ee748 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/CluStreamModel.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/CluStreamModel.java @@ -21,28 +21,24 @@ */ -import org.apache.samoa.instances.Instance; -import org.apache.samoa.learners.Model; +import org.apache.samoa.learners.InstanceUtils; import org.apache.samoa.moa.cluster.Clustering; import org.apache.samoa.moa.core.DataPoint; import org.apache.samoa.moa.evaluation.MeasureCollection; import java.util.ArrayList; -public class CluStreamModel implements Model { +public class CluStreamModel implements ClusterModel { private Clustering clustering; public CluStreamModel(Clustering clustering) { this.clustering = clustering; } - public CluStreamModel() { - } - @Override - public double[] predict(Instance inst) { - DataPoint dataPoint = (DataPoint) inst; + public double[] predict(ClusterDataInstance dataInstance) { double[] distances = new double[clustering.size()]; + DataPoint dataPoint = (DataPoint) InstanceUtils.convertClusterDataInstance(dataInstance); for (int c = 0; c < clustering.size(); c++) { double distance = 0.0; double[] center = clustering.get(c).getCenter(); @@ -52,18 +48,26 @@ public double[] predict(Instance inst) { } distances[c] = Math.sqrt(distance); } + return distances; } - public double evaluate(ArrayList points, MeasureCollection measure) { - double score = 0.0; + /** + * Given a list of data instances and a measure, evaluate the performance of the resulting cluster. + */ + public double evaluate(ArrayList points, MeasureCollection measure) { + ArrayList dataPoints = new ArrayList<>(); + for (ClusterDataInstance dataInstance : points) { + dataPoints.add((DataPoint) InstanceUtils.convertClusterDataInstance(dataInstance)); + } + try { - measure.evaluateClusteringPerformance(clustering, null, points); - score = measure.getMean(0); + measure.evaluateClusteringPerformance(clustering, null, dataPoints); } catch (Exception e) { e.printStackTrace(); } - return score; + + return measure.getMean(0); } @Override diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/ClusterDataInstance.java b/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/ClusterDataInstance.java new file mode 100644 index 00000000..9b74b7f3 --- /dev/null +++ b/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/ClusterDataInstance.java @@ -0,0 +1,51 @@ +package org.apache.samoa.learners.clusterers; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2016 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import java.io.Serializable; + +/** + * DataInstance for cluster problem + * The feature type is numeric + */ +public class ClusterDataInstance implements Serializable { + private int numberFeatures; + private int timeStamp; + private double[] data; + + public ClusterDataInstance(int numberFeatures, int timeStamp, double[] data) { + this.numberFeatures = numberFeatures; + this.timeStamp = timeStamp; + this.data = data; + } + + public int getNumberFeatures() { + return numberFeatures; + } + + public int getTimeStamp() { + return timeStamp; + } + + public double[] getData() { + return data; + } +} diff --git a/samoa-api/src/main/java/org/apache/samoa/learners/Model.java b/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/ClusterModel.java similarity index 77% rename from samoa-api/src/main/java/org/apache/samoa/learners/Model.java rename to samoa-api/src/main/java/org/apache/samoa/learners/clusterers/ClusterModel.java index f955c041..4dc519f4 100644 --- a/samoa-api/src/main/java/org/apache/samoa/learners/Model.java +++ b/samoa-api/src/main/java/org/apache/samoa/learners/clusterers/ClusterModel.java @@ -1,4 +1,4 @@ -package org.apache.samoa.learners; +package org.apache.samoa.learners.clusterers; /* * #%L @@ -9,9 +9,9 @@ * Licensed 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. @@ -20,11 +20,11 @@ * #L% */ - -import org.apache.samoa.instances.Instance; - import java.io.Serializable; -public interface Model extends Serializable { - double[] predict(Instance inst); +/** + * Model for cluster problem + */ +public interface ClusterModel extends Serializable { + double[] predict(ClusterDataInstance dataInstance); } diff --git a/samoa-gearpump/src/main/resources/reference.conf b/samoa-gearpump/src/main/resources/reference.conf index a6e4d8e5..fbb3f3b3 100644 --- a/samoa-gearpump/src/main/resources/reference.conf +++ b/samoa-gearpump/src/main/resources/reference.conf @@ -57,6 +57,9 @@ gearpump { "org.apache.samoa.learners.classifiers.trees.HoeffdingTreeModel" = "" "org.apache.samoa.learners.classifiers.trees.ActiveLearningNode" = "" "[Lorg.apache.samoa.learners.classifiers.trees.AttributeBatchContentEvent;" = "" + "com.github.javacliparser.IntOption" = "" + "com.github.javacliparser.FloatOption" = "" + "org.apache.samoa.learners.InstanceContent" = "" "java.util.ArrayList" = "" "java.util.LinkedList" = "" "java.util.HashMap" = "" diff --git a/samoa-local/src/test/java/org/apache/samoa/serialize/AMRulesModelTest.java b/samoa-local/src/test/java/org/apache/samoa/serialize/AMRulesModelTest.java new file mode 100644 index 00000000..6631708d --- /dev/null +++ b/samoa-local/src/test/java/org/apache/samoa/serialize/AMRulesModelTest.java @@ -0,0 +1,103 @@ +package org.apache.samoa.serialize; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2015 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import com.github.javacliparser.ClassOption; +import com.github.javacliparser.FlagOption; +import com.github.javacliparser.IntOption; +import com.github.javacliparser.Option; +import junit.framework.TestCase; +import org.apache.commons.io.FileUtils; +import org.apache.samoa.instances.Instance; +import org.apache.samoa.learners.InstanceUtils; +import org.apache.samoa.learners.classifiers.ClassificationDataInstance; +import org.apache.samoa.learners.classifiers.rules.AMRulesModel; +import org.apache.samoa.moa.core.SerializeUtils; +import org.apache.samoa.tasks.Task; +import org.apache.samoa.topology.impl.SimpleComponentFactory; +import org.apache.samoa.topology.impl.SimpleEngine; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; + +public class AMRulesModelTest extends TestCase { + private static final String BASE_DIR = "amr"; + private static final int NUM_MODEL_IN_DIR = 10; + + private static final int numberNumericFeatures = 10; + private static final int numberNominalFeatures = 10; + private static final String CLISTRING = + "PrequentialEvaluation " + + "-l (org.apache.samoa.learners.classifiers.rules.VerticalAMRulesRegressor -p 4) " + + "-s (generators.RandomTreeGenerator -c 2 -o " + + numberNominalFeatures + " -u " + numberNumericFeatures +")"; + + private static final String SUPPRESS_STATUS_OUT_MSG = "Suppress the task status output. Normally it is sent to stderr."; + private static final String SUPPRESS_RESULT_OUT_MSG = "Suppress the task result output. Normally it is sent to stdout."; + private static final String STATUS_UPDATE_FREQ_MSG = "Wait time in milliseconds between status updates."; + + private Option[] extraOptions; + + @Before + public void setUp() { + FlagOption suppressStatusOutOpt = new FlagOption("suppressStatusOut", 'S', SUPPRESS_STATUS_OUT_MSG); + FlagOption suppressResultOutOpt = new FlagOption("suppressResultOut", 'R', SUPPRESS_RESULT_OUT_MSG); + IntOption statusUpdateFreqOpt = new IntOption("statusUpdateFrequency", 'F', STATUS_UPDATE_FREQ_MSG, 1000, 0, + Integer.MAX_VALUE); + extraOptions = new Option[] { suppressStatusOutOpt, suppressResultOutOpt, statusUpdateFreqOpt }; + } + + @After + public void tearDown() { + + } + + @Test + public void testAMRulesModel() throws Exception { + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + FileUtils.forceMkdir(new File(BASE_DIR)); + + Task task = ClassOption.cliStringToObject(CLISTRING, Task.class, extraOptions); + task.setFactory(new SimpleComponentFactory()); + task.init(); + SimpleEngine.submitTopology(task.getTopology()); + + for (int i = 0; i < NUM_MODEL_IN_DIR; i++) { + File fileModel = new File(BASE_DIR + "/amr-model-0-" + i); + File fileData = new File(BASE_DIR + "/amr-data-0-" + i); + + AMRulesModel amRulesModel = (AMRulesModel) SerializeUtils.readFromFile(fileModel); + Instance inst = (Instance) SerializeUtils.readFromFile(fileData); + System.out.println("=== model: " + i + " ==="); + + ClassificationDataInstance dataInstance = + InstanceUtils.reConvertClassificationDataInstance(inst, numberNominalFeatures, numberNumericFeatures); + + System.out.println(Arrays.toString(amRulesModel.predict(dataInstance))); + System.out.println("true predict: " + (int) inst.classValue()); + } + + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + } +} diff --git a/samoa-local/src/test/java/org/apache/samoa/serialize/CluStreamModelTest.java b/samoa-local/src/test/java/org/apache/samoa/serialize/CluStreamModelTest.java new file mode 100644 index 00000000..c73ae64e --- /dev/null +++ b/samoa-local/src/test/java/org/apache/samoa/serialize/CluStreamModelTest.java @@ -0,0 +1,104 @@ +package org.apache.samoa.serialize; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2015 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import com.github.javacliparser.ClassOption; +import com.github.javacliparser.FlagOption; +import com.github.javacliparser.IntOption; +import com.github.javacliparser.Option; +import junit.framework.TestCase; +import org.apache.commons.io.FileUtils; +import org.apache.samoa.evaluation.measures.SSQ; +import org.apache.samoa.learners.InstanceUtils; +import org.apache.samoa.learners.clusterers.CluStreamModel; +import org.apache.samoa.learners.clusterers.ClusterDataInstance; +import org.apache.samoa.moa.core.DataPoint; +import org.apache.samoa.moa.core.SerializeUtils; +import org.apache.samoa.moa.evaluation.MeasureCollection; +import org.apache.samoa.tasks.Task; +import org.apache.samoa.topology.impl.SimpleComponentFactory; +import org.apache.samoa.topology.impl.SimpleEngine; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; + +public class CluStreamModelTest extends TestCase { + private static final String BASE_DIR = "clu"; + private static final String CLISTRING = "ClusteringEvaluation"; + + private static final String SUPPRESS_STATUS_OUT_MSG = "Suppress the task status output. Normally it is sent to stderr."; + private static final String SUPPRESS_RESULT_OUT_MSG = "Suppress the task result output. Normally it is sent to stdout."; + private static final String STATUS_UPDATE_FREQ_MSG = "Wait time in milliseconds between status updates."; + + private Option[] extraOptions; + + @Before + public void setUp() { + FlagOption suppressStatusOutOpt = new FlagOption("suppressStatusOut", 'S', SUPPRESS_STATUS_OUT_MSG); + FlagOption suppressResultOutOpt = new FlagOption("suppressResultOut", 'R', SUPPRESS_RESULT_OUT_MSG); + IntOption statusUpdateFreqOpt = new IntOption("statusUpdateFrequency", 'F', STATUS_UPDATE_FREQ_MSG, 1000, 0, + Integer.MAX_VALUE); + extraOptions = new Option[] { suppressStatusOutOpt, suppressResultOutOpt, statusUpdateFreqOpt }; + } + + @After + public void tearDown() { + + } + + @Test + public void testCluStreamModel() throws Exception { + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + FileUtils.forceMkdir(new File(BASE_DIR)); + + Task task = ClassOption.cliStringToObject(CLISTRING, Task.class, extraOptions); + task.setFactory(new SimpleComponentFactory()); + task.init(); + SimpleEngine.submitTopology(task.getTopology()); + + File fileModel = new File(BASE_DIR + "/clu-model"); + File fileData = new File(BASE_DIR + "/clu-data"); + + ArrayList points = (ArrayList) SerializeUtils.readFromFile(fileData); + CluStreamModel cluStreamModel = (CluStreamModel) SerializeUtils.readFromFile(fileModel); + + assert points != null; + ArrayList dataInstances = new ArrayList<>(); + for (DataPoint point : points) { + ClusterDataInstance dataInstance = InstanceUtils.reConvertClusterDataInstance(point); + dataInstances.add(dataInstance); + System.out.println(Arrays.toString(cluStreamModel.predict(dataInstance))); + } + + assert cluStreamModel != null; + System.out.println(cluStreamModel.toString()); + + MeasureCollection measure = new SSQ(); + double score = cluStreamModel.evaluate(dataInstances, measure); + System.out.println(score); + + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + } +} diff --git a/samoa-local/src/test/java/org/apache/samoa/serialize/EnsembleModelTest.java b/samoa-local/src/test/java/org/apache/samoa/serialize/EnsembleModelTest.java new file mode 100644 index 00000000..63fe4cec --- /dev/null +++ b/samoa-local/src/test/java/org/apache/samoa/serialize/EnsembleModelTest.java @@ -0,0 +1,108 @@ +package org.apache.samoa.serialize; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2015 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import com.github.javacliparser.ClassOption; +import com.github.javacliparser.FlagOption; +import com.github.javacliparser.IntOption; +import com.github.javacliparser.Option; +import junit.framework.TestCase; +import org.apache.commons.io.FileUtils; +import org.apache.samoa.instances.Instance; +import org.apache.samoa.learners.InstanceUtils; +import org.apache.samoa.learners.classifiers.ClassificationDataInstance; +import org.apache.samoa.learners.classifiers.ensemble.EnsembleModel; +import org.apache.samoa.moa.core.SerializeUtils; +import org.apache.samoa.tasks.Task; +import org.apache.samoa.topology.impl.SimpleComponentFactory; +import org.apache.samoa.topology.impl.SimpleEngine; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; + +public class EnsembleModelTest extends TestCase { + private static final String ENS_BASE_DIR = "bagging"; + private static final String BASE_DIR = "vht"; + private static final int NUM_MODEL_IN_DIR = 10; + + private static final int numberNumericFeatures = 10; + private static final int numberNominalFeatures = 10; + private static final String CLISTRING = + "PrequentialEvaluation -i 1000000 -f 100000 " + + "-l (classifiers.ensemble.Bagging -s 10 -l (classifiers.trees.VerticalHoeffdingTree)) " + + "-s (generators.RandomTreeGenerator -c 2 -o " + + numberNominalFeatures + " -u " + numberNumericFeatures +")"; + + private static final String SUPPRESS_STATUS_OUT_MSG = "Suppress the task status output. Normally it is sent to stderr."; + private static final String SUPPRESS_RESULT_OUT_MSG = "Suppress the task result output. Normally it is sent to stdout."; + private static final String STATUS_UPDATE_FREQ_MSG = "Wait time in milliseconds between status updates."; + + private Option[] extraOptions; + + @Before + public void setUp() { + FlagOption suppressStatusOutOpt = new FlagOption("suppressStatusOut", 'S', SUPPRESS_STATUS_OUT_MSG); + FlagOption suppressResultOutOpt = new FlagOption("suppressResultOut", 'R', SUPPRESS_RESULT_OUT_MSG); + IntOption statusUpdateFreqOpt = new IntOption("statusUpdateFrequency", 'F', STATUS_UPDATE_FREQ_MSG, 1000, 0, + Integer.MAX_VALUE); + extraOptions = new Option[] { suppressStatusOutOpt, suppressResultOutOpt, statusUpdateFreqOpt }; + } + + @After + public void tearDown() { + + } + + @Test + public void testEnsembleModel() throws Exception { + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + FileUtils.forceMkdir(new File(BASE_DIR)); + FileUtils.forceDeleteOnExit(new File(ENS_BASE_DIR)); + FileUtils.forceMkdir(new File(ENS_BASE_DIR)); + + Task task = ClassOption.cliStringToObject(CLISTRING, Task.class, extraOptions); + task.setFactory(new SimpleComponentFactory()); + task.init(); + SimpleEngine.submitTopology(task.getTopology()); + + for (int i = 0; i < NUM_MODEL_IN_DIR; i++) { + File fileModel = new File(ENS_BASE_DIR + "/bagging-model-" + i); + File fileData = new File(BASE_DIR + "/vht-data-0-" + i); + + EnsembleModel em = (EnsembleModel) SerializeUtils.readFromFile(fileModel); + Instance inst = (Instance) SerializeUtils.readFromFile(fileData); + System.out.println("=== model: " + i + " ==="); + + ClassificationDataInstance dataInstance = + InstanceUtils.reConvertClassificationDataInstance(inst,numberNominalFeatures, numberNumericFeatures); + + System.out.println(Arrays.toString(em.predict(dataInstance))); + System.out.println("true predict: " + (int) inst.classValue()); + System.out.println("predict: " + em.evaluate(dataInstance)); + } + + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + FileUtils.forceDeleteOnExit(new File(ENS_BASE_DIR)); + } +} diff --git a/samoa-local/src/test/java/org/apache/samoa/serialize/HoeffdingTreeModelTest.java b/samoa-local/src/test/java/org/apache/samoa/serialize/HoeffdingTreeModelTest.java new file mode 100644 index 00000000..575a396c --- /dev/null +++ b/samoa-local/src/test/java/org/apache/samoa/serialize/HoeffdingTreeModelTest.java @@ -0,0 +1,104 @@ +package org.apache.samoa.serialize; + +/* + * #%L + * SAMOA + * %% + * Copyright (C) 2014 - 2015 Apache Software Foundation + * %% + * Licensed 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. + * #L% + */ + +import com.github.javacliparser.ClassOption; +import com.github.javacliparser.FlagOption; +import com.github.javacliparser.IntOption; +import com.github.javacliparser.Option; +import junit.framework.TestCase; +import org.apache.commons.io.FileUtils; +import org.apache.samoa.instances.Instance; +import org.apache.samoa.learners.InstanceUtils; +import org.apache.samoa.learners.classifiers.ClassificationDataInstance; +import org.apache.samoa.learners.classifiers.trees.HoeffdingTreeModel; +import org.apache.samoa.moa.core.SerializeUtils; +import org.apache.samoa.tasks.Task; +import org.apache.samoa.topology.impl.SimpleComponentFactory; +import org.apache.samoa.topology.impl.SimpleEngine; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; + +public class HoeffdingTreeModelTest extends TestCase { + private static final String BASE_DIR = "vht"; + private static final int NUM_MODEL_IN_DIR = 10; + + private static final int numberNumericFeatures = 10; + private static final int numberNominalFeatures = 10; + private static final String CLISTRING = + "PrequentialEvaluation -i 1000000 -f 100000 " + + "-l (classifiers.trees.VerticalHoeffdingTree -p 4) " + + "-s (generators.RandomTreeGenerator -c 2 -o " + + numberNominalFeatures + " -u " + numberNumericFeatures +")"; + + private static final String SUPPRESS_STATUS_OUT_MSG = "Suppress the task status output. Normally it is sent to stderr."; + private static final String SUPPRESS_RESULT_OUT_MSG = "Suppress the task result output. Normally it is sent to stdout."; + private static final String STATUS_UPDATE_FREQ_MSG = "Wait time in milliseconds between status updates."; + + private Option[] extraOptions; + + @Before + public void setUp() { + FlagOption suppressStatusOutOpt = new FlagOption("suppressStatusOut", 'S', SUPPRESS_STATUS_OUT_MSG); + FlagOption suppressResultOutOpt = new FlagOption("suppressResultOut", 'R', SUPPRESS_RESULT_OUT_MSG); + IntOption statusUpdateFreqOpt = new IntOption("statusUpdateFrequency", 'F', STATUS_UPDATE_FREQ_MSG, 1000, 0, + Integer.MAX_VALUE); + extraOptions = new Option[] { suppressStatusOutOpt, suppressResultOutOpt, statusUpdateFreqOpt }; + } + + @After + public void tearDown() { + + } + + @Test + public void testHoeffdingTreeModel() throws Exception { + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + FileUtils.forceMkdir(new File(BASE_DIR)); + + Task task = ClassOption.cliStringToObject(CLISTRING, Task.class, extraOptions); + task.setFactory(new SimpleComponentFactory()); + task.init(); + SimpleEngine.submitTopology(task.getTopology()); + + for (int i = 0; i < NUM_MODEL_IN_DIR; i++) { + File fileModel = new File(BASE_DIR + "/vht-model-0-" + i); + File fileData = new File(BASE_DIR + "/vht-data-0-" + i); + + HoeffdingTreeModel htm = (HoeffdingTreeModel) SerializeUtils.readFromFile(fileModel); + Instance inst = (Instance) SerializeUtils.readFromFile(fileData); + System.out.println("=== model: " + i + " ==="); + + ClassificationDataInstance dataInstance = + InstanceUtils.reConvertClassificationDataInstance(inst,numberNominalFeatures, numberNumericFeatures); + + System.out.println(Arrays.toString(htm.predict(dataInstance))); + System.out.println("true predict: " + (int) inst.classValue()); + System.out.println("predict: " + htm.evaluate(dataInstance)); + } + + FileUtils.forceDeleteOnExit(new File(BASE_DIR)); + } +}