Skip to content

Instantly share code, notes, and snippets.

@saketkc
Created June 22, 2015 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saketkc/dab5f3d8907f62232062 to your computer and use it in GitHub Desktop.
Save saketkc/dab5f3d8907f62232062 to your computer and use it in GitHub Desktop.
n_obs=200000
Line # Hits Time Per Hit % Time Line Contents
==============================================================
356 @profile
357 def _smw_solver(s, A, AtA, B, BI):
358 """
359 Solves the system (s*I + A*B*A') * x = rhs for an arbitrary rhs.
360
361 Parameters
362 ----------
363 s : scalar
364 See above for usage
365 A : square symmetric ndarray
366 See above for usage
367 AtA : square ndarray
368 A.T * A
369 B : square symmetric ndarray
370 See above for usage
371 BI : square symmetric ndarray
372 The inverse of `B`.
373
374 Returns
375 -------
376 A function that takes `rhs` as an input argument and returns a
377 solution to the linear system defined above.
378 """
379
380 # Use SMW identity
381 5880 49233 8.4 1.4 qmat = BI + AtA / s
382 5880 3297098 560.7 95.4 qmati = np.linalg.solve(qmat, A.T)
383
384 5880 105434 17.9 3.1 @profile
385 def solver(rhs):
386 ql = np.dot(qmati, rhs)
387 ql = np.dot(A, ql)
388 rslt = rhs / s - ql / s**2
389 return rslt
390
391 5880 4084 0.7 0.1 return solver
Total time: 18.2266 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: solver at line 384
Line # Hits Time Per Hit % Time Line Contents
==============================================================
384 @profile
385 def solver(rhs):
386 13440 8058252 599.6 44.2 ql = np.dot(qmati, rhs)
387 13440 9291510 691.3 51.0 ql = np.dot(A, ql)
388 13440 868379 64.6 4.8 rslt = rhs / s - ql / s**2
389 13440 8449 0.6 0.0 return rslt
Total time: 0.18264 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: _smw_logdet at line 394
Line # Hits Time Per Hit % Time Line Contents
==============================================================
394 @profile
395 def _smw_logdet(s, A, AtA, B, BI, B_logdet):
396 """
397 Use the matrix determinant lemma to accelerate the calculation of
398 the log determinant of s*I + A*B*A'.
399
400 Parameters
401 ----------
402 s : scalar
403 See above for usage
404 A : square symmetric ndarray
405 See above for usage
406 AtA : square matrix
407 A.T * A
408 B : square symmetric ndarray
409 See above for usage
410 BI : square symmetric ndarray
411 The inverse of `B`; can be None if B is singular.
412 B_logdet : real
413 The log determinant of B
414
415 Returns
416 -------
417 The log determinant of s*I + A*B*A'.
418 """
419
420 1500 1868 1.2 1.0 p = A.shape[0]
421 1500 8406 5.6 4.6 ld = p * np.log(s)
422 1500 11205 7.5 6.1 qmat = BI + AtA / s
423 1500 159363 106.2 87.3 _, ld1 = np.linalg.slogdet(qmat)
424 1500 1798 1.2 1.0 return B_logdet + ld + ld1
Total time: 14.2719 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: _gen_dV_dPar at line 1313
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1313 @profile
1314 def _gen_dV_dPar(self, ex_r, solver, group, max_ix=None):
1315 """
1316 A generator that yields the element-wise derivative of the
1317 marginal covariance matrix with respect to the random effects
1318 variance and covariance parameters.
1319
1320 ex_r : array-like
1321 The random effects design matrix
1322 solver : function
1323 A function that given x returns V^{-1}x, where V
1324 is the group's marginal covariance matrix.
1325 group : scalar
1326 The group label
1327 max_ix : integer or None
1328 If not None, the generator ends when this index
1329 is reached.
1330 """
1331
1332 1560 7171154 4596.9 50.2 axr = solver(ex_r)
1333
1334 # Regular random effects
1335 1560 937 0.6 0.0 jj = 0
1336 1560 4707 3.0 0.0 for j1 in range(self.k_re):
1337 for j2 in range(j1 + 1):
1338 if max_ix is not None and jj > max_ix:
1339 return
1340 mat_l, mat_r = ex_r[:,j1:j1+1], ex_r[:,j2:j2+1] # Need 2d
1341 vsl, vsr = axr[:,j1:j1+1], axr[:,j2:j2+1]
1342 yield jj, mat_l, mat_r, vsl, vsr, j1 == j2
1343 jj += 1
1344
1345 # Variance components
1346 4620 3834 0.8 0.0 for ky in self._vc_names:
1347 3120 4155 1.3 0.0 if group in self.exog_vc[ky]:
1348 3120 1796 0.6 0.0 if max_ix is not None and jj > max_ix:
1349 60 71 1.2 0.0 return
1350 3060 2188 0.7 0.0 mat = self.exog_vc[ky][group]
1351 3060 7078682 2313.3 49.6 axmat = solver(mat)
1352 3060 2299 0.8 0.0 yield jj, mat, mat, axmat, axmat, True
1353 3060 2074 0.7 0.0 jj += 1
Total time: 17.5665 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: score at line 1356
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1356 @profile
1357 def score(self, params, profile_fe=True):
1358 """
1359 Returns the score vector of the profile log-likelihood.
1360
1361 Notes
1362 -----
1363 The score vector that is returned is computed with respect to
1364 the parameterization defined by this model instance's
1365 `use_sqrt` attribute.
1366 """
1367
1368 23 29 1.3 0.0 if type(params) is not MixedLMParams:
1369 23 33 1.4 0.0 params = MixedLMParams.from_packed(params, self.k_fe,
1370 23 18 0.8 0.0 self.k_re, self.use_sqrt,
1371 23 1530 66.5 0.0 with_fe=False)
1372
1373 23 20 0.9 0.0 if profile_fe:
1374 23 1894457 82367.7 10.8 params.fe_params = self.get_fe_params(params.cov_re, params.vcomp)
1375
1376 23 27 1.2 0.0 if self.use_sqrt:
1377 23 15670289 681316.9 89.2 score_fe, score_re, score_vc = self.score_sqrt(params, calc_fe=not profile_fe)
1378 else:
1379 score_fe, score_re, score_vc = self.score_full(params, calc_fe=not profile_fe)
1380
1381 23 18 0.8 0.0 if self._freepat is not None:
1382 score_fe *= self._freepat.fe_params
1383 score_re *= self._freepat.cov_re[self._freepat._ix]
1384 score_vc *= self._freepat.vcomp
1385
1386 23 14 0.6 0.0 if profile_fe:
1387 23 60 2.6 0.0 return np.concatenate((score_re, score_vc))
1388 else:
1389 return np.concatenate((score_fe, score_re, score_vc))
Total time: 15.5742 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: score_full at line 1392
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1392 @profile
1393 def score_full(self, params, calc_fe):
1394 """
1395 Returns the score with respect to untransformed parameters.
1396
1397 Calculates the score vector for the profiled log-likelihood of
1398 the mixed effects model with respect to the parameterization
1399 in which the random effects covariance matrix is represented
1400 in its full form (not using the Cholesky factor).
1401
1402 Parameters
1403 ----------
1404 params : MixedLMParams or array-like
1405 The parameter at which the score function is evaluated.
1406 If array-like, must contain the packed random effects
1407 parameters (cov_re and vcomp) without fe_params.
1408 calc_fe : boolean
1409 If True, calculate the score vector for the fixed effects
1410 parameters. If False, this vector is not calculated, and
1411 a vector of zeros is returned in its place.
1412
1413 Returns
1414 -------
1415 score_fe : array-like
1416 The score vector with respect to the fixed effects
1417 parameters.
1418 score_re : array-like
1419 The score vector with respect to the random effects
1420 parameters (excluding variance components parameters).
1421 score_vc : array-like
1422 The score vector with respect to variance components
1423 parameters.
1424
1425 Notes
1426 -----
1427 `score_re` is taken with respect to the parameterization in
1428 which `cov_re` is represented through its lower triangle
1429 (without taking the Cholesky square root).
1430 """
1431
1432 23 27 1.2 0.0 fe_params = params.fe_params
1433 23 28 1.2 0.0 cov_re = params.cov_re
1434 23 26 1.1 0.0 vcomp = params.vcomp
1435
1436 23 23 1.0 0.0 try:
1437 23 426 18.5 0.0 cov_re_inv = np.linalg.inv(cov_re)
1438 except np.linalg.LinAlgError:
1439 cov_re_inv = None
1440
1441 23 110 4.8 0.0 score_fe = np.zeros(self.k_fe)
1442 23 63 2.7 0.0 score_re = np.zeros(self.k_re2)
1443 23 44 1.9 0.0 score_vc = np.zeros(self.k_vc)
1444
1445 # Handle the covariance penalty.
1446 23 31 1.3 0.0 if self.cov_pen is not None:
1447 score_re -= self.cov_pen.grad(cov_re, cov_re_inv)
1448
1449 # Handle the fixed effects penalty.
1450 23 23 1.0 0.0 if calc_fe and (self.fe_pen is not None):
1451 score_fe -= self.fe_pen.grad(fe_params)
1452
1453 # resid' V^{-1} resid, summed over the groups (a scalar)
1454 23 23 1.0 0.0 rvir = 0.
1455
1456 # exog' V^{-1} resid, summed over the groups (a k_fe
1457 # dimensional vector)
1458 23 23 1.0 0.0 xtvir = 0.
1459
1460 # exog' V^{_1} exog, summed over the groups (a k_fe x k_fe
1461 # matrix)
1462 23 23 1.0 0.0 xtvix = 0.
1463
1464 # V^{-1} exog' dV/dQ_jj exog V^{-1}, where Q_jj is the jj^th
1465 # covariance parameter.
1466 23 42 1.8 0.0 xtax = [0.,] * (self.k_re2 + self.k_vc)
1467
1468 # Temporary related to the gradient of log |V|
1469 23 46 2.0 0.0 dlv = np.zeros(self.k_re2 + self.k_vc)
1470
1471 # resid' V^{-1} dV/dQ_jj V^{-1} resid (a scalar)
1472 23 89 3.9 0.0 rvavr = np.zeros(self.k_re2 + self.k_vc)
1473
1474 1403 2096 1.5 0.0 for group_ix, group in enumerate(self.group_labels):
1475
1476 1380 91349 66.2 0.6 cov_aug, cov_aug_inv, _ = self._augment_cov_re(cov_re, cov_re_inv, vcomp, group)
1477
1478 1380 2454 1.8 0.0 exog = self.exog_li[group_ix]
1479 1380 2252 1.6 0.0 ex_r, ex2_r = self._aex_r[group_ix], self._aex_r2[group_ix]
1480 1380 867894 628.9 5.6 solver = _smw_solver(1., ex_r, ex2_r, cov_aug, cov_aug_inv)
1481
1482 # The residuals
1483 1380 2550 1.8 0.0 resid = self.endog_li[group_ix]
1484 1380 1656 1.2 0.0 if self.k_fe > 0:
1485 1380 46926 34.0 0.3 expval = np.dot(exog, fe_params)
1486 1380 9635 7.0 0.1 resid = resid - expval
1487
1488 1380 1692 1.2 0.0 if self.reml:
1489 1380 766214 555.2 4.9 viexog = solver(exog)
1490 1380 45652 33.1 0.3 xtvix += np.dot(exog.T, viexog)
1491
1492 # Contributions to the covariance parameter gradient
1493 1380 205120 148.6 1.3 vir = solver(resid)
1494 4140 12798991 3091.5 82.2 for jj, matl, matr, vsl, vsr, sym in self._gen_dV_dPar(ex_r, solver, group):
1495 2760 139621 50.6 0.9 dlv[jj] = np.sum(matr * vsl) # trace dot
1496 2760 3831 1.4 0.0 if not sym:
1497 dlv[jj] += np.sum(matl * vsr) # trace dot
1498
1499 2760 95452 34.6 0.6 ul = np.dot(vir, matl)
1500 2760 6467 2.3 0.0 ur = ul.T if sym else np.dot(matr.T, vir)
1501 2760 8057 2.9 0.1 ulr = np.dot(ul, ur)
1502 2760 6870 2.5 0.0 rvavr[jj] += ulr
1503 2760 3043 1.1 0.0 if not sym:
1504 rvavr[jj] += ulr.T
1505
1506 2760 3121 1.1 0.0 if self.reml:
1507 2760 411924 149.2 2.6 ul = np.dot(viexog.T, matl)
1508 2760 4835 1.8 0.0 ur = ul.T if sym else np.dot(matr.T, viexog)
1509 2760 7859 2.8 0.1 ulr = np.dot(ul, ur)
1510 2760 9793 3.5 0.1 xtax[jj] += ulr
1511 2760 3491 1.3 0.0 if not sym:
1512 xtax[jj] += ulr.T
1513
1514 # Contribution of log|V| to the covariance parameter
1515 # gradient.
1516 1380 1815 1.3 0.0 if self.k_re > 0:
1517 score_re -= 0.5 * dlv[0:self.k_re2]
1518 1380 1599 1.2 0.0 if self.k_vc > 0:
1519 1380 8991 6.5 0.1 score_vc -= 0.5 * dlv[self.k_re2:]
1520
1521 1380 7580 5.5 0.0 rvir += np.dot(resid, vir)
1522
1523 1380 1593 1.2 0.0 if calc_fe:
1524 xtvir += np.dot(exog.T, vir)
1525
1526 23 32 1.4 0.0 fac = self.n_totobs
1527 23 24 1.0 0.0 if self.reml:
1528 23 30 1.3 0.0 fac -= self.k_fe
1529
1530 23 23 1.0 0.0 if calc_fe and self.k_fe > 0:
1531 score_fe += fac * xtvir / rvir
1532
1533 23 25 1.1 0.0 if self.k_re > 0:
1534 score_re += 0.5 * fac * rvavr[0:self.k_re2] / rvir
1535 23 26 1.1 0.0 if self.k_vc > 0:
1536 23 234 10.2 0.0 score_vc += 0.5 * fac * rvavr[self.k_re2:] / rvir
1537
1538 23 30 1.3 0.0 if self.reml:
1539 23 1327 57.7 0.0 xtvixi = np.linalg.inv(xtvix)
1540 23 65 2.8 0.0 for j in range(self.k_re2):
1541 score_re[j] += 0.5 * np.sum(xtvixi.T * xtax[j]) # trace dot
1542 69 100 1.4 0.0 for j in range(self.k_vc):
1543 46 762 16.6 0.0 score_vc[j] += 0.5 * np.sum(xtvixi.T * xtax[self.k_re2 + j]) # trace dot
1544
1545 23 25 1.1 0.0 return score_fe, score_re, score_vc
Total time: 15.6697 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: score_sqrt at line 1548
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1548 @profile
1549 def score_sqrt(self, params, calc_fe=True):
1550 """
1551 Returns the score with respect to transformed parameters.
1552
1553 Calculates the score vector with respect to the
1554 parameterization in which the random effects covariance matrix
1555 is represented through its Cholesky square root.
1556
1557 Parameters
1558 ----------
1559 params : MixedLMParams or array-like
1560 The model parameters. If array-like must contain packed
1561 parameters that are compatible with this model instance.
1562 calc_fe : boolean
1563 If True, calculate the score vector for the fixed effects
1564 parameters. If False, this vector is not calculated, and
1565 a vector of zeros is returned in its place.
1566
1567 Returns
1568 -------
1569 score_fe : array-like
1570 The score vector with respect to the fixed effects
1571 parameters.
1572 score_re : array-like
1573 The score vector with respect to the random effects
1574 parameters (excluding variance components parameters).
1575 score_vc : array-like
1576 The score vector with respect to variance components
1577 parameters.
1578 """
1579
1580 23 15667517 681196.4 100.0 score_fe, score_re, score_vc = self.score_full(params, calc_fe=calc_fe)
1581 23 346 15.0 0.0 params_vec = params.get_packed(use_sqrt=True, with_fe=True)
1582
1583 23 62 2.7 0.0 score_full = np.concatenate((score_fe, score_re, score_vc))
1584 23 15 0.7 0.0 scr = 0.
1585 161 138 0.9 0.0 for i in range(len(params_vec)):
1586 138 928 6.7 0.0 v = self._lin[i] + 2 * np.dot(self._quad[i], params_vec)
1587 138 548 4.0 0.0 scr += score_full[i] * v
1588 23 29 1.3 0.0 score_fe = scr[0:self.k_fe]
1589 23 31 1.3 0.0 score_re = scr[self.k_fe:self.k_fe + self.k_re2]
1590 23 23 1.0 0.0 score_vc = scr[self.k_fe + self.k_re2:]
1591
1592 23 14 0.6 0.0 return score_fe, score_re, score_vc
Total time: 38.9766 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: hessian at line 1594
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1594 @profile
1595 def hessian(self, params):
1596 """
1597 Returns the model's Hessian matrix.
1598
1599 Calculates the Hessian matrix for the linear mixed effects
1600 model with respect to the parameterization in which the
1601 covariance matrix is represented directly (without square-root
1602 transformation).
1603
1604 Parameters
1605 ----------
1606 params : MixedLMParams or array-like
1607 The model parameters at which the Hessian is calculated.
1608 If array-like, must contain the packed parameters in a
1609 form that is compatible with this model instance.
1610
1611 Returns
1612 -------
1613 hess : 2d ndarray
1614 The Hessian matrix, evaluated at `params`.
1615 """
1616
1617 1 1 1.0 0.0 if type(params) is not MixedLMParams:
1618 params = MixedLMParams.from_packed(params, self.k_fe, self.k_re,
1619 use_sqrt=self.use_sqrt,
1620 with_fe=True)
1621
1622 1 1 1.0 0.0 fe_params = params.fe_params
1623 1 2 2.0 0.0 vcomp = params.vcomp
1624 1 1 1.0 0.0 cov_re = params.cov_re
1625 1 1 1.0 0.0 if self.k_re > 0:
1626 cov_re_inv = np.linalg.inv(cov_re)
1627 else:
1628 1 4 4.0 0.0 cov_re_inv = np.empty((0, 0))
1629
1630 # Blocks for the fixed and random effects parameters.
1631 1 2 2.0 0.0 hess_fe = 0.
1632 1 3 3.0 0.0 hess_re = np.zeros((self.k_re2 + self.k_vc, self.k_re2 + self.k_vc))
1633 1 2 2.0 0.0 hess_fere = np.zeros((self.k_re2 + self.k_vc, self.k_fe))
1634
1635 1 1 1.0 0.0 fac = self.n_totobs
1636 1 2 2.0 0.0 if self.reml:
1637 1 3 3.0 0.0 fac -= self.exog.shape[1]
1638
1639 1 1 1.0 0.0 rvir = 0.
1640 1 1 1.0 0.0 xtvix = 0.
1641 1 3 3.0 0.0 xtax = [0.,] * (self.k_re2 + self.k_vc)
1642 1 2 2.0 0.0 m = self.k_re2 + self.k_vc
1643 1 4 4.0 0.0 B = np.zeros(m)
1644 1 2 2.0 0.0 D = np.zeros((m, m))
1645 3 8 2.7 0.0 F = [[0.] * m for k in range(m)]
1646 61 134 2.2 0.0 for k, group in enumerate(self.group_labels):
1647
1648 60 6386 106.4 0.0 cov_aug, cov_aug_inv, _ = self._augment_cov_re(cov_re, cov_re_inv, vcomp, group)
1649
1650 60 128 2.1 0.0 exog = self.exog_li[k]
1651 60 124 2.1 0.0 ex_r, ex2_r = self._aex_r[k], self._aex_r2[k]
1652 60 43165 719.4 0.1 solver = _smw_solver(1., ex_r, ex2_r, cov_aug, cov_aug_inv)
1653
1654 # The residuals
1655 60 150 2.5 0.0 resid = self.endog_li[k]
1656 60 98 1.6 0.0 if self.k_fe > 0:
1657 60 1819 30.3 0.0 expval = np.dot(exog, fe_params)
1658 60 478 8.0 0.0 resid = resid - expval
1659
1660 60 33386 556.4 0.1 viexog = solver(exog)
1661 60 2019 33.6 0.0 xtvix += np.dot(exog.T, viexog)
1662 60 9100 151.7 0.0 vir = solver(resid)
1663 60 403 6.7 0.0 rvir += np.dot(resid, vir)
1664
1665 180 557280 3096.0 1.4 for jj1, matl1, matr1, vsl1, vsr1, sym1 in self._gen_dV_dPar(ex_r, solver, group):
1666
1667 120 17454 145.4 0.0 ul = np.dot(viexog.T, matl1)
1668 120 4104 34.2 0.0 ur = np.dot(matr1.T, vir)
1669 120 1149 9.6 0.0 hess_fere[jj1, :] += np.dot(ul, ur)
1670 120 196 1.6 0.0 if not sym1:
1671 ul = np.dot(viexog.T, matr1)
1672 ur = np.dot(matl1.T, vir)
1673 hess_fere[jj1, :] += np.dot(ul, ur)
1674
1675 120 185 1.5 0.0 if self.reml:
1676 120 17082 142.3 0.0 ul = np.dot(viexog.T, matl1)
1677 120 221 1.8 0.0 ur = ul if sym1 else np.dot(viexog.T, matr1)
1678 120 466 3.9 0.0 ulr = np.dot(ul, ur.T)
1679 120 446 3.7 0.0 xtax[jj1] += ulr
1680 120 174 1.4 0.0 if not sym1:
1681 xtax[jj1] += ulr.T
1682
1683 120 3857 32.1 0.0 ul = np.dot(vir, matl1)
1684 120 212 1.8 0.0 ur = ul if sym1 else np.dot(vir, matr1)
1685 120 876 7.3 0.0 B[jj1] += np.dot(ul, ur) * (1 if sym1 else 2)
1686
1687 # V^{-1} * dV/d_theta
1688 120 6276293 52302.4 16.1 E = np.dot(vsl1, matr1.T)
1689 120 404 3.4 0.0 if not sym1:
1690 E += np.dot(vsr1, matl1.T)
1691
1692 300 968825 3229.4 2.5 for jj2, matl2, matr2, vsl2, vsr2, sym2 in self._gen_dV_dPar(ex_r, solver, group, jj1):
1693
1694 180 28761228 159784.6 73.8 re = np.dot(matr2.T, E)
1695 180 11733 65.2 0.0 rev = np.dot(re, vir[:, None])
1696 180 11308 62.8 0.0 vl = np.dot(vir[None, :], matl2)
1697 180 3808 21.2 0.0 vt = 2*np.dot(vl, rev)
1698
1699 180 312 1.7 0.0 if not sym2:
1700 le = np.dot(matl2.T, E)
1701 lev = np.dot(le, vir[:, None])
1702 vr = np.dot(vir[None, :], matr2)
1703 vt += 2*np.dot(vr, lev)
1704
1705 180 2127 11.8 0.0 D[jj1, jj2] += vt
1706 180 339 1.9 0.0 if jj1 != jj2:
1707 60 224 3.7 0.0 D[jj2, jj1] += vt
1708
1709 180 24104 133.9 0.1 rt = np.sum(vsl2 * re.T) / 2 # trace dot
1710 180 301 1.7 0.0 if not sym2:
1711 rt += np.sum(vsr2 * le.T) / 2 # trace dot
1712
1713 180 494 2.7 0.0 hess_re[jj1, jj2] += rt
1714 180 248 1.4 0.0 if jj1 != jj2:
1715 60 106 1.8 0.0 hess_re[jj2, jj1] += rt
1716
1717 180 367 2.0 0.0 if self.reml:
1718 180 2148143 11934.1 5.5 ev = np.dot(E, viexog)
1719 180 33557 186.4 0.1 u1 = np.dot(viexog.T, matl2)
1720 180 25086 139.4 0.1 u2 = np.dot(matr2.T, ev)
1721 180 666 3.7 0.0 um = np.dot(u1, u2)
1722 180 4853 27.0 0.0 F[jj1][jj2] += um + um.T
1723 180 351 1.9 0.0 if not sym2:
1724 u1 = np.dot(viexog.T, matr2)
1725 u2 = np.dot(matl2.T, ev)
1726 um = np.dot(u1, u2)
1727 F[jj1][jj2] += um + um.T
1728
1729 1 26 26.0 0.0 hess_fe -= fac * xtvix / rvir
1730 1 47 47.0 0.0 hess_re = hess_re - 0.5 * fac * (D/rvir - np.outer(B, B) / rvir**2)
1731 1 9 9.0 0.0 hess_fere = -fac * hess_fere / rvir
1732
1733 1 1 1.0 0.0 if self.reml:
1734 3 184 61.3 0.0 QL = [np.linalg.solve(xtvix, x) for x in xtax]
1735 3 9 3.0 0.0 for j1 in range(self.k_re2 + self.k_vc):
1736 5 8 1.6 0.0 for j2 in range(j1 + 1):
1737 3 55 18.3 0.0 a = np.sum(QL[j1].T * QL[j2]) # trace dot
1738 3 162 54.0 0.0 a -= np.trace(np.linalg.solve(xtvix, F[j1][j2]))
1739 3 6 2.0 0.0 a *= 0.5
1740 3 7 2.3 0.0 hess_re[j1, j2] += a
1741 3 6 2.0 0.0 if j1 > j2:
1742 1 2 2.0 0.0 hess_re[j2, j1] += a
1743
1744 # Put the blocks together to get the Hessian.
1745 1 2 2.0 0.0 m = self.k_fe + self.k_re2 + self.k_vc
1746 1 4 4.0 0.0 hess = np.zeros((m, m))
1747 1 4 4.0 0.0 hess[0:self.k_fe, 0:self.k_fe] = hess_fe
1748 1 3 3.0 0.0 hess[0:self.k_fe, self.k_fe:] = hess_fere.T
1749 1 3 3.0 0.0 hess[self.k_fe:, 0:self.k_fe] = hess_fere
1750 1 2 2.0 0.0 hess[self.k_fe:, self.k_fe:] = hess_re
1751
1752 1 2 2.0 0.0 return hess
Total time: 61.0446 s
File: statsmodels/regression/mixed_linear_model.orig.py
Function: fit at line 1807
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1807 @profile
1808 def fit(self, start_params=None, reml=True,
1809 fe_pen=None, cov_pen=None, free=None,
1810 full_output=False, method='bfgs', **kwargs):
1811 """
1812 Fit a linear mixed model to the data.
1813
1814 Parameters
1815 ----------
1816 start_params: array-like or MixedLMParams
1817 Starting values for the profile log-likeihood. If not a
1818 `MixedLMParams` instance, this should be an array
1819 containing the packed parameters for the profile
1820 log-likelihood, including the fixed effects
1821 parameters.
1822 reml : bool
1823 If true, fit according to the REML likelihood, else
1824 fit the standard likelihood using ML.
1825 cov_pen : CovariancePenalty object
1826 A penalty for the random effects covariance matrix
1827 fe_pen : Penalty object
1828 A penalty on the fixed effects
1829 free : MixedLMParams object
1830 If not `None`, this is a mask that allows parameters to be
1831 held fixed at specified values. A 1 indicates that the
1832 correspondinig parameter is estimated, a 0 indicates that
1833 it is fixed at its starting value. Setting the `cov_re`
1834 component to the identity matrix fits a model with
1835 independent random effects. Note that some optimization
1836 methods do not respect this contraint (bfgs and lbfgs both
1837 work).
1838 full_output : bool
1839 If true, attach iteration history to results
1840 method : string
1841 Optimization method.
1842
1843 Returns
1844 -------
1845 A MixedLMResults instance.
1846 """
1847
1848 1 3 3.0 0.0 _allowed_kwargs = ['gtol', 'maxiter']
1849 1 3 3.0 0.0 for x in kwargs.keys():
1850 if x not in _allowed_kwargs:
1851 raise ValueError("Argument %s not allowed for MixedLM.fit" % x)
1852
1853 1 2 2.0 0.0 if method.lower() in ["newton", "ncg"]:
1854 raise ValueError("method %s not available for MixedLM" % method)
1855
1856 1 2 2.0 0.0 self.reml = reml
1857 1 1 1.0 0.0 self.cov_pen = cov_pen
1858 1 2 2.0 0.0 self.fe_pen = fe_pen
1859
1860 1 1 1.0 0.0 self._freepat = free
1861
1862 1 2 2.0 0.0 if full_output:
1863 hist = []
1864 else:
1865 1 2 2.0 0.0 hist = None
1866
1867 1 2 2.0 0.0 if start_params is None:
1868 1 43 43.0 0.0 params = MixedLMParams(self.k_fe, self.k_re, self.k_vc)
1869 1 4 4.0 0.0 params.fe_params = np.zeros(self.k_fe)
1870 1 8 8.0 0.0 params.cov_re = np.eye(self.k_re)
1871 1 14 14.0 0.0 params.vcomp = np.ones(self.k_vc)
1872 else:
1873 if isinstance(start_params, MixedLMParams):
1874 params = start_params
1875 else:
1876 params = MixedLMParams.from_packed(start_params, self.k_fe,
1877 self.k_re, self.use_sqrt,
1878 with_fe=True)
1879
1880 1 2 2.0 0.0 kwargs["retall"] = hist is not None
1881 1 1 1.0 0.0 if "disp" not in kwargs:
1882 1 2 2.0 0.0 kwargs["disp"] = False
1883 1 14 14.0 0.0 packed = params.get_packed(use_sqrt=self.use_sqrt, with_fe=False)
1884 1 3 3.0 0.0 rslt = super(MixedLM, self).fit(start_params=packed,
1885 1 1 1.0 0.0 skip_hessian=True,
1886 1 1 1.0 0.0 method=method,
1887 1 21922116 21922116.0 35.9 **kwargs)
1888
1889 # The optimization succeeded
1890 1 22 22.0 0.0 params = np.atleast_1d(rslt.params)
1891 1 2 2.0 0.0 if hist is not None:
1892 hist.append(rslt.mle_retvals)
1893
1894 1 1 1.0 0.0 converged = rslt.mle_retvals['converged']
1895 1 2 2.0 0.0 if not converged:
1896 msg = "Gradient optimization failed."
1897 warnings.warn(msg, ConvergenceWarning)
1898
1899 # Convert to the final parameterization (i.e. undo the square
1900 # root transform of the covariance matrix, and the profiling
1901 # over the error variance).
1902 1 3 3.0 0.0 params = MixedLMParams.from_packed(params, self.k_fe, self.k_re,
1903 1 66 66.0 0.0 use_sqrt=self.use_sqrt, with_fe=False)
1904 1 2 2.0 0.0 cov_re_unscaled = params.cov_re
1905 1 1 1.0 0.0 vcomp_unscaled = params.vcomp
1906 1 80065 80065.0 0.1 fe_params = self.get_fe_params(cov_re_unscaled, vcomp_unscaled)
1907 1 3 3.0 0.0 params.fe_params = fe_params
1908 1 47347 47347.0 0.1 scale = self.get_scale(fe_params, cov_re_unscaled, vcomp_unscaled)
1909 1 6 6.0 0.0 cov_re = scale * cov_re_unscaled
1910 1 3 3.0 0.0 vcomp = scale * vcomp_unscaled
1911
1912 1 1 1.0 0.0 if (((self.k_re > 0) and (np.min(np.abs(np.diag(cov_re))) < 0.01)) or
1913 1 20 20.0 0.0 ((self.k_vc > 0) and (np.min(np.abs(vcomp)) < 0.01))):
1914 msg = "The MLE may be on the boundary of the parameter space."
1915 warnings.warn(msg, ConvergenceWarning)
1916
1917 # Compute the Hessian at the MLE. Note that this is the
1918 # Hessian with respect to the random effects covariance matrix
1919 # (not its square root). It is used for obtaining standard
1920 # errors, not for optimization.
1921 1 38990445 38990445.0 63.9 hess = self.hessian(params)
1922 1 15 15.0 0.0 hess_diag = np.diag(hess)
1923 1 2 2.0 0.0 if free is not None:
1924 pcov = np.zeros_like(hess)
1925 pat = self._freepat.get_packed(use_sqrt=False, with_fe=True)
1926 ii = np.flatnonzero(pat)
1927 hess_diag = hess_diag[ii]
1928 if len(ii) > 0:
1929 hess1 = hess[np.ix_(ii, ii)]
1930 pcov[np.ix_(ii, ii)] = np.linalg.inv(-hess1)
1931 else:
1932 1 52 52.0 0.0 pcov = np.linalg.inv(-hess)
1933 1 28 28.0 0.0 if np.any(hess_diag >= 0):
1934 msg = "The Hessian matrix at the estimated parameter values is not positive definite."
1935 warnings.warn(msg, ConvergenceWarning)
1936
1937 # Prepare a results class instance
1938 1 14 14.0 0.0 params_packed = params.get_packed(use_sqrt=False, with_fe=True)
1939 1 4250 4250.0 0.0 results = MixedLMResults(self, params_packed, pcov / scale)
1940 1 2 2.0 0.0 results.params_object = params
1941 1 2 2.0 0.0 results.fe_params = fe_params
1942 1 2 2.0 0.0 results.cov_re = cov_re
1943 1 1 1.0 0.0 results.vcomp = vcomp
1944 1 2 2.0 0.0 results.scale = scale
1945 1 1 1.0 0.0 results.cov_re_unscaled = cov_re_unscaled
1946 1 3 3.0 0.0 results.method = "REML" if self.reml else "ML"
1947 1 1 1.0 0.0 results.converged = converged
1948 1 2 2.0 0.0 results.hist = hist
1949 1 1 1.0 0.0 results.reml = self.reml
1950 1 2 2.0 0.0 results.cov_pen = self.cov_pen
1951 1 2 2.0 0.0 results.k_fe = self.k_fe
1952 1 2 2.0 0.0 results.k_re = self.k_re
1953 1 2 2.0 0.0 results.k_re2 = self.k_re2
1954 1 3 3.0 0.0 results.k_vc = self.k_vc
1955 1 2 2.0 0.0 results.use_sqrt = self.use_sqrt
1956 1 3 3.0 0.0 results.freepat = self._freepat
1957
1958 1 7 7.0 0.0 return MixedLMResultsWrapper(results)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment