Class NonlinearityTests

java.lang.Object
edu.cmu.tetrad.search.utils.NonlinearityTests

public final class NonlinearityTests extends Object
Practical nonlinearity tests for conditional mean E(Y|X). All methods assume continuous variables; callers should remove missing rows via clean(...).

All tests internally center y and each column of X (on copies; caller arrays are not modified), so the linear null hypothesis includes an intercept. Without this, any linear relationship with a nonzero intercept - which is the typical case for raw (uncentered) real data - is misspecified under the no-intercept fits used here, and the tests reject "linearity" with probability approaching 1 for reasons that have nothing to do with nonlinearity.

Caveat, deliberate and documented: these are conditional-MEAN tests computed under homoskedasticity assumptions. Heteroskedastic but linear-in-mean data inflates their type I error above nominal (verified by harness on y = x + (0.5 + |x|) e: rejection rates of roughly 10-35 percent at alpha = 0.05). A rejection therefore supports "not linear-homoskedastic" more strongly than "nonlinear conditional mean" when heteroskedasticity is plausible.

Second caveat: these tests are about the conditional mean of the particular regression given, and that judgment is direction-relative. For a linear non-Gaussian pair y = bx + e, the forward mean E[y|x] is exactly linear (the tests hold their size under skewed or heavy-tailed noise; harness-verified), but the anticausal mean E[x|y] is genuinely nonlinear whenever the pair is non-Gaussian with distinct component distributions - the same asymmetry LiNGAM exploits - and the tests correctly reject there (harness-verified at up to 100 percent). A rejection on a pair of unknown causal direction therefore does NOT establish that the system is nonlinear: it may be a linear non-Gaussian system tested anticausally. Testing both directions disambiguates: linear both ways suggests a linear (near-)Gaussian pair; linear one way and nonlinear the other suggests a linear non-Gaussian pair with the linear direction causal; nonlinear both ways suggests a genuinely nonlinear system.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final class 
    Represents cleaned data for nonlinearity tests, with NaNs removed from y and X.
    static final class 
    Encapsulates the result of a statistical test, including the test statistic, p-value, and the decision to reject the null hypothesis.
  • Method Summary

    Modifier and Type
    Method
    Description
    additiveHingeTest(double[] y, double[][] X, double alpha)
    Performs an additive-component test using hinge basis functions to assess nonlinearity in the data.
    clean(double[] y, double[][] X)
    Remove rows with NaNs in y or any X column.
    conditionalMomentTest(double[] y, double[][] X, double alpha)
    Performs a conditional moment test to assess the specification of a linear model.
    cvAdditiveVsRff(double[] y, double[][] X, int kfold, double alpha)
    Tests additivity of the conditional mean E(Y|X) by a nested cross-validated comparison: an additive ridge model (per-variable hinge features plus per-variable one-dimensional RFF features) versus the same additive design augmented with joint RFF (RBF random Fourier) features.
    cvLinearVsNonlinear(double[] y, double[][] X, int kfold, double alpha)
    Performs cross-validation to compare linear ridge regression with nonlinear kernel ridge regression using Random Fourier Features (RFF).
    resetTest(double[] y, double[][] X, double alpha)
    Performs the RESET (Regression Equation Specification Error Test) to assess model specification.

    Methods inherited from class Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • clean

      public static NonlinearityTests.CleanData clean(double[] y, double[][] X)
      Remove rows with NaNs in y or any X column.
      Parameters:
      y - the array of dependent variable values
      X - the 2D array of independent variable values
      Returns:
      a CleanData object containing the cleaned data arrays
    • resetTest

      public static NonlinearityTests.TestResult resetTest(double[] y, double[][] X, double alpha)
      Performs the RESET (Regression Equation Specification Error Test) to assess model specification. The test evaluates whether nonlinear transformations of the predicted values improve the model's fit.
      Parameters:
      y - the response variable array, of length n
      X - the predictor variable matrix, of size n-by-d
      alpha - the significance level for the hypothesis test
      Returns:
      a TestResult object containing the test statistic, p-value, and a boolean indicating whether the null hypothesis is rejected
    • cvLinearVsNonlinear

      public static NonlinearityTests.TestResult cvLinearVsNonlinear(double[] y, double[][] X, int kfold, double alpha)
      Performs cross-validation to compare linear ridge regression with nonlinear kernel ridge regression using Random Fourier Features (RFF).
      Parameters:
      y - The target variable values.
      X - The feature matrix.
      kfold - The number of folds for cross-validation.
      alpha - The significance level for hypothesis testing.
      Returns:
      TestResult containing F-statistic, p-value, and rejection status.
    • conditionalMomentTest

      public static NonlinearityTests.TestResult conditionalMomentTest(double[] y, double[][] X, double alpha)
      Performs a conditional moment test to assess the specification of a linear model. This test evaluates whether non-linear transformations of the predictor variables contain additional information not captured by the linear model.
      Parameters:
      y - the response variable array, of length n
      X - the predictor variable matrix, of size n-by-d
      alpha - the significance level for hypothesis testing
      Returns:
      a TestResult object containing the test statistic, p-value, and a boolean indicating whether the null hypothesis of linearity is rejected
    • additiveHingeTest

      public static NonlinearityTests.TestResult additiveHingeTest(double[] y, double[][] X, double alpha)
      Performs an additive-component test using hinge basis functions to assess nonlinearity in the data.
      Parameters:
      y - The response variable.
      X - The predictor variables.
      alpha - The significance level for hypothesis testing.
      Returns:
      A TestResult object containing the test statistic, p-value, and rejection decision.
    • cvAdditiveVsRff

      public static NonlinearityTests.TestResult cvAdditiveVsRff(double[] y, double[][] X, int kfold, double alpha)
      Tests additivity of the conditional mean E(Y|X) by a nested cross-validated comparison: an additive ridge model (per-variable hinge features plus per-variable one-dimensional RFF features) versus the same additive design augmented with joint RFF (RBF random Fourier) features. Because the models are nested on a shared additive base, the joint block only has to explain the non-additive remainder, and the full model cannot lose the marginals; the CV comparison therefore concentrates on interaction signal. The per-variable RFF features matter for size: they let the additive model represent smooth additive nonlinearity (e.g. sine components) as well as the joint block can, so additive lack-of-fit in a fixed hinge basis is not mistaken for non-additivity. Ridge strength is chosen on each training fold by GCV over a small log grid on the full model and shared by both models (see the in-method comment for why a shared penalty is a size safeguard), and inference pools the per-observation paired squared-error differences across all held-out points into a one-sided Wilcoxon signed-rank test (n observations rather than kfold fold means; rank-based because squared-error differences are heavy-tailed).

      Design notes, deliberate and documented. (1) The previous implementation compared a non-nested pair (additive hinge-ridge vs a standalone 600-feature RFF-ridge at a fixed ridge of 1e-3); with more features than training rows at near-interpolation regularization the RFF fit had explosive variance and lost the CV comparison even when the truth was a pure interaction, so the test had almost no power (verified by harness: the mean CV improvement was negative on y = x1*x2). Additionally, with a hinge-only additive base, additive-but-smooth truths (e.g. y = x1^2 + sin(2 x2)) were falsely flagged non-additive about 45 percent of the time, because the joint block absorbed the hinge basis's approximation bias; the per-variable RFF enrichment removes this. (2) Pooled per-observation differences are dependent within a fold through the shared fitted models, so the t-test is approximate; empirical size on additive truths (linear and additive-nonlinear, n = 150 and 400) is near nominal (see TestNonlinearityTests). (3) Like the other CV test, both models face the same noise, so this comparison remains size-correct under heteroskedasticity, unlike the F/LM tests in this class.

      Parameters:
      y - the array of dependent variable values
      X - the 2D array of independent variable values
      kfold - the number of folds for cross-validation
      alpha - the significance level for the one-sided test of "full model predicts better"
      Returns:
      a TestResult whose statistic is the mean per-observation CV improvement (additive MSE minus full MSE; positive favors non-additivity), with its pooled one-sided p-value and rejection decision