Skip to content

Instantly share code, notes, and snippets.

@saketkc
Created June 22, 2015 18:35
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/23fd682d4ece6b57c895 to your computer and use it in GitHub Desktop.
Save saketkc/23fd682d4ece6b57c895 to your computer and use it in GitHub Desktop.
overwrites
Total time: 3.02405 s
File: statsmodels/regression/mixed_linear_model.mod.py
Function: _smw_solver at line 356
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 49134 8.4 1.6 qmat = BI + AtA / s
382 5880 2868186 487.8 94.8 qmati = scipy.linalg.solve(qmat, A.T, overwrite_a=True, check_finite=False) #np.linalg.solve(qmat, A.T)
383
384 5880 102470 17.4 3.4 @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 4264 0.7 0.1 return solver
Total time: 24.0576 s
File: statsmodels/regression/mixed_linear_model.mod.py
Function: solver at line 384
Line # Hits Time Per Hit % Time Line Contents
==============================================================
384 @profile
385 def solver(rhs):
386 13440 13665521 1016.8 56.8 ql = np.dot(qmati, rhs)
387 13440 9524465 708.7 39.6 ql = np.dot(A, ql)
388 13440 859182 63.9 3.6 rslt = rhs / s - ql / s**2
389 13440 8410 0.6 0.0 return rslt
Total time: 0.183025 s
File: statsmodels/regression/mixed_linear_model.mod.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 2077 1.4 1.1 p = A.shape[0]
421 1500 8634 5.8 4.7 ld = p * np.log(s)
422 1500 11393 7.6 6.2 qmat = BI + AtA / s
423 1500 159054 106.0 86.9 _, ld1 = np.linalg.slogdet(qmat)
424 1500 1867 1.2 1.0 return B_logdet + ld + ld1
Total time: 19.2829 s
File: statsmodels/regression/mixed_linear_model.mod.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 9635596 6176.7 50.0 axr = solver(ex_r)
1333
1334 # Regular random effects
1335 1560 928 0.6 0.0 jj = 0
1336 1560 4133 2.6 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 3931 0.9 0.0 for ky in self._vc_names:
1347 3120 4291 1.4 0.0 if group in self.exog_vc[ky]:
1348 3120 1743 0.6 0.0 if max_ix is not None and jj > max_ix:
1349 60 68 1.1 0.0 return
1350 3060 2189 0.7 0.0 mat = self.exog_vc[ky][group]
1351 3060 9625683 3145.6 49.9 axmat = solver(mat)
1352 3060 2294 0.7 0.0 yield jj, mat, mat, axmat, axmat, True
1353 3060 1995 0.7 0.0 jj += 1
Total time: 22.3189 s
File: statsmodels/regression/mixed_linear_model.mod.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 28 1.2 0.0 if type(params) is not MixedLMParams:
1369 23 35 1.5 0.0 params = MixedLMParams.from_packed(params, self.k_fe,
1370 23 17 0.7 0.0 self.k_re, self.use_sqrt,
1371 23 1521 66.1 0.0 with_fe=False)
1372
1373 23 18 0.8 0.0 if profile_fe:
1374 23 1978680 86029.6 8.9 params.fe_params = self.get_fe_params(params.cov_re, params.vcomp)
1375
1376 23 26 1.1 0.0 if self.use_sqrt:
1377 23 20338446 884280.3 91.1 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 20 0.9 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 11 0.5 0.0 if profile_fe:
1387 23 52 2.3 0.0 return np.concatenate((score_re, score_vc))
1388 else:
1389 return np.concatenate((score_fe, score_re, score_vc))
Total time: 20.2441 s
File: statsmodels/regression/mixed_linear_model.mod.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 28 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 439 19.1 0.0 cov_re_inv = np.linalg.inv(cov_re)
1438 except np.linalg.LinAlgError:
1439 cov_re_inv = None
1440
1441 23 92 4.0 0.0 score_fe = np.zeros(self.k_fe)
1442 23 65 2.8 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 27 1.2 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 22 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 22 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 43 1.9 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 48 2.1 0.0 rvavr = np.zeros(self.k_re2 + self.k_vc)
1473
1474 1403 2122 1.5 0.0 for group_ix, group in enumerate(self.group_labels):
1475
1476 1380 93150 67.5 0.5 cov_aug, cov_aug_inv, _ = self._augment_cov_re(cov_re, cov_re_inv, vcomp, group)
1477
1478 1380 2394 1.7 0.0 exog = self.exog_li[group_ix]
1479 1380 2210 1.6 0.0 ex_r, ex2_r = self._aex_r[group_ix], self._aex_r2[group_ix]
1480 1380 821419 595.2 4.1 solver = _smw_solver(1., ex_r, ex2_r, cov_aug, cov_aug_inv)
1481
1482 # The residuals
1483 1380 2724 2.0 0.0 resid = self.endog_li[group_ix]
1484 1380 1613 1.2 0.0 if self.k_fe > 0:
1485 1380 46352 33.6 0.2 expval = np.dot(exog, fe_params)
1486 1380 9717 7.0 0.0 resid = resid - expval
1487
1488 1380 1715 1.2 0.0 if self.reml:
1489 1380 944717 684.6 4.7 viexog = solver(exog)
1490 1380 45748 33.2 0.2 xtvix += np.dot(exog.T, viexog)
1491
1492 # Contributions to the covariance parameter gradient
1493 1380 224998 163.0 1.1 vir = solver(resid)
1494 4140 17297152 4178.1 85.4 for jj, matl, matr, vsl, vsr, sym in self._gen_dV_dPar(ex_r, solver, group):
1495 2760 152018 55.1 0.8 dlv[jj] = np.sum(matr * vsl) # trace dot
1496 2760 3889 1.4 0.0 if not sym:
1497 dlv[jj] += np.sum(matl * vsr) # trace dot
1498
1499 2760 103546 37.5 0.5 ul = np.dot(vir, matl)
1500 2760 6389 2.3 0.0 ur = ul.T if sym else np.dot(matr.T, vir)
1501 2760 8025 2.9 0.0 ulr = np.dot(ul, ur)
1502 2760 6913 2.5 0.0 rvavr[jj] += ulr
1503 2760 2861 1.0 0.0 if not sym:
1504 rvavr[jj] += ulr.T
1505
1506 2760 3132 1.1 0.0 if self.reml:
1507 2760 409631 148.4 2.0 ul = np.dot(viexog.T, matl)
1508 2760 4988 1.8 0.0 ur = ul.T if sym else np.dot(matr.T, viexog)
1509 2760 7883 2.9 0.0 ulr = np.dot(ul, ur)
1510 2760 10056 3.6 0.0 xtax[jj] += ulr
1511 2760 3431 1.2 0.0 if not sym:
1512 xtax[jj] += ulr.T
1513
1514 # Contribution of log|V| to the covariance parameter
1515 # gradient.
1516 1380 1781 1.3 0.0 if self.k_re > 0:
1517 score_re -= 0.5 * dlv[0:self.k_re2]
1518 1380 1567 1.1 0.0 if self.k_vc > 0:
1519 1380 8917 6.5 0.0 score_vc -= 0.5 * dlv[self.k_re2:]
1520
1521 1380 7548 5.5 0.0 rvir += np.dot(resid, vir)
1522
1523 1380 1532 1.1 0.0 if calc_fe:
1524 xtvir += np.dot(exog.T, vir)
1525
1526 23 28 1.2 0.0 fac = self.n_totobs
1527 23 24 1.0 0.0 if self.reml:
1528 23 28 1.2 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 25 1.1 0.0 if self.k_vc > 0:
1536 23 255 11.1 0.0 score_vc += 0.5 * fac * rvavr[self.k_re2:] / rvir
1537
1538 23 32 1.4 0.0 if self.reml:
1539 23 1547 67.3 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 103 1.5 0.0 for j in range(self.k_vc):
1543 46 782 17.0 0.0 score_vc[j] += 0.5 * np.sum(xtvixi.T * xtax[self.k_re2 + j]) # trace dot
1544
1545 23 23 1.0 0.0 return score_fe, score_re, score_vc
Total time: 20.3378 s
File: statsmodels/regression/mixed_linear_model.mod.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 20335705 884161.1 100.0 score_fe, score_re, score_vc = self.score_full(params, calc_fe=calc_fe)
1581 23 339 14.7 0.0 params_vec = params.get_packed(use_sqrt=True, with_fe=True)
1582
1583 23 55 2.4 0.0 score_full = np.concatenate((score_fe, score_re, score_vc))
1584 23 14 0.6 0.0 scr = 0.
1585 161 126 0.8 0.0 for i in range(len(params_vec)):
1586 138 930 6.7 0.0 v = self._lin[i] + 2 * np.dot(self._quad[i], params_vec)
1587 138 549 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 27 1.2 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 16 0.7 0.0 return score_fe, score_re, score_vc
Total time: 41.2382 s
File: statsmodels/regression/mixed_linear_model.mod.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 1 1.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 2 2.0 0.0 xtax = [0.,] * (self.k_re2 + self.k_vc)
1642 1 1 1.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 142 2.3 0.0 for k, group in enumerate(self.group_labels):
1647
1648 60 6479 108.0 0.0 cov_aug, cov_aug_inv, _ = self._augment_cov_re(cov_re, cov_re_inv, vcomp, group)
1649
1650 60 130 2.2 0.0 exog = self.exog_li[k]
1651 60 121 2.0 0.0 ex_r, ex2_r = self._aex_r[k], self._aex_r2[k]
1652 60 38955 649.2 0.1 solver = _smw_solver(1., ex_r, ex2_r, cov_aug, cov_aug_inv)
1653
1654 # The residuals
1655 60 156 2.6 0.0 resid = self.endog_li[k]
1656 60 98 1.6 0.0 if self.k_fe > 0:
1657 60 1888 31.5 0.0 expval = np.dot(exog, fe_params)
1658 60 487 8.1 0.0 resid = resid - expval
1659
1660 60 42226 703.8 0.1 viexog = solver(exog)
1661 60 2010 33.5 0.0 xtvix += np.dot(exog.T, viexog)
1662 60 9703 161.7 0.0 vir = solver(resid)
1663 60 396 6.6 0.0 rvir += np.dot(resid, vir)
1664
1665 180 748306 4157.3 1.8 for jj1, matl1, matr1, vsl1, vsr1, sym1 in self._gen_dV_dPar(ex_r, solver, group):
1666
1667 120 17543 146.2 0.0 ul = np.dot(viexog.T, matl1)
1668 120 5630 46.9 0.0 ur = np.dot(matr1.T, vir)
1669 120 1160 9.7 0.0 hess_fere[jj1, :] += np.dot(ul, ur)
1670 120 184 1.5 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 189 1.6 0.0 if self.reml:
1676 120 17181 143.2 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 473 3.9 0.0 ulr = np.dot(ul, ur.T)
1679 120 462 3.9 0.0 xtax[jj1] += ulr
1680 120 166 1.4 0.0 if not sym1:
1681 xtax[jj1] += ulr.T
1682
1683 120 3838 32.0 0.0 ul = np.dot(vir, matl1)
1684 120 203 1.7 0.0 ur = ul if sym1 else np.dot(vir, matr1)
1685 120 926 7.7 0.0 B[jj1] += np.dot(ul, ur) * (1 if sym1 else 2)
1686
1687 # V^{-1} * dV/d_theta
1688 120 6278210 52318.4 15.2 E = np.dot(vsl1, matr1.T)
1689 120 425 3.5 0.0 if not sym1:
1690 E += np.dot(vsr1, matl1.T)
1691
1692 300 1293123 4310.4 3.1 for jj2, matl2, matr2, vsl2, vsr2, sym2 in self._gen_dV_dPar(ex_r, solver, group, jj1):
1693
1694 180 30494830 169415.7 73.9 re = np.dot(matr2.T, E)
1695 180 11760 65.3 0.0 rev = np.dot(re, vir[:, None])
1696 180 11262 62.6 0.0 vl = np.dot(vir[None, :], matl2)
1697 180 3949 21.9 0.0 vt = 2*np.dot(vl, rev)
1698
1699 180 318 1.8 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 2209 12.3 0.0 D[jj1, jj2] += vt
1706 180 337 1.9 0.0 if jj1 != jj2:
1707 60 232 3.9 0.0 D[jj2, jj1] += vt
1708
1709 180 23846 132.5 0.1 rt = np.sum(vsl2 * re.T) / 2 # trace dot
1710 180 309 1.7 0.0 if not sym2:
1711 rt += np.sum(vsr2 * le.T) / 2 # trace dot
1712
1713 180 481 2.7 0.0 hess_re[jj1, jj2] += rt
1714 180 251 1.4 0.0 if jj1 != jj2:
1715 60 96 1.6 0.0 hess_re[jj2, jj1] += rt
1716
1717 180 353 2.0 0.0 if self.reml:
1718 180 2151158 11950.9 5.2 ev = np.dot(E, viexog)
1719 180 33738 187.4 0.1 u1 = np.dot(viexog.T, matl2)
1720 180 25453 141.4 0.1 u2 = np.dot(matr2.T, ev)
1721 180 668 3.7 0.0 um = np.dot(u1, u2)
1722 180 4964 27.6 0.0 F[jj1][jj2] += um + um.T
1723 180 340 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 27 27.0 0.0 hess_fe -= fac * xtvix / rvir
1730 1 45 45.0 0.0 hess_re = hess_re - 0.5 * fac * (D/rvir - np.outer(B, B) / rvir**2)
1731 1 8 8.0 0.0 hess_fere = -fac * hess_fere / rvir
1732
1733 1 2 2.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 11 2.2 0.0 for j2 in range(j1 + 1):
1737 3 56 18.7 0.0 a = np.sum(QL[j1].T * QL[j2]) # trace dot
1738 3 168 56.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 5 1.7 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 3 3.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: 68.2131 s
File: statsmodels/regression/mixed_linear_model.mod.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 2 2.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 3 3.0 0.0 if method.lower() in ["newton", "ncg"]:
1854 raise ValueError("method %s not available for MixedLM" % method)
1855
1856 1 1 1.0 0.0 self.reml = reml
1857 1 2 2.0 0.0 self.cov_pen = cov_pen
1858 1 2 2.0 0.0 self.fe_pen = fe_pen
1859
1860 1 2 2.0 0.0 self._freepat = free
1861
1862 1 1 1.0 0.0 if full_output:
1863 hist = []
1864 else:
1865 1 1 1.0 0.0 hist = None
1866
1867 1 1 1.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 9 9.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 1 1.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 26827200 26827200.0 39.3 **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 2 2.0 0.0 converged = rslt.mle_retvals['converged']
1895 1 1 1.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 2 2.0 0.0 params = MixedLMParams.from_packed(params, self.k_fe, self.k_re,
1903 1 65 65.0 0.0 use_sqrt=self.use_sqrt, with_fe=False)
1904 1 1 1.0 0.0 cov_re_unscaled = params.cov_re
1905 1 1 1.0 0.0 vcomp_unscaled = params.vcomp
1906 1 84099 84099.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 45318 45318.0 0.1 scale = self.get_scale(fe_params, cov_re_unscaled, vcomp_unscaled)
1909 1 7 7.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 19 19.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 41252083 41252083.0 60.5 hess = self.hessian(params)
1922 1 16 16.0 0.0 hess_diag = np.diag(hess)
1923 1 1 1.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 53 53.0 0.0 pcov = np.linalg.inv(-hess)
1933 1 29 29.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 4008 4008.0 0.0 results = MixedLMResults(self, params_packed, pcov / scale)
1940 1 3 3.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 2 2.0 0.0 results.cov_re_unscaled = cov_re_unscaled
1946 1 2 2.0 0.0 results.method = "REML" if self.reml else "ML"
1947 1 2 2.0 0.0 results.converged = converged
1948 1 1 1.0 0.0 results.hist = hist
1949 1 2 2.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 1 1.0 0.0 results.k_re2 = self.k_re2
1954 1 4 4.0 0.0 results.k_vc = self.k_vc
1955 1 1 1.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