'Returns the Integrated Mean Square Error for the unconditional KDE.
Parameters
bw: array_like
The bandwidth parameter(s).
Returns
CV: float
The cross-validation objective function.
Notes
See p. 27 in [1]_ for details on how to handle the multivariate
estimation with mixed data types see p.6 in [2]_.
The formula for the cross-validation objective function is:
.. math:: CV=\frac{1}{n^{2}}\sum_{i=1}^{n}\sum_{j=1}^{N}
\bar{K}_{h}(X_{i},X_{j})-\frac{2}{n(n-1)}\sum_{i=1}^{n}
\sum_{j=1,j\neq i}^{N}K_{h}(X_{i},X_{j})
Where :math:`\bar{K}_{h}` is the multivariate product convolution
kernel (consult [2]_ for mixed data types).
References
.. [1] Racine, J., Li, Q. Nonparametric econometrics: theory and
practice. Princeton University Press. (2007)
.. [2] Racine, J., Li, Q. "Nonparametric Estimation of Distributions
with Categorical and Continuous Data." Working Paper. (2000)'

def imse(self, bw):

    F = 0
    kertypes = dict(c=kernels.gaussian_convolution, o=kernels.wang_ryzin_convolution, u=kernels.aitchison_aitken_convolution)
    nobs = self.nobs
    data = (- self.data)
    var_type = self.var_type
    ix_cont = np.array([(c == 'c') for c in var_type])
    _bw_cont_product = bw[ix_cont].prod()
    Kval = np.empty(data.shape)
    for i in range(nobs):
        for (ii, vtype) in enumerate(var_type):
            Kval[:, ii] = kertypes[vtype](bw[ii], data[:, ii], data[(i, ii)])
        dens = (Kval.prod(axis=1) / _bw_cont_product)
        k_bar_sum = dens.sum(axis=0)
        F += k_bar_sum
    kertypes = dict(c=kernels.gaussian, o=kernels.wang_ryzin, u=kernels.aitchison_aitken)
    LOO = LeaveOneOut(self.data)
    L = 0
    Kval = np.empty(((data.shape[0] - 1), data.shape[1]))
    for (i, X_not_i) in enumerate(LOO):
        for (ii, vtype) in enumerate(var_type):
            Kval[:, ii] = kertypes[vtype](bw[ii], (- X_not_i[:, ii]), data[(i, ii)])
        dens = (Kval.prod(axis=1) / _bw_cont_product)
        L += dens.sum(axis=0)
    return ((F / (nobs ** 2)) - ((2 * L) / (nobs * (nobs - 1))))
