Using Program Induction to Interpret Transition System Dynamics
Svetlin Penkov Subramanian Ramamoorthy
cs.AI


[
Using Program Induction to Interpret Transition System Dynamics















Svetlin Penkoved
Subramanian Ramamoorthyed


edThe University of Edinburgh, Edinburgh, United Kingdom

Svetlin Penkovsv.penkov@ed.ac.uk




program induction, explainability, interpretability

0.3in
]









  



Explaining and reasoning about processes which underlie observed black-box phenomena enables the discovery of causal mechanisms, derivation of suitable abstract representations and the formulation of more robust predictions. We propose to learn high level functional programs in order to represent abstract models which capture the invariant structure in the observed data. We introduce the π-machine (program-induction machine) – an architecture able to induce interpretable LISP-like programs from observed data traces. We propose an optimisation procedure for program learning based on backpropagation, gradient descent and A* search. We apply the proposed method to two problems: system identification of dynamical systems and explaining the behaviour of a DQN agent. Our results show that the π-machine can efficiently induce interpretable programs from individual data traces.




§ INTRODUCTION

Learning models of transition systems has been a core concern within machine learning, with applications ranging from system identification of dynamical systems <cit.> and inference of human choice behaviour <cit.> to reverse engineering the behaviour of a device or computer program from observations and traces <cit.>. With the increasing use of these learnt models in the inner loops of decision making systems, e.g., in robotics and human-machine interfaces, it has become necessary to ensure not only that these models are accurate predictors of behaviour, but also that their causal mechanisms are exposed to the system designer in a more interpretable manner. There is also the need to explain the model in terms of counterfactual reasoning <cit.>, e.g., what would we expect the system to do if a certain variable were changed or removed, or model checking <cit.> of longer term properties including safety and large deviations in performance. We address these needs through a program induction based framework.

We propose to learn high level functional programs in order to represent abstract models which capture the invariant structure in the observed data. Recent works have demonstrated the usefulness of program representations in capturing human-like concepts <cit.>. Used in this way, program-based representations boost generalisation and enable one-shot learning. Also, and arguably more importantly, they are significantly more amenable to model checking and human interpretability.

In this paper, we introduce the π-machine (program-induction machine), an architecture which is able to induce LISP-like programs from observed transition system data traces in order to explain various phenomena. Inspired by differentiable neural computers <cit.>, the π-machine, as shown in Figure <ref>, is composed of a memory unit and a controller capable of learning programs from data by exploiting the scalability of stochastic gradient descent. However, the final program obtained after training is not an opaque object encoded in the weights of a controller neural network, but a LISP-like program which provides a rigorous and interpretable description of the observed phenomenon. A key feature of our approach is that we allow the user to provide a set of predicates of interest in order to specify the properties they are interested in understanding as well as the context in which the data is to be explained. By exploiting the equivalence between computational graphs and functional programs we describe a hybrid optimisation procedure based on backpropagation, gradient descent, and A* search which is used to induce programs from data traces.

We evaluate the performance of the π-machine on two different problems. Firstly, we apply it to data from physics experiments and show that it is able to induce programs which represent fundamental laws of physics. The learning procedure has access to relevant variables, but it does not have any other prior knowledge regarding physical laws which it has discovered in the same sense as in <cit.> although far more computationally tractably. Secondly, we study the use of the proposed procedure in explaining control policies learnt by a deep Q-network (DQN). Starting from behaviour traces of a reinforcement learning agent that has learnt to play the game of Pong, we demonstrate how the π-machine learns a functional program to describe that policy.



§ RELATED WORK



  
Explainability and interpretability.
The immense success of deep neural network based learning systems and their rapid adoption in numerous real world application domains has renewed interest in the interpretability and explainability of learnt models <cit.>. There is recognition that Bayesian rule lists <cit.>, decision trees and probabilistic graphical models are interpretable to the extent that they impose strong structural constraints on models of the observed data and allow for various types of queries, including introspective and counterfactual ones. In contrast, deep learning models usually are trained `per query' and have numerous parameters that could be hard to interpret. <cit.> introduced deconvolutional networks in order to visualise the layers of convolutional networks and provide a more intuitive understanding of why they perform well. <cit.> describe Semi-Aggregated Markov Decision Process (SAMDP) in order to analyse and understand the behaviour of a DQN based agent. Methods for textual rationalisation of the predictions made by deep models have also been proposed <cit.>. While all of these works provide useful direction, more generic methods are required which need not be hand-crafted to explain specific aspects of individual models. In this sense, we follow the model-agnostic explanation approach of <cit.>, who provide “textual or visual artefacts” explaining the prediction of any classifier by treating it as a black-box. Similarly to the way in which <cit.> utilise local classifiers composed together to explain a more complex model, we present an approach to incrementally constructing functional programs that explain a complex transition system from more localised predicates of interest.



The π-machine treats the process which has generated the observed data as a black-box and attempts to induce LISP-like program which can be interpreted and used to explain the data. We show that the proposed method can be applied both to introspection of machine learning models and to the broader context of autonomous agents.



  
Program learning and synthesis.
Program learning and synthesis has a long history, with the long-standing challenge being the high complexity deriving from the immense search space. Following classic and pioneering work such as by <cit.> who used inductive inference in a logic programming setting, others have developed methods based on a variety of approaches ranging from SAT solvers <cit.> to genetic algorithms <cit.>, which tend to scale poorly hence often become restricted to a narrow class of programs. Recently, deep neural networks have been augmented with a memory unit resulting in models similar to the original von Neumann architecture. These models can induce programs through stochastic gradient descent by optimising performance on input/output examples <cit.> or synthetic execution traces <cit.>. Programs induced with such neural architectures are encoded in the parameters of the controller network and are, in general, not easily interpretable (particularly from the point of view of being able to ask counterfactual questions or performing model checking). Another approach is to directly generate the source code of the output program which yields consistent high level programs. Usually, these types of approaches require large amounts of labelled data - either program input/output examples <cit.> or input paired with the desired output program code <cit.>.

Determining how many input/output examples or execution traces are required in order to generalise well is still an open research problem. However, in this paper, we focus attention more on the explanatory power afforded by programs rather than on the broader problems of generalisation in the space of programs. While these characteristics are of course related, we take a view similar to that of <cit.>, arguing that it is possible to build from locally valid program fragments which provide useful insight into the black-box processes generating the data. By combining gradient descent and A* search the π-machine is able to learn informative and interpretable high-level LISP-like programs, even just from a single observation trace.





§ PROBLEM DEFINITION

Consider the labelled transition system Ω(𝒮, 𝒜, δ) where 𝒮 is a non-empty set of states, 𝒜 is a non-empty set of actions, each parametrised by θ∈ℝ^D, and δ: 𝒮×𝒜→𝒮 is the state transition function. We define an observation trace 𝒯 as a sequence of observed state-action pairs (s_t, a_t(θ_t)) ∈𝒮×𝒜 generated by the recursive relationship s_t+1 = δ(s_t, a_t(θ_t)) for 1 ≤ t ≤ T. We are interested in inducing a LISP-like functional program ρ which when executed by an abstract machine is mapped to an execution trace 𝒯_ρ such that 𝒯_ρ and 𝒯 are equivalent according to an input specification.

We represent the abstract machine as another labelled transition system Π(ℳ, ℐ, ε) where ℳ is the set of possible memory state configurations, ℐ is the set of supported instructions and ε: ℳ×ℐ→ℳ specifies the effect of each instruction. We consider two types of instructions – primitive actions which emulate the execution of a ∈𝒜 or arithmetic functions f ∈ℱ such that ℐ = 𝒜∪ℱ. Furthermore, a set of observed state variables ℳ_v ⊆𝒮, which vary over time, are stored in memory together with a set of induced free parameters ℳ_p. The variables in ℳ_v form a context which the program will be built on. A custom  detector 𝒟_v, operating on the raw data stream, could be provided for each variable, thus enabling the user to make queries with respect to different contexts and property specifications.

The execution of a program containing primitive actions results in a sequence of actions. Therefore, we represent a program ρ as a function which maps a set of input variables x_v ⊂ℳ_v and a set of free parameters x_p ⊂ℳ_p to a finite sequence of actions â_1(θ̂_̂1̂), …â_T'(θ̂_̂T̂'̂). We are interested in inducing a program which minimises the total error between the executed and the observed actions:

    L(ρ) = ∑_t=1^min(T, T')σ_act(â_t, θ̂_̂t̂, a_t, θ_t) + σ_len(T, T')

The error function σ_act determines the difference between two actions, while σ_len compares the lengths of the generated and observed action traces.  By providing the error functions σ_act and σ_len one can target different aspects of the observation trace to be explained as they specify when two action traces are equivalent.



§ METHOD


The proposed program induction procedure is based on two major steps. Firstly, we explain how a given functional program can be optimised such that the loss L(ρ) is minimised. Secondly, we explain how the space of possible program structures can be searched efficiently by utilising gradient information. An architectural overview of the π-machine is provided in Figure <ref>.



 §.§ Program optimisation



Neural networks are naturally expressed as computational graphs which are the most fundamental abstraction in computational deep learning frameworks <cit.>. Optimisation within a computational graph is usually performed by pushing the input through the entire graph in order to calculate the output (forward pass) and then backpropagating the error signal to update each parameter (backward pass). A key observation for the development of the π-machine is that computational graphs and functional programs are equivalent as both describe arbitrary compositions of pure functions applied to input data.  Therefore, similarly to a computational graph, a functional program can also be optimised by executing the program (forward pass), measuring the error signal and then performing backpropagation to update the program (backward pass).



  
Forward pass.
When a program is executed it is interpreted to a sequence of instructions i_1, …, i_n ∈ℐ which are executed by recursively calling  ε(…ε(ε(ℳ_1, i_1), i_2)…, i_n). ℳ_1 is the initial memory state initialised with the observed variables from s_1 and any induced parameters. The π-machine keeps a time counter t which is initialised to 1 and is automatically incremented whenever a primitive action instruction is executed. If the instruction i_k is a primitive action, i_k ∈𝒜, then the π-machine automatically sets â_t = i_k and invokes the error function σ_act(â_t, θ̂_̂t̂, a_t, θ_t), where θ̂_̂t̂ has been calculated by previous instructions. If the error is above a certain threshold e_max the program execution is terminated and the backward pass is initiated. Otherwise, the time counter is incremented and the values of the variables in ℳ_v are automatically updated to the new observed state. Essentially, the π-machine simulates the execution of each action reflecting any changes it has caused in the observed state. Alternatively, if the currently executed instruction i_k is a function, i_k ∈ℱ, then the resulting value is calculated and i_k, together with its arguments, is added to a detailed call trace χ maintained by the π-machine. Importantly, each function argument is either a parameter or a variable read from memory at time t or the result of another function. All this information is kept in χ which eventually contains the computational tree of the program.



  
Backward pass.
The gradients of the loss function L(ρ) with respect to the program inputs x_v and x_p are required to perform a gradient descent step. Crucially, programs executed by the π-machine are automatically differentiated. The π-machine performs reverse-mode automatic differentiation, similarly to Autograd <cit.>, by traversing the call trace χ, and post-multiplying Jacobian matrices. We assume that the Jacobian matrix with respect to every input argument of any function f ∈ℱ or any specified error function σ_act is known a priori. Let f ∈ℱ be a function whose output needs to be differentiated with respect to the input arguments. There are three types of derivatives, which need to be considered in order to traverse backwards the entire tree of computations:


  * Let g ∈ℱ, then ∂ f/∂ g is the Jacobian matrix of f with respect to the output of g and can be directly calculated.

  * Let p ∈ x_p, then the gradient ∂ f/∂ p is calculated by multiplying the corresponding Jacobian matrix of f with the value of p.

  * Let v ∈ x_v, then the gradient ∂ f/∂ v|_t=t_r is calculated by multiplying the corresponding Jacobian of f with the value of the variable at the time it was read from memory t_r.




  
Gradient descent step.
Once the gradient ∇_p L(ρ) of the loss function with respect to each input parameter p ∈ x_p is calculated we utilise AdaGrad <cit.> to update the values of all parameters after each program execution. The gradient ∇_v L(ρ) with respect to each input variable v ∈ x_v is also available. However, a variable cannot be simply updated in the direction of the gradient as it represents a symbol, not just a value. Variables can only take values from memory which is automatically updated according to the observation trace during execution. Nevertheless, the gradient provides important information about the direction of change which we utilise to find variables that minimise the loss. Whenever the memory state is automatically updated, a KD-tree is built for each type of variable stored in memory. We assume that the variables in memory are real vectors with different length. So, we represent the KD-tree which stores all D-dimensional variables in memory at time t as 𝒦^D_t. If a d-dimensional variable v is to be optimised it is replaced with a temporary parameter p_temp initialised with v_t which is the value of v read from memory at the respective time step t. The temporary parameter p_temp is also updated with AdaGrad <cit.>. After each descent step, the nearest neighbour of the updated value p'_temp is determined by querying the KD-tree with 𝒦^d_t(p'_temp). If the result of the query is a different d-dimensional variable u then the temporary parameter is immediately set to p_temp = u_t. As this often shifts the solution to a new region of the error space the gradient history for all parameters p ∈ x_p is reset. Eventually, when a solution is to be returned, the temporary parameters are substituted with their closest variables according to the respective 𝒦^D_t. The forward and backward passes are repeated until the error is below the maximum error threshold e_max or a maximum number of iterations is reached. After that the optimised program ρ^* is scored according to its error and complexity, and pushed to a priority queue holding potential solutions.





 §.§ Structure search

We represent the space of possible program structures as a graph G=(T^AST, E) where each node T_i ∈ T^AST is a valid program abstract syntax tree (AST). There is an edge from T_i to T_j if and only if T_j can be obtained by replacing exactly one of the leaves in T_i with a subtree T_s of depth 1. The program induction procedure always starts with an empty program. So, we frame structure search as a path finding problem, solved through the use of A* search.



  
Score function.
The total cost function we use is f_total(ρ) = C(ρ) + L(ρ), where L(ρ) is the loss function defined in equation (<ref>) and C(ρ) is a function which measures the complexity of the program ρ. C(ρ) can be viewed as the cost to reach ρ and L(ρ) as the distance to the desired goal. The complexity function C(ρ) is the weighted sum of (i) maximum depth of the program AST; (ii) the number of free parameters; (iii) the number of variables used by the program; the weights of which we set to w_C = [10, 5, 1]. These choices ensure that short programs, maximally exploiting structure of the observation trace, are preferred.



  
Neighbours expansion.
When the current best candidate solution is popped from the priority queue, we check if it matches the observation trace according to the input specification. If so, the candidate can be returned as the final solution, otherwise it is used as a seed to propose new candidate solutions. Typically in A* search, all neighbouring nodes are expanded and pushed to the priority queue, which is not feasible in our case, though. Therefore, we utilise the available gradients in order to perform a guided proposal selection. Each leaf in the abstract syntax tree T_ρ of a seed candidate solution ρ corresponds to a parameter or a variable. According to the definition of G we need to select exactly 1 leaf to be replaced with a subtree T_s of depth 1. We select leaf l ∈ T_ρ according to:

    l = x ∈ x_p ∪ x_v‖∇_x L(ρ) ‖_2

After that, all possible replacement subtrees are constructed. An AST subtree T_s of depth 1 represents a function call. We prune the number of possible functions in ℱ by ensuring type consistency. Each leaf of T_s can be a parameter or a variable. So, all possible combinations are considered. New variable leaves are initialised to a random variable with suitable type from memory, while new parameter leaves are sampled from the multivariate normal distribution 𝒩(0, 0.1). As a result, if n_f functions are type compatible with l and each function takes n_a arguments at most, then there are 2^n_a· n_f replacement subtrees, resulting in that many new candidates. All newly proposed candidates are optimised in parallel, scored by f_total and pushed to the priority queue.





§ EXPERIMENTAL RESULTS

The π-machine is implemented in Clojure, which is a LISP dialect supporting powerful data structures and homoiconic syntax. All experiments are run on an Intel Core i7-4790 processor with 32GB RAM and use the following list of functions, ℱ: vector addition, subtraction and scaling.





  
Physical systems.

Firstly, we apply the π-machine to model learning for physical systems. The transition dynamics of a second order dynamical system is written as 𝐱̈(t)  = k_1 𝐱(t) + k_2 𝐱̇(t), where 𝐱(t) is the state of the system at time t and k_1, k_2 are system coefficients. We have recreated an experiment described in <cit.>, where the authors show the learning of physical laws associated with classical mechanical systems including the simple pendulum and linear oscillator. A diagram of these two systems is shown in Figure <ref> (left). We set 𝒜 = {accel(θ)} where θ∈ℝ for both experiments. The observation trace for each system is generated by simulating the dynamics for 1s at 100Hz. We specify the action error function as σ_act = ‖θ̂ - θ‖_2 and set σ_len = 0. In both experiments 𝐱∈ℝ and 𝐯 = ẋ∈ℝ represent linear position and velocity.

The three best solutions found by the π-machine for each system are shown in Figure <ref> (middle). The best solution for each system correctly represents the underlying laws of motion. The program describing the behaviour of the pendulum was induced in 18 iterations, while the linear oscillator program needed 146 iterations. The total number of possible programs with AST depth of 2, given the described experimental setup, is approximately 1.7 × 10^4. The average duration of an entire iteration (propose new programs, optimise and evaluate) was 0.6s. <cit.> achieve similar execution times, but distributed over 8 quad core computers (32 cores in total). The experimental results demonstrate that the π-machine can efficiently induce programs representing fundamental laws of physics.




  
Deep Q-network.

This experiment is based on our view that the core deep neural network based policy learner and the explanation layer play complementary roles. There are numerous advantages to performing end-to-end policy learning, such as DQN-learning from raw video, however, there is also a need to explain the behaviour of the learnt policy with respect to user-defined properties of interest. We consider explaining the behaviour of a DQN agent playing the ATARI Pong game and are interested in the question: how does the network control the position of the paddle in order to hit the ball when it is in the right side of the screen. A diagram of the experimental setup is shown in figure <ref> (left). The behaviour of the DQN is observed during a single game. Since the environment is deterministic, the state transition function, which generates the observation trace for this experiment, is the policy π(s) that the DQN has learnt. We would like to explain the behaviour of the DQN in terms of the position of the opponent, the ball and the DQN agent (so, not just in terms of RAM memory values, for instance). Therefore, the observation trace contains those positions which are extracted from each frame by a predefined detector. We set 𝒜 = {move(θ)} where θ∈ℝ and represent the discrete actions of the network , ,  as move(1), move(-1), move(0) respectively. We specify the action error function as σ_act = ‖θ̂ - θ‖_2 and set σ_len = 0.

The best 3 programs found by the π-machine are shown in Figure <ref> (middle), where it took 38 iterations for the best one (average iteration duration 3.2s). By inspecting the second solution it becomes clear that the neural network behaviour can be explained as a proportional controller minimising the vertical distance between the agent and the ball. However, the best solution reveals even more structure in the behaviour of the DQN. The coefficient in front of the agent position is slightly larger than the one in front of the ball position which results in a small amount of damping in the motion of the paddle. Thus, it is evident that the DQN not only learns the value of each game state, but also the underlying dynamics of controlling the paddle. Furthermore, we have tested the performance of an agent following a greedy policy defined by the induced program. In our experiments over 100 games this agent achieved a score of 11.1 (± 0.17). This is not quite the score of 18.9 (± 1.3) obtained by an optimised DQN, but it is better than human performance 9.3 <cit.>. This difference of course emanates from the predefined detector not capturing all aspects of what the perceptual layers in DQN have learnt, so improved detector choices should yield interpretable programs that also attain performance closer to the higher score of the black-box policy.



§ DISCUSSION

The π-machine can be viewed as a framework for automatic network architecture design <cit.>, as different models can be expressed as concise LISP-like programs. Deep learning methods for limiting the search space of possible programs, which poses the greatest challenge, have been proposed <cit.>, but how they can be applied to more generic frameworks such as the π-machine is an open question. The specification of variable detectors not only addresses this issue, but enables the user to make targeted and well grounded queries about the observed data trace. Such detectors can also be learnt from raw data in an unsupervised fashion <cit.>.



§ CONCLUSION

In conclusion, we propose a novel architecture, the π-machine, for inducing LISP-like functional programs from observed data traces by utilising backpropagation, stochastic gradient descent and A* search. The experimental results demonstrate that the π-machine can efficiently induce interpretable programs from short data traces.











icml2017

