/* (non-Javadoc) * @see datamining.clustering.protoype.AbstractPrototypeClusteringAlgorithm#getObjectiveFunctionValue() */ @Override public double getObjectiveFunctionValue() { if (!this.initialized) throw new AlgorithmNotInitializedException("Prototypes not initialized."); int i, j; // i: index for clusters // j: index for data objects // k: index for dimensions, others double objectiveFunctionValue = 0.0d; double distanceSum = 0.0d; // the sum_i dist[i][l]^{2/(1-fuzzifier)}: the sum of all parametrised distances for // one cluster l double doubleTMP = 0.0d; // a temporarly variable for multiple perpuses double[] fuzzDistances = new double[this.getClusterCount()]; double[] distancesSq = new double[this.getClusterCount()]; double minDistValue = 0.0d; for (j = 0; j < this.getDataCount(); j++) { distanceSum = 0.0d; minDistValue = Double.MAX_VALUE; for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = this.dist.distanceSq(this.data.get(j).element, this.prototypes.get(i).getPosition()); distancesSq[i] = doubleTMP; if (minDistValue > doubleTMP) minDistValue = doubleTMP; } minDistValue *= this.distanceMultiplierConstant; for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = distancesSq[i] - minDistValue; if (doubleTMP <= 0.0d) { fuzzDistances[i] = 1.0d; } else { doubleTMP = 1.0d / doubleTMP; fuzzDistances[i] = doubleTMP; distanceSum += doubleTMP; } } // don't check for distance sum to be zero.. that would just be rediculus!! for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = fuzzDistances[i] / distanceSum; objectiveFunctionValue += MyMath.pow(doubleTMP, this.fuzzifier) * (distancesSq[i] - minDistValue); } } return objectiveFunctionValue; }
@Override public void apply(int steps) { if (!this.initialized) throw new AlgorithmNotInitializedException("Prototypes not initialized."); int i, j, k, t; // i: index for clusters // j: index for data objects // k: index for dimensions, others // t: index for iterations double distanceSum = 0.0d; // the sum_i dist[i][l]^{2/(1-fuzzifier)}: the sum of all parametrised distances for // one cluster l double doubleTMP = 0.0d; // a temporarly variable for multiple perpuses double maxPrototypeMovement = 0.0d; ArrayList<T> newPrototypePosition = new ArrayList<T>(this.getClusterCount()); for (i = 0; i < this.getClusterCount(); i++) newPrototypePosition.add(this.vs.getNewAddNeutralElement()); double[] fuzzDistances = new double[this.getClusterCount()]; double[] membershipValues = new double[this.getClusterCount()]; double[] membershipSum = new double[this.getClusterCount()]; T tmpX = this.vs.getNewAddNeutralElement(); double minDistValue = 0.0d; int[] zeroDistanceIndexList = new int[this.getClusterCount()]; int zeroDistanceCount; for (t = 0; t < steps; t++) { // reset values maxPrototypeMovement = 0.0d; for (i = 0; i < this.getClusterCount(); i++) { this.vs.resetToAddNeutralElement(newPrototypePosition.get(i)); membershipSum[i] = 0.0d; } // update membership values for (j = 0; j < this.getDataCount(); j++) { for (i = 0; i < this.getClusterCount(); i++) zeroDistanceIndexList[i] = -1; zeroDistanceCount = 0; distanceSum = 0.0d; minDistValue = Double.MAX_VALUE; for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = this.dist.distanceSq(this.data.get(j).element, this.prototypes.get(i).getPosition()); fuzzDistances[i] = doubleTMP; if (minDistValue > doubleTMP) minDistValue = doubleTMP; } minDistValue *= this.distanceMultiplierConstant; for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = fuzzDistances[i] - minDistValue; if (doubleTMP <= 0.0d) { doubleTMP = 0.0d; zeroDistanceIndexList[zeroDistanceCount] = i; zeroDistanceCount++; } else { doubleTMP = 1.0d / doubleTMP; fuzzDistances[i] = doubleTMP; distanceSum += doubleTMP; } } // special case handling: if one (or more) prototype sits on top of a data object if (zeroDistanceCount > 0) { for (i = 0; i < this.getClusterCount(); i++) { membershipValues[i] = 0.0d; } doubleTMP = 1.0d / ((double) zeroDistanceCount); for (k = 0; k < zeroDistanceCount; k++) { membershipValues[zeroDistanceIndexList[k]] = doubleTMP; } } else { for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = fuzzDistances[i] / distanceSum; membershipValues[i] = doubleTMP; } } for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = MyMath.pow(membershipValues[i], this.fuzzifier); membershipSum[i] += doubleTMP; this.vs.copy(tmpX, this.data.get(j).element); this.vs.mul(tmpX, doubleTMP); this.vs.add(newPrototypePosition.get(i), tmpX); } } // update prototype positions for (i = 0; i < this.getClusterCount(); i++) { doubleTMP = 1.0d / membershipSum[i]; this.vs.mul(newPrototypePosition.get(i), doubleTMP); } // copy new prototype values into prototypes wrt. learning factor for (i = 0; i < this.getClusterCount(); i++) { if (Math.abs(this.learningFactor - 1.0d) > 0.01d) { this.vs.sub(newPrototypePosition.get(i), this.prototypes.get(i).getPosition()); this.vs.mul(newPrototypePosition.get(i), this.learningFactor); this.vs.add(newPrototypePosition.get(i), this.prototypes.get(i).getPosition()); } doubleTMP = this.dist.distanceSq(this.prototypes.get(i).getPosition(), newPrototypePosition.get(i)); maxPrototypeMovement = (doubleTMP > maxPrototypeMovement) ? doubleTMP : maxPrototypeMovement; this.prototypes.get(i).moveTo(newPrototypePosition.get(i)); } this.iterationComplete(); if (maxPrototypeMovement < this.epsilon * this.epsilon) break; } }