def backprop_d(W_d, a_d_tree, a_e_tree): if len(a_d_tree) > 0: tree_out = Tree(a_d_tree.node, [backprop_d(W_d, child, a_e_tree[i]) for i, child in enumerate(a_d_tree)]) delta_p = np.concatenate([child.delta for child in tree_out]) # add contribution to gradient using current node a_d & prev. node delta tree_out.gradW_d = delta_p.reshape((len(delta_p.flatten()), 1)) * a_d_tree.node tree_out.gradb_d = delta_p # calculate this node's delta, return annotated tree tree_out.delta = np.dot(W_d.transpose(), delta_p) * (1 - tree_out.node ** 2) return tree_out else: tree_out = Tree(a_d_tree.node, []) tree_out.delta = (a_d_tree.node - get_concat_terminals(a_e_tree)) * (1 - a_d_tree.node ** 2) tree_out.gradW_d = np.zeros(W_d.shape) tree_out.gradb_d = np.zeros(W_d.shape[0]) return tree_out