def update_grads(self, X, dL_dW):
for i_seq, i_fea in enumerate(self.warping_indices):<EOL><INDENT>ai, bi = self.params[i_seq][<NUM_LIT:0>], self.params[i_seq][<NUM_LIT:1>]<EOL>x_pow_a = np.power(self.X_normalized[:, i_fea], ai)<EOL>dz_dai = bi * np.power(<NUM_LIT:1> - x_pow_a, bi-<NUM_LIT:1>) * x_pow_a * np.log(self.X_normalized[:, i_fea])<EOL>dz_dbi = - np.power(<NUM_LIT:1> - x_pow_a, bi) * np.log(<NUM_LIT:1> - x_pow_a)<EOL>dL_dai = np.sum(dL_dW[:, i_fea] * dz_dai)<EOL>dL_dbi = np.sum(dL_dW[:, i_fea] * dz_dbi)<EOL>self.params[i_seq][<NUM_LIT:0>].gradient[:] = dL_dai<EOL>self.params[i_seq][<NUM_LIT:1>].gradient[:] = dL_dbi<EOL><DEDENT>
Update the gradients of marginal log likelihood with respect to the parameters of warping function

        Parameters
        ----------
        X : array_like, shape = (n_samples, n_features)
            The input BEFORE warping

        dL_dW : array_like, shape = (n_samples, n_features)
            The gradient of marginal log likelihood with respect to the Warped input

        Math
        ----
        let w = f(x), the input after warping, then
        dW_da = b * (1 - x^a)^(b - 1) * x^a * ln(x)
        dW_db = - (1 - x^a)^b * ln(1 - x^a)
        dL_da = dL_dW * dW_da
        dL_db = dL_dW * dW_db