docs: def pdf(self, data_predict=None):
          r"""
          Evaluate the probability density function.
  
          Parameters
          ----------
          data_predict: array_like, optional
              Points to evaluate at.  If unspecified, the training data is used.
  
          Returns
          -------
          pdf_est: array_like
              Probability density function evaluated at `data_predict`.
  
          Notes
          -----
          The probability density is given by the generalized product kernel
          estimator:
  
          .. math:: K_{h}(X_{i},X_{j}) =
              \prod_{s=1}^{q}h_{s}^{-1}k\left(\frac{X_{is}-X_{js}}{h_{s}}\right)
          """
          if data_predict is None:
              data_predict = self.data
          else:
              data_predict = _adjust_shape(data_predict, self.k_vars)
  
          pdf_est = []
          for i in range(np.shape(data_predict)[0]):
              pdf_est.append(gpke(self.bw, data=self.data,
                                  data_predict=data_predict[i, :],
                                  var_type=self.var_type) / self.nobs)
  
          pdf_est = np.squeeze(pdf_est)
          return pdf_est