<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def predict_logpdf(self, X, y, nsamples=200, likelihood_args=()):
 r""" Predictive log-probability density function of a Bayesian GLM. Parameters X : ndarray (N*,d) array query input dataset (N* samples, D dimensions). y : float or ndarray The test observations of shape (N*,) to evaluate under, :math:`\log p(y^* |\mathbf{x}^*, \mathbf{X}, y)`. nsamples : int, optional Number of samples for sampling the log predictive distribution. likelihood_args : sequence, optional sequence of arguments to pass to the likelihood function. These are non-learnable parameters. They can be scalars or arrays of length N*. Returns ------- logp : ndarray The log probability of y* given X* of shape (N*,). logp_min : ndarray The minimum sampled values of the predicted log probability (same shape as p) logp_max : ndarray The maximum sampled values of the predicted log probability (same shape as p) """

        X, y = check_X_y(X, y)

        # Get latent function samples
        N = X.shape[0]
        ps = np.empty((N, nsamples))
        fsamples = self._sample_func(X, nsamples)

        # Push samples though likelihood pdf
        llargs = tuple(chain(atleast_list(self.like_hypers_), likelihood_args))
        for i, f in enumerate(fsamples):
            ps[:, i] = self.likelihood.loglike(y, f, *llargs)

        # Average transformed samples (MC integration)
        logp = ps.mean(axis=1)
        logp_min = ps.min(axis=1)
        logp_max = ps.max(axis=1)

        return logp, logp_min, logp_max