From 9af4c34f90ebdefeb402603496f34e8584e7f318 Mon Sep 17 00:00:00 2001 From: Max Zwiessele Date: Thu, 13 Feb 2014 21:14:08 +0000 Subject: [PATCH] gradcheck fixes are not easy --- GPy/core/model.py | 53 +++++++++++++-------- GPy/core/parameterization/param.py | 2 +- GPy/core/parameterization/parameter_core.py | 8 ++-- GPy/core/parameterization/parameterized.py | 8 +--- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/GPy/core/model.py b/GPy/core/model.py index 1252198a..e7c6c7ec 100644 --- a/GPy/core/model.py +++ b/GPy/core/model.py @@ -411,12 +411,21 @@ class Model(Parameterized): f2 = self.objective_function(x - dx) gradient = self.objective_function_gradients(x) - param_list = self._raveled_index_for(target_param) - if self._has_fixes(): - param_list = np.intersect1d(np.r_[:self.size][self._fixes_], param_list, True) - - + if target_param is None: + transformed_index = range(len(x)) + else: + transformed_index = self._raveled_index_for(target_param) + if self._has_fixes(): + indices = np.r_[:self.size] + which = (transformed_index[:,None]==indices[self._fixes_]).nonzero()[0] + indices -= (~self._fixes_).cumsum() + transformed_index = indices[which] + + if transformed_index.size == 0: + print "No free parameters to check" + return + gradient = gradient[transformed_index] numerical_gradient = (f1 - f2) / (2 * dx) global_ratio = (f1 - f2) / (2 * np.dot(dx, np.where(gradient == 0, 1e-32, gradient))) @@ -439,40 +448,46 @@ class Model(Parameterized): separator = '-' * len(header_string[0]) print '\n'.join([header_string[0], separator]) if target_param is None: - param_list = range(len(x)) + param_index = range(len(x)) + transformed_index = param_index else: - param_list = self._raveled_index_for(target_param) + param_index = self._raveled_index_for(target_param) if self._has_fixes(): - param_list = np.intersect1d(np.r_[:self.size][self._fixes_], param_list, True) - - if param_list.size == 0: + indices = np.r_[:self.size] + which = (param_index[:,None]==indices[self._fixes_][None,:]).nonzero() + transformed_index = (indices-(~self._fixes_).cumsum())[which[1]] + param_index = indices[which[0]] + print param_index, transformed_index + else: + transformed_index = param_index + + if param_index.size == 0: print "No free parameters to check" return gradient = self.objective_function_gradients(x) np.where(gradient == 0, 1e-312, gradient) ret = True - for i, ind in enumerate(param_list): + for nind, xind in itertools.izip(param_index, transformed_index): xx = x.copy() - xx[ind] += step + xx[xind] += step f1 = self.objective_function(xx) - xx[ind] -= 2.*step + xx[xind] -= 2.*step f2 = self.objective_function(xx) - print ind numerical_gradient = (f1 - f2) / (2 * step) - ratio = (f1 - f2) / (2 * step * gradient[ind]) - difference = np.abs((f1 - f2) / 2 / step - gradient[ind]) + ratio = (f1 - f2) / (2 * step * gradient[xind]) + difference = np.abs((f1 - f2) / 2 / step - gradient[xind]) if (np.abs(1. - ratio) < tolerance) or np.abs(difference) < tolerance: - formatted_name = "\033[92m {0} \033[0m".format(names[ind]) + formatted_name = "\033[92m {0} \033[0m".format(names[nind]) ret &= True else: - formatted_name = "\033[91m {0} \033[0m".format(names[ind]) + formatted_name = "\033[91m {0} \033[0m".format(names[nind]) ret &= False r = '%.6f' % float(ratio) d = '%.6f' % float(difference) - g = '%.6f' % gradient[ind] + g = '%.6f' % gradient[xind] ng = '%.6f' % float(numerical_gradient) grad_string = "{0:<{c0}}|{1:^{c1}}|{2:^{c2}}|{3:^{c3}}|{4:^{c4}}".format(formatted_name, r, d, g, ng, c0=cols[0] + 9, c1=cols[1], c2=cols[2], c3=cols[3], c4=cols[4]) print grad_string diff --git a/GPy/core/parameterization/param.py b/GPy/core/parameterization/param.py index 56b8aab6..940cd1a0 100644 --- a/GPy/core/parameterization/param.py +++ b/GPy/core/parameterization/param.py @@ -348,7 +348,7 @@ class Param(ObservableArray, Constrainable, Gradcheckable, Indexable, Parameteri def _description_str(self): if self.size <= 1: return ["%f" % self] else: return [str(self.shape)] - def _parameter_names(self, add_name): + def parameter_names(self, add_name=False): return [self.name] @property def flattened_parameters(self): diff --git a/GPy/core/parameterization/parameter_core.py b/GPy/core/parameterization/parameter_core.py index 65504652..7ad228f7 100644 --- a/GPy/core/parameterization/parameter_core.py +++ b/GPy/core/parameterization/parameter_core.py @@ -25,8 +25,10 @@ class Parameterizable(object): from GPy.core.parameterization.array_core import ParamList _parameters_ = ParamList() - def parameter_names(self): - return [p.name for p in self._parameters_] + def parameter_names(self, add_name=False): + if add_name: + return [adjust_name_for_printing(self.name) + "." + xi for x in self._parameters_ for xi in x.parameter_names(add_name=True)] + return [xi for x in self._parameters_ for xi in x.parameter_names(add_name=True)] def parameters_changed(self): """ @@ -209,7 +211,7 @@ class Constrainable(Nameable, Indexable, Parameterizable): reconstrained = self.unconstrain() self.constraints.add(transform, self._raveled_index()) if warning and reconstrained.size > 0: - print "WARNING: reconstraining parameters {}".format(self.parameter_names) + print "WARNING: reconstraining parameters {}".format(self.parameter_names() or self.name) if update: self._highest_parent_.parameters_changed() diff --git a/GPy/core/parameterization/parameterized.py b/GPy/core/parameterization/parameterized.py index a976eb93..593c37e9 100644 --- a/GPy/core/parameterization/parameterized.py +++ b/GPy/core/parameterization/parameterized.py @@ -434,11 +434,7 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable): return self._direct_parent_.hirarchy_name() + adjust_name_for_printing(self.name) else: return adjust_name_for_printing(self.name) - def _parameter_names(self, add_name=False): - if add_name: - return [adjust_name_for_printing(self.name) + "." + xi for x in self._parameters_ for xi in x._parameter_names(add_name=True)] - return [xi for x in self._parameters_ for xi in x._parameter_names(add_name=True)] - parameter_names = property(_parameter_names, doc="Names for all parameters handled by this parameterization object -- will add hirarchy name entries for printing") + #parameter_names = property(parameter_names, doc="Names for all parameters handled by this parameterization object -- will add hirarchy name entries for printing") def _collect_gradient(self, target): [p._collect_gradient(target[s]) for p, s in itertools.izip(self._parameters_, self._param_slices_)] @property @@ -468,7 +464,7 @@ class Parameterized(Constrainable, Pickleable, Observable, Gradcheckable): name = adjust_name_for_printing(self.name) + "." constrs = self._constraints_str; ts = self._ties_str - desc = self._description_str; names = self.parameter_names + desc = self._description_str; names = self.parameter_names() nl = max([len(str(x)) for x in names + [name]]) sl = max([len(str(x)) for x in desc + ["Value"]]) cl = max([len(str(x)) if x else 0 for x in constrs + ["Constraint"]])