Skip to content

TST: Compare the summaries of effects-only results as words and numbers - #846

Merged
bashtage merged 5 commits into
mainfrom
lm71-intel-mac-tests
Oct 15, 2026
Merged

bashtage merged 5 commits into
mainfrom
lm71-intel-mac-tests

Conversation

@bashtage

Copy link
Copy Markdown
Owner

The R-squared of a PanelOLS model that only has effects is 0 in exact
arithmetic. It is computed as 1 - residual_ss / total_ss, which is 0, 1.11e-16
or -2.22e-16 depending on the rounding of the platform, and the summary prints
the difference: "-2.22e-16" in one result and "0.0000" in the other. The two
fits that test_effects_only.py compares (a formula and the same model without
one) differ in the last bit on Intel macOS, and comparing their summaries as
text failed about 25 tests in every Intel macOS job of the wheels build, in
test_formula_equals_the_model_without_regressors,
test_formula_equals_the_model_with_fit_options and
test_formula_with_other_effects.

assert_same_results compared the summaries and the string of each test statistic
as text. It now compares the words of the two texts, with the numbers replaced by
a placeholder, and the numbers as numbers, with rtol=1e-8 and atol=1e-12. The
absolute tolerance is the one that the same function gives to the R-squared and
the other attributes of the results. The confidence intervals use the check of
the other tables, labels and assert_allclose, instead of DataFrame.equals.

The R-squared of a PanelOLS model that only has effects is 0 in exact
arithmetic. It is computed as 1 - residual_ss / total_ss, which is 0, 1.11e-16
or -2.22e-16 depending on the rounding of the platform, and the summary prints
the difference: "-2.22e-16" in one result and "0.0000" in the other. The two
fits that test_effects_only.py compares (a formula and the same model without
one) differ in the last bit on Intel macOS, and comparing their summaries as
text failed about 25 tests in every Intel macOS job of the wheels build, in
test_formula_equals_the_model_without_regressors,
test_formula_equals_the_model_with_fit_options and
test_formula_with_other_effects.

assert_same_results compared the summaries and the string of each test statistic
as text. It now compares the words of the two texts, with the numbers replaced by
a placeholder, and the numbers as numbers, with rtol=1e-8 and atol=1e-12. The
absolute tolerance is the one that the same function gives to the R-squared and
the other attributes of the results. The confidence intervals use the check of
the other tables, labels and assert_allclose, instead of DataFrame.equals.
test_summary_with_a_zero_standard_error fits a system whose first equation is
exact, so that the standard error is 0, the t-statistic is infinite and the
summary has to format "inf". With a normal regressor the fit is only exact if the
cross products x'x and x'y round alike. They do with the linear algebra of Linux,
Windows and Apple silicon. On Intel macOS the standard error is 7.5e-17, the
t-statistic is 2.7e16 and no inf is formatted, so that the test failed in every
Intel macOS job of the wheels build. Comparing the standard error with a
tolerance is not enough, because the test also needs the infinite t-statistic.

The regressor is now 1 or -1 in 64 observations. Its sum of squares and its
product with the dependent variable of the exact equation, 64 and 128, are
integers, so that the parameter is exactly 2 and the standard error exactly 0,
whatever the order of the sums of the platform. The standard error is compared
with assert_allclose and the t-statistic with np.isinf, as before.
Four tests compare two fits of the same data that are equal in exact arithmetic.
On Intel macOS the two fits differ in the last bits and the comparisons were too
strict. The tolerances come from the differences that the fits show when the data
change in the last bit, and are far below the differences of a wrong result.

test_label_resolution.py::test_asset_pricing_inputs failed for
LinearFactorModelGMM in the three pairs of resolutions. The model minimizes its
objective with BFGS and a finite difference gradient, so that fits that only
differ by rounding stop at estimates that differ by up to 1e-7, not by 1e-16.
The parameters differed by 3.7e-8, against rtol=1e-10. This model now uses
rtol=1e-6, and the other models keep 1e-10.

test_case_insensitive_options.py::test_mixed_case_names_give_the_results_of_lower_case_names
failed once across the Intel macOS jobs, for the same reason. The relative
differences of the smallest elements of its covariance reach 2e-7, which is above
the default rtol of 1e-7 in half of the fits whose data change in the last bit.
This model now uses rtol=1e-5, and the other models keep the default.

test_gmm_kernel_bandwidth.py compared two ways to set the same bandwidth with
assert_array_equal and ==. The J statistic of the debiased weights was
1.564448925745796 in one and 1.5644489257457959 in the other. assert_identical is
now assert_same_results and uses rtol=1e-8 for the parameters, the standard
errors, the covariance, the weight matrix and the J statistic. Changing the data
in the last bit changes them by up to 4e-10, in the covariance of the Parzen
kernel.

test_grid_inputs.py::test_weights_in_a_grid_are_those_of_the_rows_in_every_model
compared the residuals with rtol=1e-12 and no absolute tolerance. The relative
error of a residual of 1e-4 reaches 2e-11 when the data change in the last bit,
and this failed for RandomEffects in 15 of 384 such fits. compare_results now uses
rtol=1e-10 for the parameters, the covariance and the residuals, and atol=1e-12
for the residuals.
The wheels of linearmodels 7.1 are built for Intel macOS (macos-15-intel) as
well. In the trial build every Intel macOS job failed 29 to 33 tests, while the
Linux, Windows and Apple silicon jobs passed, because no job of this repository
runs on Intel macOS and so nothing here noticed that the linear algebra of that
platform rounds differently.

This adds one matrix entry to cron-test.yml, macos-15-intel with Python 3.14
(cp314). The six jobs of the existing matrix are unchanged.
The tests that failed on Intel macOS compared two results that are equal in exact
arithmetic exactly, and the last bits of a result depend on the linear algebra of
the platform. This applies the same rule to the other tests: a float that is
computed is compared with assert_allclose and a tolerance that follows from the
difference that is expected, and the numbers in a text are compared as numbers.

The comparisons were found by searching the tests for ==, assert_array_equal,
assert_equal and array_equal on floats, and for assert_allclose with rtol=0 or
atol=0, and by running the whole suite with the last bit of the floats of these
comparisons changed. By package:

- asset_pricing: the J statistic of a just identified model, the moment covariance
  of an exactly identified one, the standard errors that are set to 0 for variances
  that are 0 up to rounding, the t-statistics and p-values that are recomputed, and
  the parameters after the missing values are dropped.
- iv: the kernel weights, s2 of the covariances, the covariances of the aliases of a
  kernel, the R-squared of a formula and of the model it stands for, the refits of
  IVJIVE, and the tests of the default bandwidth of IVGMM and IVGMMCUE, like the one
  of IVSystemGMM that was changed before.
- panel: the zeros of a model that only has effects, and the variance of the effects
  with and without the small sample adjustment.
- shared and system: the statistic of a quadratic form that is 0, the p-values of
  statistics that are infinite, r_squared, the weight matrix of the kernel, and the
  transform of a linear constraint.
- tests: the R-squared that is recomputed from the sums of squares, and the models
  that only have a constant.

The tolerance is 1e-10 for results of closed form from the same data (1e-12 for
scalars and elementwise formulas), atol=1e-12 for what is 0 in exact arithmetic, and
relative to the largest element for matrices (assert_close_matrix), since the
elements of a matrix that are close to 0 have larger relative errors.

IVGMMCUE minimizes its objective with BFGS. Changing the data in the last bit
changes its estimates by up to 6e-6, the covariance by 3e-6, the R-squared by 6e-9
and the J statistic by 1e-13. The tests use rtol=1e-4 for the estimates and the
covariance, 1e-6 for the R-squared and 1e-8 for the J statistic. A bandwidth that
differs by 1 changes the estimates by 4e-2 or more.

assert_same_text (tests/_utility.py) compares two texts as their words, with the
numbers replaced by a placeholder, and as their numbers, with rtol=1e-8 and
atol=1e-12. It replaces the comparison of whole texts of the summary of a pickled
result, the representation of the results of the Hausman test, the clones of the
test statistics and str(res) of a model that only has effects.

These stay exact, because exact is the property that is tested: values that are
copied, converted or reshaped without arithmetic (the containers of the data, the
options of a model, pickled statistics), indicators of 0 and 1 and counts that are
stored as floats, the equal weights that normalize to exactly 1, which the models
test for, the covariance that is symmetric to the last bit, a series of integers
that sums to 0, the exact zeros of sparse matrices in assert_allclose, and the tests
of the format of the text of a number that is a literal.
@bashtage
bashtage merged commit 017dcdb into main Oct 15, 2026
17 of 24 checks passed
@codecov

codecov Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.68%. Comparing base (1c3fe26) to head (a99a236).
⚠️ Report is 13 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #846   +/-   ##
=======================================
  Coverage   99.68%   99.68%           
=======================================
  Files         198      198           
  Lines       37727    37768   +41     
  Branches     2430     2431    +1     
=======================================
+ Hits        37608    37649   +41     
  Misses         51       51           
  Partials       68       68           
Flag Coverage Δ
adder 99.67% <100.00%> (+<0.01%) ⬆️
subtractor 99.67% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant