'Apply dimensionality reduction to X using the model.
Compute the expected mean of the latent variables.
See Barber, 21.2.33 (or Bishop, 12.66).
Parameters
X : array-like, shape (n_samples, n_features)
Training data.
Returns
X_new : array-like, shape (n_samples, n_components)
The latent variables of X.'

def transform(self, X):

    check_is_fitted(self, 'components_')
    X = check_array(X)
    Ih = np.eye(len(self.components_))
    X_transformed = (X - self.mean_)
    Wpsi = (self.components_ / self.noise_variance_)
    cov_z = linalg.inv((Ih + np.dot(Wpsi, self.components_.T)))
    tmp = np.dot(X_transformed, Wpsi.T)
    X_transformed = np.dot(tmp, cov_z)
    return X_transformed
