def check_gradients(x, model=None, delta=1e-10): """Compute gradients using symmetric differences. x: The expression to compute gradients of. model: Optional list of parameters to compute gradients with respect to. This is extremely slow and is used only for debugging.""" if model is None: model = [subx for subx in expr.topological(x) if isinstance(subx, expr.parameter)] gradients = {} for param in model: g = numpy.empty_like(param.value) it = numpy.nditer([param.value, g], [], [['readwrite'], ['writeonly']]) for pi, gi in it: save = pi pi -= delta/2 val_minus = compute_values(x)[x] pi += delta val_plus = compute_values(x)[x] pi[...] = save gi[...] = (val_plus-val_minus)/delta gradients[param] = g return gradients
def compute_values(x, initvalues={}): """Evaluate an expression and all its subexpressions. x: The expression to evaluate. initvalues: Optional dictionary from subexpressions to precomputed values; can be used to continue a computation when the expression grows. """ values = collections.OrderedDict() for subx in expr.topological(x): if subx in initvalues: values[subx] = initvalues[subx] else: try: subx.forward(values) except: if logging.debug: sys.stderr.write("Expression traceback (most recent call last):\n" + "".join(logging.format_list(subx.stack))) raise if logging.trace: sys.stdout.write("<%s> = %s = %s" % (subx.serial, subx, format_value(values[subx]))) return values