Torch-Struct: Deep Structured Prediction Library

by   Alexander M. Rush, et al.
cornell university

The literature on structured prediction for NLP describes a rich collection of distributions and algorithms over sequences, segmentations, alignments, and trees; however, these algorithms are difficult to utilize in deep learning frameworks. We introduce Torch-Struct, a library for structured prediction designed to take advantage of and integrate with vectorized, auto-differentiation based frameworks. Torch-Struct includes a broad collection of probabilistic structures accessed through a simple and flexible distribution-based API that connects to any deep learning model. The library utilizes batched, vectorized operations and exploits auto-differentiation to produce readable, fast, and testable code. Internally, we also include a number of general-purpose optimizations to provide cross-algorithm efficiency. Experiments show significant performance gains over fast baselines and case-studies demonstrate the benefits of the library. Torch-Struct is available at


page 1

page 3

page 4


Torchbearer: A Model Fitting Library for PyTorch

We introduce torchbearer, a model fitting library for pytorch aimed at r...

DLOPT: Deep Learning Optimization Library

Deep learning hyper-parameter optimization is a tough task. Finding an a...

ReservoirComputing.jl: An Efficient and Modular Library for Reservoir Computing Models

We introduce ReservoirComputing.jl, an open source Julia library for res...

PyTorch Tabular: A Framework for Deep Learning with Tabular Data

In spite of showing unreasonable effectiveness in modalities like Text a...

DeepMoD: Deep learning for Model Discovery in noisy data

We introduce DeepMoD, a deep learning based model discovery algorithm wh...

IllinoisSL: A JAVA Library for Structured Prediction

IllinoisSL is a Java library for learning structured prediction models. ...

minicons: Enabling Flexible Behavioral and Representational Analyses of Transformer Language Models

We present minicons, an open source library that provides a standard API...

Code Repositories


Fast, general, and tested differentiable structured prediction in PyTorch

view repo


DGMs for NLP. A roadmap.

view repo

1 Introduction

Structured prediction is an area of machine learning focusing on representations of spaces with combinatorial structure, and algorithms for inference and parameter estimation over these structures. Core methods include both tractable exact approaches like dynamic programming and spanning tree algorithms as well as heuristic techniques such linear programming relaxations and greedy search.

Figure 1:

Distribution of binary trees over an 1000-token sequence. Coloring shows the marginal probabilities of every span. Torch-Struct is an optimized collection of common CRF distributions used in NLP designed to integrate with deep learning frameworks.

Name Structure () Parts () Algorithm () LoC T/S Sample Reference
Linear-Chain Labeled Chain Edges Forward-Backward,
20 390k Lafferty et al. (2001)
Factorial-HMM Labeled Chains Trans.
Factorial F-B 20 25k Ghahramani and Jordan (1996)
Alignment Alignment Match
50 13k Needleman and Wunsch (1970)
Semi-Markov Seg. Labels Edges Segmental F-B 30 87k Baum and Petrie (1966)
Sarawagi and Cohen (2005)
Context-Free Labeled Tree CF Rules
Inside-Outside CKY 70 37k Kasami (1966)
Simple CKY Labeled Tree Splits 0-th order CKY 30 118k Kasami (1966)
Dependency Proj. Tree Arcs Eisner Algorithm 40 28k Eisner (2000)
Dependency (NP) Non-Proj. Tree Arcs Matrix-Tree
Chiu-Liu (MAP)
40 1.1m Koo et al. (2007)
McDonald et al. (2005)
Auto-Regressive Sequence Prefix Greedy Search,
Beam Search
60 - Tillmann and Ney (2003)
Table 1: Models and algorithms implemented in Torch-Struct. Notation is developed in Section 5. Parts are described in terms of sequence lengths , label size , segment length , and layers / grammar size . Lines of code (LoC) is from the log-partition () implementation. T/S is the tokens per second of a batched computation, computed with batch 32, (K80 GPU run on Google Colab).

Structured prediction has played a key role in the history of natural language processing. Example methods include techniques for sequence labeling and segmentation

Lafferty et al. (2001); Sarawagi and Cohen (2005), discriminative dependency and constituency parsing Finkel et al. (2008); McDonald et al. (2005)

, unsupervised learning for labeling and alignment

Vogel et al. (1996); Goldwater and Griffiths (2007), approximate translation decoding with beam search Tillmann and Ney (2003), among many others.

In recent years, research into deep structured prediction has studied how these approaches can be integrated with neural networks and pretrained models. One line of work has utilized structured prediction as the final final layer for deep models

Collobert et al. (2011); Durrett and Klein (2015). Another has incorporated structured prediction within deep learning models, exploring novel models for latent-structure learning, unsupervised learning, or model control Johnson et al. (2016); Yogatama et al. (2016); Wiseman et al. (2018). We aspire to make both of these use-cases as easy to use as standard neural networks.

The practical challenge of employing structured prediction is that many required algorithms are difficult to implement efficiently and correctly. Most projects reimplement custom versions of standard algorithms or focus particularly on a single well-defined model class. This research style makes it difficult to combine and try out new approaches, a problem that has compounded with the complexity of research in deep structured prediction.

With this challenge in mind, we introduce Torch-Struct with three specific contributions:

  • Modularity: models are represented as distributions with a standard flexible API integrated into a deep learning framework.

  • Completeness: a broad array of classical algorithms are implemented and new models can easily be added in Python.

  • Efficiency: implementations target computational/memory efficiency for GPUs and the backend includes extensions for optimization.

In this system description, we first motivate the approach taken by the library, then present a technical description of the methods used, and finally present several example use cases.

2 Related Work

Several software libraries target structured prediction. Optimization tools, such as SVM-struct Joachims (2008), focus on parameter estimation. Model libraries, such as CRFSuite Okazaki (2007) or CRF++ Kudo (2005), implement inference for a fixed set of popular models, such as linear-chain CRFs. General-purpose inference libraries, such as PyStruct Müller and Behnke (2014) or TurboParser Martins et al. (2010), utilize external solvers for (primarily MAP) inference such as integer linear programming solvers and ADMM. Probabilistic programming languages, for example languages that integrate with deep learning such as Pyro Bingham et al. (2019), allow for specification and inference over some discrete domains. Most ambitiously, inference libraries such as Dyna Eisner et al. (2004) allow for declarative specifications of dynamic programming algorithms to support inference for generic algorithms. Torch-Struct takes a different approach and integrates a library of optimized structured distributions into a vectorized deep learning system. We begin by motivating this approach with a case study.

3 Motivating Case Study

While structured prediction is traditionally presented at the output layer, recent applications have deployed structured models broadly within neural networks (Johnson et al., 2016; Kim et al., 2017; Yogatama et al., 2016, inter alia). Torch-Struct aims to encourage this general use case.

To illustrate, we consider a latent tree model. ListOps Nangia and Bowman (2018) is a dataset of mathematical functions. Each data point consists of a prefix expression and its result , e.g.

Models such as a flat RNN will fail to capture the hierarchical structure of this task. However, if a model can induce an explicit latent , the parse tree of the expression, then the task is easy to learn by a tree-RNN model Yogatama et al. (2016); Havrylov et al. (2019).

A popular approach is a latent-tree RL model which we briefly summarize. The objective is to maximize the probability of the correct prediction under the expectation of a prior tree model, ,

Computing the expectation is intractable so policy gradient is used. First a tree is sampled , then the gradient with respect to is approximated as,


is a variance reduction baseline. A common choice is the self-critical baseline

Rennie et al. (2017),

Finally an entropy regularization term is added to the objective encourage exploration of different trees, .

Even in this brief overview, we can see how complex a latent structured learning problem can be. To compute these terms, we need 5 different properties of the tree model :



Policy gradient,


Score policy samples,






Objective regularizer,

For structured models, each of these terms is non-trivial to compute. A goal of Torch-Struct is to make it seamless to deploy structured models for these complex settings. To demonstrate this, Torch-Struct includes an implementation of this latent-tree approach. With a minimal amount of user code, the implementation achieves near perfect accuracy on the ListOps dataset.

4 Library Design

The library design of Torch-Struct follows the distributions API used by both TensorFlow and PyTorch 

Dillon et al. (2017). For each structured model in the library, we define a conditional random field (CRF) distribution object. From a user’s standpoint, this object provides all necessary distributional properties. Given log-potentials (scores) output from a deep network , the user can request samples , probabilities , modes , or other distributional properties such as

. The library is agnostic to how these are utilized, and when possible, they allow for backpropagation to update the input network. The same distributional object can be used for standard output prediction as for more complex operations like attention or reinforcement learning.

Figure 2: Latent Tree CRF example. (a) Log-potentials for each part/span. (b) Marginals for computed by backpropagation. (c) Mode tree . (d) Sampled tree .

Figure 2 demonstrates this API for a binary tree CRF over an ordered sequence, such as from the previous section. The distribution takes in log-potentials which score each possible span in the input. The distribution converts these to probabilities of a specific tree. This distribution can be queried for predicting over the set of trees, sampling a tree for model structure, or even computing entropy over all trees.

Table 1 shows all of the structures and distributions implemented in Torch-Struct. While each is internally implemented using different specialized algorithms and optimizations, from the user’s perspective they all utilize the same external distributional API, and pass a generic set of distributional tests.111The test suite for each distribution enumerates over all structures to ensure that properties hold. While this is intractable for large spaces, it can be done for small sets and was extremely useful for development. This approach hides the internal complexity of the inference procedure, while giving the user full access to the model.

5 Technical Approach

5.1 Conditional Random Fields

We now describe the technical approach underlying the library. To establish notation first consider the implementation of a categorical distribution, Cat(), with one-hot categories with from a set and probabilities given by the softmax,

Define the log-partition as , i.e. log of the denominator, where is the log-sum-exp operator. Computing probabilities or sampling from this distribution, requires enumerating to compute the log-partition . A useful identity is that derivatives of yield category probabilities,

Other distributional properties can be similarly extracted from variants of the log-partition. For instance, define then222This is a subgradient identity, but we observe that libraries like PyTorch will default to this value.: .

Conditional random fields, CRF(), extend the softmax to combinatorial spaces where is exponentially sized. Each , is now represented as a binary vector over polynomial-sized set of parts, , i.e. . Similarly log-potentials are now defined over parts . For instance, in Figure 2 each span is a part and the vector is shown in the top-left figure. Define the probability of a structure as,

Computing probabilities or sampling from this distribution, requires computing the log-partition term . In general computing this term is now intractable, however for many core algorithms in NLP there are exist efficient combinatorial algorithms for this term (as enumerated in Table 1).

Derivatives of the log-partition again provide distributional properties. For instance, the marginal probabilities of parts are given by,

Similarly derivatives of correspond to whether a part appears in the argmax structure. .

While these gradient identities are well-known Eisner (2016), they are not commonly deployed. Computing CRF properties is typically done through two-step specialized algorithms, such as forward-backward, inside-outside, or similar variants such as viterbi-backpointers Jurafsky and Martin (2014). In our experiments, we found that using these identities with auto-differentiation on GPU was often faster, and much simpler, than custom two-pass approaches. Torch-Struct is thus designed around using gradients for distributional computations.

5.2 Dynamic Programming and Semirings

Name Ops () Backprop Gradients
K-Max K-Argmax
K-Sample K-Samples
Entropy ( ) See Li and Eisner (2009)
Exp. See Li and Eisner (2009)
Sparsemax See Mensch and Blondel (2018)
Table 2: (Top) Semirings implemented in Torch-Struct. Backprop/Gradients gives overridden backpropagation computation and value computed by this combination. (Bot) Example of gradients from different semirings on sequence alignment with dynamic time warping.

Torch-Struct is a collection of generic algorithms for CRF inference. Each CRF distribution object, , is constructed by providing where the parts are specific to the type of distribution. Internally, each distribution is implemented through a single Python function for computing the log-partition function . From this function, the library uses auto-differentiation and the identities from the previous section, to define a complete distribution object. The core models implemented by the library are shown in Table 1.

Figure 3: Speed impact of optimizations. Time is given in seconds for 10 runs with batch 16 executed on Google Colab. (a) Speed of a linear-chain forward with 20 classes for lengths up to 500. Compares left-to-right ordering to parallel scan. (b) Speed of CKY inside with lengths up to 80. Compares inner loop versus vectorization. (c) Speed of linear-chain forward of length 20 with up to 100 classes. Compares broadcast-reduction versus CUDA semiring kernel. (Baseline memory is exhausted after 100 classes.)

To make the approach concrete, we consider the example of a linear-chain CRF.

The model has labels per node with a length

edges utilizing a first-order linear-chain (Markov) model. This model has

parts corresponding to edges in the chain, and thus requires . The log-partition function factors into two reduce computations,

Computing this function left-to-right using dynamic programming yield the standard forward algorithm for sequence models. As we have seen, the gradient with respect to produces marginals for each part, i.e. the probability of a specific labeled edge.

We can further extend the same function to support generic semiring dynamic programming Goodman (1999). A semiring is defined by a pair with commutative , distribution, and appropriate identities. The log-partition utilizes , but we can substitute alternatives.

For instance, utilizing the log-max semiring in the forward algorithm yields the max score. As we have seen, its gradient with respect to is the argmax sequence, negating the need for a separate argmax (Viterbi) algorithm. Some distributional properties cannot be computed directly through gradient identities but still use a forward-backward style compute structure. For instance, sampling requires first computing the log-partition term and then sampling each part, (forward filtering / backward sampling). We can compute this value by overriding each backpropagation operation for the to instead compute a sample.

Table 2 shows the set of semirings and backpropagation steps for computing different terms of interest. We note that many of the terms necessary in the case-study can be computed with variant semirings, negating the need for specialized algorithms.

6 Optimizations

Torch-Struct aims for computational and memory efficiency. Implemented naively, dynamic programming algorithms in Python are prohibitively slow. As such Torch-Struct provides key primitives to help batch and vectorize these algorithms to take advantage of GPU computation and to minimize the overhead of backpropagating through chart-based dynamic programmming. Figure 3 shows the impact of these optimizations on the core algorithms.

a) Parallel Scan Inference

The commutative properties of semiring algorithms allow flexibility in the order in which we compute . Typical implementations of dynamic programming algorithms are serial in the length of the sequence. On parallel hardware, an appealing approach is a parallel scan ordering Särkkä and García-Fernández (2019), typically used for computing prefix sums. To compute,

in this manner we first pad the sequence length

out to the nearest power of two, and then compute a balanced parallel tree over the parts, shown in Figure 4. Concretely each node layer would compute a semiring matrix multiplication, e.g. . Under this approach, we only need steps in Python and can use parallel GPU operations for the rest. Similar parallel approach can also be used for computing sequence alignment and semi-Markov models.

b) Vectorized Parsing

Computational complexity is even more of an issue for parsing algorithms, which cannot be as easily parallelized. The log-partition for parsing is computed with the Inside algorithm. This algorithm must compute each width from 1 through T in serial; however it is important to parallelize each inner step. Assuming we have computed all inside spans of width less than , computing the inside span of width requires computing for all ,

In order to vectorize this loop over , we reindex the chart. Instead of using a single chart , we split it into two parts: one right-facing and one left facing, . After this reindexing, the update can be written.

Unlike the original, this formula can easily be computed as a vectorized semiring dot product. This allows use to compute in one operation. Variants of this same approach can be used for all the parsing models employed.

c) Semiring Matrix Operations

The two previous optimizations reduce most of the cost to semiring matrix multiplication. In the specific case of the semiring these can be computed very efficiently using matrix multiplication, which is highly-tuned on GPU hardware. Unfortunately for other semirings, such as log and max, these operations are either slow or very memory inefficient. For instance, for matrices and of sized and , we can broadcast with

to a tensor of size

and then reduce dim by at a huge memory cost. To avoid this issue, we implement custom CUDA kernels targeting fast and memory efficient tensor operations. For log, this corresponds to computing,

where . To optimize this operation on GPU we utilize the TVM language Chen et al. (2018) to layout the CUDA loops and tune it to hardware.

Figure 4: Parallel scan implementation of the linear-chain CRF inference algorithm. Here represents a semiring matrix operation and is padding.

7 Conclusion and Future Work

We present Torch-Struct, a library for deep structured prediction. The library achieves modularity through its adoption of a generic distributional API, completeness by utilizing CRFs and semirings to make it easy to add new algorithms, and efficiency through core optimizations to vectorize important dynamic programming steps. In addition to the problems discussed so far, Torch-Struct also includes several other example implementations including supervised dependency parsing with BERT, unsupervised tagging, structured attention, and connectionist temporal classification (CTC) for speech. The full library is available at

In the future, we hope to support research and production applications employing structured models. We also believe the library provides a strong foundation for building generic tools for interpretablity, control, and visualization through its probabilistic API. Finally, we hope to explore further optimizations to make core algorithms competitive with highly-optimized neural network components.


We thank Yoon Kim, Xiang Lisa Li, Sebastian Gehrmann, Yuntian Deng, and Justin Chiu for discussion and feedback on the project. The project was supported by NSF CAREER 1845664, NSF 1901030, and research awards by Sony and AWS.