def svgd_kernel_grady(self, h=(- 1), uStat=True, regCoeff=0.1):
    m = self.y.shape[0]
    xAdverSubsetInd = np.random.choice(self.theta.shape[0], m, replace=False)
    self.thetaSubset = self.theta[xAdverSubsetInd, :]
    self.SqxSubset = self.Sqx[xAdverSubsetInd, :]
    (n, d) = self.thetaSubset.shape
    pairwise_dists = (cdist(self.thetaSubset, self.y) ** 2)
    if (h < 0):
        h = np.median(pairwise_dists)
        h = np.sqrt(((0.5 * h) / np.log((n + 1))))
    Kxy = np.exp((((- pairwise_dists) / (h ** 2)) / 2))
    yGrad = np.zeros((m, d))
    for yInd in range(m):
        Kxy_cur = Kxy[:, yInd]
        xmy = ((self.thetaSubset - np.tile(self.y[yInd, :], [n, 1])) / (h ** 2))
        Sqxxmy = (self.SqxSubset - xmy)
        back = (np.tile(np.array([Kxy_cur]).T, (1, d)) * Sqxxmy)
        inner = np.tile(np.array([np.sum(np.matmul(back, back.T), axis=1)]).T, [1, d])
        yGrad[yInd, :] = (np.sum((xmy * inner), axis=0) + ((np.sum(back, axis=0) * np.sum(Kxy_cur)) / (h ** 2)))
        if uStat:
            front_u = (np.tile(np.array([((Kxy_cur ** 2) * np.sum((Sqxxmy ** 2), axis=1))]).T, [1, d]) * xmy)
            back_u = (np.tile(np.array([((Kxy_cur ** 2) / (h ** 2))]).T, [1, d]) * Sqxxmy)
            yGrad[yInd, :] = (yGrad[yInd, :] - np.sum((front_u + back_u), axis=0))
    if uStat:
        yGrad = ((yGrad * 2) / ((n * (n - 1)) * m))
    else:
        yGrad = ((yGrad * 2) / ((n ** 2) * m))
    if (regCoeff > 0):
        H_y = (cdist(self.y, self.y) ** 2)
        Kxy_y = np.exp((((- H_y) / (h ** 2)) / 2))
        sumKxy_y = np.sum(Kxy_y, axis=1)
        yReg = (((self.y * np.tile(np.array([sumKxy_y]).T, [1, d])) - np.matmul(Kxy_y, self.y)) / ((h ** 2) * m))
    yGrad = (yGrad + (regCoeff * yReg))
    return yGrad
def svgd_kernel_grady(self, h=(- 1), uStat=True, regCoeff=0.1):
    m = self.y.shape[0]
    xAdverSubsetInd = np.random.choice(self.theta.shape[0], m, replace=False)
    self.thetaSubset = self.theta[xAdverSubsetInd, :]
    self.SqxSubset = self.Sqx[xAdverSubsetInd, :]
    (n, d) = self.thetaSubset.shape
    pairwise_dists = (cdist(self.thetaSubset, self.y) ** 2)
    if (h < 0):
        h = np.median(pairwise_dists)
        h = np.sqrt(((0.5 * h) / np.log((n + 1))))
    Kxy = np.exp((((- pairwise_dists) / (h ** 2)) / 2))
    yGrad = np.zeros((m, d))
    for yInd in range(m):
        Kxy_cur = Kxy[:, yInd]
        xmy = ((self.thetaSubset - np.tile(self.y[yInd, :], [n, 1])) / (h ** 2))
        Sqxxmy = (self.SqxSubset - xmy)
        back = (np.tile(np.array([Kxy_cur]).T, (1, d)) * Sqxxmy)
        inner = np.tile(np.array([np.sum(np.matmul(back, back.T), axis=1)]).T, [1, d])
        yGrad[yInd, :] = (np.sum((xmy * inner), axis=0) + ((np.sum(back, axis=0) * np.sum(Kxy_cur)) / (h ** 2)))
        if uStat:
            front_u = (np.tile(np.array([((Kxy_cur ** 2) * np.sum((Sqxxmy ** 2), axis=1))]).T, [1, d]) * xmy)
            back_u = (np.tile(np.array([((Kxy_cur ** 2) / (h ** 2))]).T, [1, d]) * Sqxxmy)
            yGrad[yInd, :] = (yGrad[yInd, :] - np.sum((front_u + back_u), axis=0))
    if uStat:
        yGrad = ((yGrad * 2) / ((n * (n - 1)) * m))
    else:
        yGrad = ((yGrad * 2) / ((n ** 2) * m))
    if (regCoeff > 0):
        H_y = (cdist(self.y, self.y) ** 2)
        Kxy_y = np.exp((((- H_y) / (h ** 2)) / 2))
        sumKxy_y = np.sum(Kxy_y, axis=1)
        yReg = (((self.y * np.tile(np.array([sumKxy_y]).T, [1, d])) - np.matmul(Kxy_y, self.y)) / ((h ** 2) * m))
    yGrad = (yGrad + (regCoeff * yReg))
    return yGrad