Java tutorial
/******************************************************************************* * Copyright (C) 2014 Anonymized * Contributors: * Anonymized * * This file is part of ICDM2014SUBMISSION. * This is a program related to the paper "Dynamic Time Warping Averaging of * Time Series allows more Accurate and Faster Classification" submitted to the * 2014 Int. Conf. on Data Mining. * * ICDM2014SUBMISSION is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * ICDM2014SUBMISSION is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ICDM2014SUBMISSION. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package classif.dropx; import items.Sequence; import items.ClassedSequence; import items.SortedSequence; import java.util.ArrayList; import java.util.Collections; import weka.core.Instances; public class DTWKNNClassifierDropOne extends PrototyperSorted { private static final long serialVersionUID = 3200558026536565321L; @Override protected void buildSortedSequences(Instances data) { sortedSequences = new ArrayList<ClassedSequence>(); // precompute distances double[][] distances = new double[data.numInstances()][data.numInstances()]; for (int i = 0; i < distances.length; i++) { for (int j = i + 1; j < distances[i].length; j++) { distances[i][j] = sequences[i].distance(sequences[j]); distances[j][i] = distances[i][j]; } } // init temp structure ArrayList<SortedSequence> tmpSequences = new ArrayList<SortedSequence>(); for (int i = 0; i < sequences.length; i++) { tmpSequences.add(new SortedSequence(new Sequence(sequences[i]), i, 0.0, classMap[i])); } // sort by nearest enemy for (int i = 0; i < tmpSequences.size(); i++) { // find nearest enemy double minD = Double.MAX_VALUE; for (int j = 0; j < tmpSequences.size(); j++) { // avoid diagonal if (j != i && !tmpSequences.get(i).classValue.equals(tmpSequences.get(j).classValue)) { // check distance double tmpD = distances[tmpSequences.get(i).index][tmpSequences.get(j).index]; // if we found a new NN if (tmpD < minD) { minD = tmpD; } } } tmpSequences.get(i).sortingValue = minD; } Collections.sort(tmpSequences); // compute nearest neigbor and candidates ArrayList<Integer> toRemove = new ArrayList<Integer>(); while (tmpSequences.size() > 2) { /** compute the NN and candidates **/ int[] nearestNeighbor = new int[data.numInstances()]; ArrayList<Integer>[] candidates = new ArrayList[data.numInstances()]; // for each object for (int i = 0; i < tmpSequences.size(); i++) { // looking for the nearest double minD = Double.MAX_VALUE; int nn = -1; // we look for the NN for (int j = 0; j < tmpSequences.size(); j++) { // avoid diagonal if (j != i) { // check distance double tmpD = distances[tmpSequences.get(i).index][tmpSequences.get(j).index]; // if we found a new NN if (tmpD < minD) { nn = j; minD = tmpD; } } } if (candidates[nn] == null) { candidates[nn] = new ArrayList<Integer>(); } // we tell to the NN that he is the winner candidates[nn].add(i); // we store the NN nearestNeighbor[i] = nn; } // remove object one by one according to with/without rule int toRem = -1; for (int i = 0; i < tmpSequences.size(); i++) { int with = 0; int without = 0; if (candidates[i] == null) { toRem = i; // System.out.println("candidate null break"); break; } else { ArrayList<Integer> candidatesOf = candidates[i]; // compute WITH for (int j = 0; j < candidatesOf.size(); j++) { if (tmpSequences.get(i).classValue .equals(tmpSequences.get(candidatesOf.get(j)).classValue)) { with++; } } // compute WITHOUT int[] newNearestNeighbor = new int[candidatesOf.size()]; double[] minForNewNearestNeighbor = new double[candidatesOf.size()]; for (int k = 0; k < minForNewNearestNeighbor.length; k++) { minForNewNearestNeighbor[k] = Double.MAX_VALUE; } // for each object for (int k = 0; k < tmpSequences.size(); k++) { // if different from current if (k != i) { // get the object SortedSequence tmpSeq = tmpSequences.get(k); for (int l = 0; l < newNearestNeighbor.length; l++) { if (k != candidatesOf.get(l)) { double tmpD = distances[tmpSeq.index][tmpSequences .get(candidatesOf.get(l)).index]; if (tmpD < minForNewNearestNeighbor[l]) { minForNewNearestNeighbor[l] = tmpD; newNearestNeighbor[l] = k; } } } } } for (int j = 0; j < newNearestNeighbor.length; j++) { if (tmpSequences.get(newNearestNeighbor[j]).classValue .equals(tmpSequences.get(candidatesOf.get(j)).classValue)) { without++; } } if (without >= with) { toRem = i; break; } } } // no match found if (toRem == -1) { toRem = 0; } toRemove.add(tmpSequences.get(toRem).index); tmpSequences.remove(toRem); } // create the list used to return the prototypes for (int j = toRemove.size() - 1; j >= 0; j--) { sortedSequences.add(new ClassedSequence(sequences[toRemove.get(j)], classMap[toRemove.get(j)])); } } }