Getting started with giotto-tda. A Python library for topological... | by Lewis Tunstall | Towards Data Science

Written by Lewis Tunstall, Colin Kälin, Francesco Palma, and Thomas Boys
At L2F, one of the most common questions we get around giotto-tda and topological machine learning is “Where do I start?”.
In this guide we present an overview of the basic concepts and workflow so that you can start using giotto-tda in your machine learning pipelines. The code to reproduce the analysis is available on GitHub.
Topological machine learning refers to a set of techniques that combine elements from algebraic topology with statistical learning. By focusing on global properties of data such as shape and connectivity, these topological methods can capture patterns that may be missed by conventional machine learning approaches.
For example, topological machine learning has produced state-of-the-art results in drug design and graph classification, and led to novel insights in protein binding.
The main ingredient underlying these techniques is known as persistent homology. Persistent homology measures the presence of topological invariants like connected components, holes, and voids across varying length scales. The “birth” and “death” of these invariants is summarised via a persistence diagram, which is the most common and intuitive way to generate new types of features to feed to downstream machine learning tasks. For an excellent overview of these concepts, see Gary Koplik’s article or Matthew Wright’s video.
To summarise, the key steps in topological machine learning are:
Extract topological features from the input data using persistent homology.
Combine these features with machine learning methods, using either supervised or unsupervised approaches.
The giotto-tda library is designed to simplify these steps and make topological machine learning accessible to the wider data science community. It is based on the fit-transform paradigm of scikit-learn and provides tight integration with the popular framework. Getting started with giotto-tda is as simple as running:
pip install giotto-tda
To show giotto-tda in action, we will use the CHAMPS dataset from the Predicting Molecular Properties competition on Kaggle. Here the task is to predict the magnetic interaction or “scalar coupling constant” between two atoms in a molecule. Since these couplings take continuous values, the learning task is a regression one.
The training data consists of atom-pairs in molecules, with each pair characterised by the type of scalar coupling and the (x,y,z) coordinates of each atom. To simplify the analysis, we’ll focus on the 100 largest molecules, i.e. those with the largest number of atoms. As shown in the figure below, these molecules have five different couplings, whose strength varies depending on the type of coupling.
The first step in our topological machine learning pipeline is to construct persistence diagrams from the training data.
In giotto-tda, there are two main ways to achieve this:
Represent the data as a point cloud: treat each observation as a point in space, along with a metric to calculate distances between pairs of observations. In our context, the point cloud for a single molecule could simply be the (x, y, z) coordinates of each atom relative to the mean value (x̅, y̅, z̅) of all the atoms. In the code snippet below, homology_dimensions specifies the type of topological invariants to track (“0” for connected components, “1” for holes, and “2” for voids), while euclidean defines the metric we wish to apply in the persistent homology calculation.
Represent the data as a distance matrix: calculate the pairwise distances between each observation, where “distance” does not necessarily have to be a metric. If we treat a single molecule as a graph, the distance between two atoms could be the number of edges along a shortest path connecting them. In the code snippet below, we simply need to specify that our metric is precomputed and ensure the input is a distance matrix.
For each input point cloud or distance matrix, we get a single persistence diagram. In the training data, each observation is an atom-pair, so when these pairs are grouped to form the 100 molecules, we obtain 100 point clouds and thus 100 persistence diagrams.
Points in the persistence diagram which are furthest away from the diagonal death = birth line correspond to the most persistent topological features.
Although persistence diagrams are useful descriptors of the data, they cannot be used directly for machine learning applications. This is because different persistence diagrams may have different numbers of points, and basic operations like the addition and multiplication of diagrams are not well-defined.
To overcome these limitations, a variety of proposals have been made to “vectorise” persistence diagrams via embeddings or kernels which are well-suited for machine learning. In giotto-tda, we provide access to the most common vectorisations via the gtda.diagrams module.
For example, calculating the “amplitude” of a persistence diagram can be achieved by selecting a metric as shown in the following code snippet.
Alternatively, you can create custom topological features of your own! Since persistence diagrams in giotto-tda are arrays of birth-death-dimension triples, it is straightforward to manipulate them with NumPy or Pandas. For example, the code snippet below shows how we can calculate the average lifetime of the points per homology_dimension.
In our full analysis of the CHAMPS dataset we extracted a wide variety of topological features — see the accompanying code for details.
With topological features at hand, the next step is to train a regressor. In the scikit-learn conventions, this amounts to combining all relevant features and the target variable into arrays X and y. For this guide, we adopt the approach taken in this Kaggle submission and use an XGBoostRegressor to make predictions. In order to evaluate the influence of the features on performance, we compare the results of a model trained with 5-fold cross-validation, both with and without topological features. The code snippet for this step is standard and reproduced below.
The final step is to score the predictions from our models. The metric for the competition is the mean of the logarithm of the mean absolute error (yes, it’s a bit complicated — just think of it as multiple scores, one for each bond type. For each type calculate the mean absolute error, take the log of these results and in the end calculate the mean over all bond types):
Here:
T is the number of scalar coupling types (in our case five)
nj is the number of observations of type j
yi is the scalar coupling constant for the observation
ŷi is the predicted scalar coupling constant
Due to the logarithm we can get negative values, and thus a score of say -0.5 is better than a score of -0.3.
The figure below shows the scores per coupling type and compares the model that includes topological features against those without.
We can clearly see that the topological features help improve the score by up to 5.5%, and by 3.6% on average. In a Kaggle competition, these small improvements can make a big difference in the final leaderboard and provide a nice demonstration of how topology can provide complementary information to conventional feature extraction methods.
This guide only scratches the surface of what is possible with giotto-tda. In addition to core machine learning tasks like our regression example, the library currently supports the application of persistent homology to graph and time series data.
For example, giotto-tda has been used to detect stock market crashes, study the population dynamics of beetle populations, or predict whether a molecule inhibits the spreading of HIV.
If you have questions on how to use giotto-tda, feel free to reach out to us on Slack.
If you would like to learn more about topological machine learning, please consult the links below.
Update 23/01/2020: The giotto-learn library has been renamed to giotto-tda! While the new name is meant to better convey the library's focus on topological machine learning, the commitment to seamless integration with scikit-learn will remain just as strong and a defining feature of the project.
An introduction to topological data analysis: fundamental and practical aspects for data scientists
Persistent-homology-based machine learning and its applications — a survey