'Evaluate the probability density function.
Parameters
endog_predict: array_like, optional
Evaluation data for the dependent variables.  If unspecified, the
training data is used.
exog_predict: array_like, optional
Evaluation data for the independent variables.
Returns
pdf: array_like
The value of the probability density at `endog_predict` and `exog_predict`.
Notes
The formula for the conditional probability density is:
.. math:: f(y|x)=\frac{f(x,y)}{f(x)}
with
.. math:: f(x)=\prod_{s=1}^{q}h_{s}^{-1}k
\left(\frac{x_{is}-x_{js}}{h_{s}}\right)
where :math:`k` is the appropriate kernel for each variable.'

def pdf(self, endog_predict=None, exog_predict=None):

    if (endog_predict is None):
        endog_predict = self.endog
    else:
        endog_predict = _adjust_shape(endog_predict, self.k_dep)
    if (exog_predict is None):
        exog_predict = self.exog
    else:
        exog_predict = _adjust_shape(exog_predict, self.k_indep)
    pdf_est = []
    data_predict = np.column_stack((endog_predict, exog_predict))
    for i in range(np.shape(data_predict)[0]):
        f_yx = gpke(self.bw, data=self.data, data_predict=data_predict[i, :], var_type=(self.dep_type + self.indep_type))
        f_x = gpke(self.bw[self.k_dep:], data=self.exog, data_predict=exog_predict[i, :], var_type=self.indep_type)
        pdf_est.append((f_yx / f_x))
    return np.squeeze(pdf_est)
