Return shape is NxMx(Ntheta)

def _param_grad_helper(self,X,X2,target):
        """Return shape is NxMx(Ntheta)"""
        if X2 is None: X2 = X
        FX = np.column_stack([f(X) for f in self.F])
        FX2 = np.column_stack([f(X2) for f in self.F])
        DER = np.zeros((self.n,self.n,self.n))
        for i in range(self.n):
            DER[i,i,i] = np.sqrt(self.weights[i])
        dw = self.variance * mdot(FX,DER,self.G_1,np.diag(np.sqrt(self.weights)),FX2.T)
        dv = mdot(FX,np.diag(np.sqrt(self.weights)),self.G_1,np.diag(np.sqrt(self.weights)),FX2.T)
        np.add(target[:,:,0],np.transpose(dv,(0,2,1)), target[:,:,0])
        np.add(target[:,:,1:],np.transpose(dw,(0,2,1)), target[:,:,1:])