/*
 * Copyright (C) 2008-2015 by Holger Arndt
 *
 * This file is part of the Java Data Mining Package (JDMP).
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership and licensing.
 *
 * JDMP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * JDMP 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with JDMP; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

package org.jdmp.core.algorithm.regression;

import org.jdmp.core.algorithm.AbstractAlgorithm;
import org.jdmp.core.algorithm.Algorithm;
import org.jdmp.core.algorithm.basic.FMeasure;
import org.jdmp.core.algorithm.basic.Minus;
import org.jdmp.core.algorithm.basic.Precision;
import org.jdmp.core.algorithm.basic.Recall;
import org.jdmp.core.algorithm.basic.Sensitivity;
import org.jdmp.core.algorithm.basic.Specificity;
import org.jdmp.core.dataset.ListDataSet;
import org.jdmp.core.sample.Sample;
import org.jdmp.core.variable.Variable;
import org.ujmp.core.Matrix;
import org.ujmp.core.calculation.Calculation.Ret;
import org.ujmp.core.util.MathUtil;
import org.ujmp.core.util.concurrent.PFor;

public abstract class AbstractRegressor extends AbstractAlgorithm implements Regressor {
	private static final long serialVersionUID = 4674447558395794134L;

	public static final String OUTPUTERRORALGORITHM = "OutputErrorAlgorithm";

	public static final int TRAIN = 0;

	public static final int PREDICT = 1;

	public int mode = TRAIN;

	private int iteration = 0;

	private String inputLabel;
	private String targetLabel;
	private String weightLabel;

	public AbstractRegressor(String inputLabel, String targetLabel, String weightLabel) {
		super();
		this.inputLabel = inputLabel;
		this.targetLabel = targetLabel;
		this.weightLabel = weightLabel;
		setAlgorithm(OUTPUTERRORALGORITHM, new Minus());
	}

	public AbstractRegressor(String inputLabel, String targetLabel) {
		this(inputLabel, targetLabel, WEIGHT);
	}

	public AbstractRegressor(String inputLabel) {
		this(inputLabel, TARGET);
	}

	public AbstractRegressor() {
		this(INPUT);
	}

	public int getClassCount(ListDataSet dataSet) {
		return (int) dataSet.get(0).getAsMatrix(getTargetLabel()).toRowVector(Ret.NEW)
				.getRowCount();
	}

	public boolean isDiscrete(ListDataSet dataSet) {
		for (Sample s : dataSet) {
			Matrix input = s.getAsMatrix(getInputLabel());
			for (long[] c : input.availableCoordinates()) {
				if (!MathUtil.isDiscrete(input.getAsDouble(c))) {
					return false;
				}
			}
		}
		return true;
	}

	public int getFeatureCount(ListDataSet dataSet) {
		return (int) dataSet.iterator().next().getAsMatrix(getInputLabel()).toRowVector(Ret.NEW)
				.getRowCount();
	}

	public String getInputLabel() {
		return inputLabel;
	}

	public String getWeightLabel() {
		return weightLabel;
	}

	public void setWeightLabel(String weightLabel) {
		this.weightLabel = weightLabel;
	}

	public void setInputLabel(String inputLabel) {
		this.inputLabel = inputLabel;
	}

	public String getTargetLabel() {
		return targetLabel;
	}

	public void setTargetLabel(String targetLabel) {
		this.targetLabel = targetLabel;
	}

	public void trainOne(Matrix input, Matrix sampleWeight, Matrix targetOutput) {
		throw new RuntimeException("not supported");
	}

	public final void predictOne(Sample sample) {
		Matrix predicted = predictOne(sample.getAsMatrix(getInputLabel()));
		predicted = predicted.toColumnVector(Ret.LINK);
		sample.put(PREDICTED, predicted);

		if (sample.getAsMatrix(getTargetLabel()) != null) {
			Matrix target = sample.getAsMatrix(getTargetLabel()).toColumnVector(Ret.LINK);
			Matrix error = target.minus(predicted);
			sample.put(DIFFERENCE, error);
			sample.put(RMSE, Matrix.Factory.linkToValue(error.getRMS()));
		}

		sample.fireValueChanged();
	}

	public final void trainOne(Matrix input, Matrix targetOutput) {
		trainOne(input, Matrix.Factory.linkToValue(1.0), targetOutput);
	}

	public final void trainOne(Sample sample) {
		Matrix input = sample.getAsMatrix(getInputLabel());
		Matrix weight = sample.getAsMatrix(getWeightLabel());
		Matrix target = sample.getAsMatrix(getTargetLabel());
		trainOne(input, weight, target);
	}

	public void predictAll(final ListDataSet dataSet) {

		new PFor(0, dataSet.size() - 1) {

			@Override
			public void step(int i) {
				Sample sample = dataSet.get(i);
				predictOne(sample);
			}
		};

		if (dataSet.get(0).getAsMatrix(getTargetLabel()) != null) {
			final Matrix confusion;
			double error = 0.0;
			int correctCount = 0;
			int errorCount = 0;
			final int classCount;

			classCount = getClassCount(dataSet);
			confusion = Matrix.Factory.zeros(classCount, classCount);
			confusion.setDimensionLabel(Matrix.ROW, "expected");
			confusion.setDimensionLabel(Matrix.COLUMN, "predicted");

			for (Sample sample : dataSet) {

				double rmse = sample.getAsMatrix(RMSE).getEuklideanValue();
				error += Math.pow(rmse, 2.0);

				int recognized = sample.getRecognizedClass();
				int targetClass = sample.getTargetClass();

				if (classCount == 1 || recognized == -1) {
					confusion.setAsDouble(confusion.getAsDouble(0, 0) + 1, 0, 0);
				} else {
					confusion.setAsDouble(confusion.getAsDouble(targetClass, recognized) + 1,
							targetClass, recognized);
				}

				if (sample.isCorrect()) {
					correctCount++;
					// weight = weight * 0.99;
				} else {
					errorCount++;
					// weight = weight / 0.99;
				}

				// ((RegressionSample) sample).setWeight(weight);

			}

			Matrix rmse = Matrix.Factory.linkToValue(Math.sqrt(error / dataSet.size()));
			rmse.setLabel("RMSE with " + getLabel());
			dataSet.setMatrix(Variable.RMSE, rmse);

			double maxRMSE = 0.0;
			double minRMSE = 1e100;
			double sumRMSE = 0;
			for (Sample s : dataSet) {
				Matrix m = s.getAsMatrix("RMSE");
				if (m != null) {
					double sampleRMSE = m.doubleValue();
					sumRMSE += sampleRMSE;
					if (sampleRMSE > maxRMSE) {
						maxRMSE = sampleRMSE;
					}
					if (sampleRMSE < minRMSE) {
						minRMSE = sampleRMSE;
					}
				}
			}

			// calculate sample weight
			// if (maxRMSE > 0 && maxRMSE != minRMSE) {
			// for (Sample s : dataSet.getSampleMap()) {
			// Matrix m = s.getMatrix("RMSE");
			// if (m != null) {
			// double sampleWeight = (m.doubleValue() / (sumRMSE));
			// s.setMatrix("SampleWeight",
			// Matrix.Factory.linkToValue(sampleWeight));
			// }
			// }
			// }

			confusion.setLabel("Confusion with " + getLabel());
			dataSet.setMatrix(Variable.CONFUSION, confusion);

			Matrix accuracy = Matrix.Factory.linkToValue((double) correctCount
					/ (double) dataSet.size());
			accuracy.setLabel("Accuracy with " + getLabel());
			dataSet.setMatrix(Variable.ACCURACY, accuracy);

			Matrix errorMatrix = Matrix.Factory.linkToValue(errorCount);
			errorMatrix.setLabel("Errors with " + getLabel());
			dataSet.setMatrix(Variable.ERRORCOUNT, errorMatrix);

			Matrix sensitivity = (Matrix) new Sensitivity().calculate(confusion).get(
					getTargetLabel());
			dataSet.setMatrix(Variable.SENSITIVITY, sensitivity);

			Matrix specificity = (Matrix) new Specificity().calculate(confusion).get(
					getTargetLabel());
			dataSet.setMatrix(Variable.SPECIFICITY, specificity);

			Matrix precision = (Matrix) new Precision().calculate(confusion).get(getTargetLabel());
			dataSet.setMatrix(Variable.PRECISION, precision);

			Matrix recall = (Matrix) new Recall().calculate(confusion).get(getTargetLabel());
			dataSet.setMatrix(Variable.RECALL, recall);

			Matrix fmeasure = (Matrix) new FMeasure().calculate(confusion).get(getTargetLabel());
			dataSet.setMatrix(Variable.FMEASURE, fmeasure);

			Matrix fmeasureMacro = fmeasure.mean(Ret.NEW, Matrix.ALL, false);
			dataSet.setMatrix(Variable.FMEASUREMACRO, fmeasureMacro);

			iteration++;
			System.out.println("Iteration: " + iteration + ", RMSE: " + rmse.doubleValue()
					+ ", errors: " + errorCount + ", accuracy: " + accuracy.doubleValue());

		}

		dataSet.fireValueChanged();
	}

	public Algorithm getOutputErrorAlgorithm() {
		return getAlgorithmMap().get(OUTPUTERRORALGORITHM);
	}

	public void setOutputErrorAlgorithm(Algorithm a) {
		setAlgorithm(OUTPUTERRORALGORITHM, a);
	}

	public int getMode() {
		return mode;
	}

	public void setMode(int mode) {
		this.mode = mode;
	}

}

 

Ads help maintain this website.