diff --git a/vkoga_2L/kernels.py b/vkoga_2L/kernels.py index ab6d209f7de7425654f81ec4f3d90f09633c2386..ca47965c6e1db06e4211f13c7faf6450e72eb6eb 100644 --- a/vkoga_2L/kernels.py +++ b/vkoga_2L/kernels.py @@ -76,42 +76,58 @@ class IMQ(RBF): self.rbf = lambda ep, r: 1. / np.sqrt(1 + (ep * r) ** 2) class Matern(RBF): - def __init__(self, ep=1, k=0): - self.ep = ep + def __init__(self, ep=1, k=0, flag_normalize_y=False, flag_normalize_x=False): + + # flag_normalize_x: Adjusts the shape parameter such that we "converge" to the Gaussian kernel as k -> inf + # flag_normalize_y: Adjusts the kernel such that the diagonal is 1 + + + self.ep = ep * np.sqrt(2 * k + 1) if flag_normalize_x else ep + if k == 0: self.name = 'mat0' - self.rbf = lambda ep, r : np.exp(-ep * r) + self.rbf_ = lambda ep, r : np.exp(-ep * r) elif k == -1: self.name = 'derivative kernel ob quadratic matern' - self.rbf = lambda ep, r: np.exp(-r) * (r**2 - (2 * 1 + 3) * r + 1 ** 2 + 2 * 1) + self.rbf_ = lambda ep, r: np.exp(-r) * (r**2 - (2 * 1 + 3) * r + 1 ** 2 + 2 * 1) elif k == 1: self.name = 'mat1' - self.rbf = lambda ep, r: np.exp(-ep * r) * (1 + ep * r) + self.rbf_ = lambda ep, r: np.exp(-ep * r) * (1 + ep * r) elif k == 2: self.name = 'mat2' - self.rbf = lambda ep, r: np.exp(-ep * r) * (3 + 3 * ep * r + 1 * (ep * r) ** 2) + self.rbf_ = lambda ep, r: np.exp(-ep * r) * (3 + 3 * ep * r + 1 * (ep * r) ** 2) elif k == 3: self.name = 'mat3' - self.rbf = lambda ep, r: np.exp(-ep * r) * (15 + 15 * ep * r + 6 * (ep * r) ** 2 + 1 * (ep * r) ** 3) + self.rbf_ = lambda ep, r: np.exp(-ep * r) * (15 + 15 * ep * r + 6 * (ep * r) ** 2 + 1 * (ep * r) ** 3) elif k == 4: self.name = 'mat4' - self.rbf = lambda ep, r: np.exp(-ep * r) * (105 + 105 * ep * r + 45 * (ep * r) ** 2 + 10 * (ep * r) ** 3 + 1 * (ep * r) ** 4) + self.rbf_ = lambda ep, r: np.exp(-ep * r) * (105 + 105 * ep * r + 45 * (ep * r) ** 2 + 10 * (ep * r) ** 3 + 1 * (ep * r) ** 4) elif k == 5: self.name = 'mat5' - self.rbf = lambda ep, r: np.exp(-ep * r) * (945 + 945 * ep * r + 420 * (ep * r) ** 2 + 105 * (ep * r) ** 3 + 15 * (ep * r) ** 4 + 1 * (ep * r) ** 5) + self.rbf_ = lambda ep, r: np.exp(-ep * r) * (945 + 945 * ep * r + 420 * (ep * r) ** 2 + 105 * (ep * r) ** 3 + 15 * (ep * r) ** 4 + 1 * (ep * r) ** 5) elif k == 6: self.name = 'mat6' - self.rbf = lambda ep, r: np.exp(-ep * r) * (10395 + 10395 * ep * r + 4725 * (ep * r) ** 2 + 1260 * (ep * r) ** 3 + 210 * (ep * r) ** 4 + 21 * (ep * r) ** 5 + 1 * (ep * r) ** 6) + self.rbf_ = lambda ep, r: np.exp(-ep * r) * (10395 + 10395 * ep * r + 4725 * (ep * r) ** 2 + 1260 * (ep * r) ** 3 + 210 * (ep * r) ** 4 + 21 * (ep * r) ** 5 + 1 * (ep * r) ** 6) elif k == 7: self.name = 'mat7' - self.rbf = lambda ep, r: np.exp(-ep * r) * (135135 + 135135 * ep * r + 62370 * (ep * r) ** 2 + 17325 * (ep * r) ** 3 + 3150 * (ep * r) ** 4 + 378 * (ep * r) ** 5 + 28 * (ep * r) ** 6 + 1 * (ep * r) ** 7) + self.rbf_ = lambda ep, r: np.exp(-ep * r) * (135135 + 135135 * ep * r + 62370 * (ep * r) ** 2 + 17325 * (ep * r) ** 3 + 3150 * (ep * r) ** 4 + 378 * (ep * r) ** 5 + 28 * (ep * r) ** 6 + 1 * (ep * r) ** 7) else: self.name = None - self.rbf = None + self.rbf_ = None raise Exception('This Matern kernel is not implemented') + + if flag_normalize_y: + c_norm = 1 / self.rbf_(ep, 0) + else: + c_norm = 1 + + self.rbf = lambda ep, r: c_norm * self.rbf_(ep, r) class Wendland(RBF): - def __init__(self, ep=1, k=0, d=1): + def __init__(self, ep=1, k=0, d=1, flag_normalize_y=False): + + # flag_normalize_y: Adjusts the kernel such that the diagonal is 1 + self.ep = ep self.name = 'wen_' + str(d) + '_' + str(k) l = np.floor(d / 2) + k + 1 @@ -129,7 +145,13 @@ class Wendland(RBF): raise Exception('This Wendland kernel is not implemented') c = np.math.factorial(l + 2 * k) / np.math.factorial(l) e = l + k - self.rbf = lambda ep, r: np.maximum(1 - ep * r, 0) ** e * p(ep * r) / c + + if flag_normalize_y: + c_norm = c / p(0) + else: + c_norm = 1 + + self.rbf = lambda ep, r: c_norm * np.maximum(1 - ep * r, 0) ** e * p(ep * r) / c # Polynomial kernels diff --git a/vkoga_2L/tkernels.py b/vkoga_2L/tkernels.py index 26e26602f18e4819b4ba4ff29f0345e83b26bf95..40a032d4e9a90f5a4679a2ee0d6eae7590a75730 100644 --- a/vkoga_2L/tkernels.py +++ b/vkoga_2L/tkernels.py @@ -75,43 +75,56 @@ class IMQ(RBF): class Matern(RBF): - def __init__(self, ep=1, k=0): - self.ep = ep + def __init__(self, ep=1, k=0, flag_normalize_y=False, flag_normalize_x=False): + + # flag_normalize_x: Adjusts the shape parameter such that we "converge" to the Gaussian kernel as k -> inf + # flag_normalize_y: Adjusts the kernel such that the diagonal is 1 + + + self.ep = ep * np.sqrt(2 * k + 1) if flag_normalize_x else ep + if k == 0: self.name = 'mat0' - self.rbf = lambda ep, r: torch.exp(-ep * r) + self.rbf_ = lambda ep, r: torch.exp(-ep * r) elif k == 1: self.name = 'mat1' - self.rbf = lambda ep, r: torch.exp(-ep * r) * (1 + ep * r) + self.rbf_ = lambda ep, r: torch.exp(-ep * r) * (1 + ep * r) elif k == 2: self.name = 'mat2' - self.rbf = lambda ep, r: torch.exp(-ep * r) * (3 + 3 * ep * r + (ep * r) ** 2) + self.rbf_ = lambda ep, r: torch.exp(-ep * r) * (3 + 3 * ep * r + (ep * r) ** 2) elif k == 3: self.name = 'mat3' - self.rbf = lambda ep, r: torch.exp(-ep * r) * (15 + 15 * ep * r + 6 * (ep * r) ** 2 + 1 * (ep * r) ** 3) + self.rbf_ = lambda ep, r: torch.exp(-ep * r) * (15 + 15 * ep * r + 6 * (ep * r) ** 2 + 1 * (ep * r) ** 3) elif k == 4: self.name = 'mat4' - self.rbf = lambda ep, r: torch.exp(-ep * r) * ( + self.rbf_ = lambda ep, r: torch.exp(-ep * r) * ( 105 + 105 * ep * r + 45 * (ep * r) ** 2 + 10 * (ep * r) ** 3 + 1 * (ep * r) ** 4) elif k == 5: self.name = 'mat5' - self.rbf = lambda ep, r: torch.exp(-ep * r) * ( + self.rbf_ = lambda ep, r: torch.exp(-ep * r) * ( 945 + 945 * ep * r + 420 * (ep * r) ** 2 + 105 * (ep * r) ** 3 + 15 * (ep * r) ** 4 + 1 * ( ep * r) ** 5) elif k == 6: self.name = 'mat6' - self.rbf = lambda ep, r: torch.exp(-ep * r) * ( + self.rbf_ = lambda ep, r: torch.exp(-ep * r) * ( 10395 + 10395 * ep * r + 4725 * (ep * r) ** 2 + 1260 * (ep * r) ** 3 + 210 * ( ep * r) ** 4 + 21 * (ep * r) ** 5 + 1 * (ep * r) ** 6) elif k == 7: self.name = 'mat7' - self.rbf = lambda ep, r: torch.exp(-ep * r) * ( + self.rbf_ = lambda ep, r: torch.exp(-ep * r) * ( 135135 + 135135 * ep * r + 62370 * (ep * r) ** 2 + 17325 * (ep * r) ** 3 + 3150 * ( ep * r) ** 4 + 378 * (ep * r) ** 5 + 28 * (ep * r) ** 6 + 1 * (ep * r) ** 7) else: self.name = None - self.rbf = None + self.rbf_ = None raise Exception('This Matern kernel is not implemented') + + if flag_normalize_y: + c_norm = 1 / self.rbf_(ep, torch.tensor(0)) + else: + c_norm = 1 + + self.rbf = lambda ep, r: c_norm * self.rbf_(ep, r) class HatFunction(RBF): @@ -129,10 +142,13 @@ class PowerKernels(RBF): class Wendland(RBF): - def __init__(self, ep=1, k=0, d=1): + def __init__(self, ep=1, k=0, d=1, flag_normalize_y=False): + + # flag_normalize_y: Adjusts the kernel such that the diagonal is 1 + self.ep = ep self.name = 'wen_' + str(d) + '_' + str(k) - l = np.floor(d / 2) + k + 1 + l = int(np.floor(d / 2) + k + 1) if k == 0: p = lambda r: 1 elif k == 1: @@ -148,10 +164,15 @@ class Wendland(RBF): 105 * (l + 4)) * r + 105 else: raise Exception('This Wendland kernel is not implemented') - c = np.math.factorial(l + 2 * k) / np.math.factorial(l) + c = np.math.factorial(l + 2 * int(k)) / np.math.factorial(l) e = l + k - # self.rbf = lambda ep, r: np.maximum(1 - ep * r, 0) ** e * p(ep * r) / c - self.rbf = lambda ep, r: torch.clamp(1 - ep * r, min=0) ** e * p(ep * r) / c + + if flag_normalize_y: + c_norm = c / p(0) + else: + c_norm = 1 + + self.rbf = lambda ep, r: c_norm * torch.clamp(1 - ep * r, min=0) ** e * p(ep * r) / c # # Polynomial kernels