|
3 | 3 | import logging |
4 | 4 | import multiprocessing |
5 | 5 | import numpy as np |
6 | | -import pprint |
7 | 6 | import scipy |
8 | 7 | import scipy.sparse |
9 | 8 | import scipy.optimize |
@@ -270,16 +269,28 @@ def iwls_step( |
270 | 269 | # Have to use a workaround to solve problems in parallel in dask here. This workaround does |
271 | 270 | # not work if there is only a single problem, ie. if the first dimension of a and b has length 1. |
272 | 271 | if a.shape[0] != 1: |
273 | | - delta_theta[:, idx_update] = dask.array.map_blocks( |
274 | | - np.linalg.solve, a, b[:, :, None], chunks=b[:, :, None].shape |
| 272 | + get_cond_number = lambda x: np.expand_dims(np.expand_dims(np.linalg.cond(x, p=None), axis=-1), axis=-1) |
| 273 | + invertible = np.where(dask.array.map_blocks( |
| 274 | + get_cond_number, a, chunks=a.shape |
| 275 | + ).squeeze().compute() < 1 / sys.float_info.epsilon)[0] |
| 276 | + delta_theta[:, idx_update[invertible]] = dask.array.map_blocks( |
| 277 | + np.linalg.solve, a[invertible], b[invertible, :, None], |
| 278 | + chunks=b[invertible, :, None].shape |
275 | 279 | ).squeeze().T.compute() |
276 | 280 | else: |
277 | | - delta_theta[:, idx_update] = np.expand_dims( |
278 | | - np.linalg.solve(a[0], b[0]).compute(), |
279 | | - axis=-1 |
280 | | - ) |
| 281 | + if np.linalg.cond(a.compute(), p=None) < 1 / sys.float_info.epsilon: |
| 282 | + delta_theta[:, idx_update] = np.expand_dims( |
| 283 | + np.linalg.solve(a[0], b[0]).compute(), |
| 284 | + axis=-1 |
| 285 | + ) |
| 286 | + invertible = np.array([0]) |
| 287 | + else: |
| 288 | + invertible = np.array([]) |
281 | 289 | else: |
282 | | - delta_theta[:, idx_update] = np.linalg.solve(a, b).T |
| 290 | + invertible = np.where(np.linalg.cond(a, p=None) < 1 / sys.float_info.epsilon)[0] |
| 291 | + delta_theta[:, idx_update[invertible]] = np.linalg.solve(a[invertible], b[invertible]).T |
| 292 | + if invertible.shape[0] < len(idx_update): |
| 293 | + print("caught %i linalg singular matrix errors" % (len(idx_update) - invertible.shape[0])) |
283 | 294 | # Via np.linalg.lsts: |
284 | 295 | #delta_theta[:, idx_update] = np.concatenate([ |
285 | 296 | # np.expand_dims(np.linalg.lstsq(a[i, :, :], b[i, :])[0], axis=-1) |
@@ -512,7 +523,10 @@ def finalize(self): |
512 | 523 | """ |
513 | 524 | # Read from numpy-IRLS estimator specific model: |
514 | 525 | self._hessian = - self.model.fim.compute() |
515 | | - self._fisher_inv = np.linalg.inv(- self._hessian) |
| 526 | + fisher_inv = np.zeros_like(self._hessian) |
| 527 | + invertible = np.where(np.linalg.cond(self._hessian, p=None) < 1 / sys.float_info.epsilon)[0] |
| 528 | + fisher_inv[invertible] = np.linalg.inv(- self._hessian[invertible]) |
| 529 | + self._fisher_inv = fisher_inv |
516 | 530 | self._jacobian = np.sum(np.abs(self.model.jac.compute() / self.model.x.shape[0]), axis=1) |
517 | 531 | self._log_likelihood = self.model.ll_byfeature.compute() |
518 | 532 | self._loss = np.sum(self._log_likelihood) |
|
0 commit comments