Repository: statsmodels/statsmodels

Issue:
precision problems in degenerate case
`OLS(y, y)` should have a perfect fit with resid == zeros

at https://github.com/statsmodels/statsmodels/commit/3303360a73b9dccb50a0a52524861ec6dcf31b9c
problem is that TravisCI has currently a test failure with wresid = -1.45519152e-11
That's too far away for a purely numerical precision problem.
On my computer wresid == zeros is True

this is from a test branch that checks more intermediate results:

```
======================================================================
FAIL: statsmodels.regression.tests.test_regression.TestOLS.test_norm_resid_zero_variance
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/usr/local/lib/python2.7/dist-packages/statsmodels-0.6.0-py2.7-linux-x86_64.egg/statsmodels/regression/tests/test_regression.py", line 244, in test_norm_resid_zero_variance
    assert_allclose(res.wresid, np.zeros(len(y)), rtol=1e-20)
  File "/usr/lib/python2.7/dist-packages/numpy/testing/utils.py", line 1168, in assert_allclose
    verbose=verbose, header=header)
  File "/usr/lib/python2.7/dist-packages/numpy/testing/utils.py", line 636, in assert_array_compare
    raise AssertionError(msg)
AssertionError: 
Not equal to tolerance rtol=1e-20, atol=0
(mismatch 100.0%)
 x: array([ -1.45519152e-11,  -1.45519152e-11,  -1.45519152e-11,
        -1.45519152e-11,  -1.45519152e-11,  -1.45519152e-11,
        -1.45519152e-11,  -1.45519152e-11,  -1.45519152e-11,...
 y: array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.])
```



Discussion:
As Robert pointed out on the mailing list this is just machine precision since the endog are around 1e4

When I compae `scale` with zero, then I get an atol around 1e-21 on TravisCI, 
Note: rtol doesn't make sense

```
x86_64.egg/statsmodels/regression/tests/test_regression.py", line 247, in test_norm_resid_zero_variance
    assert_allclose(res.scale, 0, rtol=1e-20)
...
AssertionError: 
Not equal to tolerance rtol=1e-20, atol=0
(mismatch 100.0%)
 x: array(2.2587545260114675e-22)
 y: array(0)
```


Resolving patch:
diff --git a/statsmodels/regression/linear_model.py b/statsmodels/regression/linear_model.py
--- a/statsmodels/regression/linear_model.py
+++ b/statsmodels/regression/linear_model.py
@@ -1253,8 +1253,9 @@ def resid_pearson(self):
 
         if not hasattr(self, 'resid'):
             raise ValueError('Method requires residuals.')
-        if np.all(np.abs(self.wresid) <= 0.0):
-            # This is a very exact check, does not account for numerical error
+        eps = np.finfo(self.wresid.dtype).eps
+        if np.sqrt(self.scale) < 10 * eps * self.model.endog.mean():
+            # don't divide if scale is zero close to numerical precision
             from warnings import warn
             warn("All residuals are 0, cannot compute normed residuals.")
             return self.wresid


Test patch:
diff --git a/statsmodels/regression/tests/test_regression.py b/statsmodels/regression/tests/test_regression.py
--- a/statsmodels/regression/tests/test_regression.py
+++ b/statsmodels/regression/tests/test_regression.py
@@ -241,7 +241,8 @@ def test_norm_resid_zero_variance(self):
         with warnings.catch_warnings(record=True):
             y = self.res1.model.endog
             res = OLS(y,y).fit()
-            assert_equal(res.wresid, res.resid_pearson)
+            assert_allclose(res.scale, 0, atol=1e-20)
+            assert_allclose(res.wresid, res.resid_pearson, atol=5e-11)
 
 
 class TestRTO(CheckRegressionResults):