Building Production-Grade spaCy Text Classification Pipelines for Business Data

Karthik Shiraly
January 29, 2023

spacy ecosystem for text classification pipelines
Source: spaCy

SpaCy describes itself as industrial-strength natural language processing (NLP). But what makes it better than other Python frameworks like the natural language toolkit (NLTK), scikit-learn, TensorFlow, or PyTorch? Unfortunately, many of its unique capabilities are under the hood and easy to miss. Its documentation prefers technical details and is rather modest about marketing its big-picture benefits.

In this article, we dive into spaCy's unique but hidden benefits. We’ll illustrate them by using spaCy text classification for some interesting use cases.

A Quick Demo of spaCy

In our article NLP with spaCy, we explored spaCy's features and common use cases like sentiment analysis in detail. So here, we'll just do a quick demo of spaCy for you to get some hands-on familiarity with it.

1. Load a pre-trained pipeline:

Import spaCy and load the pre-trained transformer model
Import spaCy and load the pre-trained transformer model

2. Apply the pipeline to your text:

doc model example

3. Examine universal and language-specific part-of-speech tags:

part of speech tagging

4. Get named entities:

extract named entities from text

5. Visualize named entities:

Visualize named entites with spaCy

6. Examine token embeddings:

Token embeddings

Notice that with just one call on the pipeline, we got out so much useful information — tokens, part-of-speech tags, parse tree, word roots, named entities, word embeddings, spans, noun phrases, and more. Plus, you can apply algorithms like vector norms and cosine similarities to get basic document search features in your application.

9 Compelling Reasons to Use spaCy for All Text Processing Workflows in Your Business

The demo above is probably the extent to which most developers know and use spaCy. But it has a lot more to offer than you’d think. In the next few sections, we'll explore spaCy's unique advantages and underlying technical designs.

1. Development-Friendly Focus on Text Processing

spaCy pipeline
Source: spaCy

SpaCy's top-level application programming interface (API) is already exceptionally developer-friendly. Just call "nlp('your text data')" and you're done. It automatically tokenizes, adds part-of-speech annotations, finds named entities, guesses text categories, and more. If you need to customize a few steps, that's simple too.

But sometimes, that may not be enough for real-world requirements. Your data may need special tokenization. Or your language may not be supported by spaCy. Or you may want to use a domain-specific pre-trained model.

In such situations, developers tend to string together multiple frameworks using simplistic glue code. They may still use spaCy just to get the tokens. Then they pass those tokens through a PyTorch model to get high-quality embeddings. Next, they pass those embeddings through a sklearn random forest for text classification. And perhaps apply some custom rules at the end to handle any edge cases.

However, such glued pipelines break often and need constant code changes to keep up with new requirements. Plus, the simplistic glue code often becomes an information bottleneck that fails to pass on important knowledge from one stage to the next. Not every application developer will know concepts like forward and backward propagation, and even if they do, designing knowledge flow between components is non-trivial.

SpaCy solves all this elegantly. Instead of treating a pipeline as a mere idea, spAcy provides concrete APIs to construct pipelines and insert custom components, including machine learning models or rule-based models. SpaCy also has built-in support for the forward and backward flow of knowledge through all the components of a pipeline. SpaCy thus gives a solid scaffolding for any real-world text processing scenario while avoiding brittle glue code.

2. 75+ Pre-Trained Pipelines for 24 Languages

language options for spacy operations

At the time of writing this in January 2023, spaCy fully supports 24 languages and another 48 partially. Full support for a language means it typically has at least three pre-trained pipelines, ranging from an efficient small model to a more accurate large model. A pre-trained spaCy model comes with built-in support for common tasks like tokenization, tagging, parsing, lemmatization, and named entity recognition. Partial support means just basic tokenization features that work for most text.

Some major languages also have transformer-based pre-trained pipelines that improve accuracy further.

3. Custom Pipelines and Components

SpaCy allows you to create custom components and plug them into any spaCy pipeline. This is how specialized libraries like scispacy work. You can also create an entire custom pipeline implementation if your design requires special dependencies between different components.

For example, you can seamlessly combine machine learning components with rule-based post-processing components to handle real-life edge cases.

4. Built-In Support for the Latest Transformer Models

SpaCy abstracts its token-to-embedding conversion through the Tok2Vec, or token-to-vector, interface. Any implementation with this interface can be plugged into any spaCy pipeline. The default implementation is a convolutional model, HashEmbedCNN, that defaults to 96-dimensional embeddings but can go up to 300 dimensions.

By default, spaCy shares a single Tok2Vec embedding model (and its weights) with multiple components. It generates embeddings for them whenever they ask and receives gradient updates (via Tok2VecListener) from them during fine-tuning. This design is depicted below.

Shared embedding model for multi-task learning
Shared embedding model for multi-task learning (Source: spaCy

But you can also configure every component to have its own independent Tok2Vec embedding layer as shown below.

pipeline options
Source: spaCy

Whether it's shared or multiple, the Tok2Vec abstraction allows you to easily swap out the default convolutional model with any other embedding model, including highly capable transformer models like BERT, RoBERTa, BART, and similar.

Transformer in the pipeline (Source: spaCy)

Due to their inherent capabilities, transformer-based embedding models can produce higher accuracy compared to default models with embedding dimensions as high as 768, 1024, or more. Their high learning capacity means that in the shared layer mode, the same transformer model can get updates from all the components and achieve accurate multi-task learning.

SpaCy supports any pre-trained transformer model from the HuggingFace repository or the PyTorch hub.

5. Integrates With PyTorch and TensorFlow

SpaCy's deep learning capabilities come from its use of a standalone deep learning library called thinc (pronounced "think"). Not only does this library have its own data structures and logic for standalone deep learning, but it also provides the ability to wrap and reuse models and layers from other frameworks like PyTorch and TensorFlow. This way, spaCy's able to integrate absolutely any PyTorch, TensorFlow, or MXNet model or layer out there, including all the latest state-of-the-art models.

6. Trainable Components

SpaCy's architecture is unique because it has multiple planes of abstraction. On one plane, you can see it as just another natural language toolkit without ever knowing about any of its deep learning capabilities.

But underneath that, it's also a full-fledged, end-to-end deep learning framework similar to PyTorch or TensorFlow.

SpaCy manages to do this without compromising on its pipeline abstraction. Essentially, every component in the pipeline is trainable and uses deep neural networks under the hood. Through a clever design involving listeners, it allows gradient updates to backpropagate through all the components during fine-tuning and achieves end-to-end multi-task learning.

For some reason, if you don't want end-to-end learning or want to keep one intermediate component out, it supports independent model learning too. We've explained these design details in the transformers section above.

7. Scalable Training

Like PyTorch and TensorFlow, spaCy's deep learning library, thinc, uses Cython components under the hood for speed and efficiency on a single machine. Simultaneously, spaCy also supports parallel and distributed model training on multiple machines. You can use the same training code transparently for both local and distributed training, and keep all aspects of distributed testing outside your code in a config file.

Its ability to transparently switch to distributed training for large models makes spaCy unique compared to other frameworks like NLTK and scikit-learn.

8. Production-Grade Efficiency

Its use of Cython data structures and operations enables spaCy to run efficiently, use less memory, exploit multicore capabilities of CPUs, and even run on GPUs.

9. Flexibility Through Configurability

spaCy options

SpaCy comes with a powerful declarative configuration system that allows you to build custom pipelines that can be finely configured at every level, from the bottom-most helper to the top-level pipeline components.

This enables applications to keep pipeline setups outside their code and swap pipelines on demand by simply loading a different configuration file without any code modification. You can easily switch your application to a prototype, development, staging, or production machine learning model at runtime.

Text Classification Use Cases

In these sections, you'll learn in depth about two applications of text classification and their implementation using spaCy.

1. Intent Classification for Conversational Ai

What is intent classification? In applications like customer service chatbots and ticketing systems, understanding the customer's intention is critical. Are they complaining about the functioning of your product or service? Or is it a billing problem? Or do they want to upgrade or downgrade their subscription but aren't using the right words?

Intent classification understands what the customer wants and applies an accurate intention label for filing, routing, and resolving the issue properly.

For intent classification with spaCy, you'd use spaCy's text categorization component. Let's first understand its architecture and capabilities.

Text Categorization Architecture of spaCy

Text Categorization Architecture of spaCy

SpaCy's TextCategorizer, or textcat, is a trainable pipeline component for any type of single-label or multilabel text categorization task, including whole-document classification, intent classification, or sentiment analysis. You must explicitly append it to a pipeline using add_pipe because it's not included by default.

Internally, TextCategorizer can use any thinc model that accepts a list of documents and produces a matrix of class probabilities.

SpaCy's default text classification model is an ensemble of two models — a traditional bag-of-words model called TextCatBOW and a neural model with attention, called TextCatCNN. Unlike most other spaCy components, these are not pre-trained. All three are completely untrained and it's up to you to train them from scratch on your training data.

Customize Textcat Architecture

Customize spaCy textcat architecture
Customize spaCy textcat architecture

There are a couple of ways to customize this text categorization architecture. You can either keep the ensemble model and plug in a custom embedding model into its Tok2Vec attribute, or you can throw away the ensemble entirely and use a custom thinc model:

  • Use another built-in embedding model: You can use any of the other built-in embedding models, such as the BiLSTM encoder.
  • Reuse token attributes as embeddings: If a custom component in the pipeline is generating custom embeddings and storing them as token attributes, you can reuse them using the feature extractor.
  • Plug your custom embedding model: For example, use Tok2VecTransformer to use a transformer as your embedding model. The text classifier's still an ensemble of the same two models but one of them will use the transformer for the embeddings.
  • Throw away the ensemble and use a custom classifier model: You can discard spaCy's ensemble entirely and use your own classifier, as long as it has thinc's Model interface. You can use any HuggingFace transformer through the TransformerModel. Or you can wrap any other PyTorch or TensorFlow model. For example, you can use domain-specific classifiers like ClinicalBERT.

Chatbot Intent Classification Example

For this example, we'll use the banking77 intent classification dataset to train the textcat component as a banking intent classifier. The dataset contains customer queries received by a bank. They're categorized into 77 intents like card_arrival, card_linking, card_payment_wrong_exchange_rate, and so on.

Instead of writing training code, the easiest way to train a textcat or any other custom spaCy model is by using spaCy projects. It comes with a bunch of templates that we can simply customize for our data. We first clone the repository, create a copy of the textcat_demo pipeline directory, and call it textcat_intent.

1. First, we replace the data files under "assets/" with the training and test data evaluation files from our dataset and modify project.yml suitably.

Textcat intent classification

2. We modify convert.py script to read the dataset under "assets/" into DocBin files that spaCy can read efficiently while training:

docbin example for spacy

3. Then run the data converter. The files it creates are suitable for training.

spaCy project run convert

4. We train the model:

train the textcat model with spaCy

5. We evaluate the metrics:

evaluation metrics for textcat F

6. We package the trained pipeline as an installable pip package:

train the pipeline

7. We'll install this custom pipeline package:

install a custom pipeline for intent classification

8. Load it like any other pipeline:

load the intent classification model

9. And finally do a quick interference check to compare the ground truth label with the predicted label:

Inference time of intent classification with spaCy

Your custom intent classifier is now ready for production deployment on your server!

2. Span Categorization

In spaCy, a span is any contiguous slice of a document and has a start and end position. A span may align with a well-defined unit like a word, sentence, or paragraph, or it may cross multiple words, sentences, and paragraph boundaries with ad hoc start and end positions.

Span categorization examines arbitrary slices, which may even overlap with one another, and assigns labels to them. Applications of span categorization include:

  • More powerful named entity recognition than spaCy's built-in capability.
  • Identify language spans in multilingual text or transcriptions with code-switching.
  • Classify arbitrary slices with data analysis labels like humorous, sarcastic, toxic, and so on. Notice that a word may belong to multiple spans with different labels, for example as part of a humorous phrase that's also toxic.

Let's learn about spaCy's span categorization architecture next.

Span Categorization Architecture

SpaCy's SpanCategorizer, or spancat, is the pipeline component responsible for span categorization. It consists of a suggester component, typically an n-gram extractor, and a classifier model.

The classifier model can be any thinc Model that accepts a list of documents and their spans and produces a probability matrix. SpaCy's default model is called SpanCategorizer.v1. It consists of:

  • A token-to-vector embedding model to produce embeddings for the span's tokens
  • A reducer model to reduce the sequence of embeddings to one span embedding
  • A scoring algorithm that calculates precision, recall, and f1-score metrics for each span embedding

You can customize spancat too just like textcat above, either by using your own embedding model or replacing the entire "SpanCategorizer.v1" model with your custom logic.

Span Categorization Example

For span categorization, we follow a similar workflow as above but this time we'll just experiment with one of the spancat demos that ship with spaCy projects. It's called Healthsea and its objective is to analyze user reviews of health supplements to detect any health impacts. It consists of data like this:

span categorization example text

1. Like before, we start by running a preprocessing script to convert the raw data to a binary format suitable for spaCy:

train span categorization model

2. Then we train the spancat component on this data:

span categorization training and pipeline results

3. Create an installable package for the pipeline:

installable package for span categorization

4. Install it using pip, load the model, and apply it to your text:

load the span categorization model

Implement Powerful Deep Learning Easily in Your Business With spaCy Text Classification

As you saw in this article, spaCy offers elegant, and a tad opinionated, programming models for any kind of text-processing workflow. Though there's a bit of a learning curve to understanding its internals, we have found that the effort pays off in terms of accuracy, flexibility, and maintainability compared to stringing together disparate frameworks with glue code.

We have multiple years of experience in building production-grade data science, text, and natural language processing systems. Get in touch with us for expert guidance on automating text processing and data science in your business operations.