Advanced visualization techniques for time series analysis | by Michaël HOARAU | Towards Data Science

Markov transition fields (MTF) is a visualization technique to highlight behavior of time series. This blog post dives into how we build and interpret these fields. We will then further build on top of Markov transition fields by exploring network graphs interpretation. Feel free to follow along by browsing to GitHub to grab this companion Jupyter notebook.
In the GitHub repository mentioned above, you will also find 7 signals captured on industrial equipment. Each signal contains one year of data with a one-hour sampling rate and they sports different behavior that we are going to try to characterize. Let’s plot the first one:
The pyts package includes some time series imaging capabilities out of the box, including the MTF: passed through this transformation, the previous signal can be represented by the following matrix:
Let’s now decompose the process that leads to this visual representation. In the following sections, we are going to decompose the way a Markov transition fields is built to better understand its properties and how it can be used to build our understanding of time series behavior:
Discretize the timeseries along the different values it can takeBuild the Markov transition matrixCompute transition probabilitiesCompute the Markov transition fieldCompute an aggregated MTFExtracting meaningful metricsMapping transition probabilities back to the initial signals
Discretize the timeseries along the different values it can take
Build the Markov transition matrix
Compute transition probabilities
Compute the Markov transition field
Compute an aggregated MTF
Extracting meaningful metrics
Mapping transition probabilities back to the initial signals
We use once again the pyts package (abstracted by the tsia package built by yours truly) to discretize our signal:
X_binned, bin_edges = tsia.markov.discretize(tag_df)
After this, each value x[i] of the timeseries is associated to one of the bin (quantile) we just computed. The first and the last bin edges respectively correspond to the lowest and highest value taken by the signal. The intermediate bin edges are computed by the discretizer. For the signal loaded earlier, this quantization process bins the different values taken by this signal in the following bins:
| Bin | Start  |   End   ||  0  | < 82.4 |    82.4 ||  1  |   82.4 |   118.4 ||  2  |  118.4 |   137.4 ||  3  |  137.4 |   156.8 ||  4  |  156.8 |   166.4 ||  5  |  166.4 |   175.2 ||  6  |  175.2 |   183.9 ||  7  |  183.9 |   196.5 ||  8  |  196.5 |   255.3 ||  9  |  255.3 | > 255.3 |
Let’s plot these bins over the time series to visualize how the values are discretized:
Once our signal is quantized, we can build a Markov transition matrix:
How to read the Markov transition matrix? Let’s have a look at the first row: | 465 | 86 | 1 | 0 | 0 | 0 | 0 | 0 |:
The first cell tells us that 465 points that are in the bin 0 (with values between 82.4 and 118.4) are followed by a value that stays in this very bin.
The second cell tells us that 86 points that are in bin 0 transition to the next bin (with a value between 118.4 and 137.4)
... and so on...
The eighth cell tells us that no point from bin 0 transition to the last bin
Let’s now have a look at the second row: | 80 | 405 | 63 | 2 | 0 | 2 | 0 | 0 |: the first cell tells us that 80 points that are in bin 1 (with a value between 118.4 and 137.4) are followed by a value that is in bin 0 (between 82.4 and 118.4).
Last but not least, the diagonal captures the frequency at which a quantile transitions to itself (self-transition frequency).
We will now normalize each bin. This matrix contains now the transition probability on the magnitude axis:
The first column correspond to the probabilities that a given value (part of a given bin) transitions to bin 0. The second column are probabilities that a given value transitions to bin 1, etc. For instance, if a given value X[i] is equal to 130.0, it is between 118.42 and 137.42 and it's binned in bin 1. Given the matrix above, there is:
A 14.5% chance that the next value will be between 82.43 and 118.42 (bin 0)
A 73.4% chance to stay within the same range (between 118.42 and 137.42, bin 1)
A 11.4% chance that the next value will be between 137.42 and 156.78 (bin 2)
... and so on...
The idea of the transition field is to represent the Markov transition probabilities sequentially to preserve the information in the time domain. The MTF generation process aligns each probability along the temporal order to build the MTF for the whole signal:
How to read the Markov transition field? MTF[i,j] denotes the transition probability from the quantile q[i] to the quantile q[j]. Let's have a look at a couple values in the second row of this field:
array([68.8, 68.8, 68.8, 68.8, 68.8, 68.8, 10.7, 10.7, 10.7, 10.7])
Let’s have a look at M[1,2]:
We look in which bin falls the signal at timestep x[1]: this is X_binned[1] = 2
We also look in which bin falls the signal at timestep x[2]: this is X_binned[2] = 2
We then look up into the Markov transition matrix to get the probability that a value from bin 2 stays into bin 2
This value is 68.8%, hence M[1,2] = 68.8%
What does this mean? Well, the transition that occurs between timestep x[1] and timestamp x[2] has an 68.8% chance from happening when looking at the whole signal.
Let’s now have a look at M[1,6]:
We look in which bin falls the signal at timestep x[1]: this is X_binned[1] = 2
We also look in which bin falls the signal at timestep x[10]: this is X_binned[6] = 1
We then look up into the Markov transition matrix to get the probability that a value from bin 2 transitions into bin 1
This value is 10.7%, hence M[1,6] = 10.7%
The transition that happens between timestep x[1] and x[6] has a 10.7% chance of happening when looking at the whole signal.
Let’s now plot the transition field we just computed:
To make the image size manageable and computation more efficient (the above MTF is a matrix of dimension 4116 x 4116), we reduce the MTF size by averaging the pixels in each non-overlapping m x m patch with the blurring kernel 1/m2. m is the image size and we set it, arbitrarily, to 48. That is, we aggregate the transition probabilities in each subsequence of length m = 48 together. Let's compute an aggregated MTF accordingly: if the signal length can be divided by the chosen image size (48), which is the case here, we can just compute the aggregate MTF with this simple function:
Otherwise, we need to compute a piecewise aggregate approximation, but don’t worry, this is fully implemented and taken care for you in the pyts package! The image obtained is exactly the same than the one shown at the top of this article:
The diagonal of the MTF contains probabilities for the self-transitions:
Self-transition probabilities are probabilities to move from a quantile to the same one on the next timestep).
We can extract the characteristic of this distribution (mean and standard deviation).
The other diagonals of the MTF are harder to interpret but can still be plotted.
One way we can map back these probabilities on the original signal, is to take the transition probabilities shown on the diagonal of the MTF:
Let’s have a look at a coarse MTF (image_size=8 will make it quite coarse) to better understand what we can extract from this Markov field:
What is the interpretation we can give to this plot?
In average, the average transition probability of the first section (in yellow) is around 19%: this means that the transitions that we see in this section do not happen very often (19% of the time) when we look at the whole signal.
In contrast, the section in dark blue (the sixth one), have transitions that happen more often in this signal (around 50% of the time)
The blue section is closer to the normal behavior of this signal whereas the yellow section is diverging more from it.
Before moving to the next section, have a look at the notebook, if you’d like to check how the behavior of very different signals can be mapped to different MTF plots and metrics!
From the MTF, we can generate a graph G = (V, E): we have a direct mapping between vertex V and the time index i. From there, there is two possible encoding of interest:
Flow encoding: this representation help us observe where do the big information flow occurs. We map the flow of time to the vertex, using a color gradient from T0 to TN to color each node of the network graph and we use the MTF weight to color the edges between vertices
Modularity encoding: modularity is an important pattern in network analysis to identify specific local structures. We map the module label (which community ID) to each vertex with a specific color attached to each community, the size of the vertices to a clustering coefficient and the edge color to the module label of the target vertex
In the following sections, we are going to decompose the way a network graph is built to better understand its properties and how it can be used to build our understanding of time series behavior:
Build the signal MTF and extract a network graph from itCompute the partitions and modularity and encode this information in the network graph representationPlot the network graphMap the partitions color back to the time series
Build the signal MTF and extract a network graph from it
Compute the partitions and modularity and encode this information in the network graph representation
Plot the network graph
Map the partitions color back to the time series
We extract the graph from the MTF and plot a vanilla network graph from there:
The above network graph does not give us a lot of new insights. We will search for the communities in this network graph with the Louvain method: modularity is a scale value between −0.5 (non-modular clustering) and 1 (fully modular clustering) that measures the relative density of edges inside communities with respect to edges outside communities. Optimizing this value theoretically results in the best possible grouping of the nodes of a given network, however going through all possible iterations of the nodes into groups is impractical so heuristic algorithms are used. In the Louvain Method of community detection, first small communities are found by optimizing modularity locally on all nodes, then each small community is grouped into one node and the first step is repeated. This method is implemented in the community package (documented here) and we use it in the tsia package to encode our network graph:
On top of modularity and number of communities (or partitions), there are other statistics of interest we can compute from a network graph:
We can now encode these information in the network graph to make it more colorful, and hopefully, more useful:
What is the interpretation we can give to this plot? The modularity metric and the Louvain methods uncovers 4 communities in this signal. At this stage, it is difficult to understand how we can leverage this knowledge though...
Each community detected in the network graphs has its own shapelet in the original time series:
You can refer to the notebook to further build your intuition by drawing the same plot for the other signals available in the repository. Here are a few examples:
These mapping looks less valuable than the one obtained from the MTF. However, the features that that can be extracted from these network graphs look promising for classifying signals depending on their behavior. Here is an example on the 7 signals provided in the repository referenced earlier:
Mapping Markov transition fields transition probabilities back onto the time series signal appears like a great tool to provide some understanding about a given signal. On the other hand, mapping network graphs communities back to original time series does not seem to bring much values: however, the features extracted from these networks graphs (see table above) look interesting to provide high quality features to a neural network. As one of the future area of investigation, we are interested into investigating how these tools could be applied to multivariate timeseries (especially highly dimensional ones as we can find in industrial settings with hundreds if not thousands of sensors per industrial equipment).
These Markov transition fields and network graphs could be potentially used:
To compare training and validation dataset consistency (and detect concept drift).
To train semi-supervised anomaly prediction models: train a temporal CNN on normal signals, perform and inline MTF calculation every minute (for instance) and compare inference results with the trained model to detect signal behavior change.
To further explain why an unsupervised time series model found something of interest.
Wang, Zhiguang; Oates, Tim (2015), Imaging Time-Series to Improve Classification and Imputation, Arxiv.
Liu, Lu.; Wang, Zhiguang (2018) Encoding temporal Markov dynamics in graph for visualizing and mining time series Arxiv.