gov.sandia.cognition.statistics.method.NemenyiConfidence Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gov-sandia-cognition-learning-core Show documentation
Show all versions of gov-sandia-cognition-learning-core Show documentation
Algorithms and components for machine learning and statistics.
The newest version!
/*
* File: NemenyiConfidence.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright May 9, 2011, Sandia Corporation.
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
* license for use of this work by or on behalf of the U.S. Government.
* Export of this program may require a license from the United States
* Government. See CopyrightHistory.txt for complete details.
*
*/
package gov.sandia.cognition.statistics.method;
import gov.sandia.cognition.statistics.distribution.StudentizedRangeDistribution;
import gov.sandia.cognition.annotation.PublicationReference;
import gov.sandia.cognition.annotation.PublicationType;
import gov.sandia.cognition.collection.CollectionUtil;
import gov.sandia.cognition.math.matrix.Matrix;
import gov.sandia.cognition.math.matrix.MatrixFactory;
import gov.sandia.cognition.util.ObjectUtil;
import java.util.ArrayList;
import java.util.Collection;
/**
* The Nemenyi test is the rank-based analogue of the Tukey multiple-comparison
* test. Its primary use is in determining which treatments are significant
* after a Friedman's test indicates that one of the treatments is statistically
* different.
* @author Kevin R. Dixon
* @since 3.1
*/
@ConfidenceTestAssumptions(
name="Nemenyi's test",
description={
"Nemenyi's test determines which treatment is statistically different from a multiple comparison.",
"This is a nonparametric rank-based alternative to Tukey's multiple comparison test."
},
assumptions={
"All data came from same distribution, without considering treatment effects.",
"Measurements are independent and equivalent within a treatment.",
"All observations are independent."
},
nullHypothesis="Each treatment has no effect on the rank-based outcome of the subjects",
dataPaired=true,
dataSameSize=true,
distribution=StudentizedRangeDistribution.class,
reference={
@PublicationReference(
author="Janez Demsar",
title="Statistical Comparisons of Classifiers over Multiple Data Sets",
type=PublicationType.Journal,
publication="Journal of Machine Learning Research",
year=2006,
url="http://www.jmlr.org/papers/volume7/demsar06a/demsar06a.pdf"
)
,
@PublicationReference(
author="Wikipedia",
title="Multiple comparisons, Post-hoc testing of ANOVAs",
type=PublicationType.WebPage,
year=2011,
url="http://en.wikipedia.org/wiki/Multiple_comparisons#Post-hoc_testing_of_ANOVAs"
)
}
)
public class NemenyiConfidence
extends AbstractMultipleHypothesisComparison, NemenyiConfidence.Statistic>
{
/**
* Default instance.
*/
public static final NemenyiConfidence INSTANCE = new NemenyiConfidence();
/**
* Creates a new instance of NemenyiConfidence
*/
public NemenyiConfidence()
{
super();
}
@Override
public NemenyiConfidence.Statistic evaluateNullHypotheses(
final Collection extends Collection extends Number>> data,
final double uncompensatedAlpha)
{
// There are "K" treatments
final int K = data.size();
// There are "N" subjects for each treatment
int N = CollectionUtil.getFirst(data).size();
ArrayList treatmentRankMeans =
FriedmanConfidence.computeTreatmentRankMeans(data);
final double standardError = Math.sqrt( K*(K+1.0) / (6.0*N) );
return new NemenyiConfidence.Statistic(
uncompensatedAlpha, N, treatmentRankMeans, standardError );
}
/**
* Statistic from Nemenyi's multiple comparison test
*/
public static class Statistic
extends AbstractMultipleHypothesisComparison.Statistic
{
/**
* Number of subjects in each treatment
*/
private int subjectCount;
/**
* Mean for each treatment
*/
private ArrayList treatmentRankMeans;
/**
* Standard error of the entire experiment
*/
private double standardError;
/**
* Creates a new instance of StudentizedMultipleComparisonStatistic
* @param uncompensatedAlpha
* Uncompensated alpha (p-value threshold) for the multiple comparison
* test
* @param subjectCount
* Number of subjects in each treatment
* @param treatmentRankMeans
* Mean for each treatment
* @param standardError
* Standard error of the entire experiment
*/
public Statistic(
final double uncompensatedAlpha,
final int subjectCount,
final ArrayList treatmentRankMeans,
final double standardError )
{
this.treatmentCount = treatmentRankMeans.size();
this.uncompensatedAlpha = uncompensatedAlpha;
this.subjectCount = subjectCount;
this.treatmentRankMeans = treatmentRankMeans;
this.standardError = standardError;
this.testStatistics = this.computeTestStatistics(
subjectCount, treatmentRankMeans, standardError);
this.nullHypothesisProbabilities = this.computeNullHypothesisProbabilities(
subjectCount, this.testStatistics );
}
/**
* Computes the test statistic for all treatments
* @param subjectCount
* Number of subjects in each treatment
* @param treatmentRankMeans
* Mean for each treatment
* @param standardError
* Standard error of the entire experiment
* @return
* Test statistics, where the (i,j) element compares treatment "i" to
* treatment "j", the statistic is symmetric
*/
public Matrix computeTestStatistics(
final int subjectCount,
final ArrayList treatmentRankMeans,
final double standardError )
{
int K = treatmentRankMeans.size();
Matrix Z = MatrixFactory.getDefault().createMatrix(K,K);
for( int i = 0; i < K; i++ )
{
final double yi = treatmentRankMeans.get(i);
for( int j = i+1; j < K; j++ )
{
final double yj = treatmentRankMeans.get(j);
final double zij = Math.abs(yi-yj) / standardError;
Z.setElement(i, j, zij);
Z.setElement(j, i, zij);
}
}
return Z;
}
/**
* Computes null-hypothesis probability for the (i,j) treatment comparison
* @param subjectCount
* Number of subjects in the experiment
* @param Z
* Test statistic for the (i,j) treatment comparison
* @return
* Null-hypothesis probability for the (i,j) treatment comparison
*/
protected Matrix computeNullHypothesisProbabilities(
final int subjectCount,
final Matrix Z )
{
final int K = Z.getNumRows();
final int N = subjectCount;
Matrix P = MatrixFactory.getDefault().createMatrix(K, K);
StudentizedRangeDistribution.CDF cdf =
new StudentizedRangeDistribution.CDF( K, K*N-1 );
for( int i = 0; i < K; i++ )
{
// A classifier is equal to itself.
P.setElement(i, i, 1.0);
for( int j = i+1; j < K; j++ )
{
// The difference is symmetric
double zij = Z.getElement(i,j);
double pij = 1.0-cdf.evaluate( zij*Math.sqrt(2) );
P.setElement(i, j, pij);
P.setElement(j, i, pij);
}
}
return P;
}
@Override
public Statistic clone()
{
Statistic clone = (Statistic) super.clone();
clone.treatmentRankMeans = ObjectUtil.cloneSmartElementsAsArrayList(
this.getTreatmentMeans() );
return clone;
}
/**
* Getter for subjectCount
* @return
* Number of subjects in the experiment
*/
public int getSubjectCount()
{
return this.subjectCount;
}
/**
* Getter for standardError
* @return
* Standard error of the entire experiment
*/
public double getStandardError()
{
return this.standardError;
}
/**
* Getter for treatmentRankMeans
* @return
* Mean for each treatment
*/
public ArrayList getTreatmentMeans()
{
return this.treatmentRankMeans;
}
@Override
public boolean acceptNullHypothesis(
final int i,
final int j)
{
return this.getNullHypothesisProbability(i, j) >= this.getUncompensatedAlpha();
}
}
}